diff --git a/mp/src/common/language.cpp b/mp/src/common/language.cpp index 16aeda32..33877f60 100644 --- a/mp/src/common/language.cpp +++ b/mp/src/common/language.cpp @@ -56,6 +56,7 @@ static const Language_t s_LanguageNames[] = { "Brazilian", "brazilian", "#GameUI_Language_Brazilian", "pt_BR", k_Lang_Brazilian, 1046 } , { "Bulgarian", "bulgarian", "#GameUI_Language_Bulgarian", "bg_BG", k_Lang_Bulgarian, 1026 } , { "Greek", "greek", "#GameUI_Language_Greek", "el_GR", k_Lang_Greek, 1032 }, + { "Ukrainian", "ukrainian", "#GameUI_Language_Ukrainian", "uk_UA", k_Lang_Ukrainian, 1058 }, }; //----------------------------------------------------------------------------- diff --git a/mp/src/common/language.h b/mp/src/common/language.h index 2337c236..b16c492f 100644 --- a/mp/src/common/language.h +++ b/mp/src/common/language.h @@ -40,6 +40,7 @@ enum ELanguage k_Lang_Brazilian, k_Lang_Bulgarian, k_Lang_Greek, + k_Lang_Ukrainian, k_Lang_MAX }; diff --git a/mp/src/common/lzma/lzma.h b/mp/src/common/lzma/lzma.h new file mode 100644 index 00000000..01bd1ef9 --- /dev/null +++ b/mp/src/common/lzma/lzma.h @@ -0,0 +1,53 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: LZMA Glue. Designed for Tool time Encoding/Decoding. +// +// LZMA Codec interface for engine. Based largely on LzmaUtil.c in SDK +// +// LZMA SDK 9.38 beta +// 2015-01-03 : Igor Pavlov : Public domain +// http://www.7-zip.org/ +// +//====================================================================================// + +#ifndef LZMA_H +#define LZMA_H + +#ifdef _WIN32 +#pragma once +#endif + +//----------------------------------------------------------------------------- +// These routines are designed for TOOL TIME encoding/decoding on the PC! +// They have not been made to encode/decode on the PPC and lack big endian awarnesss. +// Lightweight GAME TIME Decoding is part of tier1.lib, via CLZMA. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Encoding glue. Returns non-null Compressed buffer if successful. +// Caller must free. +//----------------------------------------------------------------------------- +unsigned char *LZMA_Compress( +unsigned char *pInput, +unsigned int inputSize, +unsigned int *pOutputSize ); + +//----------------------------------------------------------------------------- +// Decoding glue. Returns TRUE if succesful. +//----------------------------------------------------------------------------- +bool LZMA_Uncompress( +unsigned char *pInput, +unsigned char **ppOutput, +unsigned int *pOutputSize ); + +//----------------------------------------------------------------------------- +// Decoding helper, returns TRUE if buffer is LZMA compressed. +//----------------------------------------------------------------------------- +bool LZMA_IsCompressed( unsigned char *pInput ); + +//----------------------------------------------------------------------------- +// Decoding helper, returns non-zero size of data when uncompressed, otherwise 0. +//----------------------------------------------------------------------------- +unsigned int LZMA_GetActualSize( unsigned char *pInput ); + +#endif diff --git a/mp/src/common/studiobyteswap.cpp b/mp/src/common/studiobyteswap.cpp index 0c4e59d8..7b2c992e 100644 --- a/mp/src/common/studiobyteswap.cpp +++ b/mp/src/common/studiobyteswap.cpp @@ -1679,6 +1679,11 @@ int ByteswapMDLFile( void *pDestBase, void *pSrcBase, const int fileSize ) SET_INDEX_POINTERS( pData, pSequence, keyvalueindex ) WriteBuffer( pDataDest, pDataSrc, SrcNative( &pSequence->keyvaluesize ) ); + + /** ACTIVITY MODIFIERS **/ + + SET_INDEX_POINTERS( pData, pSequence, activitymodifierindex ) + WriteObjects( pDataDest, pDataSrc, SrcNative( &pSequence->numactivitymodifiers ) ); } /** TRANSITION GRAPH **/ @@ -2801,6 +2806,10 @@ BEGIN_BYTESWAP_DATADESC( mstudiomovement_t ) DEFINE_FIELD( position, FIELD_VECTOR ), END_BYTESWAP_DATADESC() +BEGIN_BYTESWAP_DATADESC( mstudioactivitymodifier_t ) + DEFINE_INDEX( sznameindex, FIELD_INTEGER ), +END_BYTESWAP_DATADESC() + BEGIN_BYTESWAP_DATADESC( mstudioseqdesc_t ) DEFINE_INDEX( baseptr, FIELD_INTEGER ), DEFINE_INDEX( szlabelindex, FIELD_INTEGER ), @@ -2840,7 +2849,9 @@ BEGIN_BYTESWAP_DATADESC( mstudioseqdesc_t ) DEFINE_INDEX( keyvalueindex, FIELD_INTEGER ), DEFINE_FIELD( keyvaluesize, FIELD_INTEGER ), DEFINE_INDEX( cycleposeindex, FIELD_INTEGER ), - DEFINE_ARRAY( unused, FIELD_INTEGER, 7 ), // remove/add as appropriate (grow back to 8 ints on version change!) + DEFINE_INDEX( activitymodifierindex, FIELD_INTEGER ), + DEFINE_FIELD( numactivitymodifiers, FIELD_INTEGER ), + DEFINE_ARRAY( unused, FIELD_INTEGER, 5 ), // remove/add as appropriate (grow back to 8 ints on version change!) END_BYTESWAP_DATADESC() BEGIN_BYTESWAP_DATADESC( mstudioevent_t ) diff --git a/mp/src/devtools/bin/vpc_linux b/mp/src/devtools/bin/vpc_linux index b83b870e..e7680782 100755 Binary files a/mp/src/devtools/bin/vpc_linux and b/mp/src/devtools/bin/vpc_linux differ diff --git a/mp/src/devtools/bin/vpc_osx b/mp/src/devtools/bin/vpc_osx index cbe1e289..2827ae4b 100755 Binary files a/mp/src/devtools/bin/vpc_osx and b/mp/src/devtools/bin/vpc_osx differ diff --git a/mp/src/devtools/gendbg.sh b/mp/src/devtools/gendbg.sh index 3bf30781..780533e8 100755 --- a/mp/src/devtools/gendbg.sh +++ b/mp/src/devtools/gendbg.sh @@ -1,6 +1,6 @@ #!/bin/bash -OBJCOPY=objcopy +OBJCOPY=$STEAM_RUNTIME_PATH/bin/objcopy function usage { echo "$0 /path/to/input/file [-o /path/to/output/file ]" diff --git a/mp/src/devtools/makefile_base_posix.mak b/mp/src/devtools/makefile_base_posix.mak index 0211e157..c76a1b1f 100644 --- a/mp/src/devtools/makefile_base_posix.mak +++ b/mp/src/devtools/makefile_base_posix.mak @@ -1,5 +1,5 @@ # -# Base makefile for Linux and OSX +# Base makefile for Linux. # # !!!!! Note to future editors !!!!! # @@ -26,6 +26,10 @@ ifneq (,$(findstring clang,$(CXX))) CLANG_BUILD = 1 endif +ifeq ($(OS),Darwin) + $(error This file should never be used for Mac - use base.xconfig) +endif + ifeq ($(CFG), release) # With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3. # There also was no speed difference running at 1280x1024. May 2012, mikesart. @@ -46,22 +50,106 @@ endif # CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags" ARCH_FLAGS = BUILDING_MULTI_ARCH = 0 +# Preserve cflags set in environment +ENV_CFLAGS := $(CFLAGS) +ENV_CXXFLAGS := $(CXXFLAGS) CPPFLAGS = $(DEFINES) $(addprefix -I, $(abspath $(INCLUDEDIRS) )) -CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE +BASE_CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE +CFLAGS = $(BASE_CFLAGS) $(ENV_CFLAGS) # In -std=gnu++0x mode we get lots of errors about "error: narrowing conversion". -fpermissive # turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+. ifeq ($(CLANG_BUILD),1) - CXXFLAGS = $(CFLAGS) -std=gnu++0x -Wno-c++11-narrowing -Wno-dangling-else + CXXFLAGS = $(BASE_CFLAGS) -std=gnu++0x -Wno-c++11-narrowing -Wno-dangling-else $(ENV_CXXFLAGS) else - CXXFLAGS = $(CFLAGS) -std=gnu++0x -fpermissive + CXXFLAGS = $(BASE_CFLAGS) -std=gnu++0x -fpermissive $(ENV_CXXFLAGS) endif DEFINES += -DVPROF_LEVEL=1 -DGNUC -DNO_HOOK_MALLOC -DNO_MALLOC_OVERRIDE + +## TODO: This cases build errors in cstrike/bin right now. Need to debug. +# This causes all filesystem interfaces to default to their 64bit versions on +# 32bit systems, which means we don't break on filesystems with inodes > 32bit. +# DEFINES += -D_FILE_OFFSET_BITS=64 + LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel) GENDEP_CXXFLAGS = -MMD -MP -MF $(@:.o=.P) MAP_FLAGS = Srv_GAMEOUTPUTFILE = COPY_DLL_TO_SRV = 0 +# We should always specify -Wl,--build-id, as documented at: +# http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId +LDFLAGS += -Wl,--build-id + +# +# If we should be running in a chroot, check to see if we are. If not, then prefix everything with the +# required chroot +# +ifdef MAKE_CHROOT + export STEAM_RUNTIME_PATH := /usr + ifneq ("$(SCHROOT_CHROOT_NAME)", "$(CHROOT_NAME)") + $(info '$(SCHROOT_CHROOT_NAME)' is not '$(CHROOT_NAME)') + $(error This makefile should be run from within a chroot. 'schroot --chroot $(CHROOT_NAME) -- $(MAKE) $(MAKEFLAGS)') + endif + GCC_VER = -4.8 + P4BIN = $(SRCROOT)/devtools/bin/linux/p4 + CRYPTOPPDIR=ubuntu12_32_gcc48 +else ifeq ($(USE_VALVE_BINDIR),1) + # Using /valve/bin directory. + export STEAM_RUNTIME_PATH ?= /valve + GCC_VER = -4.6 + P4BIN = p4 + CRYPTOPPDIR=linux32 +else + # Not using chroot, use old steam-runtime. (gcc 4.6.3) + export STEAM_RUNTIME_PATH ?= /valve/steam-runtime + GCC_VER = + P4BIN = p4 + CRYPTOPPDIR=ubuntu12_32 +endif + +ifeq ($(TARGET_PLATFORM),linux64) + MARCH_TARGET = core2 +else + MARCH_TARGET = pentium4 +endif + +ifeq ($(USE_VALVE_BINDIR),1) + # On dedicated servers, some plugins depend on global variable symbols in addition to functions. + # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. + STRIP_FLAGS = +else + # Linux desktop client (or client/dedicated server in chroot). + STRIP_FLAGS = -x +endif + +ifeq ($(CLANG_BUILD),1) + # Clang does not support -mfpmath=sse because it uses whatever + # instruction set extensions are available by default. + SSE_GEN_FLAGS = -msse2 +else + SSE_GEN_FLAGS = -msse2 -mfpmath=sse +endif + +CCACHE := $(SRCROOT)/devtools/bin/linux/ccache + +ifeq ($(origin AR), default) + AR = $(STEAM_RUNTIME_PATH)/bin/ar crs +endif +ifeq ($(origin CC), default) + CC = $(CCACHE) $(STEAM_RUNTIME_PATH)/bin/gcc$(GCC_VER) +endif +ifeq ($(origin CXX), default) + CXX = $(CCACHE) $(STEAM_RUNTIME_PATH)/bin/g++$(GCC_VER) +endif + +# Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to +# a ccache quirk. Could also upgrade ccache. +# http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html +ifeq ($(CLANG_BUILD),1) + CC := $(CCACHE) $(CC) -Qunused-arguments -fcolor-diagnostics + CXX := $(CCACHE) $(CXX) -Qunused-arguments -fcolor-diagnostics +endif +LINK ?= $(CC) ifeq ($(STEAM_BRANCH),1) WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof @@ -71,141 +159,67 @@ else WARN_FLAGS += -Wno-unused-variable WARN_FLAGS += -Wno-unused-but-set-variable WARN_FLAGS += -Wno-unused-function +endif - ifeq ($(CLANG_BUILD),1) - # Clang specific flags - else - # Gcc specific flags. Need this for gcc 4.8. - # WARN_FLAGS += -Wno-unused-local-typedefs - # WARN_FLAGS += -Wno-unused-function - # WARN_FLAGS += -Wno-unused-result - # WARN_FLAGS += -Wno-narrowing - endif +ifeq ($(CLANG_BUILD),1) + # Clang specific flags +else ifeq ($(GCC_VER),-4.8) + WARN_FLAGS += -Wno-unused-local-typedefs + WARN_FLAGS += -Wno-unused-result + WARN_FLAGS += -Wno-narrowing + # WARN_FLAGS += -Wno-unused-function endif WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers WARN_FLAGS += -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Werror=return-type WARN_FLAGS += -fdiagnostics-show-option -Wformat -Wformat-security -ifeq ($(OS),Darwin) -$(error This file should never be used for Mac - use base.xconfig) +ifeq ($(TARGET_PLATFORM),linux64) + # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) + ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 + LD_SO = ld-linux-x86_64.so.2 + LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) + LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) +else + # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse + ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) + LD_SO = ld-linux.so.2 + LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) + LDFLAGS += -m32 endif -ifeq ($(OS),Linux) - # We should always specify -Wl,--build-id, as documented at: - # http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId - LDFLAGS += -Wl,--build-id - # Set USE_VALVE_BINDIR to build with /Steam/tools/linux in the /valve/bin path. - # Dedicated server uses this. - ifeq ($(USE_VALVE_BINDIR),1) - # dedicated server flags - ifeq ($(TARGET_PLATFORM),linux64) - VALVE_BINDIR = /valve/bin64/ - MARCH_TARGET = nocona - else - VALVE_BINDIR = /valve/bin/ - MARCH_TARGET = pentium4 - endif - STRIP_FLAGS = - else - # linux desktop client flags - VALVE_BINDIR = - # If the steam-runtime is available, use it. We should just default to using it when - # buildbot and everyone has a bit of time to get it installed. - ifneq "$(wildcard /valve/steam-runtime/bin/)" "" - VALVE_BINDIR = /valve/steam-runtime/bin/ - endif - - GCC_VER = - MARCH_TARGET = pentium4 - # On dedicated servers, some plugins depend on global variable symbols in addition to functions. - # So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2. - STRIP_FLAGS = -x - endif - - ifeq ($(CLANG_BUILD),1) - # The steam-runtime is incompatible with clang at this point, so disable it - VALVE_BINDIR = - - # Clang does not support -mfpmath=sse because it uses whatever - # instruction set extensions are available by default. - SSE_GEN_FLAGS = -msse2 - else - SSE_GEN_FLAGS = -msse2 -mfpmath=sse - endif - - CCACHE := $(SRCROOT)/devtools/bin/linux/ccache - - ifeq ($(origin GCC_VER), undefined) - GCC_VER=-4.6 - endif - ifeq ($(origin AR), default) - AR = $(VALVE_BINDIR)ar crs - endif - ifeq ($(origin CC), default) - CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER) - endif - ifeq ($(origin CXX), default) - CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER) - endif - - # Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to - # a ccache quirk. Could also upgrade ccache. - # http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html - ifeq ($(CLANG_BUILD),1) - CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments - CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments - endif - LINK ?= $(CC) - - ifeq ($(TARGET_PLATFORM),linux64) - # nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2) - ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2 - LD_SO = ld-linux-x86_64.so.2 - LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.a) - LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++-pic.a) - else - # pentium4 = MMX, SSE, SSE2 - no SSE3 (added in prescott) # -msse3 -mfpmath=sse - ARCH_FLAGS += -m32 -march=$(MARCH_TARGET) -mtune=core2 $(SSE_GEN_FLAGS) - LD_SO = ld-linux.so.2 - LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.so) - LDFLAGS += -m32 - endif - - GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh - ifeq ($(CFG),release) - STRIP ?= strip $(STRIP_FLAGS) -S - # CFLAGS += -ffunction-sections -fdata-sections - # LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections - else - STRIP ?= true - endif - VSIGN ?= true - - ifeq ($(SOURCE_SDK), 1) - Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) - COPY_DLL_TO_SRV := 1 - endif - - LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map - - SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined - - _WRAP := -Xlinker --wrap= - PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ - $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ - $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ - $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ - $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath - - LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread - - LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group - LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt - +GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh +ifeq ($(CFG),release) + STRIP ?= strip $(STRIP_FLAGS) -S +# CFLAGS += -ffunction-sections -fdata-sections +# LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections +else + STRIP ?= true endif +VSIGN ?= true + +ifeq ($(SOURCE_SDK), 1) + Srv_GAMEOUTPUTFILE := $(GAMEOUTPUTFILE:.so=_srv.so) + COPY_DLL_TO_SRV := 1 +endif + +LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map + +SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined + +_WRAP := -Xlinker --wrap= +PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \ + $(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \ + $(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \ + $(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \ + $(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath + +LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group +LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread + +LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group +LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt # # Profile-directed optimizations. @@ -289,7 +303,7 @@ else # setting is best, but here is an alternate example: # export P4_EDIT_CHANGELIST_CMD="echo 1424335" # ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed. - P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 + P4_EDIT_CHANGELIST_CMD ?= $(P4BIN) changes -c `$(P4BIN) client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1 P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD)) endif ifeq ($(P4_EDIT_CHANGELIST),) @@ -298,13 +312,13 @@ else # Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be # interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which # confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command. - P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ') + P4_EDIT_CHANGELIST = $(shell echo -e "Change: new\nDescription: POSIX Auto Checkout" | $(P4BIN) change -i | cut -f 2 -d ' ') endif P4_EDIT_START := for f in - P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) + P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | $(P4BIN) -x - edit -c $(P4_EDIT_CHANGELIST); else $(P4BIN) edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) P4_REVERT_START := for f in - P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) + P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | $(P4BIN) -x - revert; else $(P4BIN) revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX) endif ifeq ($(CONFTYPE),dll) @@ -345,7 +359,7 @@ ifneq "$(OBJ_DIR)" "" endif ifneq "$(OUTPUTFILE)" "" $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 revert $(OUTPUTFILE)"; \ + echo "$(P4BIN) revert $(OUTPUTFILE)"; \ $(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \ fi; endif @@ -354,7 +368,7 @@ ifneq "$(OTHER_DEPENDENCIES)" "" $(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES) endif ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)" + $(QUIET_PREFIX) echo "$(P4BIN) revert $(GAMEOUTPUTFILE)" $(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END) endif @@ -370,7 +384,7 @@ ifneq "$(OBJ_DIR)" "" endif ifneq "$(OUTPUTFILE)" "" $(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \ - echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ + echo "$(P4BIN) edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \ $(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \ fi; $(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT); @@ -380,7 +394,7 @@ ifneq "$(OTHER_DEPENDENCIES)" "" $(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES) endif ifneq "$(GAMEOUTPUTFILE)" "" - $(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" + $(QUIET_PREFIX) echo "$(P4BIN) edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)" $(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END) $(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE) endif diff --git a/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll b/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll index b439fda1..001b2446 100644 Binary files a/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll and b/mp/src/dx10sdk/Utilities/dx9_30/dx_proxy.dll differ diff --git a/mp/src/dx9sdk/utilities/dx_proxy.dll b/mp/src/dx9sdk/utilities/dx_proxy.dll index df99e9e5..725a6273 100644 Binary files a/mp/src/dx9sdk/utilities/dx_proxy.dll and b/mp/src/dx9sdk/utilities/dx_proxy.dll differ diff --git a/mp/src/game/client/baseanimatedtextureproxy.cpp b/mp/src/game/client/baseanimatedtextureproxy.cpp index 4365e866..b7151114 100644 --- a/mp/src/game/client/baseanimatedtextureproxy.cpp +++ b/mp/src/game/client/baseanimatedtextureproxy.cpp @@ -11,6 +11,8 @@ #include "materialsystem/itexture.h" #include "tier1/KeyValues.h" #include "toolframework_client.h" +#include "tier0/minidump.h" +#include "tier0/stacktools.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" @@ -39,25 +41,33 @@ CBaseAnimatedTextureProxy::~CBaseAnimatedTextureProxy() bool CBaseAnimatedTextureProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues ) { char const* pAnimatedTextureVarName = pKeyValues->GetString( "animatedTextureVar" ); - if( !pAnimatedTextureVarName ) - return false; - bool foundVar; - m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false ); - if( !foundVar ) - return false; + if( pAnimatedTextureVarName ) + { + bool foundVar; - char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" ); - if( !pAnimatedTextureFrameNumVarName ) - return false; + m_AnimatedTextureVar = pMaterial->FindVar( pAnimatedTextureVarName, &foundVar, false ); + if( foundVar ) + { + char const* pAnimatedTextureFrameNumVarName = pKeyValues->GetString( "animatedTextureFrameNumVar" ); - m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false ); - if( !foundVar ) - return false; + if( pAnimatedTextureFrameNumVarName ) + { + m_AnimatedTextureFrameNumVar = pMaterial->FindVar( pAnimatedTextureFrameNumVarName, &foundVar, false ); - m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 ); - m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 ); - return true; + if( foundVar ) + { + m_FrameRate = pKeyValues->GetFloat( "animatedTextureFrameRate", 15 ); + m_WrapAnimation = !pKeyValues->GetInt( "animationNoWrap", 0 ); + return true; + } + } + } + } + + // Error - null out pointers. + Cleanup(); + return false; } void CBaseAnimatedTextureProxy::Cleanup() diff --git a/mp/src/game/client/bsp_utils.cpp b/mp/src/game/client/bsp_utils.cpp new file mode 100644 index 00000000..c21c2ada --- /dev/null +++ b/mp/src/game/client/bsp_utils.cpp @@ -0,0 +1,170 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Exposes bsp tools to game for e.g. workshop use +// +// $NoKeywords: $ +//===========================================================================// + +#include "cbase.h" +#include +#include "filesystem.h" +#include "bsp_utils.h" +#include "utlbuffer.h" +#include "igamesystem.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +bool BSP_SyncRepack( const char *pszInputMapFile, + const char *pszOutputMapFile, + IBSPPack::eRepackBSPFlags eRepackFlags ) +{ + // load the bsppack dll + IBSPPack *libBSPPack = NULL; + CSysModule *pModule = g_pFullFileSystem->LoadModule( "bsppack" ); + if ( pModule ) + { + CreateInterfaceFn BSPPackFactory = Sys_GetFactory( pModule ); + if ( BSPPackFactory ) + { + libBSPPack = ( IBSPPack * )BSPPackFactory( IBSPPACK_VERSION_STRING, NULL ); + } + } + if( !libBSPPack ) + { + Warning( "Can't load bsppack library - unable to compress bsp\n" ); + return false; + } + + Msg( "Repacking %s -> %s\n", pszInputMapFile, pszOutputMapFile ); + + if ( !g_pFullFileSystem->FileExists( pszInputMapFile ) ) + { + Warning( "Couldn't open input file %s - BSP recompress failed\n", pszInputMapFile ); + return false; + } + + CUtlBuffer inputBuffer; + if ( !g_pFullFileSystem->ReadFile( pszInputMapFile, NULL, inputBuffer ) ) + { + Warning( "Couldn't read file %s - BSP compression failed\n", pszInputMapFile ); + return false; + } + + CUtlBuffer outputBuffer; + + if ( !libBSPPack->RepackBSP( inputBuffer, outputBuffer, eRepackFlags ) ) + { + Warning( "Internal error compressing BSP\n" ); + return false; + } + + g_pFullFileSystem->WriteFile( pszOutputMapFile, NULL, outputBuffer ); + + Msg( "Successfully repacked %s as %s -- %u -> %u bytes\n", + pszInputMapFile, pszOutputMapFile, inputBuffer.TellPut(), outputBuffer.TellPut() ); + + return true; +} + +// Helper to create a thread that calls SyncCompressMap, and clean it up when it exists +void BSP_BackgroundRepack( const char *pszInputMapFile, + const char *pszOutputMapFile, + IBSPPack::eRepackBSPFlags eRepackFlags ) +{ + // Make this a gamesystem and thread, so it can check for completion each frame and clean itself up. Run() is the + // background thread, Update() is the main thread tick. + class BackgroundBSPRepackThread : public CThread, public CAutoGameSystemPerFrame + { + public: + BackgroundBSPRepackThread( const char *pszInputFile, const char *pszOutputFile, IBSPPack::eRepackBSPFlags eRepackFlags ) + : m_strInput( pszInputFile ) + , m_strOutput( pszOutputFile ) + , m_eRepackFlags( eRepackFlags ) + { + Start(); + } + + // CThread job - returns 0 for success + virtual int Run() OVERRIDE + { + return BSP_SyncRepack( m_strInput.Get(), m_strOutput.Get(), m_eRepackFlags ) ? 0 : 1; + } + + // GameSystem + virtual const char* Name( void ) OVERRIDE { return "BackgroundBSPRepackThread"; } + + // Runs on main thread + void CheckFinished() + { + if ( !IsAlive() ) + { + // Thread finished + if ( GetResult() != 0 ) + { + Warning( "Map compression thread failed :(\n" ); + } + + // AutoGameSystem deregisters itself on destruction, we're done + delete this; + } + } + + #ifdef CLIENT_DLL + virtual void Update( float frametime ) OVERRIDE { CheckFinished(); } + #else // GAME DLL + virtual void FrameUpdatePostEntityThink() OVERRIDE { CheckFinished(); } + #endif + private: + CUtlString m_strInput; + CUtlString m_strOutput; + IBSPPack::eRepackBSPFlags m_eRepackFlags; + }; + + Msg( "Starting BSP repack job %s -> %s\n", pszInputMapFile, pszOutputMapFile ); + + // Deletes itself up when done + new BackgroundBSPRepackThread( pszInputMapFile, pszOutputMapFile, eRepackFlags ); +} + +CON_COMMAND( bsp_repack, "Repack and output a (re)compressed version of a bsp file" ) +{ +#ifdef GAME_DLL + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; +#endif + + // Handle -nocompress + bool bCompress = true; + const char *szInFilename = NULL; + const char *szOutFilename = NULL; + + if ( args.ArgC() == 4 && V_strcasecmp( args.Arg( 1 ), "-nocompress" ) == 0 ) + { + bCompress = false; + szInFilename = args.Arg( 2 ); + szOutFilename = args.Arg( 3 ); + } + else if ( args.ArgC() == 3 ) + { + szInFilename = args.Arg( 1 ); + szOutFilename = args.Arg( 2 ); + } + + if ( !szInFilename || !szOutFilename || !strlen( szInFilename ) || !strlen( szOutFilename ) ) + { + Msg( "Usage: bsp_repack [-nocompress] map.bsp output_map.bsp\n" ); + return; + } + + if ( bCompress ) + { + // Use default compress flags + BSP_BackgroundRepack( szInFilename, szOutFilename ); + } + else + { + // No compression + BSP_BackgroundRepack( szInFilename, szOutFilename, (IBSPPack::eRepackBSPFlags)0 ); + } +} diff --git a/mp/src/game/client/bsp_utils.h b/mp/src/game/client/bsp_utils.h new file mode 100644 index 00000000..1cdfaf50 --- /dev/null +++ b/mp/src/game/client/bsp_utils.h @@ -0,0 +1,21 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Exposes bsp tools to game for e.g. workshop use +// +// $NoKeywords: $ +//===========================================================================// + +#include "../utils/common/bsplib.h" +#include "ibsppack.h" + +// Loads bsppack module (IBSPPack) and calls RepackBSP() +bool BSP_SyncRepack( const char *pszInputMapFile, + const char *pszOutputMapFile, + IBSPPack::eRepackBSPFlags eRepackFlags = (IBSPPack::eRepackBSPFlags) ( IBSPPack::eRepackBSP_CompressLumps | + IBSPPack::eRepackBSP_CompressPackfile ) ); + +// Helper to spawn a background thread that runs SyncRepack +void BSP_BackgroundRepack( const char *pszInputMapFile, + const char *pszOutputMapFile, + IBSPPack::eRepackBSPFlags eRepackFlags = (IBSPPack::eRepackBSPFlags) ( IBSPPack::eRepackBSP_CompressLumps | + IBSPPack::eRepackBSP_CompressPackfile ) ); diff --git a/mp/src/game/client/c_ai_basenpc.cpp b/mp/src/game/client/c_ai_basenpc.cpp index 1b1e2e65..69b675b3 100644 --- a/mp/src/game/client/c_ai_basenpc.cpp +++ b/mp/src/game/client/c_ai_basenpc.cpp @@ -153,9 +153,13 @@ void C_AI_BaseNPC::OnDataChanged( DataUpdateType_t type ) } } -void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) +bool C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) { - ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ); + bool bRet = true; + + if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) ) + bRet = false; + GetRagdollCurSequenceWithDeathPose( this, pDeltaBones1, gpGlobals->curtime, m_iDeathPose, m_iDeathFrame ); float ragdollCreateTime = PhysGetSyncCreateTime(); if ( ragdollCreateTime != gpGlobals->curtime ) @@ -164,11 +168,15 @@ void C_AI_BaseNPC::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x // so initialize the ragdoll at that time so that it will reach the current // position at curtime. Otherwise the ragdoll will simulate forward from curtime // and pop into the future a bit at this point of transition - ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ); + if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) ) + bRet = false; } else { - SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); + if ( !SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ) ) + bRet = false; } + + return bRet; } diff --git a/mp/src/game/client/c_ai_basenpc.h b/mp/src/game/client/c_ai_basenpc.h index 64636c45..834be64d 100644 --- a/mp/src/game/client/c_ai_basenpc.h +++ b/mp/src/game/client/c_ai_basenpc.h @@ -14,7 +14,7 @@ #include "c_basecombatcharacter.h" -// NOTE: MOved all controller code into c_basestudiomodel +// NOTE: Moved all controller code into c_basestudiomodel class C_AI_BaseNPC : public C_BaseCombatCharacter { DECLARE_CLASS( C_AI_BaseNPC, C_BaseCombatCharacter ); @@ -29,7 +29,7 @@ public: bool ShouldAvoidObstacle( void ){ return m_bPerformAvoidance; } virtual bool AddRagdollToFadeQueue( void ) { return m_bFadeCorpse; } - virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ); + virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) OVERRIDE; int GetDeathPose( void ) { return m_iDeathPose; } diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 75c9d7a8..78bc38be 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -79,6 +79,11 @@ const float RUN_SPEED_ESTIMATE_SQR = 150.0f * 150.0f; static ConVar dbganimmodel( "dbganimmodel", "" ); #endif +#if defined( STAGING_ONLY ) + static ConVar dbg_bonestack_perturb( "dbg_bonestack_perturb", "0", 0); + static CInterlockedInt dbg_bonestack_reentrant_count = 0; +#endif // STAGING_ONLY + mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc ); C_EntityDissolve *DissolveEffect( C_BaseEntity *pTarget, float flTime ); @@ -632,7 +637,10 @@ void C_ClientRagdoll::Release( void ) } ClientEntityList().RemoveEntity( GetClientHandle() ); - partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() ); + if ( CollisionProp()->GetPartitionHandle() != PARTITION_INVALID_HANDLE ) + { + partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() ); + } RemoveFromLeafSystem(); BaseClass::Release(); @@ -744,15 +752,25 @@ C_BaseAnimating::~C_BaseAnimating() int i = g_PreviousBoneSetups.Find( this ); if ( i != -1 ) g_PreviousBoneSetups.FastRemove( i ); - RemoveFromClientSideAnimationList(); TermRopes(); + + Assert( !m_pRagdoll ); + delete m_pRagdollInfo; - Assert(!m_pRagdoll); + m_pRagdollInfo = NULL; + delete m_pIk; + m_pIk = NULL; + delete m_pBoneMergeCache; + m_pBoneMergeCache = NULL; + Studio_DestroyBoneCache( m_hitboxBoneCacheHandle ); + delete m_pJiggleBones; + m_pJiggleBones = NULL; + InvalidateMdlCache(); // Kill off anything bone attached to us. @@ -852,7 +870,7 @@ void C_BaseAnimating::UpdateRelevantInterpolatedVars() { MDLCACHE_CRITICAL_SECTION(); // Remove any interpolated vars that need to be removed. - if ( !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() ) + if ( !IsMarkedForDeletion() && !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() ) { AddBaseAnimatingInterpolatedVars(); } @@ -892,6 +910,17 @@ void C_BaseAnimating::RemoveBaseAnimatingInterpolatedVars() } } +/* + From Ken: Lock() and Unlock() are render frame only, it’s just so the mdlcache + doesn’t toss the memory when it reshuffles the data, or at least used to. I + don't have any idea if mdlcache even does that anymore, but at one point it would + happily throw away the animation data if you ran out of memory on the + consoles. Jay adds: Ken is correct and the pointer should be valid until the end + of the frame lock (provided you are within a MDLCACHE_LOCK() block or whatever + + Jay also recommends running with a forced small cache size (1MB) to put maximum + pressure on the cache when testing changes. Look for datacache ConVar in datacache.cpp. + */ void C_BaseAnimating::LockStudioHdr() { Assert( m_hStudioHdr == MDLHANDLE_INVALID && m_pStudioHdr == NULL ); @@ -963,6 +992,9 @@ void C_BaseAnimating::UnlockStudioHdr() mdlcache->UnlockStudioHdr( m_hStudioHdr ); } m_hStudioHdr = MDLHANDLE_INVALID; + + delete m_pStudioHdr; + m_pStudioHdr = NULL; } } @@ -1511,10 +1543,21 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater if (pbones[i].parent == -1) { ConcatTransforms( cameraTransform, bonematrix, goalMX ); - } + } else { - ConcatTransforms( GetBone( pbones[i].parent ), bonematrix, goalMX ); + // If the parent bone has been scaled (like with BuildBigHeadTransformations) + // scale it back down so the jiggly bones show up non-scaled in the correct location. + matrix3x4_t parentMX = GetBone( pbones[i].parent ); + + float fScale = Square( parentMX[0][0] ) + Square( parentMX[1][0] ) + Square( parentMX[2][0] ); + if ( fScale > Square( 1.0001f ) ) + { + fScale = 1.0f / FastSqrt( fScale ); + MatrixScaleBy( fScale, parentMX ); + } + + ConcatTransforms( parentMX, bonematrix, goalMX ); } // get jiggle properties from QC data @@ -1995,10 +2038,10 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo } -void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) +bool C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) { - if ( !hdr || !hdr->GetNumAttachments() ) - return; + if ( !hdr ) + return false; // calculate attachment points matrix3x4_t world; @@ -2024,6 +2067,8 @@ void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) FormatViewModelAttachment( i, world ); PutAttachment( i + 1, world ); } + + return true; } bool C_BaseAnimating::CalcAttachments() @@ -2214,18 +2259,36 @@ bool C_BaseAnimating::GetSoundSpatialization( SpatializationInfo_t& info ) return true; } - +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool C_BaseAnimating::IsViewModel() const { return false; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseAnimating::UpdateOnRemove( void ) +{ + RemoveFromClientSideAnimationList( true ); + + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool C_BaseAnimating::IsMenuModel() const { return false; } // UNDONE: Seems kind of silly to have this when we also have the cached bones in C_BaseAnimating +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- CBoneCache *C_BaseAnimating::GetBoneCache( CStudioHdr *pStudioHdr ) { int boneMask = BONE_USED_BY_HITBOX; @@ -2908,10 +2971,14 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i if( !( oldReadableBones & BONE_USED_BY_ATTACHMENT ) && ( boneMask & BONE_USED_BY_ATTACHMENT ) ) { - SetupBones_AttachmentHelper( hdr ); + if ( !SetupBones_AttachmentHelper( hdr ) ) + { + DevWarning( 2, "SetupBones: SetupBones_AttachmentHelper failed.\n" ); + return false; + } } } - + // Do they want to get at the bone transforms? If it's just making sure an aiment has // its bones setup, it doesn't need the transforms yet. if ( pBoneToWorldOut ) @@ -2922,7 +2989,7 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i } else { - Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() ); + ExecuteNTimes( 25, Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() ) ); return false; } } @@ -2989,6 +3056,9 @@ struct BoneAccess char const *tag; }; +// the modelcache critical section is insufficient for preventing us from getting into the bone cache at the same time. +// The bonecache itself is protected by a mutex, but the actual bone access stack needs to be protected separately. +static CThreadFastMutex g_BoneAccessMutex; static CUtlVector< BoneAccess > g_BoneAccessStack; static BoneAccess g_BoneAcessBase; @@ -3003,6 +3073,9 @@ bool C_BaseAnimating::IsBoneAccessAllowed() const // (static function) void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels, char const *tagPush ) { + AUTO_LOCK( g_BoneAccessMutex ); + STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) ); + BoneAccess save = g_BoneAcessBase; g_BoneAccessStack.AddToTail( save ); @@ -3014,6 +3087,9 @@ void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAll void C_BaseAnimating::PopBoneAccess( char const *tagPop ) { + AUTO_LOCK( g_BoneAccessMutex ); + STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) ); + // Validate that pop matches the push Assert( ( g_BoneAcessBase.tag == tagPop ) || ( g_BoneAcessBase.tag && g_BoneAcessBase.tag != ( char const * ) 1 && tagPop && tagPop != ( char const * ) 1 && !strcmp( g_BoneAcessBase.tag, tagPop ) ) ); int lastIndex = g_BoneAccessStack.Count() - 1; @@ -3481,7 +3557,7 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr ) } // Necessary to get the next loop working - m_flPrevEventCycle = -0.01; + m_flPrevEventCycle = flEventCycle - 0.001f; } for (int i = 0; i < (int)seqdesc.numevents; i++) @@ -4496,7 +4572,7 @@ void C_BaseAnimating::OnPreDataChanged( DataUpdateType_t updateType ) m_bLastClientSideFrameReset = m_bClientSideFrameReset; } -void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ) +bool C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ) { // blow the cached prev bones InvalidateBoneCache(); @@ -4505,13 +4581,18 @@ void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTim Interpolate( flTime ); // Setup bone state at the given time - SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); + return SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); } -void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) +bool C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) { - ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ); - ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime ); + bool bSuccess = true; + + if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) ) + bSuccess = false; + if ( !ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime ) ) + bSuccess = false; + float ragdollCreateTime = PhysGetSyncCreateTime(); if ( ragdollCreateTime != gpGlobals->curtime ) { @@ -4519,12 +4600,15 @@ void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri // so initialize the ragdoll at that time so that it will reach the current // position at curtime. Otherwise the ragdoll will simulate forward from curtime // and pop into the future a bit at this point of transition - ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ); + if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) ) + bSuccess = false; } else { memcpy( pCurrentBones, m_CachedBoneData.Base(), sizeof( matrix3x4_t ) * m_CachedBoneData.Count() ); } + + return bSuccess; } C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy() @@ -4592,14 +4676,32 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient() { MoveToLastReceivedPosition( true ); GetAbsOrigin(); - C_BaseAnimating *pRagdoll = CreateRagdollCopy(); - matrix3x4_t boneDelta0[MAXSTUDIOBONES]; - matrix3x4_t boneDelta1[MAXSTUDIOBONES]; - matrix3x4_t currentBones[MAXSTUDIOBONES]; - const float boneDt = 0.1f; - GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); - pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); + C_BaseAnimating *pRagdoll = CreateRagdollCopy(); + if ( pRagdoll ) + { + matrix3x4_t boneDelta0[MAXSTUDIOBONES]; + matrix3x4_t boneDelta1[MAXSTUDIOBONES]; + matrix3x4_t currentBones[MAXSTUDIOBONES]; + const float boneDt = 0.1f; + + bool bInitAsClient = false; + bool bInitBoneArrays = GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); + + if ( bInitBoneArrays ) + { + bInitAsClient = pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); + } + + if ( !bInitAsClient || !bInitBoneArrays ) + { + Warning( "C_BaseAnimating::BecomeRagdollOnClient failed. pRagdoll:%p bInitBoneArrays:%d bInitAsClient:%d\n", + pRagdoll, bInitBoneArrays, bInitAsClient ); + pRagdoll->Release(); + return NULL; + } + } + return pRagdoll; } @@ -5512,6 +5614,13 @@ int C_BaseAnimating::SelectWeightedSequence ( int activity ) } +int C_BaseAnimating::SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) +{ + Assert( activity != ACT_INVALID ); + Assert( GetModelPtr() ); + return GetModelPtr()->SelectWeightedSequenceFromModifiers( activity, pActivityModifiers, iModifierCount ); +} + //========================================================= //========================================================= int C_BaseAnimating::LookupPoseParameter( CStudioHdr *pstudiohdr, const char *szName ) @@ -6018,7 +6127,7 @@ void C_BaseAnimating::AddToClientSideAnimationList() UpdateRelevantInterpolatedVars(); } -void C_BaseAnimating::RemoveFromClientSideAnimationList() +void C_BaseAnimating::RemoveFromClientSideAnimationList( bool bBeingDestroyed /*= false*/ ) { // Not in list yet if ( INVALID_CLIENTSIDEANIMATION_LIST_HANDLE == m_ClientSideAnimationListHandle ) @@ -6049,7 +6158,10 @@ void C_BaseAnimating::RemoveFromClientSideAnimationList() // Invalidate our handle no matter what. m_ClientSideAnimationListHandle = INVALID_CLIENTSIDEANIMATION_LIST_HANDLE; - UpdateRelevantInterpolatedVars(); + if ( !bBeingDestroyed ) + { + UpdateRelevantInterpolatedVars(); + } } diff --git a/mp/src/game/client/c_baseanimating.h b/mp/src/game/client/c_baseanimating.h index f91745ef..f1b0467c 100644 --- a/mp/src/game/client/c_baseanimating.h +++ b/mp/src/game/client/c_baseanimating.h @@ -247,7 +247,7 @@ public: void ForceClientSideAnimationOn(); void AddToClientSideAnimationList(); - void RemoveFromClientSideAnimationList(); + void RemoveFromClientSideAnimationList( bool bBeingDestroyed = false ); virtual bool IsSelfAnimating(); virtual void ResetLatched(); @@ -298,8 +298,8 @@ public: virtual void Clear( void ); void ClearRagdoll(); void CreateUnragdollInfo( C_BaseAnimating *pRagdoll ); - void ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ); - virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ); + bool ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ); + virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ); // For shadows rendering the correct body + sequence... virtual int GetBody() { return m_nBody; } @@ -429,6 +429,7 @@ public: // For prediction int SelectWeightedSequence ( int activity ); + int SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ); void ResetSequenceInfo( void ); float SequenceDuration( void ); float SequenceDuration( CStudioHdr *pStudioHdr, int iSequence ); @@ -444,6 +445,7 @@ public: virtual bool ShouldResetSequenceOnNewModel( void ); virtual bool IsViewModel() const; + virtual void UpdateOnRemove( void ); protected: // View models scale their attachment positions to account for FOV. To get the unmodified @@ -605,7 +607,7 @@ private: // Calculated attachment points CUtlVector m_Attachments; - void SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr ); + bool SetupBones_AttachmentHelper( CStudioHdr *pStudioHdr ); EHANDLE m_hLightingOrigin; EHANDLE m_hLightingOriginRelative; @@ -758,19 +760,12 @@ inline CStudioHdr *C_BaseAnimating::GetModelPtr() const inline void C_BaseAnimating::InvalidateMdlCache() { - if ( m_pStudioHdr ) - { - UnlockStudioHdr(); - delete m_pStudioHdr; - m_pStudioHdr = NULL; - } + UnlockStudioHdr(); } - -inline bool C_BaseAnimating::IsModelScaleFractional() const /// very fast way to ask if the model scale is < 1.0f +inline bool C_BaseAnimating::IsModelScaleFractional() const { - COMPILE_TIME_ASSERT( sizeof( m_flModelScale ) == sizeof( int ) ); - return *((const int *) &m_flModelScale) < 0x3f800000; + return ( m_flModelScale < 1.0f ); } inline bool C_BaseAnimating::IsModelScaled() const diff --git a/mp/src/game/client/c_basecombatcharacter.cpp b/mp/src/game/client/c_basecombatcharacter.cpp index fee63118..846901a5 100644 --- a/mp/src/game/client/c_basecombatcharacter.cpp +++ b/mp/src/game/client/c_basecombatcharacter.cpp @@ -34,6 +34,7 @@ C_BaseCombatCharacter::C_BaseCombatCharacter() m_pGlowEffect = NULL; m_bGlowEnabled = false; m_bOldGlowEnabled = false; + m_bClientSideGlowEnabled = false; #endif // GLOWS_ENABLE } @@ -113,6 +114,22 @@ void C_BaseCombatCharacter::GetGlowEffectColor( float *r, float *g, float *b ) *b = 0.76f; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +/* +void C_BaseCombatCharacter::EnableGlowEffect( float r, float g, float b ) +{ + // destroy the existing effect + if ( m_pGlowEffect ) + { + DestroyGlowEffect(); + } + + m_pGlowEffect = new CGlowObject( this, Vector( r, g, b ), 1.0, true ); +} +*/ + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -125,7 +142,7 @@ void C_BaseCombatCharacter::UpdateGlowEffect( void ) } // create a new effect - if ( m_bGlowEnabled ) + if ( m_bGlowEnabled || m_bClientSideGlowEnabled ) { float r, g, b; GetGlowEffectColor( &r, &g, &b ); diff --git a/mp/src/game/client/c_basecombatcharacter.h b/mp/src/game/client/c_basecombatcharacter.h index 1d84e4ce..0a135b05 100644 --- a/mp/src/game/client/c_basecombatcharacter.h +++ b/mp/src/game/client/c_basecombatcharacter.h @@ -97,6 +97,10 @@ public: #ifdef GLOWS_ENABLE CGlowObject *GetGlowObject( void ){ return m_pGlowEffect; } virtual void GetGlowEffectColor( float *r, float *g, float *b ); +// void EnableGlowEffect( float r, float g, float b ); + + void SetClientSideGlowEnabled( bool bEnabled ){ m_bClientSideGlowEnabled = bEnabled; UpdateGlowEffect(); } + bool IsClientSideGlowEnabled( void ){ return m_bClientSideGlowEnabled; } #endif // GLOWS_ENABLE public: @@ -121,7 +125,8 @@ private: CHandle< C_BaseCombatWeapon > m_hActiveWeapon; #ifdef GLOWS_ENABLE - bool m_bGlowEnabled; + bool m_bClientSideGlowEnabled; // client-side only value used for spectator + bool m_bGlowEnabled; // networked value bool m_bOldGlowEnabled; CGlowObject *m_pGlowEffect; #endif // GLOWS_ENABLE diff --git a/mp/src/game/client/c_basecombatweapon.cpp b/mp/src/game/client/c_basecombatweapon.cpp index 55d21b39..ef4c845e 100644 --- a/mp/src/game/client/c_basecombatweapon.cpp +++ b/mp/src/game/client/c_basecombatweapon.cpp @@ -163,7 +163,10 @@ void C_BaseCombatWeapon::OnDataChanged( DataUpdateType_t updateType ) } } - UpdateVisibility(); + if ( updateType == DATA_UPDATE_CREATED ) + { + UpdateVisibility(); + } m_iOldState = m_iState; diff --git a/mp/src/game/client/c_baseentity.cpp b/mp/src/game/client/c_baseentity.cpp index 25b089cd..338f986c 100644 --- a/mp/src/game/client/c_baseentity.cpp +++ b/mp/src/game/client/c_baseentity.cpp @@ -1150,6 +1150,13 @@ bool C_BaseEntity::InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t re return true; } +void C_BaseEntity::TrackAngRotation( bool bTrack ) +{ + if ( bTrack ) + AddVar( &m_angRotation, &m_iv_angRotation, LATCH_SIMULATION_VAR ); + else + RemoveVar( &m_angRotation, false ); +} void C_BaseEntity::Term() { @@ -2459,37 +2466,36 @@ void C_BaseEntity::UnlinkFromHierarchy() void C_BaseEntity::ValidateModelIndex( void ) { #ifdef TF_CLIENT_DLL + if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_HALLOWEEN ) ) + { + if ( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] > 0 ) + { + SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] ); + return; + } + } + + if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) ) + { + if ( m_nModelIndexOverrides[VISION_MODE_PYRO] > 0 ) + { + SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_PYRO] ); + return; + } + } + + if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_ROME ) ) + { + if ( m_nModelIndexOverrides[VISION_MODE_ROME] > 0 ) + { + SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_ROME] ); + return; + } + } + if ( m_nModelIndexOverrides[VISION_MODE_NONE] > 0 ) { - if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_HALLOWEEN ) ) - { - if ( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] > 0 ) - { - SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_HALLOWEEN] ); - return; - } - } - - if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_PYRO ) ) - { - if ( m_nModelIndexOverrides[VISION_MODE_PYRO] > 0 ) - { - SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_PYRO] ); - return; - } - } - - if ( IsLocalPlayerUsingVisionFilterFlags( TF_VISION_FILTER_ROME ) ) - { - if ( m_nModelIndexOverrides[VISION_MODE_ROME] > 0 ) - { - SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_ROME] ); - return; - } - } - SetModelByIndex( m_nModelIndexOverrides[VISION_MODE_NONE] ); - return; } #endif @@ -2621,14 +2627,6 @@ void C_BaseEntity::PostDataUpdate( DataUpdateType_t updateType ) //----------------------------------------------------------------------------- void C_BaseEntity::OnDataUnchangedInPVS() { - Interp_RestoreToLastNetworked( GetVarMapping() ); - - // For non-predicted and non-client only ents, we need to latch network values into the interpolation histories - if ( !GetPredictable() && !IsClientCreated() ) - { - OnLatchInterpolatedVariables( LATCH_SIMULATION_VAR ); - } - Assert( m_hNetworkMoveParent.Get() || !m_hNetworkMoveParent.IsValid() ); HierarchySetParent(m_hNetworkMoveParent); @@ -6308,6 +6306,9 @@ bool C_BaseEntity::ValidateEntityAttachedToPlayer( bool &bShouldRetry ) if ( FStrEq( pszModel, "models/flag/briefcase.mdl" ) ) return true; + if ( FStrEq( pszModel, "models/passtime/ball/passtime_ball.mdl" ) ) + return true; + if ( FStrEq( pszModel, "models/props_doomsday/australium_container.mdl" ) ) return true; @@ -6323,6 +6324,13 @@ bool C_BaseEntity::ValidateEntityAttachedToPlayer( bool &bShouldRetry ) if ( FStrEq( pszModel, "models/props_moonbase/powersupply_flag.mdl" ) ) return true; + + // The Halloween 2014 doomsday flag replacement + if ( FStrEq( pszModel, "models/flag/ticket_case.mdl" ) ) + return true; + + if ( FStrEq( pszModel, "models/weapons/c_models/c_grapple_proj/c_grapple_proj.mdl" ) ) + return true; } // Any entity that's not an item parented to a player is invalid. diff --git a/mp/src/game/client/c_baseentity.h b/mp/src/game/client/c_baseentity.h index f062760d..e90d1e32 100644 --- a/mp/src/game/client/c_baseentity.h +++ b/mp/src/game/client/c_baseentity.h @@ -1226,7 +1226,7 @@ protected: public: // Accessors for above - static int GetPredictionRandomSeed( void ); + static int GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime = false ); static void SetPredictionRandomSeed( const CUserCmd *cmd ); static C_BasePlayer *GetPredictionPlayer( void ); static void SetPredictionPlayer( C_BasePlayer *player ); @@ -1394,6 +1394,7 @@ public: virtual bool IsDeflectable() { return false; } + bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; } protected: int m_nFXComputeFrame; @@ -1442,6 +1443,8 @@ public: // a render handle, and is put into the spatial partition. bool InitializeAsClientEntityByIndex( int iIndex, RenderGroup_t renderGroup ); + void TrackAngRotation( bool bTrack ); + private: friend void OnRenderStart(); diff --git a/mp/src/game/client/c_baseplayer.cpp b/mp/src/game/client/c_baseplayer.cpp index 942f7a37..a6c682d0 100644 --- a/mp/src/game/client/c_baseplayer.cpp +++ b/mp/src/game/client/c_baseplayer.cpp @@ -122,6 +122,9 @@ ConVar demo_fov_override( "demo_fov_override", "0", FCVAR_CLIENTDLL | FCVAR_DONT ConVar cl_meathook_neck_pivot_ingame_up( "cl_meathook_neck_pivot_ingame_up", "7.0" ); ConVar cl_meathook_neck_pivot_ingame_fwd( "cl_meathook_neck_pivot_ingame_fwd", "3.0" ); +static ConVar cl_clean_textures_on_death( "cl_clean_textures_on_death", "0", FCVAR_DEVELOPMENTONLY, "If enabled, attempts to purge unused textures every time a freeze cam is shown" ); + + void RecvProxy_LocalVelocityX( const CRecvProxyData *pData, void *pStruct, void *pOut ); void RecvProxy_LocalVelocityY( const CRecvProxyData *pData, void *pStruct, void *pOut ); void RecvProxy_LocalVelocityZ( const CRecvProxyData *pData, void *pStruct, void *pOut ); @@ -436,6 +439,7 @@ C_BasePlayer::C_BasePlayer() : m_iv_vecViewOffset( "C_BasePlayer::m_iv_vecViewOf m_bFiredWeapon = false; m_nForceVisionFilterFlags = 0; + m_nLocalPlayerVisionFlags = 0; ListenForGameEvent( "base_player_teleported" ); } @@ -541,6 +545,7 @@ CBaseEntity *C_BasePlayer::GetObserverTarget() const // returns players target o case OBS_MODE_FIXED: // view from a fixed camera position case OBS_MODE_IN_EYE: // follow a player in first person view case OBS_MODE_CHASE: // follow a player in third person view + case OBS_MODE_POI: // PASSTIME point of interest - game objective, big fight, anything interesting case OBS_MODE_ROAMING: // free roaming return m_hObserverTarget; break; @@ -635,6 +640,7 @@ int C_BasePlayer::GetObserverMode() const case OBS_MODE_FIXED: // view from a fixed camera position case OBS_MODE_IN_EYE: // follow a player in first person view case OBS_MODE_CHASE: // follow a player in third person view + case OBS_MODE_POI: // PASSTIME point of interest - game objective, big fight, anything interesting case OBS_MODE_ROAMING: // free roaming return m_iObserverMode; break; @@ -880,6 +886,10 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType ) // Force the sound mixer to the freezecam mixer ConVar *pVar = (ConVar *)cvar->FindVar( "snd_soundmixer" ); pVar->SetValue( "FreezeCam_Only" ); + + // When we start, give unused textures an opportunity to unload + if ( cl_clean_textures_on_death.GetBool() ) + g_pMaterialSystem->UncacheUnusedMaterials( false ); } else if ( m_bWasFreezeFraming && GetObserverMode() != OBS_MODE_FREEZECAM ) { @@ -897,6 +907,14 @@ void C_BasePlayer::PostDataUpdate( DataUpdateType_t updateType ) m_nForceVisionFilterFlags = 0; CalculateVisionUsingCurrentFlags(); } + + // force calculate vision when the local vision flags changed + int nCurrentLocalPlayerVisionFlags = GetLocalPlayerVisionFilterFlags(); + if ( m_nLocalPlayerVisionFlags != nCurrentLocalPlayerVisionFlags ) + { + CalculateVisionUsingCurrentFlags(); + m_nLocalPlayerVisionFlags = nCurrentLocalPlayerVisionFlags; + } } // If we are updated while paused, allow the player origin to be snapped by the @@ -2078,7 +2096,7 @@ void C_BasePlayer::GetToolRecordingState( KeyValues *msg ) // then this code can (should!) be removed if ( state.m_bThirdPerson ) { - Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); + const Vector& cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); QAngle camAngles; camAngles[ PITCH ] = cam_ofs[ PITCH ]; @@ -2594,7 +2612,7 @@ void C_BasePlayer::NotePredictionError( const Vector &vDelta ) // offset curtime and setup bones at that time using fake interpolation // fake interpolation means we don't have reliable interpolation history (the local player doesn't animate locally) // so we just modify cycle and origin directly and use that as a fake guess -void C_BasePlayer::ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset ) +bool C_BasePlayer::ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset ) { // we don't have any interpolation data, so fake it float cycle = m_flCycle; @@ -2609,30 +2627,37 @@ void C_BasePlayer::ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOu m_flCycle = fmod( 10 + cycle + m_flPlaybackRate * curtimeOffset, 1.0f ); SetLocalOrigin( origin + curtimeOffset * GetLocalVelocity() ); // Setup bone state to extrapolate physics velocity - SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime + curtimeOffset ); + bool bSuccess = SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime + curtimeOffset ); m_flCycle = cycle; SetLocalOrigin( origin ); + return bSuccess; } -void C_BasePlayer::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) +bool C_BasePlayer::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) { if ( !IsLocalPlayer() ) - { - BaseClass::GetRagdollInitBoneArrays(pDeltaBones0, pDeltaBones1, pCurrentBones, boneDt); - return; - } - ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones0, -boneDt ); - ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones1, 0 ); + return BaseClass::GetRagdollInitBoneArrays(pDeltaBones0, pDeltaBones1, pCurrentBones, boneDt); + + bool bSuccess = true; + + if ( !ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones0, -boneDt ) ) + bSuccess = false; + if ( !ForceSetupBonesAtTimeFakeInterpolation( pDeltaBones1, 0 ) ) + bSuccess = false; + float ragdollCreateTime = PhysGetSyncCreateTime(); if ( ragdollCreateTime != gpGlobals->curtime ) { - ForceSetupBonesAtTimeFakeInterpolation( pCurrentBones, ragdollCreateTime - gpGlobals->curtime ); + if ( !ForceSetupBonesAtTimeFakeInterpolation( pCurrentBones, ragdollCreateTime - gpGlobals->curtime ) ) + bSuccess = false; } else { - SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); + if ( !SetupBones( pCurrentBones, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, gpGlobals->curtime ) ) + bSuccess = false; } + return bSuccess; } @@ -2838,6 +2863,7 @@ void C_BasePlayer::UpdateWearables( void ) { pItem->ValidateModelIndex(); pItem->UpdateVisibility(); + pItem->CreateShadow(); } } } diff --git a/mp/src/game/client/c_baseplayer.h b/mp/src/game/client/c_baseplayer.h index 9d3657bf..5e4372bc 100644 --- a/mp/src/game/client/c_baseplayer.h +++ b/mp/src/game/client/c_baseplayer.h @@ -169,7 +169,7 @@ public: virtual IRagdoll* GetRepresentativeRagdoll() const; // override the initial bone position for ragdolls - virtual void GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ); + virtual bool GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) OVERRIDE; // Returns eye vectors void EyeVectors( Vector *pForward, Vector *pRight = NULL, Vector *pUp = NULL ); @@ -388,7 +388,7 @@ public: #if defined USES_ECON_ITEMS // Wearables - void UpdateWearables(); + virtual void UpdateWearables(); C_EconWearable *GetWearable( int i ) { return m_hMyWearables[i]; } int GetNumWearables( void ) { return m_hMyWearables.Count(); } #endif @@ -585,7 +585,7 @@ protected: virtual bool IsDucked( void ) const { return m_Local.m_bDucked; } virtual bool IsDucking( void ) const { return m_Local.m_bDucking; } virtual float GetFallVelocity( void ) { return m_Local.m_flFallVelocity; } - void ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset ); + bool ForceSetupBonesAtTimeFakeInterpolation( matrix3x4_t *pBonesOut, float curtimeOffset ); float m_flLaggedMovementValue; @@ -611,6 +611,7 @@ protected: float m_flNextAchievementAnnounceTime; int m_nForceVisionFilterFlags; // Force our vision filter to a specific setting + int m_nLocalPlayerVisionFlags; #if defined USES_ECON_ITEMS // Wearables diff --git a/mp/src/game/client/c_baseviewmodel.cpp b/mp/src/game/client/c_baseviewmodel.cpp index 8ae21f63..28c804fb 100644 --- a/mp/src/game/client/c_baseviewmodel.cpp +++ b/mp/src/game/client/c_baseviewmodel.cpp @@ -18,6 +18,9 @@ #include "tools/bonelist.h" #include #include "hltvcamera.h" +#ifdef TF_CLIENT_DLL + #include "tf_weaponbase.h" +#endif #if defined( REPLAY_ENABLED ) #include "replay/replaycamera.h" @@ -53,8 +56,8 @@ void FormatViewModelAttachment( Vector &vOrigin, bool bInverse ) // aspect ratio cancels out, so only need one factor // the difference between the screen coordinates of the 2 systems is the ratio // of the coefficients of the projection matrices (tan (fov/2) is that coefficient) - float factorX = worldx / viewx; - + // NOTE: viewx was coming in as 0 when folks set their viewmodel_fov to 0 and show their weapon. + float factorX = viewx ? ( worldx / viewx ) : 0.0f; float factorY = factorX; // Get the coordinates in the viewer's space. @@ -331,6 +334,16 @@ int C_BaseViewModel::DrawModel( int flags ) } } +#ifdef TF_CLIENT_DLL + CTFWeaponBase* pTFWeapon = dynamic_cast( pWeapon ); + if ( ( flags & STUDIO_RENDER ) && pTFWeapon && pTFWeapon->m_viewmodelStatTrakAddon ) + { + pTFWeapon->m_viewmodelStatTrakAddon->RemoveEffects( EF_NODRAW ); + pTFWeapon->m_viewmodelStatTrakAddon->DrawModel( flags ); + pTFWeapon->m_viewmodelStatTrakAddon->AddEffects( EF_NODRAW ); + } +#endif + return ret; } diff --git a/mp/src/game/client/c_rope.cpp b/mp/src/game/client/c_rope.cpp index 9f11fc5d..0c84778c 100644 --- a/mp/src/game/client/c_rope.cpp +++ b/mp/src/game/client/c_rope.cpp @@ -12,6 +12,7 @@ #include "input.h" #ifdef TF_CLIENT_DLL #include "cdll_util.h" +#include "tf_gamerules.h" #endif #include "rope_helpers.h" #include "engine/ivmodelinfo.h" @@ -640,6 +641,15 @@ bool CRopeManager::IsHolidayLightMode( void ) return false; } +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsPowerupMode() ) + { + // We don't want to draw the lights for the grapple. + // They get left behind for a while and look bad. + return false; + } +#endif + bool bDrawHolidayLights = false; #ifdef USES_ECON_ITEMS @@ -1638,12 +1648,12 @@ struct catmull_t }; // bake out the terms of the catmull rom spline -void Catmull_Rom_Spline_Matrix( const Vector &p1, const Vector &p2, const Vector &p3, const Vector &p4, catmull_t &output ) +void Catmull_Rom_Spline_Matrix( const Vector &vecP1, const Vector &vecP2, const Vector &vecP3, const Vector &vecP4, catmull_t &output ) { - output.t3 = 0.5f * ((-1*p1) + (3*p2) + (-3*p3) + p4); // 0.5 t^3 * [ (-1*p1) + ( 3*p2) + (-3*p3) + p4 ] - output.t2 = 0.5f * ((2*p1) + (-5*p2) + (4*p3) - p4); // 0.5 t^2 * [ ( 2*p1) + (-5*p2) + ( 4*p3) - p4 ] - output.t = 0.5f * ((-1*p1) + p3); // 0.5 t * [ (-1*p1) + p3 ] - output.c = p2; // p2 + output.t3 = 0.5f * ( ( -1 * vecP1 ) + ( 3 * vecP2 ) + ( -3 * vecP3 ) + vecP4 ); // 0.5 t^3 * [ (-1*p1) + ( 3*p2) + (-3*p3) + p4 ] + output.t2 = 0.5f * ( ( 2 * vecP1 ) + ( -5 * vecP2 ) + ( 4 * vecP3 ) - vecP4 ); // 0.5 t^2 * [ ( 2*p1) + (-5*p2) + ( 4*p3) - p4 ] + output.t = 0.5f * ( ( -1 * vecP1 ) + vecP3 ); // 0.5 t * [ (-1*p1) + p3 ] + output.c = vecP2; // p2 } // evaluate one point on the spline, t is a vector of (t, t^2, t^3) diff --git a/mp/src/game/client/c_sceneentity.cpp b/mp/src/game/client/c_sceneentity.cpp index baf2770e..abd211c0 100644 --- a/mp/src/game/client/c_sceneentity.cpp +++ b/mp/src/game/client/c_sceneentity.cpp @@ -219,7 +219,7 @@ void C_SceneEntity::SetupClientOnlyScene( const char *pszFilename, C_BaseFlex *p { LoadSceneFromFile( szFilename ); - if (!CommandLine()->FindParm("-hushasserts")) + if ( !HushAsserts() ) { Assert( m_pScene ); } @@ -257,7 +257,7 @@ void C_SceneEntity::SetupClientOnlyScene( const char *pszFilename, C_BaseFlex *p if ( m_hOwner.Get() ) { - if (!CommandLine()->FindParm("-hushasserts")) + if ( !HushAsserts() ) { Assert( m_pScene ); } @@ -1108,7 +1108,7 @@ void C_SceneEntity::SetCurrentTime( float t, bool forceClientSync ) //----------------------------------------------------------------------------- void C_SceneEntity::PrefetchAnimBlocks( CChoreoScene *pScene ) { - if (!CommandLine()->FindParm("-hushasserts")) + if ( !HushAsserts() ) { Assert( pScene && m_bMultiplayer ); } diff --git a/mp/src/game/client/c_slideshow_display.cpp b/mp/src/game/client/c_slideshow_display.cpp index 90ee0a74..b721f4c3 100644 --- a/mp/src/game/client/c_slideshow_display.cpp +++ b/mp/src/game/client/c_slideshow_display.cpp @@ -272,8 +272,8 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void ) if ( bLoaded ) { - char szKeywords[ 256 ]; - Q_strcpy( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) ); + char szKeywords[ 256 ] = {0}; + V_strcpy_safe( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) ); char *pchKeyword = szKeywords; @@ -306,7 +306,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void ) { // Couldn't find the list, so create it iList = m_SlideMaterialLists.AddToTail( new SlideMaterialList_t ); - Q_strcpy( m_SlideMaterialLists[ iList ]->szSlideKeyword, pchKeyword ); + V_strcpy_safe( m_SlideMaterialLists[iList]->szSlideKeyword, pchKeyword ); } // Add material index to this list @@ -329,7 +329,7 @@ void C_SlideshowDisplay::BuildSlideShowImagesList( void ) { // Couldn't find the generic list, so create it iList = m_SlideMaterialLists.AddToHead( new SlideMaterialList_t ); - Q_strcpy( m_SlideMaterialLists[ iList ]->szSlideKeyword, "" ); + V_strcpy_safe( m_SlideMaterialLists[iList]->szSlideKeyword, "" ); } // Add material index to this list diff --git a/mp/src/game/client/c_soundscape.cpp b/mp/src/game/client/c_soundscape.cpp index 3196eb94..a9baa479 100644 --- a/mp/src/game/client/c_soundscape.cpp +++ b/mp/src/game/client/c_soundscape.cpp @@ -150,7 +150,7 @@ public: { Msg( "- %d: %s\n", i, m_soundscapes[i]->GetName() ); } - if ( m_forcedSoundscapeIndex ) + if ( m_forcedSoundscapeIndex >= 0 ) { Msg( "- PLAYING DEBUG SOUNDSCAPE: %d [%s]\n", m_forcedSoundscapeIndex, SoundscapeNameByIndex(m_forcedSoundscapeIndex) ); } diff --git a/mp/src/game/client/c_team_objectiveresource.h b/mp/src/game/client/c_team_objectiveresource.h index b7139802..9cc431e2 100644 --- a/mp/src/game/client/c_team_objectiveresource.h +++ b/mp/src/game/client/c_team_objectiveresource.h @@ -104,7 +104,7 @@ public: Assert( iCapper != TEAM_UNASSIGNED ); - return GetIconForTeam( index, iCapper );; + return GetIconForTeam( index, iCapper ); } // Icon for the specified team diff --git a/mp/src/game/client/c_vote_controller.cpp b/mp/src/game/client/c_vote_controller.cpp index c900c27e..e99372da 100644 --- a/mp/src/game/client/c_vote_controller.cpp +++ b/mp/src/game/client/c_vote_controller.cpp @@ -81,7 +81,7 @@ C_VoteController::~C_VoteController() void C_VoteController::ResetData() { m_iActiveIssueIndex = INVALID_ISSUE; - m_iOnlyTeamToVote = TEAM_INVALID; + m_iOnlyTeamToVote = TEAM_UNASSIGNED; for( int index = 0; index < MAX_VOTE_OPTIONS; index++ ) { m_nVoteOptionCount[index] = 0; @@ -118,9 +118,11 @@ void C_VoteController::ClientThink() { if ( m_nPotentialVotes > 0 ) { +#ifdef STAGING_ONLY // Currently hard-coded to MAX_VOTE_COUNT options per issue DevMsg( "Votes: Option1 - %d, Option2 - %d, Option3 - %d, Option4 - %d, Option5 - %d\n", m_nVoteOptionCount[0], m_nVoteOptionCount[1], m_nVoteOptionCount[2], m_nVoteOptionCount[3], m_nVoteOptionCount[4] ); +#endif // STAGING_ONLY IGameEvent *event = gameeventmanager->CreateEvent( "vote_changed" ); if ( event ) diff --git a/mp/src/game/client/cdll_bounded_cvars.cpp b/mp/src/game/client/cdll_bounded_cvars.cpp index 0928b774..fa00db63 100644 --- a/mp/src/game/client/cdll_bounded_cvars.cpp +++ b/mp/src/game/client/cdll_bounded_cvars.cpp @@ -133,7 +133,7 @@ float GetClientInterpAmount() } else { - if (!CommandLine()->FindParm("-hushasserts")) + if ( !HushAsserts() ) { AssertMsgOnce( false, "GetInterpolationAmount: can't get cl_updaterate cvar." ); } diff --git a/mp/src/game/client/cdll_client_int.cpp b/mp/src/game/client/cdll_client_int.cpp index 10cce078..5b8f10d9 100644 --- a/mp/src/game/client/cdll_client_int.cpp +++ b/mp/src/game/client/cdll_client_int.cpp @@ -141,6 +141,7 @@ #if defined( TF_CLIENT_DLL ) #include "econ/tool_items/custom_texture_cache.h" + #endif #ifdef WORKSHOP_IMPORT_ENABLED @@ -568,7 +569,8 @@ void DisplayBoneSetupEnts() if ( pEnt->m_Count >= 3 ) { printInfo.color[0] = 1; - printInfo.color[1] = printInfo.color[2] = 0; + printInfo.color[1] = 0; + printInfo.color[2] = 0; } else if ( pEnt->m_Count == 2 ) { @@ -578,7 +580,9 @@ void DisplayBoneSetupEnts() } else { - printInfo.color[0] = printInfo.color[0] = printInfo.color[0] = 1; + printInfo.color[0] = 1; + printInfo.color[1] = 1; + printInfo.color[2] = 1; } engine->Con_NXPrintf( &printInfo, "%25s / %3d / %3d", pEnt->m_ModelName, pEnt->m_Count, pEnt->m_Index ); printInfo.index++; @@ -2561,8 +2565,8 @@ void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params ) // Halloween voice futzery? else { - float flHeadScale = 1.f; - CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flHeadScale, head_scale ); + float flVoicePitchScale = 1.f; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pEntity, flVoicePitchScale, voice_pitch_scale ); int iHalloweenVoiceSpell = 0; CALL_ATTRIB_HOOK_INT_ON_OTHER( pEntity, iHalloweenVoiceSpell, halloween_voice_modulation ); @@ -2570,17 +2574,9 @@ void CHLClient::ClientAdjustStartSoundParams( StartSoundParams_t& params ) { params.pitch *= 0.8f; } - else if( flHeadScale != 1.f ) + else if( flVoicePitchScale != 1.f ) { - // Big head, deep voice - if( flHeadScale > 1.f ) - { - params.pitch *= 0.8f; - } - else // Small head, high voice - { - params.pitch *= 1.3f; - } + params.pitch *= flVoicePitchScale; } } } diff --git a/mp/src/game/client/client_base.vpc b/mp/src/game/client/client_base.vpc index 309ffb8c..b1e5ae53 100644 --- a/mp/src/game/client/client_base.vpc +++ b/mp/src/game/client/client_base.vpc @@ -1252,7 +1252,8 @@ $Project $Lib vtf $ImpLib steam_api - $Lib $LIBCOMMON/libcrypto [$POSIX] + $Libexternal $LIBCOMMON/libcrypto [$OSXALL] + $Libexternal "$SRCDIR\lib\common\$(CRYPTOPPDIR)\libcrypto" [$LINUXALL] $ImpLib "$LIBCOMMON\curl" [$OSXALL] @@ -1262,7 +1263,7 @@ $Project $Libexternal libz [$LINUXALL] $Libexternal "$LIBCOMMON/libcurl" [$LINUXALL] $Libexternal "$LIBCOMMON/libcurlssl" [$LINUXALL] - $Libexternal "$LIBCOMMON/libssl" [$LINUXALL] + $Libexternal "$SRCDIR\lib\common\$(CRYPTOPPDIR)\libssl" [$LINUXALL] } } diff --git a/mp/src/game/client/clientleafsystem.cpp b/mp/src/game/client/clientleafsystem.cpp index 0a4018f1..fa3a0097 100644 --- a/mp/src/game/client/clientleafsystem.cpp +++ b/mp/src/game/client/clientleafsystem.cpp @@ -189,12 +189,12 @@ private: void RemoveShadowFromLeaves( ClientLeafShadowHandle_t handle ); // Methods associated with the various bi-directional sets - static unsigned short& FirstRenderableInLeaf( int leaf ) + static unsigned int& FirstRenderableInLeaf( int leaf ) { return s_ClientLeafSystem.m_Leaf[leaf].m_FirstElement; } - static unsigned short& FirstLeafInRenderable( unsigned short renderable ) + static unsigned int& FirstLeafInRenderable( unsigned short renderable ) { return s_ClientLeafSystem.m_Renderables[renderable].m_LeafList; } @@ -248,8 +248,8 @@ private: int m_RenderFrame2; int m_EnumCount; // Have I been added to a particular shadow yet? int m_TranslucencyCalculated; - unsigned short m_LeafList; // What leafs is it in? - unsigned short m_RenderLeaf; // What leaf do I render in? + unsigned int m_LeafList; // What leafs is it in? + unsigned int m_RenderLeaf; // What leaf do I render in? unsigned char m_Flags; // rendering flags unsigned char m_RenderGroup; // RenderGroup_t type unsigned short m_FirstShadow; // The first shadow caster that cast on it @@ -260,7 +260,7 @@ private: // The leaf contains an index into a list of renderables struct ClientLeaf_t { - unsigned short m_FirstElement; + unsigned int m_FirstElement; unsigned short m_FirstShadow; unsigned short m_FirstDetailProp; @@ -302,7 +302,7 @@ private: CUtlLinkedList< ShadowInfo_t, ClientLeafShadowHandle_t, false, unsigned int > m_Shadows; // Maintains the list of all renderables in a particular leaf - CBidirectionalSet< int, ClientRenderHandle_t, unsigned short, unsigned int > m_RenderablesInLeaf; + CBidirectionalSet< int, ClientRenderHandle_t, unsigned int, unsigned int > m_RenderablesInLeaf; // Maintains a list of all shadows in a particular leaf CBidirectionalSet< int, ClientLeafShadowHandle_t, unsigned short, unsigned int > m_ShadowsInLeaf; @@ -343,7 +343,8 @@ void DefaultRenderBoundsWorldspace( IClientRenderable *pRenderable, Vector &absM { // Tracker 37433: This fixes a bug where if the stunstick is being wielded by a combine soldier, the fact that the stick was // attached to the soldier's hand would move it such that it would get frustum culled near the edge of the screen. - C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); + IClientUnknown *pUnk = pRenderable->GetIClientUnknown(); + C_BaseEntity *pEnt = pUnk->GetBaseEntity(); if ( pEnt && pEnt->IsFollowingEntity() ) { C_BaseEntity *pParent = pEnt->GetFollowedEntity(); @@ -629,7 +630,7 @@ void CClientLeafSystem::NewRenderable( IClientRenderable* pRenderable, RenderGro info.m_Flags = flags; info.m_RenderGroup = (unsigned char)type; info.m_EnumCount = 0; - info.m_RenderLeaf = 0xFFFF; + info.m_RenderLeaf = m_RenderablesInLeaf.InvalidIndex(); if ( IsViewModelRenderGroup( (RenderGroup_t)info.m_RenderGroup ) ) { AddToViewModelList( handle ); @@ -986,7 +987,7 @@ void CClientLeafSystem::AddShadowToLeaf( int leaf, ClientLeafShadowHandle_t shad m_ShadowsInLeaf.AddElementToBucket( leaf, shadow ); // Add the shadow exactly once to all renderables in the leaf - unsigned short i = m_RenderablesInLeaf.FirstElement( leaf ); + unsigned int i = m_RenderablesInLeaf.FirstElement( leaf ); while ( i != m_RenderablesInLeaf.InvalidIndex() ) { ClientRenderHandle_t renderable = m_RenderablesInLeaf.Element(i); @@ -1092,7 +1093,54 @@ void CClientLeafSystem::AddRenderableToLeaf( int leaf, ClientRenderHandle_t rend #ifdef VALIDATE_CLIENT_LEAF_SYSTEM m_RenderablesInLeaf.ValidateAddElementToBucket( leaf, renderable ); #endif - m_RenderablesInLeaf.AddElementToBucket( leaf, renderable ); + +#ifdef DUMP_RENDERABLE_LEAFS + static uint32 count = 0; + if (count < m_RenderablesInLeaf.NumAllocated()) + { + count = m_RenderablesInLeaf.NumAllocated(); + Msg("********** frame: %d count:%u ***************\n", gpGlobals->framecount, count ); + + if (count >= 20000) + { + for (int j = 0; j < m_RenderablesInLeaf.NumAllocated(); j++) + { + const ClientRenderHandle_t& renderable = m_RenderablesInLeaf.Element(j); + RenderableInfo_t& info = m_Renderables[renderable]; + + char pTemp[256]; + const char *pClassName = ""; + C_BaseEntity *pEnt = info.m_pRenderable->GetIClientUnknown()->GetBaseEntity(); + if ( pEnt ) + { + pClassName = pEnt->GetClassname(); + } + else + { + CNewParticleEffect *pEffect = dynamic_cast< CNewParticleEffect*>( info.m_pRenderable ); + if ( pEffect ) + { + Vector mins, maxs; + pEffect->GetRenderBounds(mins, maxs); + Q_snprintf( pTemp, sizeof(pTemp), "ps: %s %.2f,%.2f", pEffect->GetEffectName(), maxs.x - mins.x, maxs.y - mins.y ); + pClassName = pTemp; + } + else if ( dynamic_cast< CParticleEffectBinding* >( info.m_pRenderable ) ) + { + pClassName = ""; + } + } + + Msg(" %d: %p group:%d %s %d %d TransCalc:%d renderframe:%d\n", j, info.m_pRenderable, info.m_RenderGroup, pClassName, + info.m_LeafList, info.m_RenderLeaf, info.m_TranslucencyCalculated, info.m_RenderFrame); + } + + DebuggerBreak(); + } + } +#endif // DUMP_RENDERABLE_LEAFS + + m_RenderablesInLeaf.AddElementToBucket(leaf, renderable); if ( !ShouldRenderableReceiveShadow( renderable, SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ) ) return; @@ -1344,7 +1392,7 @@ void CClientLeafSystem::ComputeTranslucentRenderLeaf( int count, const LeafIndex orderedList.AddToTail( LeafToMarker( leaf ) ); // iterate over all elements in this leaf - unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf); + unsigned int idx = m_RenderablesInLeaf.FirstElement(leaf); while (idx != m_RenderablesInLeaf.InvalidIndex()) { RenderableInfo_t& info = m_Renderables[m_RenderablesInLeaf.Element(idx)]; @@ -1512,7 +1560,7 @@ void CClientLeafSystem::CollateRenderablesInLeaf( int leaf, int worldListLeafInd AddRenderableToRenderList( *info.m_pRenderList, NULL, worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, NULL ); // Collate everything. - unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf); + unsigned int idx = m_RenderablesInLeaf.FirstElement(leaf); for ( ;idx != m_RenderablesInLeaf.InvalidIndex(); idx = m_RenderablesInLeaf.NextElement(idx) ) { ClientRenderHandle_t handle = m_RenderablesInLeaf.Element(idx); diff --git a/mp/src/game/client/clientmode_shared.cpp b/mp/src/game/client/clientmode_shared.cpp index 68bc89cb..622208a4 100644 --- a/mp/src/game/client/clientmode_shared.cpp +++ b/mp/src/game/client/clientmode_shared.cpp @@ -85,6 +85,12 @@ extern ConVar v_viewmodel_fov; extern ConVar voice_modenable; extern bool IsInCommentaryMode( void ); +extern const char* GetWearLocalizationString( float flWear ); + +CON_COMMAND( cl_reload_localization_files, "Reloads all localization files" ) +{ + g_pVGuiLocalize->ReloadLocalizationFiles(); +} #ifdef VOICE_VOX_ENABLE void VoxCallback( IConVar *var, const char *oldString, float oldFloat ) @@ -141,7 +147,7 @@ CON_COMMAND( hud_reloadscheme, "Reloads hud layout and animation scripts." ) if ( !mode ) return; - mode->ReloadScheme(); + mode->ReloadScheme(true); } #ifdef _DEBUG @@ -292,8 +298,14 @@ ClientModeShared::~ClientModeShared() delete m_pViewport; } -void ClientModeShared::ReloadScheme( void ) +void ClientModeShared::ReloadScheme( bool flushLowLevel ) { + // Invalidate the global cache first. + if (flushLowLevel) + { + KeyValuesSystem()->InvalidateCache(); + } + m_pViewport->ReloadScheme( "resource/ClientScheme.res" ); ClearKeyValuesCache(); } @@ -335,7 +347,7 @@ void ClientModeShared::Init() Assert( m_pReplayReminderPanel ); #endif - ListenForGameEvent( "player_connect" ); + ListenForGameEvent( "player_connect_client" ); ListenForGameEvent( "player_disconnect" ); ListenForGameEvent( "player_team" ); ListenForGameEvent( "server_cvar" ); @@ -421,7 +433,7 @@ void ClientModeShared::OverrideView( CViewSetup *pSetup ) if( ::input->CAM_IsThirdPerson() ) { - Vector cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); + const Vector& cam_ofs = g_ThirdPersonManager.GetCameraOffsetAngles(); Vector cam_ofs_distance = g_ThirdPersonManager.GetFinalCameraOffset(); cam_ofs_distance *= g_ThirdPersonManager.GetDistanceFraction(); @@ -867,7 +879,7 @@ void ClientModeShared::LevelShutdown( void ) void ClientModeShared::Enable() { - vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel(); // Add our viewport to the root panel. if( pRoot != 0 ) @@ -894,7 +906,7 @@ void ClientModeShared::Enable() void ClientModeShared::Disable() { - vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel();; + vgui::VPANEL pRoot = VGui_GetClientDLLRootPanel(); // Remove our viewport from the root panel. if( pRoot != 0 ) @@ -923,7 +935,7 @@ void ClientModeShared::Layout() m_pViewport->SetBounds(0, 0, wide, tall); if ( changed ) { - ReloadScheme(); + ReloadScheme(false); } } } @@ -955,7 +967,7 @@ void ClientModeShared::FireGameEvent( IGameEvent *event ) const char *eventname = event->GetName(); - if ( Q_strcmp( "player_connect", eventname ) == 0 ) + if ( Q_strcmp( "player_connect_client", eventname ) == 0 ) { if ( !hudChat ) return; @@ -1115,7 +1127,7 @@ void ClientModeShared::FireGameEvent( IGameEvent *event ) { CBasePlayer *pSpectatorTarget = UTIL_PlayerByIndex( GetSpectatorTarget() ); - if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE) ) + if ( pSpectatorTarget && (GetSpectatorMode() == OBS_MODE_IN_EYE || GetSpectatorMode() == OBS_MODE_CHASE || GetSpectatorMode() == OBS_MODE_POI) ) { if ( pSpectatorTarget->GetTeamNumber() == team ) { @@ -1222,10 +1234,14 @@ void ClientModeShared::FireGameEvent( IGameEvent *event ) entityquality_t iItemQuality = event->GetInt( "quality" ); int iMethod = event->GetInt( "method" ); int iItemDef = event->GetInt( "itemdef" ); + bool bIsStrange = event->GetInt( "isstrange" ); + bool bIsUnusual = event->GetInt( "isunusual" ); + float flWear = event->GetFloat( "wear" ); + C_BasePlayer *pPlayer = UTIL_PlayerByIndex( iPlayerIndex ); const GameItemDefinition_t *pItemDefinition = dynamic_cast( GetItemSchema()->GetItemDefinition( iItemDef ) ); - if ( !pPlayer || !pItemDefinition ) + if ( !pPlayer || !pItemDefinition || pItemDefinition->IsHidden() ) return; if ( g_PR ) @@ -1245,19 +1261,101 @@ void ClientModeShared::FireGameEvent( IGameEvent *event ) _snwprintf( wszItemFound, ARRAYSIZE( wszItemFound ), L"%ls", g_pVGuiLocalize->Find( pszLocString ) ); wchar_t *colorMarker = wcsstr( wszItemFound, L"::" ); + const CEconItemRarityDefinition* pItemRarity = GetItemSchema()->GetRarityDefinition( pItemDefinition->GetRarity() ); + if ( colorMarker ) - { - const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality ); - if ( pszQualityColorString ) + { + if ( pItemRarity ) { - hudChat->SetCustomColor( pszQualityColorString ); - *(colorMarker+1) = COLOR_CUSTOM; + attrib_colors_t colorRarity = pItemRarity->GetAttribColor(); + vgui::HScheme scheme = vgui::scheme()->GetScheme( "ClientScheme" ); + vgui::IScheme *pScheme = vgui::scheme()->GetIScheme( scheme ); + Color color = pScheme->GetColor( GetColorNameForAttribColor( colorRarity ), Color( 255, 255, 255, 255 ) ); + hudChat->SetCustomColor( color ); } + else + { + const char *pszQualityColorString = EconQuality_GetColorString( (EEconItemQuality)iItemQuality ); + if ( pszQualityColorString ) + { + hudChat->SetCustomColor( pszQualityColorString ); + } + } + + *(colorMarker+1) = COLOR_CUSTOM; } // TODO: Update the localization strings to only have two format parameters since that's all we need. wchar_t wszLocalizedString[256]; - g_pVGuiLocalize->ConstructString( wszLocalizedString, sizeof( wszLocalizedString ), wszItemFound, 3, wszPlayerName, CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName(), L"" ); + g_pVGuiLocalize->ConstructString( + wszLocalizedString, + sizeof( wszLocalizedString ), + LOCCHAR( "%s1" ), + 1, + CEconItemLocalizedFullNameGenerator( GLocalizationProvider(), pItemDefinition, iItemQuality ).GetFullName() + ); + + locchar_t tempName[MAX_ITEM_NAME_LENGTH]; + if ( pItemRarity ) + { + // grade and Wear + loc_scpy_safe( tempName, wszLocalizedString ); + + const locchar_t *loc_WearText = LOCCHAR(""); + const char *pszTooltipText = "TFUI_InvTooltip_Rarity"; + + if ( !IsWearableSlot( pItemDefinition->GetDefaultLoadoutSlot() ) ) + { + loc_WearText = g_pVGuiLocalize->Find( GetWearLocalizationString( flWear ) ); + } + else + { + pszTooltipText = "TFUI_InvTooltip_RarityNoWear"; + } + + g_pVGuiLocalize->ConstructString( wszLocalizedString, + ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ), + g_pVGuiLocalize->Find( pszTooltipText ), + 3, + g_pVGuiLocalize->Find( pItemRarity->GetLocKey() ), + tempName, + loc_WearText + ); + + if ( bIsUnusual ) + { + loc_scpy_safe( tempName, wszLocalizedString ); + + g_pVGuiLocalize->ConstructString( wszLocalizedString, + ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ), + LOCCHAR( "%s1 %s2" ), + 2, + g_pVGuiLocalize->Find( "rarity4" ), + tempName + ); + } + + if ( bIsStrange ) + { + loc_scpy_safe( tempName, wszLocalizedString ); + + g_pVGuiLocalize->ConstructString( wszLocalizedString, + ARRAYSIZE( wszLocalizedString ) * sizeof( locchar_t ), + LOCCHAR( "%s1 %s2" ), + 2, + g_pVGuiLocalize->Find( "strange" ), + tempName + ); + } + } + + loc_scpy_safe( tempName, wszLocalizedString ); + g_pVGuiLocalize->ConstructString( + wszLocalizedString, + sizeof( wszLocalizedString ), + wszItemFound, + 3, + wszPlayerName, tempName, L"" ); char szLocalized[256]; g_pVGuiLocalize->ConvertUnicodeToANSI( wszLocalizedString, szLocalized, sizeof( szLocalized ) ); diff --git a/mp/src/game/client/clientmode_shared.h b/mp/src/game/client/clientmode_shared.h index 27336964..beef0ad9 100644 --- a/mp/src/game/client/clientmode_shared.h +++ b/mp/src/game/client/clientmode_shared.h @@ -66,7 +66,7 @@ public: virtual void Disable(); virtual void Layout(); - virtual void ReloadScheme( void ); + virtual void ReloadScheme( bool flushLowLevel ); virtual void OverrideView( CViewSetup *pSetup ); virtual bool ShouldDrawDetailObjects( ); virtual bool ShouldDrawEntity(C_BaseEntity *pEnt); diff --git a/mp/src/game/client/clientshadowmgr.cpp b/mp/src/game/client/clientshadowmgr.cpp index c37e7650..bd3e2c2a 100644 --- a/mp/src/game/client/clientshadowmgr.cpp +++ b/mp/src/game/client/clientshadowmgr.cpp @@ -1802,6 +1802,9 @@ ClientShadowHandle_t CClientShadowMgr::CreateProjectedTexture( ClientEntityHandl if( !( flags & SHADOW_FLAGS_FLASHLIGHT ) ) { IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( entity ); + if ( !pRenderable ) + return m_Shadows.InvalidIndex(); + int modelType = modelinfo->GetModelType( pRenderable->GetModel() ); if (modelType == mod_brush) { diff --git a/mp/src/game/client/clientsideeffects.cpp b/mp/src/game/client/clientsideeffects.cpp index b9cb5f56..c7912e3b 100644 --- a/mp/src/game/client/clientsideeffects.cpp +++ b/mp/src/game/client/clientsideeffects.cpp @@ -68,6 +68,15 @@ const char *CClientSideEffect::GetName( void ) return m_pszName; } +//----------------------------------------------------------------------------- +// Purpose: Set the name of effect +// Input : const char +//----------------------------------------------------------------------------- +void CClientSideEffect::SetEffectName( const char *pszName ) +{ + m_pszName = pszName; +} + //----------------------------------------------------------------------------- // Purpose: Is effect still active? // Output : Returns true on success, false on failure. @@ -99,6 +108,7 @@ public: // Add an effect to the effects list void AddEffect( CClientSideEffect *effect ); // Remove the specified effect + void RemoveEffect( CClientSideEffect *effect ); // Draw/update all effects in the current list void DrawEffects( double frametime ); // Flush out all effects from the list @@ -160,6 +170,23 @@ void CEffectsList::AddEffect( CClientSideEffect *effect ) m_rgEffects[ m_nEffects++ ] = effect; } +//----------------------------------------------------------------------------- +void CEffectsList::RemoveEffect( CClientSideEffect *effect ) +{ + Assert( effect ); + CClientSideEffect **end = &m_rgEffects[m_nEffects]; + for( CClientSideEffect **p = &m_rgEffects[0]; p < end; ++p) + { + if ( *p == effect ) + { + RemoveEffect( p - &m_rgEffects[0] ); // todo remove this crutch + return; + } + } + + Assert( false ); // don't know this effect +} + //----------------------------------------------------------------------------- // Purpose: Remove specified effect by index // Input : effectIndex - diff --git a/mp/src/game/client/clientsideeffects.h b/mp/src/game/client/clientsideeffects.h index c5aa4fd6..fd749565 100644 --- a/mp/src/game/client/clientsideeffects.h +++ b/mp/src/game/client/clientsideeffects.h @@ -32,7 +32,10 @@ public: virtual bool IsActive( void ); // Sets the effect to inactive so it can be destroed virtual void Destroy( void ); - + + // Sets the effect name (useful for debugging). + virtual void SetEffectName( const char *pszName ); + private: // Name of effect ( static data ) const char *m_pszName; @@ -50,6 +53,8 @@ public: // Add an effect to the list of effects virtual void AddEffect( CClientSideEffect *effect ) = 0; + // Remove the specified effect + virtual void RemoveEffect( CClientSideEffect *effect ) = 0; // Simulate/Update/Draw effects on list virtual void DrawEffects( double frametime ) = 0; // Flush out all effects fbrom the list diff --git a/mp/src/game/client/fx_quad.cpp b/mp/src/game/client/fx_quad.cpp index 6a254b97..12d95b7d 100644 --- a/mp/src/game/client/fx_quad.cpp +++ b/mp/src/game/client/fx_quad.cpp @@ -13,11 +13,21 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -CFXQuad::CFXQuad( const FXQuadData_t &data ) +static const char g_EffectName[] = "Quad"; -: CClientSideEffect( "Quad" ) +CFXQuad::CFXQuad( const FXQuadData_t &data ) + : CClientSideEffect( g_EffectName ) { m_FXData = data; + + if ( data.m_pMaterial != NULL ) + { + // If we've got a material, use that as our effectname instead of just "Quad". + // This should hopefully help narrow down messages like "No room for effect Quad". + const char *szMaterialName = data.m_pMaterial->GetName(); + if ( szMaterialName ) + SetEffectName( szMaterialName ); + } } CFXQuad::~CFXQuad( void ) @@ -62,6 +72,12 @@ void CFXQuad::Draw( double frametime ) float alpha = m_FXData.m_flStartAlpha + ( ( m_FXData.m_flEndAlpha - m_FXData.m_flStartAlpha ) * alphaTimePerc ); alpha = clamp( alpha, 0.0f, 1.0f ); + + // PASSTIME don't bother if alpha is 0 + if ( alpha == 0 ) + { + return; + } CMatRenderContextPtr pRenderContext( materials ); @@ -152,6 +168,8 @@ bool CFXQuad::IsActive( void ) //----------------------------------------------------------------------------- void CFXQuad::Destroy( void ) { + SetEffectName( g_EffectName ); + //Release the material if ( m_FXData.m_pMaterial != NULL ) { diff --git a/mp/src/game/client/fx_quad.h b/mp/src/game/client/fx_quad.h index 77563e8b..638547e8 100644 --- a/mp/src/game/client/fx_quad.h +++ b/mp/src/game/client/fx_quad.h @@ -82,8 +82,6 @@ public: virtual void Destroy( void ); virtual void Update( double frametime ); -protected: - FXQuadData_t m_FXData; }; diff --git a/mp/src/game/client/fx_tracer.cpp b/mp/src/game/client/fx_tracer.cpp index f0ca0e13..cec013a6 100644 --- a/mp/src/game/client/fx_tracer.cpp +++ b/mp/src/game/client/fx_tracer.cpp @@ -13,6 +13,9 @@ // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" +ConVar r_drawtracers( "r_drawtracers", "1", FCVAR_CHEAT ); +ConVar r_drawtracers_firstperson( "r_drawtracers_firstperson", "1", FCVAR_ARCHIVE, "Toggle visibility of first person weapon tracers" ); + #define TRACER_SPEED 5000 //----------------------------------------------------------------------------- @@ -23,7 +26,7 @@ Vector GetTracerOrigin( const CEffectData &data ) Vector vecStart = data.m_vStart; QAngle vecAngles; - int iAttachment = data.m_nAttachmentIndex;; + int iAttachment = data.m_nAttachmentIndex; // Attachment? if ( data.m_fFlags & TRACER_FLAG_USEATTACHMENT ) @@ -77,6 +80,17 @@ void TracerCallback( const CEffectData &data ) if ( !player ) return; + if ( !r_drawtracers.GetBool() ) + return; + + if ( !r_drawtracers_firstperson.GetBool() ) + { + C_BasePlayer *pPlayer = dynamic_cast( data.GetEntity() ); + + if ( pPlayer && !pPlayer->ShouldDrawThisPlayer() ) + return; + } + // Grab the data Vector vecStart = GetTracerOrigin( data ); float flVelocity = data.m_flScale; @@ -120,6 +134,17 @@ void ParticleTracerCallback( const CEffectData &data ) if ( !player ) return; + if ( !r_drawtracers.GetBool() ) + return; + + if ( !r_drawtracers_firstperson.GetBool() ) + { + C_BasePlayer *pPlayer = dynamic_cast( data.GetEntity() ); + + if ( pPlayer && !pPlayer->ShouldDrawThisPlayer() ) + return; + } + // Grab the data Vector vecStart = GetTracerOrigin( data ); Vector vecEnd = data.m_vOrigin; diff --git a/mp/src/game/client/game_controls/MapOverview.cpp b/mp/src/game/client/game_controls/MapOverview.cpp index b4262fbb..73d259ff 100644 --- a/mp/src/game/client/game_controls/MapOverview.cpp +++ b/mp/src/game/client/game_controls/MapOverview.cpp @@ -181,7 +181,7 @@ void CMapOverview::Init( void ) // register for events as client listener ListenForGameEvent( "game_newmap" ); ListenForGameEvent( "round_start" ); - ListenForGameEvent( "player_connect" ); + ListenForGameEvent( "player_connect_client" ); ListenForGameEvent( "player_info" ); ListenForGameEvent( "player_team" ); ListenForGameEvent( "player_spawn" ); @@ -933,7 +933,7 @@ void CMapOverview::FireGameEvent( IGameEvent *event ) ResetRound(); } - else if ( Q_strcmp(type,"player_connect") == 0 ) + else if ( Q_strcmp(type,"player_connect_client") == 0 ) { int index = event->GetInt("index"); // = entity index - 1 diff --git a/mp/src/game/client/game_controls/SpectatorGUI.cpp b/mp/src/game/client/game_controls/SpectatorGUI.cpp index 1c95068a..3ce30008 100644 --- a/mp/src/game/client/game_controls/SpectatorGUI.cpp +++ b/mp/src/game/client/game_controls/SpectatorGUI.cpp @@ -67,6 +67,7 @@ static const char *s_SpectatorModes[] = "#Spec_Mode2", // OBS_MODE_FIXED, "#Spec_Mode3", // OBS_MODE_IN_EYE, "#Spec_Mode4", // OBS_MODE_CHASE, + "#Spec_Mode_POI", // OBS_MODE_POI, PASSTIME "#Spec_Mode5", // OBS_MODE_ROAMING, }; @@ -806,6 +807,8 @@ CON_COMMAND_F( spec_mode, "Set spectator mode", FCVAR_CLIENTCMD_CAN_EXECUTE ) if ( mode > LAST_PLAYER_OBSERVERMODE ) mode = OBS_MODE_IN_EYE; + else if ( mode == OBS_MODE_POI ) // PASSTIME skip POI mode since hltv doesn't have the entity data required to make it work + mode = OBS_MODE_ROAMING; } // handle the command clientside diff --git a/mp/src/game/client/game_controls/basemodel_panel.cpp b/mp/src/game/client/game_controls/basemodel_panel.cpp index e4115ea4..5f834412 100644 --- a/mp/src/game/client/game_controls/basemodel_panel.cpp +++ b/mp/src/game/client/game_controls/basemodel_panel.cpp @@ -22,6 +22,7 @@ CBaseModelPanel::CBaseModelPanel( vgui::Panel *pParent, const char *pName ): Bas m_bForcePos = false; m_bMousePressed = false; m_bAllowRotation = false; + m_bAllowPitch = false; m_bAllowFullManipulation = false; m_bApplyManipulators = false; m_bForcedCameraPosition = false; @@ -43,6 +44,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData ) // Set whether we render to texture m_bRenderToTexture = inResourceData->GetBool( "render_texture", true ); + m_bUseParticle = inResourceData->GetBool( "use_particle", false ); // Grab and set the camera FOV. float flFOV = GetCameraFOV(); @@ -51,6 +53,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData ) // Do we allow rotation on these panels. m_bAllowRotation = inResourceData->GetBool( "allow_rot", false ); + m_bAllowPitch = inResourceData->GetBool( "allow_pitch", false ); // Do we allow full manipulation on these panels. m_bAllowFullManipulation = inResourceData->GetBool( "allow_manip", false ); @@ -64,7 +67,7 @@ void CBaseModelPanel::ApplySettings( KeyValues *inResourceData ) } } - SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation ); + SetMouseInputEnabled( m_bAllowFullManipulation || m_bAllowRotation || m_bAllowPitch ); } //----------------------------------------------------------------------------- @@ -412,13 +415,16 @@ void CBaseModelPanel::OnMousePressed ( vgui::MouseCode code ) return; } - if ( !m_bAllowRotation ) + if ( !m_bAllowRotation && !m_bAllowPitch ) return; RequestFocus(); EnableMouseCapture( true, code ); + // Save where they clicked + input()->GetCursorPosition( m_nClickStartX, m_nClickStartY ); + // Warp the mouse to the center of the screen int width, height; GetSize( width, height ); @@ -446,11 +452,14 @@ void CBaseModelPanel::OnMouseReleased( vgui::MouseCode code ) return; } - if ( !m_bAllowRotation ) + if ( !m_bAllowRotation && !m_bAllowPitch ) return; EnableMouseCapture( false ); m_bMousePressed = false; + + // Restore the cursor to where the clicked + input()->SetCursorPos( m_nClickStartX, m_nClickStartY ); } //----------------------------------------------------------------------------- @@ -467,7 +476,7 @@ void CBaseModelPanel::OnCursorMoved( int x, int y ) return; } - if ( !m_bAllowRotation ) + if ( !m_bAllowRotation && !m_bAllowPitch ) return; if ( m_bMousePressed ) @@ -476,11 +485,25 @@ void CBaseModelPanel::OnCursorMoved( int x, int y ) int xpos, ypos; input()->GetCursorPos( xpos, ypos ); - // Only want the x delta. - float flDelta = xpos - m_nManipStartX; + if ( m_bAllowRotation ) + { + // Only want the x delta. + float flDelta = xpos - m_nManipStartX; - // Apply the delta and rotate the player. - RotateYaw( flDelta ); + + // Apply the delta and rotate the player. + RotateYaw( flDelta ); + } + + if ( m_bAllowPitch ) + { + // Only want the y delta. + float flDelta = ypos - m_nManipStartY; + + + // Apply the delta and rotate the player. + RotatePitch( flDelta ); + } } } @@ -501,6 +524,23 @@ void CBaseModelPanel::RotateYaw( float flDelta ) SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos ); } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CBaseModelPanel::RotatePitch( float flDelta ) +{ + m_angPlayer.x += flDelta; + if ( m_angPlayer.x > m_flMaxPitch ) + { + m_angPlayer.x = m_flMaxPitch; + } + else if ( m_angPlayer.x < -m_flMaxPitch ) + { + m_angPlayer.x = -m_flMaxPitch; + } + + SetModelAnglesAndPosition( m_angPlayer, m_vecPlayerPos ); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- Vector CBaseModelPanel::GetPlayerPos() const @@ -643,7 +683,7 @@ void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &ve // Clear the camera pivot and set position matrix. ResetCameraPivot(); - if (m_bAllowRotation ) + if (m_bAllowRotation || m_bAllowPitch ) { vecCameraOffset.x = 0.0f; } @@ -651,3 +691,150 @@ void CBaseModelPanel::LookAtBounds( const Vector &vecBoundsMin, const Vector &ve UpdateCameraTransform(); } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBaseModelPanel::particle_data_t::~particle_data_t() +{ + if ( m_pParticleSystem ) + { + delete m_pParticleSystem; + m_pParticleSystem = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Allocate particle data +//----------------------------------------------------------------------------- +void CBaseModelPanel::particle_data_t::UpdateControlPoints( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix, const CUtlVector< int >& vecAttachments, int iDefaultBone /*= 0*/, const Vector& vecParticleOffset /*= vec3_origin*/ ) +{ + if ( m_pParticleSystem ) + { + // Update control points which is updating the position of the particles + matrix3x4_t matAttachToWorld; + Vector vecPosition, vecForward, vecRight, vecUp; + if ( vecAttachments.Count() ) + { + for ( int i = 0; i < vecAttachments.Count(); ++i ) + { + const mstudioattachment_t& attach = pStudioHdr->pAttachment( vecAttachments[i] ); + MatrixMultiply( pWorldMatrix[ attach.localbone ], attach.local, matAttachToWorld ); + + MatrixVectors( matAttachToWorld, &vecForward, &vecRight, &vecUp ); + MatrixPosition( matAttachToWorld, vecPosition ); + + m_pParticleSystem->SetControlPointOrientation( i, vecForward, vecRight, vecUp ); + m_pParticleSystem->SetControlPoint( i, vecPosition + vecParticleOffset ); + } + } + else + { + matAttachToWorld = pWorldMatrix[iDefaultBone]; + MatrixVectors( matAttachToWorld, &vecForward, &vecRight, &vecUp ); + MatrixPosition( matAttachToWorld, vecPosition ); + + m_pParticleSystem->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); + m_pParticleSystem->SetControlPoint( 0, vecPosition + vecParticleOffset ); + } + } + + m_bIsUpdateToDate = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Allocate particle data +//----------------------------------------------------------------------------- +CBaseModelPanel::particle_data_t *CBaseModelPanel::CreateParticleData( const char *pszParticleName ) +{ + Assert( m_bUseParticle ); + if ( !m_bUseParticle ) + return NULL; + + CParticleCollection *pParticle = g_pParticleSystemMgr->CreateParticleCollection( pszParticleName ); + if ( !pParticle ) + return NULL; + + particle_data_t *pData = new particle_data_t; + pData->m_bIsUpdateToDate = false; + pData->m_pParticleSystem = pParticle; + + m_particleList.AddToTail( pData ); + + return pData; +} + + +//----------------------------------------------------------------------------- +// Purpose: remove and delete particle data +//----------------------------------------------------------------------------- +bool CBaseModelPanel::SafeDeleteParticleData( particle_data_t **pData ) +{ + if ( !m_bUseParticle ) + return false; + + if ( *pData ) + { + FOR_EACH_VEC( m_particleList, i ) + { + if ( *pData == m_particleList[i] ) + { + delete *pData; + *pData = NULL; + m_particleList.FastRemove( i ); + return true; + } + } + } + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseModelPanel::PrePaint3D( IMatRenderContext *pRenderContext ) +{ + if ( !m_bUseParticle ) + return; + + // mark all effects need to be updated + FOR_EACH_VEC( m_particleList, i ) + { + m_particleList[i]->m_bIsUpdateToDate = false; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseModelPanel::PostPaint3D( IMatRenderContext *pRenderContext ) +{ + if ( !m_bUseParticle ) + return; + + // This needs calling to reset various counters. + g_pParticleSystemMgr->SetLastSimulationTime( gpGlobals->curtime ); + + // Render Particles + pRenderContext->MatrixMode( MATERIAL_MODEL ); + pRenderContext->PushMatrix(); + pRenderContext->LoadIdentity( ); + + FOR_EACH_VEC( m_particleList, i ) + { + if ( m_particleList[i]->m_bIsUpdateToDate ) + { + m_particleList[i]->m_pParticleSystem->Simulate( gpGlobals->frametime, false ); + m_particleList[i]->m_pParticleSystem->Render( pRenderContext ); + m_particleList[i]->m_bIsUpdateToDate = false; + } + } + + pRenderContext->MatrixMode( MATERIAL_MODEL ); + pRenderContext->PopMatrix(); +} + diff --git a/mp/src/game/client/game_controls/basemodel_panel.h b/mp/src/game/client/game_controls/basemodel_panel.h index b9fa0d68..a71bb7a4 100644 --- a/mp/src/game/client/game_controls/basemodel_panel.h +++ b/mp/src/game/client/game_controls/basemodel_panel.h @@ -182,7 +182,8 @@ public: studiohdr_t* GetStudioHdr( void ) { return m_RootMDL.m_MDL.GetStudioHdr(); } void SetBody( unsigned int nBody ) { m_RootMDL.m_MDL.m_nBody = nBody; } - void RotateYaw( float flDelta ); + void RotateYaw( float flDelta ); + void RotatePitch( float flDelta ); Vector GetPlayerPos() const; QAngle GetPlayerAngles() const; @@ -213,6 +214,7 @@ protected: bool m_bForcePos; bool m_bMousePressed; bool m_bAllowRotation; + bool m_bAllowPitch; bool m_bAllowFullManipulation; bool m_bApplyManipulators; bool m_bForcedCameraPosition; @@ -220,6 +222,25 @@ protected: // VGUI script accessible variables. CPanelAnimationVar( bool, m_bStartFramed, "start_framed", "0" ); CPanelAnimationVar( bool, m_bDisableManipulation, "disable_manipulation", "0" ); + CPanelAnimationVar( bool, m_bUseParticle, "use_particle", "0" ); + CPanelAnimationVar( float, m_flMaxPitch, "max_pitch", "90" ); + + struct particle_data_t + { + ~particle_data_t(); + + void UpdateControlPoints( CStudioHdr *pStudioHdr, matrix3x4_t *pWorldMatrix, const CUtlVector< int >& vecAttachments, int iDefaultBone = 0, const Vector& vecParticleOffset = vec3_origin ); + + bool m_bIsUpdateToDate; + CParticleCollection *m_pParticleSystem; + }; + CUtlVector< particle_data_t* > m_particleList; + + particle_data_t *CreateParticleData( const char *pszParticleName ); + bool SafeDeleteParticleData( particle_data_t **pData ); + + virtual void PrePaint3D( IMatRenderContext *pRenderContext ) OVERRIDE; + virtual void PostPaint3D( IMatRenderContext *pRenderContext ) OVERRIDE; }; #endif // BASEMODEL_PANEL_H \ No newline at end of file diff --git a/mp/src/game/client/game_controls/baseviewport.cpp b/mp/src/game/client/game_controls/baseviewport.cpp index f239cde8..31d8dca2 100644 --- a/mp/src/game/client/game_controls/baseviewport.cpp +++ b/mp/src/game/client/game_controls/baseviewport.cpp @@ -65,7 +65,17 @@ vgui::Panel *g_lastPanel = NULL; // used for mouseover buttons, keeps track of t vgui::Button *g_lastButton = NULL; // used for mouseover buttons, keeps track of the last active button using namespace vgui; -ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran"); +void hud_autoreloadscript_callback( IConVar *var, const char *pOldValue, float flOldValue ); + +ConVar hud_autoreloadscript("hud_autoreloadscript", "0", FCVAR_NONE, "Automatically reloads the animation script each time one is ran", hud_autoreloadscript_callback); + +void hud_autoreloadscript_callback( IConVar *var, const char *pOldValue, float flOldValue ) +{ + if ( g_pClientMode && g_pClientMode->GetViewportAnimationController() ) + { + g_pClientMode->GetViewportAnimationController()->SetAutoReloadScript( hud_autoreloadscript.GetBool() ); + } +} static ConVar cl_leveloverviewmarker( "cl_leveloverviewmarker", "0", FCVAR_CHEAT ); @@ -573,11 +583,12 @@ void CBaseViewport::OnThink() else m_pActivePanel = NULL; } - - m_pAnimController->UpdateAnimations( gpGlobals->curtime ); - // check the auto-reload cvar - m_pAnimController->SetAutoReloadScript(hud_autoreloadscript.GetBool()); + // TF does this in OnTick in TFViewport. This remains to preserve old + // behavior in other games +#if !defined( TF_CLIENT_DLL ) + m_pAnimController->UpdateAnimations( gpGlobals->curtime ); +#endif int count = m_Panels.Count(); diff --git a/mp/src/game/client/game_controls/vguitextwindow.cpp b/mp/src/game/client/game_controls/vguitextwindow.cpp index 3c641859..3c25eb80 100644 --- a/mp/src/game/client/game_controls/vguitextwindow.cpp +++ b/mp/src/game/client/game_controls/vguitextwindow.cpp @@ -138,9 +138,9 @@ void CTextWindow::Reset( void ) // HPE_BEGIN: // [Forrest] Replace strange hard-coded default message with hard-coded error message. //============================================================================= - Q_strcpy( m_szTitle, "Error loading info message." ); - Q_strcpy( m_szMessage, "" ); - Q_strcpy( m_szMessageFallback, "" ); + V_strcpy_safe( m_szTitle, "Error loading info message." ); + V_strcpy_safe( m_szMessage, "" ); + V_strcpy_safe( m_szMessageFallback, "" ); //============================================================================= // HPE_END //============================================================================= diff --git a/mp/src/game/client/hl2/c_waterbullet.cpp b/mp/src/game/client/hl2/c_waterbullet.cpp index b4491ca1..c758069d 100644 --- a/mp/src/game/client/hl2/c_waterbullet.cpp +++ b/mp/src/game/client/hl2/c_waterbullet.cpp @@ -85,7 +85,7 @@ public: sParticle->m_flDieTime = 0.2f; sParticle->m_flRoll = random->RandomInt( 0, 360 ); - sParticle->m_flRollDelta = random->RandomInt( -4, 4 );; + sParticle->m_flRollDelta = random->RandomInt( -4, 4 ); unsigned char color = random->RandomInt( 200, 255 ); diff --git a/mp/src/game/client/hl2/hud_credits.cpp b/mp/src/game/client/hl2/hud_credits.cpp index 8021c49a..6ad1488b 100644 --- a/mp/src/game/client/hl2/hud_credits.cpp +++ b/mp/src/game/client/hl2/hud_credits.cpp @@ -215,8 +215,8 @@ void CHudCredits::ReadNames( KeyValues *pKeyValue ) while ( pKVNames ) { creditname_t Credits; - Q_strcpy( Credits.szCreditName, pKVNames->GetName()); - Q_strcpy( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) ); + V_strcpy_safe( Credits.szCreditName, pKVNames->GetName() ); + V_strcpy_safe( Credits.szFontName, pKeyValue->GetString( Credits.szCreditName, "Default" ) ); m_CreditsList.AddToTail( Credits ); pKVNames = pKVNames->GetNextKey(); diff --git a/mp/src/game/client/hltvcamera.cpp b/mp/src/game/client/hltvcamera.cpp index 9754b99f..1da4acfd 100644 --- a/mp/src/game/client/hltvcamera.cpp +++ b/mp/src/game/client/hltvcamera.cpp @@ -736,7 +736,7 @@ void C_HLTVCamera::FireGameEvent( IGameEvent * event) } // after this only auto-director commands follow - // don't execute them is autodirector is off and PVS is unlocked + // don't execute them if autodirector is off and PVS is unlocked if ( !spec_autodirector.GetBool() && !IsPVSLocked() ) return; diff --git a/mp/src/game/client/hud_basechat.cpp b/mp/src/game/client/hud_basechat.cpp index 69d67862..f6b20413 100644 --- a/mp/src/game/client/hud_basechat.cpp +++ b/mp/src/game/client/hud_basechat.cpp @@ -24,6 +24,7 @@ #include "vgui/IInput.h" #include "vgui/ILocalize.h" #include "multiplay_gamerules.h" +#include "voice_status.h" // memdbgon must be the last include file in a .cpp file!!! @@ -36,6 +37,7 @@ ConVar hud_saytext_time( "hud_saytext_time", "12", 0 ); ConVar cl_showtextmsg( "cl_showtextmsg", "1", 0, "Enable/disable text messages printing on the screen." ); ConVar cl_chatfilters( "cl_chatfilters", "63", FCVAR_CLIENTDLL | FCVAR_ARCHIVE, "Stores the chat filter settings " ); ConVar cl_chatfilter_version( "cl_chatfilter_version", "0", FCVAR_CLIENTDLL | FCVAR_ARCHIVE | FCVAR_HIDDEN, "Stores the chat filter version" ); +ConVar cl_mute_all_comms("cl_mute_all_comms", "1", FCVAR_ARCHIVE, "If 1, then all communications from a player will be blocked when that player is muted, including chat messages."); const int kChatFilterVersion = 1; @@ -1750,6 +1752,13 @@ void CBaseHudChat::ChatPrintf( int iPlayerIndex, int iFilter, const char *fmt, . return; } + // If a player is muted for voice, also mute them for text because jerks gonna jerk. + if ( cl_mute_all_comms.GetBool() && iPlayerIndex != 0 ) + { + if ( GetClientVoiceMgr() && GetClientVoiceMgr()->IsPlayerBlocked( iPlayerIndex ) ) + return; + } + if ( *pmsg < 32 ) { hudlcd->AddChatLine( pmsg + 1 ); diff --git a/mp/src/game/client/hud_basedeathnotice.cpp b/mp/src/game/client/hud_basedeathnotice.cpp index c7499ac6..36a9cc3c 100644 --- a/mp/src/game/client/hud_basedeathnotice.cpp +++ b/mp/src/game/client/hud_basedeathnotice.cpp @@ -115,7 +115,9 @@ void CHudBaseDeathNotice::Paint() DeathNoticeItem &msg = m_DeathNotices[i]; CHudTexture *icon = msg.iconDeath; - CHudTexture *iconPrekiller = msg.iconPreKiller; + CHudTexture *iconPostKillerName = msg.iconPostKillerName; + CHudTexture *iconPreKillerName = msg.iconPreKillerName; + CHudTexture *iconPostVictimName = msg.iconPostVictimName; wchar_t victim[256]=L""; wchar_t killer[256]=L""; @@ -135,7 +137,11 @@ void CHudBaseDeathNotice::Paint() int iconWide = 0, iconTall = 0, iDeathInfoOffset = 0, iVictimTextOffset = 0, iconActualWide = 0; int iPreKillerTextWide = msg.wzPreKillerText[0] ? UTIL_ComputeStringWidth( m_hTextFont, msg.wzPreKillerText ) - xSpacing : 0; - int iconPrekillerWide = 0, iconPrekillerActualWide = 0, iconPreKillerTall = 0; + + int iconPrekillerWide = 0, iconPrekillerActualWide = 0, iconPrekillerTall = 0; + int iconPostkillerWide = 0, iconPostkillerActualWide = 0, iconPostkillerTall = 0; + + int iconPostVictimWide = 0, iconPostVictimActualWide = 0, iconPostVictimTall = 0; // Get the local position for this notice if ( icon ) @@ -153,23 +159,53 @@ void CHudBaseDeathNotice::Paint() iconWide *= flScale; } - if ( iconPrekiller ) + if ( iconPreKillerName ) { - iconPrekillerActualWide = iconPrekiller->EffectiveWidth( 1.0f ); + iconPrekillerActualWide = iconPreKillerName->EffectiveWidth( 1.0f ); iconPrekillerWide = iconPrekillerActualWide; - iconPreKillerTall = iconPrekiller->EffectiveHeight( 1.0f ); + iconPrekillerTall = iconPreKillerName->EffectiveHeight( 1.0f ); - int iconTallDesired = iLineTall-YRES(2); + int iconTallDesired = iLineTall - YRES( 2 ); Assert( 0 != iconTallDesired ); - float flScale = (float) iconTallDesired / (float) iconPreKillerTall; + float flScale = (float)iconTallDesired / (float)iconPrekillerTall; iconPrekillerActualWide *= flScale; - iconPreKillerTall *= flScale; + iconPrekillerTall *= flScale; iconPrekillerWide *= flScale; } + if ( iconPostKillerName ) + { + iconPostkillerActualWide = iconPostKillerName->EffectiveWidth( 1.0f ); + iconPostkillerWide = iconPostkillerActualWide; + iconPostkillerTall = iconPostKillerName->EffectiveHeight( 1.0f ); + + int iconTallDesired = iLineTall-YRES(2); + Assert( 0 != iconTallDesired ); + float flScale = (float) iconTallDesired / (float) iconPostkillerTall; + + iconPostkillerActualWide *= flScale; + iconPostkillerTall *= flScale; + iconPostkillerWide *= flScale; + } + + if ( iconPostVictimName ) + { + iconPostVictimActualWide = iconPostVictimName->EffectiveWidth( 1.0f ); + iconPostVictimWide = iconPostVictimActualWide; + iconPostVictimTall = iconPostVictimName->EffectiveHeight( 1.0f ); + + int iconTallDesired = iLineTall - YRES( 2 ); + Assert( 0 != iconTallDesired ); + float flScale = (float)iconTallDesired / (float)iconPostVictimTall; + + iconPostVictimActualWide *= flScale; + iconPostVictimTall *= flScale; + iconPostVictimWide *= flScale; + } + int iTotalWide = iKillerTextWide + iconWide + iVictimTextWide + iDeathInfoTextWide + iDeathInfoEndTextWide + ( xMargin * 2 ); - iTotalWide += iconPrekillerWide + iPreKillerTextWide; + iTotalWide += iconPrekillerWide + iconPostkillerWide + iPreKillerTextWide + iconPostVictimWide; int y = yStart + ( ( iLineTall + m_flLineSpacing ) * i ); int yText = y + ( ( iLineTall - iTextTall ) / 2 ); @@ -190,6 +226,14 @@ void CHudBaseDeathNotice::Paint() x += xMargin; + // prekiller icon + if ( iconPreKillerName ) + { + int yPreIconTall = y + ( ( iLineTall - iconPrekillerTall ) / 2 ); + iconPreKillerName->DrawSelf( x, yPreIconTall, iconPrekillerActualWide, iconPrekillerTall, m_clrIcon); + x += iconPrekillerWide + xSpacing; + } + if ( killer[0] ) { // Draw killer's name @@ -205,12 +249,12 @@ void CHudBaseDeathNotice::Paint() x += iPreKillerTextWide; } - // Prekiller icon - if ( iconPrekiller ) + // postkiller icon + if ( iconPostKillerName ) { - int yPreIconTall = y + ( ( iLineTall - iconPreKillerTall ) / 2 ); - iconPrekiller->DrawSelf( x, yPreIconTall, iconPrekillerActualWide, iconPreKillerTall, m_clrIcon ); - x += iconPrekillerWide + xSpacing; + int yPreIconTall = y + ( ( iLineTall - iconPostkillerTall ) / 2 ); + iconPostKillerName->DrawSelf( x, yPreIconTall, iconPostkillerActualWide, iconPostkillerTall, m_clrIcon ); + x += iconPostkillerWide + xSpacing; } // Draw glow behind weapon icon to show it was a crit death @@ -243,6 +287,14 @@ void CHudBaseDeathNotice::Paint() DrawText( x + iVictimTextOffset, yText, m_hTextFont, GetTeamColor( msg.Victim.iTeam, msg.bLocalPlayerInvolved ), victim ); x += iVictimTextWide; + // postkiller icon + if ( iconPostVictimName ) + { + int yPreIconTall = y + ( ( iLineTall - iconPostVictimTall ) / 2 ); + iconPostVictimName->DrawSelf( x, yPreIconTall, iconPostVictimActualWide, iconPostVictimTall, m_clrIcon ); + x += iconPostkillerWide + xSpacing; + } + // Draw Additional Text on the end of the victims name if ( msg.wzInfoTextEnd[0] ) { @@ -569,16 +621,27 @@ void CHudBaseDeathNotice::FireGameEvent( IGameEvent *event ) } } + bool bIsHalloween2014 = TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ); + switch ( iEventType ) { case TF_FLAGEVENT_PICKUP: - pszMsgKey = "#Msg_PickedUpFlag"; + pszMsgKey = bIsHalloween2014 ? "#Msg_PickedUpFlagHalloween2014" : "#Msg_PickedUpFlag"; break; case TF_FLAGEVENT_CAPTURE: - pszMsgKey = "#Msg_CapturedFlag"; + pszMsgKey = bIsHalloween2014 ? "#Msg_CapturedFlagHalloween2014" : "#Msg_CapturedFlag"; break; case TF_FLAGEVENT_DEFEND: - pszMsgKey = bIsMvM ? "#Msg_DefendedBomb" : "#Msg_DefendedFlag"; + if ( bIsMvM ) + { + pszMsgKey = "#Msg_DefendedBomb"; + } + else + { + pszMsgKey = bIsHalloween2014 ? "#Msg_DefendedFlagHalloween2014" : "#Msg_DefendedFlag"; + } + + break; // Add this when we can get localization for it diff --git a/mp/src/game/client/hud_basedeathnotice.h b/mp/src/game/client/hud_basedeathnotice.h index 2a9da0c5..b4f34eb8 100644 --- a/mp/src/game/client/hud_basedeathnotice.h +++ b/mp/src/game/client/hud_basedeathnotice.h @@ -42,8 +42,10 @@ struct DeathNoticeItem iKillerID = -1; iVictimID = -1; - iconPreKiller = NULL; + iconPreKillerName = NULL; + iconPostKillerName = NULL; wzPreKillerText[0] = 0; + iconPostVictimName = NULL; } float GetExpiryTime(); @@ -56,9 +58,13 @@ struct DeathNoticeItem CHudTexture *iconDeath; CHudTexture *iconCritDeath; // crit background icon - CHudTexture *iconPreKiller; + CHudTexture *iconPreKillerName; + + CHudTexture *iconPostKillerName; wchar_t wzPreKillerText[32]; + CHudTexture *iconPostVictimName; + bool bSelfInflicted; bool bLocalPlayerInvolved; bool bCrit; diff --git a/mp/src/game/client/hud_controlpointicons.cpp b/mp/src/game/client/hud_controlpointicons.cpp index cc446c83..2c0628e3 100644 --- a/mp/src/game/client/hud_controlpointicons.cpp +++ b/mp/src/game/client/hud_controlpointicons.cpp @@ -1402,7 +1402,7 @@ void CControlPointProgressBar::PerformLayout( void ) { BaseClass::PerformLayout(); - if ( m_pAttachedToIcon && m_pTeardrop && m_pTeardropSide ) + if ( m_pAttachedToIcon && m_pTeardrop && m_pTeardropSide && m_pAttachedToIcon->GetVPanel() ) { int iIconX, iIconY; ipanel()->GetAbsPos(m_pAttachedToIcon->GetVPanel(), iIconX, iIconY ); diff --git a/mp/src/game/client/hud_vote.cpp b/mp/src/game/client/hud_vote.cpp index 64d3e76e..319255dd 100644 --- a/mp/src/game/client/hud_vote.cpp +++ b/mp/src/game/client/hud_vote.cpp @@ -59,7 +59,7 @@ public: { g_pVGuiLocalize->ConvertANSIToUnicode( pPlayerName, m_wszPlayerName, sizeof(m_wszPlayerName) ); SetLifetime( 7 ); - SetText( "#Vote_notification_text" ); + SetText( "#GameUI_Vote_Notification_Text" ); AddStringToken( "initiator", m_wszPlayerName ); } virtual bool CanBeTriggered() @@ -68,7 +68,10 @@ public: } virtual void Trigger() { - CTFGenericConfirmDialog *pDialog = ShowConfirmDialog( "#Vote_notification_title", "#Vote_notification_text", "#Vote_notification_view", "#cancel", &ConfirmShowVoteSetup ); + CTFGenericConfirmDialog *pDialog = ShowConfirmDialog( "#GameUI_Vote_Notification_Title", + "#GameUI_Vote_Notification_Text", + "#GameUI_Vote_Notification_View", + "#cancel", &ConfirmShowVoteSetup ); pDialog->SetContext( this ); pDialog->AddStringToken( "initiator", m_wszPlayerName ); // so we aren't deleted @@ -95,7 +98,7 @@ public: CHudVote *pHudVote = GET_HUDELEMENT( CHudVote ); if ( pHudVote ) { - pHudVote->ShowVoteUI(); + pHudVote->ShowVoteUI( true ); } } pNotification->SetIsInUse( false ); @@ -290,6 +293,76 @@ void CVoteSetupDialog::ApplySettings(KeyValues *inResourceData) m_HeaderFGColor = pScheme->GetColor( pszColor, Color( 255, 255, 255, 255 ) ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVoteSetupDialog::InitializeIssueList( void ) +{ + m_pComboBox->RemoveAll(); + m_pComboBox->SetVisible( false ); + SetDialogVariable( "combo_label", "" ); + + for ( int index = 0; index < m_VoteIssues.Count(); index++ ) + { + if ( !m_VoteIssues[index].szName || !m_VoteIssues[index].szName[0] ) + continue; + + bool bActive = m_VoteIssues[index].bIsActive; + + char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 }; + g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( m_VoteIssues[index].szNameString ), szIssueLocalized, sizeof( szIssueLocalized ) ); + + if ( !bActive ) + { + char szDisabled[k_MAX_VOTE_NAME_LENGTH] = { 0 }; + g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_Disabled" ), szDisabled, sizeof( szDisabled ) ); + V_strcat_safe( szIssueLocalized, szDisabled ); + } + + KeyValues *pKeyValues = new KeyValues( "Issue" ); + pKeyValues->SetString( "Issue", szIssueLocalized ); + pKeyValues->SetString( "IssueRaw", m_VoteIssues[index].szName ); + pKeyValues->SetBool( "Active", m_VoteIssues[index].bIsActive ); + int iId = m_pVoteSetupList->AddItem( 0, pKeyValues ); + pKeyValues->deleteThis(); + + // Setup the list entry style + if ( m_hIssueFont != INVALID_FONT ) + { + m_pVoteSetupList->SetItemFont( iId, m_hIssueFont ); + Color colFG = bActive ? m_IssueFGColor : m_IssueFGColorDisabled; + m_pVoteSetupList->SetItemFgColor( iId, colFG ); + } + } + + // Select the first item by default + if ( m_pVoteSetupList->GetItemCount() > 0 ) + { + m_pVoteSetupList->SetSelectedItem( 0 ); + } + else + { + // No active issues + char szIssueLocalized[k_MAX_VOTE_NAME_LENGTH] = { 0 }; + g_pVGuiLocalize->ConvertUnicodeToANSI( g_pVGuiLocalize->Find( "#GameUI_Vote_System_Disabled" ), szIssueLocalized, sizeof( szIssueLocalized ) ); + + KeyValues *pKeyValues = new KeyValues( "Issue" ); + pKeyValues->SetString( "Issue", szIssueLocalized ); + pKeyValues->SetString( "IssueRaw", "Disabled" ); + pKeyValues->SetBool( "Active", false ); + int iId = m_pVoteSetupList->AddItem( 0, pKeyValues ); + pKeyValues->deleteThis(); + + if ( m_hIssueFont != INVALID_FONT ) + { + m_pVoteSetupList->SetItemFont( iId, m_hIssueFont ); + m_pVoteSetupList->SetItemFgColor( iId, m_IssueFGColor ); + } + } + + UpdateCurrentMap(); +} + //----------------------------------------------------------------------------- // Purpose: Keep track of the current map //----------------------------------------------------------------------------- @@ -302,7 +375,7 @@ void CVoteSetupDialog::UpdateCurrentMap( void ) //----------------------------------------------------------------------------- // Purpose: Feeds Issues from the server to this Dialog //----------------------------------------------------------------------------- -void CVoteSetupDialog::AddVoteIssues( CUtlStringList &m_VoteSetupIssues ) +void CVoteSetupDialog::AddVoteIssues( CUtlVector< VoteIssue_t > &m_VoteSetupIssues ) { m_VoteIssues.RemoveAll(); for ( int index = 0; index < m_VoteSetupIssues.Count(); index++ ) @@ -385,36 +458,7 @@ void CVoteSetupDialog::Activate() m_pVoteParameterList->SetSectionFgColor( 1, m_HeaderFGColor ); } - // Populate the Issue list - for ( int index = 0; index < m_VoteIssues.Count(); index++ ) - { - const char *pszIssue = m_VoteIssues[index]; - if ( !pszIssue || !pszIssue[0] ) - continue; - - KeyValues *pKeyValues = new KeyValues( "Issue" ); - pKeyValues->SetString( "Issue", pszIssue ); - int iId = m_pVoteSetupList->AddItem( 0, pKeyValues ); - pKeyValues->deleteThis(); - - // Setup the list entry style - if ( m_hIssueFont != INVALID_FONT ) - { - m_pVoteSetupList->SetItemFont( iId, m_hIssueFont ); - - bool bDisabled = V_stristr( pszIssue, "(Disabled on Server)" ); // driller: need to localize - Color colFG = bDisabled ? m_IssueFGColorDisabled : m_IssueFGColor; - m_pVoteSetupList->SetItemFgColor( iId, colFG ); - } - } - - // Select the first item by default - if ( m_pVoteSetupList->GetItemCount() > 0 ) - { - m_pVoteSetupList->SetSelectedItem( 0 ); - } - - UpdateCurrentMap(); + InitializeIssueList(); } //----------------------------------------------------------------------------- @@ -432,15 +476,15 @@ void CVoteSetupDialog::OnClose() void CVoteSetupDialog::OnCommand(const char *command) { // We should have enough data to issue a CallVote command - if ( V_stricmp( command, "CallVote" ) == 0 ) + if ( !V_stricmp( command, "CallVote" ) ) { int iSelectedItem = m_pVoteSetupList->GetSelectedItem(); if ( iSelectedItem >= 0 ) { - char szVoteCommand[128]; + char szVoteCommand[k_MAX_VOTE_NAME_LENGTH]; KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem ); - const char *szIssue = pIssueKeyValues->GetString( "Issue" ); - if ( V_stricmp( "changelevel", szIssue ) == 0 || V_stricmp( "nextlevel", szIssue ) == 0 ) + const char *szIssueRaw = pIssueKeyValues->GetString( "IssueRaw" ); + if ( !V_stricmp( "ChangeLevel", szIssueRaw ) || !V_stricmp( "NextLevel", szIssueRaw ) ) { int nSelectedParam = m_pVoteParameterList->GetSelectedItem(); if ( nSelectedParam >= 0 ) @@ -454,13 +498,13 @@ void CVoteSetupDialog::OnCommand(const char *command) { // Which Map? const char *szMapName = pParameterKeyValues->GetString( "Name" ); - Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssue, szMapName ); + Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szMapName ); engine->ClientCmd( szVoteCommand ); } } } } - else if ( V_stricmp( "kick", szIssue ) == 0 ) + else if ( !V_stricmp( "Kick", szIssueRaw ) ) { // Get selected Player int iSelectedParam = m_pVoteParameterList->GetSelectedItem(); @@ -476,7 +520,7 @@ void CVoteSetupDialog::OnCommand(const char *command) if ( engine->GetPlayerInfo( playerIndex, &playerInfo ) ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( playerIndex ); - Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s \"%d %s\"\n;", szIssue, pPlayer->GetUserID(), pReasonString ); + Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s \"%d %s\"\n;", szIssueRaw, pPlayer->GetUserID(), pReasonString ); engine->ClientCmd( szVoteCommand ); #ifdef TF_CLIENT_DLL CSteamID steamID; @@ -495,7 +539,7 @@ void CVoteSetupDialog::OnCommand(const char *command) } } #ifdef TF_CLIENT_DLL - else if ( V_stricmp( "ChangeMission", szIssue ) == 0 ) + else if ( !V_stricmp( "ChangeMission", szIssueRaw ) ) { int nSelectedParam = m_pVoteParameterList->GetSelectedItem(); if ( nSelectedParam >= 0 ) @@ -509,7 +553,7 @@ void CVoteSetupDialog::OnCommand(const char *command) { // Which Pop File? const char *szPopFile = pParameterKeyValues->GetString( "Name" ); - Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssue, szPopFile ); + Q_snprintf( szVoteCommand, sizeof( szVoteCommand ), "callvote %s %s\n;", szIssueRaw, szPopFile ); engine->ClientCmd( szVoteCommand ); } } @@ -519,7 +563,7 @@ void CVoteSetupDialog::OnCommand(const char *command) else { // Non-parameter vote. i.e. callvote scrambleteams - Q_snprintf( szVoteCommand, sizeof(szVoteCommand), "callvote %s\n;", szIssue ); + Q_snprintf( szVoteCommand, sizeof(szVoteCommand), "callvote %s\n;", szIssueRaw ); engine->ClientCmd( szVoteCommand ); } @@ -551,22 +595,23 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel ) if ( !pIssueKeyValues ) return; + CHudVote *pHudVote = GET_HUDELEMENT( CHudVote ); + if ( !pHudVote ) + return; + // We're rebuilding, so clear state m_bVoteButtonEnabled = false; m_pVoteParameterList->ClearSelection(); m_pVoteParameterList->RemoveAll(); - const char *szName = pIssueKeyValues->GetString( "Issue" ); - if ( V_stricmp( "Voting disabled on this Server", szName ) == 0 ) - { - m_bVoteButtonEnabled = false; - } - else if ( V_stristr( szName, "(Disabled on Server)" ) ) // driller: need to localize + const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" ); + bool bActive = pIssueKeyValues->GetBool( "Active" ); + if ( !pHudVote->IsVoteSystemActive() || !bActive ) { m_bVoteButtonEnabled = false; } // CHANGELEVEL / NEXTLEVEL - else if ( V_stricmp( "changelevel", szName ) == 0 || V_stricmp( "nextlevel", szName ) == 0 ) + else if ( !V_stricmp( "ChangeLevel", pszIssueRaw ) || !V_stricmp( "NextLevel", pszIssueRaw ) ) { // Feed the mapcycle to the parameters list for ( int index = 0; index < m_VoteIssuesMapCycle.Count(); index++ ) @@ -598,7 +643,7 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel ) } } // KICK - else if ( V_stricmp( "kick", szName ) == 0 ) + else if ( !V_stricmp( "Kick", pszIssueRaw ) ) { // Feed the player list to the parameters list int nMaxClients = engine->GetMaxClients(); @@ -656,7 +701,7 @@ void CVoteSetupDialog::OnItemSelected( vgui::Panel *panel ) } #ifdef TF_CLIENT_DLL // CHANGE POP FILE - else if ( V_stricmp( "ChangeMission", szName ) == 0 ) + else if ( !V_stricmp( "ChangeMission", pszIssueRaw ) ) { // Feed the popfiles to the parameters list for ( int index = 0; index < m_VoteIssuesPopFiles.Count(); index++ ) @@ -742,8 +787,8 @@ void CVoteSetupDialog::RefreshIssueParameters() if ( iSelectedItem >= 0 ) { KeyValues *pIssueKeyValues = m_pVoteSetupList->GetItemData( iSelectedItem ); - const char *szName = pIssueKeyValues->GetString( "Issue" ); - if ( V_stricmp( "kick", szName ) == 0 ) + const char *pszIssueRaw = pIssueKeyValues->GetString( "IssueRaw" ); + if ( !V_stricmp( "Kick", pszIssueRaw ) ) { if ( m_pVoteParameterList->GetItemCount() > 0 ) { @@ -786,10 +831,10 @@ void CVoteSetupDialog::RefreshIssueParameters() m_pVoteParameterList->InvalidateItem( index ); } - - m_pVoteParameterList->SetImageList( m_pImageList, false ); } } + + m_pVoteParameterList->SetImageList( m_pImageList, false ); } } @@ -799,9 +844,9 @@ void CVoteSetupDialog::RefreshIssueParameters() void CVoteSetupDialog::ResetData() { m_bVoteButtonEnabled = false; - m_pVoteSetupList->DeleteAllItems(); - m_pVoteParameterList->DeleteAllItems(); - m_pComboBox->DeleteAllItems(); + m_pVoteSetupList->RemoveAll(); + m_pVoteParameterList->RemoveAll(); + m_pComboBox->RemoveAll(); } //----------------------------------------------------------------------------- @@ -863,7 +908,7 @@ void CHudVote::Init( void ) ListenForGameEvent( "vote_options" ); ListenForGameEvent( "vote_cast" ); - SetVoteActive( false ); + m_bVotingActive = false; m_flVoteResultCycleTime = -1; m_flHideTime = -1; m_bIsYesNoVote = true; @@ -871,6 +916,8 @@ void CHudVote::Init( void ) m_nVoteChoicesCount = 2; // Yes/No is the default m_bShowVoteActivePanel = false; m_iVoteCallerIdx = -1; + m_bVoteSystemActive = false; + m_nVoteTeamIndex = 0; HOOK_HUD_MESSAGE( CHudVote, CallVoteFailed ); HOOK_HUD_MESSAGE( CHudVote, VoteStart ); @@ -884,7 +931,7 @@ void CHudVote::Init( void ) //----------------------------------------------------------------------------- void CHudVote::LevelInit( void ) { - SetVoteActive( false ); + m_bVotingActive = false; m_flVoteResultCycleTime = -1; m_flHideTime = -1; m_flPostVotedHideTime = -1; @@ -901,7 +948,7 @@ int CHudVote::KeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBin if ( !down ) return 1; - if ( !m_bVoteActive ) + if ( !m_bVotingActive ) return 1; if ( m_bPlayerVoted ) @@ -979,21 +1026,19 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) m_pCallVoteFailed->SetVisible( true ); m_pVoteSetupDialog->SetVisible( false ); - m_flHideTime = gpGlobals->curtime + 4.0; + m_flHideTime = gpGlobals->curtime + 4.f; - char szTime[256]; - wchar_t wszTime[256]; + char szTime[k_MAX_VOTE_NAME_LENGTH]; + wchar_t wszTime[k_MAX_VOTE_NAME_LENGTH]; bool bMinutes = ( nTime > 65 ); if ( bMinutes ) { nTime /= 60; } - const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently"; Q_snprintf( szTime, sizeof ( szTime), "%i", nTime ); g_pVGuiLocalize->ConvertANSIToUnicode( szTime, wszTime, sizeof( wszTime ) ); - wchar_t wszHeaderString[512]; - wchar_t *pwszHeaderString; + wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH]; switch( nReason ) { @@ -1006,10 +1051,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) break; case VOTE_FAILED_RATE_EXCEEDED: - g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_failed_vote_spam" ), 1, wszTime ); - pwszHeaderString = wszHeaderString; - m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString ); + { + const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_vote_spam_min" : "#GameUI_vote_failed_vote_spam_mins" ) : "#GameUI_vote_failed_vote_spam"; + g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime ); + m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString ); break; + } case VOTE_FAILED_ISSUE_DISABLED: m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_disabled_issue" ); @@ -1028,10 +1075,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) break; case VOTE_FAILED_ON_COOLDOWN: + { + const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_recently_min" : "#GameUI_vote_failed_recently_mins" ) : "#GameUI_vote_failed_recently"; g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime ); - pwszHeaderString = wszHeaderString; - m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString ); + m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString ); break; + } case VOTE_FAILED_TEAM_CANT_CALL: m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_team_cant_call" ); @@ -1058,10 +1107,12 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) break; case VOTE_FAILED_CANNOT_KICK_FOR_TIME: - g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_failed_cannot_kick_for_time" ), 1, wszTime ); - pwszHeaderString = wszHeaderString; - m_pCallVoteFailed->SetDialogVariable( "FailedReason", pwszHeaderString ); + { + const char *pszTimeString = ( bMinutes ) ? ( ( nTime < 2 ) ? "#GameUI_vote_failed_cannot_kick_min" : "#GameUI_vote_failed_cannot_kick_mins" ) : "#GameUI_vote_failed_cannot_kick"; + g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( pszTimeString ), 1, wszTime ); + m_pCallVoteFailed->SetDialogVariable( "FailedReason", wszHeaderString ); break; + } case VOTE_FAILED_CANNOT_KICK_DURING_ROUND: m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_round_active" ); @@ -1070,6 +1121,14 @@ void CHudVote::MsgFunc_CallVoteFailed( bf_read &msg ) case VOTE_FAILED_MODIFICATION_ALREADY_ACTIVE: m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_event_already_active" ); break; + + case VOTE_FAILED_VOTE_IN_PROGRESS: + m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_vote_in_progress" ); + break; + + case VOTE_FAILED_KICK_LIMIT_REACHED: + m_pCallVoteFailed->SetControlString( "FailedReason", "#GameUI_vote_failed_kick_limit" ); + break; } } @@ -1081,14 +1140,14 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg ) if ( IsPlayingDemo() ) return; - int iTeam = msg.ReadByte(); + m_nVoteTeamIndex = msg.ReadByte(); vote_create_failed_t nReason = (vote_create_failed_t)msg.ReadByte(); // Visibility of this error is handled by OnThink() - SetVoteActive( false ); + m_bVotingActive = false; m_bVotePassed = false; - m_flVoteResultCycleTime = gpGlobals->curtime + 2; - m_flHideTime = gpGlobals->curtime + 5; + m_flVoteResultCycleTime = gpGlobals->curtime + 2.f; + m_flHideTime = gpGlobals->curtime + 5.f; switch ( nReason ) { @@ -1105,11 +1164,10 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg ) break; } - // driller: this event has no listeners - will eventually hook into stats IGameEvent *event = gameeventmanager->CreateEvent( "vote_failed" ); if ( event ) { - event->SetInt( "team", iTeam ); + event->SetInt( "team", m_nVoteTeamIndex ); gameeventmanager->FireEventClientSide( event ); } @@ -1117,7 +1175,11 @@ void CHudVote::MsgFunc_VoteFailed( bf_read &msg ) if ( !pLocalPlayer ) return; - pLocalPlayer->EmitSound("Vote.Failed"); + bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex ); + if ( bShowToPlayer ) + { + pLocalPlayer->EmitSound("Vote.Failed"); + } } //----------------------------------------------------------------------------- @@ -1133,9 +1195,8 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) return; // Is this a team-only vote? - int iTeam = msg.ReadByte(); - uint8 invalidTeam = (uint8)TEAM_INVALID; - if ( iTeam != invalidTeam && iTeam != pLocalPlayer->GetTeamNumber() ) + m_nVoteTeamIndex = msg.ReadByte(); + if ( m_nVoteTeamIndex >= FIRST_GAME_TEAM && m_nVoteTeamIndex != pLocalPlayer->GetTeamNumber() ) return; // Entity calling the vote @@ -1163,18 +1224,18 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) } // DisplayString - char szIssue[256]; + char szIssue[k_MAX_VOTE_NAME_LENGTH]; szIssue[0] = 0; msg.ReadString( szIssue, sizeof(szIssue) ); // DetailString - char szParam1[256]; + char szParam1[k_MAX_VOTE_NAME_LENGTH]; szParam1[0] = 0; msg.ReadString( szParam1, sizeof(szParam1) ); m_bIsYesNoVote = msg.ReadByte(); - SetVoteActive( true ); + m_bVotingActive = true; m_pVoteFailed->SetVisible( false ); m_pVotePassed->SetVisible( false ); m_pCallVoteFailed->SetVisible( false ); @@ -1204,25 +1265,23 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) // Display vote caller's name wchar_t wszCallerName[MAX_PLAYER_NAME_LENGTH]; - wchar_t wszHeaderString[512]; - wchar_t *pwszHeaderString; + wchar_t wszHeaderString[k_MAX_VOTE_NAME_LENGTH]; // Player g_pVGuiLocalize->ConvertANSIToUnicode( pszCallerName, wszCallerName, sizeof( wszCallerName ) ); // String - g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof(wszHeaderString), g_pVGuiLocalize->Find( "#GameUI_vote_header" ), 1, wszCallerName ); - pwszHeaderString = wszHeaderString; + g_pVGuiLocalize->ConstructString( wszHeaderString, sizeof( wszHeaderString ), g_pVGuiLocalize->Find( "#GameUI_vote_header" ), 1, wszCallerName ); // Final - m_pVoteActive->SetDialogVariable( "header", pwszHeaderString ); + m_pVoteActive->SetDialogVariable( "header", wszHeaderString ); // Display the Issue wchar_t *pwcParam; - wchar_t wcParam[128]; + wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH]; wchar_t *pwcIssue; - wchar_t wcIssue[512]; + wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH]; if ( Q_strlen( szParam1 ) > 0 ) { @@ -1252,7 +1311,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) if ( m_bIsYesNoVote ) { // YES / NO UI - wchar_t wzFinal[512] = L""; + wchar_t wzFinal[k_MAX_VOTE_NAME_LENGTH] = L""; wchar_t *pszText = g_pVGuiLocalize->Find( "#GameUI_vote_yes_pc_instruction" ); if ( pszText ) { @@ -1294,7 +1353,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) // Construct Option name const char *pszChoiceName = m_VoteSetupChoices[iIndex]; - char szOptionName[256]; + char szOptionName[k_MAX_VOTE_NAME_LENGTH]; Q_snprintf( szOptionName, sizeof( szOptionName ), "F%i. ", iIndex + 1 ); Q_strncat( szOptionName, pszChoiceName, sizeof( szOptionName ), COPY_ALL_CHARACTERS ); @@ -1320,7 +1379,7 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) { event->SetString( "issue", szIssue ); event->SetString( "param1", szParam1 ); - event->SetInt( "team", iTeam ); + event->SetInt( "team", m_nVoteTeamIndex ); event->SetInt( "initiator", m_iVoteCallerIdx ); gameeventmanager->FireEventClientSide( event ); } @@ -1332,10 +1391,10 @@ void CHudVote::MsgFunc_VoteStart( bf_read &msg ) } else { - ShowVoteUI(); + m_bShowVoteActivePanel = true; } #else - ShowVoteUI(); + m_bShowVoteActivePanel = true; #endif // TF_CLIENT_DLL } @@ -1347,24 +1406,24 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg ) if ( IsPlayingDemo() ) return; - int iTeam = msg.ReadByte(); + m_nVoteTeamIndex = msg.ReadByte(); // Passed string - char szResult[256]; + char szResult[k_MAX_VOTE_NAME_LENGTH]; szResult[0] = 0; msg.ReadString( szResult, sizeof(szResult) ); // Detail string - char szParam1[256]; + char szParam1[k_MAX_VOTE_NAME_LENGTH]; szParam1[0] = 0; msg.ReadString( szParam1, sizeof(szParam1) ); // Localize wchar_t *pwcParam; - wchar_t wcParam[128]; + wchar_t wcParam[k_MAX_VOTE_NAME_LENGTH]; wchar_t *pwcIssue; - wchar_t wcIssue[512]; + wchar_t wcIssue[k_MAX_VOTE_NAME_LENGTH]; if ( Q_strlen( szParam1 ) > 0 ) { @@ -1390,10 +1449,10 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg ) m_pVotePassed->SetDialogVariable( "passedresult", pwcIssue ); - SetVoteActive( false ); + m_bVotingActive = false; m_bVotePassed = true; - m_flVoteResultCycleTime = gpGlobals->curtime + 2; - m_flHideTime = gpGlobals->curtime + 5; + m_flVoteResultCycleTime = gpGlobals->curtime + 2.f; + m_flHideTime = gpGlobals->curtime + 5.f; // driller: this event has no listeners - will eventually hook into stats IGameEvent *event = gameeventmanager->CreateEvent( "vote_passed" ); @@ -1401,7 +1460,7 @@ void CHudVote::MsgFunc_VotePass( bf_read &msg ) { event->SetString( "details", szResult ); event->SetString( "param1", szParam1 ); - event->SetInt( "team", iTeam ); + event->SetInt( "team", m_nVoteTeamIndex ); gameeventmanager->FireEventClientSide( event ); } @@ -1434,21 +1493,45 @@ void CHudVote::MsgFunc_VoteSetup( bf_read &msg ) int nIssueCount = msg.ReadByte(); if ( nIssueCount ) { - for ( int index = 0; index < nIssueCount; index++ ) + for ( int i = 0; i < nIssueCount; i++ ) { - char szIssue[256]; - msg.ReadString( szIssue, sizeof(szIssue) ); - if ( !m_VoteSetupIssues.HasElement( szIssue ) ) + char szIssue[k_MAX_VOTE_NAME_LENGTH]; + char szIssueString[k_MAX_VOTE_NAME_LENGTH]; + msg.ReadString( szIssue, sizeof( szIssue ) ); + msg.ReadString( szIssueString, sizeof( szIssueString ) ); + bool bIsActive = (bool)msg.ReadByte(); + + m_bVoteSystemActive |= bIsActive; + + bool bAdd = true; + FOR_EACH_VEC( m_VoteSetupIssues, j ) { + if ( !V_strcmp( szIssue, m_VoteSetupIssues[j].szName ) ) + { + bAdd = false; + break; + } + } + + if ( bAdd ) + { + // When empty, assume that we just pre-pend #Vote_ to szIssue (reduces msg size) + if ( !szIssueString[0] ) + { + V_sprintf_safe( szIssueString, "#Vote_%s", szIssue ); + } + + VoteIssue_t issue; + V_strcpy_safe( issue.szName, szIssue ); + V_strcpy_safe( issue.szNameString, szIssueString ); + issue.bIsActive = bIsActive; + // Send it over to the listpanel - m_VoteSetupIssues.CopyAndAddToTail( szIssue ); + m_VoteSetupIssues.AddToTail( issue ); } } } - else - { - m_VoteSetupIssues.CopyAndAddToTail( "Voting disabled on this Server" ); - } + m_pVoteSetupDialog->AddVoteIssues( m_VoteSetupIssues ); // Load up the list of Vote Issue Parameters @@ -1638,50 +1721,51 @@ void CHudVote::FireGameEvent( IGameEvent *event ) //----------------------------------------------------------------------------- void CHudVote::OnThink() { - // We delay hiding the menu after we cast a vote - if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && m_flPostVotedHideTime < gpGlobals->curtime ) + C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); + if ( pLocalPlayer ) { - m_pVoteActive->SetVisible( false ); - m_bShowVoteActivePanel = false; - m_flPostVotedHideTime = -1; - } + bool bShowToPlayer = ( !m_nVoteTeamIndex || pLocalPlayer->GetTeamNumber() == m_nVoteTeamIndex ); - if ( m_flVoteResultCycleTime > 0 && m_flVoteResultCycleTime < gpGlobals->curtime ) - { - m_pVoteActive->SetVisible( false ); - m_pVoteFailed->SetVisible( !m_bVotePassed ); - m_pVotePassed->SetVisible( m_bVotePassed ); - g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" ); - - m_flVoteResultCycleTime = -1; - m_bPlayerVoted = false; - m_bVoteActive = false; - m_bShowVoteActivePanel = false; - m_iVoteCallerIdx = -1; - } - - if ( m_bVoteActive ) - { - // driller: Need to rewrite this to handle all vote types (Yes/No and General) - if ( m_bIsYesNoVote && m_pVoteActive ) + // We delay hiding the menu after we cast a vote + if ( m_bPlayerVoted && m_flPostVotedHideTime > 0 && gpGlobals->curtime > m_flPostVotedHideTime ) { - char szYesCount[512] = ""; - Q_snprintf( szYesCount, 512, "%d", m_nVoteOptionCount[0] ); - - char szNoCount[512] = ""; - Q_snprintf( szNoCount, 512, "%d", m_nVoteOptionCount[1] ); - - m_pVoteActive->SetControlString( "Option1CountLabel", szYesCount ); - m_pVoteActive->SetControlString( "Option2CountLabel", szNoCount ); + m_pVoteActive->SetVisible( false ); + m_bShowVoteActivePanel = false; + m_flPostVotedHideTime = -1; } - if ( !m_pVoteActive->IsVisible() && m_bShowVoteActivePanel ) + if ( m_flVoteResultCycleTime > 0 && gpGlobals->curtime > m_flVoteResultCycleTime ) { - m_pVoteActive->SetVisible( true ); + m_pVoteActive->SetVisible( false ); + m_pVoteFailed->SetVisible( !m_bVotePassed && bShowToPlayer ); + m_pVotePassed->SetVisible( m_bVotePassed && bShowToPlayer ); + g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( m_pVoteActive, "HideVoteBackgrounds" ); - C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); - if ( pLocalPlayer ) + m_flVoteResultCycleTime = -1; + m_bPlayerVoted = false; + m_bVotingActive = false; + m_bShowVoteActivePanel = false; + m_iVoteCallerIdx = -1; + } + + if ( m_bVotingActive && m_bShowVoteActivePanel ) + { + // driller: Need to rewrite this to handle all vote types (Yes/No and General) + if ( m_bIsYesNoVote && m_pVoteActive ) { + char szYesCount[k_MAX_VOTE_NAME_LENGTH] = ""; + Q_snprintf( szYesCount, sizeof( szYesCount ), "%d", m_nVoteOptionCount[0] ); + + char szNoCount[k_MAX_VOTE_NAME_LENGTH] = ""; + Q_snprintf( szNoCount, sizeof( szNoCount ), "%d", m_nVoteOptionCount[1] ); + + m_pVoteActive->SetControlString( "Option1CountLabel", szYesCount ); + m_pVoteActive->SetControlString( "Option2CountLabel", szNoCount ); + } + + if ( !m_pVoteActive->IsVisible() && bShowToPlayer ) + { + m_pVoteActive->SetVisible( true ); pLocalPlayer->EmitSound("Vote.Created"); } } @@ -1695,7 +1779,7 @@ void CHudVote::OnThink() //----------------------------------------------------------------------------- bool CHudVote::ShouldDraw( void ) { - return ( m_bVoteActive || m_flHideTime > gpGlobals->curtime ); + return ( m_bVotingActive || gpGlobals->curtime < m_flHideTime ); } //----------------------------------------------------------------------------- @@ -1706,22 +1790,6 @@ bool CHudVote::IsPlayingDemo() const return engine->IsPlayingDemo(); } -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHudVote::SetVoteActive( bool bActive ) -{ - m_bVoteActive = bActive; -} - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void CHudVote::ShowVoteUI( void ) -{ - m_bShowVoteActivePanel = true; -} - //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/mp/src/game/client/hud_vote.h b/mp/src/game/client/hud_vote.h index 91ba1e9b..38956366 100644 --- a/mp/src/game/client/hud_vote.h +++ b/mp/src/game/client/hud_vote.h @@ -25,6 +25,8 @@ extern INetworkStringTable *g_pStringTableServerPopFiles; extern INetworkStringTable *g_pStringTableServerMapCycleMvM; #endif +static const int k_MAX_VOTE_NAME_LENGTH = 256; + namespace vgui { class SectionedListPanel; @@ -32,6 +34,13 @@ namespace vgui class ImageList; }; +struct VoteIssue_t +{ + char szName[k_MAX_VOTE_NAME_LENGTH]; + char szNameString[k_MAX_VOTE_NAME_LENGTH]; + bool bIsActive; +}; + class VoteBarPanel : public vgui::Panel, public CGameEventListener { DECLARE_CLASS_SIMPLE( VoteBarPanel, vgui::Panel ); @@ -69,8 +78,9 @@ public: virtual void PostApplySchemeSettings( vgui::IScheme *pScheme ); virtual void ApplySettings(KeyValues *inResourceData); + void InitializeIssueList( void ); void UpdateCurrentMap( void ); - void AddVoteIssues( CUtlStringList &m_VoteSetupIssues ); + void AddVoteIssues( CUtlVector< VoteIssue_t > &m_VoteSetupIssues ); void AddVoteIssueParams_MapCycle( CUtlStringList &m_VoteSetupMapCycle ); #ifdef TF_CLIENT_DLL @@ -94,7 +104,7 @@ private: vgui::Button *m_pCallVoteButton; vgui::ImageList *m_pImageList; - CUtlVector m_VoteIssues; + CUtlVector< VoteIssue_t > m_VoteIssues; CUtlVector m_VoteIssuesMapCycle; #ifdef TF_CLIENT_DLL @@ -137,12 +147,12 @@ class CHudVote : public vgui::EditablePanel, public CHudElement void MsgFunc_VoteSetup( bf_read &msg ); void PropagateOptionParameters( void ); - void ShowVoteUI( void ); + void ShowVoteUI( bool bShow ) { m_bShowVoteActivePanel = bShow; } bool IsVoteUIActive( void ); + bool IsVoteSystemActive( void ) { return m_bVoteSystemActive; } private: bool IsPlayingDemo() const; - void SetVoteActive( bool bActive ); EditablePanel *m_pVoteActive; VoteBarPanel *m_voteBar; @@ -151,7 +161,7 @@ private: EditablePanel *m_pCallVoteFailed; CVoteSetupDialog *m_pVoteSetupDialog; - CUtlStringList m_VoteSetupIssues; + CUtlVector< VoteIssue_t > m_VoteSetupIssues; CUtlStringList m_VoteSetupMapCycle; #ifdef TF_CLIENT_DLL @@ -160,7 +170,8 @@ private: CUtlStringList m_VoteSetupChoices; - bool m_bVoteActive; + bool m_bVotingActive; + bool m_bVoteSystemActive; float m_flVoteResultCycleTime; // what time will we cycle to the result float m_flHideTime; // what time will we hide bool m_bVotePassed; // what mode are we going to cycle to @@ -172,6 +183,7 @@ private: float m_flPostVotedHideTime; bool m_bShowVoteActivePanel; int m_iVoteCallerIdx; + int m_nVoteTeamIndex; // If defined, only players on this team will see/vote on the issue }; #endif // HUD_VOTE_H diff --git a/mp/src/game/client/in_camera.cpp b/mp/src/game/client/in_camera.cpp index aa010732..ec40ac18 100644 --- a/mp/src/game/client/in_camera.cpp +++ b/mp/src/game/client/in_camera.cpp @@ -60,6 +60,7 @@ void CAM_ToThirdPerson(void) { if ( cl_thirdperson.GetBool() == false ) { + g_ThirdPersonManager.SetDesiredCameraOffset( Vector( cam_idealdist.GetFloat(), cam_idealdistright.GetFloat(), cam_idealdistup.GetFloat() ) ); g_ThirdPersonManager.SetOverridingThirdPerson( true ); } diff --git a/mp/src/game/client/in_joystick.cpp b/mp/src/game/client/in_joystick.cpp index 71d03a08..a3b63620 100644 --- a/mp/src/game/client/in_joystick.cpp +++ b/mp/src/game/client/in_joystick.cpp @@ -800,7 +800,7 @@ void CInput::JoyStickMove( float frametime, CUserCmd *cmd ) if ( m_flPreviousJoystickForward || m_flPreviousJoystickSide || m_flPreviousJoystickPitch || m_flPreviousJoystickYaw ) { - Vector vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles(); + const Vector& vTempOffset = g_ThirdPersonManager.GetCameraOffsetAngles(); // update the ideal pitch and yaw cam_idealpitch.SetValue( vTempOffset[ PITCH ] - viewangles[ PITCH ] ); diff --git a/mp/src/game/client/in_mouse.cpp b/mp/src/game/client/in_mouse.cpp index bcf715a1..332b0ea1 100644 --- a/mp/src/game/client/in_mouse.cpp +++ b/mp/src/game/client/in_mouse.cpp @@ -522,7 +522,7 @@ void CInput::ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float } else { - viewangles[PITCH] += m_pitch->GetFloat() * mouse_y; + viewangles[PITCH] += CAM_CapPitch( m_pitch->GetFloat() * mouse_y ); } // Check pitch bounds diff --git a/mp/src/game/client/input.h b/mp/src/game/client/input.h index e34b82db..2fa2cec3 100644 --- a/mp/src/game/client/input.h +++ b/mp/src/game/client/input.h @@ -99,7 +99,8 @@ public: virtual bool CAM_IsOrthographic() const; virtual void CAM_OrthographicSize( float& w, float& h ) const; - virtual float CAM_CapYaw( float fVal ) { return fVal; } + virtual float CAM_CapYaw( float fVal ) const { return fVal; } + virtual float CAM_CapPitch( float fVal ) const { return fVal; } #if defined( HL2_CLIENT_DLL ) // IK back channel info @@ -113,7 +114,7 @@ public: virtual bool EnableJoystickMode(); // Private Implementation -private: +protected: // Implementation specific initialization void Init_Camera( void ); void Init_Keyboard( void ); @@ -134,8 +135,8 @@ private: void GetAccumulatedMouseDeltasAndResetAccumulators( float *mx, float *my ); void GetMouseDelta( float inmousex, float inmousey, float *pOutMouseX, float *pOutMouseY ); void ScaleMouse( float *x, float *y ); - void ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y ); - void MouseMove ( CUserCmd *cmd ); + virtual void ApplyMouse( QAngle& viewangles, CUserCmd *cmd, float mouse_x, float mouse_y ); + virtual void MouseMove ( CUserCmd *cmd ); // Joystick movement input helpers void ControllerMove ( float frametime, CUserCmd *cmd ); diff --git a/mp/src/game/client/particlemgr.cpp b/mp/src/game/client/particlemgr.cpp index f79d17a6..0eb09a43 100644 --- a/mp/src/game/client/particlemgr.cpp +++ b/mp/src/game/client/particlemgr.cpp @@ -1540,12 +1540,15 @@ static ConVar r_threaded_particles( "r_threaded_particles", "1" ); static float s_flThreadedPSystemTimeStep; -static void ProcessPSystem( CNewParticleEffect *&pNewEffect ) +static void ProcessPSystem( ParticleSimListEntry_t& pSimListEntry ) { // Enable FP exceptions here when FP_EXCEPTIONS_ENABLED is defined, // to help track down bad math. FPExceptionEnabler enableExceptions; + CNewParticleEffect* pNewEffect = pSimListEntry.m_pNewParticleEffect; + bool updateBboxOnly = pSimListEntry.m_bBoundingBoxOnly; + // If this is a new effect, then update its bbox so it goes in the // right leaves (if it has particles). int bFirstUpdate = pNewEffect->GetNeedsBBoxUpdate(); @@ -1564,12 +1567,12 @@ static void ProcessPSystem( CNewParticleEffect *&pNewEffect ) if ( pNewEffect->GetFirstFrameFlag() ) { - pNewEffect->Simulate( 0.0f ); + pNewEffect->Simulate( 0.0f, updateBboxOnly ); pNewEffect->SetFirstFrameFlag( false ); } else if ( pNewEffect->ShouldSimulate() ) { - pNewEffect->Simulate( s_flThreadedPSystemTimeStep ); + pNewEffect->Simulate( s_flThreadedPSystemTimeStep, updateBboxOnly ); } if ( pNewEffect->IsFinished() ) @@ -1684,7 +1687,7 @@ bool CParticleMgr::RetireParticleCollections( CParticleSystemDefinition* pDef, // Next, see if there are new particle systems that need early retirement static ConVar cl_particle_retire_cost( "cl_particle_retire_cost", "0", FCVAR_CHEAT ); -bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect **ppEffects ) +bool CParticleMgr::EarlyRetireParticleSystems( int nCount, ParticleSimListEntry_t *ppEffects ) { // NOTE: Doing a cheap and hacky estimate of worst-case fillrate const CViewSetup *pViewSetup = view->GetPlayerViewSetup(); @@ -1699,14 +1702,14 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect ** CParticleSystemDefinition **ppDefs = (CParticleSystemDefinition**)stackalloc( nCount * sizeof(CParticleSystemDefinition*) ); for ( int i = 0; i < nCount; ++i ) { - CParticleSystemDefinition *pDef = ppEffects[i]->m_pDef; + CParticleSystemDefinition *pDef = ppEffects[i].m_pNewParticleEffect->m_pDef; // Skip stuff that doesn't have a cull radius set if ( pDef->GetCullRadius() == 0.0f ) continue; // Only perform the cull check on creation - if ( !ppEffects[i]->GetFirstFrameFlag() ) + if ( !ppEffects[i].m_pNewParticleEffect->GetFirstFrameFlag() ) continue; if ( pDef->HasRetirementBeenChecked( gpGlobals->framecount ) ) @@ -1714,7 +1717,7 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect ** pDef->MarkRetirementCheck( gpGlobals->framecount ); - ppDefs[nDefCount++] = ppEffects[i]->m_pDef; + ppDefs[nDefCount++] = ppEffects[i].m_pNewParticleEffect->m_pDef; } if ( nDefCount == 0 ) @@ -1722,7 +1725,7 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect ** for ( int i = 0; i < nCount; ++i ) { - ppEffects[i]->MarkShouldPerformCullCheck( true ); + ppEffects[i].m_pNewParticleEffect->MarkShouldPerformCullCheck( true ); } Vector vecCameraForward; @@ -1749,28 +1752,45 @@ bool CParticleMgr::EarlyRetireParticleSystems( int nCount, CNewParticleEffect ** for ( int i = 0; i < nCount; ++i ) { - ppEffects[i]->MarkShouldPerformCullCheck( false ); + ppEffects[i].m_pNewParticleEffect->MarkShouldPerformCullCheck( false ); } return bRetiredCollections; } static ConVar particle_sim_alt_cores( "particle_sim_alt_cores", "2" ); -void CParticleMgr::BuildParticleSimList( CUtlVector< CNewParticleEffect* > &list ) +void CParticleMgr::BuildParticleSimList( CUtlVector< ParticleSimListEntry_t > &list ) { float flNow = g_pParticleSystemMgr->GetLastSimulationTime(); for( CNewParticleEffect *pNewEffect=m_NewEffects.m_pHead; pNewEffect; pNewEffect=pNewEffect->m_pNext ) { + bool bSkip = false; + bool bNeedsBboxUpdate = false; + if ( flNow >= pNewEffect->m_flNextSleepTime && pNewEffect->m_nActiveParticles > 0 ) - continue; + bSkip = true; if ( pNewEffect->GetRemoveFlag() ) - continue; - if ( g_bMeasureParticlePerformance ) + bSkip = true; + + if ( !bSkip && g_bMeasureParticlePerformance ) { g_nNumParticlesSimulated += pNewEffect->m_nActiveParticles; } - list.AddToTail( pNewEffect ); + + // Particles that are attached to moving things will need to update their bboxes even if they + // otherwise would like to skip the updates. Check that here. + if (bSkip) + { + bNeedsBboxUpdate = pNewEffect->HasMoved(); + bSkip = !bNeedsBboxUpdate; + } + + if (!bSkip) + { + ParticleSimListEntry_t entry = { pNewEffect, bNeedsBboxUpdate }; + list.AddToTail( entry ); + } } } @@ -1812,23 +1832,27 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta ) int nParticleStatsTriggerCount = cl_particle_stats_trigger_count.GetInt(); BeginSimulateParticles(); - CUtlVector particlesToSimulate; - BuildParticleSimList( particlesToSimulate ); s_flThreadedPSystemTimeStep = flTimeDelta; - int nCount = particlesToSimulate.Count(); - // first, run non-reentrant part to get CP updates from entities - for( int i=0; im_pNext) { // this one can call into random entity code which may not be thread-safe - particlesToSimulate[i]->Update( s_flThreadedPSystemTimeStep ); + pNewEffect->Update( s_flThreadedPSystemTimeStep ); if ( nParticleStatsTriggerCount > 0 ) { - nParticleActiveParticlesCount += CountParticleSystemActiveParticles( particlesToSimulate[i] ); + nParticleActiveParticlesCount += CountParticleSystemActiveParticles( pNewEffect ); } } + CUtlVector particlesToSimulate; + BuildParticleSimList(particlesToSimulate); + int nCount = particlesToSimulate.Count(); + + // See if there are new particle systems that need early retirement // This has to happen after the first update if ( EarlyRetireParticleSystems( nCount, particlesToSimulate.Base() ) ) @@ -1861,7 +1885,7 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta ) { nAltCore = 2; } - CParallelProcessor > processor( "CParticleMgr::UpdateNewEffects" ); + CParallelProcessor > processor( "CParticleMgr::UpdateNewEffects" ); processor.m_ItemProcessor.Init( ProcessPSystem, NULL, NULL ); processor.Run( particlesToSimulate.Base(), nCount, INT_MAX, m_pThreadPool[nAltCore-1] ); } @@ -1872,7 +1896,7 @@ void CParticleMgr::UpdateNewEffects( float flTimeDelta ) for( int i=0; iDetectChanges(); + particlesToSimulate[i].m_pNewParticleEffect->DetectChanges(); } EndSimulateParticles(); diff --git a/mp/src/game/client/particlemgr.h b/mp/src/game/client/particlemgr.h index 3214a55f..d4537f35 100644 --- a/mp/src/game/client/particlemgr.h +++ b/mp/src/game/client/particlemgr.h @@ -236,6 +236,13 @@ public: IMaterial *m_pMaterial; }; +// Particle simulation list, used to determine what particles to simulate and how. +struct ParticleSimListEntry_t +{ + CNewParticleEffect* m_pNewParticleEffect; + bool m_bBoundingBoxOnly; +}; + //----------------------------------------------------------------------------- // interface IParticleEffect: @@ -715,8 +722,9 @@ private: const CViewSetup& view, const VMatrix &worldToPixels, float flFocalDist ); bool RetireParticleCollections( CParticleSystemDefinition* pDef, int nCount, RetireInfo_t *pInfo, float flScreenArea, float flMaxTotalArea ); - void BuildParticleSimList( CUtlVector< CNewParticleEffect* > &list ); - bool EarlyRetireParticleSystems( int nCount, CNewParticleEffect **ppEffects ); + + void BuildParticleSimList( CUtlVector< ParticleSimListEntry_t > &list ); + bool EarlyRetireParticleSystems( int nCount, ParticleSimListEntry_t *ppEffects ); static int RetireSort( const void *p1, const void *p2 ); private: diff --git a/mp/src/game/client/particles_new.cpp b/mp/src/game/client/particles_new.cpp index d3dc6599..647d304f 100644 --- a/mp/src/game/client/particles_new.cpp +++ b/mp/src/game/client/particles_new.cpp @@ -65,6 +65,8 @@ void CNewParticleEffect::Construct() m_MaxBounds = Vector( -1.0e6, -1.0e6, -1.0e6 ); m_pDebugName = NULL; + m_bViewModelEffect = m_pDef ? m_pDef->IsViewModelEffect() : false; + if ( IsValid() && clienttools->IsInRecordingMode() ) { int nId = AllocateToolParticleEffectId(); diff --git a/mp/src/game/client/particles_new.h b/mp/src/game/client/particles_new.h index eb80f93a..06d98c9c 100644 --- a/mp/src/game/client/particles_new.h +++ b/mp/src/game/client/particles_new.h @@ -91,6 +91,9 @@ public: void SetControlPointUpVector( int nWhichPoint, const Vector &v ); void SetControlPointRightVector( int nWhichPoint, const Vector &v ); + void SetIsViewModelEffect ( bool bIsViewModelEffect ) { m_bViewModelEffect = bIsViewModelEffect; } + bool GetIsViewModelEffect () { return m_bViewModelEffect; } + FORCEINLINE EHANDLE const &GetControlPointEntity( int nWhichPoint ) { return m_hControlPointOwners[ nWhichPoint ]; @@ -153,6 +156,8 @@ protected: Vector m_LastMin; Vector m_LastMax; + bool m_bViewModelEffect; + private: // Update the reference count. void AddRef(); @@ -309,7 +314,7 @@ inline void CNewParticleEffect::MarkShouldPerformCullCheck( bool bEnable ) inline CSmartPtr CNewParticleEffect::Create( CBaseEntity *pOwner, const char *pParticleSystemName, const char *pDebugName ) { CNewParticleEffect *pRet = new CNewParticleEffect( pOwner, pParticleSystemName ); - pRet->m_pDebugName = pDebugName; + pRet->m_pDebugName = pDebugName ? pDebugName : pParticleSystemName; pRet->SetDynamicallyAllocated( true ); return pRet; } @@ -317,7 +322,7 @@ inline CSmartPtr CNewParticleEffect::Create( CBaseEntity *pO inline CSmartPtr CNewParticleEffect::Create( CBaseEntity *pOwner, CParticleSystemDefinition *pDef, const char *pDebugName ) { CNewParticleEffect *pRet = new CNewParticleEffect( pOwner, pDef ); - pRet->m_pDebugName = pDebugName; + pRet->m_pDebugName = pDebugName ? pDebugName : pDef->GetName(); pRet->SetDynamicallyAllocated( true ); return pRet; } diff --git a/mp/src/game/client/prediction.cpp b/mp/src/game/client/prediction.cpp index 6646f8f9..2a67007b 100644 --- a/mp/src/game/client/prediction.cpp +++ b/mp/src/game/client/prediction.cpp @@ -45,6 +45,12 @@ static ConVar cl_predictionentitydump( "cl_pdump", "-1", FCVAR_CHEAT, "Dump info static ConVar cl_predictionentitydumpbyclass( "cl_pclass", "", FCVAR_CHEAT, "Dump entity by prediction classname." ); static ConVar cl_pred_optimize( "cl_pred_optimize", "2", 0, "Optimize for not copying data if didn't receive a network update (1), and also for not repredicting if there were no errors (2)." ); +#ifdef STAGING_ONLY +// Do not ship this - testing a fix +static ConVar cl_pred_optimize_prefer_server_data( "cl_pred_optimize_prefer_server_data", "0", 0, "In the case where we have both server data and predicted data up to the same tick, choose server data over predicted data." ); +// +#endif // STAGING_ONLY + #endif extern IGameMovement *g_pGameMovement; @@ -1401,6 +1407,11 @@ int CPrediction::ComputeFirstCommandToExecute( bool received_new_world_update, i } else { +#ifdef STAGING_ONLY + int nPredictedLimit = cl_pred_optimize_prefer_server_data.GetBool() ? m_nCommandsPredicted - 1 : m_nCommandsPredicted; +#else + int nPredictedLimit = m_nCommandsPredicted; +#endif // STAGING_ONLY // Otherwise, there is a second optimization, wherein if we did receive an update, but no // values differed (or were outside their epsilon) and the server actually acknowledged running // one or more commands, then we can revert the entity to the predicted state from last frame, @@ -1409,7 +1420,7 @@ int CPrediction::ComputeFirstCommandToExecute( bool received_new_world_update, i if ( cl_pred_optimize.GetInt() >= 2 && !m_bPreviousAckHadErrors && m_nCommandsPredicted > 0 && - m_nServerCommandsAcknowledged <= m_nCommandsPredicted ) + m_nServerCommandsAcknowledged <= nPredictedLimit ) { // Copy all of the previously predicted data back into entity so we can skip repredicting it // This is the final slot that we previously predicted diff --git a/mp/src/game/client/rendertexture.cpp b/mp/src/game/client/rendertexture.cpp index 78780e93..fa2edb28 100644 --- a/mp/src/game/client/rendertexture.cpp +++ b/mp/src/game/client/rendertexture.cpp @@ -107,11 +107,11 @@ ITexture *GetFullFrameFrameBufferTexture( int textureIndex ) char name[256]; if( textureIndex != 0 ) { - sprintf( name, "_rt_FullFrameFB%d", textureIndex ); + V_sprintf_safe( name, "_rt_FullFrameFB%d", textureIndex ); } else { - Q_strcpy( name, "_rt_FullFrameFB" ); + V_strcpy_safe( name, "_rt_FullFrameFB" ); } s_pFullFrameFrameBufferTexture[textureIndex].Init( materials->FindTexture( name, TEXTURE_GROUP_RENDER_TARGET ) ); Assert( !IsErrorTexture( s_pFullFrameFrameBufferTexture[textureIndex] ) ); diff --git a/mp/src/game/client/replay/genericclassbased_replay.cpp b/mp/src/game/client/replay/genericclassbased_replay.cpp index 00e2feba..13dfacfd 100644 --- a/mp/src/game/client/replay/genericclassbased_replay.cpp +++ b/mp/src/game/client/replay/genericclassbased_replay.cpp @@ -141,7 +141,7 @@ bool CGenericClassBasedReplay::Read( KeyValues *pIn ) // Read killer info m_nKillerClass = pIn->GetInt( "killer_class" ); - V_strcpy( m_szKillerName, pIn->GetString( "killer_name" ) ); + V_strcpy_safe( m_szKillerName, pIn->GetString( "killer_name" ) ); // Make sure vector is clear Assert( GetKillCount() == 0 ); diff --git a/mp/src/game/client/sixense/in_sixense.cpp b/mp/src/game/client/sixense/in_sixense.cpp index e0f4ba39..c8f79ec7 100644 --- a/mp/src/game/client/sixense/in_sixense.cpp +++ b/mp/src/game/client/sixense/in_sixense.cpp @@ -2151,7 +2151,7 @@ void SixenseInput::SetPlayerHandPositions( CUserCmd *pCmd, float flFrametime ) // This 'slides' the hold origin if you pull the object back into the player float min_z_dist = sixense_hold_slide_z_min_dist.GetFloat(); - float xy_radius = sixense_hold_slide_xy_radius.GetFloat();; + float xy_radius = sixense_hold_slide_xy_radius.GetFloat(); if ( !m_bScalingLockedOneToOne && (Vector3( ss_right_pos[0], ss_right_pos[1], 0.0f ).length() < xy_radius) && (ss_right_pos[2] > min_z_dist) ) { diff --git a/mp/src/game/client/spritemodel.cpp b/mp/src/game/client/spritemodel.cpp index 018e918f..09284865 100644 --- a/mp/src/game/client/spritemodel.cpp +++ b/mp/src/game/client/spritemodel.cpp @@ -201,7 +201,7 @@ static void AdjustSubRect(CEngineSprite *pSprite, int frame, float *pfLeft, floa *pw = rc.right - rc.left; *ph = rc.bottom - rc.top; - f = 1.0 / (float)pSprite->GetWidth();; + f = 1.0 / (float)pSprite->GetWidth(); *pfLeft = ((float)rc.left + 0.5) * f; *pfRight = ((float)rc.right - 0.5) * f; @@ -415,12 +415,14 @@ IMaterial *CEngineSprite::GetMaterial( RenderMode_t nRenderMode, int nFrame ) m_VideoMaterial->SetFrame( nFrame ); } - IMaterial *pMaterial = m_material[nRenderMode]; - IMaterialVar* pFrameVar = pMaterial->FindVarFast( "$frame", &frameCache ); - if ( pFrameVar ) + if ( pMaterial ) { - pFrameVar->SetIntValue( nFrame ); + IMaterialVar* pFrameVar = pMaterial->FindVarFast( "$frame", &frameCache ); + if ( pFrameVar ) + { + pFrameVar->SetIntValue( nFrame ); + } } return pMaterial; diff --git a/mp/src/game/client/vgui_debugoverlaypanel.cpp b/mp/src/game/client/vgui_debugoverlaypanel.cpp index c3734147..32a7ee83 100644 --- a/mp/src/game/client/vgui_debugoverlaypanel.cpp +++ b/mp/src/game/client/vgui_debugoverlaypanel.cpp @@ -166,7 +166,8 @@ public: if ( debugOverlayPanel ) { debugOverlayPanel->SetParent( (vgui::Panel *)NULL ); - delete debugOverlayPanel; + debugOverlayPanel->MarkForDeletion(); + debugOverlayPanel = NULL; } } }; diff --git a/mp/src/game/client/vgui_fpspanel.cpp b/mp/src/game/client/vgui_fpspanel.cpp index a1e88875..7458b702 100644 --- a/mp/src/game/client/vgui_fpspanel.cpp +++ b/mp/src/game/client/vgui_fpspanel.cpp @@ -395,7 +395,7 @@ public: if ( fpsPanel ) { fpsPanel->SetParent( (vgui::Panel *)NULL ); - delete fpsPanel; + fpsPanel->MarkForDeletion(); fpsPanel = NULL; } } @@ -814,7 +814,7 @@ public: if ( ioPanel ) { ioPanel->SetParent( (vgui::Panel *)NULL ); - delete ioPanel; + ioPanel->MarkForDeletion(); ioPanel = NULL; } } diff --git a/mp/src/game/client/vgui_loadingdiscpanel.cpp b/mp/src/game/client/vgui_loadingdiscpanel.cpp index 94b2a9fb..2dc7dd8f 100644 --- a/mp/src/game/client/vgui_loadingdiscpanel.cpp +++ b/mp/src/game/client/vgui_loadingdiscpanel.cpp @@ -128,14 +128,14 @@ public: if ( loadingDiscPanel ) { loadingDiscPanel->SetParent( (vgui::Panel *)NULL ); - delete loadingDiscPanel; + loadingDiscPanel->MarkForDeletion(); loadingDiscPanel = NULL; } if ( m_pPauseDiscPanel ) { m_pPauseDiscPanel->SetParent( (vgui::Panel *)NULL ); - delete m_pPauseDiscPanel; + m_pPauseDiscPanel->MarkForDeletion(); m_pPauseDiscPanel = NULL; } diff --git a/mp/src/game/client/vgui_messagechars.cpp b/mp/src/game/client/vgui_messagechars.cpp index 1d1410f1..6bde7566 100644 --- a/mp/src/game/client/vgui_messagechars.cpp +++ b/mp/src/game/client/vgui_messagechars.cpp @@ -378,7 +378,7 @@ public: if ( messageCharsPanel ) { messageCharsPanel->SetParent( (vgui::Panel *)NULL ); - delete messageCharsPanel; + messageCharsPanel->MarkForDeletion(); messageCharsPanel = NULL; } } diff --git a/mp/src/game/client/vgui_netgraphpanel.cpp b/mp/src/game/client/vgui_netgraphpanel.cpp index 0f601438..adf3e4b9 100644 --- a/mp/src/game/client/vgui_netgraphpanel.cpp +++ b/mp/src/game/client/vgui_netgraphpanel.cpp @@ -492,6 +492,10 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w, { i = ( m_OutgoingSequence - a ) & ( TIMINGS - 1 ); h = MIN( ( cmdinfo[i].cmd_lerp / 3.0 ) * LERP_HEIGHT, LERP_HEIGHT ); + if ( h < 0 ) + { + h = LERP_HEIGHT; + } rcFill.x = x + w -a - 1; rcFill.width = 1; @@ -514,7 +518,9 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w, for ( j = start; j < h; j++ ) { - DrawLine(&rcFill, colors[j + extrap_point], 255 ); + int index = j + extrap_point; + Assert( (size_t)index < Q_ARRAYSIZE( colors ) ); + DrawLine(&rcFill, colors[ index ], 255 ); rcFill.y--; } } @@ -532,7 +538,9 @@ void CNetGraphPanel::DrawTimes( vrect_t vrect, cmdinfo_t *cmdinfo, int x, int w, for ( j = 0; j < h; j++ ) { - DrawLine(&rcFill, colors[j + oldh], 255 ); + int index = j + oldh; + Assert( (size_t)index < Q_ARRAYSIZE( colors ) ); + DrawLine(&rcFill, colors[ index ], 255 ); rcFill.y--; } } @@ -1533,7 +1541,7 @@ public: if ( netGraphPanel ) { netGraphPanel->SetParent( (Panel *)NULL ); - delete netGraphPanel; + netGraphPanel->MarkForDeletion(); netGraphPanel = NULL; } } diff --git a/mp/src/game/client/vgui_schemevisualizer.cpp b/mp/src/game/client/vgui_schemevisualizer.cpp index b2a6f774..afde874d 100644 --- a/mp/src/game/client/vgui_schemevisualizer.cpp +++ b/mp/src/game/client/vgui_schemevisualizer.cpp @@ -178,11 +178,13 @@ void CSchemeVisualizer::AddFontsToList() { #ifdef POSIX const char strOAccent[] = { (char)0xc3, (char)0x93, 0x00 }; // UTF-8 for U+00D3 (LATIN CAPITAL LETTER O WITH ACUTE) + const char strSkull[] = { (char)0xe2, (char)0x98, (char)0xa0, 0x00 }; #else const uint8 strOAccent[] = { 0xd3, 0x00 }; + const char strSkull[] = ""; #endif // Stick an intl character in here to test accents (O') - CFmtStr fmtText( "ABCDEFGHIJKLMN%sPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz0123456789!@#$%%^&*()-_=+", strOAccent ); + CFmtStr fmtText( "ABCDEFGHIJKLMN%sPQRSTUVWXYZ%sabcdefhijklmnopqrstuvwxyz0123456789!@#$%%^&*()-_=+", strOAccent, strSkull ); const int nFontCount = m_pViewScheme->GetFontCount(); @@ -288,4 +290,4 @@ void CSchemeVisualizer::OnTick() // Update the list now UpdateList( nType ); -} \ No newline at end of file +} diff --git a/mp/src/game/client/vgui_video.cpp b/mp/src/game/client/vgui_video.cpp index 3badea3f..57323f40 100644 --- a/mp/src/game/client/vgui_video.cpp +++ b/mp/src/game/client/vgui_video.cpp @@ -348,7 +348,8 @@ bool VideoPanel_Create( unsigned int nXPos, unsigned int nYPos, // Start it going if ( pVideoPanel->BeginPlayback( pVideoFilename ) == false ) { - delete pVideoPanel; + pVideoPanel->MarkForDeletion(); + pVideoPanel = NULL; return false; } diff --git a/mp/src/game/client/view.cpp b/mp/src/game/client/view.cpp index 333a2756..d74d326e 100644 --- a/mp/src/game/client/view.cpp +++ b/mp/src/game/client/view.cpp @@ -110,9 +110,9 @@ static ConVar v_centerspeed( "v_centerspeed","500" ); #ifdef TF_CLIENT_DLL // 54 degrees approximates a 35mm camera - we determined that this makes the viewmodels // and motions look the most natural. -ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE ); +ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 ); #else -ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_CHEAT ); +ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_CHEAT, "Sets the field-of-view for the viewmodel.", true, 0.1, true, 179.9 ); #endif ConVar mat_viewportscale( "mat_viewportscale", "1.0", FCVAR_ARCHIVE, "Scale down the main viewport (to reduce GPU impact on CPU profiling)", true, (1.0f / 640.0f), true, 1.0f ); ConVar mat_viewportupscale( "mat_viewportupscale", "1", FCVAR_ARCHIVE, "Scale the viewport back up" ); diff --git a/mp/src/game/client/weapon_selection.cpp b/mp/src/game/client/weapon_selection.cpp index 66666b59..dc2adf4e 100644 --- a/mp/src/game/client/weapon_selection.cpp +++ b/mp/src/game/client/weapon_selection.cpp @@ -101,6 +101,7 @@ void CBaseHudWeaponSelection::Reset(void) // Start hidden m_bSelectionVisible = false; m_flSelectionTime = gpGlobals->curtime; + gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) ); } //----------------------------------------------------------------------------- @@ -207,6 +208,7 @@ bool CBaseHudWeaponSelection::IsInSelectionMode() void CBaseHudWeaponSelection::OpenSelection( void ) { m_bSelectionVisible = true; + gHUD.LockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) ); } //----------------------------------------------------------------------------- @@ -215,6 +217,7 @@ void CBaseHudWeaponSelection::OpenSelection( void ) void CBaseHudWeaponSelection::HideSelection( void ) { m_bSelectionVisible = false; + gHUD.UnlockRenderGroup( gHUD.LookupRenderGroupIndexByName( "weapon_selection" ) ); } //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/AI_ResponseSystem.h b/mp/src/game/server/AI_ResponseSystem.h index a34255b2..a7b3a797 100644 --- a/mp/src/game/server/AI_ResponseSystem.h +++ b/mp/src/game/server/AI_ResponseSystem.h @@ -18,6 +18,7 @@ abstract_class IResponseFilter { public: + virtual ~IResponseFilter(){} virtual bool IsValidResponse( ResponseType_t type, const char *pszValue ) = 0; }; diff --git a/mp/src/game/server/BaseAnimatingOverlay.cpp b/mp/src/game/server/BaseAnimatingOverlay.cpp index 36534bc0..84be6fba 100644 --- a/mp/src/game/server/BaseAnimatingOverlay.cpp +++ b/mp/src/game/server/BaseAnimatingOverlay.cpp @@ -925,6 +925,25 @@ void CBaseAnimatingOverlay::SetLayerCycle( int iLayer, float flCycle, float flPr m_AnimOverlay[iLayer].MarkActive( ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseAnimatingOverlay::SetLayerCycle( int iLayer, float flCycle, float flPrevCycle, float flLastEventCheck ) +{ + if (!IsValidLayer( iLayer )) + return; + + if (!m_AnimOverlay[iLayer].m_bLooping) + { + flCycle = clamp( flCycle, 0.0f, 1.0f ); + flPrevCycle = clamp( flPrevCycle, 0.0f, 1.0f ); + } + m_AnimOverlay[iLayer].m_flCycle = flCycle; + m_AnimOverlay[iLayer].m_flPrevCycle = flPrevCycle; + m_AnimOverlay[iLayer].m_flLastEventCheck = flLastEventCheck; + m_AnimOverlay[iLayer].MarkActive( ); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- diff --git a/mp/src/game/server/BaseAnimatingOverlay.h b/mp/src/game/server/BaseAnimatingOverlay.h index ac112cbd..5184eac3 100644 --- a/mp/src/game/server/BaseAnimatingOverlay.h +++ b/mp/src/game/server/BaseAnimatingOverlay.h @@ -165,6 +165,7 @@ public: void SetLayerCycle( int iLayer, float flCycle ); void SetLayerCycle( int iLayer, float flCycle, float flPrevCycle ); + void SetLayerCycle( int iLayer, float flCycle, float flPrevCycle, float flLastEventCheck ); float GetLayerCycle( int iLayer ); void SetLayerPlaybackRate( int iLayer, float flPlaybackRate ); diff --git a/mp/src/game/server/CommentarySystem.cpp b/mp/src/game/server/CommentarySystem.cpp index f846a029..677b4d84 100644 --- a/mp/src/game/server/CommentarySystem.cpp +++ b/mp/src/game/server/CommentarySystem.cpp @@ -839,7 +839,7 @@ void CC_CommentaryChanged( IConVar *pConVar, const char *pOldString, float flOld g_CommentarySystem.SetCommentaryMode( var.GetBool() ); } } -ConVar commentary("commentary", "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_XBOX, "Desired commentary mode state.", CC_CommentaryChanged ); +ConVar commentary( "commentary", "0", FCVAR_NONE, "Desired commentary mode state.", CC_CommentaryChanged ); //----------------------------------------------------------------------------- // Purpose: We need to revert back any convar changes that are made by the diff --git a/mp/src/game/server/GameStats_BasicStatsFunctions.cpp b/mp/src/game/server/GameStats_BasicStatsFunctions.cpp index 5656b6b7..47e3de77 100644 --- a/mp/src/game/server/GameStats_BasicStatsFunctions.cpp +++ b/mp/src/game/server/GameStats_BasicStatsFunctions.cpp @@ -155,7 +155,7 @@ bool BasicGameStats_t::ParseFromBuffer( CUtlBuffer& buf, int iBufferStatsVersion for ( int i = 0; i < c; ++i ) { char mapname[ 256 ]; - buf.GetString( mapname, sizeof( mapname ) ); + buf.GetString( mapname ); BasicGameStatsRecord_t *rec = FindOrAddRecordForMap( mapname ); bool valid= rec->ParseFromBuffer( buf, iBufferStatsVersion ); diff --git a/mp/src/game/server/ai_activity.cpp b/mp/src/game/server/ai_activity.cpp index e7ba1761..3f5b5b49 100644 --- a/mp/src/game/server/ai_activity.cpp +++ b/mp/src/game/server/ai_activity.cpp @@ -1686,6 +1686,11 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_SWIM_GRENADE_ITEM2 ); ADD_ACTIVITY_TO_SR( ACT_MP_ATTACK_AIRWALK_GRENADE_ITEM2 ); + // Passtime + ADD_ACTIVITY_TO_SR( ACT_MP_STAND_PASSTIME ); + ADD_ACTIVITY_TO_SR( ACT_MP_RUN_PASSTIME ); + ADD_ACTIVITY_TO_SR( ACT_MP_CROUCHWALK_PASSTIME ); + // Flinches ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH ); ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_FLINCH_PRIMARY ); @@ -1826,6 +1831,7 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_MP_DOUBLEJUMP_CROUCH_ITEM1 ); ADD_ACTIVITY_TO_SR( ACT_MP_DOUBLEJUMP_CROUCH_ITEM2 ); ADD_ACTIVITY_TO_SR( ACT_MP_DOUBLEJUMP_CROUCH_LOSERSTATE ); + ADD_ACTIVITY_TO_SR( ACT_MP_DOUBLEJUMP_CROUCH_PASSTIME ); ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_HANDMOUTH ); ADD_ACTIVITY_TO_SR( ACT_MP_GESTURE_VC_FINGERPOINT ); @@ -1887,6 +1893,11 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_MP_STUN_MIDDLE ); ADD_ACTIVITY_TO_SR( ACT_MP_STUN_END ); + ADD_ACTIVITY_TO_SR( ACT_MP_PASSTIME_THROW_BEGIN ); + ADD_ACTIVITY_TO_SR( ACT_MP_PASSTIME_THROW_MIDDLE ); + ADD_ACTIVITY_TO_SR( ACT_MP_PASSTIME_THROW_END ); + ADD_ACTIVITY_TO_SR( ACT_MP_PASSTIME_THROW_CANCEL ); + ADD_ACTIVITY_TO_SR( ACT_VM_UNUSABLE ); ADD_ACTIVITY_TO_SR( ACT_VM_UNUSABLE_TO_USABLE ); ADD_ACTIVITY_TO_SR( ACT_VM_USABLE_TO_UNUSABLE ); @@ -2186,4 +2197,40 @@ void CAI_BaseNPC::InitDefaultActivitySR(void) ADD_ACTIVITY_TO_SR( ACT_BOT_GESTURE_FLINCH ); ADD_ACTIVITY_TO_SR( ACT_BOT_PANIC_START ); ADD_ACTIVITY_TO_SR( ACT_BOT_PANIC_END ); + + ADD_ACTIVITY_TO_SR( ACT_ENGINEER_REVOLVER_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_ENGINEER_REVOLVER_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_ENGINEER_REVOLVER_PRIMARYATTACK ); + ADD_ACTIVITY_TO_SR( ACT_ENGINEER_REVOLVER_RELOAD ); + + ADD_ACTIVITY_TO_SR( ACT_KART_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_KART_ACTION_SHOOT ); + ADD_ACTIVITY_TO_SR( ACT_KART_ACTION_DASH ); + ADD_ACTIVITY_TO_SR( ACT_KART_JUMP_START ); + ADD_ACTIVITY_TO_SR( ACT_KART_JUMP_FLOAT ); + ADD_ACTIVITY_TO_SR( ACT_KART_JUMP_LAND ); + ADD_ACTIVITY_TO_SR( ACT_KART_IMPACT ); + ADD_ACTIVITY_TO_SR( ACT_KART_IMPACT_BIG ); + ADD_ACTIVITY_TO_SR( ACT_KART_GESTURE_POSITIVE ); + ADD_ACTIVITY_TO_SR( ACT_KART_GESTURE_NEGATIVE ); + + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_DRAW ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_FIRE_START ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_FIRE_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_PULL_START ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_PULL_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_GRAPPLE_PULL_END ); + + ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_START ); + ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_END ); + + ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_START ); + ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_END ); + + ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_START ); + ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_IDLE ); + ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_END ); } diff --git a/mp/src/game/server/baseanimating.cpp b/mp/src/game/server/baseanimating.cpp index 34bf6378..9999c496 100644 --- a/mp/src/game/server/baseanimating.cpp +++ b/mp/src/game/server/baseanimating.cpp @@ -470,7 +470,6 @@ void CBaseAnimating::StudioFrameAdvanceManual( float flInterval ) if ( !pStudioHdr ) return; - UpdateModelScale(); m_flAnimTime = gpGlobals->curtime; m_flPrevAnimTime = m_flAnimTime - flInterval; float flCycleRate = GetSequenceCycleRate( pStudioHdr, GetSequence() ) * m_flPlaybackRate; @@ -490,8 +489,6 @@ void CBaseAnimating::StudioFrameAdvance() return; } - UpdateModelScale(); - if ( !m_flPrevAnimTime ) { m_flPrevAnimTime = m_flAnimTime; @@ -631,7 +628,7 @@ void CBaseAnimating::InputSetModelScale( inputdata_t &inputdata ) int CBaseAnimating::SelectWeightedSequence ( Activity activity ) { Assert( activity != ACT_INVALID ); - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::SelectWeightedSequence( GetModelPtr(), activity, GetSequence() ); } @@ -639,16 +636,23 @@ int CBaseAnimating::SelectWeightedSequence ( Activity activity ) int CBaseAnimating::SelectWeightedSequence ( Activity activity, int curSequence ) { Assert( activity != ACT_INVALID ); - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::SelectWeightedSequence( GetModelPtr(), activity, curSequence ); } +int CBaseAnimating::SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) +{ + Assert( activity != ACT_INVALID ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); + return GetModelPtr()->SelectWeightedSequenceFromModifiers( activity, pActivityModifiers, iModifierCount ); +} + //========================================================= // ResetActivityIndexes //========================================================= void CBaseAnimating::ResetActivityIndexes ( void ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); ::ResetActivityIndexes( GetModelPtr() ); } @@ -657,7 +661,7 @@ void CBaseAnimating::ResetActivityIndexes ( void ) //========================================================= void CBaseAnimating::ResetEventIndexes ( void ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); ::ResetEventIndexes( GetModelPtr() ); } @@ -669,7 +673,7 @@ void CBaseAnimating::ResetEventIndexes ( void ) //========================================================= int CBaseAnimating::SelectHeaviestSequence ( Activity activity ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::SelectHeaviestSequence( GetModelPtr(), activity ); } @@ -681,7 +685,7 @@ int CBaseAnimating::SelectHeaviestSequence ( Activity activity ) //----------------------------------------------------------------------------- int CBaseAnimating::LookupActivity( const char *label ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::LookupActivity( GetModelPtr(), label ); } @@ -689,7 +693,7 @@ int CBaseAnimating::LookupActivity( const char *label ) //========================================================= int CBaseAnimating::LookupSequence( const char *label ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::LookupSequence( GetModelPtr(), label ); } @@ -729,7 +733,7 @@ float CBaseAnimating::GetSequenceMoveYaw( int iSequence ) { Vector vecReturn; - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); ::GetSequenceLinearMotion( GetModelPtr(), iSequence, GetPoseParameterArray(), &vecReturn ); if (vecReturn.Length() > 0) @@ -765,7 +769,7 @@ float CBaseAnimating::GetSequenceMoveDist( CStudioHdr *pStudioHdr, int iSequence //----------------------------------------------------------------------------- void CBaseAnimating::GetSequenceLinearMotion( int iSequence, Vector *pVec ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); ::GetSequenceLinearMotion( GetModelPtr(), iSequence, GetPoseParameterArray(), pVec ); } @@ -912,7 +916,7 @@ void CBaseAnimating::ResetSequenceInfo ( ) //========================================================= bool CBaseAnimating::IsValidSequence( int iSequence ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); CStudioHdr* pstudiohdr = GetModelPtr( ); if (iSequence < 0 || iSequence >= pstudiohdr->GetNumSeq()) { @@ -1779,7 +1783,7 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ) MDLCACHE_CRITICAL_SECTION(); - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); CStudioHdr *pStudioHdr = GetModelPtr( ); @@ -2087,7 +2091,7 @@ void CBaseAnimating::GetEyeballs( Vector &origin, QAngle &angles ) //========================================================= int CBaseAnimating::FindTransitionSequence( int iCurrentSequence, int iGoalSequence, int *piDir ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); if (piDir == NULL) { @@ -2136,7 +2140,7 @@ void CBaseAnimating::SetBodygroup( int iGroup, int iValue ) { // SetBodygroup is not supported on pending dynamic models. Wait for it to load! // XXX TODO we could buffer up the group and value if we really needed to. -henryg - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); int newBody = m_nBody; ::SetBodygroup( GetModelPtr( ), newBody, iGroup, iValue ); m_nBody = newBody; @@ -2735,7 +2739,7 @@ void CBaseAnimating::InitBoneControllers ( void ) // FIXME: rename //========================================================= float CBaseAnimating::SetBoneController ( int iController, float flValue ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); CStudioHdr *pmodel = (CStudioHdr*)GetModelPtr(); @@ -2752,7 +2756,7 @@ float CBaseAnimating::SetBoneController ( int iController, float flValue ) //========================================================= float CBaseAnimating::GetBoneController ( int iController ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); CStudioHdr *pmodel = (CStudioHdr*)GetModelPtr(); @@ -2943,7 +2947,7 @@ void CBaseAnimating::SetHitboxSet( int setnum ) //----------------------------------------------------------------------------- void CBaseAnimating::SetHitboxSetByName( const char *setname ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); m_nHitboxSet = FindHitboxSetByName( GetModelPtr(), setname ); } @@ -2962,7 +2966,7 @@ int CBaseAnimating::GetHitboxSet( void ) //----------------------------------------------------------------------------- const char *CBaseAnimating::GetHitboxSetName( void ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::GetHitboxSetName( GetModelPtr(), m_nHitboxSet ); } @@ -2972,7 +2976,7 @@ const char *CBaseAnimating::GetHitboxSetName( void ) //----------------------------------------------------------------------------- int CBaseAnimating::GetHitboxSetCount( void ) { - Assert( GetModelPtr() ); + AssertMsg( GetModelPtr(), "GetModelPtr NULL. %s", STRING(GetEntityName()) ? STRING(GetEntityName()) : "" ); return ::GetHitboxSetCount( GetModelPtr() ); } @@ -3303,6 +3307,7 @@ void CBaseAnimating::SetModelScale( float scale, float change_duration /*= 0.0f* mvs->m_flModelScaleGoal = scale; mvs->m_flModelScaleStartTime = gpGlobals->curtime; mvs->m_flModelScaleFinishTime = mvs->m_flModelScaleStartTime + change_duration; + SetContextThink( &CBaseAnimating::UpdateModelScale, gpGlobals->curtime, "UpdateModelScaleThink" ); } else { @@ -3341,6 +3346,11 @@ void CBaseAnimating::UpdateModelScale() } RefreshCollisionBounds(); + + if ( frac < 1.f ) + { + SetContextThink( &CBaseAnimating::UpdateModelScale, gpGlobals->curtime, "UpdateModelScaleThink" ); + } } void CBaseAnimating::RefreshCollisionBounds( void ) diff --git a/mp/src/game/server/baseanimating.h b/mp/src/game/server/baseanimating.h index 75300e8e..0550683e 100644 --- a/mp/src/game/server/baseanimating.h +++ b/mp/src/game/server/baseanimating.h @@ -108,6 +108,7 @@ public: void ResetEventIndexes ( void ); int SelectWeightedSequence ( Activity activity ); int SelectWeightedSequence ( Activity activity, int curSequence ); + int SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ); int SelectHeaviestSequence ( Activity activity ); int LookupActivity( const char *label ); int LookupSequence ( const char *label ); @@ -436,10 +437,14 @@ inline CStudioHdr *CBaseAnimating::GetModelPtr( void ) return NULL; #ifdef _DEBUG - // GetModelPtr() is often called before OnNewModel() so go ahead and set it up first chance. - static IDataCacheSection *pModelCache = datacache->FindSection( "ModelData" ); - AssertOnce( pModelCache->IsFrameLocking() ); + if ( !HushAsserts() ) + { + // GetModelPtr() is often called before OnNewModel() so go ahead and set it up first chance. + static IDataCacheSection *pModelCache = datacache->FindSection( "ModelData" ); + AssertOnce( pModelCache->IsFrameLocking() ); + } #endif + if ( !m_pStudioHdr && GetModel() ) { LockStudioHdr(); diff --git a/mp/src/game/server/basecombatcharacter.cpp b/mp/src/game/server/basecombatcharacter.cpp index 9f6a8674..71d6c844 100644 --- a/mp/src/game/server/basecombatcharacter.cpp +++ b/mp/src/game/server/basecombatcharacter.cpp @@ -2280,8 +2280,8 @@ CBaseCombatWeapon *CBaseCombatCharacter::Weapon_GetWpnForAmmo( int iAmmoIndex ) //----------------------------------------------------------------------------- bool CBaseCombatCharacter::Weapon_CanUse( CBaseCombatWeapon *pWeapon ) { - acttable_t *pTable = pWeapon->ActivityList(); - int actCount = pWeapon->ActivityListCount(); + int actCount = 0; + acttable_t *pTable = pWeapon->ActivityList( actCount ); if( actCount < 1 ) { diff --git a/mp/src/game/server/baseentity.cpp b/mp/src/game/server/baseentity.cpp index 7a7a7e6c..9bd525a4 100644 --- a/mp/src/game/server/baseentity.cpp +++ b/mp/src/game/server/baseentity.cpp @@ -86,6 +86,7 @@ bool CBaseEntity::sm_bDisableTouchFuncs = false; // Disables PhysicsTouch and Ph bool CBaseEntity::sm_bAccurateTriggerBboxChecks = true; // set to false for legacy behavior in ep1 int CBaseEntity::m_nPredictionRandomSeed = -1; +int CBaseEntity::m_nPredictionRandomSeedServer = -1; CBasePlayer *CBaseEntity::m_pPredictionPlayer = NULL; // Used to make sure nobody calls UpdateTransmitState directly. @@ -1440,10 +1441,10 @@ int CBaseEntity::OnTakeDamage( const CTakeDamageInfo &info ) //----------------------------------------------------------------------------- // Purpose: Scale damage done and call OnTakeDamage //----------------------------------------------------------------------------- -void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo ) +int CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo ) { if ( !g_pGameRules ) - return; + return 0; bool bHasPhysicsForceDamage = !g_pGameRules->Damage_NoPhysicsForce( inputInfo.GetDamageType() ); if ( bHasPhysicsForceDamage && inputInfo.GetDamageType() != DMG_GENERIC ) @@ -1475,12 +1476,12 @@ void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo ) // Make sure our damage filter allows the damage. if ( !PassesDamageFilter( inputInfo )) { - return; + return 0; } if( !g_pGameRules->AllowDamage(this, inputInfo) ) { - return; + return 0; } if ( PhysIsInCallback() ) @@ -1502,8 +1503,9 @@ void CBaseEntity::TakeDamage( const CTakeDamageInfo &inputInfo ) //Msg("%s took %.2f Damage, at %.2f\n", GetClassname(), info.GetDamage(), gpGlobals->curtime ); - OnTakeDamage( info ); + return OnTakeDamage( info ); } + return 0; } //----------------------------------------------------------------------------- @@ -6089,7 +6091,7 @@ void CBaseEntity::SetLocalAngles( const QAngle& angles ) { Warning( "Bad SetLocalAngles(%f,%f,%f) on %s\n", angles.x, angles.y, angles.z, GetDebugName() ); } - Assert( false ); + AssertMsg( false, "Bad SetLocalAngles(%f,%f,%f) on %s\n", angles.x, angles.y, angles.z, GetDebugName() ); return; } diff --git a/mp/src/game/server/baseentity.h b/mp/src/game/server/baseentity.h index 7261e0a8..42c0cdf2 100644 --- a/mp/src/game/server/baseentity.h +++ b/mp/src/game/server/baseentity.h @@ -904,7 +904,7 @@ public: virtual int OnTakeDamage( const CTakeDamageInfo &info ); // This is what you should call to apply damage to an entity. - void TakeDamage( const CTakeDamageInfo &info ); + int TakeDamage( const CTakeDamageInfo &info ); virtual void AdjustDamageDirection( const CTakeDamageInfo &info, Vector &dir, CBaseEntity *pEnt ) {} virtual int TakeHealth( float flHealth, int bitsDamageType ); @@ -1748,6 +1748,7 @@ private: // randon number generators to spit out the same random numbers on both sides for a particular // usercmd input. static int m_nPredictionRandomSeed; + static int m_nPredictionRandomSeedServer; static CBasePlayer *m_pPredictionPlayer; // FIXME: Make hierarchy a member of CBaseEntity @@ -1761,7 +1762,7 @@ private: public: // Accessors for above - static int GetPredictionRandomSeed( void ); + static int GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime = false ); static void SetPredictionRandomSeed( const CUserCmd *cmd ); static CBasePlayer *GetPredictionPlayer( void ); static void SetPredictionPlayer( CBasePlayer *player ); @@ -1799,6 +1800,8 @@ public: { return s_bAbsQueriesValid; } + + virtual bool ShouldBlockNav() const { return true; } }; // Send tables exposed in this module. diff --git a/mp/src/game/server/baseflex.cpp b/mp/src/game/server/baseflex.cpp index 5c435d73..b760ed54 100644 --- a/mp/src/game/server/baseflex.cpp +++ b/mp/src/game/server/baseflex.cpp @@ -113,7 +113,7 @@ CBaseFlex::CBaseFlex( void ) : CBaseFlex::~CBaseFlex( void ) { m_LocalToGlobal.RemoveAll(); - Assert( m_SceneEvents.Count() == 0 ); + AssertMsg( m_SceneEvents.Count() == 0, "m_ScenesEvent.Count != 0: %d", m_SceneEvents.Count() ); } void CBaseFlex::SetModel( const char *szModelName ) @@ -508,7 +508,7 @@ bool CBaseFlex::HandleStartSequenceSceneEvent( CSceneEventInfo *info, CChoreoSce float seq_duration = SequenceDuration( info->m_nSequence ); float flCycle = dt / seq_duration; flCycle = flCycle - (int)flCycle; // loop - SetLayerCycle( info->m_iLayer, flCycle, flCycle ); + SetLayerCycle( info->m_iLayer, flCycle, flCycle, 0.f ); SetLayerPlaybackRate( info->m_iLayer, 0.0 ); } diff --git a/mp/src/game/server/client.cpp b/mp/src/game/server/client.cpp index f500ad5e..eced1df1 100644 --- a/mp/src/game/server/client.cpp +++ b/mp/src/game/server/client.cpp @@ -57,6 +57,60 @@ extern bool IsInCommentaryMode( void ); ConVar *sv_cheats = NULL; +enum eAllowPointServerCommand { + eAllowNever, + eAllowOfficial, + eAllowAlways +}; + +#ifdef TF_DLL +// The default value here should match the default of the convar +eAllowPointServerCommand sAllowPointServerCommand = eAllowOfficial; +#else +eAllowPointServerCommand sAllowPointServerCommand = eAllowAlways; +#endif // TF_DLL + +void sv_allow_point_servercommand_changed( IConVar *pConVar, const char *pOldString, float flOldValue ) +{ + ConVarRef var( pConVar ); + if ( !var.IsValid() ) + { + return; + } + + const char *pNewValue = var.GetString(); + if ( V_strcasecmp ( pNewValue, "always" ) == 0 ) + { + sAllowPointServerCommand = eAllowAlways; + } +#ifdef TF_DLL + else if ( V_strcasecmp ( pNewValue, "official" ) == 0 ) + { + sAllowPointServerCommand = eAllowOfficial; + } +#endif // TF_DLL + else + { + sAllowPointServerCommand = eAllowNever; + } +} + +ConVar sv_allow_point_servercommand ( "sv_allow_point_servercommand", +#ifdef TF_DLL + // The default value here should match the default of the convar + "official", +#else + // Other games may use this in their official maps, and only TF exposes IsValveMap() currently + "always", +#endif // TF_DLL + FCVAR_NONE, + "Allow use of point_servercommand entities in map. Potentially dangerous for untrusted maps.\n" + " disallow : Always disallow\n" +#ifdef TF_DLL + " official : Allowed for valve maps only\n" +#endif // TF_DLL + " always : Allow for all maps", sv_allow_point_servercommand_changed ); + void ClientKill( edict_t *pEdict, const Vector &vecForce, bool bExplode = false ) { CBasePlayer *pPlayer = static_cast( GetContainingEntity( pEdict ) ); @@ -569,7 +623,22 @@ void CPointServerCommand::InputCommand( inputdata_t& inputdata ) if ( !inputdata.value.String()[0] ) return; - engine->ServerCommand( UTIL_VarArgs( "%s\n", inputdata.value.String() ) ); + bool bAllowed = ( sAllowPointServerCommand == eAllowAlways ); +#ifdef TF_DLL + if ( sAllowPointServerCommand == eAllowOfficial ) + { + bAllowed = TFGameRules() && TFGameRules()->IsValveMap(); + } +#endif // TF_DLL + + if ( bAllowed ) + { + engine->ServerCommand( UTIL_VarArgs( "%s\n", inputdata.value.String() ) ); + } + else + { + Warning( "point_servercommand usage blocked by sv_allow_point_servercommand setting\n" ); + } } BEGIN_DATADESC( CPointServerCommand ) @@ -600,7 +669,7 @@ void CC_DrawLine( const CCommand &args ) static ConCommand drawline("drawline", CC_DrawLine, "Draws line between two 3D Points.\n\tGreen if no collision\n\tRed is collides with something\n\tArguments: x1 y1 z1 x2 y2 z2", FCVAR_CHEAT); //------------------------------------------------------------------------------ -// Purpose : Draw a cross at a points. +// Purpose : Draw a cross at a points. // Input : // Output : //------------------------------------------------------------------------------ diff --git a/mp/src/game/server/doors.h b/mp/src/game/server/doors.h index 7658482c..9b485fe2 100644 --- a/mp/src/game/server/doors.h +++ b/mp/src/game/server/doors.h @@ -150,6 +150,8 @@ public: bool ShouldLoopMoveSound( void ) { return m_bLoopMoveSound; } bool m_bLoopMoveSound; // Move sound loops until stopped + virtual bool ShouldBlockNav() const OVERRIDE { return false; } + private: void ChainUse( void ); ///< Chains +use on through to m_ChainTarget void ChainTouch( CBaseEntity *pOther ); ///< Chains touch on through to m_ChainTarget diff --git a/mp/src/game/server/episodic/ep2_gamestats.h b/mp/src/game/server/episodic/ep2_gamestats.h index cc36301c..cef1f839 100644 --- a/mp/src/game/server/episodic/ep2_gamestats.h +++ b/mp/src/game/server/episodic/ep2_gamestats.h @@ -215,7 +215,7 @@ public: { Ep2LevelStats_t::EntityDeathsLump_t data; char npcName[ 512 ]; - LoadBuffer.GetString( npcName, sizeof( npcName ) ); + LoadBuffer.GetString( npcName ); LoadBuffer.Get( &data, sizeof( data ) ); pItem->m_dictEntityDeaths.Insert( npcName, data ); } @@ -229,7 +229,7 @@ public: { Ep2LevelStats_t::WeaponLump_t data; char weaponName[ 512 ]; - LoadBuffer.GetString( weaponName, sizeof( weaponName ) ); + LoadBuffer.GetString( weaponName ); LoadBuffer.Get( &data, sizeof( data ) ); pItem->m_dictWeapons.Insert( weaponName, data ); } @@ -240,7 +240,7 @@ public: Assert( pItem ); Ep2LevelStats_t::SaveGameInfo_t *info = &pItem->m_SaveGameInfo; char sz[ 512 ]; - LoadBuffer.GetString( sz, sizeof( sz ) ); + LoadBuffer.GetString( sz ); info->m_sCurrentSaveFile = sz; info->m_nCurrentSaveFileTime = LoadBuffer.GetInt(); int c = LoadBuffer.GetInt(); @@ -277,7 +277,7 @@ public: { Ep2LevelStats_t::GenericStatsLump_t data; char pchStatName[ 512 ]; - LoadBuffer.GetString( pchStatName, sizeof( pchStatName ) ); + LoadBuffer.GetString( pchStatName ); LoadBuffer.Get( &data, sizeof( data ) ); pItem->m_dictGeneric.Insert( pchStatName, data ); } diff --git a/mp/src/game/server/func_break.cpp b/mp/src/game/server/func_break.cpp index d0b815e2..e7043ea9 100644 --- a/mp/src/game/server/func_break.cpp +++ b/mp/src/game/server/func_break.cpp @@ -817,8 +817,6 @@ void CBreakable::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ) //----------------------------------------------------------------------------- int CBreakable::OnTakeDamage( const CTakeDamageInfo &info ) { - Vector vecTemp; - CTakeDamageInfo subInfo = info; // If attacker can't do at least the min required damage to us, don't take any damage from them @@ -832,8 +830,6 @@ int CBreakable::OnTakeDamage( const CTakeDamageInfo &info ) return 1; } - vecTemp = subInfo.GetInflictor()->GetAbsOrigin() - WorldSpaceCenter(); - if (!IsBreakable()) return 0; diff --git a/mp/src/game/server/gameinterface.cpp b/mp/src/game/server/gameinterface.cpp index b20daf08..f6bbebb4 100644 --- a/mp/src/game/server/gameinterface.cpp +++ b/mp/src/game/server/gameinterface.cpp @@ -99,6 +99,7 @@ #include "tf_gamerules.h" #include "tf_lobby.h" #include "player_vs_environment/tf_population_manager.h" +#include "workshop/maps_workshop.h" extern ConVar tf_mm_trusted; extern ConVar tf_mm_servermode; @@ -559,11 +560,11 @@ void DrawAllDebugOverlays( void ) CServerGameDLL g_ServerGameDLL; // INTERFACEVERSION_SERVERGAMEDLL_VERSION_8 is compatible with the latest since we're only adding things to the end, so expose that as well. -EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameDLL, IServerGameDLL008, INTERFACEVERSION_SERVERGAMEDLL_VERSION_8, g_ServerGameDLL ); +//EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameDLL, IServerGameDLL008, INTERFACEVERSION_SERVERGAMEDLL_VERSION_8, g_ServerGameDLL ); EXPOSE_SINGLE_INTERFACE_GLOBALVAR(CServerGameDLL, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL, g_ServerGameDLL); // When bumping the version to this interface, check that our assumption is still valid and expose the older version in the same way -COMPILE_TIME_ASSERT( INTERFACEVERSION_SERVERGAMEDLL_INT == 9 ); +COMPILE_TIME_ASSERT( INTERFACEVERSION_SERVERGAMEDLL_INT == 10 ); bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, @@ -1081,9 +1082,7 @@ bool g_bCheckForChainedActivate; { \ if ( bCheck ) \ { \ - char msg[ 1024 ]; \ - Q_snprintf( msg, sizeof( msg ), "Entity (%i/%s/%s) failed to call base class Activate()\n", pClass->entindex(), pClass->GetClassname(), STRING( pClass->GetEntityName() ) ); \ - AssertMsg( g_bReceivedChainedActivate == true, msg ); \ + AssertMsg( g_bReceivedChainedActivate, "Entity (%i/%s/%s) failed to call base class Activate()\n", pClass->entindex(), pClass->GetClassname(), STRING( pClass->GetEntityName() ) ); \ } \ g_bCheckForChainedActivate = false; \ } @@ -1100,7 +1099,7 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl if ( gEntList.ResetDeleteList() != 0 ) { - Msg( "ERROR: Entity delete queue not empty on level start!\n" ); + Msg( "%s", "ERROR: Entity delete queue not empty on level start!\n" ); } for ( CBaseEntity *pClass = gEntList.FirstEnt(); pClass != NULL; pClass = gEntList.NextEnt(pClass) ) @@ -1150,6 +1149,7 @@ void CServerGameDLL::ServerActivate( edict_t *pEdictList, int edictCount, int cl void CServerGameDLL::GameServerSteamAPIActivated( void ) { #ifndef NO_STEAM + steamgameserverapicontext->Clear(); steamgameserverapicontext->Init(); if ( steamgameserverapicontext->SteamGameServer() && engine->IsDedicatedServer() ) { @@ -1160,6 +1160,7 @@ void CServerGameDLL::GameServerSteamAPIActivated( void ) #ifdef TF_DLL GCClientSystem()->GameServerActivate(); InventoryManager()->GameServerSteamAPIActivated(); + TFMapsWorkshop()->GameServerSteamAPIActivated(); #endif } @@ -1936,6 +1937,52 @@ void CServerGameDLL::Status( void (*print) (const char *fmt, ...) ) } } +//----------------------------------------------------------------------------- +void CServerGameDLL::PrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize ) +{ +#ifdef TF_DLL + TFMapsWorkshop()->PrepareLevelResources( pszMapName, nMapNameSize, pszMapFile, nMapFileSize ); +#endif // TF_DLL +} + +//----------------------------------------------------------------------------- +IServerGameDLL::ePrepareLevelResourcesResult +CServerGameDLL::AsyncPrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize, + float *flProgress /* = NULL */ ) +{ +#ifdef TF_DLL + return TFMapsWorkshop()->AsyncPrepareLevelResources( pszMapName, nMapNameSize, pszMapFile, nMapFileSize, flProgress ); +#endif // TF_DLL + + if ( flProgress ) + { + *flProgress = 1.f; + } + return IServerGameDLL::ePrepareLevelResources_Prepared; +} + +//----------------------------------------------------------------------------- +IServerGameDLL::eCanProvideLevelResult CServerGameDLL::CanProvideLevel( /* in/out */ char *pMapName, int nMapNameMax ) +{ +#ifdef TF_DLL + return TFMapsWorkshop()->OnCanProvideLevel( pMapName, nMapNameMax ); +#endif // TF_DLL + return IServerGameDLL::eCanProvideLevel_CannotProvide; +} + +//----------------------------------------------------------------------------- +bool CServerGameDLL::IsManualMapChangeOkay( const char **pszReason ) +{ + if ( GameRules() ) + { + return GameRules()->IsManualMapChangeOkay( pszReason ); + } + + return true; +} + //----------------------------------------------------------------------------- // Purpose: Called during a transition, to build a map adjacency list //----------------------------------------------------------------------------- @@ -2648,7 +2695,7 @@ void CServerGameClients::ClientActive( edict_t *pEdict, bool bLoadGame ) #if defined( TF_DLL ) Assert( pPlayer ); - if ( pPlayer && !pPlayer->IsFakeClient() ) + if ( pPlayer && !pPlayer->IsFakeClient() && !pPlayer->IsHLTV() && !pPlayer->IsReplay() ) { CSteamID steamID; if ( pPlayer->GetSteamID( &steamID ) ) @@ -2657,7 +2704,10 @@ void CServerGameClients::ClientActive( edict_t *pEdict, bool bLoadGame ) } else { - Log("WARNING: ClientActive, but we don't know his SteamID?\n"); + if ( !pPlayer->IsReplay() && !pPlayer->IsHLTV() ) + { + Log("WARNING: ClientActive, but we don't know his SteamID?\n"); + } } } #endif @@ -2731,7 +2781,10 @@ void CServerGameClients::ClientDisconnect( edict_t *pEdict ) } else { - Log("WARNING: ClientDisconnected, but we don't know his SteamID?\n"); + if ( !player->IsReplay() && !player->IsHLTV() ) + { + Log("WARNING: ClientDisconnected, but we don't know his SteamID?\n"); + } } } #endif diff --git a/mp/src/game/server/gameinterface.h b/mp/src/game/server/gameinterface.h index 91d6534c..3092d4f3 100644 --- a/mp/src/game/server/gameinterface.h +++ b/mp/src/game/server/gameinterface.h @@ -139,7 +139,19 @@ public: virtual const char *GetServerBrowserGameData() OVERRIDE; // Called to add output to the status command - virtual void Status( void (*print) (const char *fmt, ...) ); + virtual void Status( void (*print) (const char *fmt, ...) ) OVERRIDE; + + virtual void PrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize ) OVERRIDE; + + virtual ePrepareLevelResourcesResult AsyncPrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize, + float *flProgress = NULL ) OVERRIDE; + + virtual eCanProvideLevelResult CanProvideLevel( /* in/out */ char *pMapName, int nMapNameMax ) OVERRIDE; + + // Called to see if the game server is okay with a manual changelevel or map command + virtual bool IsManualMapChangeOkay( const char **pszReason ) OVERRIDE; private: diff --git a/mp/src/game/server/items.h b/mp/src/game/server/items.h index 5e7672c6..bc1bb77e 100644 --- a/mp/src/game/server/items.h +++ b/mp/src/game/server/items.h @@ -82,9 +82,10 @@ public: DECLARE_DATADESC(); protected: virtual void ComeToRest( void ); + bool m_bActivateWhenAtRest; private: - bool m_bActivateWhenAtRest; + COutputEvent m_OnPlayerTouch; COutputEvent m_OnCacheInteraction; diff --git a/mp/src/game/server/nav_area.cpp b/mp/src/game/server/nav_area.cpp index 335e6c3b..656f675d 100644 --- a/mp/src/game/server/nav_area.cpp +++ b/mp/src/game/server/nav_area.cpp @@ -3707,7 +3707,7 @@ static Vector FindPositionInArea( CNavArea *area, NavCornerType corner ) pos = cornerPos + Vector( area->GetSizeX()*0.5f*multX, area->GetSizeY()*0.5f*multY, 0.0f ); if ( !area->IsOverlapping( pos ) ) { - AssertMsg( false, UTIL_VarArgs( "A Hiding Spot can't be placed on its area at (%.0f %.0f %.0f)", cornerPos.x, cornerPos.y, cornerPos.z) ); + AssertMsg( false, "A Hiding Spot can't be placed on its area at (%.0f %.0f %.0f)", cornerPos.x, cornerPos.y, cornerPos.z ); // Just pull the position to a small offset pos = cornerPos + Vector( 1.0f*multX, 1.0f*multY, 0.0f ); @@ -4285,6 +4285,9 @@ bool CNavArea::ComputeLighting( void ) //-------------------------------------------------------------------------------------------------------------- CON_COMMAND_F( nav_update_lighting, "Recomputes lighting values", FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + int numComputed = 0; if ( args.ArgC() == 2 ) { diff --git a/mp/src/game/server/nav_area.h b/mp/src/game/server/nav_area.h index 3defa888..0c97a662 100644 --- a/mp/src/game/server/nav_area.h +++ b/mp/src/game/server/nav_area.h @@ -823,14 +823,9 @@ inline bool CNavArea::IsDegenerate( void ) const //-------------------------------------------------------------------------------------------------------------- inline CNavArea *CNavArea::GetAdjacentArea( NavDirType dir, int i ) const { - for( int iter = 0; iter < m_connect[dir].Count(); ++iter ) - { - if (i == 0) - return m_connect[dir][iter].area; - --i; - } - - return NULL; + if ( ( i < 0 ) || ( i >= m_connect[dir].Count() ) ) + return NULL; + return m_connect[dir][i].area; } //-------------------------------------------------------------------------------------------------------------- diff --git a/mp/src/game/server/nav_entities.cpp b/mp/src/game/server/nav_entities.cpp index 83a7dd83..04951113 100644 --- a/mp/src/game/server/nav_entities.cpp +++ b/mp/src/game/server/nav_entities.cpp @@ -91,8 +91,7 @@ void CFuncNavCost::Spawn( void ) // chop space-delimited string into individual tokens if ( tags ) { - char *buffer = new char [ strlen( tags ) + 1 ]; - Q_strcpy( buffer, tags ); + char *buffer = V_strdup ( tags ); for( char *token = strtok( buffer, " " ); token; token = strtok( NULL, " " ) ) { diff --git a/mp/src/game/server/nav_file.cpp b/mp/src/game/server/nav_file.cpp index 7de114ec..ea3bf5ad 100644 --- a/mp/src/game/server/nav_file.cpp +++ b/mp/src/game/server/nav_file.cpp @@ -1318,12 +1318,11 @@ const CUtlVector< Place > *CNavMesh::GetPlacesFromNavFile( bool *hasUnnamedPlace if ( IsX360() ) { // 360 has compressed NAVs - CLZMA lzma; - if ( lzma.IsCompressed( (unsigned char *)fileBuffer.Base() ) ) + if ( CLZMA::IsCompressed( (unsigned char *)fileBuffer.Base() ) ) { - int originalSize = lzma.GetActualSize( (unsigned char *)fileBuffer.Base() ); + int originalSize = CLZMA::GetActualSize( (unsigned char *)fileBuffer.Base() ); unsigned char *pOriginalData = new unsigned char[originalSize]; - lzma.Uncompress( (unsigned char *)fileBuffer.Base(), pOriginalData ); + CLZMA::Uncompress( (unsigned char *)fileBuffer.Base(), pOriginalData ); fileBuffer.AssumeMemory( pOriginalData, originalSize, originalSize, CUtlBuffer::READ_ONLY ); } } @@ -1411,12 +1410,11 @@ NavErrorType CNavMesh::Load( void ) if ( IsX360() ) { // 360 has compressed NAVs - CLZMA lzma; - if ( lzma.IsCompressed( (unsigned char *)fileBuffer.Base() ) ) + if ( CLZMA::IsCompressed( (unsigned char *)fileBuffer.Base() ) ) { - int originalSize = lzma.GetActualSize( (unsigned char *)fileBuffer.Base() ); + int originalSize = CLZMA::GetActualSize( (unsigned char *)fileBuffer.Base() ); unsigned char *pOriginalData = new unsigned char[originalSize]; - lzma.Uncompress( (unsigned char *)fileBuffer.Base(), pOriginalData ); + CLZMA::Uncompress( (unsigned char *)fileBuffer.Base(), pOriginalData ); fileBuffer.AssumeMemory( pOriginalData, originalSize, originalSize, CUtlBuffer::READ_ONLY ); } } diff --git a/mp/src/game/server/nav_generate.cpp b/mp/src/game/server/nav_generate.cpp index be9ce6b5..e10d01ea 100644 --- a/mp/src/game/server/nav_generate.cpp +++ b/mp/src/game/server/nav_generate.cpp @@ -1229,9 +1229,12 @@ void CNavMesh::RemoveOverlappingObstacleTopAreas() static void CommandNavCheckStairs( void ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + TheNavMesh->MarkStairAreas(); } -static ConCommand nav_check_stairs( "nav_check_stairs", CommandNavCheckStairs, "Update the nav mesh STAIRS attribute" ); +static ConCommand nav_check_stairs( "nav_check_stairs", CommandNavCheckStairs, "Update the nav mesh STAIRS attribute", FCVAR_CHEAT ); //-------------------------------------------------------------------------------------------------------------- /** @@ -1445,6 +1448,9 @@ bool CNavArea::TestStairs( void ) //-------------------------------------------------------------------------------------------------------------- CON_COMMAND_F( nav_test_stairs, "Test the selected set for being on stairs", FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + int count = 0; const NavAreaVector &selectedSet = TheNavMesh->GetSelectedSet(); @@ -4932,5 +4938,8 @@ void CNavMesh::PostProcessCliffAreas() CON_COMMAND_F( nav_gen_cliffs_approx, "Mark cliff areas, post-processing approximation", FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + TheNavMesh->PostProcessCliffAreas(); } diff --git a/mp/src/game/server/nav_mesh.cpp b/mp/src/game/server/nav_mesh.cpp index 4c38a6f5..09326aaf 100644 --- a/mp/src/game/server/nav_mesh.cpp +++ b/mp/src/game/server/nav_mesh.cpp @@ -1700,6 +1700,9 @@ static ConCommand nav_clear_selected_set( "nav_clear_selected_set", CommandNavCl //---------------------------------------------------------------------------------- CON_COMMAND_F( nav_dump_selected_set_positions, "Write the (x,y,z) coordinates of the centers of all selected nav areas to a file.", FCVAR_GAMEDLL | FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + const NavAreaVector &selectedSet = TheNavMesh->GetSelectedSet(); CUtlBuffer fileBuffer( 4096, 1024*1024, CUtlBuffer::TEXT_BUFFER ); @@ -1732,6 +1735,9 @@ CON_COMMAND_F( nav_dump_selected_set_positions, "Write the (x,y,z) coordinates o //---------------------------------------------------------------------------------- CON_COMMAND_F( nav_show_dumped_positions, "Show the (x,y,z) coordinate positions of the given dump file.", FCVAR_GAMEDLL | FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + CUtlBuffer fileBuffer( 4096, 1024*1024, CUtlBuffer::TEXT_BUFFER ); // filename is local to game dir for Steam, so we need to prepend game dir for regular file save @@ -1764,6 +1770,9 @@ CON_COMMAND_F( nav_show_dumped_positions, "Show the (x,y,z) coordinate positions //---------------------------------------------------------------------------------- CON_COMMAND_F( nav_select_larger_than, "Select nav areas where both dimensions are larger than the given size.", FCVAR_GAMEDLL | FCVAR_CHEAT ) { + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + if ( args.ArgC() > 1 ) { float minSize = atof( args[1] ); @@ -2665,6 +2674,9 @@ void CNavMesh::CommandNavMarkWalkable( void ) { Vector pos; + if ( !UTIL_IsCommandIssuedByServerAdmin() ) + return; + if (nav_edit.GetBool()) { // we are in edit mode, use the edit cursor's location diff --git a/mp/src/game/server/networkstringtable_gamedll.h b/mp/src/game/server/networkstringtable_gamedll.h index 9dbce97a..20965aa7 100644 --- a/mp/src/game/server/networkstringtable_gamedll.h +++ b/mp/src/game/server/networkstringtable_gamedll.h @@ -28,7 +28,7 @@ class CStringTableSaveRestoreOps; #define MAX_CHOREO_SCENES_STRINGS ( 1 << MAX_CHOREO_SCENES_STRING_BITS ) #define CHOREO_SCENES_INVALID_STRING ( MAX_CHOREO_SCENES_STRINGS - 1 ) -#define MAX_PARTICLESYSTEMS_STRING_BITS 11 +#define MAX_PARTICLESYSTEMS_STRING_BITS 12 #define MAX_PARTICLESYSTEMS_STRINGS ( 1 << MAX_PARTICLESYSTEMS_STRING_BITS ) #define PARTICLESYSTEMS_INVALID_STRING ( MAX_PARTICLESYSTEMS_STRINGS - 1 ) diff --git a/mp/src/game/server/player.cpp b/mp/src/game/server/player.cpp index a44ee551..e0e7ccd2 100644 --- a/mp/src/game/server/player.cpp +++ b/mp/src/game/server/player.cpp @@ -585,7 +585,9 @@ CBasePlayer::CBasePlayer( ) m_bForceOrigin = false; m_hVehicle = NULL; m_pCurrentCommand = NULL; - + m_iLockViewanglesTickNumber = 0; + m_qangLockViewangles.Init(); + // Setup our default FOV m_iDefaultFOV = g_pGameRules->DefaultFOV(); @@ -976,7 +978,7 @@ void CBasePlayer::DamageEffect(float flDamage, int fDamageType) } else if (fDamageType & DMG_DROWN) { - //Red damage indicator + //Blue damage indicator color32 blue = {0,0,128,128}; UTIL_ScreenFade( this, blue, 1.0f, 0.1f, FFADE_IN ); } @@ -2325,6 +2327,7 @@ bool CBasePlayer::SetObserverMode(int mode ) break; case OBS_MODE_CHASE : + case OBS_MODE_POI: // PASSTIME case OBS_MODE_IN_EYE : // udpate FOV and viewmodels SetObserverTarget( m_hObserverTarget ); @@ -2420,8 +2423,7 @@ void CBasePlayer::CheckObserverSettings() } // check if our spectating target is still a valid one - - if ( m_iObserverMode == OBS_MODE_IN_EYE || m_iObserverMode == OBS_MODE_CHASE || m_iObserverMode == OBS_MODE_FIXED ) + if ( m_iObserverMode == OBS_MODE_IN_EYE || m_iObserverMode == OBS_MODE_CHASE || m_iObserverMode == OBS_MODE_FIXED || m_iObserverMode == OBS_MODE_POI ) { ValidateCurrentObserverTarget(); @@ -2633,7 +2635,10 @@ bool CBasePlayer::SetObserverTarget(CBaseEntity *target) Vector dir, end; Vector start = target->EyePosition(); - AngleVectors( target->EyeAngles(), &dir ); + QAngle ang = target->EyeAngles(); + ang.z = 0; // PASSTIME no view roll when spectating ball + + AngleVectors( ang, &dir ); VectorNormalize( dir ); VectorMA( start, -64.0f, dir, end ); @@ -2643,7 +2648,7 @@ bool CBasePlayer::SetObserverTarget(CBaseEntity *target) trace_t tr; UTIL_TraceRay( ray, MASK_PLAYERSOLID, target, COLLISION_GROUP_PLAYER_MOVEMENT, &tr ); - JumptoPosition( tr.endpos, target->EyeAngles() ); + JumptoPosition( tr.endpos, ang ); } return true; @@ -3411,6 +3416,8 @@ void CBasePlayer::ForceSimulation() m_nSimulationTick = -1; } +ConVar sv_usercmd_custom_random_seed( "sv_usercmd_custom_random_seed", "1", FCVAR_CHEAT, "When enabled server will populate an additional random seed independent of the client" ); + //----------------------------------------------------------------------------- // Purpose: // Input : *buf - @@ -3437,6 +3444,16 @@ void CBasePlayer::ProcessUsercmds( CUserCmd *cmds, int numcmds, int totalcmds, pCmd->MakeInert(); } + if ( sv_usercmd_custom_random_seed.GetBool() ) + { + float fltTimeNow = float( Plat_FloatTime() * 1000.0 ); + pCmd->server_random_seed = *reinterpret_cast( (char*)&fltTimeNow ); + } + else + { + pCmd->server_random_seed = pCmd->random_seed; + } + ctx->cmds.AddToTail( *pCmd ); } ctx->numcmds = numcmds; @@ -7875,7 +7892,7 @@ void CMovementSpeedMod::InputSpeedMod(inputdata_t &data) // Bring the weapon back if ( HasSpawnFlags( SF_SPEED_MOD_SUPPRESS_WEAPONS ) && pPlayer->GetActiveWeapon() == NULL ) { - pPlayer->SetActiveWeapon( pPlayer->Weapon_GetLast() ); + pPlayer->SetActiveWeapon( pPlayer->GetLastWeapon() ); if ( pPlayer->GetActiveWeapon() ) { pPlayer->GetActiveWeapon()->Deploy(); @@ -8857,8 +8874,6 @@ void CBasePlayer::SetPlayerName( const char *name ) Assert( strlen(name) > 0 ); Q_strncpy( m_szNetname, name, sizeof(m_szNetname) ); - // Be extra thorough - Q_RemoveAllEvilCharacters( m_szNetname ); } } @@ -9386,4 +9401,4 @@ uint64 CBasePlayer::GetSteamIDAsUInt64( void ) return steamIDForPlayer.ConvertToUint64(); return 0; } -#endif // NO_STEAM \ No newline at end of file +#endif // NO_STEAM diff --git a/mp/src/game/server/player.h b/mp/src/game/server/player.h index 8edefff3..e87af06d 100644 --- a/mp/src/game/server/player.h +++ b/mp/src/game/server/player.h @@ -415,7 +415,7 @@ public: virtual bool Weapon_ShouldSetLast( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ) { return true; } virtual bool Weapon_ShouldSelectItem( CBaseCombatWeapon *pWeapon ); void Weapon_DropSlot( int weaponSlot ); - CBaseCombatWeapon *Weapon_GetLast( void ) { return m_hLastWeapon.Get(); } + CBaseCombatWeapon *GetLastWeapon( void ) { return m_hLastWeapon.Get(); } virtual void OnMyWeaponFired( CBaseCombatWeapon *weapon ); // call this when this player fires a weapon to allow other systems to react virtual float GetTimeSinceWeaponFired( void ) const; // returns the time, in seconds, since this player fired a weapon @@ -735,6 +735,8 @@ public: bool IsPredictingWeapons( void ) const; int CurrentCommandNumber() const; const CUserCmd *GetCurrentUserCommand() const; + int GetLockViewanglesTickNumber() const { return m_iLockViewanglesTickNumber; } + QAngle GetLockViewanglesData() const { return m_qangLockViewangles; } int GetFOV( void ); // Get the current FOV value int GetDefaultFOV( void ) const; // Default FOV if not specified otherwise @@ -891,7 +893,8 @@ public: #if defined USES_ECON_ITEMS CEconWearable *GetWearable( int i ) { return m_hMyWearables[i]; } - int GetNumWearables( void ) { return m_hMyWearables.Count(); } + const CEconWearable *GetWearable( int i ) const { return m_hMyWearables[i]; } + int GetNumWearables( void ) const { return m_hMyWearables.Count(); } #endif private: @@ -1058,6 +1061,8 @@ protected: // Last received usercmd (in case we drop a lot of packets ) CUserCmd m_LastCmd; CUserCmd *m_pCurrentCommand; + int m_iLockViewanglesTickNumber; + QAngle m_qangLockViewangles; float m_flStepSoundTime; // time to check for next footstep sound diff --git a/mp/src/game/server/player_command.cpp b/mp/src/game/server/player_command.cpp index b607bbab..bf77b5d4 100644 --- a/mp/src/game/server/player_command.cpp +++ b/mp/src/game/server/player_command.cpp @@ -23,6 +23,7 @@ extern CMoveData *g_pMoveData; // This is a global because it is subclassed by e extern ConVar sv_noclipduringpause; ConVar sv_maxusrcmdprocessticks_warning( "sv_maxusrcmdprocessticks_warning", "-1", FCVAR_NONE, "Print a warning when user commands get dropped due to insufficient usrcmd ticks allocated, number of seconds to throttle, negative disabled" ); +static ConVar sv_maxusrcmdprocessticks_holdaim( "sv_maxusrcmdprocessticks_holdaim", "1", FCVAR_CHEAT, "Hold client aim for multiple server sim ticks when client-issued usrcmd contains multiple actions (0: off; 1: hold this server tick; 2+: hold multiple ticks)" ); //----------------------------------------------------------------------------- // Purpose: @@ -442,6 +443,12 @@ void CPlayerMove::RunCommand ( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper // Copy output FinishMove( player, ucmd, g_pMoveData ); + // If we have to restore the view angle then do so right now + if ( !player->IsBot() && ( gpGlobals->tickcount - player->GetLockViewanglesTickNumber() < sv_maxusrcmdprocessticks_holdaim.GetInt() ) ) + { + player->pl.v_angle = player->GetLockViewanglesData(); + } + // Let server invoke any needed impact functions VPROF_SCOPE_BEGIN( "moveHelper->ProcessImpacts" ); moveHelper->ProcessImpacts(); diff --git a/mp/src/game/server/point_spotlight.cpp b/mp/src/game/server/point_spotlight.cpp index 9ff28cf6..030537ed 100644 --- a/mp/src/game/server/point_spotlight.cpp +++ b/mp/src/game/server/point_spotlight.cpp @@ -56,6 +56,7 @@ private: private: bool m_bSpotlightOn; bool m_bEfficientSpotlight; + bool m_bIgnoreSolid; Vector m_vSpotlightTargetPos; Vector m_vSpotlightCurrentPos; Vector m_vSpotlightDir; @@ -88,6 +89,7 @@ BEGIN_DATADESC( CPointSpotlight ) DEFINE_FIELD( m_vSpotlightDir, FIELD_VECTOR ), DEFINE_FIELD( m_nHaloSprite, FIELD_INTEGER ), + DEFINE_KEYFIELD( m_bIgnoreSolid, FIELD_BOOLEAN, "IgnoreSolid" ), DEFINE_KEYFIELD( m_flSpotlightMaxLength,FIELD_FLOAT, "SpotlightLength"), DEFINE_KEYFIELD( m_flSpotlightGoalWidth,FIELD_FLOAT, "SpotlightWidth"), DEFINE_KEYFIELD( m_flHDRColorScale, FIELD_FLOAT, "HDRColorScale" ), @@ -118,6 +120,7 @@ CPointSpotlight::CPointSpotlight() #endif m_flHDRColorScale = 1.0f; m_nMinDXLevel = 0; + m_bIgnoreSolid = false; } @@ -332,12 +335,21 @@ void CPointSpotlight::SpotlightCreate(void) AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_vSpotlightDir * m_flSpotlightMaxLength, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr); + Vector vTargetPos; + if ( m_bIgnoreSolid ) + { + vTargetPos = GetAbsOrigin() + m_vSpotlightDir * m_flSpotlightMaxLength; + } + else + { + trace_t tr; + UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + m_vSpotlightDir * m_flSpotlightMaxLength, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); + vTargetPos = tr.endpos; + } m_hSpotlightTarget = (CSpotlightEnd*)CreateEntityByName( "spotlight_end" ); m_hSpotlightTarget->Spawn(); - m_hSpotlightTarget->SetAbsOrigin( tr.endpos ); + m_hSpotlightTarget->SetAbsOrigin( vTargetPos ); m_hSpotlightTarget->SetOwnerEntity( this ); m_hSpotlightTarget->m_clrRender = m_clrRender; m_hSpotlightTarget->m_Radius = m_flSpotlightMaxLength; @@ -381,9 +393,17 @@ Vector CPointSpotlight::SpotlightCurrentPos(void) AngleVectors( GetAbsAngles(), &m_vSpotlightDir ); // Get beam end point. Only collide with solid objects, not npcs - trace_t tr; - UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + (m_vSpotlightDir * 2 * m_flSpotlightMaxLength), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); - return tr.endpos; + Vector vEndPos = GetAbsOrigin() + ( m_vSpotlightDir * 2 * m_flSpotlightMaxLength ); + if ( m_bIgnoreSolid ) + { + return vEndPos; + } + else + { + trace_t tr; + UTIL_TraceLine( GetAbsOrigin(), vEndPos, MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr ); + return tr.endpos; + } } //------------------------------------------------------------------------------ diff --git a/mp/src/game/server/props.cpp b/mp/src/game/server/props.cpp index 648191db..9ba6c11b 100644 --- a/mp/src/game/server/props.cpp +++ b/mp/src/game/server/props.cpp @@ -1811,6 +1811,8 @@ LINK_ENTITY_TO_CLASS( dynamic_prop, CDynamicProp ); LINK_ENTITY_TO_CLASS( prop_dynamic, CDynamicProp ); LINK_ENTITY_TO_CLASS( prop_dynamic_override, CDynamicProp ); +IMPLEMENT_AUTO_LIST( IPhysicsPropAutoList ); + BEGIN_DATADESC( CDynamicProp ) // Fields diff --git a/mp/src/game/server/props.h b/mp/src/game/server/props.h index 8db20f2f..7dc9f48a 100644 --- a/mp/src/game/server/props.h +++ b/mp/src/game/server/props.h @@ -327,7 +327,8 @@ protected: //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -class CPhysicsProp : public CBreakableProp +DECLARE_AUTO_LIST( IPhysicsPropAutoList ); +class CPhysicsProp : public CBreakableProp, public IPhysicsPropAutoList { DECLARE_CLASS( CPhysicsProp, CBreakableProp ); DECLARE_SERVERCLASS(); diff --git a/mp/src/game/server/recipientfilter.cpp b/mp/src/game/server/recipientfilter.cpp index d39419c3..64889b31 100644 --- a/mp/src/game/server/recipientfilter.cpp +++ b/mp/src/game/server/recipientfilter.cpp @@ -341,7 +341,7 @@ CTeamRecipientFilter::CTeamRecipientFilter( int team, bool isReliable ) if ( pPlayer->GetTeamNumber() != team ) { //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets. - if ( pPlayer->GetTeamNumber() == TEAM_SPECTATOR && (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE || pPlayer->GetObserverMode() == OBS_MODE_CHASE) ) + if ( pPlayer->GetTeamNumber() == TEAM_SPECTATOR && (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE || pPlayer->GetObserverMode() == OBS_MODE_CHASE || pPlayer->GetObserverMode() == OBS_MODE_POI) ) { if ( pPlayer->GetObserverTarget() ) { diff --git a/mp/src/game/server/sceneentity.cpp b/mp/src/game/server/sceneentity.cpp index ccdc4cd4..f092624f 100644 --- a/mp/src/game/server/sceneentity.cpp +++ b/mp/src/game/server/sceneentity.cpp @@ -4951,8 +4951,9 @@ void CSceneManager::RemoveScenesInvolvingActor( CBaseFlex *pActor ) if ( !pActor ) return; + // This loop can remove items from m_ActiveScenes array, so loop through backwards. int c = m_ActiveScenes.Count(); - for ( int i = 0; i < c; i++ ) + for ( int i = c - 1 ; i >= 0; --i ) { CSceneEntity *pScene = m_ActiveScenes[ i ].Get(); if ( !pScene ) diff --git a/mp/src/game/server/slideshow_display.cpp b/mp/src/game/server/slideshow_display.cpp index 79e78841..12e19ceb 100644 --- a/mp/src/game/server/slideshow_display.cpp +++ b/mp/src/game/server/slideshow_display.cpp @@ -528,8 +528,8 @@ void CSlideshowDisplay::BuildSlideShowImagesList( void ) if ( bLoaded ) { - char szKeywords[ 256 ]; - Q_strcpy( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) ); + char szKeywords[ 256 ] = {0}; + V_strcpy_safe( szKeywords, pMaterialKeys->GetString( "%keywords", "" ) ); char *pchKeyword = szKeywords; @@ -562,7 +562,7 @@ void CSlideshowDisplay::BuildSlideShowImagesList( void ) { // Couldn't find the list, so create it iList = m_SlideKeywordList.AddToTail( new SlideKeywordList_t ); - Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, pchKeyword ); + V_strcpy_safe( m_SlideKeywordList[iList]->szSlideKeyword, pchKeyword ); } pchKeyword = pNextKeyword; @@ -581,7 +581,7 @@ void CSlideshowDisplay::BuildSlideShowImagesList( void ) { // Couldn't find the generic list, so create it iList = m_SlideKeywordList.AddToHead( new SlideKeywordList_t ); - Q_strcpy( m_SlideKeywordList[ iList ]->szSlideKeyword, "" ); + V_strcpy_safe( m_SlideKeywordList[iList]->szSlideKeyword, "" ); } if ( IsX360() ) diff --git a/mp/src/game/server/team_control_point.cpp b/mp/src/game/server/team_control_point.cpp index 1bbec70a..a1288ad7 100644 --- a/mp/src/game/server/team_control_point.cpp +++ b/mp/src/game/server/team_control_point.cpp @@ -17,6 +17,7 @@ #ifdef TF_DLL #include "tf_shareddefs.h" +#include "tf_gamerules.h" #endif #define CONTROL_POINT_UNLOCK_THINK "UnlockThink" @@ -269,6 +270,7 @@ void CTeamControlPoint::Precache( void ) #ifdef TF_DLL PrecacheScriptSound( "Announcer.ControlPointContested" ); + PrecacheScriptSound( "Announcer.ControlPointContested_Neutral" ); #endif } @@ -653,7 +655,15 @@ void CTeamControlPoint::InternalSetOwner( int iCapTeam, bool bMakeSound, int iNu Assert( playerIndex > 0 && playerIndex <= gpGlobals->maxClients ); - PlayerCapped( ToBaseMultiplayerPlayer(UTIL_PlayerByIndex( playerIndex )) ); + CBaseMultiplayerPlayer *pPlayer = ToBaseMultiplayerPlayer( UTIL_PlayerByIndex( playerIndex ) ); + PlayerCapped( pPlayer ); + +#ifdef TF_DLL + if ( TFGameRules() && TFGameRules()->IsHolidayActive( kHoliday_EOTL ) ) + { + TFGameRules()->DropBonusDuck( pPlayer->GetAbsOrigin(), ToTFPlayer( pPlayer ), NULL, NULL, false, true ); + } +#endif } // Remap team to get first game team = 1 @@ -733,7 +743,7 @@ void CTeamControlPoint::SendCapString( int iCapTeam, int iNumCappingPlayers, int //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -void CTeamControlPoint::CaptureBlocked( CBaseMultiplayerPlayer *pPlayer ) +void CTeamControlPoint::CaptureBlocked( CBaseMultiplayerPlayer *pPlayer, CBaseMultiplayerPlayer *pVictim ) { if( strlen( STRING(m_iszPrintName) ) <= 0 ) return; @@ -746,6 +756,10 @@ void CTeamControlPoint::CaptureBlocked( CBaseMultiplayerPlayer *pPlayer ) event->SetString( "cpname", STRING(m_iszPrintName) ); event->SetInt( "blocker", pPlayer->entindex() ); event->SetInt( "priority", 9 ); + if ( pVictim ) + { + event->SetInt( "victim", pVictim->entindex() ); + } gameeventmanager->FireEvent( event ); } diff --git a/mp/src/game/server/team_control_point.h b/mp/src/game/server/team_control_point.h index 816a3ac1..bfcfe100 100644 --- a/mp/src/game/server/team_control_point.h +++ b/mp/src/game/server/team_control_point.h @@ -82,7 +82,7 @@ public: void SetCappersRequiredForTeam( int iGameTeam, int iCappers ); - void CaptureBlocked( CBaseMultiplayerPlayer *pPlayer ); + void CaptureBlocked( CBaseMultiplayerPlayer *pPlayer, CBaseMultiplayerPlayer *pVictim ); int PointValue( void ); diff --git a/mp/src/game/server/team_control_point_master.cpp b/mp/src/game/server/team_control_point_master.cpp index 956f7ddb..9b007e06 100644 --- a/mp/src/game/server/team_control_point_master.cpp +++ b/mp/src/game/server/team_control_point_master.cpp @@ -1056,65 +1056,44 @@ bool CTeamControlPointMaster::IsBaseControlPoint( int iPointIndex ) int CTeamControlPointMaster::GetBaseControlPoint( int iTeam ) { int iRetVal = -1; - int nLowestValue = 999, nHighestValue = -1; - int iLowestIndex = 0, iHighestIndex = 0; + int nLowestValue = 999; + int nHighestValue = -1; + CTeamControlPoint *pLowestPoint = NULL; + CTeamControlPoint *pHighestPoint = NULL; - for( int i = 0 ; i < (int)m_ControlPoints.Count() ; i++ ) + for( unsigned int i = 0 ; i < m_ControlPoints.Count() ; i++ ) { CTeamControlPoint *pPoint = m_ControlPoints[i]; - int iPointIndex = m_ControlPoints[i]->GetPointIndex(); - - if ( PlayingMiniRounds() && iTeam > LAST_SHARED_TEAM ) + if ( !PlayingMiniRounds() || ( IsInRound( pPoint ) && ( iTeam > LAST_SHARED_TEAM ) ) ) { - if ( IsInRound( pPoint ) ) // is this point in the current round? - { - if ( iPointIndex > nHighestValue ) - { - nHighestValue = iPointIndex; - iHighestIndex = i; - } + int nTempValue = pPoint->GetPointIndex(); - if ( iPointIndex < nLowestValue ) - { - nLowestValue = iPointIndex; - iLowestIndex = i; - } - } - } - else - { - if ( pPoint->GetDefaultOwner() != iTeam ) + if ( nTempValue > nHighestValue ) { - continue; + nHighestValue = nTempValue; + pHighestPoint = pPoint; } - // If it's the first or the last point, it's their base - if ( iPointIndex == 0 || iPointIndex == (((int)m_ControlPoints.Count())-1) ) + if ( nTempValue < nLowestValue ) { - iRetVal = iPointIndex; - break; + nLowestValue = nTempValue; + pLowestPoint = pPoint; } } } - if ( PlayingMiniRounds() && iTeam > LAST_SHARED_TEAM ) + if ( pLowestPoint && pHighestPoint ) { - if ( nLowestValue != 999 && nHighestValue != -1 ) + // which point is owned by this team? + if ( ( pLowestPoint->GetDefaultOwner() == iTeam && pHighestPoint->GetDefaultOwner() == iTeam ) || // if the same team owns both, take the highest value to be the last point + ( pHighestPoint->GetDefaultOwner() == iTeam ) ) { - CTeamControlPoint *pLowestPoint = m_ControlPoints[iLowestIndex]; - CTeamControlPoint *pHighestPoint = m_ControlPoints[iHighestIndex]; - - // which point is owned by this team? - if ( ( pLowestPoint->GetDefaultOwner() == iTeam && pHighestPoint->GetDefaultOwner() == iTeam ) || // if the same team owns both, take the highest value to be the last point - ( pHighestPoint->GetDefaultOwner() == iTeam ) ) - { - iRetVal = nHighestValue; - } - else if ( pLowestPoint->GetDefaultOwner() == iTeam ) - { - iRetVal = nLowestValue; - } + iRetVal = nHighestValue; + } + else if ( pLowestPoint->GetDefaultOwner() == iTeam ) + { + iRetVal = nLowestValue; } } diff --git a/mp/src/game/server/team_control_point_master.h b/mp/src/game/server/team_control_point_master.h index 0c229a05..465a67dd 100644 --- a/mp/src/game/server/team_control_point_master.h +++ b/mp/src/game/server/team_control_point_master.h @@ -132,6 +132,7 @@ public: float GetLastOwnershipChangeTime( void ) { return m_flLastOwnershipChangeTime; } int GetCurrentRoundIndex() { return m_iCurrentRoundIndex; } + bool ShouldSwitchTeamsOnRoundWin( void ) { return m_bSwitchTeamsOnWin; } private: void EXPORT CPMThink( void ); diff --git a/mp/src/game/server/trigger_area_capture.cpp b/mp/src/game/server/trigger_area_capture.cpp index 648a3b86..979ef4bc 100644 --- a/mp/src/game/server/trigger_area_capture.cpp +++ b/mp/src/game/server/trigger_area_capture.cpp @@ -535,7 +535,7 @@ void CTriggerAreaCapture::CaptureThink( void ) if ( !bRepeatBlocker ) { - m_hPoint->CaptureBlocked( pBlockingPlayer ); + m_hPoint->CaptureBlocked( pBlockingPlayer, NULL ); // Add this guy to our blocker list int iNew = m_Blockers.AddToTail(); @@ -882,6 +882,12 @@ void CTriggerAreaCapture::EndCapture( int team ) m_nCapturingTeam = TEAM_UNASSIGNED; SetCapTimeRemaining( 0 ); + // play any special cap sounds. need to do this before we update the owner of the point. + if ( TeamplayRoundBasedRules() ) + { + TeamplayRoundBasedRules()->PlaySpecialCapSounds( m_nOwningTeam, m_hPoint.Get() ); + } + //there may have been more than one capper, but only report this one. //he hasn't gotten points yet, and his name will go in the cap string if its needed //first capper gets name sent and points given by flag. @@ -912,12 +918,6 @@ void CTriggerAreaCapture::EndCapture( int team ) } } } - - // play any special cap sounds - if ( TeamplayRoundBasedRules() ) - { - TeamplayRoundBasedRules()->PlaySpecialCapSounds( m_nOwningTeam ); - } } //----------------------------------------------------------------------------- @@ -1140,7 +1140,7 @@ bool CTriggerAreaCapture::CheckIfDeathCausesBlock( CBaseMultiplayerPlayer *pVict if ( bBreakCap ) { - m_hPoint->CaptureBlocked( pKiller ); + m_hPoint->CaptureBlocked( pKiller, pVictim ); //BreakCapture( true ); } diff --git a/mp/src/game/server/triggers.cpp b/mp/src/game/server/triggers.cpp index 742976fb..1e317567 100644 --- a/mp/src/game/server/triggers.cpp +++ b/mp/src/game/server/triggers.cpp @@ -475,6 +475,7 @@ void CBaseTrigger::StartTouch(CBaseEntity *pOther) { // First entity to touch us that passes our filters m_OnStartTouchAll.FireOutput( pOther, this ); + StartTouchAll(); } } } @@ -514,7 +515,10 @@ void CBaseTrigger::EndTouch(CBaseEntity *pOther) else if ( hOther->IsPlayer() && !hOther->IsAlive() ) { #ifdef STAGING_ONLY - AssertMsg( 0, CFmtStr( "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ) ); + if ( !HushAsserts() ) + { + AssertMsg( false, "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ); + } Warning( "Dead player [%s] is still touching this trigger at [%f %f %f]", hOther->GetEntityName().ToCStr(), XYZ( hOther->GetAbsOrigin() ) ); #endif m_hTouchingEntities.Remove( i ); @@ -530,6 +534,7 @@ void CBaseTrigger::EndTouch(CBaseEntity *pOther) if ( !bFoundOtherTouchee /*&& !m_bDisabled*/ ) { m_OnEndTouchAll.FireOutput(pOther, this); + EndTouchAll(); } } } @@ -634,8 +639,8 @@ void CTriggerRemove::Touch( CBaseEntity *pOther ) BEGIN_DATADESC( CTriggerHurt ) // Function Pointers - DEFINE_FUNCTION( RadiationThink ), - DEFINE_FUNCTION( HurtThink ), + DEFINE_FUNCTION( CTriggerHurtShim::RadiationThinkShim ), + DEFINE_FUNCTION( CTriggerHurtShim::HurtThinkShim ), // Fields DEFINE_FIELD( m_flOriginalDamage, FIELD_FLOAT ), @@ -661,6 +666,7 @@ END_DATADESC() LINK_ENTITY_TO_CLASS( trigger_hurt, CTriggerHurt ); +IMPLEMENT_AUTO_LIST( ITriggerHurtAutoList ); //----------------------------------------------------------------------------- // Purpose: Called when spawning, after keyvalues have been handled. @@ -677,7 +683,7 @@ void CTriggerHurt::Spawn( void ) SetThink( NULL ); if (m_bitsDamageInflict & DMG_RADIATION) { - SetThink ( &CTriggerHurt::RadiationThink ); + SetThink ( &CTriggerHurtShim::RadiationThinkShim ); SetNextThink( gpGlobals->curtime + random->RandomFloat(0.0, 0.5) ); } } @@ -723,6 +729,15 @@ bool CTriggerHurt::HurtEntity( CBaseEntity *pOther, float damage ) if ( !pOther->m_takedamage || !PassesTriggerFilters(pOther) ) return false; + // If player is disconnected, we're probably in this routine via the + // PhysicsRemoveTouchedList() function to make sure all Untouch()'s are called for the + // player. Calling TakeDamage() in this case can get into the speaking criteria, which + // will then loop through the control points and the touched list again. We shouldn't + // need to hurt players that are disconnected, so skip all of this... + bool bPlayerDisconnected = pOther->IsPlayer() && ( ((CBasePlayer *)pOther)->IsConnected() == false ); + if ( bPlayerDisconnected ) + return false; + if ( damage < 0 ) { pOther->TakeHealth( -damage, m_bitsDamageInflict ); @@ -862,11 +877,29 @@ void CTriggerHurt::Touch( CBaseEntity *pOther ) { if ( m_pfnThink == NULL ) { - SetThink( &CTriggerHurt::HurtThink ); + SetThink( &CTriggerHurtShim::HurtThinkShim ); SetNextThink( gpGlobals->curtime ); } } +//----------------------------------------------------------------------------- +// Purpose: Checks if this point is in any trigger_hurt zones with positive damage +//----------------------------------------------------------------------------- +bool IsTakingTriggerHurtDamageAtPoint( const Vector &vecPoint ) +{ + for ( int i = 0; i < ITriggerHurtAutoList::AutoList().Count(); i++ ) + { + // Some maps use trigger_hurt with negative values as healing triggers; don't consider those + CTriggerHurt *pTrigger = static_cast( ITriggerHurtAutoList::AutoList()[i] ); + if ( !pTrigger->m_bDisabled && pTrigger->PointIsWithin( vecPoint ) && pTrigger->m_flDamage > 0.f ) + { + return true; + } + } + + return false; +} + // ################################################################################## // >> TriggerMultiple @@ -2310,8 +2343,8 @@ class CTriggerTeleport : public CBaseTrigger public: DECLARE_CLASS( CTriggerTeleport, CBaseTrigger ); - void Spawn( void ); - void Touch( CBaseEntity *pOther ); + virtual void Spawn( void ) OVERRIDE; + virtual void Touch( CBaseEntity *pOther ) OVERRIDE; string_t m_iLandmark; @@ -2326,14 +2359,11 @@ BEGIN_DATADESC( CTriggerTeleport ) END_DATADESC() - - void CTriggerTeleport::Spawn( void ) { InitTrigger(); } - //----------------------------------------------------------------------------- // Purpose: Teleports the entity that touched us to the location of our target, // setting the toucher's angles to our target's angles if they are a @@ -2415,6 +2445,46 @@ void CTriggerTeleport::Touch( CBaseEntity *pOther ) LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity ); +//----------------------------------------------------------------------------- +// Teleport Relative trigger +//----------------------------------------------------------------------------- +class CTriggerTeleportRelative : public CBaseTrigger +{ +public: + DECLARE_CLASS(CTriggerTeleportRelative, CBaseTrigger); + + virtual void Spawn( void ) OVERRIDE; + virtual void Touch( CBaseEntity *pOther ) OVERRIDE; + + Vector m_TeleportOffset; + + DECLARE_DATADESC(); +}; + +LINK_ENTITY_TO_CLASS( trigger_teleport_relative, CTriggerTeleportRelative ); +BEGIN_DATADESC( CTriggerTeleportRelative ) + DEFINE_KEYFIELD( m_TeleportOffset, FIELD_VECTOR, "teleportoffset" ) +END_DATADESC() + + +void CTriggerTeleportRelative::Spawn( void ) +{ + InitTrigger(); +} + +void CTriggerTeleportRelative::Touch( CBaseEntity *pOther ) +{ + if ( !PassesTriggerFilters(pOther) ) + { + return; + } + + const Vector finalPos = m_TeleportOffset + WorldSpaceCenter(); + const Vector *momentum = &vec3_origin; + + pOther->Teleport( &finalPos, NULL, momentum ); +} + //----------------------------------------------------------------------------- // Purpose: Saves the game when the player touches the trigger. Can be enabled or disabled //----------------------------------------------------------------------------- @@ -4822,6 +4892,78 @@ void CServerRagdollTrigger::EndTouch(CBaseEntity *pOther) } } + +//----------------------------------------------------------------------------- +// Purpose: A trigger that adds impulse to touching entities +//----------------------------------------------------------------------------- +class CTriggerApplyImpulse : public CBaseTrigger +{ +public: + DECLARE_CLASS( CTriggerApplyImpulse, CBaseTrigger ); + DECLARE_DATADESC(); + + CTriggerApplyImpulse(); + + void Spawn( void ); + + void InputApplyImpulse( inputdata_t& ); + +private: + Vector m_vecImpulseDir; + float m_flForce; +}; + + +BEGIN_DATADESC( CTriggerApplyImpulse ) + DEFINE_KEYFIELD( m_vecImpulseDir, FIELD_VECTOR, "impulse_dir" ), + DEFINE_KEYFIELD( m_flForce, FIELD_FLOAT, "force" ), + DEFINE_INPUTFUNC( FIELD_VOID, "ApplyImpulse", InputApplyImpulse ), +END_DATADESC() + + +LINK_ENTITY_TO_CLASS( trigger_apply_impulse, CTriggerApplyImpulse ); + + +CTriggerApplyImpulse::CTriggerApplyImpulse() +{ + m_flForce = 300.f; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerApplyImpulse::Spawn() +{ + // Convert pushdir from angles to a vector + Vector vecAbsDir; + QAngle angPushDir = QAngle(m_vecImpulseDir.x, m_vecImpulseDir.y, m_vecImpulseDir.z); + AngleVectors(angPushDir, &vecAbsDir); + + // Transform the vector into entity space + VectorIRotate( vecAbsDir, EntityToWorldTransform(), m_vecImpulseDir ); + + BaseClass::Spawn(); + + InitTrigger(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTriggerApplyImpulse::InputApplyImpulse( inputdata_t& ) +{ + Vector vecImpulse = m_flForce * m_vecImpulseDir; + FOR_EACH_VEC( m_hTouchingEntities, i ) + { + if ( m_hTouchingEntities[i] ) + { + m_hTouchingEntities[i]->ApplyAbsVelocityImpulse( vecImpulse ); + } + } +} + #ifdef HL1_DLL //---------------------------------------------------------------------------------- // func_friction diff --git a/mp/src/game/server/triggers.h b/mp/src/game/server/triggers.h index 7695d08c..6ae7312f 100644 --- a/mp/src/game/server/triggers.h +++ b/mp/src/game/server/triggers.h @@ -68,6 +68,8 @@ public: virtual bool PassesTriggerFilters(CBaseEntity *pOther); virtual void StartTouch(CBaseEntity *pOther); virtual void EndTouch(CBaseEntity *pOther); + virtual void StartTouchAll() {} + virtual void EndTouchAll() {} bool IsTouching( CBaseEntity *pOther ); CBaseEntity *GetTouchedEntityOfType( const char *sClassName ); @@ -164,7 +166,21 @@ protected: // Purpose: Hurts anything that touches it. If the trigger has a targetname, // firing it will toggle state. //----------------------------------------------------------------------------- -class CTriggerHurt : public CBaseTrigger + +// This class is to get around the fact that DEFINE_FUNCTION doesn't like multiple inheritance +class CTriggerHurtShim : public CBaseTrigger +{ + virtual void RadiationThink( void ) = 0; + virtual void HurtThink( void ) = 0; + +public: + + void RadiationThinkShim( void ){ RadiationThink(); } + void HurtThinkShim( void ){ HurtThink(); } +}; + +DECLARE_AUTO_LIST( ITriggerHurtAutoList ); +class CTriggerHurt : public CTriggerHurtShim, public ITriggerHurtAutoList { public: CTriggerHurt() @@ -173,7 +189,7 @@ public: m_flDamageCap = 20.0f; } - DECLARE_CLASS( CTriggerHurt, CBaseTrigger ); + DECLARE_CLASS( CTriggerHurt, CTriggerHurtShim ); void Spawn( void ); void RadiationThink( void ); @@ -207,4 +223,6 @@ public: CUtlVector m_hurtEntities; }; +bool IsTakingTriggerHurtDamageAtPoint( const Vector &vecPoint ); + #endif // TRIGGERS_H diff --git a/mp/src/game/server/util.cpp b/mp/src/game/server/util.cpp index 8cd8f989..4b2008df 100644 --- a/mp/src/game/server/util.cpp +++ b/mp/src/game/server/util.cpp @@ -59,7 +59,7 @@ void DBG_AssertFunction( bool fExpr, const char *szExpr, const char *szFile, int Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n%s", szExpr, szFile, szLine, szMessage); else Q_snprintf(szOut,sizeof(szOut), "ASSERT FAILED:\n %s \n(%s@%d)\n", szExpr, szFile, szLine); - Warning( szOut); + Warning( "%s", szOut); } #endif // DEBUG @@ -161,6 +161,11 @@ IServerNetworkable *CEntityFactoryDictionary::Create( const char *pClassName ) IEntityFactory *pFactory = FindFactory( pClassName ); if ( !pFactory ) { +#ifdef STAGING_ONLY + static ConVarRef tf_bot_use_items( "tf_bot_use_items" ); + if ( tf_bot_use_items.IsValid() && tf_bot_use_items.GetInt() ) + return NULL; +#endif Warning("Attempted to create unknown entity type %s!\n", pClassName ); return NULL; } @@ -568,6 +573,24 @@ CBasePlayer *UTIL_PlayerByIndex( int playerIndex ) return pPlayer; } +CBasePlayer *UTIL_PlayerBySteamID( const CSteamID &steamID ) +{ + CSteamID steamIDPlayer; + for ( int i = 1; i <= gpGlobals->maxClients; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + if ( !pPlayer->GetSteamID( &steamIDPlayer ) ) + continue; + + if ( steamIDPlayer == steamID ) + return pPlayer; + } + return NULL; +} + CBasePlayer* UTIL_PlayerByName( const char *name ) { if ( !name || !name[0] ) diff --git a/mp/src/game/server/util.h b/mp/src/game/server/util.h index 92c341d8..c06cbfe9 100644 --- a/mp/src/game/server/util.h +++ b/mp/src/game/server/util.h @@ -222,6 +222,7 @@ float UTIL_GetSimulationInterval(); // NOTENOTE: Use UTIL_GetLocalPlayer instead of UTIL_PlayerByIndex IF you're in single player // and you want the player. CBasePlayer *UTIL_PlayerByIndex( int playerIndex ); +CBasePlayer *UTIL_PlayerBySteamID( const CSteamID &steamID ); // NOTENOTE: Use this instead of UTIL_PlayerByIndex IF you're in single player // and you want the player. diff --git a/mp/src/game/server/vote_controller.cpp b/mp/src/game/server/vote_controller.cpp index 7dab54bb..a29b449f 100644 --- a/mp/src/game/server/vote_controller.cpp +++ b/mp/src/game/server/vote_controller.cpp @@ -14,6 +14,7 @@ #ifdef TF_DLL #include "tf/tf_gamerules.h" +#include "tf/tf_voteissues.h" #endif // memdbgon must be the last include file in a .cpp file!!! @@ -38,15 +39,15 @@ LINK_ENTITY_TO_CLASS( vote_controller, CVoteController ); CVoteController *g_voteController = NULL; -ConVar sv_vote_timer_duration("sv_vote_timer_duration", "15", FCVAR_DEVELOPMENTONLY, "How long to allow voting on an issue"); -ConVar sv_vote_command_delay("sv_vote_command_delay", "2", FCVAR_DEVELOPMENTONLY, "How long after a vote passes until the action happens", false, 0, true, 4.5); -ConVar sv_allow_votes("sv_allow_votes", "1", FCVAR_NONE, "Allow voting?"); +ConVar sv_vote_timer_duration( "sv_vote_timer_duration", "15", FCVAR_DEVELOPMENTONLY, "How long to allow voting on an issue" ); +ConVar sv_vote_command_delay( "sv_vote_command_delay", "2", FCVAR_DEVELOPMENTONLY, "How long after a vote passes until the action happens", false, 0.f, true, 4.5f ); +ConVar sv_allow_votes( "sv_allow_votes", "1", FCVAR_NONE, "Allow voting?" ); ConVar sv_vote_failure_timer( "sv_vote_failure_timer", "300", FCVAR_NONE, "A vote that fails cannot be re-submitted for this long" ); #ifdef TF_DLL ConVar sv_vote_failure_timer_mvm( "sv_vote_failure_timer_mvm", "120", FCVAR_NONE, "A vote that fails in MvM cannot be re-submitted for this long" ); #endif // TF_DLL -ConVar sv_vote_creation_timer("sv_vote_creation_timer", "120", FCVAR_DEVELOPMENTONLY, "How often someone can individually call a vote."); -ConVar sv_vote_quorum_ratio( "sv_vote_quorum_ratio", "0.6", FCVAR_HIDDEN, "The minimum ratio of players needed to vote on an issue to resolve it.", true, 0.1, true, 1.0 ); +ConVar sv_vote_creation_timer( "sv_vote_creation_timer", "150", FCVAR_NONE, "How long before a player can attempt to call another vote (in seconds)." ); +ConVar sv_vote_quorum_ratio( "sv_vote_quorum_ratio", "0.6", FCVAR_NOTIFY, "The minimum ratio of eligible players needed to pass a vote. Min 0.5, Max 1.0.", true, 0.1f, true, 1.0f ); ConVar sv_vote_allow_spectators( "sv_vote_allow_spectators", "0", FCVAR_NONE, "Allow spectators to vote?" ); ConVar sv_vote_ui_hide_disabled_issues( "sv_vote_ui_hide_disabled_issues", "1", FCVAR_NONE, "Suppress listing of disabled issues in the vote setup screen." ); @@ -61,7 +62,9 @@ public: CVoteControllerSystem( char const *name ) : CAutoGameSystemPerFrame( name ) { SetDefLessFunc( m_mapKickWatchList ); + SetDefLessFunc( m_mapNameLockedList ); m_flNextKickCheckTime = 0.f; + m_flNextNameLockCheckTime = 0.f; } virtual void LevelInitPreEntity() @@ -93,24 +96,7 @@ public: break; // Constantly called code - resume on next pass } - CBasePlayer *pTarget = NULL; - CSteamID steamIDPlayer; - for ( int j = 1; j <= gpGlobals->maxClients; j++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( j ); - if ( !pPlayer ) - continue; - - if ( pPlayer->GetSteamID( &steamIDPlayer ) == false ) - continue; - - if ( steamIDPlayer == m_mapKickWatchList.Key( i ) ) - { - pTarget = pPlayer; - break; - } - } - + CBasePlayer *pTarget = UTIL_PlayerBySteamID( m_mapKickWatchList.Key( i ) ); if ( pTarget ) { // Welcome back @@ -120,11 +106,44 @@ public: m_flNextKickCheckTime = gpGlobals->curtime + 0.2f; } + + // Name lock management + if ( m_flNextNameLockCheckTime < gpGlobals->curtime ) + { + FOR_EACH_MAP( m_mapNameLockedList, i ) + { + CBasePlayer *pPlayer = UTIL_PlayerBySteamID( m_mapNameLockedList.Key( i ) ); + + // Time up? + if ( gpGlobals->curtime > m_mapNameLockedList[i] ) + { + // Disable the lock if they're still here + if ( pPlayer ) + { + engine->ServerCommand( UTIL_VarArgs( "namelockid %d %d\n", pPlayer->GetUserID(), 0 ) ); + } + + // Remove and break - this will re-run in 1 second + m_mapNameLockedList.RemoveAt( i ); + break; + } + // See if they reconnected + else if ( pPlayer && !engine->IsPlayerNameLocked( pPlayer->edict() ) ) + { + engine->ServerCommand( UTIL_VarArgs( "namelockid %d %d\n", pPlayer->GetUserID(), 1 ) ); + } + } + + m_flNextNameLockCheckTime = gpGlobals->curtime + 1.f; + } } } void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ) { + if ( !steamID.IsValid() || !steamID.BIndividualAccount() ) + return; + flDuration = clamp( flDuration, 1.f, (float)k_nKickWatchListMaxDuration ); if ( m_mapKickWatchList.Find( steamID ) == m_mapKickWatchList.InvalidIndex() ) { @@ -132,10 +151,24 @@ public: } } + void AddPlayerToNameLockedList( CSteamID steamID, float flDuration ) + { + if ( !steamID.IsValid() || !steamID.BIndividualAccount() ) + return; + + flDuration = clamp( flDuration, 1.f, (float)k_nKickWatchListMaxDuration ); + if ( m_mapNameLockedList.Find( steamID ) == m_mapNameLockedList.InvalidIndex() ) + { + m_mapNameLockedList.Insert( steamID, ( gpGlobals->curtime + flDuration ) ); + } + } + private: CUtlMap< CSteamID, float > m_mapKickWatchList; + CUtlMap< CSteamID, float > m_mapNameLockedList; float m_flNextKickCheckTime; + float m_flNextNameLockCheckTime; }; CVoteControllerSystem VoteControllerSystem( "CVoteControllerSystem" ); @@ -185,7 +218,7 @@ CON_COMMAND( callvote, "Start a vote on an issue." ) } CBasePlayer *pVoteCaller = UTIL_GetCommandClient(); - if( !pVoteCaller ) + if ( !pVoteCaller ) return; if ( !sv_vote_allow_spectators.GetBool() ) @@ -197,15 +230,21 @@ CON_COMMAND( callvote, "Start a vote on an issue." ) } } - // Prevent spamming commands -#ifndef _DEBUG - int nCooldown = 0; - if ( !g_voteController->CanEntityCallVote( pVoteCaller, nCooldown ) ) + if ( g_voteController->IsVoteActive() ) { - g_voteController->SendVoteCreationFailedMessage( VOTE_FAILED_RATE_EXCEEDED, pVoteCaller, nCooldown ); + ClientPrint( pVoteCaller, HUD_PRINTCENTER, "#GameUI_vote_failed_vote_in_progress" ); + return; + } + + // Ask the controller if this is allowed + int nCooldown = 0; + vote_create_failed_t nError = VOTE_FAILED_GENERIC; + + if ( !g_voteController->CanEntityCallVote( pVoteCaller, nCooldown, nError ) ) + { + g_voteController->SendVoteCreationFailedMessage( nError, pVoteCaller, nCooldown ); return; } -#endif // Parameters char szEmptyDetails[MAX_VOTE_DETAILS_LENGTH]; @@ -214,7 +253,7 @@ CON_COMMAND( callvote, "Start a vote on an issue." ) const char *arg3 = args.ArgC() >= 3 ? args[2] : szEmptyDetails; // If we don't have any arguments, invoke VoteSetup UI - if( args.ArgC() < 2 ) + if ( args.ArgC() < 2 ) { g_voteController->SetupVote( pVoteCaller->entindex() ); return; @@ -252,7 +291,7 @@ void CVoteController::ResetData( void ) m_acceptingVotesTimer.Invalidate(); m_executeCommandTimer.Invalidate(); m_iEntityHoldingVote = -1; - m_iOnlyTeamToVote = TEAM_INVALID; + m_iOnlyTeamToVote = TEAM_UNASSIGNED; m_bIsYesNoVote = true; for( int voteIndex = 0; voteIndex < ARRAYSIZE( m_nVotesCast ); ++voteIndex ) @@ -287,12 +326,25 @@ int CVoteController::UpdateTransmitState( void ) return SetTransmitState( FL_EDICT_ALWAYS ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CVoteController::IsVoteSystemEnabled( void ) +{ +#ifdef TF_DLL + if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() ) + return false; +#endif // TF_DLL + + return sv_allow_votes.GetBool(); +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- bool CVoteController::CanTeamCastVote( int iTeam ) const { - if ( m_iOnlyTeamToVote == TEAM_INVALID ) + if ( m_iOnlyTeamToVote == TEAM_UNASSIGNED ) return true; return iTeam == m_iOnlyTeamToVote; @@ -310,7 +362,7 @@ bool CVoteController::SetupVote( int iEntIndex ) int nIssueCount = 0; // Passing an nIssueCount of 0 triggers a "Voting disabled on server" message in the setup UI - if ( sv_allow_votes.GetBool() ) + if ( IsVoteSystemEnabled() ) { for( int iIndex = 0; iIndex < m_potentialIssues.Count(); ++iIndex ) { @@ -330,28 +382,28 @@ bool CVoteController::SetupVote( int iEntIndex ) filter.MakeReliable(); UserMessageBegin( filter, "VoteSetup" ); WRITE_BYTE( nIssueCount ); + int nMsgSize = 0; for( int iIndex = 0; iIndex < m_potentialIssues.Count(); ++iIndex ) { CBaseIssue *pCurrentIssue = m_potentialIssues[iIndex]; if ( pCurrentIssue ) { - if ( pCurrentIssue->IsEnabled() ) - { - WRITE_STRING( pCurrentIssue->GetTypeString() ); - } - else - { - // Don't send/display disabled issues when set - if ( sv_vote_ui_hide_disabled_issues.GetBool() ) - continue; + // Don't send/display disabled issues when set + if ( !pCurrentIssue->IsEnabled() && sv_vote_ui_hide_disabled_issues.GetBool() ) + continue; - char szDisabledIssueStr[MAX_COMMAND_LENGTH + 12]; - V_strcpy( szDisabledIssueStr, pCurrentIssue->GetTypeString() ); - V_strcat( szDisabledIssueStr, " (Disabled on Server)", sizeof(szDisabledIssueStr) ); + // Don't exceed MAX_USER_MSG_DATA (hack) + nMsgSize += ( V_strlen( pCurrentIssue->GetTypeString() ) + 1 ); + nMsgSize += ( V_strlen( pCurrentIssue->GetTypeStringLocalized() ) + 1 ); + ++nMsgSize; + Assert( nMsgSize <= MAX_USER_MSG_DATA ); + if ( nMsgSize > MAX_USER_MSG_DATA ) + continue; - WRITE_STRING( szDisabledIssueStr ); - } + WRITE_STRING( pCurrentIssue->GetTypeString() ); + WRITE_STRING( pCurrentIssue->GetTypeStringLocalized() ); + WRITE_BYTE( pCurrentIssue->IsEnabled() ); } } @@ -368,29 +420,29 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons // Terrible Hack: Dedicated servers pass 99 as the EntIndex bool bDedicatedServer = ( iEntIndex == DEDICATED_SERVER ) ? true : false; - if( !sv_allow_votes.GetBool() ) + if ( !IsVoteSystemEnabled() ) return false; // Already running a vote? - if( IsVoteActive() ) + if ( IsVoteActive() ) return false; CBasePlayer *pVoteCaller = UTIL_PlayerByIndex( iEntIndex ); - if( !pVoteCaller && !bDedicatedServer ) + if ( !pVoteCaller && !bDedicatedServer ) return false; // Find the issue the user is asking for - for( int issueIndex = 0; issueIndex < m_potentialIssues.Count(); ++issueIndex ) + for ( int issueIndex = 0; issueIndex < m_potentialIssues.Count(); ++issueIndex ) { CBaseIssue *pCurrentIssue = m_potentialIssues[issueIndex]; if ( !pCurrentIssue ) return false; - if( FStrEq( pszTypeString, pCurrentIssue->GetTypeString() ) ) + if ( FStrEq( pszTypeString, pCurrentIssue->GetTypeString() ) ) { vote_create_failed_t nErrorCode = VOTE_FAILED_GENERIC; int nTime = 0; - if( pCurrentIssue->CanCallVote( iEntIndex, pszDetailString, nErrorCode, nTime ) ) + if ( pCurrentIssue->CanCallVote( iEntIndex, pszDetailString, nErrorCode, nTime ) ) { // Establish a bunch of data on this particular issue pCurrentIssue->SetIssueDetails( pszDetailString ); @@ -399,14 +451,7 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons m_iEntityHoldingVote = iEntIndex; if ( !bDedicatedServer ) { - if( pCurrentIssue->IsAllyRestrictedVote() ) - { - m_iOnlyTeamToVote = GetVoterTeam( pVoteCaller ); - } - else - { - m_iOnlyTeamToVote = TEAM_INVALID; - } + m_iOnlyTeamToVote = ( pCurrentIssue->IsTeamRestrictedVote() ) ? GetVoterTeam( pVoteCaller ) : TEAM_UNASSIGNED; } // Now get our choices @@ -442,10 +487,10 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons // Now the vote handling and UI m_nPotentialVotes = pCurrentIssue->CountPotentialVoters(); - m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() ); + m_acceptingVotesTimer.Start( sv_vote_timer_duration.GetFloat() + random->RandomFloat( -1.f, 1.f ) ); // Force the vote holder to agree with a Yes/No vote - if ( m_bIsYesNoVote && !bDedicatedServer ) + if ( pCurrentIssue->IsYesNoVote() && !bDedicatedServer ) { TryCastVote( iEntIndex, "Option1" ); } @@ -458,7 +503,7 @@ bool CVoteController::CreateVote( int iEntIndex, const char *pszTypeString, cons WRITE_BYTE( m_iEntityHoldingVote ); WRITE_STRING( pCurrentIssue->GetDisplayString() ); WRITE_STRING( pCurrentIssue->GetDetailsString() ); - WRITE_BOOL( m_bIsYesNoVote ); + WRITE_BOOL( pCurrentIssue->IsYesNoVote() ); MessageEnd(); if ( !bDedicatedServer ) @@ -506,11 +551,7 @@ void CVoteController::SendVoteFailedToPassMessage( vote_create_failed_t nReason { Assert( m_potentialIssues[m_iActiveIssueIndex] ); - // See if we have a player target. - CBasePlayer *pVoteTarget = m_potentialIssues[m_iActiveIssueIndex]->m_hPlayerTarget; - bool bFakeClient = ( pVoteTarget && ( pVoteTarget->IsFakeClient() || pVoteTarget->IsHLTV() || pVoteTarget->IsReplay() ) ); - - UTIL_LogPrintf( "Vote failed \"%s %s\" with code %i (proxy: %i) \n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString(), (int)nReason, bFakeClient ); + UTIL_LogPrintf( "Vote failed \"%s %s\" with code %i\n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString(), (int)nReason ); CBroadcastRecipientFilter filter; filter.MakeReliable(); @@ -526,24 +567,24 @@ void CVoteController::SendVoteFailedToPassMessage( vote_create_failed_t nReason //----------------------------------------------------------------------------- CVoteController::TryCastVoteResult CVoteController::TryCastVote( int iEntIndex, const char *pszVoteString ) { - if( !sv_allow_votes.GetBool() ) + if ( !IsVoteSystemEnabled() ) return CAST_FAIL_SERVER_DISABLE; - if( iEntIndex >= ARRAYSIZE( m_nVotesCast ) ) + if ( iEntIndex >= ARRAYSIZE( m_nVotesCast ) ) return CAST_FAIL_SYSTEM_ERROR; - if( !IsVoteActive() ) + if ( !IsVoteActive() ) return CAST_FAIL_NO_ACTIVE_ISSUE; - if( m_executeCommandTimer.HasStarted() ) + if ( m_executeCommandTimer.HasStarted() ) return CAST_FAIL_VOTE_CLOSED; - if( m_potentialIssues[m_iActiveIssueIndex] && m_potentialIssues[m_iActiveIssueIndex]->IsAllyRestrictedVote() ) + if ( m_potentialIssues[m_iActiveIssueIndex] && m_potentialIssues[m_iActiveIssueIndex]->IsTeamRestrictedVote() ) { CBaseEntity *pVoteHolder = UTIL_EntityByIndex( m_iEntityHoldingVote ); CBaseEntity *pVoter = UTIL_EntityByIndex( iEntIndex ); - if( ( pVoteHolder == NULL ) || ( pVoter == NULL ) || ( GetVoterTeam( pVoteHolder ) != GetVoterTeam( pVoter ) ) ) + if ( ( pVoteHolder == NULL ) || ( pVoter == NULL ) || ( GetVoterTeam( pVoteHolder ) != GetVoterTeam( pVoter ) ) ) { return CAST_FAIL_TEAM_RESTRICTED; } @@ -552,7 +593,7 @@ CVoteController::TryCastVoteResult CVoteController::TryCastVote( int iEntIndex, // Look for a previous vote int nOldVote = m_nVotesCast[iEntIndex]; #ifndef DEBUG - if( nOldVote != VOTE_UNCAST ) + if ( nOldVote != VOTE_UNCAST ) { return CAST_FAIL_NO_CHANGES; } @@ -644,67 +685,54 @@ void CVoteController::VoteControllerThink( void ) } // Vote time is up - process the result - if( m_acceptingVotesTimer.HasStarted() && m_acceptingVotesTimer.IsElapsed() ) + if ( m_acceptingVotesTimer.HasStarted() && m_acceptingVotesTimer.IsElapsed() ) { m_acceptingVotesTimer.Invalidate(); - int nVoteTally = 0; - for ( int index = 0; index < MAX_VOTE_OPTIONS; index++ ) - { - nVoteTally += m_nVoteOptionCount.Get( index ); - } - - bool bVotePassed = true; - - // for record-keeping + // For GC record-keeping if ( m_potentialIssues[m_iActiveIssueIndex]->IsYesNoVote() ) { m_potentialIssues[m_iActiveIssueIndex]->SetYesNoVoteCount( m_nVoteOptionCount[VOTE_OPTION1], m_nVoteOptionCount[VOTE_OPTION2], m_nPotentialVotes ); } - // Have we exceeded the required ratio of Voted-vs-Abstained? - if ( nVoteTally >= m_nPotentialVotes * sv_vote_quorum_ratio.GetFloat() ) - { - int nWinningVoteOption = GetWinningVoteOption(); - Assert( nWinningVoteOption >= 0 && nWinningVoteOption < m_VoteOptions.Count() ); + bool bVotePassed = false; - if ( nWinningVoteOption >= 0 && nWinningVoteOption < MAX_VOTE_OPTIONS ) + if ( GetNumVotesCast() >= ( m_nPotentialVotes * m_potentialIssues[m_iActiveIssueIndex]->GetQuorumRatio() ) ) + { + int nPassingVoteOptionIndex = GetVoteIssueIndexWithHighestCount(); + if ( nPassingVoteOptionIndex >= 0 && nPassingVoteOptionIndex < MAX_VOTE_OPTIONS ) { - // YES/NO VOTES + // YES/NO VOTES - hard-wired to VOTE_OPTION1 (Yes) if ( m_potentialIssues[m_iActiveIssueIndex]->IsYesNoVote() ) { - // Option1 is Yes - if ( nWinningVoteOption != VOTE_OPTION1 ) + if ( nPassingVoteOptionIndex == VOTE_OPTION1 ) { - SendVoteFailedToPassMessage( VOTE_FAILED_YES_MUST_EXCEED_NO ); - bVotePassed = false; - } + bVotePassed = true; + } } - // GENERAL VOTES: - // We set the details string after the vote, since that's when - // we finally have a parameter to pass along and execute - else if ( nWinningVoteOption < m_VoteOptions.Count() ) + // GENERAL VOTES - as long as there's a quorum, go with the most popular choice + else { - m_potentialIssues[m_iActiveIssueIndex]->SetIssueDetails( m_VoteOptions[nWinningVoteOption] ); + bVotePassed = true; + + // We set the details string after the vote, since that's when + // we finally have a parameter to pass along and execute + m_potentialIssues[m_iActiveIssueIndex]->SetIssueDetails( m_VoteOptions[nPassingVoteOptionIndex] ); } } } - else - { - SendVoteFailedToPassMessage( VOTE_FAILED_QUORUM_FAILURE ); - bVotePassed = false; - } - if ( bVotePassed ) + if ( bVotePassed ) { - m_executeCommandTimer.Start( sv_vote_command_delay.GetFloat() ); - m_resetVoteTimer.Start( 5.0 ); - - // Target is not always a player (changelevel, etc) + // Always NULL check, as some votes don't target players (i.e. ChangeLevel) CBasePlayer *pVoteTarget = m_potentialIssues[m_iActiveIssueIndex]->m_hPlayerTarget; - bool bFakeClient = ( pVoteTarget && ( pVoteTarget->IsFakeClient() || pVoteTarget->IsHLTV() || pVoteTarget->IsReplay() ) ); - UTIL_LogPrintf( "Vote succeeded \"%s %s\" (proxy: %i) \n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString(), bFakeClient ); + // Don't delay successful kick votes + float flDelay = IsPlayerBeingKicked( pVoteTarget ) ? 0.f : sv_vote_command_delay.GetFloat(); + m_executeCommandTimer.Start( flDelay ); + m_resetVoteTimer.Start( 5.f ); + + UTIL_LogPrintf( "Vote succeeded \"%s %s\"\n", m_potentialIssues[m_iActiveIssueIndex]->GetTypeString(), m_potentialIssues[m_iActiveIssueIndex]->GetDetailsString() ); CBroadcastRecipientFilter filter; filter.MakeReliable(); @@ -717,8 +745,10 @@ void CVoteController::VoteControllerThink( void ) } else { + vote_create_failed_t nReason = m_potentialIssues[m_iActiveIssueIndex]->IsYesNoVote() ? VOTE_FAILED_YES_MUST_EXCEED_NO : VOTE_FAILED_QUORUM_FAILURE; + SendVoteFailedToPassMessage( nReason ); m_potentialIssues[m_iActiveIssueIndex]->OnVoteFailed( m_iEntityHoldingVote ); - m_resetVoteTimer.Start( 5.0 ); + m_resetVoteTimer.Start( 5.f ); } } @@ -768,12 +798,15 @@ void CVoteController::CheckForEarlyVoteClose( void ) //----------------------------------------------------------------------------- bool CVoteController::IsValidVoter( CBasePlayer *pWhom ) { - if ( pWhom == NULL ) + if ( !pWhom ) return false; if ( !pWhom->IsConnected() ) return false; + if ( pWhom->GetTeamNumber() == TEAM_UNASSIGNED ) + return false; + if ( !sv_vote_allow_spectators.GetBool() ) { if ( pWhom->GetTeamNumber() == TEAM_SPECTATOR ) @@ -818,7 +851,7 @@ void CVoteController::RegisterIssue( CBaseIssue *pszNewIssue ) //----------------------------------------------------------------------------- void CVoteController::ListIssues( CBasePlayer *pForWhom ) { - if( !sv_allow_votes.GetBool() ) + if ( !IsVoteSystemEnabled() ) return; ClientPrint( pForWhom, HUD_PRINTCONSOLE, "---Vote commands---\n" ); @@ -832,45 +865,34 @@ void CVoteController::ListIssues( CBasePlayer *pForWhom ) } //----------------------------------------------------------------------------- -// Purpose: +// Purpose: -1 when invalid //----------------------------------------------------------------------------- -int CVoteController::GetWinningVoteOption( void ) +int CVoteController::GetVoteIssueIndexWithHighestCount( void ) { - if ( m_potentialIssues[m_iActiveIssueIndex]->IsYesNoVote() ) + int nMaxIndex = -1; + + // Legacy Yes/No system + if ( m_iActiveIssueIndex != INVALID_ISSUE && m_potentialIssues[m_iActiveIssueIndex]->IsYesNoVote() ) { return ( m_nVoteOptionCount[VOTE_OPTION1] > m_nVoteOptionCount[VOTE_OPTION2] ) ? VOTE_OPTION1 : VOTE_OPTION2; } + // Which option had the most votes? else { - CUtlVector pVoteCounts; + int nMaxCount = 0; - // Which option had the most votes? - // driller: Need to handle ties - int nHighest = m_nVoteOptionCount[0]; + // TODO: Handle ties for ( int iIndex = 0; iIndex < m_nVoteOptionCount.Count(); iIndex ++ ) { - nHighest = ( ( nHighest < m_nVoteOptionCount[iIndex] ) ? m_nVoteOptionCount[iIndex] : nHighest ); - pVoteCounts.AddToTail( m_nVoteOptionCount[iIndex] ); - } - - m_nHighestCountIndex = -1; - for ( int iIndex = 0; iIndex < m_nVoteOptionCount.Count(); iIndex++ ) - { - if ( m_nVoteOptionCount[iIndex] == nHighest ) + if ( m_nVoteOptionCount[iIndex] && m_nVoteOptionCount[iIndex] > nMaxCount ) { - m_nHighestCountIndex = iIndex; - // henryg: break on first match, not last. this avoids a crash - // if we are all tied at zero and we pick something beyond the - // last vote option. this code really ought to ignore attempts - // to tally votes for options beyond the last valid one! - break; + nMaxCount = m_nVoteOptionCount[iIndex]; + nMaxIndex = iIndex; } } - - return m_nHighestCountIndex; } - return -1; + return nMaxIndex; } //----------------------------------------------------------------------------- @@ -898,11 +920,12 @@ void CVoteController::TrackVoteCaller( CBasePlayer *pPlayer ) //----------------------------------------------------------------------------- // Purpose: Check the history of steamIDs that called votes and test against a timer //----------------------------------------------------------------------------- -bool CVoteController::CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown ) +bool CVoteController::CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown, vote_create_failed_t &nErrorCode ) { if ( !pPlayer ) return false; - + +#ifndef _DEBUG CSteamID steamID; pPlayer->GetSteamID( &steamID ); @@ -913,15 +936,34 @@ bool CVoteController::CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown ) // Timer elapsed? nCooldown = (int)( m_VoteCallers[ iIdx ] - gpGlobals->curtime ); if ( nCooldown > 0 ) + { + nErrorCode = VOTE_FAILED_RATE_EXCEEDED; return false; + } // Expired m_VoteCallers.Remove( iIdx ); } +#endif return true; }; +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CVoteController::GetNumVotesCast( void ) +{ + int nVoteTally = 0; + + for ( int index = 0; index < MAX_VOTE_OPTIONS; index++ ) + { + nVoteTally += m_nVoteOptionCount.Get( index ); + } + + return nVoteTally; +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -930,12 +972,41 @@ void CVoteController::AddPlayerToKickWatchList( CSteamID steamID, float flDurati VoteControllerSystem.AddPlayerToKickWatchList( steamID, flDuration ); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CVoteController::AddPlayerToNameLockedList( CSteamID steamID, float flDuration, int nUserID ) +{ + engine->ServerCommand( UTIL_VarArgs( "namelockid %d %d\n", nUserID, 1 ) ); + + VoteControllerSystem.AddPlayerToNameLockedList( steamID, flDuration ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CVoteController::IsPlayerBeingKicked( CBasePlayer *pPlayer ) +{ +#ifdef TF_DLL + if ( pPlayer && m_iActiveIssueIndex != INVALID_ISSUE ) + { + CKickIssue *pKickIssue = dynamic_cast< CKickIssue* >( m_potentialIssues[m_iActiveIssueIndex] ); + if ( pKickIssue ) + { + return pKickIssue->m_hPlayerTarget == pPlayer; + } + } +#endif // TF_DLL + + return false; +} + //----------------------------------------------------------------------------- // Purpose: BaseIssue //----------------------------------------------------------------------------- CBaseIssue::CBaseIssue( const char *pszTypeString ) { - Q_strcpy( m_szTypeString, pszTypeString ); + V_strcpy_safe( m_szTypeString, pszTypeString ); m_iNumYesVotes = 0; m_iNumNoVotes = 0; @@ -979,13 +1050,13 @@ const char *CBaseIssue::GetDetailsString( void ) //----------------------------------------------------------------------------- void CBaseIssue::SetIssueDetails( const char *pszDetails ) { - Q_strcpy( m_szDetailsString, pszDetails ); + V_strcpy_safe( m_szDetailsString, pszDetails ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CBaseIssue::IsAllyRestrictedVote( void ) +bool CBaseIssue::IsTeamRestrictedVote( void ) { return false; } @@ -1030,7 +1101,7 @@ void CBaseIssue::OnVoteFailed( int iEntityHoldingVote ) // Need to create a new one FailedVote *pNewFailedVote = new FailedVote; int iIndex = m_FailedVotes.AddToTail( pNewFailedVote ); - Q_strcpy( m_FailedVotes[iIndex]->szFailedVoteParameter, GetDetailsString() ); + V_strcpy_safe( m_FailedVotes[iIndex]->szFailedVoteParameter, GetDetailsString() ); m_FailedVotes[iIndex]->flLockoutTime = gpGlobals->curtime + sv_vote_failure_timer.GetFloat(); } } @@ -1184,4 +1255,12 @@ bool CBaseIssue::GetVoteOptions( CUtlVector &vecNames ) return true; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CBaseIssue::GetQuorumRatio( void ) +{ + return sv_vote_quorum_ratio.GetFloat(); +} + diff --git a/mp/src/game/server/vote_controller.h b/mp/src/game/server/vote_controller.h index ccc55cd5..a3f82ff6 100644 --- a/mp/src/game/server/vote_controller.h +++ b/mp/src/game/server/vote_controller.h @@ -20,17 +20,18 @@ class CBaseIssue // Base class concept for vote issues (i.e. Kick Player). Created per level-load and destroyed by CVoteController's dtor. { public: - CBaseIssue(const char *typeString); - virtual ~CBaseIssue(); + CBaseIssue( const char *typeString ); + virtual ~CBaseIssue(); const char *GetTypeString( void ); // Connection between console command and specific type of issue - virtual const char *GetDetailsString(); + virtual const char *GetTypeStringLocalized( void ) { return ""; } // When empty, the client uses the classname string and prepends "#Vote_" + virtual const char *GetDetailsString( void ); virtual void SetIssueDetails( const char *pszDetails ); // We need to know the details part of the con command for later virtual void OnVoteFailed( int iEntityHoldingVote ); // The moment the vote fails, also has some time for feedback before the window goes away virtual void OnVoteStarted( void ) {} // Called as soon as the vote starts virtual bool IsEnabled( void ) { return false; } // Query the issue to see if it's enabled virtual bool CanTeamCallVote( int iTeam ) const; // Can someone on the given team call this vote? virtual bool CanCallVote( int nEntIndex, const char *pszDetails, vote_create_failed_t &nFailCode, int &nTime ); // Can this guy hold a vote on this issue? - virtual bool IsAllyRestrictedVote( void ); // Can only members of the same team vote on this? + virtual bool IsTeamRestrictedVote( void ); // Restrict access and visibility of this vote to a specific team? virtual const char *GetDisplayString( void ) = 0; // The string that will be passed to the client for display virtual void ExecuteCommand( void ) = 0; // Where the magic happens. Do your thing. virtual void ListIssueDetails( CBasePlayer *pForWhom ) = 0; // Someone would like to know all your valid details @@ -42,6 +43,7 @@ public: virtual bool GetVoteOptions( CUtlVector &vecNames ); // We use this to generate options for voting virtual bool BRecordVoteFailureEventForEntity( int iVoteCallingEntityIndex ) const { return iVoteCallingEntityIndex != DEDICATED_SERVER; } void SetIssueCooldownDuration( float flDuration ) { m_flNextCallTime = gpGlobals->curtime + flDuration; } // The issue can not be raised again for this period of time (in seconds) + virtual float GetQuorumRatio( void ); // Each issue can decide the required ratio of voted-vs-abstained CHandle< CBasePlayer > m_hPlayerTarget; // If the target of the issue is a player, we should store them here @@ -54,11 +56,9 @@ protected: float flLockoutTime; }; - CUtlVector m_FailedVotes; - - char m_szTypeString[MAX_COMMAND_LENGTH]; - char m_szDetailsString[MAX_VOTE_DETAILS_LENGTH]; - + CUtlVector< FailedVote* > m_FailedVotes; + char m_szTypeString[MAX_COMMAND_LENGTH]; + char m_szDetailsString[MAX_VOTE_DETAILS_LENGTH]; int m_iNumYesVotes; int m_iNumNoVotes; int m_iNumPotentialVotes; @@ -89,6 +89,7 @@ public: virtual void Spawn( void ); virtual int UpdateTransmitState( void ); + virtual bool IsVoteSystemEnabled( void ); bool SetupVote( int iEntIndex ); // This creates a list of issues for the UI bool CreateVote( int iEntIndex, const char *pszTypeString, const char *pszDetailString ); // This is what the UI passes in @@ -101,12 +102,15 @@ public: void SendVoteFailedToPassMessage( vote_create_failed_t nReason ); void VoteChoice_Increment( int nVoteChoice ); void VoteChoice_Decrement( int nVoteChoice ); - int GetWinningVoteOption( void ); + int GetVoteIssueIndexWithHighestCount( void ); void TrackVoteCaller( CBasePlayer *pPlayer ); - bool CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown ); + bool CanEntityCallVote( CBasePlayer *pPlayer, int &nCooldown, vote_create_failed_t &nErrorCode ); bool IsVoteActive( void ) { return m_iActiveIssueIndex != INVALID_ISSUE; } + int GetNumVotesCast( void ); - void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ); + void AddPlayerToKickWatchList( CSteamID steamID, float flDuration ); // Band-aid until we figure out how player's avoid kick votes + void AddPlayerToNameLockedList( CSteamID steamID, float flDuration, int nUserID ); + bool IsPlayerBeingKicked( CBasePlayer *pPlayer ); protected: void ResetData( void ); @@ -123,7 +127,6 @@ protected: CountdownTimer m_resetVoteTimer; // when the current vote will end int m_nVotesCast[MAX_PLAYERS + 1]; // arrays are zero-based and player indices are one-based int m_iEntityHoldingVote; - int m_nHighestCountIndex; CUtlVector m_potentialIssues; CUtlVector m_VoteOptions; diff --git a/mp/src/game/shared/GameStats.cpp b/mp/src/game/shared/GameStats.cpp index d01e56fb..7351647b 100644 --- a/mp/src/game/shared/GameStats.cpp +++ b/mp/src/game/shared/GameStats.cpp @@ -46,6 +46,11 @@ extern const ConVar *sv_cheats; #endif #endif +#ifdef CLIENT_DLL + // Ensure this is declared in the client dll so everyone finds the same one. + ConVar dev_loadtime_mainmenu("dev_loadtime_mainmenu", "0.0", FCVAR_HIDDEN ); +#endif + // NOTE: This has to be the last file included! #include "tier0/memdbgon.h" @@ -141,7 +146,7 @@ CBaseGameStats_Driver::CBaseGameStats_Driver( void ) : m_bDidVoiceChat( false ) { - m_szLoadedUserID[0] = 0;; + m_szLoadedUserID[0] = 0; m_tLastUpload = 0; m_LastUserCmd.Reset(); } @@ -1061,6 +1066,33 @@ void CBaseGameStats_Driver::SendData() ResetData(); } +#ifdef CLIENT_DLL + // Adds the main menu load time to the specified key values, but only ever does the work once. + static void AddLoadTimeMainMenu( KeyValues* pKV ) + { + Assert( pKV ); + float loadTimeMainMenu = dev_loadtime_mainmenu.GetFloat(); + if ( loadTimeMainMenu > 0.0f ) { + pKV->SetFloat( "LoadTimeMainMenu", loadTimeMainMenu ); + // Only want to set this once, clear it to 0.0 here. The other code will only ever set it once. + dev_loadtime_mainmenu.SetValue( 0.0f ); + } + } + + // Adds the map load time to the specified key values, but clears the elapsed data to 0.0 for next computation. + static void AddLoadTimeMap(KeyValues* pKV) + { + static ConVarRef dev_loadtime_map_elapsed( "dev_loadtime_map_elapsed" ); + float loadTimeMap = dev_loadtime_map_elapsed.GetFloat(); + if ( loadTimeMap > 0.0f ) + { + pKV->SetFloat( "LoadTimeMap", loadTimeMap ); + dev_loadtime_map_elapsed.SetValue( 0.0f ); + } + } + +#endif + bool CBaseGameStats_Driver::AddBaseDataForSend( KeyValues *pKV, StatSendType_t sendType ) { switch ( sendType ) @@ -1074,6 +1106,12 @@ bool CBaseGameStats_Driver::AddBaseDataForSend( KeyValues *pKV, StatSendType_t s pKVData->SetInt( "TotalLevelTime", m_flTotalTimeInLevels ); pKVData->SetInt( "NumLevels", m_iNumLevels ); pKV->AddSubKey( pKVData ); + + AddLoadTimeMainMenu( pKV ); + // If the user quits directly from the map, we still want to (possibly) capture their map load time, so + // do add it here. It will not be added if it was already attached to a session. + AddLoadTimeMap( pKV ); + return true; } #endif @@ -1141,6 +1179,9 @@ bool CBaseGameStats_Driver::AddBaseDataForSend( KeyValues *pKV, StatSendType_t s int mapTime = gpGlobals->realtime - m_flLevelStartTime; pKV->SetInt( "MapTime", mapTime ); + AddLoadTimeMainMenu(pKV); + AddLoadTimeMap(pKV); + return true; } #endif @@ -1177,6 +1218,10 @@ void CBaseGameStats_Driver::ResetData() OverWriteCharsWeHate( cpu.m_szProcessorID ); pKV->SetString( "CPUID", cpu.m_szProcessorID ); pKV->SetFloat( "CPUGhz", cpu.m_Speed * ( 1.0 / 1.0e9 ) ); + pKV->SetUint64( "CPUModel", cpu.m_nModel ); + pKV->SetUint64( "CPUFeatures0", cpu.m_nFeatures[ 0 ] ); + pKV->SetUint64( "CPUFeatures1", cpu.m_nFeatures[ 1 ] ); + pKV->SetUint64( "CPUFeatures2", cpu.m_nFeatures[ 2 ] ); pKV->SetInt( "NumCores", cpu.m_nPhysicalProcessors ); MaterialAdapterInfo_t gpu; diff --git a/mp/src/game/shared/ModelSoundsCache.cpp b/mp/src/game/shared/ModelSoundsCache.cpp index e6ad628b..4f4f10fb 100644 --- a/mp/src/game/shared/ModelSoundsCache.cpp +++ b/mp/src/game/shared/ModelSoundsCache.cpp @@ -68,7 +68,7 @@ void CModelSoundsCache::Restore( CUtlBuffer& buf ) { char soundname[ 512 ]; - buf.GetString( soundname, sizeof( soundname ) ); + buf.GetString( soundname ); int idx = soundemitterbase->GetSoundIndex( soundname ); if ( idx != -1 ) diff --git a/mp/src/game/shared/Multiplayer/multiplayer_animstate.cpp b/mp/src/game/shared/Multiplayer/multiplayer_animstate.cpp index 4d1ad4fe..2734eba0 100644 --- a/mp/src/game/shared/Multiplayer/multiplayer_animstate.cpp +++ b/mp/src/game/shared/Multiplayer/multiplayer_animstate.cpp @@ -91,6 +91,10 @@ CMultiPlayerAnimState::CMultiPlayerAnimState( CBasePlayer *pPlayer, MultiPlayerM m_flMaxGroundSpeed = 0.0f; + // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between + // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window, + // and the fact that m_flEyeYaw is never propogated from the server to the client. + // TODO: Fix this after Halloween 2014. m_bForceAimYaw = false; Init( pPlayer, movementData ); @@ -1655,6 +1659,10 @@ void CMultiPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ) bool bMoving = ( vecVelocity.Length() > 1.0f ) ? true : false; // If we are moving or are prone and undeployed. + // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between + // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window, + // and the fact that m_flEyeYaw is never propogated from the server to the client. + // TODO: Fix this after Halloween 2014. if ( bMoving || m_bForceAimYaw ) { // The feet match the eye direction when moving - the move yaw takes care of the rest. @@ -1688,6 +1696,10 @@ void CMultiPlayerAnimState::ComputePoseParam_AimYaw( CStudioHdr *pStudioHdr ) m_flGoalFeetYaw = AngleNormalize( m_flGoalFeetYaw ); if ( m_flGoalFeetYaw != m_flCurrentFeetYaw ) { + // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between + // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window, + // and the fact that m_flEyeYaw is never propogated from the server to the client. + // TODO: Fix this after Halloween 2014. if ( m_bForceAimYaw ) { m_flCurrentFeetYaw = m_flGoalFeetYaw; diff --git a/mp/src/game/shared/Multiplayer/multiplayer_animstate.h b/mp/src/game/shared/Multiplayer/multiplayer_animstate.h index 007533a1..a3c7937a 100644 --- a/mp/src/game/shared/Multiplayer/multiplayer_animstate.h +++ b/mp/src/game/shared/Multiplayer/multiplayer_animstate.h @@ -63,6 +63,10 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_STUN_BEGIN, PLAYERANIMEVENT_STUN_MIDDLE, PLAYERANIMEVENT_STUN_END, + PLAYERANIMEVENT_PASSTIME_THROW_BEGIN, + PLAYERANIMEVENT_PASSTIME_THROW_MIDDLE, + PLAYERANIMEVENT_PASSTIME_THROW_END, + PLAYERANIMEVENT_PASSTIME_THROW_CANCEL, PLAYERANIMEVENT_ATTACK_PRIMARY_SUPER, @@ -203,6 +207,10 @@ public: bool VerifyAnimLayerInSlot( int iGestureSlot ); // Feet. + // If you are forcing aim yaw, your code is almost definitely broken if you don't include a delay between + // teleporting and forcing yaw. This is due to an unfortunate interaction between the command lookback window, + // and the fact that m_flEyeYaw is never propogated from the server to the client. + // TODO: Fix this after Halloween 2014. bool m_bForceAimYaw; protected: diff --git a/mp/src/game/shared/SceneCache.cpp b/mp/src/game/shared/SceneCache.cpp index 0728c27b..c993ef46 100644 --- a/mp/src/game/shared/SceneCache.cpp +++ b/mp/src/game/shared/SceneCache.cpp @@ -59,7 +59,7 @@ void CSceneCache::Restore( CUtlBuffer& buf ) for ( int i = 0; i < c; ++i ) { char soundname[ 512 ]; - buf.GetString( soundname, sizeof( soundname ) ); + buf.GetString( soundname ); int idx = soundemitterbase->GetSoundIndex( soundname ); if ( idx != -1 ) diff --git a/mp/src/game/shared/SoundEmitterSystem.cpp b/mp/src/game/shared/SoundEmitterSystem.cpp index 7b641c20..39aca858 100644 --- a/mp/src/game/shared/SoundEmitterSystem.cpp +++ b/mp/src/game/shared/SoundEmitterSystem.cpp @@ -337,6 +337,15 @@ public: FinishLog(); #endif } + + void Flush() + { + Assert( soundemitterbase ); +#if !defined( CLIENT_DLL ) + FinishLog(); +#endif + soundemitterbase->Flush(); + } void InternalPrecacheWaves( int soundIndex ) { @@ -998,10 +1007,7 @@ void S_SoundEmitterSystemFlush( void ) // save the current soundscape // kill the system - g_SoundEmitterSystem.Shutdown(); - - // restart the system - g_SoundEmitterSystem.Init(); + g_SoundEmitterSystem.Flush(); #if !defined( CLIENT_DLL ) // Redo precache all wave files... (this should work now that we have dynamic string tables) diff --git a/mp/src/game/shared/SpriteTrail.h b/mp/src/game/shared/SpriteTrail.h index 3e4fb763..2248dc99 100644 --- a/mp/src/game/shared/SpriteTrail.h +++ b/mp/src/game/shared/SpriteTrail.h @@ -82,8 +82,8 @@ private: enum { // NOTE: # of points max must be a power of two! - MAX_SPRITE_TRAIL_POINTS = 64, - MAX_SPRITE_TRAIL_MASK = 0x3F, + MAX_SPRITE_TRAIL_POINTS = 256, + MAX_SPRITE_TRAIL_MASK = MAX_SPRITE_TRAIL_POINTS - 1, }; TrailPoint_t *GetTrailPoint( int n ); @@ -114,6 +114,11 @@ private: string_t m_iszSpriteName; bool m_bAnimate; bool m_bDrawForMoveParent; + +#if defined( CLIENT_DLL ) +public: + void SetUpdateTime(float setTo){ m_flUpdateTime = setTo; } +#endif }; #endif // SPRITETRAIL_H diff --git a/mp/src/game/shared/activitylist.cpp b/mp/src/game/shared/activitylist.cpp index 4c882d47..49e93e93 100644 --- a/mp/src/game/shared/activitylist.cpp +++ b/mp/src/game/shared/activitylist.cpp @@ -1802,6 +1802,11 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_MP_ATTACK_SWIM_GRENADE_ITEM2 ); REGISTER_SHARED_ACTIVITY( ACT_MP_ATTACK_AIRWALK_GRENADE_ITEM2 ); + // Passtime + REGISTER_SHARED_ACTIVITY( ACT_MP_STAND_PASSTIME ); + REGISTER_SHARED_ACTIVITY( ACT_MP_RUN_PASSTIME ); + REGISTER_SHARED_ACTIVITY( ACT_MP_CROUCHWALK_PASSTIME ); + // Flinches REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH ); REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_FLINCH_PRIMARY ); @@ -1943,6 +1948,7 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY ( ACT_MP_DOUBLEJUMP_CROUCH_ITEM1 ); REGISTER_SHARED_ACTIVITY ( ACT_MP_DOUBLEJUMP_CROUCH_ITEM2 ); REGISTER_SHARED_ACTIVITY ( ACT_MP_DOUBLEJUMP_CROUCH_LOSERSTATE ); + REGISTER_SHARED_ACTIVITY ( ACT_MP_DOUBLEJUMP_CROUCH_PASSTIME ); REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_HANDMOUTH ); REGISTER_SHARED_ACTIVITY( ACT_MP_GESTURE_VC_FINGERPOINT ); @@ -2004,6 +2010,11 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_MP_STUN_MIDDLE ); REGISTER_SHARED_ACTIVITY( ACT_MP_STUN_END ); + REGISTER_SHARED_ACTIVITY( ACT_MP_PASSTIME_THROW_BEGIN ); + REGISTER_SHARED_ACTIVITY( ACT_MP_PASSTIME_THROW_MIDDLE ); + REGISTER_SHARED_ACTIVITY( ACT_MP_PASSTIME_THROW_END ); + REGISTER_SHARED_ACTIVITY( ACT_MP_PASSTIME_THROW_CANCEL ); + REGISTER_SHARED_ACTIVITY ( ACT_VM_UNUSABLE ); REGISTER_SHARED_ACTIVITY ( ACT_VM_UNUSABLE_TO_USABLE ); REGISTER_SHARED_ACTIVITY ( ACT_VM_USABLE_TO_UNUSABLE ); @@ -2304,6 +2315,42 @@ void ActivityList_RegisterSharedActivities( void ) REGISTER_SHARED_ACTIVITY( ACT_BOT_PANIC_START ); REGISTER_SHARED_ACTIVITY( ACT_BOT_PANIC_END ); + REGISTER_SHARED_ACTIVITY( ACT_ENGINEER_REVOLVER_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_ENGINEER_REVOLVER_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_ENGINEER_REVOLVER_PRIMARYATTACK ); + REGISTER_SHARED_ACTIVITY( ACT_ENGINEER_REVOLVER_RELOAD ); + + REGISTER_SHARED_ACTIVITY( ACT_KART_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_KART_ACTION_SHOOT ); + REGISTER_SHARED_ACTIVITY( ACT_KART_ACTION_DASH ); + REGISTER_SHARED_ACTIVITY( ACT_KART_JUMP_START ); + REGISTER_SHARED_ACTIVITY( ACT_KART_JUMP_FLOAT ); + REGISTER_SHARED_ACTIVITY( ACT_KART_JUMP_LAND ); + REGISTER_SHARED_ACTIVITY( ACT_KART_IMPACT ); + REGISTER_SHARED_ACTIVITY( ACT_KART_IMPACT_BIG ); + REGISTER_SHARED_ACTIVITY( ACT_KART_GESTURE_POSITIVE ); + REGISTER_SHARED_ACTIVITY( ACT_KART_GESTURE_NEGATIVE ); + + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_DRAW ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_FIRE_START ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_FIRE_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_PULL_START ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_PULL_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_GRAPPLE_PULL_END ); + + REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_START ); + REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_END ); + + REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_START ); + REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_END ); + + REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_START ); + REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_IDLE ); + REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_END ); + AssertMsg( g_HighestActivity == LAST_SHARED_ACTIVITY - 1, "Not all activities from ai_activity.h registered in activitylist.cpp" ); } diff --git a/mp/src/game/shared/ai_activity.h b/mp/src/game/shared/ai_activity.h index 3d3207c9..0f5bba44 100644 --- a/mp/src/game/shared/ai_activity.h +++ b/mp/src/game/shared/ai_activity.h @@ -1631,6 +1631,11 @@ typedef enum ACT_MP_ATTACK_SWIM_GRENADE_ITEM2, ACT_MP_ATTACK_AIRWALK_GRENADE_ITEM2, + // Passtime + ACT_MP_STAND_PASSTIME, + ACT_MP_RUN_PASSTIME, + ACT_MP_CROUCHWALK_PASSTIME, + // Flinches ACT_MP_GESTURE_FLINCH, ACT_MP_GESTURE_FLINCH_PRIMARY, @@ -1771,6 +1776,7 @@ typedef enum ACT_MP_DOUBLEJUMP_CROUCH_ITEM1, ACT_MP_DOUBLEJUMP_CROUCH_ITEM2, ACT_MP_DOUBLEJUMP_CROUCH_LOSERSTATE, + ACT_MP_DOUBLEJUMP_CROUCH_PASSTIME, ACT_MP_GESTURE_VC_HANDMOUTH, ACT_MP_GESTURE_VC_FINGERPOINT, @@ -1832,6 +1838,11 @@ typedef enum ACT_MP_STUN_MIDDLE, ACT_MP_STUN_END, + ACT_MP_PASSTIME_THROW_BEGIN, + ACT_MP_PASSTIME_THROW_MIDDLE, + ACT_MP_PASSTIME_THROW_END, + ACT_MP_PASSTIME_THROW_CANCEL, + ACT_VM_UNUSABLE, ACT_VM_UNUSABLE_TO_USABLE, ACT_VM_USABLE_TO_UNUSABLE, @@ -2138,6 +2149,45 @@ typedef enum ACT_BOT_PANIC_START, ACT_BOT_PANIC_END, + ACT_ENGINEER_REVOLVER_DRAW, + ACT_ENGINEER_REVOLVER_IDLE, + ACT_ENGINEER_REVOLVER_PRIMARYATTACK, + ACT_ENGINEER_REVOLVER_RELOAD, + + // Kart! + ACT_KART_IDLE, + ACT_KART_ACTION_SHOOT, + ACT_KART_ACTION_DASH, + ACT_KART_JUMP_START, + ACT_KART_JUMP_FLOAT, + ACT_KART_JUMP_LAND, + ACT_KART_IMPACT, + ACT_KART_IMPACT_BIG, + ACT_KART_GESTURE_POSITIVE, + ACT_KART_GESTURE_NEGATIVE, + + // grappling hook + ACT_GRAPPLE_DRAW, + ACT_GRAPPLE_IDLE, + ACT_GRAPPLE_FIRE_START, + ACT_GRAPPLE_FIRE_IDLE, + ACT_GRAPPLE_PULL_START, + ACT_GRAPPLE_PULL_IDLE, + ACT_GRAPPLE_PULL_END, + + // inspect + ACT_PRIMARY_VM_INSPECT_START, + ACT_PRIMARY_VM_INSPECT_IDLE, + ACT_PRIMARY_VM_INSPECT_END, + + ACT_SECONDARY_VM_INSPECT_START, + ACT_SECONDARY_VM_INSPECT_IDLE, + ACT_SECONDARY_VM_INSPECT_END, + + ACT_MELEE_VM_INSPECT_START, + ACT_MELEE_VM_INSPECT_IDLE, + ACT_MELEE_VM_INSPECT_END, + // this is the end of the global activities, private per-monster activities start here. LAST_SHARED_ACTIVITY, } Activity; diff --git a/mp/src/game/shared/animation.cpp b/mp/src/game/shared/animation.cpp index 0f6dd754..97561581 100644 --- a/mp/src/game/shared/animation.cpp +++ b/mp/src/game/shared/animation.cpp @@ -339,6 +339,77 @@ int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr * } +int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequenceFromModifiers( CStudioHdr *pstudiohdr, int activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) +{ + if ( !pstudiohdr->SequencesAvailable() ) + { + return ACTIVITY_NOT_AVAILABLE; + } + + VerifySequenceIndex( pstudiohdr ); + + if ( pstudiohdr->GetNumSeq() == 1 ) + { + return ( ::GetSequenceActivity( pstudiohdr, 0, NULL ) == activity ) ? 0 : ACTIVITY_NOT_AVAILABLE; + } + + if (!ValidateAgainst(pstudiohdr)) + { + AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName()); + ExecuteOnce(DebuggerBreakIfDebugging()); + Reinitialize(pstudiohdr); + } + + // a null m_pSequenceTuples just means that this studio header has no activities. + if (!m_pSequenceTuples) + return ACTIVITY_NOT_AVAILABLE; + + // get the data for the given activity + HashValueType dummy( activity, 0, 0, 0 ); + UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy); + if (!m_ActToSeqHash.IsValidHandle(handle)) + { + return ACTIVITY_NOT_AVAILABLE; + } + const HashValueType * __restrict actData = &m_ActToSeqHash[handle]; + + // go through each sequence and give it a score + int top_score = -1; + CUtlVector topScoring( actData->count, actData->count ); + for ( int i = 0; i < actData->count; i++ ) + { + SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx + i; + int score = 0; + // count matching activity modifiers + for ( int m = 0; m < iModifierCount; m++ ) + { + int num_modifiers = sequenceInfo->iNumActivityModifiers; + for ( int k = 0; k < num_modifiers; k++ ) + { + if ( sequenceInfo->pActivityModifiers[ k ] == pActivityModifiers[ m ] ) + { + score++; + break; + } + } + } + if ( score > top_score ) + { + topScoring.RemoveAll(); + topScoring.AddToTail( sequenceInfo->seqnum ); + top_score = score; + } + } + + // randomly pick between the highest scoring sequences ( NOTE: this method of selecting a sequence ignores activity weights ) + if ( IsInPrediction() ) + { + return topScoring[ SharedRandomInt( "SelectWeightedSequence", 0, topScoring.Count() - 1 ) ]; + } + + return topScoring[ RandomInt( 0, topScoring.Count() - 1 ) ]; +} + #endif @@ -446,9 +517,9 @@ int LookupSequence( CStudioHdr *pstudiohdr, const char *label ) void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float poseParameter[], Vector *pVec ) { - if (! pstudiohdr) + if ( !pstudiohdr) { - Msg( "Bad pstudiohdr in GetSequenceLinearMotion()!\n" ); + ExecuteNTimes( 20, Msg( "Bad pstudiohdr in GetSequenceLinearMotion()!\n" ) ); return; } @@ -460,11 +531,7 @@ void GetSequenceLinearMotion( CStudioHdr *pstudiohdr, int iSequence, const float // Don't spam on bogus model if ( pstudiohdr->GetNumSeq() > 0 ) { - static int msgCount = 0; - while ( ++msgCount <= 10 ) - { - Msg( "Bad sequence (%i out of %i max) in GetSequenceLinearMotion() for model '%s'!\n", iSequence, pstudiohdr->GetNumSeq(), pstudiohdr->pszName() ); - } + ExecuteNTimes( 20, Msg( "Bad sequence (%i out of %i max) in GetSequenceLinearMotion() for model '%s'!\n", iSequence, pstudiohdr->GetNumSeq(), pstudiohdr->pszName() ) ); } pVec->Init(); return; @@ -849,7 +916,7 @@ const char *GetBodygroupName( CStudioHdr *pstudiohdr, int iGroup ) int FindBodygroupByName( CStudioHdr *pstudiohdr, const char *name ) { - if ( !pstudiohdr ) + if ( !pstudiohdr || !pstudiohdr->IsValid() ) return -1; int group; diff --git a/mp/src/game/shared/base_playeranimstate.cpp b/mp/src/game/shared/base_playeranimstate.cpp index d90655ac..768e4f17 100644 --- a/mp/src/game/shared/base_playeranimstate.cpp +++ b/mp/src/game/shared/base_playeranimstate.cpp @@ -269,7 +269,7 @@ void CBasePlayerAnimState::ComputeMainSequence() int animDesired = SelectWeightedSequence( TranslateActivity(idealActivity) ); #if !defined( HL1_CLIENT_DLL ) && !defined ( HL1_DLL ) - if ( pPlayer->GetSequenceActivity( pPlayer->GetSequence() ) == pPlayer->GetSequenceActivity( animDesired ) ) + if ( !ShouldResetMainSequence( pPlayer->GetSequence(), animDesired ) ) return; #endif @@ -289,8 +289,13 @@ void CBasePlayerAnimState::ComputeMainSequence() #endif } +bool CBasePlayerAnimState::ShouldResetMainSequence( int iCurrentSequence, int iNewSequence ) +{ + if ( !GetOuter() ) + return false; - + return GetOuter()->GetSequenceActivity( iCurrentSequence ) != GetOuter()->GetSequenceActivity( iNewSequence ); +} void CBasePlayerAnimState::UpdateAimSequenceLayers( diff --git a/mp/src/game/shared/base_playeranimstate.h b/mp/src/game/shared/base_playeranimstate.h index 0b1f6b34..5c84755a 100644 --- a/mp/src/game/shared/base_playeranimstate.h +++ b/mp/src/game/shared/base_playeranimstate.h @@ -234,6 +234,7 @@ private: void EstimateYaw(); + virtual bool ShouldResetMainSequence( int iCurrentSequence, int iNewSequence ); void ComputeMainSequence(); void ComputeAimSequence(); diff --git a/mp/src/game/shared/basecombatcharacter_shared.cpp b/mp/src/game/shared/basecombatcharacter_shared.cpp index c032cd54..32e823fa 100644 --- a/mp/src/game/shared/basecombatcharacter_shared.cpp +++ b/mp/src/game/shared/basecombatcharacter_shared.cpp @@ -90,8 +90,23 @@ bool CBaseCombatCharacter::Weapon_CanSwitchTo( CBaseCombatWeapon *pWeapon ) if ( m_hActiveWeapon ) { - if ( !m_hActiveWeapon->CanHolster() ) + if ( !m_hActiveWeapon->CanHolster() && !pWeapon->ForceWeaponSwitch() ) return false; + + if ( IsPlayer() ) + { + CBasePlayer *pPlayer = (CBasePlayer *)this; + // check if active weapon force the last weapon to switch + if ( m_hActiveWeapon->ForceWeaponSwitch() ) + { + // last weapon wasn't allowed to switch, don't allow to switch to new weapon + CBaseCombatWeapon *pLastWeapon = pPlayer->GetLastWeapon(); + if ( pLastWeapon && pWeapon != pLastWeapon && !pLastWeapon->CanHolster() && !pWeapon->ForceWeaponSwitch() ) + { + return false; + } + } + } } return true; diff --git a/mp/src/game/shared/basecombatweapon_shared.cpp b/mp/src/game/shared/basecombatweapon_shared.cpp index 4ab20c12..616dcf47 100644 --- a/mp/src/game/shared/basecombatweapon_shared.cpp +++ b/mp/src/game/shared/basecombatweapon_shared.cpp @@ -1149,7 +1149,7 @@ float CBaseCombatWeapon::GetViewModelSequenceDuration() return vm->SequenceDuration(); } -bool CBaseCombatWeapon::IsViewModelSequenceFinished( void ) +bool CBaseCombatWeapon::IsViewModelSequenceFinished( void ) const { // These are not valid activities and always complete immediately if ( GetActivity() == ACT_RESET || GetActivity() == ACT_INVALID ) @@ -1452,7 +1452,12 @@ selects and deploys each weapon as you pass it. (sjb) bool CBaseCombatWeapon::Deploy( ) { MDLCACHE_CRITICAL_SECTION(); - return DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), GetDrawActivity(), (char*)GetAnimPrefix() ); + bool bResult = DefaultDeploy( (char*)GetViewModel(), (char*)GetWorldModel(), GetDrawActivity(), (char*)GetAnimPrefix() ); + + // override pose parameters + PoseParameterOverride( false ); + + return bResult; } Activity CBaseCombatWeapon::GetDrawActivity( void ) @@ -1511,6 +1516,9 @@ bool CBaseCombatWeapon::Holster( CBaseCombatWeapon *pSwitchingTo ) RescindReloadHudHint(); } + // reset pose parameters + PoseParameterOverride( true ); + return true; } @@ -1775,8 +1783,8 @@ void CBaseCombatWeapon::ItemPostFrame( void ) // ----------------------- // Reload pressed / Clip Empty - // ----------------------- - if ( ( pOwner->m_nButtons & IN_RELOAD ) && UsesClipsForAmmo1() && !m_bInReload ) + // Can only start the Reload Cycle after the firing cycle + if ( ( pOwner->m_nButtons & IN_RELOAD ) && m_flNextPrimaryAttack <= gpGlobals->curtime && UsesClipsForAmmo1() && !m_bInReload ) { // reload when reload is pressed, or if no buttons are down and weapon is empty. Reload(); @@ -2440,23 +2448,53 @@ bool CBaseCombatWeapon::IsLocked( CBaseEntity *pAsker ) //----------------------------------------------------------------------------- Activity CBaseCombatWeapon::ActivityOverride( Activity baseAct, bool *pRequired ) { - acttable_t *pTable = ActivityList(); - int actCount = ActivityListCount(); + int actCount = 0; + acttable_t *pTable = ActivityList( actCount ); - for ( int i = 0; i < actCount; i++, pTable++ ) + for ( int i = 0; i < actCount; i++ ) { - if ( baseAct == pTable->baseAct ) + const acttable_t& act = pTable[i]; + if ( baseAct == act.baseAct ) { if (pRequired) { - *pRequired = pTable->required; + *pRequired = act.required; } - return (Activity)pTable->weaponAct; + return (Activity)act.weaponAct; } } return baseAct; } + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CBaseCombatWeapon::PoseParameterOverride( bool bReset ) +{ + CBaseCombatCharacter *pOwner = GetOwner(); + if ( !pOwner ) + return; + + CStudioHdr *pStudioHdr = pOwner->GetModelPtr(); + if ( !pStudioHdr ) + return; + + int iCount = 0; + poseparamtable_t *pPoseParamList = PoseParamList( iCount ); + if ( pPoseParamList ) + { + for ( int i=0; iLookupPoseParameter( pStudioHdr, pPoseParamList[i].pszName ); + + if ( iPoseParam != -1 ) + pOwner->SetPoseParameter( iPoseParam, bReset ? 0 : pPoseParamList[i].flValue ); + } + } +} + + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -2745,6 +2783,13 @@ void* SendProxy_SendNonLocalWeaponDataTable( const SendProp *pProp, const void * } REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_SendNonLocalWeaponDataTable ); +#else +void CBaseCombatWeapon::RecvProxy_WeaponState( const CRecvProxyData *pData, void *pStruct, void *pOut ) +{ + CBaseCombatWeapon *pWeapon = (CBaseCombatWeapon*)pStruct; + pWeapon->m_iState = pData->m_Value.m_Int; + pWeapon->UpdateVisibility(); +} #endif #if PREDICTION_ERROR_CHECK_LEVEL > 1 @@ -2818,7 +2863,7 @@ BEGIN_NETWORK_TABLE(CBaseCombatWeapon, DT_BaseCombatWeapon) RecvPropDataTable("LocalActiveWeaponData", 0, 0, &REFERENCE_RECV_TABLE(DT_LocalActiveWeaponData)), RecvPropInt( RECVINFO(m_iViewModelIndex)), RecvPropInt( RECVINFO(m_iWorldModelIndex)), - RecvPropInt( RECVINFO(m_iState )), + RecvPropInt( RECVINFO(m_iState), 0, &CBaseCombatWeapon::RecvProxy_WeaponState ), RecvPropEHandle( RECVINFO(m_hOwner ) ), #endif END_NETWORK_TABLE() diff --git a/mp/src/game/shared/basecombatweapon_shared.h b/mp/src/game/shared/basecombatweapon_shared.h index 2c712923..d4964d83 100644 --- a/mp/src/game/shared/basecombatweapon_shared.h +++ b/mp/src/game/shared/basecombatweapon_shared.h @@ -55,8 +55,7 @@ class CUserCmd; // Put this in your derived class definition to declare it's activity table // UNDONE: Cascade these? #define DECLARE_ACTTABLE() static acttable_t m_acttable[];\ - acttable_t *ActivityList( void );\ - int ActivityListCount( void ); + virtual acttable_t *ActivityList( int &iActivityCount ) OVERRIDE; // You also need to include the activity table itself in your class' implementation: // e.g. @@ -73,8 +72,7 @@ class CUserCmd; // activity table. // UNDONE: Cascade these? #define IMPLEMENT_ACTTABLE(className) \ - acttable_t *className::ActivityList( void ) { return m_acttable; } \ - int className::ActivityListCount( void ) { return ARRAYSIZE(m_acttable); } \ + acttable_t *className::ActivityList( int &iActivityCount ) { iActivityCount = ARRAYSIZE(m_acttable); return m_acttable; } typedef struct { @@ -83,6 +81,29 @@ typedef struct bool required; } acttable_t; + +struct poseparamtable_t +{ + const char *pszName; + float flValue; +}; + +// Put this in your derived class definition to declare it's poseparam table +#define DECLARE_POSEPARAMTABLE() static poseparamtable_t m_poseparamtable[];\ + virtual poseparamtable_t* PoseParamList( int &iPoseParamCount ) { return NULL; } + +// You also need to include the activity table itself in your class' implementation: +// e.g. +// acttable_t CTFGrapplingHook::m_poseparamtable[] = +// { +// { "r_arm", 2 }, +// }; +// +// The grapplinghook overrides the r_arm pose param, value to 2. + +#define IMPLEMENT_POSEPARAMTABLE(className)\ + poseparamtable_t* className::PoseParamList( int &iPoseParamCount ) { iPoseParamCount = ARRAYSIZE(m_poseparamtable); return m_poseparamtable; } + class CHudTexture; class Color; @@ -208,7 +229,7 @@ public: virtual bool SendWeaponAnim( int iActivity ); virtual void SendViewModelAnim( int nSequence ); float GetViewModelSequenceDuration(); // Return how long the current view model sequence is. - bool IsViewModelSequenceFinished( void ); // Returns if the viewmodel's current animation is finished + bool IsViewModelSequenceFinished( void ) const; // Returns if the viewmodel's current animation is finished virtual void SetViewModel(); @@ -224,7 +245,7 @@ public: bool UsesSecondaryAmmo( void ); // returns true if the weapon actually uses secondary ammo void GiveDefaultAmmo( void ); - virtual bool CanHolster( void ) { return TRUE; }; // returns true if the weapon can be holstered + virtual bool CanHolster( void ) const { return TRUE; }; // returns true if the weapon can be holstered virtual bool DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt ); virtual bool CanDeploy( void ) { return true; } // return true if the weapon's allowed to deploy virtual bool Deploy( void ); // returns true is deploy was successful @@ -266,8 +287,7 @@ public: bool DefaultReload( int iClipSize1, int iClipSize2, int iActivity ); bool ReloadsSingly( void ) const; - virtual bool AutoFiresFullClip( void ) { return false; } - virtual bool CanOverload( void ) { return false; } + virtual bool AutoFiresFullClip( void ) const { return false; } virtual void UpdateAutoFire( void ); // Weapon firing @@ -308,7 +328,7 @@ public: virtual void SetActivity( Activity act, float duration ); inline void SetActivity( Activity eActivity ) { m_Activity = eActivity; } - inline Activity GetActivity( void ) { return m_Activity; } + inline Activity GetActivity( void ) const { return m_Activity; } virtual void AddViewKick( void ); // Add in the view kick for the weapon @@ -349,6 +369,7 @@ public: virtual int GetWeight( void ) const; virtual bool AllowsAutoSwitchTo( void ) const; virtual bool AllowsAutoSwitchFrom( void ) const; + virtual bool ForceWeaponSwitch( void ) const { return false; } virtual int GetWeaponFlags( void ) const; virtual int GetSlot( void ) const; virtual int GetPosition( void ) const; @@ -387,8 +408,10 @@ public: virtual CHudTexture const *GetSpriteZoomedAutoaim( void ) const; virtual Activity ActivityOverride( Activity baseAct, bool *pRequired ); - virtual acttable_t* ActivityList( void ) { return NULL; } - virtual int ActivityListCount( void ) { return 0; } + virtual acttable_t* ActivityList( int &iActivityCount ) { return NULL; } + + virtual void PoseParameterOverride( bool bReset ); + virtual poseparamtable_t* PoseParamList( int &iPoseParamCount ) { return NULL; } virtual void Activate( void ); @@ -577,6 +600,9 @@ public: IMPLEMENT_NETWORK_VAR_FOR_DERIVED( m_nNextThinkTick ); +#ifdef CLIENT_DLL + static void RecvProxy_WeaponState( const CRecvProxyData *pData, void *pStruct, void *pOut ); +#endif int WeaponState() const { return m_iState; } // Weapon data diff --git a/mp/src/game/shared/baseentity_shared.cpp b/mp/src/game/shared/baseentity_shared.cpp index a843543f..376cd34e 100644 --- a/mp/src/game/shared/baseentity_shared.cpp +++ b/mp/src/game/shared/baseentity_shared.cpp @@ -636,10 +636,17 @@ void CBaseEntity::SetPredictionRandomSeed( const CUserCmd *cmd ) if ( !cmd ) { m_nPredictionRandomSeed = -1; +#ifdef GAME_DLL + m_nPredictionRandomSeedServer = -1; +#endif + return; } m_nPredictionRandomSeed = ( cmd->random_seed ); +#ifdef GAME_DLL + m_nPredictionRandomSeedServer = ( cmd->server_random_seed ); +#endif } @@ -1679,7 +1686,7 @@ void CBaseEntity::FireBullets( const FireBulletsInfo_t &info ) int iSeed = 0; if ( IsPlayer() ) { - iSeed = CBaseEntity::GetPredictionRandomSeed() & 255; + iSeed = CBaseEntity::GetPredictionRandomSeed( info.m_bUseServerRandomSeed ) & 255; } #if defined( HL2MP ) && defined( GAME_DLL ) diff --git a/mp/src/game/shared/baseentity_shared.h b/mp/src/game/shared/baseentity_shared.h index b5c95ba6..52a90ab4 100644 --- a/mp/src/game/shared/baseentity_shared.h +++ b/mp/src/game/shared/baseentity_shared.h @@ -119,9 +119,13 @@ inline CBaseEntity *CBaseEntity::GetEffectEntity() const return m_hEffectEntity.Get(); } -inline int CBaseEntity::GetPredictionRandomSeed( void ) +inline int CBaseEntity::GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime ) { +#ifdef GAME_DLL + return bUseUnSyncedServerPlatTime ? m_nPredictionRandomSeedServer : m_nPredictionRandomSeed; +#else return m_nPredictionRandomSeed; +#endif } inline CBasePlayer *CBaseEntity::GetPredictionPlayer( void ) diff --git a/mp/src/game/shared/baseplayer_shared.cpp b/mp/src/game/shared/baseplayer_shared.cpp index cba09eb7..70056463 100644 --- a/mp/src/game/shared/baseplayer_shared.cpp +++ b/mp/src/game/shared/baseplayer_shared.cpp @@ -342,7 +342,7 @@ Vector CBasePlayer::EyePosition( ) #ifdef CLIENT_DLL if ( IsObserver() ) { - if ( GetObserverMode() == OBS_MODE_CHASE ) + if ( GetObserverMode() == OBS_MODE_CHASE || GetObserverMode() == OBS_MODE_POI ) { if ( IsLocalPlayer() ) { @@ -1035,7 +1035,7 @@ void CBasePlayer::SelectItem( const char *pstr, int iSubType ) // Make sure the current weapon can be holstered if ( GetActiveWeapon() ) { - if ( !GetActiveWeapon()->CanHolster() ) + if ( !GetActiveWeapon()->CanHolster() && !pItem->ForceWeaponSwitch() ) return; ResetAutoaim( ); @@ -1703,6 +1703,7 @@ void CBasePlayer::CalcObserverView( Vector& eyeOrigin, QAngle& eyeAngles, float& case OBS_MODE_IN_EYE : CalcInEyeCamView( eyeOrigin, eyeAngles, fov ); break; + case OBS_MODE_POI : // PASSTIME case OBS_MODE_CHASE : CalcChaseCamView( eyeOrigin, eyeAngles, fov ); break; diff --git a/mp/src/game/shared/baseprojectile.cpp b/mp/src/game/shared/baseprojectile.cpp index 54a0e9bc..f2ff3fdd 100644 --- a/mp/src/game/shared/baseprojectile.cpp +++ b/mp/src/game/shared/baseprojectile.cpp @@ -20,6 +20,11 @@ BEGIN_NETWORK_TABLE( CBaseProjectile, DT_BaseProjectile ) END_NETWORK_TABLE() +#ifndef CLIENT_DLL +IMPLEMENT_AUTO_LIST( IBaseProjectileAutoList ); +#endif // !CLIENT_DLL + + //----------------------------------------------------------------------------- // Purpose: Constructor. //----------------------------------------------------------------------------- diff --git a/mp/src/game/shared/baseprojectile.h b/mp/src/game/shared/baseprojectile.h index d87b9fdd..9f16f828 100644 --- a/mp/src/game/shared/baseprojectile.h +++ b/mp/src/game/shared/baseprojectile.h @@ -28,7 +28,12 @@ // Base Projectile. // //============================================================================= +#ifdef CLIENT_DLL class CBaseProjectile : public CBaseAnimating +#else // CLIENT_DLL +DECLARE_AUTO_LIST( IBaseProjectileAutoList ); +class CBaseProjectile : public CBaseAnimating, public IBaseProjectileAutoList +#endif // !CLIENT_DLL { public: DECLARE_CLASS( CBaseProjectile, CBaseAnimating ); @@ -39,10 +44,12 @@ public: virtual void Spawn(); #ifdef GAME_DLL + virtual int GetBaseProjectileType() const { return -1; } // no base + virtual int GetProjectileType() const { return -1; } // no type virtual int GetDestroyableHitCount( void ) const { return m_iDestroyableHitCount; } void IncrementDestroyableHitCount( void ) { ++m_iDestroyableHitCount; } - bool CanCollideWithTeammates() const { return m_bCanCollideWithTeammates; } + virtual bool CanCollideWithTeammates() const { return m_bCanCollideWithTeammates; } virtual float GetCollideWithTeammatesDelay() const { return 0.25f; } #endif // GAME_DLL diff --git a/mp/src/game/shared/cam_thirdperson.cpp b/mp/src/game/shared/cam_thirdperson.cpp index 81db62d4..02d7753b 100644 --- a/mp/src/game/shared/cam_thirdperson.cpp +++ b/mp/src/game/shared/cam_thirdperson.cpp @@ -21,10 +21,6 @@ static Vector CAM_HULL_MAX( CAM_HULL_OFFSET, CAM_HULL_OFFSET, CAM_HULL_OFFSET); extern const ConVar *sv_cheats; -extern ConVar cam_idealdist; -extern ConVar cam_idealdistright; -extern ConVar cam_idealdistup; - void CAM_ToThirdPerson(void); void CAM_ToFirstPerson(void); @@ -103,16 +99,6 @@ void CThirdPersonManager::Update( void ) } -Vector CThirdPersonManager::GetDesiredCameraOffset( void ) -{ - if ( IsOverridingThirdPerson() == true ) - { - return Vector( cam_idealdist.GetFloat(), cam_idealdistright.GetFloat(), cam_idealdistup.GetFloat() ); - } - - return m_vecDesiredCameraOffset; -} - Vector CThirdPersonManager::GetFinalCameraOffset( void ) { Vector vDesired = GetDesiredCameraOffset(); @@ -157,7 +143,7 @@ Vector CThirdPersonManager::GetDistanceFraction( void ) return Vector( flFraction, flFraction, flUpFraction ); } -void CThirdPersonManager::PositionCamera( CBasePlayer *pPlayer, QAngle angles ) +void CThirdPersonManager::PositionCamera( CBasePlayer *pPlayer, const QAngle& angles ) { if ( pPlayer ) { diff --git a/mp/src/game/shared/cam_thirdperson.h b/mp/src/game/shared/cam_thirdperson.h index 8271a642..54dfecaa 100644 --- a/mp/src/game/shared/cam_thirdperson.h +++ b/mp/src/game/shared/cam_thirdperson.h @@ -42,25 +42,25 @@ class CThirdPersonManager public: CThirdPersonManager(); - void SetCameraOffsetAngles( Vector vecOffset ) { m_vecCameraOffset = vecOffset; } - Vector GetCameraOffsetAngles( void ) { return m_vecCameraOffset; } + void SetCameraOffsetAngles( const Vector& vecOffset ) { m_vecCameraOffset = vecOffset; } + const Vector& GetCameraOffsetAngles( void ) const { return m_vecCameraOffset; } - void SetDesiredCameraOffset( Vector vecOffset ) { m_vecDesiredCameraOffset = vecOffset; } - Vector GetDesiredCameraOffset( void ); + void SetDesiredCameraOffset( const Vector& vecOffset ) { m_vecDesiredCameraOffset = vecOffset; } + const Vector& GetDesiredCameraOffset( void ) const { return m_vecDesiredCameraOffset; } Vector GetFinalCameraOffset( void ); - void SetCameraOrigin( Vector vecOffset ) { m_vecCameraOrigin = vecOffset; } - Vector GetCameraOrigin( void ) { return m_vecCameraOrigin; } + void SetCameraOrigin( const Vector& vecOffset ) { m_vecCameraOrigin = vecOffset; } + const Vector& GetCameraOrigin( void ) const { return m_vecCameraOrigin; } void Update( void ); - void PositionCamera( CBasePlayer *pPlayer, QAngle angles ); + void PositionCamera( CBasePlayer *pPlayer, const QAngle& angles ); void UseCameraOffsets( bool bUse ) { m_bUseCameraOffsets = bUse; } bool UsingCameraOffsets( void ) { return m_bUseCameraOffsets; } - QAngle GetCameraViewAngles( void ) { return m_ViewAngles; } + const QAngle& GetCameraViewAngles( void ) const { return m_ViewAngles; } Vector GetDistanceFraction( void ); diff --git a/mp/src/game/shared/effect_dispatch_data.cpp b/mp/src/game/shared/effect_dispatch_data.cpp index e295991f..8128468e 100644 --- a/mp/src/game/shared/effect_dispatch_data.cpp +++ b/mp/src/game/shared/effect_dispatch_data.cpp @@ -116,7 +116,7 @@ SendPropInt( SENDINFO_NOCHECK( m_nMaterial ), MAX_MODEL_INDEX_BITS, SPROP_UNSIGNED ), SendPropInt( SENDINFO_NOCHECK( m_nDamageType ), 32, SPROP_UNSIGNED ), - SendPropInt( SENDINFO_NOCHECK( m_nHitBox ), 11, SPROP_UNSIGNED ), + SendPropInt( SENDINFO_NOCHECK( m_nHitBox ), 12, SPROP_UNSIGNED ), SendPropInt( SENDINFO_NAME( m_nEntIndex, entindex ), MAX_EDICT_BITS, SPROP_UNSIGNED ), diff --git a/mp/src/game/shared/eventlist.cpp b/mp/src/game/shared/eventlist.cpp index 84014b49..f52f8021 100644 --- a/mp/src/game/shared/eventlist.cpp +++ b/mp/src/game/shared/eventlist.cpp @@ -249,4 +249,7 @@ void EventList_RegisterSharedEvents( void ) REGISTER_SHARED_ANIMEVENT( AE_WPN_PLAYWPNSOUND, AE_TYPE_CLIENT | AE_TYPE_SERVER ); REGISTER_SHARED_ANIMEVENT( AE_RD_ROBOT_POP_PANELS_OFF, AE_TYPE_CLIENT | AE_TYPE_SERVER ); + + REGISTER_SHARED_ANIMEVENT( AE_TAUNT_ENABLE_MOVE, AE_TYPE_CLIENT | AE_TYPE_SERVER ); + REGISTER_SHARED_ANIMEVENT( AE_TAUNT_DISABLE_MOVE, AE_TYPE_CLIENT | AE_TYPE_SERVER ); } \ No newline at end of file diff --git a/mp/src/game/shared/eventlist.h b/mp/src/game/shared/eventlist.h index c4944616..69c6f0ca 100644 --- a/mp/src/game/shared/eventlist.h +++ b/mp/src/game/shared/eventlist.h @@ -87,6 +87,9 @@ typedef enum AE_RD_ROBOT_POP_PANELS_OFF, + AE_TAUNT_ENABLE_MOVE, + AE_TAUNT_DISABLE_MOVE, + LAST_SHARED_ANIMEVENT, } Animevent; diff --git a/mp/src/game/shared/expressionsample.h b/mp/src/game/shared/expressionsample.h index 663328dc..006db6d0 100644 --- a/mp/src/game/shared/expressionsample.h +++ b/mp/src/game/shared/expressionsample.h @@ -69,6 +69,7 @@ private: class ICurveDataAccessor { public: + virtual ~ICurveDataAccessor(){} virtual float GetDuration() = 0; virtual bool CurveHasEndTime() = 0; // only matters for events virtual int GetDefaultCurveType() = 0; diff --git a/mp/src/game/shared/gamemovement.cpp b/mp/src/game/shared/gamemovement.cpp index 8b5921bd..76e4f22f 100644 --- a/mp/src/game/shared/gamemovement.cpp +++ b/mp/src/game/shared/gamemovement.cpp @@ -2147,7 +2147,7 @@ void CGameMovement::FullObserverMove( void ) { int mode = player->GetObserverMode(); - if ( mode == OBS_MODE_IN_EYE || mode == OBS_MODE_CHASE ) + if ( mode == OBS_MODE_IN_EYE || mode == OBS_MODE_CHASE || mode == OBS_MODE_POI ) { CBaseEntity * target = player->GetObserverTarget(); diff --git a/mp/src/game/shared/gamerules.h b/mp/src/game/shared/gamerules.h index 347f7941..5ba66820 100644 --- a/mp/src/game/shared/gamerules.h +++ b/mp/src/game/shared/gamerules.h @@ -418,6 +418,8 @@ public: virtual bool IsHolidayActive( /*EHoliday*/ int eHoliday ) const { return false; } + virtual bool IsManualMapChangeOkay( const char **pszReason ){ return true; } + #ifndef CLIENT_DLL private: float m_flNextVerboseLogOutput; diff --git a/mp/src/game/shared/mp_shareddefs.cpp b/mp/src/game/shared/mp_shareddefs.cpp index 66a5e0e3..a4204357 100644 --- a/mp/src/game/shared/mp_shareddefs.cpp +++ b/mp/src/game/shared/mp_shareddefs.cpp @@ -158,6 +158,7 @@ const char *g_pszMPConcepts[] = "TLK_PLAYER_CAST_MONOCULOUS", // MP_CONCEPT_PLAYER_CAST_MONOCULOUS "TLK_PLAYER_CAST_METEOR_SWARM", // MP_CONCEPT_PLAYER_CAST_METEOR_SWARM "TLK_PLAYER_CAST_SKELETON_HORDE", // MP_CONCEPT_PLAYER_CAST_SKELETON_HORDE + "TLK_PLAYER_CAST_BOMB_HEAD_CURSE", // MP_CONCEPT_PLAYER_CAST_BOMB_HEAD_CURSE "TLK_PLAYER_SPELL_FIREBALL", // MP_CONCEPT_PLAYER_SPELL_FIREBALL "TLK_PLAYER_SPELL_MERASMUS_ZAP", // MP_CONCEPT_PLAYER_SPELL_MERASMUS_ZAP @@ -171,6 +172,7 @@ const char *g_pszMPConcepts[] = "TLK_PLAYER_SPELL_MONOCULOUS", // MP_CONCEPT_PLAYER_SPELL_MONOCULOUS "TLK_PLAYER_SPELL_METEOR_SWARM", // MP_CONCEPT_PLAYER_SPELL_METEOR_SWARM "TLK_PLAYER_SPELL_SKELETON_HORDE", // MP_CONCEPT_PLAYER_SPELL_SKELETON_HORDE + "TLK_PLAYER_SPELL_BOMB_HEAD_CURSE", // MP_CONCEPT_PLAYER_SPELL_BOMB_HEAD_CURSE // Events. "TLK_PLAYER_SPELL_PICKUP_COMMON", // MP_CONCEPT_PLAYER_SPELL_PICKUP_COMMON @@ -189,6 +191,8 @@ const char *g_pszMPConcepts[] = "TLK_TAUNT_EUREKA_EFFECT", // MP_CONCEPT_TAUNT_EUREKA_EFFECT_TELEPORT "TLK_COMBO_KILLED", // MP_CONCEPT_COMBO_KILLED + + "TLK_PLAYER_ASK_FOR_BALL", // MP_CONCEPT_PLAYER_ASK_FOR_BALL }; COMPILE_TIME_ASSERT( ARRAYSIZE( g_pszMPConcepts ) == MP_TF_CONCEPT_COUNT ); diff --git a/mp/src/game/shared/mp_shareddefs.h b/mp/src/game/shared/mp_shareddefs.h index d0fa99c8..c65cbac2 100644 --- a/mp/src/game/shared/mp_shareddefs.h +++ b/mp/src/game/shared/mp_shareddefs.h @@ -167,6 +167,7 @@ enum MP_CONCEPT_PLAYER_CAST_MONOCULOUS, // "TLK_PLAYER_CAST_MONOCULOUS" MP_CONCEPT_PLAYER_CAST_METEOR_SWARM, // "TLK_PLAYER_CAST_METEOR_SWARM" MP_CONCEPT_PLAYER_CAST_SKELETON_HORDE, // "TLK_PLAYER_CAST_SKELETON_HORDE" + MP_CONCEPT_PLAYER_CAST_BOMB_HEAD_CURSE, // "TLK_PLAYER_CAST_BOMB_HEAD_CURSE" MP_CONCEPT_PLAYER_SPELL_FIREBALL, // "TLK_PLAYER_SPELL_FIREBALL" MP_CONCEPT_PLAYER_SPELL_MERASMUS_ZAP, // "TLK_PLAYER_SPELL_MERASMUS_ZAP" @@ -180,6 +181,7 @@ enum MP_CONCEPT_PLAYER_SPELL_MONOCULOUS, // "TLK_PLAYER_SPELL_MONOCULOUS" MP_CONCEPT_PLAYER_SPELL_METEOR_SWARM, // "TLK_PLAYER_SPELL_METEOR_SWARM" MP_CONCEPT_PLAYER_SPELL_SKELETON_HORDE, // "TLK_PLAYER_SPELL_SKELETON_HORDE" + MP_CONCEPT_PLAYER_SPELL_BOMB_HEAD_CURSE, // "TLK_PLAYER_SPELL_BOMB_HEAD_CURSE" // Events. MP_CONCEPT_PLAYER_SPELL_PICKUP_COMMON, // "TLK_PLAYER_SPELL_PICKUP_COMMON" @@ -198,6 +200,7 @@ enum MP_CONCEPT_TAUNT_EUREKA_EFFECT_TELEPORT,// "TLK_TAUNT_EUREKA_EFFECT" MP_CONCEPT_COMBO_KILLED, // "TLK_COMBO_KILLED" + MP_CONCEPT_PLAYER_ASK_FOR_BALL, // "TLK_PLAYER_ASK_FOR_BALL" MP_TF_CONCEPT_COUNT diff --git a/mp/src/game/shared/multiplay_gamerules.cpp b/mp/src/game/shared/multiplay_gamerules.cpp index 16cfe297..ae26bde6 100644 --- a/mp/src/game/shared/multiplay_gamerules.cpp +++ b/mp/src/game/shared/multiplay_gamerules.cpp @@ -85,7 +85,8 @@ ConVar mp_show_voice_icons( "mp_show_voice_icons", "1", FCVAR_REPLICATED, "Show #ifdef GAME_DLL -ConVar tv_delaymapchange( "tv_delaymapchange", "0", 0, "Delays map change until broadcast is complete" ); +ConVar tv_delaymapchange( "tv_delaymapchange", "0", FCVAR_NONE, "Delays map change until broadcast is complete" ); +ConVar tv_delaymapchange_protect( "tv_delaymapchange_protect", "1", FCVAR_NONE, "Protect against doing a manual map change if HLTV is broadcasting and has not caught up with a major game event such as round_end" ); ConVar mp_restartgame( "mp_restartgame", "0", FCVAR_GAMEDLL, "If non-zero, game will restart in the specified number of seconds" ); ConVar mp_restartgame_immediate( "mp_restartgame_immediate", "0", FCVAR_GAMEDLL, "If non-zero, game will restart immediately" ); @@ -278,7 +279,7 @@ CMultiplayRules::CMultiplayRules() if ( cfgfile && cfgfile[0] ) { - char szCommand[256]; + char szCommand[MAX_PATH]; Log( "Executing dedicated server config file %s\n", cfgfile ); Q_snprintf( szCommand,sizeof(szCommand), "exec %s\n", cfgfile ); @@ -292,7 +293,7 @@ CMultiplayRules::CMultiplayRules() if ( cfgfile && cfgfile[0] ) { - char szCommand[256]; + char szCommand[MAX_PATH]; Log( "Executing listen server config file %s\n", cfgfile ); Q_snprintf( szCommand,sizeof(szCommand), "exec %s\n", cfgfile ); @@ -1164,7 +1165,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); void CMultiplayRules::GetNextLevelName( char *pszNextMap, int bufsize, bool bRandom /* = false */ ) { - char mapcfile[256]; + char mapcfile[MAX_PATH]; DetermineMapCycleFilename( mapcfile, sizeof(mapcfile), false ); // Check the time of the mapcycle file and re-populate the list of level names if the file has been modified @@ -1182,10 +1183,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); // If map cycle file has changed or this is the first time through ... if ( m_nMapCycleTimeStamp != nMapCycleTimeStamp ) { - // Reset map index and map cycle timestamp - m_nMapCycleTimeStamp = nMapCycleTimeStamp; - m_nMapCycleindex = 0; - + // Reload LoadMapCycleFile(); } } @@ -1209,7 +1207,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); void CMultiplayRules::DetermineMapCycleFilename( char *pszResult, int nSizeResult, bool bForceSpew ) { - static char szLastResult[ 256]; + static char szLastResult[ MAX_PATH ]; const char *pszVar = mapcyclefile.GetString(); if ( *pszVar == '\0' ) @@ -1223,7 +1221,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); return; } - char szRecommendedName[ 256 ]; + char szRecommendedName[ MAX_PATH ]; V_sprintf_safe( szRecommendedName, "cfg/%s", pszVar ); // First, look for a mapcycle file in the cfg directory, which is preferred @@ -1274,7 +1272,12 @@ ConVarRef suitcharger( "sk_suitcharger" ); } } - void CMultiplayRules::LoapMapCycleFileIntoVector( const char *pszMapCycleFile, CUtlVector &mapList ) + void CMultiplayRules::LoadMapCycleFileIntoVector( const char *pszMapCycleFile, CUtlVector &mapList ) + { + CMultiplayRules::RawLoadMapCycleFileIntoVector( pszMapCycleFile, mapList ); + } + + void CMultiplayRules::RawLoadMapCycleFileIntoVector( const char *pszMapCycleFile, CUtlVector &mapList ) { CUtlBuffer buf; if ( !filesystem->ReadFile( pszMapCycleFile, "GAME", buf ) ) @@ -1293,13 +1296,6 @@ ConVarRef suitcharger( "sk_suitcharger" ); { bIgnore = true; } - else if ( !engine->IsMapValid( mapList[i] ) ) - { - bIgnore = true; - - // If the engine doesn't consider it a valid map remove it from the lists - Warning( "Invalid map '%s' included in map cycle file. Ignored.\n", mapList[i] ); - } if ( bIgnore ) { @@ -1321,6 +1317,27 @@ ConVarRef suitcharger( "sk_suitcharger" ); mapList.RemoveAll(); } + bool CMultiplayRules::IsManualMapChangeOkay( const char **pszReason ) + { + if ( HLTVDirector()->IsActive() && ( HLTVDirector()->GetDelay() >= HLTV_MIN_DIRECTOR_DELAY ) ) + { + if ( tv_delaymapchange.GetBool() && tv_delaymapchange_protect.GetBool() ) + { + float flLastEvent = GetLastMajorEventTime(); + if ( flLastEvent > -1 ) + { + if ( flLastEvent > ( gpGlobals->curtime - ( HLTVDirector()->GetDelay() + 3 ) ) ) // +3 second delay to prevent instant change after a major event + { + *pszReason = "\n***WARNING*** Map change blocked. HLTV is broadcasting and has not caught up to the last major game event yet.\nYou can disable this check by setting the value of the server convar \"tv_delaymapchange_protect\" to 0.\n"; + return false; + } + } + } + } + + return true; + } + bool CMultiplayRules::IsMapInMapCycle( const char *pszName ) { for ( int i = 0; i < m_MapList.Count(); i++ ) @@ -1338,7 +1355,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); { char szNextMap[MAX_MAP_NAME]; - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) + if ( nextlevel.GetString() && *nextlevel.GetString() ) { Q_strncpy( szNextMap, nextlevel.GetString(), sizeof( szNextMap ) ); } @@ -1353,13 +1370,19 @@ ConVarRef suitcharger( "sk_suitcharger" ); void CMultiplayRules::LoadMapCycleFile( void ) { - char mapcfile[256]; + int nOldCycleIndex = m_nMapCycleindex; + m_nMapCycleindex = 0; + + char mapcfile[MAX_PATH]; DetermineMapCycleFilename( mapcfile, sizeof(mapcfile), false ); FreeMapCycleFileVector( m_MapList ); + const int nMapCycleTimeStamp = filesystem->GetPathTime( mapcfile, "GAME" ); + m_nMapCycleTimeStamp = nMapCycleTimeStamp; + // Repopulate map list from mapcycle file - LoapMapCycleFileIntoVector( mapcfile, m_MapList ); + LoadMapCycleFileIntoVector( mapcfile, m_MapList ); // Load server's mapcycle into network string table for client-side voting if ( g_pStringTableServerMapCycle ) @@ -1466,16 +1489,29 @@ ConVarRef suitcharger( "sk_suitcharger" ); } #endif - // If the current map selection is in the list, set m_nMapCycleindex to the map that follows it. - for ( int i = 0; i < m_MapList.Count(); i++ ) + // If the current map is in the same location in the new map cycle, keep that index. This gives better behavior + // when reloading a map cycle that has the current map in it multiple times. + int nOldPreviousMap = ( nOldCycleIndex == 0 ) ? ( m_MapList.Count() - 1 ) : ( nOldCycleIndex - 1 ); + if ( nOldCycleIndex >= 0 && nOldCycleIndex < m_MapList.Count() && + nOldPreviousMap >= 0 && nOldPreviousMap < m_MapList.Count() && + V_strcmp( STRING( gpGlobals->mapname ), m_MapList[ nOldPreviousMap ] ) == 0 ) { - if ( V_strcmp( STRING( gpGlobals->mapname ), m_MapList[i] ) == 0 ) + // The old index is still valid, and falls after our current map in the new cycle, use it + m_nMapCycleindex = nOldCycleIndex; + } + else + { + // Otherwise, if the current map selection is in the list, set m_nMapCycleindex to the map that follows it. + for ( int i = 0; i < m_MapList.Count(); i++ ) { - m_nMapCycleindex = i; - IncrementMapCycleIndex(); - break; + if ( V_strcmp( STRING( gpGlobals->mapname ), m_MapList[i] ) == 0 ) + { + m_nMapCycleindex = i; + IncrementMapCycleIndex(); + break; + } } - } + } } void CMultiplayRules::ChangeLevelToMap( const char *pszMap ) @@ -1556,7 +1592,7 @@ ConVarRef suitcharger( "sk_suitcharger" ); Msg( "Skipping: %s\tNext map: %s\n", szSkippedMap, szNextMap ); - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) + if ( nextlevel.GetString() && *nextlevel.GetString() ) { Msg( "Warning! \"nextlevel\" is set to \"%s\" and will override the next map to be played.\n", nextlevel.GetString() ); } @@ -1624,10 +1660,6 @@ ConVarRef suitcharger( "sk_suitcharger" ); pPlayer->OnAchievementEarned( nAchievementID ); } } - else if ( FStrEq( pszCommand, "SendServerMapCycle" ) ) - { - LoadMapCycleFile(); - } } } diff --git a/mp/src/game/shared/multiplay_gamerules.h b/mp/src/game/shared/multiplay_gamerules.h index 08e06e4a..b74dd34f 100644 --- a/mp/src/game/shared/multiplay_gamerules.h +++ b/mp/src/game/shared/multiplay_gamerules.h @@ -239,20 +239,26 @@ public: virtual void GetNextLevelName( char *szNextMap, int bufsize, bool bRandom = false ); static void DetermineMapCycleFilename( char *pszResult, int nSizeResult, bool bForceSpew ); - static void LoapMapCycleFileIntoVector ( const char *pszMapCycleFile, CUtlVector &mapList ); + virtual void LoadMapCycleFileIntoVector ( const char *pszMapCycleFile, CUtlVector &mapList ); static void FreeMapCycleFileVector ( CUtlVector &mapList ); + // LoadMapCycleFileIntoVector without the fixups inherited versions of gamerules may provide + static void RawLoadMapCycleFileIntoVector ( const char *pszMapCycleFile, CUtlVector &mapList ); + bool IsMapInMapCycle( const char *pszName ); + virtual bool IsManualMapChangeOkay( const char **pszReason ) OVERRIDE; + protected: virtual bool UseSuicidePenalty() { return true; } // apply point penalty for suicide? + virtual float GetLastMajorEventTime( void ){ return -1.0f; } public: virtual void ChangeLevel( void ); protected: virtual void GoToIntermission( void ); - void LoadMapCycleFile( void ); + virtual void LoadMapCycleFile( void ); void ChangeLevelToMap( const char *pszMap ); float m_flIntermissionEndTime; diff --git a/mp/src/game/shared/particle_parse.cpp b/mp/src/game/shared/particle_parse.cpp index db15685d..28c559e2 100644 --- a/mp/src/game/shared/particle_parse.cpp +++ b/mp/src/game/shared/particle_parse.cpp @@ -567,4 +567,37 @@ void StopParticleEffects( CBaseEntity *pEntity ) } static ConCommand particle_test_stop("particle_test_stop", CC_Particle_Test_Stop, "Stops all particle systems on the selected entities.\n\tArguments: {entity_name} / {class_name} / no argument picks what player is looking at ", FCVAR_CHEAT); -#endif //CLIENT_DLL +#endif //!CLIENT_DLL + +#if defined( CLIENT_DLL ) && defined( STAGING_ONLY ) + + void CC_DispatchParticle( const CCommand& args ) + { + C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer(); + if ( !pLocalPlayer ) + return; + + if ( args.ArgC() < 2 ) + { + DevMsg( "Use: dispatch_particle {particle_name} {surface_offset_distance}\n" ); + return; + } + + float flSurfaceOffsetDistance = 0.f; + if ( args.ArgC() == 3 ) + { + flSurfaceOffsetDistance = atof( args[2] ); + } + + Vector vForward; + pLocalPlayer->GetVectors( &vForward, NULL, NULL ); + trace_t tr; + UTIL_TraceLine( pLocalPlayer->EyePosition(), pLocalPlayer->EyePosition() + vForward * 3000, MASK_SOLID_BRUSHONLY, NULL, &tr ); + + Vector vTargetDeathPos = tr.endpos; + DispatchParticleEffect( args[1], vTargetDeathPos + flSurfaceOffsetDistance * tr.plane.normal, vec3_angle ); + } + + static ConCommand dispatch_particle( "dispatch_particle", CC_DispatchParticle, "Dispatch specified particle effect 50 units away from the lookat surface normal.\n\tArguments: {particle_name} {surface_offset_distance}", FCVAR_CHEAT ); + +#endif // CLIENT_DLL && STAGING_ONLY diff --git a/mp/src/game/shared/particle_property.cpp b/mp/src/game/shared/particle_property.cpp index 5b5c2603..fe108721 100644 --- a/mp/src/game/shared/particle_property.cpp +++ b/mp/src/game/shared/particle_property.cpp @@ -618,7 +618,9 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i if ( !pAnimating->C_BaseAnimating::GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) { Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() ); - attachmentToWorld = pAnimating->RenderableToWorldTransform(); + // Remove the effect cause this warning means something is orphaned + StopParticlesNamed( pEffect->pParticleEffect->GetEffectName() ); + return; } } @@ -627,7 +629,7 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i MatrixVectors( vMat.As3x4(), &vecForward, &vecRight, &vecUp ); MatrixPosition( vMat.As3x4(), vecOrigin ); - if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) + if ( pEffect->pParticleEffect->GetIsViewModelEffect() ) { FormatViewModelAttachment( vecOrigin, true ); } diff --git a/mp/src/game/shared/ragdoll_shared.cpp b/mp/src/game/shared/ragdoll_shared.cpp index e77e9a75..0fc50772 100644 --- a/mp/src/game/shared/ragdoll_shared.cpp +++ b/mp/src/game/shared/ragdoll_shared.cpp @@ -40,7 +40,7 @@ void CRagdollLowViolenceManager::SetLowViolence( const char *pMapName ) #if !defined( CLIENT_DLL ) // the server doesn't worry about low violence during multiplayer games - if ( g_pGameRules->IsMultiplayer() ) + if ( g_pGameRules && g_pGameRules->IsMultiplayer() ) { m_bLowViolence = false; } @@ -742,8 +742,12 @@ bool ShouldRemoveThisRagdoll( CBaseAnimating *pRagdoll ) return false; */ + // Bail if we have a null ragdoll pointer. + if ( !pRagdoll->m_pRagdoll ) + return true; + Vector vMins, vMaxs; - + Vector origin = pRagdoll->m_pRagdoll->GetRagdollOrigin(); pRagdoll->m_pRagdoll->GetRagdollBounds( vMins, vMaxs ); diff --git a/mp/src/game/shared/shareddefs.h b/mp/src/game/shared/shareddefs.h index 11156a36..5236693f 100644 --- a/mp/src/game/shared/shareddefs.h +++ b/mp/src/game/shared/shareddefs.h @@ -151,6 +151,8 @@ typedef enum VOTE_FAILED_MAP_NOT_VALID, VOTE_FAILED_CANNOT_KICK_FOR_TIME, VOTE_FAILED_CANNOT_KICK_DURING_ROUND, + VOTE_FAILED_VOTE_IN_PROGRESS, + VOTE_FAILED_KICK_LIMIT_REACHED, // TF-specific? VOTE_FAILED_MODIFICATION_ALREADY_ACTIVE, @@ -455,6 +457,7 @@ enum { OBS_MODE_FIXED, // view from a fixed camera position OBS_MODE_IN_EYE, // follow a player in first person view OBS_MODE_CHASE, // follow a player in third person view + OBS_MODE_POI, // PASSTIME point of interest - game objective, big fight, anything interesting; added in the middle of the enum due to tons of hard-coded "IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) + { + pszRetVal = MERASMUS_SETUP_5SECS; + } + else +#endif + { + pszRetVal = ROUND_SETUP_5SECS; + } } else { @@ -585,7 +610,16 @@ const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) case RT_WARNING_4SECS: if ( m_nState == RT_STATE_SETUP ) { - pszRetVal = ROUND_SETUP_4SECS; +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) + { + pszRetVal = MERASMUS_SETUP_4SECS; + } + else +#endif + { + pszRetVal = ROUND_SETUP_4SECS; + } } else { @@ -595,7 +629,16 @@ const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) case RT_WARNING_3SECS: if ( m_nState == RT_STATE_SETUP ) { - pszRetVal = ROUND_SETUP_3SECS; +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) + { + pszRetVal = MERASMUS_SETUP_3SECS; + } + else +#endif + { + pszRetVal = ROUND_SETUP_3SECS; + } } else { @@ -605,7 +648,16 @@ const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) case RT_WARNING_2SECS: if ( m_nState == RT_STATE_SETUP ) { - pszRetVal = ROUND_SETUP_2SECS; +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) + { + pszRetVal = MERASMUS_SETUP_2SECS; + } + else +#endif + { + pszRetVal = ROUND_SETUP_2SECS; + } } else { @@ -615,7 +667,16 @@ const char *CTeamRoundTimer::GetTimeWarningSound( int nWarning ) case RT_WARNING_1SECS: if ( m_nState == RT_STATE_SETUP ) { - pszRetVal = ROUND_SETUP_1SECS; +#ifdef TF_CLIENT_DLL + if ( TFGameRules() && TFGameRules()->IsHalloweenScenario( CTFGameRules::HALLOWEEN_SCENARIO_DOOMSDAY ) ) + { + pszRetVal = MERASMUS_SETUP_1SECS; + } + else +#endif + { + pszRetVal = ROUND_SETUP_1SECS; + } } else { diff --git a/mp/src/game/shared/teamplay_round_timer.h b/mp/src/game/shared/teamplay_round_timer.h index fd2e7613..df94a271 100644 --- a/mp/src/game/shared/teamplay_round_timer.h +++ b/mp/src/game/shared/teamplay_round_timer.h @@ -80,7 +80,7 @@ public: bool IsStopWatchTimer( void ) { return m_bStopWatchTimer; } float GetStopWatchTotalTime( void ) { return m_flTotalTime; } bool IsRoundMaxTimerSet( void ) { return m_nTimerMaxLength > 0; } - + int GetTimerInitialLength( void ) { return m_nTimerInitialLength; } private: void CalculateOutputMessages( void ); diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.cpp b/mp/src/game/shared/teamplayroundbased_gamerules.cpp index 3930798d..8d2b3e00 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.cpp +++ b/mp/src/game/shared/teamplayroundbased_gamerules.cpp @@ -35,17 +35,15 @@ #if defined(TF_CLIENT_DLL) || defined(TF_DLL) #include "tf_gamerules.h" - #if defined(TF_CLIENT_DLL) || defined(TF_DLL) - #include "tf_lobby.h" - #ifdef GAME_DLL - #include "player_vs_environment/tf_population_manager.h" - #include "../server/tf/tf_gc_server.h" - #include "../server/tf/tf_objective_resource.h" - #else - #include "../client/tf/tf_gc_client.h" - #include "../client/tf/c_tf_objective_resource.h" - #endif // GAME_DLL - #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) + #include "tf_lobby.h" + #ifdef GAME_DLL + #include "player_vs_environment/tf_population_manager.h" + #include "../server/tf/tf_gc_server.h" + #include "../server/tf/tf_objective_resource.h" + #else + #include "../client/tf/tf_gc_client.h" + #include "../client/tf/c_tf_objective_resource.h" + #endif // GAME_DLL #endif // memdbgon must be the last include file in a .cpp file!!! @@ -196,9 +194,14 @@ ConVar mp_maxrounds( "mp_maxrounds", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "max ConVar mp_winlimit( "mp_winlimit", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Max score one team can reach before server changes maps", true, 0, false, 0 ); ConVar mp_disable_respawn_times( "mp_disable_respawn_times", "0", FCVAR_NOTIFY | FCVAR_REPLICATED ); ConVar mp_bonusroundtime( "mp_bonusroundtime", "15", FCVAR_REPLICATED, "Time after round win until round restarts", true, 5, true, 15 ); +ConVar mp_bonusroundtime_final( "mp_bonusroundtime_final", "15", FCVAR_REPLICATED, "Time after final round ends until round restarts", true, 5, true, 300 ); ConVar mp_stalemate_meleeonly( "mp_stalemate_meleeonly", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Restrict everyone to melee weapons only while in Sudden Death." ); ConVar mp_forceautoteam( "mp_forceautoteam", "0", FCVAR_REPLICATED | FCVAR_NOTIFY, "Automatically assign players to teams when joining." ); +#if defined( _DEBUG ) || defined( STAGING_ONLY ) +ConVar mp_developer( "mp_developer", "0", FCVAR_ARCHIVE | FCVAR_REPLICATED | FCVAR_NOTIFY, "1: basic conveniences (instant respawn and class change, etc). 2: add combat conveniences (infinite ammo, buddha, etc)" ); +#endif // _DEBUG || STAGING_ONLY + #ifdef GAME_DLL ConVar mp_showroundtransitions( "mp_showroundtransitions", "0", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY, "Show gamestate round transitions." ); ConVar mp_enableroundwaittime( "mp_enableroundwaittime", "1", FCVAR_REPLICATED, "Enable timers to wait between rounds." ); @@ -358,25 +361,21 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_flNextRespawnWave.Set( i, 0 ); m_TeamRespawnWaveTimes.Set( i, -1.0f ); - m_bTeamReady.Set( i, false ); - #ifdef GAME_DLL m_flOriginalTeamRespawnWaveTime[i] = -1.0f; #endif } - for ( int i = 0; i < MAX_PLAYERS; i++ ) - { - m_bPlayerReady.Set( i, false ); - } - m_bInOvertime = false; m_bInSetup = false; m_bSwitchedTeamsThisRound = false; m_flStopWatchTotalTime = -1.0f; m_bMultipleTrains = false; + m_bAllowBetweenRounds = true; #ifdef GAME_DLL + ListenForGameEvent( "server_changelevel_failed" ); + m_pCurStateInfo = NULL; State_Transition( GR_STATE_PREGAME ); @@ -390,8 +389,8 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) SetRoundToPlayNext( NULL_STRING ); m_bInWaitingForPlayers = false; m_bAwaitingReadyRestart = false; - m_flRestartRoundTime = -1; - m_flMapResetTime = 0; + m_flRestartRoundTime = -1.0f; + m_flMapResetTime = 0.0f; m_bPrevRoundWasWaitingForPlayers = false; m_iWinningTeam = TEAM_UNASSIGNED; @@ -400,12 +399,13 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_bAllowStalemateAtTimelimit = false; m_bChangelevelAfterStalemate = false; - m_flRoundStartTime = 0; - m_flNewThrottledAlertTime = 0; - m_flStartBalancingTeamsAt = 0; + m_flRoundStartTime = 0.0f; + m_flNewThrottledAlertTime = 0.0f; + m_flStartBalancingTeamsAt = 0.0f; m_bPrintedUnbalanceWarning = false; - m_flFoundUnbalancedTeamsTime = -1; + m_flFoundUnbalancedTeamsTime = -1.0f; m_flWaitingForPlayersTimeEnds = 0.0f; + m_flLastTeamWin = -1.0f; m_nRoundsPlayed = 0; m_bUseAddScoreAnim = false; @@ -413,18 +413,20 @@ CTeamplayRoundBasedRules::CTeamplayRoundBasedRules( void ) m_bStopWatch = false; m_bAwaitingReadyRestart = false; - if ( IsInTournamentMode() == true ) + if ( IsInTournamentMode() ) { m_bAwaitingReadyRestart = true; } - m_flAutoBalanceQueueTimeEnd = -1; + m_flAutoBalanceQueueTimeEnd = -1.0f; m_nAutoBalanceQueuePlayerIndex = -1; m_nAutoBalanceQueuePlayerScore = -1; SetDefLessFunc( m_GameTeams ); m_bCheatsEnabledDuringLevel = false; + ResetPlayerAndTeamReadyState(); + #endif } @@ -580,6 +582,22 @@ float CTeamplayRoundBasedRules::GetRespawnTimeScalar( int iTeam ) return flScale; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamplayRoundBasedRules::FireGameEvent( IGameEvent * event ) +{ +#ifdef GAME_DLL + const char *eventName = event->GetName(); + if ( g_fGameOver && !Q_strcmp( eventName, "server_changelevel_failed" ) ) + { + Warning( "In gameover, but failed to load the next map. Trying next map in cycle.\n" ); + nextlevel.SetValue( "" ); + ChangeLevel(); + } +#endif +} + #ifdef GAME_DLL //----------------------------------------------------------------------------- // Purpose: @@ -616,7 +634,7 @@ void CTeamplayRoundBasedRules::Think( void ) // Don't run this code again m_flIntermissionEndTime = 0.f; - } + } return; } @@ -853,7 +871,14 @@ void CTeamplayRoundBasedRules::CheckWaitingForPlayers( void ) mp_waitingforplayers_restart.SetValue( 0 ); } - if( (mp_waitingforplayers_cancel.GetBool() || IsInItemTestingMode()) && IsInTournamentMode() == false ) + bool bCancelWait = ( mp_waitingforplayers_cancel.GetBool() || IsInItemTestingMode() ) && !IsInTournamentMode(); + +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + bCancelWait = true; +#endif // _DEBUG || STAGING_ONLY + + if ( bCancelWait ) { // Cancel the wait period and manually Resume() the timer if // it's not supposed to start paused at the beginning of a round. @@ -975,11 +1000,7 @@ void CTeamplayRoundBasedRules::CheckRestartRound( void ) int iDelayMax = 60; #if defined(TF_CLIENT_DLL) || defined(TF_DLL) -#ifdef STAGING_ONLY - if ( TFGameRules() && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsRatedTournamentMode() ) ) -#else - if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) -#endif // STAGING_ONLY + if ( TFGameRules() && ( TFGameRules()->IsMannVsMachineMode() || TFGameRules()->IsCompetitiveMode() ) ) { iDelayMax = 180; } @@ -1068,7 +1089,7 @@ void CTeamplayRoundBasedRules::CheckRestartRound( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckTimeLimit( void ) +bool CTeamplayRoundBasedRules::CheckTimeLimit( bool bAllowEnd /*= true*/ ) { if ( IsInPreMatch() == true ) return false; @@ -1095,18 +1116,21 @@ bool CTeamplayRoundBasedRules::CheckTimeLimit( void ) bSwitchDueToTime = false; } - if( GetTimeLeft() <= 0 || m_bChangelevelAfterStalemate || bSwitchDueToTime ) + if ( GetTimeLeft() <= 0 || m_bChangelevelAfterStalemate || bSwitchDueToTime ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Time Limit" ); - gameeventmanager->FireEvent( event ); + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Time Limit" ); + gameeventmanager->FireEvent( event ); + } + + SendTeamScoresEvent(); + + GoToIntermission(); } - - SendTeamScoresEvent(); - - GoToIntermission(); return true; } } @@ -1145,20 +1169,23 @@ int CTeamplayRoundBasedRules::GetTimeLeft( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckNextLevelCvar( void ) +bool CTeamplayRoundBasedRules::CheckNextLevelCvar( bool bAllowEnd /*= true*/ ) { if ( m_bForceMapReset ) { - if ( nextlevel.GetString() && *nextlevel.GetString() && engine->IsMapValid( nextlevel.GetString() ) ) + if ( nextlevel.GetString() && *nextlevel.GetString() ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "NextLevel CVAR" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "NextLevel CVAR" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1169,7 +1196,7 @@ bool CTeamplayRoundBasedRules::CheckNextLevelCvar( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckWinLimit( void ) +bool CTeamplayRoundBasedRules::CheckWinLimit( bool bAllowEnd /*= true*/ ) { // has one team won the specified number of rounds? int iWinLimit = mp_winlimit.GetInt(); @@ -1183,14 +1210,17 @@ bool CTeamplayRoundBasedRules::CheckWinLimit( void ) if ( pTeam->GetScore() >= iWinLimit ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Win Limit" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Win Limit" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1202,20 +1232,23 @@ bool CTeamplayRoundBasedRules::CheckWinLimit( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::CheckMaxRounds() +bool CTeamplayRoundBasedRules::CheckMaxRounds( bool bAllowEnd /*= true*/ ) { if ( mp_maxrounds.GetInt() > 0 && IsInPreMatch() == false ) { if ( m_nRoundsPlayed >= mp_maxrounds.GetInt() ) { - IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); - if ( event ) + if ( bAllowEnd ) { - event->SetString( "reason", "Reached Round Limit" ); - gameeventmanager->FireEvent( event ); - } + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_game_over" ); + if ( event ) + { + event->SetString( "reason", "Reached Round Limit" ); + gameeventmanager->FireEvent( event ); + } - GoToIntermission(); + GoToIntermission(); + } return true; } } @@ -1435,17 +1468,17 @@ void CTeamplayRoundBasedRules::State_Enter_PREROUND( void ) m_flStateTransitionTime = gpGlobals->curtime + tf_arena_preround_time.GetInt(); } #if defined(TF_CLIENT_DLL) || defined(TF_DLL) - else if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + // Only allow at the very beginning of the game, or between waves in mvm + else if ( TFGameRules() && TFGameRules()->UsePlayerReadyStatusMode() && m_bAllowBetweenRounds ) { State_Transition( GR_STATE_BETWEEN_RNDS ); - TFObjectiveResource()->SetMannVsMachineBetweenWaves( true ); + m_bAllowBetweenRounds = false; + + if ( TFGameRules()->IsMannVsMachineMode() ) + { + TFObjectiveResource()->SetMannVsMachineBetweenWaves( true ); + } } -#ifdef STAGING_ONLY - else if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) - { - State_Transition( GR_STATE_BETWEEN_RNDS ); - } -#endif // STAGING_ONLY #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) else { @@ -1527,28 +1560,33 @@ void CTeamplayRoundBasedRules::State_Enter_RND_RUNNING( void ) void CTeamplayRoundBasedRules::CheckReadyRestart( void ) { // check round restart - if( m_flRestartRoundTime > 0 && m_flRestartRoundTime <= gpGlobals->curtime && !g_pServerBenchmark->IsBenchmarkRunning() ) + if ( m_flRestartRoundTime > 0 && m_flRestartRoundTime <= gpGlobals->curtime && !g_pServerBenchmark->IsBenchmarkRunning() ) { m_flRestartRoundTime = -1; #ifdef TF_DLL if ( TFGameRules() ) { - if ( TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + if ( TFGameRules()->IsMannVsMachineMode() ) { - if ( TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) + if ( g_pPopulationManager && TFObjectiveResource()->GetMannVsMachineIsBetweenWaves() ) { g_pPopulationManager->StartCurrentWave(); + m_bAllowBetweenRounds = true; return; } } -#ifdef STAGING_ONLY - else if ( TFGameRules()->IsRatedTournamentMode() ) + else if ( TFGameRules()->IsCompetitiveMode() ) { - TFGameRules()->StartRatedTournamentMatch(); + TFGameRules()->StartCompetitiveMatch(); + return; + } + else if ( mp_tournament.GetBool() ) + { + // Temp + TFGameRules()->StartCompetitiveMatch(); return; } -#endif // STAGING_ONLY } #endif // TF_DLL @@ -1556,34 +1594,28 @@ void CTeamplayRoundBasedRules::CheckReadyRestart( void ) State_Transition( GR_STATE_RESTART ); } - // check ready restart - if( m_bAwaitingReadyRestart ) - { - int nTime = 5; - bool bTeamReady = false; + bool bProcessReadyRestart = m_bAwaitingReadyRestart; #ifdef TF_DLL - if ( TFGameRules() ) - { - if ( TFGameRules()->IsMannVsMachineMode() ) - { - bTeamReady = AreDefendingPlayersReady(); - if ( bTeamReady ) - { - nTime = 10; - } - } - else - { - bTeamReady = m_bTeamReady[TF_TEAM_BLUE] && m_bTeamReady[TF_TEAM_RED]; - } - } + bProcessReadyRestart &= TFGameRules() && !TFGameRules()->UsePlayerReadyStatusMode(); #endif // TF_DLL - if ( bTeamReady ) + // check ready restart + if ( bProcessReadyRestart ) + { + bool bTeamNotReady = false; + for ( int i = LAST_SHARED_TEAM + 1; i < GetNumberOfTeams(); i++ ) { - //State_Transition( GR_STATE_RESTART ); - mp_restartgame.SetValue( nTime ); + if ( !m_bTeamReady[i] ) + { + bTeamNotReady = true; + break; + } + } + + if ( !bTeamNotReady ) + { + mp_restartgame.SetValue( 5 ); m_bAwaitingReadyRestart = false; ShouldResetScores( true, true ); @@ -1596,31 +1628,31 @@ void CTeamplayRoundBasedRules::CheckReadyRestart( void ) //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() +bool CTeamplayRoundBasedRules::AreLobbyPlayersOnTeamReady( int iTeam ) { - // Get list of defenders - CUtlVector vecMvMDefenders; - GetMvMPotentialDefendersLobbyPlayerInfo( vecMvMDefenders ); + if ( !TFGameRules() ) + return false; + + if ( TFGameRules()->IsMannVsMachineMode() && iTeam == TF_TEAM_PVE_INVADERS ) + return true; - // Scan all the players, and bail as soon as we find one person - // worth waiting for bool bAtLeastOnePersonReady = false; - for ( int i = 0; i < vecMvMDefenders.Count(); i++ ) + + CUtlVector vecLobbyPlayers; + GetPotentialPlayersLobbyPlayerInfo( vecLobbyPlayers ); + + for ( int i = 0; i < vecLobbyPlayers.Count(); i++ ) { - - // Are they on the red team? - const LobbyPlayerInfo_t &p = vecMvMDefenders[i]; - if ( !p.m_bConnected || p.m_iTeam == TEAM_UNASSIGNED || p.m_nEntNum <= 0 || p.m_nEntNum >= MAX_PLAYERS ) + const LobbyPlayerInfo_t &p = vecLobbyPlayers[i]; + + // Make sure all lobby players are connected + if ( !AreLobbyPlayersConnected() ) { - // They're still getting set up. We'll wait for them, - // but only if they are in the lobby - if ( p.m_bInLobby ) - return false; + return false; } - else if ( p.m_iTeam == TF_TEAM_PVE_DEFENDERS ) + // All are connected, make sure their team is ready + else if ( p.m_iTeam == iTeam ) { - - // If he isn't ready, then we aren't ready if ( !m_bPlayerReady[ p.m_nEntNum ] ) return false; @@ -1629,8 +1661,12 @@ bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() } else { - // And you may ask yourself, "How did I get here?" - Assert( p.m_iTeam == TF_TEAM_PVE_DEFENDERS ); + // In MvM, only the red team should pass through here + if ( TFGameRules()->IsMannVsMachineMode() ) + { + // And you may ask yourself, "How did I get here?" + Assert( p.m_iTeam == iTeam ); + } } } @@ -1639,6 +1675,32 @@ bool CTeamplayRoundBasedRules::AreDefendingPlayersReady() return bAtLeastOnePersonReady; } +//----------------------------------------------------------------------------- +// Purpose: Is everyone in the lobby connected to the server? +//----------------------------------------------------------------------------- +bool CTeamplayRoundBasedRules::AreLobbyPlayersConnected( void ) +{ + CUtlVector vecLobbyPlayers; + GetPotentialPlayersLobbyPlayerInfo( vecLobbyPlayers ); + + // If you're calling this, you should have lobby members + Assert( vecLobbyPlayers.Count() ); + + for ( int i = 0; i < vecLobbyPlayers.Count(); i++ ) + { + const LobbyPlayerInfo_t &pLobbyPlayer = vecLobbyPlayers[i]; + if ( !pLobbyPlayer.m_bConnected || + pLobbyPlayer.m_nEntNum <= 0 || + pLobbyPlayer.m_nEntNum >= MAX_PLAYERS || + ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && pLobbyPlayer.m_iTeam == TEAM_UNASSIGNED ) ) + { + if ( pLobbyPlayer.m_bInLobby ) + return false; + } + } + + return true; +} #endif // #if defined(TF_CLIENT_DLL) || defined(TF_DLL) //----------------------------------------------------------------------------- @@ -1657,6 +1719,15 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) } #endif +#ifdef TF_DLL + // Mass time-out? Clean everything up. + if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() ) + { + TFGameRules()->EndCompetitiveMatch(); + return; + } +#endif // TF_DLL + State_Transition( GR_STATE_PREGAME ); return; } @@ -1672,9 +1743,8 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) // check round restart CheckReadyRestart(); - // See if we're coming up to the server timelimit, in which case force a stalemate immediately. - if ( State_Get() == GR_STATE_RND_RUNNING && mp_timelimit.GetInt() > 0 && IsInPreMatch() == false && GetTimeLeft() <= 0 ) + if ( mp_timelimit.GetInt() > 0 && IsInPreMatch() == false && GetTimeLeft() <= 0 ) { if ( m_bAllowStalemateAtTimelimit || ( mp_match_end_at_timelimit.GetBool() && !IsValveMap() ) ) { @@ -1730,9 +1800,7 @@ void CTeamplayRoundBasedRules::State_Think_RND_RUNNING( void ) //----------------------------------------------------------------------------- void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) { - float flTime = GetBonusRoundTime(); - - m_flStateTransitionTime = gpGlobals->curtime + flTime; + m_flStateTransitionTime = gpGlobals->curtime + GetBonusRoundTime(); // if we're forcing the map to reset it must be the end of a "full" round not a mini-round if ( m_bForceMapReset ) @@ -1744,18 +1812,14 @@ void CTeamplayRoundBasedRules::State_Enter_TEAM_WIN( void ) SendWinPanelInfo(); -#ifdef STAGING_ONLY #ifdef TF_DLL - if ( TFGameRules() && TFGameRules()->IsRatedTournamentMode() ) + // Do this now, so players don't leave before the usual CheckWinLimit() call happens + bool bDone = ( CheckTimeLimit( false ) || CheckWinLimit( false ) || CheckMaxRounds( false ) || CheckNextLevelCvar( false ) ); + if ( TFGameRules() && TFGameRules()->IsCompetitiveMode() && bDone ) { - // Do this now, so players don't leave before the usual CheckWinLimit() call happens - if ( CheckWinLimit() ) - { - TFGameRules()->SkillRating_CalculateAdjustmentForTeams( m_iWinningTeam ); - } + TFGameRules()->StopCompetitiveMatch( CMsgGC_Match_Result_Status_MATCH_SUCCEEDED ); } #endif // TF_DLL -#endif // STAGING_ONLY } //----------------------------------------------------------------------------- @@ -1773,10 +1837,10 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) } #endif // TF_DLL - bool bDone = !(!CheckTimeLimit() && !CheckWinLimit() && !CheckMaxRounds() && !CheckNextLevelCvar()); + bool bDone = ( CheckTimeLimit() || CheckWinLimit() || CheckMaxRounds() || CheckNextLevelCvar() ); // check the win limit, max rounds, time limit and nextlevel cvar before starting the next round - if ( bDone == false ) + if ( !bDone ) { PreviousRoundEnd(); @@ -1797,7 +1861,7 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) State_Transition( GR_STATE_PREROUND ); } } - else if ( IsInTournamentMode() == true ) + else if ( IsInTournamentMode() ) { for ( int i = 1; i <= MAX_PLAYERS; i++ ) { @@ -1811,7 +1875,7 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) RestartTournament(); - if ( IsInArenaMode() == true ) + if ( IsInArenaMode() ) { #if defined( REPLAY_ENABLED ) if ( g_pReplay ) @@ -1823,33 +1887,43 @@ void CTeamplayRoundBasedRules::State_Think_TEAM_WIN( void ) State_Transition( GR_STATE_PREROUND ); } - else - { #ifdef TF_DLL - if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + else if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() && g_pPopulationManager ) + { + // one of the convars mp_timelimit, mp_winlimit, mp_maxrounds, or nextlevel has been triggered + for ( int i = 1; i <= MAX_PLAYERS; i++ ) { - // one of the convars mp_timelimit, mp_winlimit, mp_maxrounds, or nextlevel has been triggered - if ( g_pPopulationManager ) - { - for ( int i = 1; i <= MAX_PLAYERS; i++ ) - { - CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; - if ( !pPlayer ) - continue; - - pPlayer->AddFlag( FL_FROZEN ); - pPlayer->ShowViewPortPanel( PANEL_SCOREBOARD ); - } - - g_fGameOver = true; - g_pPopulationManager->SetMapRestartTime( gpGlobals->curtime + 10.0f ); - State_Enter( GR_STATE_GAME_OVER ); - return; - } + pPlayer->AddFlag( FL_FROZEN ); } + g_fGameOver = true; + g_pPopulationManager->SetMapRestartTime( gpGlobals->curtime + 10.0f ); + State_Enter( GR_STATE_GAME_OVER ); + return; + } + else if ( TFGameRules() && TFGameRules()->UsePlayerReadyStatusMode() ) + { + for ( int i = 1; i <= MAX_PLAYERS; i++ ) + { + CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); + if ( !pPlayer ) + continue; + + pPlayer->AddFlag( FL_FROZEN ); + } + + g_fGameOver = true; + State_Enter( GR_STATE_GAME_OVER ); + m_flStateTransitionTime = gpGlobals->curtime + GetBonusRoundTime( true ); + return; + } #endif // TF_DLL + else + { State_Transition( GR_STATE_RND_RUNNING ); } } @@ -2180,7 +2254,7 @@ int TeamScoreSort( CTeam* const *pTeam1, CTeam* const *pTeam2 ) //----------------------------------------------------------------------------- // Purpose: Input for other entities to declare a round winner. //----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false*/, bool bDontAddScore /* = false*/ ) +void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bForceMapReset /* = true */, bool bSwitchTeams /* = false*/, bool bDontAddScore /* = false*/, bool bFinal /*= false*/ ) { // Commentary doesn't let anyone win if ( IsInCommentaryMode() ) @@ -2224,6 +2298,8 @@ void CTeamplayRoundBasedRules::SetWinningTeam( int team, int iWinReason, bool bF State_Transition( GR_STATE_TEAM_WIN ); + m_flLastTeamWin = gpGlobals->curtime; + IGameEvent *event = gameeventmanager->CreateEvent( "teamplay_round_win" ); if ( event ) { @@ -2438,6 +2514,10 @@ void CTeamplayRoundBasedRules::RestartTournament( void ) m_flStopWatchTotalTime = -1.0f; m_bStopWatch = false; + // we might have had a stalemate during the last round + // so reset this bool each time we restart the tournament + m_bChangelevelAfterStalemate = false; + for ( int i = 0; i < MAX_TEAMS; i++ ) { m_bTeamReady.Set( i, false ); @@ -2579,6 +2659,30 @@ void CTeamplayRoundBasedRules::HandleTimeLimitChange( void ) } } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTeamplayRoundBasedRules::ResetPlayerAndTeamReadyState( void ) +{ + for ( int i = 0; i < MAX_TEAMS; i++ ) + { + m_bTeamReady.Set( i, false ); + } + + for ( int i = 0; i < MAX_PLAYERS; i++ ) + { + m_bPlayerReady.Set( i, false ); + } + +#ifdef GAME_DLL + // Note <= MAX_PLAYERS vs < MAX_PLAYERS above + for ( int i = 0; i <= MAX_PLAYERS; i++ ) + { + m_bPlayerReadyBefore[i] = false; + } +#endif // GAME_DLL +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -2606,6 +2710,12 @@ void CTeamplayRoundBasedRules::CreateTimeLimitTimer( void ) if ( IsInArenaMode () == true || IsInKothMode() == true ) return; + // this is the same check we use in State_Think_RND_RUNNING() + // don't show the timelimit timer if we're not going to end the map when it runs out + bool bAllowStalemate = ( m_bAllowStalemateAtTimelimit || ( mp_match_end_at_timelimit.GetBool() && !IsValveMap() ) ); + if ( !bAllowStalemate ) + return; + #ifndef CSTRIKE_DLL if ( !m_hTimeLimitTimer ) { @@ -2886,6 +2996,11 @@ void CTeamplayRoundBasedRules::BalanceTeams( bool bRequireSwitcheesToBeDead ) return; } +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return; +#endif // _DEBUG || STAGING_ONLY + if ( IsInTraining() || IsInItemTestingMode() ) { return; @@ -3314,9 +3429,12 @@ bool CTeamplayRoundBasedRules::IsInHighlanderMode( void ) #endif } -int CTeamplayRoundBasedRules::GetBonusRoundTime( void ) +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CTeamplayRoundBasedRules::GetBonusRoundTime( bool bFinal /*= false*/ ) { - return MAX( 5, mp_bonusroundtime.GetFloat() ); + return bFinal ? mp_bonusroundtime_final.GetInt() : Max( 5, mp_bonusroundtime.GetInt() ); } //----------------------------------------------------------------------------- @@ -3330,6 +3448,11 @@ bool CTeamplayRoundBasedRules::ShouldBalanceTeams( void ) if ( IsInTraining() == true || IsInItemTestingMode() ) return false; +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return false; +#endif // _DEBUG || STAGING_ONLY + if ( mp_teams_unbalance_limit.GetInt() <= 0 ) return false; @@ -3349,6 +3472,11 @@ bool CTeamplayRoundBasedRules::WouldChangeUnbalanceTeams( int iNewTeam, int iCur if ( ShouldBalanceTeams() == false ) return false; +#if defined( _DEBUG ) || defined( STAGING_ONLY ) + if ( mp_developer.GetBool() ) + return false; +#endif // _DEBUG || STAGING_ONLY + // if they are joining a non-playing team, allow if ( iNewTeam < FIRST_GAME_TEAM ) return false; @@ -3524,25 +3652,30 @@ void CTeamplayRoundBasedRules::ResetTeamsRoundWinTracking( void ) //----------------------------------------------------------------------------- // Purpose: Are you now, or are you ever going to be, a member of the defending party? //----------------------------------------------------------------------------- -void CTeamplayRoundBasedRules::GetMvMPotentialDefendersLobbyPlayerInfo( CUtlVector &vecMvMDefenders, bool bIncludeBots /*= false*/ ) +void CTeamplayRoundBasedRules::GetPotentialPlayersLobbyPlayerInfo( CUtlVector &vecLobbyPlayers, bool bIncludeBots /*= false*/ ) { - GetAllPlayersLobbyInfo( vecMvMDefenders, bIncludeBots ); + GetAllPlayersLobbyInfo( vecLobbyPlayers, bIncludeBots ); // Now scan through and remove the spectators - for (int i = vecMvMDefenders.Count() - 1 ; i >= 0 ; --i ) + for ( int i = vecLobbyPlayers.Count() - 1; i >= 0; --i ) { - switch ( vecMvMDefenders[i].m_iTeam ) + switch ( vecLobbyPlayers[i].m_iTeam ) { case TEAM_UNASSIGNED: - case TF_TEAM_PVE_DEFENDERS: + case TF_TEAM_RED: + break; + + case TF_TEAM_BLUE: + if ( TFGameRules() && TFGameRules()->IsMannVsMachineMode() ) + vecLobbyPlayers.FastRemove( i ); + break; + + case TEAM_SPECTATOR: + vecLobbyPlayers.FastRemove( i ); break; default: - AssertMsg1( false, "Bogus team %d", vecMvMDefenders[i].m_iTeam ); - case TF_TEAM_PVE_INVADERS: - case TEAM_SPECTATOR: - vecMvMDefenders.FastRemove( i ); - break; + AssertMsg1( false, "Bogus team %d", vecLobbyPlayers[i].m_iTeam ); } } } diff --git a/mp/src/game/shared/teamplayroundbased_gamerules.h b/mp/src/game/shared/teamplayroundbased_gamerules.h index ddf6e791..95060d3d 100644 --- a/mp/src/game/shared/teamplayroundbased_gamerules.h +++ b/mp/src/game/shared/teamplayroundbased_gamerules.h @@ -12,6 +12,7 @@ #include "teamplay_gamerules.h" #include "teamplay_round_timer.h" +#include "GameEventListener.h" #ifdef GAME_DLL #include "team_control_point.h" @@ -162,7 +163,7 @@ public: //----------------------------------------------------------------------------- // Purpose: Teamplay game rules that manage a round based structure for you //----------------------------------------------------------------------------- -class CTeamplayRoundBasedRules : public CTeamplayRules +class CTeamplayRoundBasedRules : public CTeamplayRules, public CGameEventListener { DECLARE_CLASS( CTeamplayRoundBasedRules, CTeamplayRules ); public: @@ -248,7 +249,7 @@ public: void SetMultipleTrains( bool bMultipleTrains ){ m_bMultipleTrains = bMultipleTrains; } bool HasMultipleTrains( void ){ return m_bMultipleTrains; } - virtual int GetBonusRoundTime( void ); + virtual int GetBonusRoundTime( bool bFinal = false ); #if defined(TF_CLIENT_DLL) || defined(TF_DLL) @@ -258,10 +259,15 @@ public: // Get list of players who are on the defending team now, or are likely // to end up on the defending team (not yet connected or assigned a team) - void GetMvMPotentialDefendersLobbyPlayerInfo( CUtlVector &vecMvmDefenders, bool bIncludeBots = false ); + void GetPotentialPlayersLobbyPlayerInfo( CUtlVector &vecLobbyPlayers, bool bIncludeBots = false ); #endif + void SetAllowBetweenRounds( bool bValue ) { m_bAllowBetweenRounds = bValue; } + +public: // IGameEventListener Interface + virtual void FireGameEvent( IGameEvent * event ); + //---------------------------------------------------------------------------------- // Server specific #ifdef GAME_DLL @@ -309,7 +315,7 @@ public: virtual bool ShouldScorePerRound( void ){ return true; } - bool CheckNextLevelCvar( void ); + bool CheckNextLevelCvar( bool bAllowEnd = true ); virtual bool TimerMayExpire( void ); @@ -332,7 +338,7 @@ public: bool IsPreviouslyPlayedRound ( string_t strName ); string_t GetLastPlayedRound( void ); - virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false ); + virtual void SetWinningTeam( int team, int iWinReason, bool bForceMapReset = true, bool bSwitchTeams = false, bool bDontAddScore = false, bool bFinal = false ) OVERRIDE; virtual void SetStalemate( int iReason, bool bForceMapReset = true, bool bSwitchTeams = false ); virtual void SetRoundOverlayDetails( void ){ return; } @@ -365,10 +371,11 @@ public: { m_bPlayerReady.Set( iIndex, bState ); } + void ResetPlayerAndTeamReadyState( void ); virtual void PlayTrainCaptureAlert( CTeamControlPoint *pPoint, bool bFinalPointInMap ){ return; } - virtual void PlaySpecialCapSounds( int iCappingTeam ){ return; } + virtual void PlaySpecialCapSounds( int iCappingTeam, CTeamControlPoint *pPoint ){ return; } bool PlayThrottledAlert( int iTeam, const char *sound, float fDelayBeforeNext ); @@ -393,14 +400,15 @@ protected: void CheckWaitingForPlayers( void ); virtual bool AllowWaitingForPlayers( void ) { return true; } void CheckRestartRound( void ); - bool CheckTimeLimit( void ); + bool CheckTimeLimit( bool bAllowEnd = true ); int GetTimeLeft( void ); - virtual bool CheckWinLimit( void ); - bool CheckMaxRounds( void ); + virtual bool CheckWinLimit( bool bAllowEnd = true ); + bool CheckMaxRounds( bool bAllowEnd = true ); void CheckReadyRestart( void ); #if defined(TF_CLIENT_DLL) || defined(TF_DLL) - bool AreDefendingPlayersReady(); + bool AreLobbyPlayersOnTeamReady( int iTeam ); + bool AreLobbyPlayersConnected( void ); #endif virtual bool CanChangelevelBecauseOfTimeLimit( void ) { return true; } @@ -479,6 +487,8 @@ protected: bool MapHasActiveTimer( void ); void CreateTimeLimitTimer( void ); + virtual float GetLastMajorEventTime( void ) OVERRIDE { return m_flLastTeamWin; } + protected: CGameRulesRoundStateInfo *m_pCurStateInfo; // Per-state data float m_flStateTransitionTime; // Timer for round states @@ -521,10 +531,13 @@ protected: gamerules_roundstate_t m_prevState; + bool m_bPlayerReadyBefore[MAX_PLAYERS+1]; // Test to see if a player has hit ready before + + float m_flLastTeamWin; + private: CUtlMap < int, int > m_GameTeams; // Team index, Score - #endif // End server specific //---------------------------------------------------------------------------------- @@ -582,6 +595,9 @@ private: int m_nAutoBalanceQueuePlayerIndex; int m_nAutoBalanceQueuePlayerScore; +protected: + bool m_bAllowBetweenRounds; + public: float m_flStopWatchTotalTime; diff --git a/mp/src/game/shared/triggers_shared.h b/mp/src/game/shared/triggers_shared.h new file mode 100644 index 00000000..1467ae93 --- /dev/null +++ b/mp/src/game/shared/triggers_shared.h @@ -0,0 +1,33 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= +// +// Purpose: +// +//============================================================================= + +#ifndef TRIGGERS_SHARED_H +#define TRIGGERS_SHARED_H +#ifdef _WIN32 +#pragma once +#endif + +// +// Spawnflags +// +enum +{ + SF_TRIGGER_ALLOW_CLIENTS = 0x01, // Players can fire this trigger + SF_TRIGGER_ALLOW_NPCS = 0x02, // NPCS can fire this trigger + SF_TRIGGER_ALLOW_PUSHABLES = 0x04, // Pushables can fire this trigger + SF_TRIGGER_ALLOW_PHYSICS = 0x08, // Physics objects can fire this trigger + SF_TRIGGER_ONLY_PLAYER_ALLY_NPCS = 0x10, // *if* NPCs can fire this trigger, this flag means only player allies do so + SF_TRIGGER_ONLY_CLIENTS_IN_VEHICLES = 0x20, // *if* Players can fire this trigger, this flag means only players inside vehicles can + SF_TRIGGER_ALLOW_ALL = 0x40, // Everything can fire this trigger EXCEPT DEBRIS! + SF_TRIGGER_ONLY_CLIENTS_OUT_OF_VEHICLES = 0x200, // *if* Players can fire this trigger, this flag means only players outside vehicles can + SF_TRIG_PUSH_ONCE = 0x80, // trigger_push removes itself after firing once + SF_TRIG_PUSH_AFFECT_PLAYER_ON_LADDER = 0x100, // if pushed object is player on a ladder, then this disengages them from the ladder (HL2only) + SF_TRIG_TOUCH_DEBRIS = 0x400, // Will touch physics debris objects + SF_TRIGGER_ONLY_NPCS_IN_VEHICLES = 0X800, // *if* NPCs can fire this trigger, only NPCs in vehicles do so (respects player ally flag too) + SF_TRIGGER_DISALLOW_BOTS = 0x1000, // Bots are not allowed to fire this trigger +}; + +#endif // TRIGGERS_SHARED_H diff --git a/mp/src/game/shared/usercmd.h b/mp/src/game/shared/usercmd.h index 20b40345..0005bde9 100644 --- a/mp/src/game/shared/usercmd.h +++ b/mp/src/game/shared/usercmd.h @@ -51,6 +51,9 @@ public: weaponselect = 0; weaponsubtype = 0; random_seed = 0; +#ifdef GAME_DLL + server_random_seed = 0; +#endif mousedx = 0; mousedy = 0; @@ -76,6 +79,9 @@ public: weaponselect = src.weaponselect; weaponsubtype = src.weaponsubtype; random_seed = src.random_seed; +#ifdef GAME_DLL + server_random_seed = src.server_random_seed; +#endif mousedx = src.mousedx; mousedy = src.mousedy; @@ -151,6 +157,9 @@ public: int weaponsubtype; int random_seed; // For shared random functions +#ifdef GAME_DLL + int server_random_seed; // Only the server populates this seed +#endif short mousedx; // mouse accum in x from create move short mousedy; // mouse accum in y from create move diff --git a/mp/src/game/shared/util_shared.h b/mp/src/game/shared/util_shared.h index 18f066c3..83793418 100644 --- a/mp/src/game/shared/util_shared.h +++ b/mp/src/game/shared/util_shared.h @@ -441,8 +441,8 @@ inline float DistanceToRay( const Vector &pos, const Vector &rayStart, const Vec public: \ interfaceName( bool bAutoAdd = true ); \ virtual ~interfaceName(); \ - static void Add( interfaceName *pElement ) { m_##interfaceName##AutoList.AddToTail( pElement ); } \ - static void Remove( interfaceName *pElement ) { m_##interfaceName##AutoList.FindAndFastRemove( pElement ); } \ + static void AddToAutoList( interfaceName *pElement ) { m_##interfaceName##AutoList.AddToTail( pElement ); } \ + static void RemoveFromAutoList( interfaceName *pElement ) { m_##interfaceName##AutoList.FindAndFastRemove( pElement ); } \ static const CUtlVector< interfaceName* >& AutoList( void ) { return m_##interfaceName##AutoList; } \ private: \ static CUtlVector< interfaceName* > m_##interfaceName##AutoList; \ @@ -456,14 +456,28 @@ inline float DistanceToRay( const Vector &pos, const Vector &rayStart, const Vec { \ if ( bAutoAdd ) \ { \ - Add( this ); \ + AddToAutoList( this ); \ } \ } \ interfaceName::~interfaceName() \ { \ - Remove( this ); \ + RemoveFromAutoList( this ); \ } +//-------------------------------------------------------------------------------------------------------------- +// This would do the same thing without requiring casts all over the place. Yes, it's a template, but +// DECLARE_AUTO_LIST requires a CUtlVector anyway. TODO ask about replacing the macros with this. +//template +//class AutoList { +//public: +// typedef CUtlVector AutoListType; +// static AutoListType& All() { return m_autolist; } +//protected: +// AutoList() { m_autolist.AddToTail(static_cast(this)); } +// virtual ~AutoList() { m_autolist.FindAndFastRemove(static_cast(this)); } +//private: +// static AutoListType m_autolist; +//}; //-------------------------------------------------------------------------------------------------------------- /** @@ -579,7 +593,15 @@ public: private: float m_duration; float m_timestamp; - float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime + virtual float Now( void ) const; // work-around since client header doesn't like inlined gpGlobals->curtime +}; + +class RealTimeCountdownTimer : public CountdownTimer +{ + virtual float Now( void ) const OVERRIDE + { + return Plat_FloatTime(); + } }; char* ReadAndAllocStringValue( KeyValues *pSub, const char *pName, const char *pFilename = NULL ); diff --git a/mp/src/game/shared/voice_gamemgr.cpp b/mp/src/game/shared/voice_gamemgr.cpp index 15523859..79933896 100644 --- a/mp/src/game/shared/voice_gamemgr.cpp +++ b/mp/src/game/shared/voice_gamemgr.cpp @@ -37,7 +37,7 @@ ConVar voice_serverdebug( "voice_serverdebug", "0" ); // Set game rules to allow all clients to talk to each other. // Muted players still can't talk to each other. -ConVar sv_alltalk( "sv_alltalk", "0", FCVAR_NOTIFY, "Players can hear all other players, no team restrictions" ); +ConVar sv_alltalk( "sv_alltalk", "0", FCVAR_NOTIFY | FCVAR_REPLICATED, "Players can hear all other players, no team restrictions" ); CVoiceGameMgr g_VoiceGameMgr; @@ -289,4 +289,4 @@ bool CVoiceGameMgr::CheckProximity( int iDistance ) return true; return false; -} \ No newline at end of file +} diff --git a/mp/src/game/shared/weapon_parse.cpp b/mp/src/game/shared/weapon_parse.cpp index 514da202..c42ad7f1 100644 --- a/mp/src/game/shared/weapon_parse.cpp +++ b/mp/src/game/shared/weapon_parse.cpp @@ -70,7 +70,7 @@ itemFlags_t g_ItemFlags[8] = { "ITEM_FLAG_NOITEMPICKUP", ITEM_FLAG_NOITEMPICKUP } }; #else -extern itemFlags_t g_ItemFlags[7]; +extern itemFlags_t g_ItemFlags[8]; #endif @@ -78,7 +78,7 @@ static CUtlDict< FileWeaponInfo_t*, unsigned short > m_WeaponInfoDatabase; #ifdef _DEBUG // used to track whether or not two weapons have been mistakenly assigned the wrong slot -bool g_bUsedWeaponSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS] = { 0 }; +bool g_bUsedWeaponSlots[MAX_WEAPON_SLOTS][MAX_WEAPON_POSITIONS] = { { false } }; #endif diff --git a/mp/src/lib/common/lzma.lib b/mp/src/lib/common/lzma.lib new file mode 100644 index 00000000..f165ed04 Binary files /dev/null and b/mp/src/lib/common/lzma.lib differ diff --git a/mp/src/lib/common/ubuntu12_32/libcrypto.a b/mp/src/lib/common/ubuntu12_32/libcrypto.a new file mode 100644 index 00000000..274849e0 Binary files /dev/null and b/mp/src/lib/common/ubuntu12_32/libcrypto.a differ diff --git a/mp/src/lib/common/ubuntu12_32/libssl.a b/mp/src/lib/common/ubuntu12_32/libssl.a new file mode 100644 index 00000000..a96bdc0a Binary files /dev/null and b/mp/src/lib/common/ubuntu12_32/libssl.a differ diff --git a/mp/src/lib/public/appframework.lib b/mp/src/lib/public/appframework.lib index 99b139fb..87f29560 100644 Binary files a/mp/src/lib/public/appframework.lib and b/mp/src/lib/public/appframework.lib differ diff --git a/mp/src/lib/public/bitmap.lib b/mp/src/lib/public/bitmap.lib index 8c26ea0c..0fa0ee6a 100644 Binary files a/mp/src/lib/public/bitmap.lib and b/mp/src/lib/public/bitmap.lib differ diff --git a/mp/src/lib/public/choreoobjects.lib b/mp/src/lib/public/choreoobjects.lib index b3d18d06..98b10324 100644 Binary files a/mp/src/lib/public/choreoobjects.lib and b/mp/src/lib/public/choreoobjects.lib differ diff --git a/mp/src/lib/public/dmxloader.lib b/mp/src/lib/public/dmxloader.lib index c2ca709a..c8a1f3d9 100644 Binary files a/mp/src/lib/public/dmxloader.lib and b/mp/src/lib/public/dmxloader.lib differ diff --git a/mp/src/lib/public/fgdlib.lib b/mp/src/lib/public/fgdlib.lib index 29e44c49..d4fc94ff 100644 Binary files a/mp/src/lib/public/fgdlib.lib and b/mp/src/lib/public/fgdlib.lib differ diff --git a/mp/src/lib/public/libz.lib b/mp/src/lib/public/libz.lib index 6f69f170..15d90ea3 100644 Binary files a/mp/src/lib/public/libz.lib and b/mp/src/lib/public/libz.lib differ diff --git a/mp/src/lib/public/linux32/bitmap.a b/mp/src/lib/public/linux32/bitmap.a index c08b921f..81618a08 100644 Binary files a/mp/src/lib/public/linux32/bitmap.a and b/mp/src/lib/public/linux32/bitmap.a differ diff --git a/mp/src/lib/public/linux32/choreoobjects.a b/mp/src/lib/public/linux32/choreoobjects.a index 322c6341..ccf44ac1 100644 Binary files a/mp/src/lib/public/linux32/choreoobjects.a and b/mp/src/lib/public/linux32/choreoobjects.a differ diff --git a/mp/src/lib/public/linux32/dmxloader.a b/mp/src/lib/public/linux32/dmxloader.a index 34fc5797..0ec68d06 100644 Binary files a/mp/src/lib/public/linux32/dmxloader.a and b/mp/src/lib/public/linux32/dmxloader.a differ diff --git a/mp/src/lib/public/linux32/libsteam_api.so b/mp/src/lib/public/linux32/libsteam_api.so index cb4ee649..d4680813 100755 Binary files a/mp/src/lib/public/linux32/libsteam_api.so and b/mp/src/lib/public/linux32/libsteam_api.so differ diff --git a/mp/src/lib/public/linux32/libtier0.so b/mp/src/lib/public/linux32/libtier0.so index 3de9e585..8ba0224f 100644 Binary files a/mp/src/lib/public/linux32/libtier0.so and b/mp/src/lib/public/linux32/libtier0.so differ diff --git a/mp/src/lib/public/linux32/libvstdlib.so b/mp/src/lib/public/linux32/libvstdlib.so index d1cd4453..fa47f0c5 100644 Binary files a/mp/src/lib/public/linux32/libvstdlib.so and b/mp/src/lib/public/linux32/libvstdlib.so differ diff --git a/mp/src/lib/public/linux32/mathlib.a b/mp/src/lib/public/linux32/mathlib.a index 8fdab97f..51797819 100644 Binary files a/mp/src/lib/public/linux32/mathlib.a and b/mp/src/lib/public/linux32/mathlib.a differ diff --git a/mp/src/lib/public/linux32/matsys_controls.a b/mp/src/lib/public/linux32/matsys_controls.a index 9b769f99..f3c040bf 100644 Binary files a/mp/src/lib/public/linux32/matsys_controls.a and b/mp/src/lib/public/linux32/matsys_controls.a differ diff --git a/mp/src/lib/public/linux32/particles.a b/mp/src/lib/public/linux32/particles.a index aab4a4ec..41b07209 100644 Binary files a/mp/src/lib/public/linux32/particles.a and b/mp/src/lib/public/linux32/particles.a differ diff --git a/mp/src/lib/public/linux32/raytrace.a b/mp/src/lib/public/linux32/raytrace.a index c128a3a9..575d0f78 100644 Binary files a/mp/src/lib/public/linux32/raytrace.a and b/mp/src/lib/public/linux32/raytrace.a differ diff --git a/mp/src/lib/public/linux32/shaderlib.a b/mp/src/lib/public/linux32/shaderlib.a index 9e9dad9b..cefd152a 100644 Binary files a/mp/src/lib/public/linux32/shaderlib.a and b/mp/src/lib/public/linux32/shaderlib.a differ diff --git a/mp/src/lib/public/linux32/tier1.a b/mp/src/lib/public/linux32/tier1.a index 9dd219fe..4490368f 100644 Binary files a/mp/src/lib/public/linux32/tier1.a and b/mp/src/lib/public/linux32/tier1.a differ diff --git a/mp/src/lib/public/linux32/tier2.a b/mp/src/lib/public/linux32/tier2.a index 69f52a3b..207aee67 100644 Binary files a/mp/src/lib/public/linux32/tier2.a and b/mp/src/lib/public/linux32/tier2.a differ diff --git a/mp/src/lib/public/linux32/tier3.a b/mp/src/lib/public/linux32/tier3.a index 3777a2cf..4b7ec24a 100644 Binary files a/mp/src/lib/public/linux32/tier3.a and b/mp/src/lib/public/linux32/tier3.a differ diff --git a/mp/src/lib/public/linux32/vgui_controls.a b/mp/src/lib/public/linux32/vgui_controls.a index 35758546..12e4ea9e 100644 Binary files a/mp/src/lib/public/linux32/vgui_controls.a and b/mp/src/lib/public/linux32/vgui_controls.a differ diff --git a/mp/src/lib/public/linux32/vtf.a b/mp/src/lib/public/linux32/vtf.a index 1a085f0d..c8733982 100644 Binary files a/mp/src/lib/public/linux32/vtf.a and b/mp/src/lib/public/linux32/vtf.a differ diff --git a/mp/src/lib/public/mathlib.lib b/mp/src/lib/public/mathlib.lib index 09a025cf..bb5b681f 100644 Binary files a/mp/src/lib/public/mathlib.lib and b/mp/src/lib/public/mathlib.lib differ diff --git a/mp/src/lib/public/matsys_controls.lib b/mp/src/lib/public/matsys_controls.lib index e37e25a4..d2e68a1a 100644 Binary files a/mp/src/lib/public/matsys_controls.lib and b/mp/src/lib/public/matsys_controls.lib differ diff --git a/mp/src/lib/public/nvtristrip.lib b/mp/src/lib/public/nvtristrip.lib index 59c948fa..8ae02492 100644 Binary files a/mp/src/lib/public/nvtristrip.lib and b/mp/src/lib/public/nvtristrip.lib differ diff --git a/mp/src/lib/public/osx32/bitmap.a b/mp/src/lib/public/osx32/bitmap.a index 2841ae0a..38abbc8e 100644 Binary files a/mp/src/lib/public/osx32/bitmap.a and b/mp/src/lib/public/osx32/bitmap.a differ diff --git a/mp/src/lib/public/osx32/choreoobjects.a b/mp/src/lib/public/osx32/choreoobjects.a index a69eed34..3215158e 100644 Binary files a/mp/src/lib/public/osx32/choreoobjects.a and b/mp/src/lib/public/osx32/choreoobjects.a differ diff --git a/mp/src/lib/public/osx32/dmxloader.a b/mp/src/lib/public/osx32/dmxloader.a index 3d3496a5..27f82331 100644 Binary files a/mp/src/lib/public/osx32/dmxloader.a and b/mp/src/lib/public/osx32/dmxloader.a differ diff --git a/mp/src/lib/public/osx32/libsteam_api.dylib b/mp/src/lib/public/osx32/libsteam_api.dylib index 80dc4752..7ffacb8f 100755 Binary files a/mp/src/lib/public/osx32/libsteam_api.dylib and b/mp/src/lib/public/osx32/libsteam_api.dylib differ diff --git a/mp/src/lib/public/osx32/libtier0.dylib b/mp/src/lib/public/osx32/libtier0.dylib index ccc08ecf..f0941cb7 100755 Binary files a/mp/src/lib/public/osx32/libtier0.dylib and b/mp/src/lib/public/osx32/libtier0.dylib differ diff --git a/mp/src/lib/public/osx32/libvstdlib.dylib b/mp/src/lib/public/osx32/libvstdlib.dylib index abcccb4e..8d723863 100755 Binary files a/mp/src/lib/public/osx32/libvstdlib.dylib and b/mp/src/lib/public/osx32/libvstdlib.dylib differ diff --git a/mp/src/lib/public/osx32/matsys_controls.a b/mp/src/lib/public/osx32/matsys_controls.a index 70b91aba..6b8e0634 100644 Binary files a/mp/src/lib/public/osx32/matsys_controls.a and b/mp/src/lib/public/osx32/matsys_controls.a differ diff --git a/mp/src/lib/public/osx32/particles.a b/mp/src/lib/public/osx32/particles.a index 4ba2a91a..807793ee 100644 Binary files a/mp/src/lib/public/osx32/particles.a and b/mp/src/lib/public/osx32/particles.a differ diff --git a/mp/src/lib/public/osx32/shaderlib.a b/mp/src/lib/public/osx32/shaderlib.a index ee0d2a1c..34ccb7d3 100644 Binary files a/mp/src/lib/public/osx32/shaderlib.a and b/mp/src/lib/public/osx32/shaderlib.a differ diff --git a/mp/src/lib/public/osx32/tier2.a b/mp/src/lib/public/osx32/tier2.a index 538e7fd7..6457180e 100644 Binary files a/mp/src/lib/public/osx32/tier2.a and b/mp/src/lib/public/osx32/tier2.a differ diff --git a/mp/src/lib/public/osx32/tier3.a b/mp/src/lib/public/osx32/tier3.a index 77558463..3e71e482 100644 Binary files a/mp/src/lib/public/osx32/tier3.a and b/mp/src/lib/public/osx32/tier3.a differ diff --git a/mp/src/lib/public/osx32/vtf.a b/mp/src/lib/public/osx32/vtf.a index 65b29f05..806347fb 100644 Binary files a/mp/src/lib/public/osx32/vtf.a and b/mp/src/lib/public/osx32/vtf.a differ diff --git a/mp/src/lib/public/particles.lib b/mp/src/lib/public/particles.lib index aebb8da9..80fd538d 100644 Binary files a/mp/src/lib/public/particles.lib and b/mp/src/lib/public/particles.lib differ diff --git a/mp/src/lib/public/raytrace.lib b/mp/src/lib/public/raytrace.lib index eb389a29..90d213fa 100644 Binary files a/mp/src/lib/public/raytrace.lib and b/mp/src/lib/public/raytrace.lib differ diff --git a/mp/src/lib/public/shaderlib.lib b/mp/src/lib/public/shaderlib.lib index 2ae660a4..2d44d4c3 100644 Binary files a/mp/src/lib/public/shaderlib.lib and b/mp/src/lib/public/shaderlib.lib differ diff --git a/mp/src/lib/public/steam_api.lib b/mp/src/lib/public/steam_api.lib index 3b9c60b6..28eb8335 100644 Binary files a/mp/src/lib/public/steam_api.lib and b/mp/src/lib/public/steam_api.lib differ diff --git a/mp/src/lib/public/tier0.lib b/mp/src/lib/public/tier0.lib index f95b5dc1..14afca62 100644 Binary files a/mp/src/lib/public/tier0.lib and b/mp/src/lib/public/tier0.lib differ diff --git a/mp/src/lib/public/tier1.lib b/mp/src/lib/public/tier1.lib index c795b838..8f62b04e 100644 Binary files a/mp/src/lib/public/tier1.lib and b/mp/src/lib/public/tier1.lib differ diff --git a/mp/src/lib/public/tier2.lib b/mp/src/lib/public/tier2.lib index 8173cb5b..0876b4ed 100644 Binary files a/mp/src/lib/public/tier2.lib and b/mp/src/lib/public/tier2.lib differ diff --git a/mp/src/lib/public/tier3.lib b/mp/src/lib/public/tier3.lib index b0e04004..208ea223 100644 Binary files a/mp/src/lib/public/tier3.lib and b/mp/src/lib/public/tier3.lib differ diff --git a/mp/src/lib/public/vgui_controls.lib b/mp/src/lib/public/vgui_controls.lib index 071e6220..71691f16 100644 Binary files a/mp/src/lib/public/vgui_controls.lib and b/mp/src/lib/public/vgui_controls.lib differ diff --git a/mp/src/lib/public/vmpi.lib b/mp/src/lib/public/vmpi.lib index d620dc24..e882e1c1 100644 Binary files a/mp/src/lib/public/vmpi.lib and b/mp/src/lib/public/vmpi.lib differ diff --git a/mp/src/lib/public/vstdlib.lib b/mp/src/lib/public/vstdlib.lib index 6709dabe..147a915e 100644 Binary files a/mp/src/lib/public/vstdlib.lib and b/mp/src/lib/public/vstdlib.lib differ diff --git a/mp/src/lib/public/vtf.lib b/mp/src/lib/public/vtf.lib index f2359f9b..6ff23e83 100644 Binary files a/mp/src/lib/public/vtf.lib and b/mp/src/lib/public/vtf.lib differ diff --git a/mp/src/materialsystem/stdshaders/BaseVSShader.cpp b/mp/src/materialsystem/stdshaders/BaseVSShader.cpp index 40e3934b..fdaeb563 100644 --- a/mp/src/materialsystem/stdshaders/BaseVSShader.cpp +++ b/mp/src/materialsystem/stdshaders/BaseVSShader.cpp @@ -458,6 +458,21 @@ void CBaseVSShader::SetPixelShaderTextureScaledTransform( int pixelReg, int tran //----------------------------------------------------------------------------- // Moves a matrix into vertex shader constants //----------------------------------------------------------------------------- +void CBaseVSShader::SetVertexShaderMatrix2x4( int vertexReg, int matrixVar ) +{ + IMaterialVar* pTranslationVar = s_ppParams[ matrixVar ]; + if ( pTranslationVar ) + { + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &pTranslationVar->GetMatrixValue()[ 0 ][ 0 ], 2 ); + } + else + { + VMatrix matrix; + MatrixSetIdentity( matrix ); + s_pShaderAPI->SetVertexShaderConstant( vertexReg, &matrix[ 0 ][ 0 ], 2 ); + } +} + void CBaseVSShader::SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ) { IMaterialVar* pTranslationVar = s_ppParams[matrixVar]; diff --git a/mp/src/materialsystem/stdshaders/BaseVSShader.h b/mp/src/materialsystem/stdshaders/BaseVSShader.h index 1ba6cc43..860c6876 100644 --- a/mp/src/materialsystem/stdshaders/BaseVSShader.h +++ b/mp/src/materialsystem/stdshaders/BaseVSShader.h @@ -118,6 +118,7 @@ public: int transformVar, int scaleVar ); // Moves a matrix into vertex shader constants + void SetVertexShaderMatrix2x4( int vertexReg, int matrixVar ); void SetVertexShaderMatrix3x4( int vertexReg, int matrixVar ); void SetVertexShaderMatrix4x4( int vertexReg, int matrixVar ); diff --git a/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp index 82b8d466..fc6a7208 100644 --- a/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp +++ b/mp/src/materialsystem/stdshaders/example_model_dx9_helper.cpp @@ -19,7 +19,7 @@ static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); -static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_NONE ); // Textures may be bound to the following samplers: // SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha diff --git a/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp index 1e2d30f3..cc999788 100644 --- a/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp +++ b/mp/src/materialsystem/stdshaders/skin_dx9_helper.cpp @@ -23,7 +23,7 @@ static ConVar mat_fullbright( "mat_fullbright", "0", FCVAR_CHEAT ); static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT ); -static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT ); +static ConVar r_rimlight( "r_rimlight", "1", FCVAR_NONE ); // Textures may be bound to the following samplers: // SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha @@ -270,6 +270,9 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad float flTintReplacementAmount = GetFloatParam( info.m_nTintReplacesBaseColor, params ); + float flPhongExponentFactor = ( info.m_nPhongExponentFactor != -1 ) ? GetFloatParam( info.m_nPhongExponentFactor, params ) : 0.0f; + const bool bHasPhongExponentFactor = flPhongExponentFactor != 0.0f; + BlendType_t nBlendType= pShader->EvaluateBlendRequirements( bBlendTintByBaseAlpha ? -1 : info.m_nBaseTexture, true ); bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlight; //dest alpha is free for special use @@ -676,6 +679,7 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PHONG_USE_EXPONENT_FACTOR, bHasPhongExponentFactor ); SET_DYNAMIC_PIXEL_SHADER( skin_ps20b ); } #ifndef _X360 @@ -697,6 +701,7 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha ); SET_DYNAMIC_PIXEL_SHADER_COMBO( PIXELFOGTYPE, pShaderAPI->GetPixelFogCombo() ); SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows ); + SET_DYNAMIC_PIXEL_SHADER_COMBO( PHONG_USE_EXPONENT_FACTOR, bHasPhongExponentFactor ); SET_DYNAMIC_PIXEL_SHADER( skin_ps30 ); bool bUnusedTexCoords[3] = { false, false, !pShaderAPI->IsHWMorphingEnabled() || !bIsDecal }; @@ -806,15 +811,23 @@ void DrawSkin_DX9_Internal( CBaseVSShader *pShader, IMaterialVar** params, IShad float vSpecularTint[4] = {1, 1, 1, 4}; pShaderAPI->GetWorldSpaceCameraPosition( vEyePos_SpecExponent ); - // Use the alpha channel of the normal map for the exponent by default - vEyePos_SpecExponent[3] = -1.f; - if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) + // If we have a phong exponent factor, then use that as a multiplier against the texture. + if ( bHasPhongExponentFactor ) { - float fValue = params[info.m_nPhongExponent]->GetFloatValue(); - if ( fValue > 0.f ) + vEyePos_SpecExponent[3] = flPhongExponentFactor; + } + else + { + // Use the alpha channel of the normal map for the exponent by default + vEyePos_SpecExponent[3] = -1.f; + if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() ) { - // Nonzero value in material overrides map channel - vEyePos_SpecExponent[3] = fValue; + float fValue = params[info.m_nPhongExponent]->GetFloatValue(); + if ( fValue > 0.f ) + { + // Nonzero value in material overrides map channel + vEyePos_SpecExponent[3] = fValue; + } } } diff --git a/mp/src/materialsystem/stdshaders/skin_ps20b.fxc b/mp/src/materialsystem/stdshaders/skin_ps20b.fxc index 20c3eef9..8d2e3204 100644 --- a/mp/src/materialsystem/stdshaders/skin_ps20b.fxc +++ b/mp/src/materialsystem/stdshaders/skin_ps20b.fxc @@ -24,6 +24,8 @@ // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps30] // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30] +// DYNAMIC: "PHONG_USE_EXPONENT_FACTOR" "0..0" [ps20] +// DYNAMIC: "PHONG_USE_EXPONENT_FACTOR" "0..1" [ps20b] [ps30] [PC] // SKIP: ($PIXELFOGTYPE == 0) && ($WRITEWATERFOGTODESTALPHA != 0) @@ -76,7 +78,9 @@ const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT ); const float4 g_FogParams : register( PSREG_FOG_PARAMS ); const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); -const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +#if FLASHLIGHT + const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE ); +#endif const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY ); // 2 registers each - 6 registers total (4th light spread across w's) @@ -96,6 +100,7 @@ const float4 g_ShaderControls : register( PSREG_CONSTANT_27 ); // x is #define g_fTintReplacementControl g_ShaderControls.z #define g_fInvertPhongMask g_ShaderControls.w + sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha sampler SpecularWarpSampler : register( s1 ); // Specular warp sampler (for iridescence etc) sampler DiffuseWarpSampler : register( s2 ); // Lighting warp sampler (1D texture for diffuse lighting modification) @@ -119,7 +124,6 @@ sampler DetailSampler : register( s13 ); // detail texture sampler SelfIllumMaskSampler : register( s14 ); // selfillummask - struct PS_INPUT { float4 baseTexCoordDetailTexCoord : TEXCOORD0; // xy=base zw=detail @@ -258,7 +262,11 @@ float4 main( PS_INPUT i ) : COLOR [flatten] #endif +#if ( PHONG_USE_EXPONENT_FACTOR ) + fSpecExp = ( 1.0f + g_EyePos_SpecExponent.w * vSpecExpMap.r ); +#else fSpecExp = (g_EyePos_SpecExponent.w >= 0.0) ? g_EyePos_SpecExponent.w : (1.0f + 149.0f * vSpecExpMap.r); +#endif // If constant tint is negative, tint with albedo, based upon scalar tint map #if defined( _X360 ) @@ -286,15 +294,17 @@ float4 main( PS_INPUT i ) : COLOR } else { - float4 flashlightSpacePosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); + #if FLASHLIGHT + float4 flashlightSpacePosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToTexture ); - DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal, - g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, - FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, vProjPos.xy / vProjPos.z, - fSpecExp, vEyeDir, bDoSpecularWarp, SpecularWarpSampler, fFresnelRanges, g_EnvmapTint_ShadowTweaks, + DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal, + g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w, + FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, true, vProjPos.xy / vProjPos.z, + fSpecExp, vEyeDir, bDoSpecularWarp, SpecularWarpSampler, fFresnelRanges, g_EnvmapTint_ShadowTweaks, - // These two values are output - diffuseLighting, specularLighting ); + // These two values are output + diffuseLighting, specularLighting ); + #endif } // If we didn't already apply Fresnel to specular warp, modulate the specular diff --git a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc index abfd9b6f..eb3cbfac 100644 --- a/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc +++ b/mp/src/materialsystem/stdshaders/vertexlit_and_unlit_generic_ps2x.fxc @@ -358,8 +358,8 @@ float4 main( PS_INPUT i ) : COLOR diffuseLighting = f3LightmapColor; #endif - float3 albedo = baseColor; + if (bBlendTintByBaseAlpha) { float3 tintedColor = albedo * g_DiffuseModulation.rgb; diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp index 4281dcac..5e7e61e9 100644 --- a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9.cpp @@ -54,6 +54,7 @@ BEGIN_VS_SHADER( VertexLitGeneric, "Help for VertexLitGeneric" ) SHADER_PARAM( PHONGFRESNELRANGES, SHADER_PARAM_TYPE_VEC3, "[0 0.5 1]", "Parameters for remapping fresnel output" ) SHADER_PARAM( PHONGBOOST, SHADER_PARAM_TYPE_FLOAT, "1.0", "Phong overbrightening factor (specular mask channel should be authored to account for this)" ) SHADER_PARAM( PHONGEXPONENTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", "Phong Exponent map" ) + SHADER_PARAM( PHONGEXPONENTFACTOR, SHADER_PARAM_TYPE_FLOAT, "0.0", "When using a phong exponent texture, this will be multiplied by the 0..1 that comes out of the texture." ) SHADER_PARAM( PHONG, SHADER_PARAM_TYPE_BOOL, "0", "enables phong lighting" ) SHADER_PARAM( BASEMAPALPHAPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "indicates that there is no normal map and that the phong mask is in base alpha" ) SHADER_PARAM( INVERTPHONGMASK, SHADER_PARAM_TYPE_INTEGER, "0", "invert the phong mask (0=full phong, 1=no phong)" ) @@ -180,6 +181,7 @@ BEGIN_VS_SHADER( VertexLitGeneric, "Help for VertexLitGeneric" ) info.m_nDiffuseWarpTexture = LIGHTWARPTEXTURE; info.m_nPhongWarpTexture = PHONGWARPTEXTURE; info.m_nPhongBoost = PHONGBOOST; + info.m_nPhongExponentFactor = PHONGEXPONENTFACTOR; info.m_nPhongFresnelRanges = PHONGFRESNELRANGES; info.m_nPhong = PHONG; info.m_nBaseMapAlphaPhongMask = BASEMAPALPHAPHONGMASK; diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp index 40390824..431d0de5 100644 --- a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.cpp @@ -433,7 +433,7 @@ static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterial bool bHasVertexAlpha = bVertexLitGeneric ? false : IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA ); /*^*/ // printf("\t\t[%d] bHasVertexColor\n",(int)bHasVertexColor); /*^*/ // printf("\t\t[%d] bHasVertexAlpha\n",(int)bHasVertexAlpha); - + if ( pShader->IsSnapshotting() || (! pContextData ) || ( pContextData->m_bMaterialVarsChanged ) ) { /*^*/ // printf("\t\t[1] snapshotting=%d pContextData=%08x pContextData->m_bMaterialVarsChanged=%d \n",(int)pShader->IsSnapshotting(), (int)pContextData, pContextData ? (int)pContextData->m_bMaterialVarsChanged : -1 ); @@ -1221,7 +1221,6 @@ static void DrawVertexLitGeneric_DX9_Internal( CBaseVSShader *pShader, IMaterial } } - MaterialFogMode_t fogType = pShaderAPI->GetSceneFogMode(); int fogIndex = ( fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) ? 1 : 0; int numBones = pShaderAPI->GetCurrentNumBones(); diff --git a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h index 8bc8d430..5820dbeb 100644 --- a/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h +++ b/mp/src/materialsystem/stdshaders/vertexlitgeneric_dx9_helper.h @@ -68,6 +68,7 @@ struct VertexLitGeneric_DX9_Vars_t int m_nPhongWarpTexture; int m_nPhongBoost; int m_nPhongFresnelRanges; + int m_nPhongExponentFactor; int m_nSelfIllumEnvMapMask_Alpha; int m_nAmbientOnly; int m_nHDRColorScale; @@ -131,7 +132,6 @@ struct VertexLitGeneric_DX9_Vars_t int m_nBlendTintByBaseAlpha; int m_nTintReplacesBaseColor; - }; void InitParamsVertexLitGeneric_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, bool bVertexLitGeneric, VertexLitGeneric_DX9_Vars_t &info ); diff --git a/mp/src/mathlib/mathlib_base.cpp b/mp/src/mathlib/mathlib_base.cpp index dee2f28e..64069a7b 100644 --- a/mp/src/mathlib/mathlib_base.cpp +++ b/mp/src/mathlib/mathlib_base.cpp @@ -1461,7 +1461,9 @@ float Bias( float x, float biasAmt ) { lastExponent = log( biasAmt ) * -1.4427f; // (-1.4427 = 1 / log(0.5)) } - return pow( x, lastExponent ); + float fRet = pow( x, lastExponent ); + Assert ( !IS_NAN( fRet ) ); + return fRet; } @@ -1477,7 +1479,9 @@ float Gain( float x, float biasAmt ) float SmoothCurve( float x ) { - return (1 - cos( x * M_PI )) * 0.5f; + // Actual smooth curve. Visualization: + // http://www.wolframalpha.com/input/?i=plot%5B+0.5+*+%281+-+cos%5B2+*+pi+*+x%5D%29+for+x+%3D+%280%2C+1%29+%5D + return 0.5f * (1 - cos( 2.0f * M_PI * x ) ); } @@ -1856,7 +1860,10 @@ void QuaternionMult( const Quaternion &p, const Quaternion &q, Quaternion &qt ) void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t& matrix ) { - Assert( pos.IsValid() ); + if ( !HushAsserts() ) + { + Assert( pos.IsValid() ); + } QuaternionMatrix( q, matrix ); @@ -1868,7 +1875,10 @@ void QuaternionMatrix( const Quaternion &q, const Vector &pos, matrix3x4_t& matr void QuaternionMatrix( const Quaternion &q, matrix3x4_t& matrix ) { Assert( s_bMathlibInitialized ); - Assert( q.IsValid() ); + if ( !HushAsserts() ) + { + Assert( q.IsValid() ); + } #ifdef _VPROF_MATHLIB VPROF_BUDGET( "QuaternionMatrix", "Mathlib" ); diff --git a/mp/src/public/SoundEmitterSystem/isoundemittersystembase.h b/mp/src/public/SoundEmitterSystem/isoundemittersystembase.h index 9cb6ee6a..77fbf0da 100644 --- a/mp/src/public/SoundEmitterSystem/isoundemittersystembase.h +++ b/mp/src/public/SoundEmitterSystem/isoundemittersystembase.h @@ -264,6 +264,9 @@ public: virtual soundlevel_t LookupSoundLevelByHandle( char const *soundname, HSOUNDSCRIPTHANDLE& handle ) = 0; virtual void ReloadSoundEntriesInList( IFileList *pFilesToReload ) = 0; + + // Called by either client or server to force ModShutdown and ModInit + virtual void Flush() = 0; }; #endif // ISOUNDEMITTERSYSTEMBASE_H diff --git a/mp/src/public/UtlCachedFileData.h b/mp/src/public/UtlCachedFileData.h index d7b0bc46..4420c21b 100644 --- a/mp/src/public/UtlCachedFileData.h +++ b/mp/src/public/UtlCachedFileData.h @@ -461,7 +461,7 @@ void CUtlCachedFileData::InitSmallBuffer( FileHandle_t& fh, int fileSize, boo // Read the element name char elementFileName[ 512 ]; - buf.GetString( elementFileName, sizeof( elementFileName ) ); + buf.GetString( elementFileName ); // Now read the element int slot = GetIndex( elementFileName ); @@ -561,7 +561,7 @@ void CUtlCachedFileData::InitLargeBuffer( FileHandle_t& fh, bool& deleteFile // Read the element name char elementFileName[ 512 ]; - buf.GetString( elementFileName, sizeof( elementFileName ) ); + buf.GetString( elementFileName ); // Now read the element int slot = GetIndex( elementFileName ); @@ -682,7 +682,7 @@ void CUtlCachedFileData::Save() fh = g_pFullFileSystem->Open( m_sRepositoryFileName, "wb" ); if ( FILESYSTEM_INVALID_HANDLE == fh ) { - Warning( "Unable to persist cache '%s', check file permissions\n", m_sRepositoryFileName.String() ); + ExecuteNTimes( 25, Warning( "Unable to persist cache '%s', check file permissions\n", m_sRepositoryFileName.String() ) ); } else { diff --git a/mp/src/public/VGuiMatSurface/IMatSystemSurface.h b/mp/src/public/VGuiMatSurface/IMatSystemSurface.h index 7e9d90fe..8d76b805 100644 --- a/mp/src/public/VGuiMatSurface/IMatSystemSurface.h +++ b/mp/src/public/VGuiMatSurface/IMatSystemSurface.h @@ -108,6 +108,13 @@ public: virtual void GetFullscreenViewportAndRenderTarget( int & x, int & y, int & w, int & h, ITexture **ppRenderTarget ) = 0; virtual void SetFullscreenViewportAndRenderTarget( int x, int y, int w, int h, ITexture *pRenderTarget ) = 0; + + // get texture id for a texture + virtual int DrawGetTextureId( ITexture *pTexture ) = 0; + + // begin and end skin composition painting + virtual void BeginSkinCompositionPainting() = 0; + virtual void EndSkinCompositionPainting() = 0; }; diff --git a/mp/src/public/appframework/ilaunchermgr.h b/mp/src/public/appframework/ilaunchermgr.h index 2498ab36..4b433ad8 100644 --- a/mp/src/public/appframework/ilaunchermgr.h +++ b/mp/src/public/appframework/ilaunchermgr.h @@ -16,13 +16,8 @@ #include "appframework/IAppSystem.h" #if defined( DX_TO_GL_ABSTRACTION ) - #if defined( LINUX ) || defined( _WIN32 ) - #include "togl/linuxwin/glmgrbasics.h" - #include "togl/linuxwin/glmdisplay.h" - #elif defined( OSX ) - #include "togl/osx/glmgrbasics.h" - #include "togl/osx/glmdisplay.h" - #endif +#include "togl/linuxwin/glmgrbasics.h" +#include "togl/linuxwin/glmdisplay.h" class GLMDisplayDB; class CShowPixelsParams; diff --git a/mp/src/public/bitmap/imageformat.h b/mp/src/public/bitmap/imageformat.h index 1a35cab1..3e8f7b13 100644 --- a/mp/src/public/bitmap/imageformat.h +++ b/mp/src/public/bitmap/imageformat.h @@ -100,6 +100,9 @@ enum ImageFormat IMAGE_FORMAT_LE_BGRA8888, #endif + IMAGE_FORMAT_DXT1_RUNTIME, + IMAGE_FORMAT_DXT5_RUNTIME, + NUM_IMAGE_FORMATS }; @@ -448,6 +451,9 @@ namespace ImageLoader int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma, int numLevels = 0 ); + // Low quality mipmap generation, but way faster. + void GenerateMipmapLevelsLQ( unsigned char* pSrc, unsigned char* pDst, int width, int height, + ImageFormat imageFormat, int numLevels ); //----------------------------------------------------------------------------- // operations on square images (src and dst can be the same) @@ -511,6 +517,10 @@ namespace ImageLoader return ( info.m_NumRedBits > 8 || info.m_NumGreeBits > 8 || info.m_NumBlueBits > 8 || info.m_NumAlphaBits > 8 ); } + inline bool IsRuntimeCompressed( ImageFormat fmt ) + { + return ( fmt == IMAGE_FORMAT_DXT1_RUNTIME ) || ( fmt == IMAGE_FORMAT_DXT5_RUNTIME ); + } } // end namespace ImageLoader diff --git a/mp/src/public/bspfile.h b/mp/src/public/bspfile.h index 21d9f375..d4c3a059 100644 --- a/mp/src/public/bspfile.h +++ b/mp/src/public/bspfile.h @@ -376,7 +376,9 @@ struct lump_t DECLARE_BYTESWAP_DATADESC(); int fileofs, filelen; int version; // default to zero - char fourCC[4]; // default to ( char )0, ( char )0, ( char )0, ( char )0 + // this field was char fourCC[4] previously, but was unused, favoring the LUMP IDs above instead. It has been + // repurposed for compression. 0 implies the lump is not compressed. + int uncompressedSize; // default to zero }; @@ -384,7 +386,7 @@ struct dheader_t { DECLARE_BYTESWAP_DATADESC(); int ident; - int version; + int version; lump_t lumps[HEADER_LUMPS]; int mapRevision; // the map's revision (iteration, version) number (added BSPVERSION 6) }; @@ -419,7 +421,7 @@ struct dgamelumpheader_t // This is expected to be a four-CC code ('lump') typedef int GameLumpId_t; -// 360 only: game lump is compressed, filelen reflects original size +// game lump is compressed, filelen reflects original size // use next entry fileofs to determine actual disk lump compressed size // compression stage ensures a terminal null dictionary entry #define GAMELUMPFLAG_COMPRESSED 0x0001 diff --git a/mp/src/public/cdll_int.h b/mp/src/public/cdll_int.h index dd3e1e90..3a1d763e 100644 --- a/mp/src/public/cdll_int.h +++ b/mp/src/public/cdll_int.h @@ -548,6 +548,9 @@ public: // returns the string name of the key to which this string is bound. Returns NULL if no such binding exists // Unlike Key_LookupBinding, leading '+' characters are not stripped from bindings. virtual const char *Key_LookupBindingExact( const char *pBinding ) = 0; + + virtual void AddPhonemeFile( const char *pszPhonemeFile ) = 0; + }; abstract_class IVEngineClient : public IVEngineClient013 diff --git a/mp/src/public/collisionutils.cpp b/mp/src/public/collisionutils.cpp index d26db4ab..2549a569 100644 --- a/mp/src/public/collisionutils.cpp +++ b/mp/src/public/collisionutils.cpp @@ -228,7 +228,7 @@ int IntersectTriangleWithPlaneBarycentric( const Vector& org, const Vector& edge { pIntersection[ptIdx].x = - ( orgDotNormal - plane.w + edgeVDotNormal) / ( edgeUDotNormal - edgeVDotNormal); - pIntersection[ptIdx].y = 1.0f - pIntersection[ptIdx].x;; + pIntersection[ptIdx].y = 1.0f - pIntersection[ptIdx].x; if ((pIntersection[ptIdx].x >= 0.0f) && (pIntersection[ptIdx].x <= 1.0f) && (pIntersection[ptIdx].y >= 0.0f) && (pIntersection[ptIdx].y <= 1.0f)) ++ptIdx; diff --git a/mp/src/public/const.h b/mp/src/public/const.h index 98293c08..0ed97e9e 100644 --- a/mp/src/public/const.h +++ b/mp/src/public/const.h @@ -46,7 +46,15 @@ #define MAX_PLAYERS_PER_CLIENT 1 // One player per PC #endif -#define MAX_MAP_NAME 32 +// Max decorated map name, with things like workshop/cp_foo.ugc123456 +#define MAX_MAP_NAME 96 + +// Max name used in save files. Needs to be left at 32 for SourceSDK compatibility. +#define MAX_MAP_NAME_SAVE 32 + +// Max non-decorated map name for e.g. server browser (just cp_foo) +#define MAX_DISPLAY_MAP_NAME 32 + #define MAX_NETWORKID_LENGTH 64 // num chars for a network (i.e steam) ID // BUGBUG: Reconcile with or derive this from the engine's internal definition! diff --git a/mp/src/public/eiface.h b/mp/src/public/eiface.h index 0311ee8b..c7ca17c6 100644 --- a/mp/src/public/eiface.h +++ b/mp/src/public/eiface.h @@ -74,8 +74,9 @@ typedef struct player_info_s player_info_t; #endif #define INTERFACEVERSION_VENGINESERVER_VERSION_21 "VEngineServer021" -#define INTERFACEVERSION_VENGINESERVER "VEngineServer022" -#define INTERFACEVERSION_VENGINESERVER_INT 22 +#define INTERFACEVERSION_VENGINESERVER_VERSION_22 "VEngineServer022" +#define INTERFACEVERSION_VENGINESERVER "VEngineServer023" +#define INTERFACEVERSION_VENGINESERVER_INT 23 struct bbox_t { @@ -91,16 +92,16 @@ abstract_class IVEngineServer public: // Tell engine to change level ( "changelevel s1\n" or "changelevel2 s1 s2\n" ) virtual void ChangeLevel( const char *s1, const char *s2 ) = 0; - + // Ask engine whether the specified map is a valid map file (exists and has valid version number). virtual int IsMapValid( const char *filename ) = 0; - + // Is this a dedicated server? virtual bool IsDedicatedServer( void ) = 0; - + // Is in Hammer editing mode? virtual int IsInEditMode( void ) = 0; - + // Add to the server/client lookup/precache table, the specified string is given a unique index // NOTE: The indices for PrecacheModel are 1 based // a 0 returned from those methods indicates the model or sound was not correctly precached @@ -416,14 +417,43 @@ public: // Exposed for server plugin authors virtual IServer *GetIServer() = 0; + + virtual bool IsPlayerNameLocked( const edict_t *pEdict ) = 0; + virtual bool CanPlayerChangeName( const edict_t *pEdict ) = 0; + + // Find the canonical name of a map, given a partial or non-canonical map name. + // Except in the case of an exact match, pMapName is updated to the canonical name of the match. + // NOTE That this is subject to the same limitation as ServerGameDLL::CanProvideLevel -- This is non-blocking, so it + // is possible that blocking ServerGameDLL::PrepareLevelResources call may be able to pull a better match than + // is immediately available to this call (e.g. blocking lookups of cloud maps) + enum eFindMapResult { + // A direct match for this name was found + eFindMap_Found, + // No match for this map name could be found. + eFindMap_NotFound, + // A fuzzy match for this mapname was found and pMapName was updated to the full name. + // Ex: cp_dust -> cp_dustbowl + eFindMap_FuzzyMatch, + // A match for this map name was found, and the map name was updated to the canonical version of the + // name. + // Ex: workshop/1234 -> workshop/cp_qualified_name.ugc1234 + eFindMap_NonCanonical, + // No currently available match for this map name could be found, but it may be possible to load ( see caveat + // about PrepareLevelResources above ) + eFindMap_PossiblyAvailable + }; + virtual eFindMapResult FindMap( /* in/out */ char *pMapName, int nMapNameMax ) = 0; }; +// These only differ in new items added to the end typedef IVEngineServer IVEngineServer021; +typedef IVEngineServer IVEngineServer022; #define INTERFACEVERSION_SERVERGAMEDLL_VERSION_8 "ServerGameDLL008" -#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL009" -#define INTERFACEVERSION_SERVERGAMEDLL_INT 9 +#define INTERFACEVERSION_SERVERGAMEDLL_VERSION_9 "ServerGameDLL009" +#define INTERFACEVERSION_SERVERGAMEDLL "ServerGameDLL010" +#define INTERFACEVERSION_SERVERGAMEDLL_INT 10 class IServerGCLobby; @@ -554,6 +584,51 @@ public: // Called to add output to the status command virtual void Status( void (*print) (const char *fmt, ...) ) = 0; + + // Informs the game we would like to load this level, giving it a chance to prepare dynamic resources. + // + // - pszMapName is the name of the map we're looking for, and may be overridden to e.g. the canonical name of the + // map. + // + // - pszMapFile is the file we intend to use for this map ( e.g. maps/.bsp ), and may be overridden to the + // file representing this map name. ( e.g. /path/to/steamapps/workshop/cp_mymap.ugc12345.bsp ) + // + // This call is blocking, and may block for extended periods. See AsyncPrepareLevelResources below. + virtual void PrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize ) = 0; + + // Asynchronous version of PrepareLevelResources. Returns preparation status of map when called. + // If passed, flProgress is filled with the current progress percentage [ 0.f to 1.f ] for the InProgress + // result + enum ePrepareLevelResourcesResult + { + // Good to go + ePrepareLevelResources_Prepared, + // Game DLL is async preparing (e.g. streaming resources). flProgress will be filled if passed. + ePrepareLevelResources_InProgress + }; + virtual ePrepareLevelResourcesResult AsyncPrepareLevelResources( /* in/out */ char *pszMapName, size_t nMapNameSize, + /* in/out */ char *pszMapFile, size_t nMapFileSize, + float *flProgress = NULL ) = 0; + + // Ask the game DLL to evaluate what it would do with this map name were it passed to PrepareLevelResources. + // NOTE That this is this is syncronous and non-blocking, so it is possible that async PrepareLevelResources call + // may be able to pull a better match than is immediately available to this call (e.g. blocking lookups of + // cloud maps) + enum eCanProvideLevelResult { + // Have no knowledge of this level name, it will be up to the engine to provide. (e.g. as maps/levelname.bsp) + eCanProvideLevel_CannotProvide, + // Can provide resources for this level, and pMapName has been updated to the canonical name we would provide it + // under (as with PrepareLevelResources) + eCanProvideLevel_CanProvide, + // We recognize this level name as something we might be able to prepare, but without a blocking/async call to + // PrepareLevelResources, it is not possible to say whether it is available. + eCanProvideLevel_Possibly + }; + virtual eCanProvideLevelResult CanProvideLevel( /* in/out */ char *pMapName, int nMapNameMax ) = 0; + + // Called to see if the game server is okay with a manual changelevel or map command + virtual bool IsManualMapChangeOkay( const char **pszReason ) = 0; }; typedef IServerGameDLL IServerGameDLL008; diff --git a/mp/src/public/filesystem_init.cpp b/mp/src/public/filesystem_init.cpp index 4b2799fe..c1bcf3e1 100644 --- a/mp/src/public/filesystem_init.cpp +++ b/mp/src/public/filesystem_init.cpp @@ -982,77 +982,6 @@ bool DoesPathExistAlready( const char *pPathEnvVar, const char *pTestPath ) } } -FSReturnCode_t SetSteamInstallPath( char *steamInstallPath, int steamInstallPathLen, CSteamEnvVars &steamEnvVars, bool bErrorsAsWarnings ) -{ - if ( IsConsole() ) - { - // consoles don't use steam - return FS_MISSING_STEAM_DLL; - } - - if ( IsPosix() ) - return FS_OK; // under posix the content does not live with steam.dll up the path, rely on the environment already being set by steam - - // Start at our bin directory and move up until we find a directory with steam.dll in it. - char executablePath[MAX_PATH]; - if ( !FileSystem_GetExecutableDir( executablePath, sizeof( executablePath ) ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "SetSteamInstallPath: FileSystem_GetExecutableDir failed.\n" ); - return FS_INVALID_PARAMETERS; - } - else - { - return SetupFileSystemError( false, FS_INVALID_PARAMETERS, "FileSystem_GetExecutableDir failed." ); - } - } - - Q_strncpy( steamInstallPath, executablePath, steamInstallPathLen ); -#ifdef WIN32 - const char *pchSteamDLL = "steam" DLL_EXT_STRING; -#elif defined(POSIX) - // under osx the bin lives in the bin/ folder, so step back one - Q_StripLastDir( steamInstallPath, steamInstallPathLen ); - const char *pchSteamDLL = "libsteam" DLL_EXT_STRING; -#else - #error -#endif - while ( 1 ) - { - // Ignore steamapp.cfg here in case they're debugging. We still need to know the real steam path so we can find their username. - // find - if ( DoesFileExistIn( steamInstallPath, pchSteamDLL ) && !DoesFileExistIn( steamInstallPath, "steamapp.cfg" ) ) - break; - - if ( !Q_StripLastDir( steamInstallPath, steamInstallPathLen ) ) - { - if ( bErrorsAsWarnings ) - { - Warning( "Can't find %s relative to executable path: %s.\n", pchSteamDLL, executablePath ); - return FS_MISSING_STEAM_DLL; - } - else - { - return SetupFileSystemError( false, FS_MISSING_STEAM_DLL, "Can't find %s relative to executable path: %s.", pchSteamDLL, executablePath ); - } - } - } - - // Also, add the install path to their PATH environment variable, so filesystem_steam.dll can get to steam.dll. - char szPath[ 8192 ]; - steamEnvVars.m_Path.GetValue( szPath, sizeof( szPath ) ); - if ( !DoesPathExistAlready( szPath, steamInstallPath ) ) - { -#ifdef WIN32 -#define PATH_SEP ";" -#else -#define PATH_SEP ":" -#endif - steamEnvVars.m_Path.SetValue( "%s%s%s", szPath, PATH_SEP, steamInstallPath ); - } - return FS_OK; -} FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ) { @@ -1132,29 +1061,6 @@ void SetSteamUserPassphrase( KeyValues *pSteamInfo, CSteamEnvVars &steamEnvVars } } -FSReturnCode_t SetupSteamStartupEnvironment( KeyValues *pFileSystemInfo, const char *pGameInfoDirectory, CSteamEnvVars &steamEnvVars ) -{ - // Ok, we're going to run Steam. See if they have SteamInfo.txt. If not, we'll try to deduce what we can. - char steamInfoFile[MAX_PATH]; - Q_strncpy( steamInfoFile, pGameInfoDirectory, sizeof( steamInfoFile ) ); - Q_AppendSlash( steamInfoFile, sizeof( steamInfoFile ) ); - Q_strncat( steamInfoFile, "steaminfo.txt", sizeof( steamInfoFile ), COPY_ALL_CHARACTERS ); - KeyValues *pSteamInfo = ReadKeyValuesFile( steamInfoFile ); - - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, false ); - if ( ret != FS_OK ) - return ret; - - SetSteamAppUser( pSteamInfo, steamInstallPath, steamEnvVars ); - SetSteamUserPassphrase( pSteamInfo, steamEnvVars ); - - if ( pSteamInfo ) - pSteamInfo->deleteThis(); - - return FS_OK; -} - FSReturnCode_t FileSystem_SetBasePaths( IFileSystem *pFileSystem ) { pFileSystem->RemoveSearchPaths( "EXECUTABLE_PATH" ); @@ -1210,18 +1116,6 @@ FSReturnCode_t FileSystem_GetFileSystemDLLName( char *pFileSystemDLL, int nMaxLe return FS_OK; } -//----------------------------------------------------------------------------- -// Sets up the steam.dll install path in our PATH env var (so you can then just -// LoadLibrary() on filesystem_steam.dll without having to copy steam.dll anywhere special ) -//----------------------------------------------------------------------------- -FSReturnCode_t FileSystem_SetupSteamInstallPath() -{ - CSteamEnvVars steamEnvVars; - char steamInstallPath[MAX_PATH]; - FSReturnCode_t ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - return ret; -} //----------------------------------------------------------------------------- // Sets up the steam environment + gets back the gameinfo.txt path @@ -1241,42 +1135,6 @@ FSReturnCode_t FileSystem_SetupSteamEnvironment( CFSSteamSetupInfo &fsInfo ) #else setenv( GAMEDIR_TOKEN, fsInfo.m_GameInfoPath, 1 ); #endif - - CSteamEnvVars steamEnvVars; - if ( fsInfo.m_bSteam ) - { - if ( fsInfo.m_bToolsMode ) - { - // Now, load gameinfo.txt (to make sure it's there) - KeyValues *pMainFile, *pFileSystemInfo, *pSearchPaths; - ret = LoadGameInfoFile( fsInfo.m_GameInfoPath, pMainFile, pFileSystemInfo, pSearchPaths ); - if ( ret != FS_OK ) - return ret; - - // If filesystem_stdio.dll is missing or -steam is specified, then load filesystem_steam.dll. - // There are two command line parameters for Steam: - // 1) -steam (runs Steam in remote filesystem mode; requires Steam backend) - // 2) -steamlocal (runs Steam in local filesystem mode (all content off HDD) - - // Setup all the environment variables related to Steam so filesystem_steam.dll knows how to initialize Steam. - ret = SetupSteamStartupEnvironment( pFileSystemInfo, fsInfo.m_GameInfoPath, steamEnvVars ); - if ( ret != FS_OK ) - return ret; - - steamEnvVars.m_SteamAppId.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - - // We're done with main file - pMainFile->deleteThis(); - } - else if ( fsInfo.m_bSetSteamDLLPath ) - { - // This is used by the engine to automatically set the path to their steam.dll when running the engine, - // so they can debug it without having to copy steam.dll up into their hl2.exe folder. - char steamInstallPath[MAX_PATH]; - ret = SetSteamInstallPath( steamInstallPath, sizeof( steamInstallPath ), steamEnvVars, true ); - steamEnvVars.m_Path.SetRestoreOriginalValue( false ); // We want to keep the change to the path going forward. - } - } return FS_OK; } diff --git a/mp/src/public/filesystem_init.h b/mp/src/public/filesystem_init.h index d95e7c3a..9274a5cb 100644 --- a/mp/src/public/filesystem_init.h +++ b/mp/src/public/filesystem_init.h @@ -209,11 +209,6 @@ void FileSystem_ClearSteamEnvVars(); // Find the steam.cfg above you for optional stuff FSReturnCode_t GetSteamCfgPath( char *steamCfgPath, int steamCfgPathLen ); -// Setup the Steam.dll path without needing all the extra gameinfo stuff first -// used by the CSteamApplication::Create() code to LoadModule() on the filesystem -// before the underlying apps know specific details about the environment to load -FSReturnCode_t FileSystem_SetupSteamInstallPath(); - // Returns the last error. const char *FileSystem_GetLastErrorString(); diff --git a/mp/src/public/gamebspfile.h b/mp/src/public/gamebspfile.h index 0b34c122..d9b1d2ac 100644 --- a/mp/src/public/gamebspfile.h +++ b/mp/src/public/gamebspfile.h @@ -36,7 +36,7 @@ enum { GAMELUMP_DETAIL_PROPS_VERSION = 4, GAMELUMP_DETAIL_PROP_LIGHTING_VERSION = 0, - GAMELUMP_STATIC_PROPS_VERSION = 7, + GAMELUMP_STATIC_PROPS_VERSION = 10, GAMELUMP_STATIC_PROP_LIGHTING_VERSION = 0, GAMELUMP_DETAIL_PROP_LIGHTING_HDR_VERSION = 0, }; diff --git a/mp/src/public/ibsppack.h b/mp/src/public/ibsppack.h index 7ecaa780..3f115d78 100644 --- a/mp/src/public/ibsppack.h +++ b/mp/src/public/ibsppack.h @@ -28,6 +28,13 @@ public: virtual void SetHDRMode( bool bHDR ) = 0; virtual bool SwapBSPFile( IFileSystem *pFileSystem, const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, CompressFunc_t pCompressFunc ) = 0; + enum eRepackBSPFlags + { + eRepackBSP_CompressLumps = 1 << 0, + eRepackBSP_CompressPackfile = 1 << 1 + }; + virtual bool RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, eRepackBSPFlags repackFlags ) = 0; + // used to get/set the pak file from a BSP virtual bool GetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, void **pPakData, int *pPakSize ) = 0; virtual bool SetPakFileLump( IFileSystem *pFileSystem, const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize ) = 0; @@ -36,6 +43,6 @@ public: virtual bool GetBSPDependants( IFileSystem *pFileSystem, const char *pBSPFilename, CUtlVector< CUtlString > *pList ) = 0; }; -#define IBSPPACK_VERSION_STRING "IBSPPACK003" +#define IBSPPACK_VERSION_STRING "IBSPPACK004" #endif // IBSPPACK_H diff --git a/mp/src/public/ispatialpartition.h b/mp/src/public/ispatialpartition.h index 6b6678f7..ff9bd7da 100644 --- a/mp/src/public/ispatialpartition.h +++ b/mp/src/public/ispatialpartition.h @@ -83,6 +83,9 @@ class IPartitionEnumerator { public: virtual IterationRetval_t EnumElement( IHandleEntity *pHandleEntity ) = 0; + // XXX(johns): This should have a virtual destructor, but would be ABI breaking (non-versioned interface implemented + // by the game) + // virtual ~IPartitionEnumerator(){} }; diff --git a/mp/src/public/jigglebones.cpp b/mp/src/public/jigglebones.cpp index 10038e58..29b8647d 100644 --- a/mp/src/public/jigglebones.cpp +++ b/mp/src/public/jigglebones.cpp @@ -23,7 +23,7 @@ ConVar cl_jiggle_bone_debug_yaw_constraints( "cl_jiggle_bone_debug_yaw_constrain ConVar cl_jiggle_bone_debug_pitch_constraints( "cl_jiggle_bone_debug_pitch_constraints", "0", FCVAR_CHEAT, "Display physics-based 'jiggle bone' debugging information" ); #endif // CLIENT_DLL -ConVar cl_jiggle_bone_framerate_cutoff( "cl_jiggle_bone_framerate_cutoff", "45", 0, "Skip jiggle bone simulation if framerate drops below this value (frames/second)" ); +ConVar cl_jiggle_bone_framerate_cutoff( "cl_jiggle_bone_framerate_cutoff", "20", 0, "Skip jiggle bone simulation if framerate drops below this value (frames/second)" ); //----------------------------------------------------------------------------- @@ -40,6 +40,10 @@ JiggleData * CJiggleBones::GetJiggleData( int bone, float currenttime, const Vec JiggleData data; data.Init( bone, currenttime, initBasePos, initTipPos ); + // Start out using jiggle bones for at least 16 frames. + data.useGoalMatrixCount = 0; + data.useJiggleBoneCount = 16; + int idx = m_jiggleBoneState.AddToHead( data ); if ( idx == m_jiggleBoneState.InvalidIndex() ) return NULL; @@ -96,11 +100,40 @@ void CJiggleBones::BuildJiggleTransformations( int boneIndex, float currenttime, float deltaT = currenttime - data->lastUpdate; const float thousandHZ = 0.001f; - if ( deltaT < thousandHZ ) + bool bMaxDeltaT = deltaT < thousandHZ; + bool bUseGoalMatrix = cl_jiggle_bone_framerate_cutoff.GetFloat() <= 0.0f || deltaT > ( 1.0f / cl_jiggle_bone_framerate_cutoff.GetFloat() ); + + if ( bUseGoalMatrix ) + { + // We hit the jiggle bone framerate cutoff. Reset the useGoalMatrixCount so we + // use the goal matrix at least 32 frames and don't flash back and forth. + data->useGoalMatrixCount = 32; + } + else if ( data->useGoalMatrixCount > 0 ) + { + // Below the cutoff, but still need to use the goal matrix a few more times. + bUseGoalMatrix = true; + data->useGoalMatrixCount--; + } + else + { + // Use real jiggle bones. Woot! + data->useJiggleBoneCount = 32; + } + + if ( data->useJiggleBoneCount > 0 ) + { + // Make sure we draw at least runs of 32 frames with real jiggle bones. + data->useJiggleBoneCount--; + data->useGoalMatrixCount = 0; + bUseGoalMatrix = false; + } + + if ( bMaxDeltaT ) { deltaT = thousandHZ; } - else if ( cl_jiggle_bone_framerate_cutoff.GetFloat() <= 0.0f || deltaT > ( 1.0f / cl_jiggle_bone_framerate_cutoff.GetFloat() ) ) + else if ( bUseGoalMatrix ) { // disable jigglebone - just use goal matrix boneMX = goalMX; diff --git a/mp/src/public/jigglebones.h b/mp/src/public/jigglebones.h index 57afdaa7..037a4866 100644 --- a/mp/src/public/jigglebones.h +++ b/mp/src/public/jigglebones.h @@ -65,6 +65,9 @@ struct JiggleData Vector boingVelDir; // current estimation of jiggle bone unit velocity vector for boing effect float boingSpeed; // current estimation of jiggle bone speed for boing effect float boingTime; + + int useGoalMatrixCount; // Count of times we need to fast draw using goal matrix. + int useJiggleBoneCount; // Count of times we need to draw using real jiggly bones. }; class CJiggleBones diff --git a/mp/src/public/loadcmdline.cpp b/mp/src/public/loadcmdline.cpp index 1df30efb..30c616f3 100644 --- a/mp/src/public/loadcmdline.cpp +++ b/mp/src/public/loadcmdline.cpp @@ -22,8 +22,7 @@ static void AddArguments( int &argc, char **&argv, const char *str ) char *argList = 0; int argCt = argc; - argList = new char[ Q_strlen( str ) + 1 ]; - Q_strcpy( argList, str ); + argList = V_strdup( str ); // Parse the arguments out of the string char *token = strtok( argList, " " ); @@ -45,8 +44,7 @@ static void AddArguments( int &argc, char **&argv, const char *str ) int i; for( i = 0; i < argc - 1; ++i ) { - args[ i ] = new char[ Q_strlen( argv[ i ] ) + 1 ]; - Q_strcpy( args[ i ], argv[ i ] ); + args[ i ] = V_strdup( argv[ i ] ); } // copy new arguments @@ -54,14 +52,12 @@ static void AddArguments( int &argc, char **&argv, const char *str ) token = strtok( argList, " " ); for( ; i < argCt - 1; ++i ) { - args[ i ] = new char[ Q_strlen( token ) + 1 ]; - Q_strcpy( args[ i ], token ); + args[ i ] = V_strdup( token ); token = strtok( NULL, " " ); } // Copy the last original argument - args[ i ] = new char[ Q_strlen( argv[ argc - 1 ] ) + 1 ]; - Q_strcpy( args[ i ], argv[ argc - 1 ] ); + args[ i ] = V_strdup( argv[ argc - 1 ] ); argc = argCt; argv = args; @@ -120,4 +116,4 @@ void DeleteCmdLine( int argc, char **argv ) delete [] argv[i]; } delete [] argv; -} \ No newline at end of file +} diff --git a/mp/src/public/materialsystem/IShader.h b/mp/src/public/materialsystem/IShader.h index 27bf91e3..7815e8aa 100644 --- a/mp/src/public/materialsystem/IShader.h +++ b/mp/src/public/materialsystem/IShader.h @@ -21,8 +21,9 @@ // it's not 256, because you can't use all 256 slots in 10.5.x. // use this constant everywhere you might normally use "256" in reference to a parameter array size. // The highest shader constant is c218, plus we allocate c219 and c220 for two clip planes -#define DXABSTRACT_VS_PARAM_SLOTS 219 +#define DXABSTRACT_VS_PARAM_SLOTS 228 #define DXABSTRACT_VS_FIRST_BONE_SLOT VERTEX_SHADER_MODEL +#define DXABSTRACT_VS_LAST_BONE_SLOT (VERTEX_SHADER_SHADER_SPECIFIC_CONST_13-1) // user clip plane 0 goes in DXABSTRACT_VS_CLIP_PLANE_BASE... plane 1 goes in the slot after that // dxabstract uses these constants to check plane index limit and to deliver planes to shader for DP4 -> oCLP[n] @@ -33,6 +34,8 @@ #include "materialsystem/imaterialsystem.h" #include "materialsystem/ishaderapi.h" +#include "materialsystem/ishadersystem_declarations.h" + //----------------------------------------------------------------------------- // forward declarations @@ -43,24 +46,6 @@ class IShaderDynamicAPI; class IShaderInit; class CBasePerMaterialContextData; -//----------------------------------------------------------------------------- -// Shader flags -//----------------------------------------------------------------------------- -enum ShaderFlags_t -{ - SHADER_NOT_EDITABLE = 0x1 -}; - - -//----------------------------------------------------------------------------- -// Shader parameter flags -//----------------------------------------------------------------------------- -enum ShaderParamFlags_t -{ - SHADER_PARAM_NOT_EDITABLE = 0x1 -}; - - //----------------------------------------------------------------------------- // Information about each shader parameter //----------------------------------------------------------------------------- @@ -74,72 +59,10 @@ struct ShaderParamInfo_t }; -//----------------------------------------------------------------------------- -// Standard vertex shader constants -//----------------------------------------------------------------------------- -enum -{ - // Standard vertex shader constants - VERTEX_SHADER_MATH_CONSTANTS0 = 0, - VERTEX_SHADER_MATH_CONSTANTS1 = 1, - VERTEX_SHADER_CAMERA_POS = 2, - VERTEX_SHADER_FLEXSCALE = 3, // used by DX9 only! - VERTEX_SHADER_LIGHT_INDEX = 3, // used by DX8 only! - VERTEX_SHADER_MODELVIEWPROJ = 4, - VERTEX_SHADER_VIEWPROJ = 8, - VERTEX_SHADER_MODELVIEWPROJ_THIRD_ROW = 12, - VERTEX_SHADER_VIEWPROJ_THIRD_ROW = 13, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_10 = 14, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_11 = 15, - VERTEX_SHADER_FOG_PARAMS = 16, - VERTEX_SHADER_VIEWMODEL = 17, - VERTEX_SHADER_AMBIENT_LIGHT = 21, - VERTEX_SHADER_LIGHTS = 27, - VERTEX_SHADER_LIGHT0_POSITION = 29, - VERTEX_SHADER_MODULATION_COLOR = 47, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 = 48, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_1 = 49, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 = 50, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 = 51, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 = 52, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 = 53, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 = 54, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_7 = 55, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_8 = 56, - VERTEX_SHADER_SHADER_SPECIFIC_CONST_9 = 57, - VERTEX_SHADER_MODEL = 58, - - // - // We reserve up through 216 for the 53 bones - // - - // 219 ClipPlane0 |------ OpenGL will jam clip planes into these two - // 220 ClipPlane1 | - - VERTEX_SHADER_FLEX_WEIGHTS = 1024, - VERTEX_SHADER_MAX_FLEX_WEIGHT_COUNT = 512, -}; #define VERTEX_SHADER_BONE_TRANSFORM( k ) ( VERTEX_SHADER_MODEL + 3 * (k) ) -//----------------------------------------------------------------------------- -// Standard vertex shader constants -//----------------------------------------------------------------------------- -enum -{ - // Standard vertex shader constants - VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST = 0, - VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST_COUNT = 4, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_0 = 4, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_1 = 5, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_2 = 6, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_3 = 7, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_4 = 8, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_5 = 9, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_6 = 10, - VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_7 = 11, -}; // The public methods exposed by each shader //----------------------------------------------------------------------------- abstract_class IShader @@ -179,27 +102,4 @@ public: // virtual const ShaderParamInfo_t& GetParamInfo( int paramIndex ) const = 0; }; - -//----------------------------------------------------------------------------- -// Shader dictionaries defined in DLLs -//----------------------------------------------------------------------------- -enum PrecompiledShaderType_t -{ - PRECOMPILED_VERTEX_SHADER = 0, - PRECOMPILED_PIXEL_SHADER, - - PRECOMPILED_SHADER_TYPE_COUNT, -}; - - -//----------------------------------------------------------------------------- -// Flags field of PrecompiledShader_t -//----------------------------------------------------------------------------- -enum -{ - // runtime flags - SHADER_DYNAMIC_COMPILE_IS_HLSL = 0x1, - SHADER_FAILED_LOAD = 0x2, -}; - #endif // ISHADER_H diff --git a/mp/src/public/materialsystem/combineoperations.h b/mp/src/public/materialsystem/combineoperations.h new file mode 100644 index 00000000..195f19f4 --- /dev/null +++ b/mp/src/public/materialsystem/combineoperations.h @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef COMBINEOPERATIONS_H +#define COMBINEOPERATIONS_H +#pragma once + +// New combines can be written in the middle (and generally should be written before Error). +// Keep these in sync with cCombineMaterialName in ctexturecompositor.cpp +enum ECombineOperation +{ + ECO_Multiply = 0, + ECO_Add, + ECO_Lerp, + + ECO_Select, + + ECO_Legacy_Lerp_FirstPass, + ECO_Legacy_Lerp_SecondPass, + + ECO_Error, + ECO_COUNT +}; + +#endif /* COMBINEOPERATIONS_H */ diff --git a/mp/src/public/materialsystem/imaterialsystem.h b/mp/src/public/materialsystem/imaterialsystem.h index 3f3563b6..bf896579 100644 --- a/mp/src/public/materialsystem/imaterialsystem.h +++ b/mp/src/public/materialsystem/imaterialsystem.h @@ -43,6 +43,7 @@ struct MaterialSystem_Config_t; class VMatrix; struct matrix3x4_t; class ITexture; +class ITextureCompositor; struct MaterialSystemHardwareIdentifier_t; class KeyValues; class IShader; @@ -88,6 +89,7 @@ enum ShaderParamType_t SHADER_PARAM_TYPE_MATRIX, SHADER_PARAM_TYPE_MATERIAL, SHADER_PARAM_TYPE_STRING, + SHADER_PARAM_TYPE_MATRIX4X2 }; enum MaterialMatrixMode_t @@ -289,7 +291,6 @@ private: #define CREATERENDERTARGETFLAGS_NOEDRAM 0x00000008 // inhibit allocation in 360 EDRAM #define CREATERENDERTARGETFLAGS_TEMP 0x00000010 // only allocates memory upon first resolve, destroyed at level end - //----------------------------------------------------------------------------- // allowed stencil operations. These match the d3d operations //----------------------------------------------------------------------------- @@ -478,6 +479,21 @@ private: int m_nBottom; }; +// Passed as the callback object to Async functions in the material system +// so that callers don't have to worry about memory going out of scope before the +// results return. +abstract_class IAsyncTextureOperationReceiver : public IRefCounted +{ +public: + virtual void OnAsyncCreateComplete( ITexture* pTex, void* pExtraArgs ) = 0; + virtual void OnAsyncFindComplete( ITexture* pTex, void* pExtraArgs ) = 0; + virtual void OnAsyncMapComplete( ITexture* pTex, void* pExtraArgs, void* pMemory, int nPitch ) = 0; + virtual void OnAsyncReadbackBegin( ITexture* pDst, ITexture* pSrc, void* pExtraArgs ) = 0; + + virtual int GetRefCount() const = 0; +}; + + //----------------------------------------------------------------------------- // Flags to be used with the Init call //----------------------------------------------------------------------------- @@ -525,7 +541,9 @@ enum RenderTargetSizeMode_t RT_SIZE_OFFSCREEN=5, // Target of specified size, don't mess with dimensions RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP=6, // Same size as the frame buffer, rounded up if necessary for systems that can't do non-power of two textures. RT_SIZE_REPLAY_SCREENSHOT = 7, // Rounded down to power of 2, essentially... - RT_SIZE_LITERAL = 8 // Use the size passed in. Don't clamp it to the frame buffer size. Really. + RT_SIZE_LITERAL = 8, // Use the size passed in. Don't clamp it to the frame buffer size. Really. + RT_SIZE_LITERAL_PICMIP = 9 // Use the size passed in, don't clamp to the frame buffer size, but do apply picmip restrictions. + }; typedef void (*MaterialBufferReleaseFunc_t)( ); @@ -1043,6 +1061,23 @@ public: // creates a texture suitable for use with materials from a raw stream of bits. // The bits will be retained by the material system and can be freed upon return. virtual ITexture* CreateTextureFromBits(int w, int h, int mips, ImageFormat fmt, int srcBufferSize, byte* srcBits) = 0; + + // Lie to the material system to pretend to be in render target allocation mode at the beginning of time. + // This was a thing that mattered a lot to old hardware, but doesn't matter at all to new hardware, + // where new is defined to be "anything from the last decade." However, we want to preserve legacy behavior + // for the old games because it's easier than testing them. + virtual void OverrideRenderTargetAllocation( bool rtAlloc ) = 0; + + // creates a texture compositor that will attempt to composite a new textuer from the steps of the specified KeyValues. + virtual ITextureCompositor* NewTextureCompositor( int w, int h, const char* pCompositeName, int nTeamNum, uint64 randomSeed, KeyValues* stageDesc, uint32 texCompositeCreateFlags = 0 ) = 0; + + // Loads the texture with the specified name, calls pRecipient->OnAsyncFindComplete with the result from the main thread. + // once the texture load is complete. If the texture cannot be found, the returned texture will return true for IsError(). + virtual void AsyncFindTexture( const char* pFilename, const char *pTextureGroupName, IAsyncTextureOperationReceiver* pRecipient, void* pExtraArgs, bool bComplain = true, int nAdditionalCreationFlags = 0 ) = 0; + + // creates a texture suitable for use with materials from a raw stream of bits. + // The bits will be retained by the material system and can be freed upon return. + virtual ITexture* CreateNamedTextureFromBitsEx( const char* pName, const char *pTextureGroupName, int w, int h, int mips, ImageFormat fmt, int srcBufferSize, byte* srcBits, int nFlags ) = 0; }; @@ -1504,6 +1539,11 @@ public: virtual void OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable ) = 0; virtual void ClearBuffersObeyStencilEx( bool bClearColor, bool bClearAlpha, bool bClearDepth ) = 0; + + // Create a texture from the specified src render target, then call pRecipient->OnAsyncCreateComplete from the main thread. + // The texture will be created using the destination format, and will optionally have mipmaps generated. + // In case of error, the provided callback function will be called with the error texture. + virtual void AsyncCreateTextureFromRenderTarget( ITexture* pSrcRt, const char* pDstName, ImageFormat dstFmt, bool bGenMips, int nAdditionalCreationFlags, IAsyncTextureOperationReceiver* pRecipient, void* pExtraArgs ) = 0; }; template< class E > inline E* IMatRenderContext::LockRenderDataTyped( int nCount, const E* pSrcData ) diff --git a/mp/src/public/materialsystem/ishadersystem_declarations.h b/mp/src/public/materialsystem/ishadersystem_declarations.h new file mode 100644 index 00000000..3c54edca --- /dev/null +++ b/mp/src/public/materialsystem/ishadersystem_declarations.h @@ -0,0 +1,131 @@ +//===== Copyright © Valve Corporation, All rights reserved. ======// +#ifndef ISHADER_DECLARATIONS_HDR +#define ISHADER_DECLARATIONS_HDR + +//----------------------------------------------------------------------------- +// Standard vertex shader constants +//----------------------------------------------------------------------------- +enum +{ + // Standard vertex shader constants + VERTEX_SHADER_MATH_CONSTANTS0 = 0, + VERTEX_SHADER_MATH_CONSTANTS1 = 1, + VERTEX_SHADER_CAMERA_POS = 2, + VERTEX_SHADER_FLEXSCALE = 3, // DX9 only + VERTEX_SHADER_LIGHT_INDEX = 3, // DX8 only + VERTEX_SHADER_MODELVIEWPROJ = 4, + VERTEX_SHADER_VIEWPROJ = 8, + VERTEX_SHADER_MODELVIEWPROJ_THIRD_ROW = 12, + VERTEX_SHADER_VIEWPROJ_THIRD_ROW = 13, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_10 = 14, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_11 = 15, + VERTEX_SHADER_FOG_PARAMS = 16, + VERTEX_SHADER_VIEWMODEL = 17, + VERTEX_SHADER_AMBIENT_LIGHT = 21, + VERTEX_SHADER_LIGHTS = 27, + VERTEX_SHADER_LIGHT0_POSITION = 29, + VERTEX_SHADER_MODULATION_COLOR = 47, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_0 = 48, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_1 = 49, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 = 50, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 = 51, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_4 = 52, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_5 = 53, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_6 = 54, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_7 = 55, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_8 = 56, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_9 = 57, + VERTEX_SHADER_MODEL = 58, + // + // We reserve up through 216 for the 53 bones supported on DX9 + // + VERTEX_SHADER_SHADER_SPECIFIC_CONST_13 = 217, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_14 = 218, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_15 = 219, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_16 = 220, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_17 = 221, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_18 = 222, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_19 = 223, + VERTEX_SHADER_SHADER_SPECIFIC_CONST_12 = 224, + + // 226 ClipPlane0 |------ OpenGL will jam clip planes into these two + // 227 ClipPlane1 | + + + VERTEX_SHADER_FLEX_WEIGHTS = 1024, + VERTEX_SHADER_MAX_FLEX_WEIGHT_COUNT = 512, +}; + +//----------------------------------------------------------------------------- +// forward declarations +//----------------------------------------------------------------------------- +class IMaterialVar; +class IShaderShadow; +class IShaderDynamicAPI; +class IShaderInit; +class CBasePerMaterialContextData; + + +//----------------------------------------------------------------------------- +// Shader flags +//----------------------------------------------------------------------------- +enum ShaderFlags_t +{ + SHADER_NOT_EDITABLE = 0x1 +}; + + +//----------------------------------------------------------------------------- +// Shader parameter flags +//----------------------------------------------------------------------------- +enum ShaderParamFlags_t +{ + SHADER_PARAM_NOT_EDITABLE = 0x1 +}; + + + +//----------------------------------------------------------------------------- +// Standard vertex shader constants +//----------------------------------------------------------------------------- +enum +{ + // Standard vertex shader constants + VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST = 0, + VERTEX_SHADER_LIGHT_ENABLE_BOOL_CONST_COUNT = 4, + + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_0 = 4, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_1 = 5, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_2 = 6, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_3 = 7, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_4 = 8, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_5 = 9, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_6 = 10, + VERTEX_SHADER_SHADER_SPECIFIC_BOOL_CONST_7 = 11, +}; + + +//----------------------------------------------------------------------------- +// Shader dictionaries defined in DLLs +//----------------------------------------------------------------------------- +enum PrecompiledShaderType_t +{ + PRECOMPILED_VERTEX_SHADER = 0, + PRECOMPILED_PIXEL_SHADER, + + PRECOMPILED_SHADER_TYPE_COUNT, +}; + + +//----------------------------------------------------------------------------- +// Flags field of PrecompiledShader_t +//----------------------------------------------------------------------------- +enum +{ + // runtime flags + SHADER_IS_ASM = 0x1, + SHADER_FAILED_LOAD = 0x2, +}; + + +#endif \ No newline at end of file diff --git a/mp/src/public/materialsystem/itexture.h b/mp/src/public/materialsystem/itexture.h index a5aa20fd..0e315447 100644 --- a/mp/src/public/materialsystem/itexture.h +++ b/mp/src/public/materialsystem/itexture.h @@ -39,6 +39,10 @@ public: // This will be called when the regenerator needs to be deleted // which will happen when the texture is destroyed virtual void Release() = 0; + + // (erics): This should have a virtual destructor, but would be ABI breaking (non-versioned interface implemented + // by the game) +// virtual ~ITextureRegenerator(){} }; abstract_class ITexture @@ -120,6 +124,13 @@ public: // Save texture to a file. virtual bool SaveToFile( const char *fileName ) = 0; + + // Copy this texture, which must be a render target or a renderable texture, to the destination texture, + // which must have been created with the STAGING bit. + virtual void CopyToStagingTexture( ITexture* pDstTex ) = 0; + + // Set that this texture should return true for the call "IsError" + virtual void SetErrorTexture( bool bIsErrorTexture ) = 0; }; diff --git a/mp/src/public/materialsystem/itexturecompositor.h b/mp/src/public/materialsystem/itexturecompositor.h new file mode 100644 index 00000000..a158d36c --- /dev/null +++ b/mp/src/public/materialsystem/itexturecompositor.h @@ -0,0 +1,50 @@ +//========= Copyright Valve Corporation, All rights reserved. ================================== // +// +// Purpose: Defines a texture compositor infterface which uses simple operations and shaders to +// create complex procedural textures. +// +//============================================================================================== // + +#ifndef ITEXTURECOMPOSITOR_H +#define ITEXTURECOMPOSITOR_H +#pragma once + +#include "interface.h" +#include "itexture.h" + +#define ITEXTURE_COMPOSITOR_INTERFACE_VERSION "_ITextureCompositor000" + +enum ECompositeResolveStatus +{ + ECRS_Idle, + ECRS_Scheduled, + ECRS_PendingTextureLoads, + ECRS_PendingComposites, + ECRS_Error, + ECRS_Complete +}; + +enum TextureCompositeCreateFlags_t +{ + TEX_COMPOSITE_CREATE_FLAGS_FORCE = 0x00000001, + TEX_COMPOSITE_CREATE_FLAGS_NO_COMPRESSION = 0x00000002, + TEX_COMPOSITE_CREATE_FLAGS_NO_MIPMAPS = 0x00000004, +}; + +abstract_class ITextureCompositor +{ +public: + virtual int AddRef() = 0; + virtual int Release() = 0; + virtual int GetRefCount() const = 0; + + virtual void Update() = 0; + virtual ITexture* GetResultTexture() const = 0; + virtual ECompositeResolveStatus GetResolveStatus() const = 0; + virtual void ScheduleResolve() = 0; +protected: + virtual ~ITextureCompositor() {} +}; + + +#endif /* ITEXTURECOMPOSITOR_H */ diff --git a/mp/src/public/mathlib/mathlib.h b/mp/src/public/mathlib/mathlib.h index bd6f3027..05df16d5 100644 --- a/mp/src/public/mathlib/mathlib.h +++ b/mp/src/public/mathlib/mathlib.h @@ -1203,7 +1203,7 @@ inline float SimpleSplineRemapValClamped( float val, float A, float B, float C, FORCEINLINE int RoundFloatToInt(float f) { -#if defined(__i386__) || defined(_M_IX86) || defined( PLATFORM_WINDOWS_PC64 ) +#if defined(__i386__) || defined(_M_IX86) || defined( PLATFORM_WINDOWS_PC64 ) || defined(__x86_64__) return _mm_cvtss_si32(_mm_load_ss(&f)); #elif defined( _X360 ) #ifdef Assert diff --git a/mp/src/public/matsys_controls/QCGenerator.h b/mp/src/public/matsys_controls/QCGenerator.h index d9978f88..d6b69d21 100644 --- a/mp/src/public/matsys_controls/QCGenerator.h +++ b/mp/src/public/matsys_controls/QCGenerator.h @@ -79,9 +79,9 @@ struct QCInfo { pQCGenerator = pPanel; - Q_strcpy( pszSMDPath, "" ); - Q_strcpy( pszCollisionPath, "" ); - Q_strcpy( pszSurfaceProperty, "default" ); + V_strcpy_safe( pszSMDPath, "" ); + V_strcpy_safe( pszCollisionPath, "" ); + V_strcpy_safe( pszSurfaceProperty, "default" ); bStaticProp = false; bMostlyOpaque = false; bDisableCollision = false; diff --git a/mp/src/public/matsys_controls/manipulator.h b/mp/src/public/matsys_controls/manipulator.h index a08426ef..f030509a 100644 --- a/mp/src/public/matsys_controls/manipulator.h +++ b/mp/src/public/matsys_controls/manipulator.h @@ -19,6 +19,7 @@ class IManipulator { public: + virtual ~IManipulator(){} virtual void OnBeginManipulation( void ) = 0; virtual void OnAcceptManipulation( void ) = 0; virtual void OnCancelManipulation( void ) = 0; diff --git a/mp/src/public/matsys_controls/mdlpanel.h b/mp/src/public/matsys_controls/mdlpanel.h index 070fb973..60068567 100644 --- a/mp/src/public/matsys_controls/mdlpanel.h +++ b/mp/src/public/matsys_controls/mdlpanel.h @@ -64,7 +64,7 @@ public: void SetLOD( int nLOD ); // Sets the current sequence - void SetSequence( int nSequence ); + void SetSequence( int nSequence, bool bResetSequence = false ); // Set the pose parameters void SetPoseParameters( const float *pPoseParameters, int nCount ); @@ -113,6 +113,7 @@ protected: CMDL m_MDL; matrix3x4_t m_MDLToWorld; bool m_bDisabled; + float m_flCycleStartTime; }; MDLData_t m_RootMDL; diff --git a/mp/src/public/matsys_controls/potterywheelpanel.h b/mp/src/public/matsys_controls/potterywheelpanel.h index 47125a3f..5da55e48 100644 --- a/mp/src/public/matsys_controls/potterywheelpanel.h +++ b/mp/src/public/matsys_controls/potterywheelpanel.h @@ -45,6 +45,7 @@ public: virtual ~CPotteryWheelPanel(); // Overriden methods of vgui::Panel + virtual void ApplySettings( KeyValues *inResourceData ); virtual void Init( int x, int y, int wide, int tall ); virtual void Paint(); @@ -117,6 +118,7 @@ protected: bool WarpMouse( int &x, int &y ); IManipulator *m_pCurrentManip; int m_nManipStartX, m_nManipStartY; + int m_nClickStartX, m_nClickStartY; // Re-apply the manipulators on a new model void ApplyManipulation(); @@ -136,6 +138,7 @@ protected: private: void CreateDefaultLights(); void DestroyLights(); + void ParseLightsFromKV( KeyValues *pLightsKV ); CMaterialReference m_LightProbeBackground; CMaterialReference m_LightProbeHDRBackground; diff --git a/mp/src/public/particles/particles.h b/mp/src/public/particles/particles.h index 16b48e74..4066d85e 100644 --- a/mp/src/public/particles/particles.h +++ b/mp/src/public/particles/particles.h @@ -154,6 +154,7 @@ enum ParticleFunctionType_t struct CParticleVisibilityInputs { + float m_flCameraBias; float m_flInputMin; float m_flInputMax; float m_flAlphaScaleMin; @@ -668,7 +669,7 @@ public: } // should the constraint be run only once after all other constraints? - virtual bool IsFinalConstaint( void ) const + virtual bool IsFinalConstraint( void ) const { return false; } @@ -720,6 +721,12 @@ public: return false; } + // Does this operator require that particles remain in the order they were emitted? + virtual bool RequiresOrderInvariance( void ) const + { + return false; + } + // Called when the SFM wants to skip forward in time virtual void SkipToTime( float flTime, CParticleCollection *pParticles, void *pContext ) const {} @@ -881,7 +888,9 @@ private: DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale minimum","0", float, VisibilityInputs.m_flAlphaScaleMin ) \ DMXELEMENT_UNPACK_FIELD( "Visibility Alpha Scale maximum","1", float, VisibilityInputs.m_flAlphaScaleMax ) \ DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale minimum","1", float, VisibilityInputs.m_flRadiusScaleMin ) \ - DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale maximum","1", float, VisibilityInputs.m_flRadiusScaleMax ) + DMXELEMENT_UNPACK_FIELD( "Visibility Radius Scale maximum","1", float, VisibilityInputs.m_flRadiusScaleMax ) \ + DMXELEMENT_UNPACK_FIELD( "Visibility Camera Depth Bias", "0", float, VisibilityInputs.m_flCameraBias ) + // DMXELEMENT_UNPACK_FIELD( "Visibility Use Bounding Box for Proxy", "0", bool, VisibilityInputs.m_bUseBBox ) // DMXELEMENT_UNPACK_FIELD( "Visibility Bounding Box Scale", "1.0", float, VisibilityInputs.m_flBBoxScale ) @@ -961,6 +970,7 @@ struct CParticleVisibilityData { float m_flAlphaVisibility; float m_flRadiusVisibility; + float m_flCameraBias; bool m_bUseVisibility; }; @@ -1062,7 +1072,7 @@ public: float *GetInitialFloatAttributePtrForWrite( int nAttribute, int nParticleNumber ); fltx4 *GetInitialM128AttributePtrForWrite( int nAttribute, size_t *pStrideOut ); - void Simulate( float dt ); + void Simulate( float dt, bool updateBboxOnly ); void SkipToTime( float t ); // the camera objetc may be compared for equality against control point objects @@ -1094,14 +1104,17 @@ public: // Used to retrieve the position of a control point // somewhere between m_fCurTime and m_fCurTime - m_fPreviousDT - void GetControlPointAtTime( int nControlPoint, float flTime, Vector *pControlPoint ); - void GetControlPointAtPrevTime( int nControlPoint, Vector *pControlPoint ); + void GetControlPointAtTime( int nControlPoint, float flTime, Vector *pControlPoint ) const; + void GetControlPointAtPrevTime( int nControlPoint, Vector *pControlPoint ) const; void GetControlPointOrientationAtTime( int nControlPoint, float flTime, Vector *pForward, Vector *pRight, Vector *pUp ); void GetControlPointTransformAtTime( int nControlPoint, float flTime, matrix3x4_t *pMat ); void GetControlPointTransformAtTime( int nControlPoint, float flTime, VMatrix *pMat ); void GetControlPointTransformAtTime( int nControlPoint, float flTime, CParticleSIMDTransformation *pXForm ); int GetHighestControlPoint( void ) const; + // Has this particle moved recently (since the last simulation?) + bool HasMoved() const; + // Control point accessed: // NOTE: Unlike the definition's version of these methods, // these OR-in the masks of their children. @@ -1249,6 +1262,7 @@ private: bool ComputeIsTranslucent(); bool ComputeIsTwoPass(); bool ComputeIsBatchable(); + bool ComputeRequiresOrderInvariance(); void LabelTextureUsage( void ); @@ -1270,6 +1284,7 @@ public: int m_nMaxAllowedParticles; bool m_bDormant; bool m_bEmissionStopped; + bool m_bRequiresOrderInvariance; int m_LocalLightingCP; Color m_LocalLighting; @@ -1337,6 +1352,7 @@ private: // How many frames have we drawn? int m_nDrawnFrames; + int m_nSimulatedFrames; Vector m_Center; // average of particle centers @@ -1805,9 +1821,12 @@ inline fltx4 *CParticleCollection::GetM128AttributePtrForWrite( int nAttribute, { // NOTE: If you hit this assertion, it means your particle operator isn't returning // the appropriate fields in the RequiredAttributesMask call - Assert( !m_bIsRunningInitializers || ( m_nPerParticleInitializedAttributeMask & (1 << nAttribute) ) ); - Assert( !m_bIsRunningOperators || ( m_nPerParticleUpdatedAttributeMask & (1 << nAttribute) ) ); - Assert( m_nParticleFloatStrides[nAttribute] != 0 ); + if ( !HushAsserts() ) + { + Assert( !m_bIsRunningInitializers || ( m_nPerParticleInitializedAttributeMask & (1 << nAttribute) ) ); + Assert( !m_bIsRunningOperators || ( m_nPerParticleUpdatedAttributeMask & (1 << nAttribute) ) ); + Assert( m_nParticleFloatStrides[nAttribute] != 0 ); + } *(pStrideOut) = m_nParticleFloatStrides[ nAttribute ]/4; return reinterpret_cast( m_pParticleAttributes[ nAttribute ] ); diff --git a/mp/src/public/saverestoretypes.h b/mp/src/public/saverestoretypes.h index 08a35361..7868e2fb 100644 --- a/mp/src/public/saverestoretypes.h +++ b/mp/src/public/saverestoretypes.h @@ -93,7 +93,7 @@ struct levellist_t { DECLARE_SIMPLE_DATADESC(); - char mapName[ MAX_MAP_NAME ]; + char mapName[ MAX_MAP_NAME_SAVE ]; char landmarkName[ 32 ]; edict_t *pentLandmark; Vector vecLandmarkOrigin; @@ -171,7 +171,7 @@ struct saverestorelevelinfo_t char szLandmarkName[20]; // landmark we'll spawn near in next level Vector vecLandmarkOffset; // for landmark transitions float time; - char szCurrentMapName[MAX_MAP_NAME]; // To check global entities + char szCurrentMapName[MAX_MAP_NAME_SAVE]; // To check global entities int mapVersion; }; diff --git a/mp/src/public/sentence.cpp b/mp/src/public/sentence.cpp index 1afba9b9..bb7ade5e 100644 --- a/mp/src/public/sentence.cpp +++ b/mp/src/public/sentence.cpp @@ -671,6 +671,10 @@ void CSentence::ParseDataVersionOnePointZero( CUtlBuffer& buf ) buf.GetString( token ); if ( strlen( token ) <= 0 ) break; + + // end of block, return + if ( !V_strcmp( token, "}" ) ) + break; char section[ 256 ]; Q_strncpy( section, token, sizeof( section ) ); diff --git a/mp/src/public/shaderapi/ishaderapi.h b/mp/src/public/shaderapi/ishaderapi.h index 367cd0e9..1a90caee 100644 --- a/mp/src/public/shaderapi/ishaderapi.h +++ b/mp/src/public/shaderapi/ishaderapi.h @@ -82,7 +82,7 @@ enum CreateTextureFlags_t TEXTURE_CREATE_VERTEXTEXTURE = 0x0040, // for internal use only TEXTURE_CREATE_FALLBACK = 0x0080, // 360 only TEXTURE_CREATE_NOD3DMEMORY = 0x0100, // 360 only - TEXTURE_CREATE_UNUSED3 = 0x0200, // Dead + TEXTURE_CREATE_SYSMEM = 0x0200, // This texture should be alloc'd in the sysmem pool TEXTURE_CREATE_UNUSED4 = 0x0400, // Dead TEXTURE_CREATE_UNUSED5 = 0x0800, // Dead TEXTURE_CREATE_UNFILTERABLE_OK = 0x1000, @@ -611,6 +611,13 @@ public: //extended clear buffers function with alpha independent from color virtual void ClearBuffersObeyStencilEx( bool bClearColor, bool bClearAlpha, bool bClearDepth ) = 0; + + // Allows copying a render target to another texture by specifying them both. + virtual void CopyRenderTargetToScratchTexture( ShaderAPITextureHandle_t srcRt, ShaderAPITextureHandle_t dstTex, Rect_t *pSrcRect = NULL, Rect_t *pDstRect = NULL ) = 0; + + // Allows locking and unlocking of very specific surface types. + virtual void LockRect( void** pOutBits, int* pOutPitch, ShaderAPITextureHandle_t texHandle, int mipmap, int x, int y, int w, int h, bool bWrite, bool bRead ) = 0; + virtual void UnlockRect( ShaderAPITextureHandle_t texHandle, int mipmap ) = 0; }; diff --git a/mp/src/public/steam/isteamapps.h b/mp/src/public/steam/isteamapps.h index 7070e2e9..07005836 100644 --- a/mp/src/public/steam/isteamapps.h +++ b/mp/src/public/steam/isteamapps.h @@ -49,7 +49,7 @@ public: // Install/Uninstall control for optional DLC virtual void InstallDLC( AppId_t nAppID ) = 0; virtual void UninstallDLC( AppId_t nAppID ) = 0; - + // Request cd-key for yourself or owned DLC. If you are interested in this // data then make sure you provide us with a list of valid keys to be distributed // to users when they purchase the game, before the game ships. @@ -73,13 +73,18 @@ public: // but it is advised that you not param names beginning with an underscore for your own features. virtual const char *GetLaunchQueryParam( const char *pchKey ) = 0; + // get download progress for optional DLC + virtual bool GetDlcDownloadProgress( AppId_t nAppID, uint64 *punBytesDownloaded, uint64 *punBytesTotal ) = 0; + + // return the buildid of this app, may change at any time based on backend updates to the game + virtual int GetAppBuildId() = 0; #ifdef _PS3 // Result returned in a RegisterActivationCodeResponse_t callresult virtual SteamAPICall_t RegisterActivationCode( const char *pchActivationCode ) = 0; #endif }; -#define STEAMAPPS_INTERFACE_VERSION "STEAMAPPS_INTERFACE_VERSION006" +#define STEAMAPPS_INTERFACE_VERSION "STEAMAPPS_INTERFACE_VERSION007" // callbacks #if defined( VALVE_CALLBACK_PACK_SMALL ) diff --git a/mp/src/public/steam/isteamclient.h b/mp/src/public/steam/isteamclient.h index 44c1df66..796d72d6 100644 --- a/mp/src/public/steam/isteamclient.h +++ b/mp/src/public/steam/isteamclient.h @@ -1,4 +1,4 @@ -//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= +//====== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======= // // Purpose: Main interface for loading and accessing Steamworks API's from the // Steam client. @@ -40,7 +40,7 @@ #error ??? #endif -typedef struct +typedef struct ValvePackingSentinel_t { uint32 m_u32; uint64 m_u64; @@ -98,6 +98,8 @@ class ISteamController; class ISteamUGC; class ISteamAppList; class ISteamHTMLSurface; +class ISteamInventory; +class ISteamVideo; //----------------------------------------------------------------------------- // Purpose: Interface to creating a new steam instance, or to @@ -221,9 +223,16 @@ public: virtual void Set_SteamAPI_CPostAPIResultInProcess( SteamAPI_PostAPIResultInProcess_t func ) = 0; virtual void Remove_SteamAPI_CPostAPIResultInProcess( SteamAPI_PostAPIResultInProcess_t func ) = 0; virtual void Set_SteamAPI_CCheckCallbackRegisteredInProcess( SteamAPI_CheckCallbackRegistered_t func ) = 0; + + // inventory + virtual ISteamInventory *GetISteamInventory( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; + + // Video + virtual ISteamVideo *GetISteamVideo( HSteamUser hSteamuser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0; }; -#define STEAMCLIENT_INTERFACE_VERSION "SteamClient016" + +#define STEAMCLIENT_INTERFACE_VERSION "SteamClient017" //----------------------------------------------------------------------------- // Purpose: Base values for callback identifiers, each callback must @@ -275,6 +284,7 @@ enum { k_iClientReservedCallbacks = 4300 }; enum { k_iSteamReservedCallbacks = 4400 }; enum { k_iSteamHTMLSurfaceCallbacks = 4500 }; enum { k_iClientVideoCallbacks = 4600 }; +enum { k_iClientInventoryCallbacks = 4700 }; //----------------------------------------------------------------------------- // The CALLBACK macros are for client side callback logging enabled with diff --git a/mp/src/public/steam/isteamcontroller.h b/mp/src/public/steam/isteamcontroller.h index 6a97a6fc..5c3d01ab 100644 --- a/mp/src/public/steam/isteamcontroller.h +++ b/mp/src/public/steam/isteamcontroller.h @@ -11,7 +11,6 @@ #endif #include "isteamclient.h" -#include "steamcontrollerpublic.h" // callbacks #if defined( VALVE_CALLBACK_PACK_SMALL ) @@ -26,13 +25,61 @@ #pragma pack( pop ) +#define STEAM_RIGHT_TRIGGER_MASK 0x0000001 +#define STEAM_LEFT_TRIGGER_MASK 0x0000002 +#define STEAM_RIGHT_BUMPER_MASK 0x0000004 +#define STEAM_LEFT_BUMPER_MASK 0x0000008 +#define STEAM_BUTTON_0_MASK 0x0000010 +#define STEAM_BUTTON_1_MASK 0x0000020 +#define STEAM_BUTTON_2_MASK 0x0000040 +#define STEAM_BUTTON_3_MASK 0x0000080 +#define STEAM_TOUCH_0_MASK 0x0000100 +#define STEAM_TOUCH_1_MASK 0x0000200 +#define STEAM_TOUCH_2_MASK 0x0000400 +#define STEAM_TOUCH_3_MASK 0x0000800 +#define STEAM_BUTTON_MENU_MASK 0x0001000 +#define STEAM_BUTTON_STEAM_MASK 0x0002000 +#define STEAM_BUTTON_ESCAPE_MASK 0x0004000 +#define STEAM_BUTTON_BACK_LEFT_MASK 0x0008000 +#define STEAM_BUTTON_BACK_RIGHT_MASK 0x0010000 +#define STEAM_BUTTON_LEFTPAD_CLICKED_MASK 0x0020000 +#define STEAM_BUTTON_RIGHTPAD_CLICKED_MASK 0x0040000 +#define STEAM_LEFTPAD_FINGERDOWN_MASK 0x0080000 +#define STEAM_RIGHTPAD_FINGERDOWN_MASK 0x0100000 +#define STEAM_JOYSTICK_BUTTON_MASK 0x0400000 + + +#pragma pack( push, 1 ) + +struct SteamControllerState001_t +{ + // If packet num matches that on your prior call, then the controller state hasn't been changed since + // your last call and there is no need to process it + uint32 unPacketNum; + + // bit flags for each of the buttons + uint64 ulButtons; + + // Left pad coordinates + short sLeftPadX; + short sLeftPadY; + + // Right pad coordinates + short sRightPadX; + short sRightPadY; + +}; + +#pragma pack( pop ) + +#define SteamControllerState_t SteamControllerState001_t + enum ESteamControllerPad { k_ESteamControllerPad_Left, k_ESteamControllerPad_Right }; - //----------------------------------------------------------------------------- // Purpose: Native Steam controller support API //----------------------------------------------------------------------------- diff --git a/mp/src/public/steam/isteamfriends.h b/mp/src/public/steam/isteamfriends.h index 16a2aa5a..60526edd 100644 --- a/mp/src/public/steam/isteamfriends.h +++ b/mp/src/public/steam/isteamfriends.h @@ -20,11 +20,11 @@ enum EFriendRelationship { k_EFriendRelationshipNone = 0, - k_EFriendRelationshipBlocked = 1, + k_EFriendRelationshipBlocked = 1, // this doesn't get stored; the user has just done an Ignore on an friendship invite k_EFriendRelationshipRequestRecipient = 2, k_EFriendRelationshipFriend = 3, k_EFriendRelationshipRequestInitiator = 4, - k_EFriendRelationshipIgnored = 5, + k_EFriendRelationshipIgnored = 5, // this is stored; the user has explicit blocked this other user from comments/chat/etc k_EFriendRelationshipIgnoredFriend = 6, k_EFriendRelationshipSuggested = 7, @@ -38,6 +38,12 @@ const int k_cchMaxFriendsGroupName = 64; // maximum number of groups a single user is allowed const int k_cFriendsGroupLimit = 100; +// friends group identifier type +typedef int16 FriendsGroupID_t; + +// invalid friends group identifier constant +const FriendsGroupID_t k_FriendsGroupID_Invalid = -1; + const int k_cEnumerateFollowersMax = 50; @@ -199,13 +205,27 @@ public: virtual const char *GetFriendPersonaName( CSteamID steamIDFriend ) = 0; // returns true if the friend is actually in a game, and fills in pFriendGameInfo with an extra details - virtual bool GetFriendGamePlayed( CSteamID steamIDFriend, FriendGameInfo_t *pFriendGameInfo ) = 0; + virtual bool GetFriendGamePlayed( CSteamID steamIDFriend, OUT_STRUCT() FriendGameInfo_t *pFriendGameInfo ) = 0; // accesses old friends names - returns an empty string when their are no more items in the history virtual const char *GetFriendPersonaNameHistory( CSteamID steamIDFriend, int iPersonaName ) = 0; + // friends steam level + virtual int GetFriendSteamLevel( CSteamID steamIDFriend ) = 0; // Returns nickname the current user has set for the specified player. Returns NULL if the no nickname has been set for that player. virtual const char *GetPlayerNickname( CSteamID steamIDPlayer ) = 0; + // friend grouping (tag) apis + // returns the number of friends groups + virtual int GetFriendsGroupCount() = 0; + // returns the friends group ID for the given index (invalid indices return k_FriendsGroupID_Invalid) + virtual FriendsGroupID_t GetFriendsGroupIDByIndex( int iFG ) = 0; + // returns the name for the given friends group (NULL in the case of invalid friends group IDs) + virtual const char *GetFriendsGroupName( FriendsGroupID_t friendsGroupID ) = 0; + // returns the number of members in a given friends group + virtual int GetFriendsGroupMembersCount( FriendsGroupID_t friendsGroupID ) = 0; + // gets up to nMembersCount members of the given friends group, if fewer exist than requested those positions' SteamIDs will be invalid + virtual void GetFriendsGroupMembersList( FriendsGroupID_t friendsGroupID, OUT_ARRAY_CALL(nMembersCount, GetFriendsGroupMembersCount, friendsGroupID ) CSteamID *pOutSteamIDMembers, int nMembersCount ) = 0; + // returns true if the specified user meets any of the criteria specified in iFriendFlags // iFriendFlags can be the union (binary or, |) of one or more k_EFriendFlags values virtual bool HasFriend( CSteamID steamIDFriend, int iFriendFlags ) = 0; @@ -218,7 +238,7 @@ public: // returns the most recent information we have about what's happening in a clan virtual bool GetClanActivityCounts( CSteamID steamIDClan, int *pnOnline, int *pnInGame, int *pnChatting ) = 0; // for clans a user is a member of, they will have reasonably up-to-date information, but for others you'll have to download the info to have the latest - virtual SteamAPICall_t DownloadClanActivityCounts( CSteamID *psteamIDClans, int cClansToRequest ) = 0; + virtual SteamAPICall_t DownloadClanActivityCounts( ARRAY_COUNT(cClansToRequest) CSteamID *psteamIDClans, int cClansToRequest ) = 0; // iterators for getting users in a chat room, lobby, game server or clan // note that large clans that cannot be iterated by the local user @@ -343,7 +363,7 @@ public: virtual int GetClanChatMemberCount( CSteamID steamIDClan ) = 0; virtual CSteamID GetChatMemberByIndex( CSteamID steamIDClan, int iUser ) = 0; virtual bool SendClanChatMessage( CSteamID steamIDClanChat, const char *pchText ) = 0; - virtual int GetClanChatMessage( CSteamID steamIDClanChat, int iMessage, void *prgchText, int cchTextMax, EChatEntryType *peChatEntryType, CSteamID *psteamidChatter ) = 0; + virtual int GetClanChatMessage( CSteamID steamIDClanChat, int iMessage, void *prgchText, int cchTextMax, EChatEntryType *peChatEntryType, OUT_STRUCT() CSteamID *psteamidChatter ) = 0; virtual bool IsClanChatAdmin( CSteamID steamIDClanChat, CSteamID steamIDUser ) = 0; // interact with the Steam (game overlay / desktop) @@ -363,7 +383,7 @@ public: virtual SteamAPICall_t EnumerateFollowingList( uint32 unStartIndex ) = 0; }; -#define STEAMFRIENDS_INTERFACE_VERSION "SteamFriends014" +#define STEAMFRIENDS_INTERFACE_VERSION "SteamFriends015" // callbacks #if defined( VALVE_CALLBACK_PACK_SMALL ) diff --git a/mp/src/public/steam/isteamhtmlsurface.h b/mp/src/public/steam/isteamhtmlsurface.h index 80216fc9..c257164a 100644 --- a/mp/src/public/steam/isteamhtmlsurface.h +++ b/mp/src/public/steam/isteamhtmlsurface.h @@ -13,7 +13,7 @@ #include "isteamclient.h" typedef uint32 HHTMLBrowser; -const uint32 INVALID_HTTMLBROWSER = 0; +const uint32 INVALID_HTMLBROWSER = 0; //----------------------------------------------------------------------------- // Purpose: Functions for displaying HTML pages and interacting with them @@ -123,10 +123,10 @@ public: enum EHTMLKeyModifiers { - eHTMLKeyModifier_None = 0, - eHTMLKeyModifier_AltDown = 1 << 0, - eHTMLKeyModifier_CrtlDown = 1 << 1, - eHTMLKeyModifier_ShiftDown = 1 << 2, + k_eHTMLKeyModifier_None = 0, + k_eHTMLKeyModifier_AltDown = 1 << 0, + k_eHTMLKeyModifier_CtrlDown = 1 << 1, + k_eHTMLKeyModifier_ShiftDown = 1 << 2, }; // keyboard interactions, native keycode is the virtual key code value from your OS @@ -160,9 +160,15 @@ public: // set a webcookie for the hostname in question virtual void SetCookie( const char *pchHostname, const char *pchKey, const char *pchValue, const char *pchPath = "/", RTime32 nExpires = 0, bool bSecure = false, bool bHTTPOnly = false ) = 0; - // Zoom the current page by flZoom ( from 0.0 to 4.0, so to zoom to 120% use 1.2 ), zooming around point X,Y in the page (use 0,0 if you don't care) + // Zoom the current page by flZoom ( from 0.0 to 2.0, so to zoom to 120% use 1.2 ), zooming around point X,Y in the page (use 0,0 if you don't care) virtual void SetPageScaleFactor( HHTMLBrowser unBrowserHandle, float flZoom, int nPointX, int nPointY ) = 0; + // Enable/disable low-resource background mode, where javascript and repaint timers are throttled, resources are + // more aggressively purged from memory, and audio/video elements are paused. When background mode is enabled, + // all HTML5 video and audio objects will execute ".pause()" and gain the property "._steam_background_paused = 1". + // When background mode is disabled, any video or audio objects with that property will resume with ".play()". + virtual void SetBackgroundMode( HHTMLBrowser unBrowserHandle, bool bBackgroundMode ) = 0; + // CALLBACKS // // These set of functions are used as responses to callback requests @@ -182,7 +188,7 @@ public: virtual void FileLoadDialogResponse( HHTMLBrowser unBrowserHandle, const char **pchSelectedFiles ) = 0; }; -#define STEAMHTMLSURFACE_INTERFACE_VERSION "STEAMHTMLSURFACE_INTERFACE_VERSION_002" +#define STEAMHTMLSURFACE_INTERFACE_VERSION "STEAMHTMLSURFACE_INTERFACE_VERSION_003" // callbacks #if defined( VALVE_CALLBACK_PACK_SMALL ) @@ -334,8 +340,8 @@ END_DEFINE_CALLBACK_6() //----------------------------------------------------------------------------- DEFINE_CALLBACK( HTML_LinkAtPosition_t, k_iSteamHTMLSurfaceCallbacks + 13 ) CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface -CALLBACK_MEMBER( 1, uint32, x ) // -CALLBACK_MEMBER( 2, uint32, y ) // +CALLBACK_MEMBER( 1, uint32, x ) // NOTE - Not currently set +CALLBACK_MEMBER( 2, uint32, y ) // NOTE - Not currently set CALLBACK_MEMBER( 3, const char *, pchURL ) // CALLBACK_MEMBER( 4, bool, bInput ) // CALLBACK_MEMBER( 5, bool, bLiveLink ) // @@ -364,8 +370,8 @@ END_DEFINE_CALLBACK_2() //----------------------------------------------------------------------------- -// Purpose: show a Javascript confirmation dialog, call JSDialogResponse -// when the user dismisses this dialog (or right away to ignore it) +// Purpose: when received show a file open dialog +// then call FileLoadDialogResponse with the file(s) the user selected. //----------------------------------------------------------------------------- DEFINE_CALLBACK( HTML_FileOpenDialog_t, k_iSteamHTMLSurfaceCallbacks + 16 ) CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface @@ -374,56 +380,18 @@ CALLBACK_MEMBER( 2, const char *, pchInitialFile ) // END_DEFINE_CALLBACK_3() -//----------------------------------------------------------------------------- -// Purpose: a popup item (i.e combo box) on the page needs rendering -//----------------------------------------------------------------------------- -DEFINE_CALLBACK( HTML_ComboNeedsPaint_t, k_iSteamHTMLSurfaceCallbacks + 17 ) -CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface -CALLBACK_MEMBER( 1, const char *, pBGRA ) // a pointer to the B8G8R8A8 data for this surface, valid until SteamAPI_RunCallbacks is next called -CALLBACK_MEMBER( 2, uint32, unWide ) // the total width of the pBGRA texture -CALLBACK_MEMBER( 3, uint32, unTall ) // the total height of the pBGRA texture -END_DEFINE_CALLBACK_4() - - -//----------------------------------------------------------------------------- -// Purpose: a popup (i.e combo box) wants to display -//----------------------------------------------------------------------------- -DEFINE_CALLBACK( HTML_ShowPopup_t, k_iSteamHTMLSurfaceCallbacks + 18 ) -CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface -END_DEFINE_CALLBACK_1() - - -//----------------------------------------------------------------------------- -// Purpose: a popup (i.e combo box) wants to hide -//----------------------------------------------------------------------------- -DEFINE_CALLBACK( HTML_HidePopup_t, k_iSteamHTMLSurfaceCallbacks + 19 ) -CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface -END_DEFINE_CALLBACK_1() - - -//----------------------------------------------------------------------------- -// Purpose: a popup (i.e combo box) wants to hide -//----------------------------------------------------------------------------- -DEFINE_CALLBACK( HTML_SizePopup_t, k_iSteamHTMLSurfaceCallbacks + 20 ) -CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface -CALLBACK_MEMBER( 1, uint32, unX ) // the x pos into the page to display the popup -CALLBACK_MEMBER( 2, uint32, unY ) // the y pos into the page to display the popup -CALLBACK_MEMBER( 3, uint32, unWide ) // the total width of the pBGRA texture -CALLBACK_MEMBER( 4, uint32, unTall ) // the total height of the pBGRA texture -END_DEFINE_CALLBACK_5() - - //----------------------------------------------------------------------------- // Purpose: a new html window has been created //----------------------------------------------------------------------------- DEFINE_CALLBACK( HTML_NewWindow_t, k_iSteamHTMLSurfaceCallbacks + 21 ) -CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the surface +CALLBACK_MEMBER( 0, HHTMLBrowser, unBrowserHandle ) // the handle of the current surface CALLBACK_MEMBER( 1, const char *, pchURL ) // the page to load CALLBACK_MEMBER( 2, uint32, unX ) // the x pos into the page to display the popup CALLBACK_MEMBER( 3, uint32, unY ) // the y pos into the page to display the popup CALLBACK_MEMBER( 4, uint32, unWide ) // the total width of the pBGRA texture CALLBACK_MEMBER( 5, uint32, unTall ) // the total height of the pBGRA texture -END_DEFINE_CALLBACK_6() +CALLBACK_MEMBER( 6, HHTMLBrowser, unNewWindow_BrowserHandle ) // the handle of the new window surface +END_DEFINE_CALLBACK_7() //----------------------------------------------------------------------------- diff --git a/mp/src/public/steam/isteamhttp.h b/mp/src/public/steam/isteamhttp.h index d68335d0..8fab537d 100644 --- a/mp/src/public/steam/isteamhttp.h +++ b/mp/src/public/steam/isteamhttp.h @@ -1,4 +1,4 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// +//====== Copyright © 1996-2009, Valve Corporation, All rights reserved. ======= // // Purpose: interface to http client // @@ -17,6 +17,9 @@ typedef uint32 HTTPRequestHandle; #define INVALID_HTTPREQUEST_HANDLE 0 +typedef uint32 HTTPCookieContainerHandle; +#define INVALID_HTTPCOOKIE_HANDLE 0 + //----------------------------------------------------------------------------- // Purpose: interface to http client //----------------------------------------------------------------------------- @@ -25,8 +28,8 @@ class ISteamHTTP public: // Initializes a new HTTP request, returning a handle to use in further operations on it. Requires - // the method (GET or POST) and the absolute URL for the request. Only http requests (ie, not https) are - // currently supported, so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/ + // the method (GET or POST) and the absolute URL for the request. Both http and https are supported, + // so this string must start with http:// or https:// and should look like http://store.steampowered.com/app/250/ // or such. virtual HTTPRequestHandle CreateHTTPRequest( EHTTPMethod eHTTPRequestMethod, const char *pchAbsoluteURL ) = 0; @@ -105,6 +108,35 @@ public: // have already been set for the request. Setting this raw body makes it the only contents for the post, the pchContentType // parameter will set the content-type header for the request so the server may know how to interpret the body. virtual bool SetHTTPRequestRawPostBody( HTTPRequestHandle hRequest, const char *pchContentType, uint8 *pubBody, uint32 unBodyLen ) = 0; + + // Creates a cookie container handle which you must later free with ReleaseCookieContainer(). If bAllowResponsesToModify=true + // than any response to your requests using this cookie container may add new cookies which may be transmitted with + // future requests. If bAllowResponsesToModify=false than only cookies you explicitly set will be sent. This API is just for + // during process lifetime, after steam restarts no cookies are persisted and you have no way to access the cookie container across + // repeat executions of your process. + virtual HTTPCookieContainerHandle CreateCookieContainer( bool bAllowResponsesToModify ) = 0; + + // Release a cookie container you are finished using, freeing it's memory + virtual bool ReleaseCookieContainer( HTTPCookieContainerHandle hCookieContainer ) = 0; + + // Adds a cookie to the specified cookie container that will be used with future requests. + virtual bool SetCookie( HTTPCookieContainerHandle hCookieContainer, const char *pchHost, const char *pchUrl, const char *pchCookie ) = 0; + + // Set the cookie container to use for a HTTP request + virtual bool SetHTTPRequestCookieContainer( HTTPRequestHandle hRequest, HTTPCookieContainerHandle hCookieContainer ) = 0; + + // Set the extra user agent info for a request, this doesn't clobber the normal user agent, it just adds the extra info on the end + virtual bool SetHTTPRequestUserAgentInfo( HTTPRequestHandle hRequest, const char *pchUserAgentInfo ) = 0; + + // Set that https request should require verified SSL certificate via machines certificate trust store + virtual bool SetHTTPRequestRequiresVerifiedCertificate( HTTPRequestHandle hRequest, bool bRequireVerifiedCertificate ) = 0; + + // Set an absolute timeout on the HTTP request, this is just a total time timeout different than the network activity timeout + // which can bump everytime we get more data + virtual bool SetHTTPRequestAbsoluteTimeoutMS( HTTPRequestHandle hRequest, uint32 unMilliseconds ) = 0; + + // Check if the reason the request failed was because we timed it out (rather than some harder failure) + virtual bool GetHTTPRequestWasTimedOut( HTTPRequestHandle hRequest, bool *pbWasTimedOut ) = 0; }; #define STEAMHTTP_INTERFACE_VERSION "STEAMHTTP_INTERFACE_VERSION002" @@ -136,6 +168,8 @@ struct HTTPRequestCompleted_t // Will be the HTTP status code value returned by the server, k_EHTTPStatusCode200OK is the normal // OK response, if you get something else you probably need to treat it as a failure. EHTTPStatusCode m_eStatusCode; + + uint32 m_unBodySize; // Same as GetHTTPResponseBodySize() }; diff --git a/mp/src/public/steam/isteammatchmaking.h b/mp/src/public/steam/isteammatchmaking.h index d6380076..e3be340d 100644 --- a/mp/src/public/steam/isteammatchmaking.h +++ b/mp/src/public/steam/isteammatchmaking.h @@ -201,7 +201,7 @@ public: // *pSteamIDUser is filled in with the CSteamID of the member // *pvData is filled in with the message itself // return value is the number of bytes written into the buffer - virtual int GetLobbyChatEntry( CSteamID steamIDLobby, int iChatID, CSteamID *pSteamIDUser, void *pvData, int cubData, EChatEntryType *peChatEntryType ) = 0; + virtual int GetLobbyChatEntry( CSteamID steamIDLobby, int iChatID, OUT_STRUCT() CSteamID *pSteamIDUser, void *pvData, int cubData, EChatEntryType *peChatEntryType ) = 0; // Refreshes metadata for a lobby you're not necessarily in right now // you never do this for lobbies you're a member of, only if your @@ -217,7 +217,7 @@ public: // either the IP/Port or the steamID of the game server has to be valid, depending on how you want the clients to be able to connect virtual void SetLobbyGameServer( CSteamID steamIDLobby, uint32 unGameServerIP, uint16 unGameServerPort, CSteamID steamIDGameServer ) = 0; // returns the details of a game server set in a lobby - returns false if there is no game server set, or that lobby doesn't exist - virtual bool GetLobbyGameServer( CSteamID steamIDLobby, uint32 *punGameServerIP, uint16 *punGameServerPort, CSteamID *psteamIDGameServer ) = 0; + virtual bool GetLobbyGameServer( CSteamID steamIDLobby, uint32 *punGameServerIP, uint16 *punGameServerPort, OUT_STRUCT() CSteamID *psteamIDGameServer ) = 0; // set the limit on the # of users who can join the lobby virtual bool SetLobbyMemberLimit( CSteamID steamIDLobby, int cMaxMembers ) = 0; @@ -387,12 +387,12 @@ public: // Request a new list of servers of a particular type. These calls each correspond to one of the EMatchMakingType values. // Each call allocates a new asynchronous request object. // Request object must be released by calling ReleaseRequest( hServerListRequest ) - virtual HServerListRequest RequestInternetServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; + virtual HServerListRequest RequestInternetServerList( AppId_t iApp, ARRAY_COUNT(nFilters) MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; virtual HServerListRequest RequestLANServerList( AppId_t iApp, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual HServerListRequest RequestFriendsServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual HServerListRequest RequestFavoritesServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual HServerListRequest RequestHistoryServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; - virtual HServerListRequest RequestSpectatorServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; + virtual HServerListRequest RequestFriendsServerList( AppId_t iApp, ARRAY_COUNT(nFilters) MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; + virtual HServerListRequest RequestFavoritesServerList( AppId_t iApp, ARRAY_COUNT(nFilters) MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; + virtual HServerListRequest RequestHistoryServerList( AppId_t iApp, ARRAY_COUNT(nFilters) MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; + virtual HServerListRequest RequestSpectatorServerList( AppId_t iApp, ARRAY_COUNT(nFilters) MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0; // Releases the asynchronous request object and cancels any pending query on it if there's a pending query in progress. // RefreshComplete callback is not posted when request is released. diff --git a/mp/src/public/steam/isteammusicremote.h b/mp/src/public/steam/isteammusicremote.h index fe083da5..ea29a7de 100644 --- a/mp/src/public/steam/isteammusicremote.h +++ b/mp/src/public/steam/isteammusicremote.h @@ -118,6 +118,9 @@ DEFINE_CALLBACK( MusicPlayerSelectsPlaylistEntry_t, k_iSteamMusicCallbacks + 13 CALLBACK_MEMBER(0, int, nID ) END_DEFINE_CALLBACK_1() +DEFINE_CALLBACK( MusicPlayerWantsPlayingRepeatStatus_t, k_iSteamMusicRemoteCallbacks + 14 ) + CALLBACK_MEMBER(0, int, m_nPlayingRepeatStatus ) +END_DEFINE_CALLBACK_1() #pragma pack( pop ) diff --git a/mp/src/public/steam/isteamremotestorage.h b/mp/src/public/steam/isteamremotestorage.h index c5a005f3..6853cd6f 100644 --- a/mp/src/public/steam/isteamremotestorage.h +++ b/mp/src/public/steam/isteamremotestorage.h @@ -88,24 +88,25 @@ enum EWorkshopFileType { k_EWorkshopFileTypeFirst = 0, - k_EWorkshopFileTypeCommunity = 0, - k_EWorkshopFileTypeMicrotransaction = 1, - k_EWorkshopFileTypeCollection = 2, - k_EWorkshopFileTypeArt = 3, - k_EWorkshopFileTypeVideo = 4, - k_EWorkshopFileTypeScreenshot = 5, - k_EWorkshopFileTypeGame = 6, - k_EWorkshopFileTypeSoftware = 7, - k_EWorkshopFileTypeConcept = 8, - k_EWorkshopFileTypeWebGuide = 9, - k_EWorkshopFileTypeIntegratedGuide = 10, - k_EWorkshopFileTypeMerch = 11, - k_EWorkshopFileTypeControllerBinding = 12, - k_EWorkshopFileTypeSteamworksAccessInvite = 13, - k_EWorkshopFileTypeSteamVideo = 14, + k_EWorkshopFileTypeCommunity = 0, // normal Workshop item that can be subscribed to + k_EWorkshopFileTypeMicrotransaction = 1, // Workshop item that is meant to be voted on for the purpose of selling in-game + k_EWorkshopFileTypeCollection = 2, // a collection of Workshop or Greenlight items + k_EWorkshopFileTypeArt = 3, // artwork + k_EWorkshopFileTypeVideo = 4, // external video + k_EWorkshopFileTypeScreenshot = 5, // screenshot + k_EWorkshopFileTypeGame = 6, // Greenlight game entry + k_EWorkshopFileTypeSoftware = 7, // Greenlight software entry + k_EWorkshopFileTypeConcept = 8, // Greenlight concept + k_EWorkshopFileTypeWebGuide = 9, // Steam web guide + k_EWorkshopFileTypeIntegratedGuide = 10, // application integrated guide + k_EWorkshopFileTypeMerch = 11, // Workshop merchandise meant to be voted on for the purpose of being sold + k_EWorkshopFileTypeControllerBinding = 12, // Steam Controller bindings + k_EWorkshopFileTypeSteamworksAccessInvite = 13, // internal + k_EWorkshopFileTypeSteamVideo = 14, // Steam video + k_EWorkshopFileTypeGameManagedItem = 15, // managed completely by the game, not the user, and not shown on the web // Update k_EWorkshopFileTypeMax if you add values. - k_EWorkshopFileTypeMax = 15 + k_EWorkshopFileTypeMax = 16 }; @@ -114,6 +115,7 @@ enum EWorkshopVote k_EWorkshopVoteUnvoted = 0, k_EWorkshopVoteFor = 1, k_EWorkshopVoteAgainst = 2, + k_EWorkshopVoteLater = 3, }; enum EWorkshopFileAction @@ -214,7 +216,7 @@ class ISteamRemoteStorage virtual bool GetUGCDownloadProgress( UGCHandle_t hContent, int32 *pnBytesDownloaded, int32 *pnBytesExpected ) = 0; // Gets metadata for a file after it has been downloaded. This is the same metadata given in the RemoteStorageDownloadUGCResult_t call result - virtual bool GetUGCDetails( UGCHandle_t hContent, AppId_t *pnAppID, char **ppchName, int32 *pnFileSizeInBytes, CSteamID *pSteamIDOwner ) = 0; + virtual bool GetUGCDetails( UGCHandle_t hContent, AppId_t *pnAppID, char **ppchName, int32 *pnFileSizeInBytes, OUT_STRUCT() CSteamID *pSteamIDOwner ) = 0; // After download, gets the content of the file. // Small files can be read all at once by calling this function with an offset of 0 and cubDataToRead equal to the size of the file. diff --git a/mp/src/public/steam/isteamugc.h b/mp/src/public/steam/isteamugc.h index 4bab58d6..6ac2a555 100644 --- a/mp/src/public/steam/isteamugc.h +++ b/mp/src/public/steam/isteamugc.h @@ -45,6 +45,7 @@ enum EUGCMatchingUGCType k_EUGCMatchingUGCType_IntegratedGuides = 9, k_EUGCMatchingUGCType_UsableInGame = 10, // ready-to-use items and integrated guides k_EUGCMatchingUGCType_ControllerBindings = 11, + k_EUGCMatchingUGCType_GameManagedItems = 12, // game managed items (not managed by users) }; // Different lists of published UGC for a user. @@ -89,6 +90,7 @@ enum EUGCQuery k_EUGCQuery_RankedByTotalVotesAsc = 9, k_EUGCQuery_RankedByVotesUp = 10, k_EUGCQuery_RankedByTextSearch = 11, + k_EUGCQuery_RankedByTotalUniqueSubscriptions = 12, }; enum EItemUpdateStatus @@ -101,8 +103,31 @@ enum EItemUpdateStatus k_EItemUpdateStatusCommittingChanges = 5 // The item update is committing all changes }; +enum EItemState +{ + k_EItemStateNone = 0, // item not tracked on client + k_EItemStateSubscribed = 1, // current user is subscribed to this item. Not just cached. + k_EItemStateLegacyItem = 2, // item was created with ISteamRemoteStorage + k_EItemStateInstalled = 4, // item is installed and usable (but maybe out of date) + k_EItemStateNeedsUpdate = 8, // items needs an update. Either because it's not installed yet or creator updated content + k_EItemStateDownloading = 16, // item update is currently downloading + k_EItemStateDownloadPending = 32, // DownloadItem() was called for this item, content isn't available until DownloadItemResult_t is fired +}; + +enum EItemStatistic +{ + k_EItemStatistic_NumSubscriptions = 0, + k_EItemStatistic_NumFavorites = 1, + k_EItemStatistic_NumFollowers = 2, + k_EItemStatistic_NumUniqueSubscriptions = 3, + k_EItemStatistic_NumUniqueFavorites = 4, + k_EItemStatistic_NumUniqueFollowers = 5, + k_EItemStatistic_NumUniqueWebsiteViews = 6, + k_EItemStatistic_ReportScore = 7, +}; const uint32 kNumUGCResultsPerPage = 50; +const uint32 k_cchDeveloperMetadataMax = 5000; // Details for a single published file/UGC struct SteamUGCDetails_t @@ -134,7 +159,8 @@ struct SteamUGCDetails_t uint32 m_unVotesUp; // number of votes up uint32 m_unVotesDown; // number of votes down float m_flScore; // calculated score - uint32 m_unNumChildren; // if m_eFileType == k_EWorkshopFileTypeCollection, then this number will be the number of children contained within the collection + // collection details + uint32 m_unNumChildren; }; //----------------------------------------------------------------------------- @@ -150,11 +176,22 @@ public: // Query for all matching UGC. Creator app id or consumer app id must be valid and be set to the current running app. unPage should start at 1. virtual UGCQueryHandle_t CreateQueryAllUGCRequest( EUGCQuery eQueryType, EUGCMatchingUGCType eMatchingeMatchingUGCTypeFileType, AppId_t nCreatorAppID, AppId_t nConsumerAppID, uint32 unPage ) = 0; + // Query for the details of the given published file ids (the RequestUGCDetails call is deprecated and replaced with this) + virtual UGCQueryHandle_t CreateQueryUGCDetailsRequest( PublishedFileId_t *pvecPublishedFileID, uint32 unNumPublishedFileIDs ) = 0; + // Send the query to Steam virtual SteamAPICall_t SendQueryUGCRequest( UGCQueryHandle_t handle ) = 0; // Retrieve an individual result after receiving the callback for querying UGC virtual bool GetQueryUGCResult( UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t *pDetails ) = 0; + virtual bool GetQueryUGCPreviewURL( UGCQueryHandle_t handle, uint32 index, char *pchURL, uint32 cchURLSize ) = 0; + virtual bool GetQueryUGCMetadata( UGCQueryHandle_t handle, uint32 index, char *pchMetadata, uint32 cchMetadatasize ) = 0; + virtual bool GetQueryUGCChildren( UGCQueryHandle_t handle, uint32 index, PublishedFileId_t* pvecPublishedFileID, uint32 cMaxEntries ) = 0; + virtual bool GetQueryUGCStatistic( UGCQueryHandle_t handle, uint32 index, EItemStatistic eStatType, uint32 *pStatValue ) = 0; + virtual uint32 GetQueryUGCNumAdditionalPreviews( UGCQueryHandle_t handle, uint32 index ) = 0; + virtual bool GetQueryUGCAdditionalPreview( UGCQueryHandle_t handle, uint32 index, uint32 previewIndex, char *pchURLOrVideoID, uint32 cchURLSize, bool *pbIsImage ) = 0; + virtual uint32 GetQueryUGCNumKeyValueTags( UGCQueryHandle_t handle, uint32 index ) = 0; + virtual bool GetQueryUGCKeyValueTag( UGCQueryHandle_t handle, uint32 index, uint32 keyValueTagIndex, char *pchKey, uint32 cchKeySize, char *pchValue, uint32 cchValueSize ) = 0; // Release the request to free up memory, after retrieving results virtual bool ReleaseQueryUGCRequest( UGCQueryHandle_t handle ) = 0; @@ -162,8 +199,13 @@ public: // Options to set for querying UGC virtual bool AddRequiredTag( UGCQueryHandle_t handle, const char *pTagName ) = 0; virtual bool AddExcludedTag( UGCQueryHandle_t handle, const char *pTagName ) = 0; + virtual bool SetReturnKeyValueTags( UGCQueryHandle_t handle, bool bReturnKeyValueTags ) = 0; virtual bool SetReturnLongDescription( UGCQueryHandle_t handle, bool bReturnLongDescription ) = 0; + virtual bool SetReturnMetadata( UGCQueryHandle_t handle, bool bReturnMetadata ) = 0; + virtual bool SetReturnChildren( UGCQueryHandle_t handle, bool bReturnChildren ) = 0; + virtual bool SetReturnAdditionalPreviews( UGCQueryHandle_t handle, bool bReturnAdditionalPreviews ) = 0; virtual bool SetReturnTotalOnly( UGCQueryHandle_t handle, bool bReturnTotalOnly ) = 0; + virtual bool SetLanguage( UGCQueryHandle_t handle, const char *pchLanguage ) = 0; virtual bool SetAllowCachedResponse( UGCQueryHandle_t handle, uint32 unMaxAgeSeconds ) = 0; // Options only for querying user UGC @@ -173,8 +215,9 @@ public: virtual bool SetMatchAnyTag( UGCQueryHandle_t handle, bool bMatchAnyTag ) = 0; virtual bool SetSearchText( UGCQueryHandle_t handle, const char *pSearchText ) = 0; virtual bool SetRankedByTrendDays( UGCQueryHandle_t handle, uint32 unDays ) = 0; + virtual bool AddRequiredKeyValueTag( UGCQueryHandle_t handle, const char *pKey, const char *pValue ) = 0; - // Request full details for one piece of UGC + // DEPRECATED - Use CreateQueryUGCDetailsRequest call above instead! virtual SteamAPICall_t RequestUGCDetails( PublishedFileId_t nPublishedFileID, uint32 unMaxAgeSeconds ) = 0; // Steam Workshop Creator API @@ -184,27 +227,49 @@ public: virtual bool SetItemTitle( UGCUpdateHandle_t handle, const char *pchTitle ) = 0; // change the title of an UGC item virtual bool SetItemDescription( UGCUpdateHandle_t handle, const char *pchDescription ) = 0; // change the description of an UGC item + virtual bool SetItemUpdateLanguage( UGCUpdateHandle_t handle, const char *pchLanguage ) = 0; // specify the language of the title or description that will be set + virtual bool SetItemMetadata( UGCUpdateHandle_t handle, const char *pchMetaData ) = 0; // change the metadata of an UGC item (max = k_cchDeveloperMetadataMax) virtual bool SetItemVisibility( UGCUpdateHandle_t handle, ERemoteStoragePublishedFileVisibility eVisibility ) = 0; // change the visibility of an UGC item virtual bool SetItemTags( UGCUpdateHandle_t updateHandle, const SteamParamStringArray_t *pTags ) = 0; // change the tags of an UGC item virtual bool SetItemContent( UGCUpdateHandle_t handle, const char *pszContentFolder ) = 0; // update item content from this local folder - virtual bool SetItemPreview( UGCUpdateHandle_t handle, const char *pszPreviewFile ) = 0; // change preview image file for this item. pszPreviewFile points to local image file + virtual bool SetItemPreview( UGCUpdateHandle_t handle, const char *pszPreviewFile ) = 0; // change preview image file for this item. pszPreviewFile points to local image file, which must be under 1MB in size + virtual bool RemoveItemKeyValueTags( UGCUpdateHandle_t handle, const char *pchKey ) = 0; // remove any existing key-value tags with the specified key + virtual bool AddItemKeyValueTag( UGCUpdateHandle_t handle, const char *pchKey, const char *pchValue ) = 0; // add new key-value tags for the item. Note that there can be multiple values for a tag. virtual SteamAPICall_t SubmitItemUpdate( UGCUpdateHandle_t handle, const char *pchChangeNote ) = 0; // commit update process started with StartItemUpdate() virtual EItemUpdateStatus GetItemUpdateProgress( UGCUpdateHandle_t handle, uint64 *punBytesProcessed, uint64* punBytesTotal ) = 0; // Steam Workshop Consumer API - virtual SteamAPICall_t SubscribeItem( PublishedFileId_t nPublishedFileID ) = 0; // subscript to this item, will be installed ASAP + virtual SteamAPICall_t SetUserItemVote( PublishedFileId_t nPublishedFileID, bool bVoteUp ) = 0; + virtual SteamAPICall_t GetUserItemVote( PublishedFileId_t nPublishedFileID ) = 0; + virtual SteamAPICall_t AddItemToFavorites( AppId_t nAppId, PublishedFileId_t nPublishedFileID ) = 0; + virtual SteamAPICall_t RemoveItemFromFavorites( AppId_t nAppId, PublishedFileId_t nPublishedFileID ) = 0; + virtual SteamAPICall_t SubscribeItem( PublishedFileId_t nPublishedFileID ) = 0; // subscribe to this item, will be installed ASAP virtual SteamAPICall_t UnsubscribeItem( PublishedFileId_t nPublishedFileID ) = 0; // unsubscribe from this item, will be uninstalled after game quits virtual uint32 GetNumSubscribedItems() = 0; // number of subscribed items virtual uint32 GetSubscribedItems( PublishedFileId_t* pvecPublishedFileID, uint32 cMaxEntries ) = 0; // all subscribed item PublishFileIDs - // Get info about the item on disk. If you are supporting items published through the legacy RemoteStorage APIs then *pbLegacyItem will be set to true - // and pchFolder will contain the full path to the file rather than the containing folder. - virtual bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDisk, char *pchFolder, uint32 cchFolderSize, bool *pbLegacyItem ) = 0; // returns true if item is installed - virtual bool GetItemUpdateInfo( PublishedFileId_t nPublishedFileID, bool *pbNeedsUpdate, bool *pbIsDownloading, uint64 *punBytesDownloaded, uint64 *punBytesTotal ) = 0; + // get EItemState flags about item on this client + virtual uint32 GetItemState( PublishedFileId_t nPublishedFileID ) = 0; + + // get info about currently installed content on disc for items that have k_EItemStateInstalled set + // if k_EItemStateLegacyItem is set, pchFolder contains the path to the legacy file itself (not a folder) + virtual bool GetItemInstallInfo( PublishedFileId_t nPublishedFileID, uint64 *punSizeOnDisk, char *pchFolder, uint32 cchFolderSize, uint32 *punTimeStamp ) = 0; + + // get info about pending update for items that have k_EItemStateNeedsUpdate set. punBytesTotal will be valid after download started once + virtual bool GetItemDownloadInfo( PublishedFileId_t nPublishedFileID, uint64 *punBytesDownloaded, uint64 *punBytesTotal ) = 0; + + // download new or update already installed item. If function returns true, wait for DownloadItemResult_t. If the item is already installed, + // then files on disk should not be used until callback received. If item is not subscribed to, it will be cached for some time. + // If bHighPriority is set, any other item download will be suspended and this item downloaded ASAP. + virtual bool DownloadItem( PublishedFileId_t nPublishedFileID, bool bHighPriority ) = 0; + + // game servers can set a specific workshop folder before issuing any UGC commands. + // This is helpful if you want to support multiple game servers running out of the same install folder + virtual bool BInitWorkshopForGameServer( DepotId_t unWorkshopDepotID, const char *pszFolder ) = 0; }; -#define STEAMUGC_INTERFACE_VERSION "STEAMUGC_INTERFACE_VERSION003" +#define STEAMUGC_INTERFACE_VERSION "STEAMUGC_INTERFACE_VERSION007" //----------------------------------------------------------------------------- // Purpose: Callback for querying UGC @@ -255,7 +320,7 @@ struct SubmitItemUpdateResult_t //----------------------------------------------------------------------------- -// Purpose: a new Workshop item has been installed +// Purpose: a Workshop item has been installed or updated //----------------------------------------------------------------------------- struct ItemInstalled_t { @@ -265,6 +330,52 @@ struct ItemInstalled_t }; +//----------------------------------------------------------------------------- +// Purpose: result of DownloadItem(), existing item files can be accessed again +//----------------------------------------------------------------------------- +struct DownloadItemResult_t +{ + enum { k_iCallback = k_iClientUGCCallbacks + 6 }; + AppId_t m_unAppID; + PublishedFileId_t m_nPublishedFileId; + EResult m_eResult; +}; + +//----------------------------------------------------------------------------- +// Purpose: result of AddItemToFavorites() or RemoveItemFromFavorites() +//----------------------------------------------------------------------------- +struct UserFavoriteItemsListChanged_t +{ + enum { k_iCallback = k_iClientUGCCallbacks + 7 }; + PublishedFileId_t m_nPublishedFileId; + EResult m_eResult; + bool m_bWasAddRequest; +}; + +//----------------------------------------------------------------------------- +// Purpose: The result of a call to SetUserItemVote() +//----------------------------------------------------------------------------- +struct SetUserItemVoteResult_t +{ + enum { k_iCallback = k_iClientUGCCallbacks + 8 }; + PublishedFileId_t m_nPublishedFileId; + EResult m_eResult; + bool m_bVoteUp; +}; + +//----------------------------------------------------------------------------- +// Purpose: The result of a call to GetUserItemVote() +//----------------------------------------------------------------------------- +struct GetUserItemVoteResult_t +{ + enum { k_iCallback = k_iClientUGCCallbacks + 9 }; + PublishedFileId_t m_nPublishedFileId; + EResult m_eResult; + bool m_bVotedUp; + bool m_bVotedDown; + bool m_bVoteSkipped; +}; + #pragma pack( pop ) #endif // ISTEAMUGC_H diff --git a/mp/src/public/steam/isteamuser.h b/mp/src/public/steam/isteamuser.h index a670849e..989b88e7 100644 --- a/mp/src/public/steam/isteamuser.h +++ b/mp/src/public/steam/isteamuser.h @@ -166,6 +166,18 @@ public: // gets the Steam Level of the user, as shown on their profile virtual int GetPlayerSteamLevel() = 0; + // Requests a URL which authenticates an in-game browser for store check-out, + // and then redirects to the specified URL. As long as the in-game browser + // accepts and handles session cookies, Steam microtransaction checkout pages + // will automatically recognize the user instead of presenting a login page. + // The result of this API call will be a StoreAuthURLResponse_t callback. + // NOTE: The URL has a very short lifetime to prevent history-snooping attacks, + // so you should only call this API when you are about to launch the browser, + // or else immediately navigate to the result URL using a hidden browser window. + // NOTE 2: The resulting authorization cookie has an expiration time of one day, + // so it would be a good idea to request and visit a new auth URL every 12 hours. + virtual SteamAPICall_t RequestStoreAuthURL( const char *pchRedirectURL ) = 0; + #ifdef _PS3 // Initiates PS3 Logon request using just PSN ticket. // @@ -205,7 +217,7 @@ public: }; -#define STEAMUSER_INTERFACE_VERSION "SteamUser017" +#define STEAMUSER_INTERFACE_VERSION "SteamUser018" // callbacks @@ -287,6 +299,15 @@ struct IPCFailure_t }; +//----------------------------------------------------------------------------- +// Purpose: Signaled whenever licenses change +//----------------------------------------------------------------------------- +struct LicensesUpdated_t +{ + enum { k_iCallback = k_iSteamUserCallbacks + 25 }; +}; + + //----------------------------------------------------------------------------- // callback for BeginAuthSession //----------------------------------------------------------------------------- @@ -342,6 +363,16 @@ struct GameWebCallback_t char m_szURL[256]; }; +//----------------------------------------------------------------------------- +// Purpose: sent to your game in response to ISteamUser::RequestStoreAuthURL +//----------------------------------------------------------------------------- +struct StoreAuthURLResponse_t +{ + enum { k_iCallback = k_iSteamUserCallbacks + 65 }; + char m_szURL[512]; +}; + + #pragma pack( pop ) diff --git a/mp/src/public/steam/isteamuserstats.h b/mp/src/public/steam/isteamuserstats.h index c5847cf6..3a65691c 100644 --- a/mp/src/public/steam/isteamuserstats.h +++ b/mp/src/public/steam/isteamuserstats.h @@ -1,4 +1,4 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// +//====== Copyright � 1996-2009, Valve Corporation, All rights reserved. ======= // // Purpose: interface to stats, achievements, and leaderboards // @@ -194,7 +194,9 @@ public: // as above, but downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers // if a user doesn't have a leaderboard entry, they won't be included in the result // a max of 100 users can be downloaded at a time, with only one outstanding call at a time - virtual SteamAPICall_t DownloadLeaderboardEntriesForUsers( SteamLeaderboard_t hSteamLeaderboard, CSteamID *prgUsers, int cUsers ) = 0; + METHOD_DESC(Downloads leaderboard entries for an arbitrary set of users - ELeaderboardDataRequest is k_ELeaderboardDataRequestUsers) + virtual SteamAPICall_t DownloadLeaderboardEntriesForUsers( SteamLeaderboard_t hSteamLeaderboard, + ARRAY_COUNT_D(cUsers, Array of users to retrieve) CSteamID *prgUsers, int cUsers ) = 0; // Returns data about a single leaderboard entry // use a for loop from 0 to LeaderboardScoresDownloaded_t::m_cEntryCount to get all the downloaded entries @@ -259,8 +261,8 @@ public: // So when called, pData[0] will be today, pData[1] will be yesterday, and pData[2] will be two days ago, // etc. cubData is the size in bytes of the pubData buffer. Returns the number of // elements actually set. - virtual int32 GetGlobalStatHistory( const char *pchStatName, int64 *pData, uint32 cubData ) = 0; - virtual int32 GetGlobalStatHistory( const char *pchStatName, double *pData, uint32 cubData ) = 0; + virtual int32 GetGlobalStatHistory( const char *pchStatName, ARRAY_COUNT(cubData) int64 *pData, uint32 cubData ) = 0; + virtual int32 GetGlobalStatHistory( const char *pchStatName, ARRAY_COUNT(cubData) double *pData, uint32 cubData ) = 0; #ifdef _PS3 // Call to kick off installation of the PS3 trophies. This call is asynchronous, and the results will be returned in a PS3TrophiesInstalled_t diff --git a/mp/src/public/steam/isteamutils.h b/mp/src/public/steam/isteamutils.h index 7f8d6bf0..54777d33 100644 --- a/mp/src/public/steam/isteamutils.h +++ b/mp/src/public/steam/isteamutils.h @@ -160,6 +160,9 @@ public: // returns true if Steam itself is running in VR mode virtual bool IsSteamRunningInVR() = 0; + + // Sets the inset of the overlay notification from the corner specified by SetOverlayNotificationPosition. + virtual void SetOverlayNotificationInset( int nHorizontalInset, int nVerticalInset ) = 0; }; #define STEAMUTILS_INTERFACE_VERSION "SteamUtils007" diff --git a/mp/src/public/steam/matchmakingtypes.h b/mp/src/public/steam/matchmakingtypes.h index df6a2d4f..08d5a966 100644 --- a/mp/src/public/steam/matchmakingtypes.h +++ b/mp/src/public/steam/matchmakingtypes.h @@ -64,6 +64,8 @@ enum EMatchMakingServerResponse class servernetadr_t { public: + + servernetadr_t() : m_usConnectionPort( 0 ), m_usQueryPort( 0 ), m_unIP( 0 ) {} void Init( unsigned int ip, uint16 usQueryPort, uint16 usConnectionPort ); #ifdef NETADR_H @@ -154,9 +156,9 @@ inline const char *servernetadr_t::ToString( uint32 unIP, uint16 usPort ) const static int nBuf = 0; unsigned char *ipByte = (unsigned char *)&unIP; #ifdef VALVE_BIG_ENDIAN - Q_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[0]), (int)(ipByte[1]), (int)(ipByte[2]), (int)(ipByte[3]), usPort ); + V_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[0]), (int)(ipByte[1]), (int)(ipByte[2]), (int)(ipByte[3]), usPort ); #else - Q_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[3]), (int)(ipByte[2]), (int)(ipByte[1]), (int)(ipByte[0]), usPort ); + V_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[3]), (int)(ipByte[2]), (int)(ipByte[1]), (int)(ipByte[0]), usPort ); #endif const char *pchRet = s[nBuf]; ++nBuf; diff --git a/mp/src/public/steam/steam_api.h b/mp/src/public/steam/steam_api.h index 9850cd7b..b6ab4edf 100644 --- a/mp/src/public/steam/steam_api.h +++ b/mp/src/public/steam/steam_api.h @@ -133,31 +133,56 @@ S_API ISteamPS3OverlayRender *S_CALLTYPE SteamPS3OverlayRender(); #endif #endif // VERSION_SAFE_STEAM_API_INTERFACES + //----------------------------------------------------------------------------------------------------------------------------------------------------------// -// steam callback helper functions +// steam callback and call-result helpers // -// The following classes/macros are used to be able to easily multiplex callbacks -// from the Steam API into various objects in the app in a thread-safe manner +// The following macros and classes are used to register your application for +// callbacks and call-results, which are delivered in a predictable manner. // -// These functors are triggered via the SteamAPI_RunCallbacks() function, mapping the callback -// to as many functions/objects as are registered to it +// STEAM_CALLBACK macros are meant for use inside of a C++ class definition. +// They map a Steam notification callback directly to a class member function +// which is automatically prototyped as "void func( callback_type *pParam )". +// +// CCallResult is used with specific Steam APIs that return "result handles". +// The handle can be passed to a CCallResult object's Set function, along with +// an object pointer and member-function pointer. The member function will +// be executed once the results of the Steam API call are available. +// +// CCallback and CCallbackManual classes can be used instead of STEAM_CALLBACK +// macros if you require finer control over registration and unregistration. +// +// Callbacks and call-results are queued automatically and are only +// delivered/executed when your application calls SteamAPI_RunCallbacks(). //----------------------------------------------------------------------------------------------------------------------------------------------------------// S_API void S_CALLTYPE SteamAPI_RunCallbacks(); -// functions used by the utility CCallback objects to receive callbacks +// Declares a callback member function plus a helper member variable which +// registers the callback on object creation and unregisters on destruction. +// The optional fourth 'var' param exists only for backwards-compatibility +// and can be ignored. +#define STEAM_CALLBACK( thisclass, func, .../*callback_type, [deprecated] var*/ ) \ + _STEAM_CALLBACK_SELECT( ( __VA_ARGS__, 4, 3 ), ( /**/, thisclass, func, __VA_ARGS__ ) ) + +// Declares a callback function and a named CCallbackManual variable which +// has Register and Unregister functions instead of automatic registration. +#define STEAM_CALLBACK_MANUAL( thisclass, func, callback_type, var ) \ + CCallbackManual< thisclass, callback_type > var; void func( callback_type *pParam ) + + +// Internal functions used by the utility CCallback objects to receive callbacks S_API void S_CALLTYPE SteamAPI_RegisterCallback( class CCallbackBase *pCallback, int iCallback ); S_API void S_CALLTYPE SteamAPI_UnregisterCallback( class CCallbackBase *pCallback ); -// functions used by the utility CCallResult objects to receive async call results +// Internal functions used by the utility CCallResult objects to receive async call results S_API void S_CALLTYPE SteamAPI_RegisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); S_API void S_CALLTYPE SteamAPI_UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall ); //----------------------------------------------------------------------------- -// Purpose: base for callbacks, -// used only by CCallback, shouldn't be used directly +// Purpose: base for callbacks and call results - internal implementation detail //----------------------------------------------------------------------------- class CCallbackBase { @@ -174,6 +199,26 @@ protected: uint8 m_nCallbackFlags; int m_iCallback; friend class CCallbackMgr; + +private: + CCallbackBase( const CCallbackBase& ); + CCallbackBase& operator=( const CCallbackBase& ); +}; + +//----------------------------------------------------------------------------- +// Purpose: templated base for callbacks - internal implementation detail +//----------------------------------------------------------------------------- +template< int sizeof_P > +class CCallbackImpl : protected CCallbackBase +{ +public: + ~CCallbackImpl() { if ( m_nCallbackFlags & k_ECallbackFlagsRegistered ) SteamAPI_UnregisterCallback( this ); } + void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; } + +protected: + virtual void Run( void *pvParam ) = 0; + virtual void Run( void *pvParam, bool /*bIOFailure*/, SteamAPICall_t /*hSteamAPICall*/ ) { Run( pvParam ); } + virtual int GetCallbackSizeBytes() { return sizeof_P; } }; @@ -235,7 +280,7 @@ private: m_hAPICall = k_uAPICallInvalid; // caller unregisters for us (m_pObj->*m_Func)( (P *)pvParam, false ); } - void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) + virtual void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ) { if ( hSteamAPICall == m_hAPICall ) { @@ -243,7 +288,7 @@ private: (m_pObj->*m_Func)( (P *)pvParam, bIOFailure ); } } - int GetCallbackSizeBytes() + virtual int GetCallbackSizeBytes() { return sizeof( P ); } @@ -257,31 +302,24 @@ private: //----------------------------------------------------------------------------- // Purpose: maps a steam callback to a class member function -// template params: T = local class, P = parameter struct +// template params: T = local class, P = parameter struct, +// bGameserver = listen for gameserver callbacks instead of client callbacks //----------------------------------------------------------------------------- -template< class T, class P, bool bGameServer > -class CCallback : protected CCallbackBase +template< class T, class P, bool bGameserver = false > +class CCallback : public CCallbackImpl< sizeof( P ) > { public: - typedef void (T::*func_t)( P* ); + typedef void (T::*func_t)(P*); - // If you can't support constructing a callback with the correct parameters - // then uncomment the empty constructor below and manually call - // ::Register() for your object - // Or, just call the regular constructor with (NULL, NULL) - // CCallback() {} - - // constructor for initializing this object in owner's constructor - CCallback( T *pObj, func_t func ) : m_pObj( pObj ), m_Func( func ) + // NOTE: If you can't provide the correct parameters at construction time, you should + // use the CCallbackManual callback object (STEAM_CALLBACK_MANUAL macro) instead. + CCallback( T *pObj, func_t func ) : m_pObj( NULL ), m_Func( NULL ) { - if ( pObj && func ) - Register( pObj, func ); - } - - ~CCallback() - { - if ( m_nCallbackFlags & k_ECallbackFlagsRegistered ) - Unregister(); + if ( bGameserver ) + { + this->SetGameserverFlag(); + } + Register( pObj, func ); } // manual registration of the callback @@ -290,13 +328,9 @@ public: if ( !pObj || !func ) return; - if ( m_nCallbackFlags & k_ECallbackFlagsRegistered ) + if ( this->m_nCallbackFlags & CCallbackBase::k_ECallbackFlagsRegistered ) Unregister(); - if ( bGameServer ) - { - m_nCallbackFlags |= k_ECallbackFlagsGameServer; - } m_pObj = pObj; m_Func = func; // SteamAPI_RegisterCallback sets k_ECallbackFlagsRegistered @@ -309,38 +343,50 @@ public: SteamAPI_UnregisterCallback( this ); } - void SetGameserverFlag() { m_nCallbackFlags |= k_ECallbackFlagsGameServer; } protected: virtual void Run( void *pvParam ) { (m_pObj->*m_Func)( (P *)pvParam ); } - virtual void Run( void *pvParam, bool, SteamAPICall_t ) - { - (m_pObj->*m_Func)( (P *)pvParam ); - } - int GetCallbackSizeBytes() - { - return sizeof( P ); - } T *m_pObj; func_t m_Func; }; -// Allows you to defer registration of the callback -template< class T, class P, bool bGameServer > + +//----------------------------------------------------------------------------- +// Purpose: subclass of CCallback which allows default-construction in +// an unregistered state; you must call Register manually +//----------------------------------------------------------------------------- +template< class T, class P, bool bGameServer = false > class CCallbackManual : public CCallback< T, P, bGameServer > { public: CCallbackManual() : CCallback< T, P, bGameServer >( NULL, NULL ) {} + + // Inherits public Register and Unregister functions from base class }; -// utility macro for declaring the function and callback object together -#define STEAM_CALLBACK( thisclass, func, param, var ) CCallback< thisclass, param, false > var; void func( param *pParam ) -// same as above, but lets you defer the callback binding by calling Register later -#define STEAM_CALLBACK_MANUAL( thisclass, func, param, var ) CCallbackManual< thisclass, param, false > var; void func( param *pParam ) + +//----------------------------------------------------------------------------- +// The following macros are implementation details, not intended for public use +//----------------------------------------------------------------------------- +#define _STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param ) +#define _STEAM_CALLBACK_HELPER( _1, _2, SELECTED, ... ) _STEAM_CALLBACK_##SELECTED +#define _STEAM_CALLBACK_SELECT( X, Y ) _STEAM_CALLBACK_HELPER X Y +#define _STEAM_CALLBACK_3( extra_code, thisclass, func, param ) \ + struct CCallbackInternal_ ## func : private CCallbackImpl< sizeof( param ) > { \ + CCallbackInternal_ ## func () { extra_code SteamAPI_RegisterCallback( this, param::k_iCallback ); } \ + CCallbackInternal_ ## func ( const CCallbackInternal_ ## func & ) { extra_code SteamAPI_RegisterCallback( this, param::k_iCallback ); } \ + CCallbackInternal_ ## func & operator=( const CCallbackInternal_ ## func & ) { return *this; } \ + private: virtual void Run( void *pvParam ) { _STEAM_CALLBACK_AUTO_HOOK( thisclass, func, param ) \ + thisclass *pOuter = reinterpret_cast( reinterpret_cast(this) - offsetof( thisclass, m_steamcallback_ ## func ) ); \ + pOuter->func( reinterpret_cast( pvParam ) ); \ + } \ + } m_steamcallback_ ## func ; void func( param *pParam ) +#define _STEAM_CALLBACK_4( _, thisclass, func, param, var ) \ + CCallback< thisclass, param > var; void func( param *pParam ) #ifdef _WIN32 diff --git a/mp/src/public/steam/steam_gameserver.h b/mp/src/public/steam/steam_gameserver.h index 98e26a72..6b67da1d 100644 --- a/mp/src/public/steam/steam_gameserver.h +++ b/mp/src/public/steam/steam_gameserver.h @@ -59,6 +59,7 @@ S_API ISteamUtils *SteamGameServerUtils(); S_API ISteamNetworking *SteamGameServerNetworking(); S_API ISteamGameServerStats *SteamGameServerStats(); S_API ISteamHTTP *SteamGameServerHTTP(); +S_API ISteamUGC *SteamGameServerUGC(); #endif S_API void SteamGameServer_Shutdown(); @@ -67,8 +68,20 @@ S_API void SteamGameServer_RunCallbacks(); S_API bool SteamGameServer_BSecure(); S_API uint64 SteamGameServer_GetSteamID(); -#define STEAM_GAMESERVER_CALLBACK( thisclass, func, param, var ) CCallback< thisclass, param, true > var; void func( param *pParam ) +//----------------------------------------------------------------------------------------------------------------------------------------------------------// +// These macros are similar to the STEAM_CALLBACK_* macros in steam_api.h, but only trigger for gameserver callbacks +//----------------------------------------------------------------------------------------------------------------------------------------------------------// +#define STEAM_GAMESERVER_CALLBACK( thisclass, func, /*callback_type, [deprecated] var*/... ) \ + _STEAM_CALLBACK_SELECT( ( __VA_ARGS__, GS, 3 ), ( this->SetGameserverFlag();, thisclass, func, __VA_ARGS__ ) ) + +#define STEAM_GAMESERVER_CALLBACK_MANUAL( thisclass, func, callback_type, var ) \ + CCallbackManual< thisclass, callback_type, true > var; void func( callback_type *pParam ) + + + +#define _STEAM_CALLBACK_GS( _, thisclass, func, param, var ) \ + CCallback< thisclass, param, true > var; void func( param *pParam ) //----------------------------------------------------------------------------------------------------------------------------------------------------------// // steamclient.dll private wrapper functions @@ -101,6 +114,7 @@ public: ISteamNetworking *SteamGameServerNetworking() { return m_pSteamGameServerNetworking; } ISteamGameServerStats *SteamGameServerStats() { return m_pSteamGameServerStats; } ISteamHTTP *SteamHTTP() { return m_pSteamHTTP; } + ISteamUGC *SteamUGC() { return m_pSteamUGC; } private: ISteamGameServer *m_pSteamGameServer; @@ -108,6 +122,7 @@ private: ISteamNetworking *m_pSteamGameServerNetworking; ISteamGameServerStats *m_pSteamGameServerStats; ISteamHTTP *m_pSteamHTTP; + ISteamUGC *m_pSteamUGC; }; inline CSteamGameServerAPIContext::CSteamGameServerAPIContext() @@ -122,6 +137,7 @@ inline void CSteamGameServerAPIContext::Clear() m_pSteamGameServerNetworking = NULL; m_pSteamGameServerStats = NULL; m_pSteamHTTP = NULL; + m_pSteamUGC = NULL; } S_API ISteamClient *g_pSteamClientGameServer; @@ -154,6 +170,10 @@ inline bool CSteamGameServerAPIContext::Init() if ( !m_pSteamHTTP ) return false; + m_pSteamUGC = g_pSteamClientGameServer->GetISteamUGC( hSteamUser, hSteamPipe, STEAMUGC_INTERFACE_VERSION ); + if ( !m_pSteamUGC ) + return false; + return true; } diff --git a/mp/src/public/steam/steamclientpublic.h b/mp/src/public/steam/steamclientpublic.h index f5998599..4e952dc7 100644 --- a/mp/src/public/steam/steamclientpublic.h +++ b/mp/src/public/steam/steamclientpublic.h @@ -114,6 +114,17 @@ enum EResult k_EResultAccountLoginDeniedThrottle = 87, // login attempt failed, try to throttle response to possible attacker k_EResultTwoFactorCodeMismatch = 88, // two factor code mismatch k_EResultTwoFactorActivationCodeMismatch = 89, // activation code for two-factor didn't match + k_EResultAccountAssociatedToMultiplePartners = 90, // account has been associated with multiple partners + k_EResultNotModified = 91, // data not modified + k_EResultNoMobileDevice = 92, // the account does not have a mobile device associated with it + k_EResultTimeNotSynced = 93, // the time presented is out of range or tolerance + k_EResultSmsCodeFailed = 94, // SMS code failure (no match, none pending, etc.) + k_EResultAccountLimitExceeded = 95, // Too many accounts access this resource + k_EResultAccountActivityLimitExceeded = 96, // Too many changes to this account + k_EResultPhoneActivityLimitExceeded = 97, // Too many changes to this phone + k_EResultRefundToWallet = 98, // Cannot refund to payment method, must use wallet + k_EResultEmailSendFailure = 99, // Cannot send an email + k_EResultNotSettled = 100, // Can't perform operation till payment has settled }; // Error codes for use with the voice functions @@ -127,11 +138,13 @@ enum EVoiceResult k_EVoiceResultDataCorrupted = 5, k_EVoiceResultRestricted = 6, k_EVoiceResultUnsupportedCodec = 7, + k_EVoiceResultReceiverOutOfDate = 8, + k_EVoiceResultReceiverDidNotAnswer = 9, }; // Result codes to GSHandleClientDeny/Kick -typedef enum +enum EDenyReason { k_EDenyInvalid = 0, k_EDenyInvalidVersion = 1, @@ -149,14 +162,14 @@ typedef enum k_EDenySteamResponseTimedOut = 13, k_EDenySteamValidationStalled = 14, k_EDenySteamOwnerLeftGuestUser = 15, -} EDenyReason; +}; // return type of GetAuthSessionTicket typedef uint32 HAuthTicket; const HAuthTicket k_HAuthTicketInvalid = 0; // results from BeginAuthSession -typedef enum +enum EBeginAuthSessionResult { k_EBeginAuthSessionResultOK = 0, // Ticket is valid for this game and this steamID. k_EBeginAuthSessionResultInvalidTicket = 1, // Ticket is not valid. @@ -164,10 +177,10 @@ typedef enum k_EBeginAuthSessionResultInvalidVersion = 3, // Ticket is from an incompatible interface version k_EBeginAuthSessionResultGameMismatch = 4, // Ticket is not for this game k_EBeginAuthSessionResultExpiredTicket = 5, // Ticket has expired -} EBeginAuthSessionResult; +}; // Callback values for callback ValidateAuthTicketResponse_t which is a response to BeginAuthSession -typedef enum +enum EAuthSessionResponse { k_EAuthSessionResponseOK = 0, // Steam has verified the user is online, the ticket is valid and ticket has not been reused. k_EAuthSessionResponseUserNotConnectedToSteam = 1, // The user in question is not connected to steam @@ -179,15 +192,15 @@ typedef enum k_EAuthSessionResponseAuthTicketInvalidAlreadyUsed = 7, // This ticket has already been used, it is not valid. k_EAuthSessionResponseAuthTicketInvalid = 8, // This ticket is not from a user instance currently connected to steam. k_EAuthSessionResponsePublisherIssuedBan = 9, // The user is banned for this game. The ban came via the web api and not VAC -} EAuthSessionResponse; +}; // results from UserHasLicenseForApp -typedef enum +enum EUserHasLicenseForAppResult { k_EUserHasLicenseResultHasLicense = 0, // User has a license for specified app k_EUserHasLicenseResultDoesNotHaveLicense = 1, // User does not have a license for the specified app k_EUserHasLicenseResultNoAuth = 2, // User has not been authenticated -} EUserHasLicenseForAppResult; +}; // Steam account types @@ -244,6 +257,7 @@ enum EAppOwnershipFlags k_EAppOwnershipFlags_LicensePermanent = 0x0800, // permanent license, not borrowed, or guest or freeweekend etc k_EAppOwnershipFlags_LicenseRecurring = 0x1000, // Recurring license, user is charged periodically k_EAppOwnershipFlags_LicenseCanceled = 0x2000, // Mark as canceled, but might be still active if recurring + k_EAppOwnershipFlags_AutoGrant = 0x4000, // Ownership is based on any kind of autogrant license }; @@ -262,8 +276,8 @@ enum EAppType k_EAppType_Guide = 0x040, // game guide, PDF etc k_EAppType_Driver = 0x080, // hardware driver updater (ATI, Razor etc) k_EAppType_Config = 0x100, // hidden app used to config Steam features (backpack, sales, etc) - k_EAppType_Film = 0x200, // A Movie (feature film) - k_EAppType_TVSeries = 0x400, // A TV or other video series which will have episodes and perhaps seasons + k_EAppType_Hardware = 0x200, // a hardware device (Steam Machine, Steam Controller, Steam Link, etc.) + // 0x400 is up for grabs here k_EAppType_Video = 0x800, // A video component of either a Film or TVSeries (may be the feature, an episode, preview, making-of, etc) k_EAppType_Plugin = 0x1000, // Plug-in types for other Apps k_EAppType_Music = 0x2000, // Music files @@ -313,6 +327,7 @@ enum EChatEntryType k_EChatEntryTypeHistoricalChat = 11, // a chat message from user's chat history or offilne message k_EChatEntryTypeReserved1 = 12, k_EChatEntryTypeReserved2 = 13, + k_EChatEntryTypeLinkBlocked = 14, // a link was removed by the chat filter. }; @@ -394,6 +409,27 @@ enum ENotificationPosition }; +//----------------------------------------------------------------------------- +// Purpose: Broadcast upload result details +//----------------------------------------------------------------------------- +enum EBroadcastUploadResult +{ + k_EBroadcastUploadResultNone = 0, // broadcast state unknown + k_EBroadcastUploadResultOK = 1, // broadcast was good, no problems + k_EBroadcastUploadResultInitFailed = 2, // broadcast init failed + k_EBroadcastUploadResultFrameFailed = 3, // broadcast frame upload failed + k_EBroadcastUploadResultTimeout = 4, // broadcast upload timed out + k_EBroadcastUploadResultBandwidthExceeded = 5, // broadcast send too much data + k_EBroadcastUploadResultLowFPS = 6, // broadcast FPS too low + k_EBroadcastUploadResultMissingKeyFrames = 7, // broadcast sending not enough key frames + k_EBroadcastUploadResultNoConnection = 8, // broadcast client failed to connect to relay + k_EBroadcastUploadResultRelayFailed = 9, // relay dropped the upload + k_EBroadcastUploadResultSettingsChanged = 10, // the client changed broadcast settings + k_EBroadcastUploadResultMissingAudio = 11, // client failed to send audio data + k_EBroadcastUploadResultTooFarBehind = 12, // clients was too slow uploading +}; + + #pragma pack( push, 1 ) #define CSTEAMID_DEFINED @@ -896,10 +932,10 @@ public: m_gameID.m_nType = k_EGameIDTypeGameMod; char rgchModDir[MAX_PATH]; - Q_FileBase( pchModPath, rgchModDir, sizeof( rgchModDir ) ); + V_FileBase( pchModPath, rgchModDir, sizeof( rgchModDir ) ); CRC32_t crc32; CRC32_Init( &crc32 ); - CRC32_ProcessBuffer( &crc32, rgchModDir, Q_strlen( rgchModDir ) ); + CRC32_ProcessBuffer( &crc32, rgchModDir, V_strlen( rgchModDir ) ); CRC32_Final( &crc32 ); // set the high-bit on the mod-id @@ -916,8 +952,8 @@ public: CRC32_t crc32; CRC32_Init( &crc32 ); - CRC32_ProcessBuffer( &crc32, pchExePath, Q_strlen( pchExePath ) ); - CRC32_ProcessBuffer( &crc32, pchAppName, Q_strlen( pchAppName ) ); + CRC32_ProcessBuffer( &crc32, pchExePath, V_strlen( pchExePath ) ); + CRC32_ProcessBuffer( &crc32, pchAppName, V_strlen( pchAppName ) ); CRC32_Final( &crc32 ); // set the high-bit on the mod-id @@ -937,7 +973,7 @@ public: CRC32_t crc32; CRC32_Init( &crc32 ); const char *pchFileId = vstFileID.Render(); - CRC32_ProcessBuffer( &crc32, pchFileId, Q_strlen( pchFileId ) ); + CRC32_ProcessBuffer( &crc32, pchFileId, V_strlen( pchFileId ) ); CRC32_Final( &crc32 ); // set the high-bit on the mod-id diff --git a/mp/src/public/steam/steamcontrollerpublic.h b/mp/src/public/steam/steamcontrollerpublic.h deleted file mode 100644 index 327ea46a..00000000 --- a/mp/src/public/steam/steamcontrollerpublic.h +++ /dev/null @@ -1,79 +0,0 @@ -//========= Copyright © 1996-2013, Valve LLC, All rights reserved. ============ -// -// Purpose: Controller related public types/constants -// -//============================================================================= - -#ifndef STEAMCONTROLLERPUBLIC_H -#define STEAMCONTROLLERPUBLIC_H -#ifdef _WIN32 -#pragma once -#endif - - -#if defined( STEAM ) || defined( ISTEAMCONTROLLER_H ) -// This file should only be included by the Steam build or directly from -// isteamcontroller.h. -#include "steamtypes.h" -#else -#include -typedef uint32_t uint32; -#ifdef __C51__ -typedef uint8_t uint64[8]; -#else -typedef uint64_t uint64; -#endif -#endif - -#pragma pack(1) - -// Safe to add new bitfields at the end of this list for new buttons/actions, -// but never re-use or re-number an existing flag as old client code will be -// confused. -#define STEAM_RIGHT_TRIGGER_MASK 0x0000000000000001l -#define STEAM_LEFT_TRIGGER_MASK 0x0000000000000002l -#define STEAM_RIGHT_BUMPER_MASK 0x0000000000000004l -#define STEAM_LEFT_BUMPER_MASK 0x0000000000000008l -#define STEAM_BUTTON_0_MASK 0x0000000000000010l -#define STEAM_BUTTON_1_MASK 0x0000000000000020l -#define STEAM_BUTTON_2_MASK 0x0000000000000040l -#define STEAM_BUTTON_3_MASK 0x0000000000000080l -#define STEAM_TOUCH_0_MASK 0x0000000000000100l -#define STEAM_TOUCH_1_MASK 0x0000000000000200l -#define STEAM_TOUCH_2_MASK 0x0000000000000400l -#define STEAM_TOUCH_3_MASK 0x0000000000000800l -#define STEAM_BUTTON_MENU_MASK 0x0000000000001000l -#define STEAM_BUTTON_STEAM_MASK 0x0000000000002000l -#define STEAM_BUTTON_ESCAPE_MASK 0x0000000000004000l -#define STEAM_BUTTON_BACK_LEFT_MASK 0x0000000000008000l -#define STEAM_BUTTON_BACK_RIGHT_MASK 0x0000000000010000l -#define STEAM_BUTTON_LEFTPAD_CLICKED_MASK 0x0000000000020000l -#define STEAM_BUTTON_RIGHTPAD_CLICKED_MASK 0x0000000000040000l -#define STEAM_LEFTPAD_FINGERDOWN_MASK 0x0000000000080000l -#define STEAM_RIGHTPAD_FINGERDOWN_MASK 0x0000000000100000l - -// Only add fields to the end of this struct, or if you need to change it in a larger -// way add a new message id and new struct completely so as to not break old clients. -typedef struct -{ - // If packet num matches that on your prior call, then the controller state hasn't been changed since - // your last call and there is no need to process it - uint32 unPacketNum; - - // bit flags for each of the buttons - uint64 ulButtons; - - // Left pad coordinates - short sLeftPadX; - short sLeftPadY; - - // Right pad coordinates - short sRightPadX; - short sRightPadY; - -} SteamControllerState_t; - -#pragma pack() - -#endif // STEAMCONTROLLERPUBLIC_H - diff --git a/mp/src/public/steam/steamhttpenums.h b/mp/src/public/steam/steamhttpenums.h index 11a4a03a..e15171f4 100644 --- a/mp/src/public/steam/steamhttpenums.h +++ b/mp/src/public/steam/steamhttpenums.h @@ -64,7 +64,7 @@ enum EHTTPStatusCode // Error codes k_EHTTPStatusCode400BadRequest = 400, - k_EHTTPStatusCode401Unauthorized = 401, + k_EHTTPStatusCode401Unauthorized = 401, // You probably want 403 or something else. 401 implies you're sending a WWW-Authenticate header and the client can sent an Authorization header in response. k_EHTTPStatusCode402PaymentRequired = 402, // This is reserved for future HTTP specs, not really supported by clients k_EHTTPStatusCode403Forbidden = 403, k_EHTTPStatusCode404NotFound = 404, @@ -81,6 +81,7 @@ enum EHTTPStatusCode k_EHTTPStatusCode415UnsupportedMediaType = 415, k_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, k_EHTTPStatusCode417ExpectationFailed = 417, + k_EHTTPStatusCode4xxUnknown = 418, // 418 is reserved, so we'll use it to mean unknown k_EHTTPStatusCode429TooManyRequests = 429, // Server error codes @@ -90,6 +91,7 @@ enum EHTTPStatusCode k_EHTTPStatusCode503ServiceUnavailable = 503, k_EHTTPStatusCode504GatewayTimeout = 504, k_EHTTPStatusCode505HTTPVersionNotSupported = 505, + k_EHTTPStatusCode5xxUnknown = 599, }; #endif // STEAMHTTPENUMS_H \ No newline at end of file diff --git a/mp/src/public/steam/steamtypes.h b/mp/src/public/steam/steamtypes.h index c3320a10..22ce3e61 100644 --- a/mp/src/public/steam/steamtypes.h +++ b/mp/src/public/steam/steamtypes.h @@ -84,6 +84,25 @@ typedef unsigned int uintp; #endif // else _WIN32 +#ifdef __clang__ +# define CLANG_ATTR(ATTR) __attribute__((annotate( ATTR ))) +#else +# define CLANG_ATTR(ATTR) +#endif + +#define METHOD_DESC(DESC) CLANG_ATTR( "desc:" #DESC ";" ) +#define IGNOREATTR() CLANG_ATTR( "ignore" ) +#define OUT_STRUCT() CLANG_ATTR( "out_struct: ;" ) +#define OUT_ARRAY_CALL(COUNTER,FUNCTION,PARAMS) CLANG_ATTR( "out_array_call:" #COUNTER "," #FUNCTION "," #PARAMS ";" ) +#define OUT_ARRAY_COUNT(COUNTER, DESC) CLANG_ATTR( "out_array_count:" #COUNTER ";desc:" #DESC ) +#define ARRAY_COUNT(COUNTER) CLANG_ATTR( "array_count:" #COUNTER ";" ) +#define ARRAY_COUNT_D(COUNTER, DESC) CLANG_ATTR( "array_count:" #COUNTER ";desc:" #DESC ) +#define BUFFER_COUNT(COUNTER) CLANG_ATTR( "buffer_count:" #COUNTER ";" ) +#define OUT_BUFFER_COUNT(COUNTER) CLANG_ATTR( "out_buffer_count:" #COUNTER ";" ) +#define OUT_STRING_COUNT(COUNTER) CLANG_ATTR( "out_string_count:" #COUNTER ";" ) +#define DESC(DESC) CLANG_ATTR("desc:" #DESC ";") + + const int k_cubSaltSize = 8; typedef uint8 Salt_t[ k_cubSaltSize ]; @@ -98,12 +117,13 @@ typedef uint64 GID_t; const GID_t k_GIDNil = 0xffffffffffffffffull; // For convenience, we define a number of types that are just new names for GIDs -typedef GID_t JobID_t; // Each Job has a unique ID +typedef uint64 JobID_t; // Each Job has a unique ID typedef GID_t TxnID_t; // Each financial transaction has a unique ID const GID_t k_TxnIDNil = k_GIDNil; const GID_t k_TxnIDUnknown = 0; +const JobID_t k_JobIDNil = 0xffffffffffffffffull; // this is baked into client messages and interfaces as an int, // make sure we never break this. @@ -111,6 +131,8 @@ typedef uint32 PackageId_t; const PackageId_t k_uPackageIdFreeSub = 0x0; const PackageId_t k_uPackageIdInvalid = 0xFFFFFFFF; +typedef uint32 BundleId_t; +const BundleId_t k_uBundleIdInvalid = 0; // this is baked into client messages and interfaces as an int, // make sure we never break this. diff --git a/mp/src/public/steam/steamvr.h b/mp/src/public/steam/steamvr.h deleted file mode 100644 index be62fc86..00000000 --- a/mp/src/public/steam/steamvr.h +++ /dev/null @@ -1,261 +0,0 @@ -#pragma once - -#include - -namespace vr -{ - -#if defined(__linux__) || defined(__APPLE__) - // The 32-bit version of gcc has the alignment requirement for uint64 and double set to - // 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. - // The 64-bit version of gcc has the alignment requirement for these types set to - // 8 meaning that unless we use #pragma pack(4) our structures will get bigger. - // The 64-bit structure packing has to match the 32-bit structure packing for each platform. -#pragma pack( push, 4 ) -#else -#pragma pack( push, 8 ) -#endif - - -// right-handed system -// +y is up -// +x is to the right -// -z is going away from you -// Distance unit is meters -struct HmdMatrix34_t -{ - float m[3][4]; -}; - -struct HmdMatrix44_t -{ - float m[4][4]; -}; - - -/** Used to return the post-distortion UVs for each color channel. -* UVs range from 0 to 1 with 0,0 in the upper left corner of the -* source render target. The 0,0 to 1,1 range covers a single eye. */ -struct DistortionCoordinates_t -{ - float rfRed[2]; - float rfGreen[2]; - float rfBlue[2]; -}; - - -enum Hmd_Eye -{ - Eye_Left = 0, - Eye_Right = 1 -}; - -enum GraphicsAPIConvention -{ - API_DirectX = 0, // Normalized Z goes from 0 at the viewer to 1 at the far clip plane - API_OpenGL = 1, // Normalized Z goes from 1 at the viewer to -1 at the far clip plane -}; - -enum HmdTrackingResult -{ - TrackingResult_Uninitialized = 1, - - TrackingResult_Calibrating_InProgress = 100, - TrackingResult_Calibrating_OutOfRange = 101, - - TrackingResult_Running_OK = 200, - TrackingResult_Running_OutOfRange = 201, -}; - -class IHmd -{ -public: - - - // ------------------------------------ - // Display Methods - // ------------------------------------ - - /** Size and position that the window needs to be on the VR display. */ - virtual void GetWindowBounds( int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; - - /** Suggested size for the intermediate render target that the distortion pulls from. */ - virtual void GetRecommendedRenderTargetSize( uint32_t *pnWidth, uint32_t *pnHeight ) = 0; - - /** Gets the viewport in the frame buffer to draw the output of the distortion into */ - virtual void GetEyeOutputViewport( Hmd_Eye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; - - /** The projection matrix for the specified eye */ - virtual HmdMatrix44_t GetProjectionMatrix( Hmd_Eye eEye, float fNearZ, float fFarZ, GraphicsAPIConvention eProjType ) = 0; - - /** The components necessary to build your own projection matrix in case your - * application is doing something fancy like infinite Z */ - virtual void GetProjectionRaw( Hmd_Eye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) = 0; - - /** Returns the result of the distortion function for the specified eye and input UVs. UVs go from 0,0 in - * the upper left of that eye's viewport and 1,1 in the lower right of that eye's viewport. */ - virtual DistortionCoordinates_t ComputeDistortion( Hmd_Eye eEye, float fU, float fV ) = 0; - - /** Returns the transform from eye space to the head space. Eye space is the per-eye flavor of head - * space that provides stereo disparity. Instead of Model * View * Projection the sequence is Model * View * Eye^-1 * Projection. - * Normally View and Eye^-1 will be multiplied together and treated as View in your application. - */ - virtual HmdMatrix34_t GetHeadFromEyePose( Hmd_Eye eEye ) = 0; - - /** For use in simple VR apps, this method returns the concatenation of the - * tracking pose and the eye matrix to get a full view matrix for each eye. - * This is ( GetEyeMatrix() ) * (GetWorldFromHeadPose() ^ -1 ) */ - virtual bool GetViewMatrix( float fSecondsFromNow, HmdMatrix44_t *pMatLeftView, HmdMatrix44_t *pMatRightView, HmdTrackingResult *peResult ) = 0; - - /** [D3D9 Only] - * Returns the adapter index that the user should pass into CreateDevice to set up D3D9 in such - * a way that it can go full screen exclusive on the HMD. Returns -1 if there was an error. - */ - virtual int32_t GetD3D9AdapterIndex() = 0; - - /** [D3D10/11 Only] - * Returns the adapter index and output index that the user should pass into EnumAdapters adn EnumOutputs - * to create the device and swap chain in DX10 and DX11. If an error occurs both indices will be set to -1. - */ - virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex, int32_t *pnAdapterOutputIndex ) = 0; - - /** [Windows Only] - * Notifies the system that the VR output will appear in a particular window. - */ - virtual void AttachToWindow( void *hWnd ) = 0; - - // ------------------------------------ - // Tracking Methods - // ------------------------------------ - - /** The pose that the tracker thinks that the HMD will be in at the specified - * number of seconds into the future. Pass 0 to get the current state. - * - * This is roughly analogous to the inverse of the view matrix in most applications, though - * many games will need to do some additional rotation or translation on top of the rotation - * and translation provided by the head pose. - * - * If this function returns true the pose has been populated with a pose that can be used by the application. - * Check peResult for details about the pose, including messages that should be displayed to the user. - */ - virtual bool GetTrackerFromHeadPose( float fPredictedSecondsFromNow, HmdMatrix34_t *pmPose, HmdTrackingResult *peResult ) = 0; - - /** Passes back the pose matrix from the last successful call to GetWorldFromHeadPose(). Returns true if that matrix is - * valid (because there has been a previous successful pose.) */ - virtual bool GetLastTrackerFromHeadPose( HmdMatrix34_t *pmPose ) = 0; - - /** Returns true if the tracker for this HMD will drift the Yaw component of its pose over time regardless of - * actual head motion. This is true for gyro-based trackers with no ground truth. */ - virtual bool WillDriftInYaw() = 0; - - /** Sets the zero pose for the tracker coordinate system. After this call all WorldFromHead poses will be relative - * to the pose whenever this was called. The new zero coordinate system will not change the fact that the Y axis is - * up in the real world, so the next pose returned from GetWorldFromHeadPose after a call to ZeroTracker may not be - * exactly an identity matrix. */ - virtual void ZeroTracker() = 0; - - /** Returns the zero pose for the tracker coordinate system. If the tracker has never had a valid pose, this - * will be an identity matrix. */ - virtual HmdMatrix34_t GetTrackerZeroPose() = 0; - - // ------------------------------------ - // Administrative methods - // ------------------------------------ - - /** The ID of the driver this HMD uses as a UTF-8 string. Returns the length of the ID in bytes. If - * the buffer is not large enough to fit the ID an empty string will be returned. In general, 128 bytes - * will be enough to fit any ID. */ - virtual uint32_t GetDriverId( char *pchBuffer, uint32_t unBufferLen ) = 0; - - /** The ID of this display within its driver this HMD uses as a UTF-8 string. Returns the length of the ID in bytes. If - * the buffer is not large enough to fit the ID an empty string will be returned. In general, 128 bytes - * will be enough to fit any ID. */ - virtual uint32_t GetDisplayId( char *pchBuffer, uint32_t unBufferLen ) = 0; -}; - -static const char * const IHmd_Version = "IHmd_005"; - -/** error codes returned by Vr_Init */ -enum HmdError -{ - HmdError_None = 0, - - HmdError_Init_InstallationNotFound = 100, - HmdError_Init_InstallationCorrupt = 101, - HmdError_Init_VRClientDLLNotFound = 102, - HmdError_Init_FileNotFound = 103, - HmdError_Init_FactoryNotFound = 104, - HmdError_Init_InterfaceNotFound = 105, - HmdError_Init_InvalidInterface = 106, - HmdError_Init_UserConfigDirectoryInvalid = 107, - HmdError_Init_HmdNotFound = 108, - HmdError_Init_NotInitialized = 109, - - HmdError_Driver_Failed = 200, - HmdError_Driver_Unknown = 201, - HmdError_Driver_HmdUnknown = 202, - HmdError_Driver_NotLoaded = 203, - - HmdError_IPC_ServerInitFailed = 300, - HmdError_IPC_ConnectFailed = 301, - HmdError_IPC_SharedStateInitFailed = 302, - - HmdError_VendorSpecific_UnableToConnectToOculusRuntime = 1000, - -}; - - -// figure out how to import from the VR API dll -#if defined(_WIN32) - -#ifdef VR_API_EXPORT -#define VR_INTERFACE extern "C" __declspec( dllexport ) -#else -#define VR_INTERFACE extern "C" __declspec( dllimport ) -#endif - -#elif defined(GNUC) || defined(COMPILER_GCC) - -#ifdef VR_API_EXPORT -#define VR_INTERFACE extern "C" __attribute__((visibility("default"))) -#else -#define VR_INTERFACE extern "C" -#endif - -#else -#error "Unsupported Platform." -#endif - - - - -/** Finds the active installation of the VR API and initializes it. The priority for figuring -* out where to load vrclient from are: -* 1. The convar "VR_OVERRIDE", which should contain an absolute path to the root of -* an vr API directory. -* 2. The pchVROverride argument. This should be an absolute path or a path relative to -* the current executable. -* 3. The path "./vr" relative to the current executable's path. -* -* Each of these paths are to the "root" of the VR API install. That's the directory with -* the "drivers" directory and a platform (i.e. "win32") directory in it, not the directory with the DLL itself. -*/ -VR_INTERFACE IHmd *VR_Init( HmdError *peError ); - -/** unloads vrclient.dll. Any interface pointers from the interface are -* invalid after this point */ -VR_INTERFACE void VR_Shutdown( ); - -/** Returns true if there is an HMD attached. This check is as lightweight as possible and -* can be called outside of VR_Init/VR_Shutdown. It should be used when an application wants -* to know if initializing VR is a possibility but isn't ready to take that step yet. -*/ -VR_INTERFACE bool VR_IsHmdPresent(); - -/** Returns the string version of an HMD error. This function may be called outside of VR_Init()/VR_Shutdown(). */ -VR_INTERFACE const char *VR_GetStringForHmdError( HmdError error ); - -#pragma pack( pop ) - - -} \ No newline at end of file diff --git a/mp/src/public/studio.cpp b/mp/src/public/studio.cpp index 4d84e1d0..bf6fdb7d 100644 --- a/mp/src/public/studio.cpp +++ b/mp/src/public/studio.cpp @@ -920,6 +920,16 @@ mstudioseqdesc_t &CStudioHdr::pSeqdesc( int i ) Assert( ( i >= 0 && i < GetNumSeq() ) || ( i == 1 && GetNumSeq() <= 1 ) ); if ( i < 0 || i >= GetNumSeq() ) { + if ( GetNumSeq() <= 0 ) + { + // Return a zero'd out struct reference if we've got nothing. + // C_BaseObject::StopAnimGeneratedSounds was crashing due to this function + // returning a reference to garbage. It should now see numevents is 0, + // and bail. + static mstudioseqdesc_t s_nil_seq; + return s_nil_seq; + } + // Avoid reading random memory. i = 0; } @@ -1026,9 +1036,10 @@ int CStudioHdr::GetSharedPoseParameter( int iSequence, int iLocalPose ) const Assert( m_pVModel ); - virtualgroup_t *pGroup = &m_pVModel->m_group[ m_pVModel->m_seq[iSequence].group ]; + int group = m_pVModel->m_seq[iSequence].group; + virtualgroup_t *pGroup = m_pVModel->m_group.IsValidIndex( group ) ? &m_pVModel->m_group[ group ] : NULL; - return pGroup->masterPose[iLocalPose]; + return pGroup ? pGroup->masterPose[iLocalPose] : iLocalPose; } @@ -1603,6 +1614,7 @@ void CStudioHdr::RunFlexRules( const float *src, float *dest ) //----------------------------------------------------------------------------- #define iabs(i) (( (i) >= 0 ) ? (i) : -(i) ) +CUtlSymbolTable g_ActivityModifiersTable; extern void SetActivityForSequence( CStudioHdr *pstudiohdr, int i ); void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict pstudiohdr ) @@ -1628,7 +1640,7 @@ void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict // Some studio headers have no activities at all. In those // cases we can avoid a lot of this effort. - bool bFoundOne = false; + bool bFoundOne = false; // for each sequence in the header... const int NumSeq = pstudiohdr->GetNumSeq(); @@ -1657,7 +1669,10 @@ void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict HashValueType * __restrict toUpdate = &m_ActToSeqHash.Element(handle); toUpdate->count += 1; toUpdate->totalWeight += iabs(seqdesc.actweight); - Assert( toUpdate->totalWeight > 0 ); + if ( !HushAsserts() ) + { + AssertMsg( toUpdate->totalWeight > 0, "toUpdate->totalWeight: %d", toUpdate->totalWeight ); + } } else { @@ -1720,6 +1735,23 @@ void CStudioHdr::CActivityToSequenceMapping::Initialize( CStudioHdr * __restrict int tupleOffset = seqsPerAct[seqdesc.activity]; Assert( tupleOffset < element.count ); + if ( seqdesc.numactivitymodifiers > 0 ) + { + // add entries for this model's activity modifiers + (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = new CUtlSymbol[ seqdesc.numactivitymodifiers ]; + (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = seqdesc.numactivitymodifiers; + + for ( int k = 0; k < seqdesc.numactivitymodifiers; k++ ) + { + (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers[ k ] = g_ActivityModifiersTable.AddString( seqdesc.pActivityModifier( k )->pszName() ); + } + } + else + { + (tupleList + element.startingIdx + tupleOffset)->pActivityModifiers = NULL; + (tupleList + element.startingIdx + tupleOffset)->iNumActivityModifiers = 0; + } + // You might be tempted to collapse this pointer math into a single pointer -- // don't! the tuple list is marked __restrict above. (tupleList + element.startingIdx + tupleOffset)->seqnum = i; // store sequence number diff --git a/mp/src/public/studio.h b/mp/src/public/studio.h index bcc38d5d..bc70313b 100644 --- a/mp/src/public/studio.h +++ b/mp/src/public/studio.h @@ -26,7 +26,7 @@ #include "datamap.h" #include "generichash.h" #include "localflexcontroller.h" - +#include "utlsymbol.h" #define STUDIO_ENABLE_PERF_COUNTERS @@ -755,6 +755,14 @@ struct mstudioautolayer_t float end; // end of all influence }; +struct mstudioactivitymodifier_t +{ + DECLARE_BYTESWAP_DATADESC(); + + int sznameindex; + inline char *pszName() { return (sznameindex) ? (char *)(((byte *)this) + sznameindex ) : NULL; } +}; + // sequence descriptions struct mstudioseqdesc_t { @@ -851,7 +859,11 @@ struct mstudioseqdesc_t int cycleposeindex; // index of pose parameter to use as cycle index - int unused[7]; // remove/add as appropriate (grow back to 8 ints on version change!) + int activitymodifierindex; + int numactivitymodifiers; + inline mstudioactivitymodifier_t *pActivityModifier( int i ) const { Assert( i >= 0 && i < numactivitymodifiers); return activitymodifierindex != 0 ? (mstudioactivitymodifier_t *)(((byte *)this) + activitymodifierindex) + i : NULL; }; + + int unused[5]; // remove/add as appropriate (grow back to 8 ints on version change!) mstudioseqdesc_t(){} private: @@ -1947,75 +1959,75 @@ struct vertexFileFixup_t }; // This flag is set if no hitbox information was specified -#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX ( 1 << 0 ) +#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX 0x00000001 // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild // models when we change materials. -#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP ( 1 << 1 ) +#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP 0x00000002 // Use this when there are translucent parts to the model but we're not going to sort it -#define STUDIOHDR_FLAGS_FORCE_OPAQUE ( 1 << 2 ) +#define STUDIOHDR_FLAGS_FORCE_OPAQUE 0x00000004 // Use this when we want to render the opaque parts during the opaque pass // and the translucent parts during the translucent pass -#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS ( 1 << 3 ) +#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS 0x00000008 // This is set any time the .qc files has $staticprop in it // Means there's no bones and no transforms -#define STUDIOHDR_FLAGS_STATIC_PROP ( 1 << 4 ) +#define STUDIOHDR_FLAGS_STATIC_PROP 0x00000010 // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild // models when we change materials. -#define STUDIOHDR_FLAGS_USES_FB_TEXTURE ( 1 << 5 ) +#define STUDIOHDR_FLAGS_USES_FB_TEXTURE 0x00000020 // This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present // for the .mdl (the shadow lod is the last entry in the lod list if present) -#define STUDIOHDR_FLAGS_HASSHADOWLOD ( 1 << 6 ) +#define STUDIOHDR_FLAGS_HASSHADOWLOD 0x00000040 // NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild // models when we change materials. -#define STUDIOHDR_FLAGS_USES_BUMPMAPPING ( 1 << 7 ) +#define STUDIOHDR_FLAGS_USES_BUMPMAPPING 0x00000080 // NOTE: This flag is set when we should use the actual materials on the shadow LOD // instead of overriding them with the default one (necessary for translucent shadows) -#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS ( 1 << 8 ) +#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS 0x00000100 // NOTE: This flag is set when we should use the actual materials on the shadow LOD // instead of overriding them with the default one (necessary for translucent shadows) -#define STUDIOHDR_FLAGS_OBSOLETE ( 1 << 9 ) +#define STUDIOHDR_FLAGS_OBSOLETE 0x00000200 -#define STUDIOHDR_FLAGS_UNUSED ( 1 << 10 ) +#define STUDIOHDR_FLAGS_UNUSED 0x00000400 // NOTE: This flag is set at mdl build time -#define STUDIOHDR_FLAGS_NO_FORCED_FADE ( 1 << 11 ) +#define STUDIOHDR_FLAGS_NO_FORCED_FADE 0x00000800 // NOTE: The npc will lengthen the viseme check to always include two phonemes -#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE ( 1 << 12 ) +#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE 0x00001000 // This flag is set when the .qc has $constantdirectionallight in it // If set, we use constantdirectionallightdot to calculate light intensity // rather than the normal directional dot product // only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set -#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT ( 1 << 13 ) +#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT 0x00002000 // Flag to mark delta flexes as already converted from disk format to memory format -#define STUDIOHDR_FLAGS_FLEXES_CONVERTED ( 1 << 14 ) +#define STUDIOHDR_FLAGS_FLEXES_CONVERTED 0x00004000 // Indicates the studiomdl was built in preview mode -#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE ( 1 << 15 ) +#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE 0x00008000 // Ambient boost (runtime flag) -#define STUDIOHDR_FLAGS_AMBIENT_BOOST ( 1 << 16 ) +#define STUDIOHDR_FLAGS_AMBIENT_BOOST 0x00010000 // Don't cast shadows from this model (useful on first-person models) -#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS ( 1 << 17 ) +#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS 0x00020000 // alpha textures should cast shadows in vrad on this model (ONLY prop_static!) -#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS ( 1 << 18 ) +#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS 0x00040000 // flagged on load to indicate no animation events on this model -#define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE ( 1 << 21 ) +#define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE 0x00200000 // NOTE! Next time we up the .mdl file format, remove studiohdr2_t // and insert all fields in this structure into studiohdr_t. @@ -2493,6 +2505,7 @@ private: CUtlVector< int > m_boneParent; public: + // This class maps an activity to sequences allowed for that activity, accelerating the resolution // of SelectWeightedSequence(), especially on PowerPC. Iterating through every sequence // attached to a model turned out to be a very destructive cache access pattern on 360. @@ -2508,8 +2521,10 @@ public: // A tuple of a sequence and its corresponding weight. Lists of these correspond to activities. struct SequenceTuple { - short seqnum; - short weight; // the absolute value of the weight from the sequence header + short seqnum; + short weight; // the absolute value of the weight from the sequence header + CUtlSymbol *pActivityModifiers; // list of activity modifier symbols + int iNumActivityModifiers; }; // The type of the hash's stored data, a composite of both key and value @@ -2579,9 +2594,13 @@ public: // dtor -- not virtual because this class has no inheritors ~CActivityToSequenceMapping() - { + { if ( m_pSequenceTuples != NULL ) { + if ( m_pSequenceTuples->pActivityModifiers != NULL ) + { + delete[] m_pSequenceTuples->pActivityModifiers; + } delete[] m_pSequenceTuples; } } @@ -2612,6 +2631,9 @@ public: /// A more efficient version of the old SelectWeightedSequence() function in animation.cpp. int SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence ); + // selects the sequence with the most matching modifiers + int SelectWeightedSequenceFromModifiers( CStudioHdr *pstudiohdr, int activity, CUtlSymbol *pActivityModifiers, int iModifierCount ); + // Actually a big array, into which the hash values index. SequenceTuple *m_pSequenceTuples; unsigned int m_iSequenceTuplesCount; // (size of the whole array) @@ -2656,6 +2678,19 @@ public: return m_ActivityToSequence.SelectWeightedSequence( this, activity, curSequence ); } + inline int SelectWeightedSequenceFromModifiers( int activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) + { +#if STUDIO_SEQUENCE_ACTIVITY_LAZY_INITIALIZE + // We lazy-initialize the header on demand here, because CStudioHdr::Init() is + // called from the constructor, at which time the this pointer is illegitimate. + if ( !m_ActivityToSequence.IsInitialized() ) + { + m_ActivityToSequence.Initialize( this ); + } +#endif + return m_ActivityToSequence.SelectWeightedSequenceFromModifiers( this, activity, pActivityModifiers, iModifierCount ); + } + /// True iff there is at least one sequence for the given activity. inline bool HaveSequenceForActivity( int activity ) { diff --git a/mp/src/public/texture_group_names.h b/mp/src/public/texture_group_names.h index b30ed35a..92b31279 100644 --- a/mp/src/public/texture_group_names.h +++ b/mp/src/public/texture_group_names.h @@ -23,6 +23,7 @@ #define TEXTURE_GROUP_PRECACHED "Precached" // TODO: assign texture groups to the precached materials #define TEXTURE_GROUP_CUBE_MAP "CubeMap textures" #define TEXTURE_GROUP_RENDER_TARGET "RenderTargets" +#define TEXTURE_GROUP_RUNTIME_COMPOSITE "Runtime Composite" #define TEXTURE_GROUP_UNACCOUNTED "Unaccounted textures" // Textures that weren't assigned a texture group. //#define TEXTURE_GROUP_STATIC_VERTEX_BUFFER "Static Vertex" #define TEXTURE_GROUP_STATIC_INDEX_BUFFER "Static Indices" diff --git a/mp/src/public/tier0/dbg.h b/mp/src/public/tier0/dbg.h index c35e7a67..5fa68adf 100644 --- a/mp/src/public/tier0/dbg.h +++ b/mp/src/public/tier0/dbg.h @@ -221,6 +221,9 @@ typedef void (*AssertFailedNotifyFunc_t)( const char *pchFile, int nLine, const DBG_INTERFACE void SetAssertFailedNotifyFunc( AssertFailedNotifyFunc_t func ); DBG_INTERFACE void CallAssertFailedNotifyFunc( const char *pchFile, int nLine, const char *pchMessage ); +/* True if -hushasserts was passed on command line. */ +DBG_INTERFACE bool HushAsserts(); + #if defined( USE_SDL ) DBG_INTERFACE void SetAssertDialogParent( struct SDL_Window *window ); DBG_INTERFACE struct SDL_Window * GetAssertDialogParent(); @@ -412,12 +415,15 @@ DBG_INTERFACE struct SDL_Window * GetAssertDialogParent(); /* These are always compiled in */ DBG_INTERFACE void Msg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DMsg( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); DBG_INTERFACE void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DWarning( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); DBG_INTERFACE void Log( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); #ifdef Error // p4.cpp does a #define Error Warning and in that case the Error prototype needs to @@ -425,17 +431,23 @@ DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRIN DBG_INTERFACE void Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); #else DBG_INTERFACE void NORETURN Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); +DBG_INTERFACE void NORETURN ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); + #endif #else inline void Msg( ... ) {} inline void DMsg( ... ) {} +inline void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) {} +inline void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void DWarning( ... ) {} inline void Log( ... ) {} inline void DLog( ... ) {} +inline void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void Error( ... ) {} +inline void ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} #endif diff --git a/mp/src/public/tier0/minidump.h b/mp/src/public/tier0/minidump.h index fad2d073..e6507256 100644 --- a/mp/src/public/tier0/minidump.h +++ b/mp/src/public/tier0/minidump.h @@ -82,6 +82,23 @@ PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction( FnMiniDump pfn ); // being silently swallowed. We should always call this at startup. PLATFORM_INTERFACE void EnableCrashingOnCrashes(); -#endif +#endif // defined(_WIN32) && !defined(_X360) + +// +// Minidump User Stream Info Comments. +// +// There currently is a single header string, and an array of 64 comment strings. +// MinidumpUserStreamInfoSetHeader() will set the single header string. +// MinidumpUserStreamInfoAppend() will round robin through and array and set the comment strings, overwriting old. +PLATFORM_INTERFACE void MinidumpUserStreamInfoSetHeader( const char *pFormat, ... ); +PLATFORM_INTERFACE void MinidumpUserStreamInfoAppend( const char *pFormat, ... ); + +// Retrieve the StreamInfo strings. +// Index 0: header string +// Index 1..: comment string +// Returns NULL when you've reached the end of the comment string array +// Empty strings ("\0") can be returned if comment hasn't been set +PLATFORM_INTERFACE const char *MinidumpUserStreamInfoGet( int Index ); #endif // MINIDUMP_H + diff --git a/mp/src/public/tier0/platform.h b/mp/src/public/tier0/platform.h index 389ab5b8..652c27c0 100644 --- a/mp/src/public/tier0/platform.h +++ b/mp/src/public/tier0/platform.h @@ -9,6 +9,18 @@ #ifndef PLATFORM_H #define PLATFORM_H +#if defined(__x86_64__) || defined(_WIN64) +#define PLATFORM_64BITS 1 +#endif + +#if defined(__GCC__) || defined(__GNUC__) +#define COMPILER_GCC 1 +#endif + +#ifdef __clang__ +#define COMPILER_CLANG 1 +#endif + #if defined( _X360 ) #define NO_STEAM #define NO_VOICE @@ -51,14 +63,13 @@ // need this for _alloca #include #include - #include +#include #include #endif #include #include - // need this for memset #include @@ -148,10 +159,6 @@ typedef unsigned char uint8; typedef signed char int8; -#if defined(__x86_64__) || defined(_WIN64) - #define X64BITS -#endif // __x86_64__ - #if defined( _WIN32 ) typedef __int16 int16; @@ -191,7 +198,7 @@ typedef signed char int8; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; - #ifdef X64BITS + #ifdef PLATFORM_64BITS typedef long long intp; typedef unsigned long long uintp; #else @@ -202,17 +209,39 @@ typedef signed char int8; // Avoid redefinition warnings if a previous header defines this. #undef OVERRIDE - #if defined(__clang__) + #if __cplusplus >= 201103L #define OVERRIDE override - // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions] - // Disabling this warning is less intrusive than enabling C++11 extensions - #pragma GCC diagnostic ignored "-Wc++11-extensions" + #if defined(__clang__) + // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions] + // Disabling this warning is less intrusive than enabling C++11 extensions + #pragma GCC diagnostic ignored "-Wc++11-extensions" + #endif #else #define OVERRIDE #endif #endif // else _WIN32 +//----------------------------------------------------------------------------- +// Set up platform type defines. +//----------------------------------------------------------------------------- +#if defined( PLATFORM_X360 ) || defined( _PS3 ) + #if !defined( _GAMECONSOLE ) + #define _GAMECONSOLE + #endif + #define IsPC() false + #define IsGameConsole() true +#else + #define IsPC() true + #define IsGameConsole() false +#endif + +#ifdef PLATFORM_64BITS + #define IsPlatform64Bits() true +#else + #define IsPlatform64Bits() false +#endif + // From steam/steamtypes.h // RTime32 // We use this 32 bit time representing real world time. @@ -407,6 +436,13 @@ typedef void * HINSTANCE; #define DebuggerBreakIfDebugging_StagingOnly() #endif +// Allows you to specify code that should only execute if we are in a staging build. Otherwise the code noops. +#ifdef STAGING_ONLY +#define STAGING_ONLY_EXEC( _exec ) do { _exec; } while (0) +#else +#define STAGING_ONLY_EXEC( _exec ) do { } while (0) +#endif + // C functions for external declarations that call the appropriate C++ methods #ifndef EXPORT #ifdef _WIN32 @@ -1177,6 +1213,9 @@ struct CPUInformation tchar* m_szProcessorID; // Processor vendor Identification. + uint32 m_nModel; + uint32 m_nFeatures[3]; + CPUInformation(): m_Size(0){} }; diff --git a/mp/src/public/tier0/stacktools.h b/mp/src/public/tier0/stacktools.h new file mode 100644 index 00000000..c356b8c0 --- /dev/null +++ b/mp/src/public/tier0/stacktools.h @@ -0,0 +1,153 @@ +//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============// +// +// Purpose: Tools for grabbing/dumping the stack at runtime +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TIER0_STACKTOOLS_H +#define TIER0_STACKTOOLS_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/platform.h" + +#if (defined( PLATFORM_WINDOWS ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT ) && defined( TCHAR_IS_CHAR ) //designed for windows/x360, not built/tested with wide characters, not intended for release builds (but probably wouldn't damage anything) +# define ENABLE_RUNTIME_STACK_TRANSLATION //uncomment to enable runtime stack translation tools. All of which use on-demand loading of necessary dll's and pdb's +#endif + +#if defined( ENABLE_RUNTIME_STACK_TRANSLATION ) +//#define ENABLE_THREAD_PARENT_STACK_TRACING 1 //uncomment to actually enable tracking stack traces from threads and jobs to their parent thread. Must also define THREAD_PARENT_STACK_TRACE_SUPPORTED in threadtools.h +# if defined( ENABLE_THREAD_PARENT_STACK_TRACING ) +# define THREAD_PARENT_STACK_TRACE_LENGTH 32 +# endif +#endif + + + + +PLATFORM_INTERFACE int GetCallStack( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +//ONLY WORKS IF THE CRAWLED PORTION OF THE STACK DISABLES FRAME POINTER OMISSION (/Oy-) "vpc /nofpo" +PLATFORM_INTERFACE int GetCallStack_Fast( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +typedef int (*FN_GetCallStack)( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +//where we'll find our PDB's for win32. +PLATFORM_INTERFACE void SetStackTranslationSymbolSearchPath( const char *szSemicolonSeparatedList = NULL ); +PLATFORM_INTERFACE void StackToolsNotify_LoadedLibrary( const char *szLibName ); + +//maximum output sample "tier0.dll!TranslateStackInfo - u:\Dev\L4D\src\tier0\stacktools.cpp(162) + 4 bytes" +enum TranslateStackInfo_StyleFlags_t +{ + TSISTYLEFLAG_NONE = 0, + TSISTYLEFLAG_MODULENAME = (1<<0), //start with module Sample: "tier0.dll!" + TSISTYLEFLAG_SYMBOLNAME = (1<<1), //include the symbol name Sample: "TranslateStackInfo" + TSISTYLEFLAG_FULLPATH = (1<<2), //include full path Sample: "u:\Dev\L4D\src\tier0\stacktools.cpp" + TSISTYLEFLAG_SHORTPATH = (1<<3), //only include 2 directories Sample: "\src\tier0\stacktools.cpp" + TSISTYLEFLAG_LINE = (1<<4), //file line number Sample: "(162)" + TSISTYLEFLAG_LINEANDOFFSET = (1<<5), //file line + offset Sample: "(162) + 4 bytes" + TSISTYLEFLAG_LAST = TSISTYLEFLAG_LINEANDOFFSET, + TSISTYLEFLAG_DEFAULT = (TSISTYLEFLAG_MODULENAME | TSISTYLEFLAG_SYMBOLNAME | TSISTYLEFLAG_FULLPATH | TSISTYLEFLAG_LINEANDOFFSET), //produces sample above +}; + +//Generates a formatted list of function information, returns number of translated entries +//On 360 this generates a string that can be decoded by VXConsole in print functions. Optimal path for translation because it's one way. Other paths require multiple transactions. +PLATFORM_INTERFACE int TranslateStackInfo( const void * const *pCallStack, int iCallStackCount, tchar *szOutput, int iOutBufferSize, const tchar *szEntrySeparator, TranslateStackInfo_StyleFlags_t style = TSISTYLEFLAG_DEFAULT ); + +PLATFORM_INTERFACE void PreloadStackInformation( void * const *pAddresses, int iAddressCount ); //caches data and reduces communication with VXConsole to speed up 360 decoding when using any of the Get***FromAddress() functions. Nop on PC. +PLATFORM_INTERFACE bool GetFileAndLineFromAddress( const void *pAddress, tchar *pFileNameOut, int iMaxFileNameLength, uint32 &iLineNumberOut, uint32 *pDisplacementOut = NULL ); +PLATFORM_INTERFACE bool GetSymbolNameFromAddress( const void *pAddress, tchar *pSymbolNameOut, int iMaxSymbolNameLength, uint64 *pDisplacementOut = NULL ); +PLATFORM_INTERFACE bool GetModuleNameFromAddress( const void *pAddress, tchar *pModuleNameOut, int iMaxModuleNameLength ); + + + +class PLATFORM_CLASS CCallStackStorage //a helper class to grab a stack trace as close to the leaf code surface as possible, then pass it on to deeper functions intact with less unpredictable inlining pollution +{ +public: + CCallStackStorage( FN_GetCallStack GetStackFunction = GetCallStack, uint32 iSkipCalls = 0 ); + CCallStackStorage( const CCallStackStorage ©From ) + { + iValidEntries = copyFrom.iValidEntries; + memcpy( pStack, copyFrom.pStack, sizeof( void * ) * copyFrom.iValidEntries ); + } + + void *pStack[128]; //probably too big, possibly too small for some applications. Don't want to spend the time figuring out how to generalize this without templatizing pollution or mallocs + uint32 iValidEntries; +}; + + +//Hold onto one of these to denote the top of a functional stack trace. Also allows us to string together threads to their parents +class PLATFORM_CLASS CStackTop_Base +{ +protected: +#if defined( ENABLE_RUNTIME_STACK_TRANSLATION ) + CStackTop_Base *m_pPrevTop; + void *m_pStackBase; + void *m_pReplaceAddress; + + void * const *m_pParentStackTrace; + int m_iParentStackTraceLength; +#endif +}; + +//makes a copy of the parent stack +class PLATFORM_CLASS CStackTop_CopyParentStack : public CStackTop_Base +{ +public: + CStackTop_CopyParentStack( void * const * pParentStackTrace, int iParentStackTraceLength ); + ~CStackTop_CopyParentStack( void ); +}; + +//just references the parent stack. Assuming that you'll keep that memory around as long as you're keeping this Stack Top marker. +class PLATFORM_CLASS CStackTop_ReferenceParentStack : public CStackTop_Base +{ +public: + CStackTop_ReferenceParentStack( void * const * pParentStackTrace = NULL, int iParentStackTraceLength = 0 ); + ~CStackTop_ReferenceParentStack( void ); + void ReleaseParentStackReferences( void ); //in case you need to delete the parent stack trace before this class goes out of scope +}; + + +//Encodes data so that every byte's most significant bit is a 1. Ensuring no null terminators. +//This puts the encoded data in the 128-255 value range. Leaving all standard ascii characters for control. +//Returns string length (not including the written null terminator as is standard). +//Or if the buffer is too small. Returns negative of necessary buffer size (including room needed for null terminator) +PLATFORM_INTERFACE int EncodeBinaryToString( const void *pToEncode, int iDataLength, char *pEncodeOut, int iEncodeBufferSize ); + +//Decodes a string produced by EncodeBinaryToString(). Safe to decode in place if you don't mind trashing your string, binary byte count always less than string byte count. +//Returns: +// >= 0 is the decoded data size +// INT_MIN (most negative value possible) indicates an improperly formatted string (not our data) +// all other negative values are the negative of how much dest buffer size is necessary. +PLATFORM_INTERFACE int DecodeBinaryFromString( const char *pString, void *pDestBuffer, int iDestBufferSize, char **ppParseFinishOut = NULL ); + + + + +// 360<->VXConsole specific communication definitions +#define XBX_CALLSTACKDECODEPREFIX ":CSDECODE[" + +enum StackTranslation_BinaryHandler_Command_t +{ + ST_BHC_LOADEDLIBARY, + ST_BHC_GETTRANSLATIONINFO, +}; + +#pragma pack(push) +#pragma pack(1) +struct FullStackInfo_t +{ + const void *pAddress; + char szModuleName[24]; + char szFileName[MAX_PATH/2]; + char szSymbol[64]; + uint32 iLine; + uint32 iSymbolOffset; + +}; +#pragma pack(pop) + +#endif //#ifndef TIER0_STACKTOOLS_H diff --git a/mp/src/public/tier0/threadtools.h b/mp/src/public/tier0/threadtools.h index 7a69f0c6..e5b720e2 100644 --- a/mp/src/public/tier0/threadtools.h +++ b/mp/src/public/tier0/threadtools.h @@ -233,7 +233,7 @@ inline void const *ThreadInterlockedExchangePointerToConst( void const * volatil inline void const *ThreadInterlockedCompareExchangePointerToConst( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedCompareExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } inline bool ThreadInterlockedAssignPointerToConstIf( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedAssignPointerIf( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } -#if defined( X64BITS ) +#if defined( PLATFORM_64BITS ) #if defined (_WIN32) typedef __m128i int128; inline int128 int128_zero() { return _mm_setzero_si128(); } @@ -289,6 +289,30 @@ PLATFORM_INTERFACE void ThreadNotifySyncReleasing(void *p); // work in a DLL loaded with LoadLibrary() //----------------------------------------------------------------------------- +#ifndef NO_THREAD_LOCAL + +#if defined(_LINUX) && !defined(OSX) +// linux totally supports compiler thread locals, even across dll's. +#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1 +#define CTHREADLOCALINTEGER( typ ) __thread int +#define CTHREADLOCALINT __thread int +#define CTHREADLOCALPTR( typ ) __thread typ * +#define CTHREADLOCAL( typ ) __thread typ +#define GETLOCAL( x ) ( x ) +#endif // _LINUX && !OSX + +#if defined(WIN32) || defined(OSX) +#ifndef __AFXTLS_H__ // not compatible with some Windows headers +#define CTHREADLOCALINT CThreadLocalInt +#define CTHREADLOCALINTEGER( typ ) CThreadLocalInt +#define CTHREADLOCALPTR( typ ) CThreadLocalPtr +#define CTHREADLOCAL( typ ) CThreadLocal +#define GETLOCAL( x ) ( x.Get() ) +#endif +#endif // WIN32 || OSX + +#endif // NO_THREAD_LOCALS + #ifndef __AFXTLS_H__ // not compatible with some Windows headers #ifndef NO_THREAD_LOCAL @@ -484,7 +508,7 @@ public: bool operator==( T *rhs ) const { return ( m_value == rhs ); } bool operator!=( T *rhs ) const { return ( m_value != rhs ); } -#ifdef X64BITS +#if defined( PLATFORM_64BITS ) T *operator++() { return ((T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) )) + 1; } T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) ); } @@ -523,6 +547,41 @@ private: T * volatile m_value; }; +//----------------------------------------------------------------------------- +// +// Platform independent verification that multiple threads aren't getting into the same code at the same time. +// Note: This is intended for use to identify problems, it doesn't provide any sort of thread safety. +// +//----------------------------------------------------------------------------- +class ReentrancyVerifier +{ +public: + inline ReentrancyVerifier(CInterlockedInt* counter, int sleepTimeMS) + : mCounter(counter) + { + Assert(mCounter != NULL); + + if (++(*mCounter) != 1) { + DebuggerBreakIfDebugging_StagingOnly(); + } + + if (sleepTimeMS > 0) + { + ThreadSleep(sleepTimeMS); + } + } + + inline ~ReentrancyVerifier() + { + if (--(*mCounter) != 0) { + DebuggerBreakIfDebugging_StagingOnly(); + } + } + +private: + CInterlockedInt* mCounter; +}; + //----------------------------------------------------------------------------- // diff --git a/mp/src/public/tier0/vprof.h b/mp/src/public/tier0/vprof.h index 9464e4ad..1c7321bb 100644 --- a/mp/src/public/tier0/vprof.h +++ b/mp/src/public/tier0/vprof.h @@ -140,6 +140,8 @@ #define VPROF_BUDGETGROUP_TENFOOT VPROF_BUDGETGROUP_HTMLSURFACE #define VPROF_BUDGETGROUP_STEAMUI VPROF_BUDGETGROUP_HTMLSURFACE #define VPROF_BUDGETGROUP_ATTRIBUTES _T("Attributes") +#define VPROF_BUDGETGROUP_FINDATTRIBUTE _T("FindAttribute") +#define VPROF_BUDGETGROUP_FINDATTRIBUTEUNSAFE _T("FindAttributeUnsafe") #ifdef _X360 // update flags diff --git a/mp/src/public/tier0/vprof_telemetry.h b/mp/src/public/tier0/vprof_telemetry.h index a7758cf4..c60bde5d 100644 --- a/mp/src/public/tier0/vprof_telemetry.h +++ b/mp/src/public/tier0/vprof_telemetry.h @@ -133,7 +133,7 @@ public: float time = ( tmFastTime() - time0 ) * g_Telemetry.flRDTSCToMilliSeconds; if( time >= m_threshold ) { - tmMessage( TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(dota/spike)%s %.2fms %t", m_message, time, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) ); + tmMessage( TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(source/spike)%s %.2fms %t", m_message, time, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) ); } } diff --git a/mp/src/public/tier0/wchartypes.h b/mp/src/public/tier0/wchartypes.h index 9803870c..814470fd 100644 --- a/mp/src/public/tier0/wchartypes.h +++ b/mp/src/public/tier0/wchartypes.h @@ -88,6 +88,14 @@ typedef char tchar; #define TCHAR_IS_CHAR #endif +#if defined( _MSC_VER ) || defined( WIN32 ) +typedef wchar_t uchar16; +typedef unsigned int uchar32; +#else +typedef unsigned short uchar16; +typedef wchar_t uchar32; +#endif + #ifdef FORCED_UNICODE #undef _UNICODE #endif diff --git a/mp/src/public/tier1/KeyValues.h b/mp/src/public/tier1/KeyValues.h index 0fdffb08..97ae69c2 100644 --- a/mp/src/public/tier1/KeyValues.h +++ b/mp/src/public/tier1/KeyValues.h @@ -120,8 +120,8 @@ public: // File access. Set UsesEscapeSequences true, if resource file/buffer uses Escape Sequences (eg \n, \t) void UsesEscapeSequences(bool state); // default false void UsesConditionals(bool state); // default true - bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL ); - bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool sortKeys = false, bool bAllowEmptyString = false ); + bool LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool refreshCache = false ); + bool SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID = NULL, bool sortKeys = false, bool bAllowEmptyString = false, bool bCacheResult = false ); // Read from a buffer... Note that the buffer must be null terminated bool LoadFromBuffer( char const *resourceName, const char *pBuffer, IBaseFileSystem* pFileSystem = NULL, const char *pPathID = NULL ); @@ -144,6 +144,8 @@ public: // KeyValues *GetFirstSubKey() { return m_pSub; } // returns the first subkey in the list KeyValues *GetNextKey() { return m_pPeer; } // returns the next subkey + const KeyValues *GetNextKey() const { return m_pPeer; } // returns the next subkey + void SetNextKey( KeyValues * pDat); KeyValues *FindLastSubKey(); // returns the LAST subkey in the list. This requires a linked list iteration to find the key. Returns NULL if we don't have any children @@ -203,7 +205,7 @@ public: void operator delete( void *pMem ); void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ); - KeyValues& operator=( KeyValues& src ); + KeyValues& operator=( const KeyValues& src ); // Adds a chain... if we don't find stuff in this keyvalue, we'll look // in the one we're chained to. @@ -217,6 +219,10 @@ public: // Allocate & create a new copy of the keys KeyValues *MakeCopy( void ) const; + // Allocate & create a new copy of the keys, including the next keys. This is useful for top level files + // that don't use the usual convention of a root key with lots of children (like soundscape files). + KeyValues *MakeCopy( bool copySiblings ) const; + // Make a new copy of all subkeys, add them all to the passed-in keyvalues void CopySubkeys( KeyValues *pParent ) const; @@ -270,7 +276,9 @@ private: KeyValues* CreateKeyUsingKnownLastChild( const char *keyName, KeyValues *pLastChild ); void AddSubkeyUsingKnownLastChild( KeyValues *pSubKey, KeyValues *pLastChild ); - void RecursiveCopyKeyValues( KeyValues& src ); + void CopyKeyValuesFromRecursive( const KeyValues& src ); + void CopyKeyValue( const KeyValues& src, size_t tmpBufferSizeB, char* tmpBuffer ); + void RemoveEverything(); // void RecursiveSaveToFile( IBaseFileSystem *filesystem, CUtlBuffer &buffer, int indentLevel ); // void WriteConvertedString( CUtlBuffer &buffer, const char *pszString ); diff --git a/mp/src/public/tier1/lzmaDecoder.h b/mp/src/public/tier1/lzmaDecoder.h index 51ecfd1a..6f4b87fd 100644 --- a/mp/src/public/tier1/lzmaDecoder.h +++ b/mp/src/public/tier1/lzmaDecoder.h @@ -1,15 +1,22 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// // -// LZMA Decoder. Designed for run time decoding. +// LZMA Codec interface for engine. // -// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) -// http://www.7-zip.org/ +// LZMA SDK 9.38 beta +// 2015-01-03 : Igor Pavlov : Public domain +// http://www.7-zip.org/ // -//=====================================================================================// +//========================================================================// #ifndef _LZMADECODER_H #define _LZMADECODER_H #pragma once +// Thanks for the useful define namespacing, LZMA +#include "../../utils/lzma/C/7zVersion.h" +#define LZMA_SDK_VERSION_MAJOR MY_VER_MAJOR +#define LZMA_SDK_VERSION_MINOR MY_VER_MINOR + #if !defined( _X360 ) #define LZMA_ID (('A'<<24)|('M'<<16)|('Z'<<8)|('L')) #else @@ -27,15 +34,69 @@ struct lzma_header_t }; #pragma pack() +class CLZMAStream; + class CLZMA { public: - unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); - bool IsCompressed( unsigned char *pInput ); - unsigned int GetActualSize( unsigned char *pInput ); + static unsigned int Uncompress( unsigned char *pInput, unsigned char *pOutput ); + static bool IsCompressed( unsigned char *pInput ); + static unsigned int GetActualSize( unsigned char *pInput ); +}; + +// For files besides the implementation, we forward declare a dummy struct. We can't unconditionally forward declare +// this because LzmaEnc.h typedefs this directly to an unnamed struct :-/ +#ifndef CLzmaDec_t +struct _CLzmaDec_t; +#define CLzmaDec_t struct _CLzmaDec_t +#endif + +class CLZMAStream +{ +public: + CLZMAStream(); + ~CLZMAStream(); + + // Initialize a stream to read data from a LZMA style zip file, passing the original size from the zip headers. + // Streams with a source-engine style header (lzma_header_t) do not need an init call. + void InitZIPHeader( unsigned int nCompressedSize, unsigned int nOriginalSize ); + + // Attempt to read up to nMaxInputBytes from the compressed stream, writing up to nMaxOutputBytes to pOutput. + // Makes progress until blocked on input or output. + // Returns false if read stops due to an error or if called at EOF (GetExpectedBytesRemaining == 0) + bool Read( unsigned char *pInput, unsigned int nMaxInputBytes, + unsigned char *pOutput, unsigned int nMaxOutputBytes, + /* out */ unsigned int &nCompressedBytesRead, /* out */ unsigned int &nOutputBytesWritten ); + + // Get the expected uncompressed bytes yet to be read from this stream. Returns false if not yet known, such as + // before being fed the header. + bool GetExpectedBytesRemaining( /* out */ unsigned int &nBytesRemaining ); private: + enum eHeaderParse + { + eHeaderParse_OK, + eHeaderParse_Fail, + eHeaderParse_NeedMoreBytes + }; + + eHeaderParse TryParseHeader( unsigned char *pInput, unsigned int nBytesAvailable, /* out */ unsigned int &nBytesConsumed ); + + void FreeDecoderState(); + bool CreateDecoderState( const unsigned char *pProperties ); + + // Init from a zip-embedded LZMA stream. Requires the original size be passed from zip headers. + CLzmaDec_t *m_pDecoderState; + + unsigned int m_nActualSize; + unsigned int m_nActualBytesRead; + unsigned int m_nCompressedSize; + unsigned int m_nCompressedBytesRead; + + // If we have read past the header + bool m_bParsedHeader : 1; + // If InitZIPHeader() was called. We're expecting a zip-style header and have size information. + bool m_bZIPStyleHeader : 1; }; #endif - diff --git a/mp/src/public/tier1/refcount.h b/mp/src/public/tier1/refcount.h index 264da100..9c756b84 100644 --- a/mp/src/public/tier1/refcount.h +++ b/mp/src/public/tier1/refcount.h @@ -14,6 +14,40 @@ #pragma once #endif +template +inline void SafeAssign(T** ppInoutDst, T* pInoutSrc ) +{ + Assert( ppInoutDst ); + + // Do addref before release + if ( pInoutSrc ) + ( pInoutSrc )->AddRef(); + + // Do addref before release + if ( *ppInoutDst ) + ( *ppInoutDst )->Release(); + + // Do the assignment + ( *ppInoutDst ) = pInoutSrc; +} + +template +inline void SafeAddRef( T* pObj ) +{ + if ( pObj ) + pObj->AddRef(); +} + +template +inline void SafeRelease( T** ppInoutPtr ) +{ + Assert( ppInoutPtr ); + if ( *ppInoutPtr ) + ( *ppInoutPtr )->Release(); + + ( *ppInoutPtr ) = NULL; +} + //----------------------------------------------------------------------------- // Purpose: Implement a standard reference counted interface. Use of this // is optional insofar as all the concrete tools only require diff --git a/mp/src/public/tier1/strtools.h b/mp/src/public/tier1/strtools.h index 035789f9..12e0a0c4 100644 --- a/mp/src/public/tier1/strtools.h +++ b/mp/src/public/tier1/strtools.h @@ -151,6 +151,26 @@ inline bool StringHasPrefix ( const char *str, const char *prefix ) inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; } +template< bool CASE_SENSITIVE > inline bool _V_strEndsWithInner( const char *pStr, const char *pSuffix ) +{ + int nSuffixLen = V_strlen( pSuffix ); + int nStringLen = V_strlen( pStr ); + if ( nSuffixLen == 0 ) + return true; // All strings end with the empty string (matches Java & .NET behaviour) + if ( nStringLen < nSuffixLen ) + return false; + pStr += nStringLen - nSuffixLen; + if ( CASE_SENSITIVE ) + return !V_strcmp( pStr, pSuffix ); + else + return !V_stricmp( pStr, pSuffix ); +} + +// Does 'pStr' end with 'pSuffix'? (case sensitive/insensitive variants) +inline bool V_strEndsWith( const char *pStr, const char *pSuffix ) { return _V_strEndsWithInner( pStr, pSuffix ); } +inline bool V_striEndsWith( const char *pStr, const char *pSuffix ) { return _V_strEndsWithInner( pStr, pSuffix ); } + + // Normalizes a float string in place. // (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible) void V_normalizeFloatString( char* pFloat ); @@ -220,6 +240,15 @@ template void V_strcpy_safe( OUT_Z_ARRAY char (&pDest)[ma V_strncpy( pDest, pSrc, (int)maxLenInChars ); } +// A function which duplicates a string using new[] to allocate the new string. +inline char *V_strdup( const char *pSrc ) +{ + int nLen = V_strlen( pSrc ); + char *pResult = new char [ nLen+1 ]; + V_memcpy( pResult, pSrc, nLen+1 ); + return pResult; +} + void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ); template void V_wcscpy_safe( OUT_Z_ARRAY wchar_t (&pDest)[maxLenInChars], wchar_t const *pSrc ) { @@ -245,6 +274,164 @@ template char *V_strlwr_safe( INOUT_Z_ARRAY char (&pBuf)[cchDes return _V_strnlwr( pBuf, (int)cchDest ); } +// Unicode string conversion policies - what to do if an illegal sequence is encountered +enum EStringConvertErrorPolicy +{ + _STRINGCONVERTFLAG_SKIP = 1, + _STRINGCONVERTFLAG_FAIL = 2, + _STRINGCONVERTFLAG_ASSERT = 4, + + STRINGCONVERT_REPLACE = 0, + STRINGCONVERT_SKIP = _STRINGCONVERTFLAG_SKIP, + STRINGCONVERT_FAIL = _STRINGCONVERTFLAG_FAIL, + + STRINGCONVERT_ASSERT_REPLACE = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_REPLACE, + STRINGCONVERT_ASSERT_SKIP = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_SKIP, + STRINGCONVERT_ASSERT_FAIL = _STRINGCONVERTFLAG_ASSERT + STRINGCONVERT_FAIL, +}; + +// Unicode (UTF-8, UTF-16, UTF-32) fundamental conversion functions. +bool Q_IsValidUChar32( uchar32 uValue ); +int Q_UChar32ToUTF8Len( uchar32 uValue ); +int Q_UChar32ToUTF8( uchar32 uValue, char *pOut ); +int Q_UChar32ToUTF16Len( uchar32 uValue ); +int Q_UChar32ToUTF16( uchar32 uValue, uchar16 *pOut ); + +// Validate that a Unicode string is well-formed and contains only valid code points +bool Q_UnicodeValidate( const char *pUTF8 ); +bool Q_UnicodeValidate( const uchar16 *pUTF16 ); +bool Q_UnicodeValidate( const uchar32 *pUTF32 ); + +// Returns length of string in Unicode code points (printed glyphs or non-printing characters) +int Q_UnicodeLength( const char *pUTF8 ); +int Q_UnicodeLength( const uchar16 *pUTF16 ); +int Q_UnicodeLength( const uchar32 *pUTF32 ); + +// Returns length of string in elements, not characters! These are analogous to Q_strlen and Q_wcslen +inline int Q_strlen16( const uchar16 *puc16 ) { int nElems = 0; while ( puc16[nElems] ) ++nElems; return nElems; } +inline int Q_strlen32( const uchar32 *puc32 ) { int nElems = 0; while ( puc32[nElems] ) ++nElems; return nElems; } + + +// Repair invalid Unicode strings by dropping truncated characters and fixing improperly-double-encoded UTF-16 sequences. +// Unlike conversion functions which replace with '?' by default, a repair operation assumes that you know that something +// is wrong with the string (eg, mid-sequence truncation) and you just want to do the best possible job of cleaning it up. +// You can pass a REPLACE or FAIL policy if you would prefer to replace characters with '?' or clear the entire string. +// Returns nonzero on success, or 0 if the policy is FAIL and an invalid sequence was found. +int Q_UnicodeRepair( char *pUTF8, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_SKIP ); +int Q_UnicodeRepair( uchar16 *pUTF16, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_SKIP ); +int Q_UnicodeRepair( uchar32 *pUTF32, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_SKIP ); + +// Advance pointer forward by N Unicode code points (printed glyphs or non-printing characters), stopping at terminating null if encountered. +char *Q_UnicodeAdvance( char *pUTF8, int nCharacters ); +uchar16 *Q_UnicodeAdvance( uchar16 *pUTF16, int nCharactersnCharacters ); +uchar32 *Q_UnicodeAdvance( uchar32 *pUTF32, int nChars ); +inline const char *Q_UnicodeAdvance( const char *pUTF8, int nCharacters ) { return Q_UnicodeAdvance( (char*) pUTF8, nCharacters ); } +inline const uchar16 *Q_UnicodeAdvance( const uchar16 *pUTF16, int nCharacters ) { return Q_UnicodeAdvance( (uchar16*) pUTF16, nCharacters ); } +inline const uchar32 *Q_UnicodeAdvance( const uchar32 *pUTF32, int nCharacters ) { return Q_UnicodeAdvance( (uchar32*) pUTF32, nCharacters ); } + +// Truncate to maximum of N Unicode code points (printed glyphs or non-printing characters) +inline void Q_UnicodeTruncate( char *pUTF8, int nCharacters ) { *Q_UnicodeAdvance( pUTF8, nCharacters ) = 0; } +inline void Q_UnicodeTruncate( uchar16 *pUTF16, int nCharacters ) { *Q_UnicodeAdvance( pUTF16, nCharacters ) = 0; } +inline void Q_UnicodeTruncate( uchar32 *pUTF32, int nCharacters ) { *Q_UnicodeAdvance( pUTF32, nCharacters ) = 0; } + + +// Conversion between Unicode string types (UTF-8, UTF-16, UTF-32). Deals with bytes, not element counts, +// to minimize harm from the programmer mistakes which continue to plague our wide-character string code. +// Returns the number of bytes written to the output, or if output is NULL, the number of bytes required. +int Q_UTF8ToUTF16( const char *pUTF8, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF8ToUTF32( const char *pUTF8, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF16ToUTF8( const uchar16 *pUTF16, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF16ToUTF32( const uchar16 *pUTF16, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF32ToUTF8( const uchar32 *pUTF32, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF32ToUTF16( const uchar32 *pUTF32, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); + +// This is disgusting and exist only easily to facilitate having 16-bit and 32-bit wchar_t's on different platforms +int Q_UTF32ToUTF32( const uchar32 *pUTF32Source, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar32 *pUTF32Dest, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); + +// Conversion between count-limited UTF-n character arrays, including any potential NULL characters. +// Output has a terminating NULL for safety; strip the last character if you want an unterminated string. +// Returns the number of bytes written to the output, or if output is NULL, the number of bytes required. +int Q_UTF8CharsToUTF16( const char *pUTF8, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF8CharsToUTF32( const char *pUTF8, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF16CharsToUTF8( const uchar16 *pUTF16, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF16CharsToUTF32( const uchar16 *pUTF16, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF32CharsToUTF8( const uchar32 *pUTF32, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); +int Q_UTF32CharsToUTF16( const uchar32 *pUTF32, int nElements, OUT_Z_BYTECAP(cubDestSizeInBytes) uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy = STRINGCONVERT_ASSERT_REPLACE ); + +// Decode a single UTF-8 character to a uchar32, returns number of UTF-8 bytes parsed +int Q_UTF8ToUChar32( const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut ); + +// Decode a single UTF-16 character to a uchar32, returns number of UTF-16 characters (NOT BYTES) consumed +int Q_UTF16ToUChar32( const uchar16 *pUTF16, uchar32 &uValueOut, bool &bErrorOut ); + + +// NOTE: WString means either UTF32 or UTF16 depending on the platform and compiler settings. +#if defined( _MSC_VER ) || defined( _WIN32 ) +#define Q_UTF8ToWString Q_UTF8ToUTF16 +#define Q_UTF8CharsToWString Q_UTF8CharsToUTF16 +#define Q_UTF32ToWString Q_UTF32ToUTF16 +#define Q_WStringToUTF8 Q_UTF16ToUTF8 +#define Q_WStringCharsToUTF8 Q_UTF16CharsToUTF8 +#define Q_WStringToUTF32 Q_UTF16ToUTF32 +#else +#define Q_UTF8ToWString Q_UTF8ToUTF32 +#define Q_UTF8CharsToWString Q_UTF8CharsToUTF32 +#define Q_UTF32ToWString Q_UTF32ToUTF32 +#define Q_WStringToUTF8 Q_UTF32ToUTF8 +#define Q_WStringCharsToUTF8 Q_UTF32CharsToUTF8 +#define Q_WStringToUTF32 Q_UTF32ToUTF32 +#endif + +// These are legacy names which don't make a lot of sense but are used everywhere. Prefer the WString convention wherever possible +#define V_UTF8ToUnicode Q_UTF8ToWString +#define V_UnicodeToUTF8 Q_WStringToUTF8 + + +#ifdef WIN32 +// This function is ill-defined as it relies on the current ANSI code page. Currently Win32 only for tools. +int Q_LocaleSpecificANSIToUTF8( const char *pANSI, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes ); +#endif + +// Windows-1252 is mostly the same as ISO Latin-1, and probably what you want if you are +// saddled with an 8-bit ANSI string that originated on a Windows system. +int Q_Windows1252CharsToUTF8( const char *pchSrc, int cchSrc, OUT_Z_BYTECAP(cchDestUTF8) char *pchDestUTF8, int cchDestUTF8 ); + +// CP 437 is used for VGA console text and some old-school file formats such as ZIP. It +// is also known as the "IBM PC OEM code page" and various related names. You probably +// don't want to use this function unless you know for a fact that you're dealing with +// old-school OEM code pages. Otherwise try the Windows-1252 function above. +int Q_CP437CharsToUTF8( const char *pchSrc, int cchSrc, OUT_Z_BYTECAP(cchDestUTF8) char *pchDestUTF8, int cchDestUTF8 ); + +// replaces characters in a UTF8 string with their identical-looking equivalent (non-roundtrippable) +// +// older version of API uses a small homoglyph table; newer version uses a larger one +// +// strings using old version are baked into the database, so we won't toss it quite yet, +// but don't use it for new features. +int Q_NormalizeUTF8Old( const char *pchSrc, OUT_Z_CAP(cchDest) char *pchDest, int cchDest ); +int Q_NormalizeUTF8( const char *pchSrc, OUT_Z_CAP(cchDest) char *pchDest, int cchDest ); + +//----------------------------------------------------------------------------- +// Purpose: replaces characters in a UTF8 string with similar-looking equivalents. +// Only replaces with ASCII characters.. non-recognized characters will be replaced with ? +// This operation is destructive (i.e. you can't roundtrip through the normalized +// form). +//----------------------------------------------------------------------------- +template int Q_NormalizeUTF8ToASCII( OUT_Z_ARRAY char (&pchDest)[maxLenInChars], const char *pchSrc ) +{ + int nResult = Q_NormalizeUTF8( pchSrc, pchDest, maxLenInChars ); + + // replace non ASCII characters with ? + for ( int i = 0; i < nResult; i++ ) + { + if ( pchDest[i] > 127 || pchDest[i] < 0 ) + { + pchDest[i] = '?'; + } + } + + return nResult; +} // UNDONE: Find a non-compiler-specific way to do this #ifdef _WIN32 @@ -321,13 +508,29 @@ char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek // Prints out a pretified integer with comma separators (eg, 7,233,270,000) char *V_pretifynum( int64 value ); -// conversion functions wchar_t <-> char, returning the number of characters converted -int V_UTF8ToUnicode( const char *pUTF8, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pwchDest, int cubDestSizeInBytes ); -int V_UnicodeToUTF8( const wchar_t *pUnicode, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes ); -int V_UCS2ToUnicode( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pUnicode, int cubDestSizeInBytes ); -int V_UCS2ToUTF8( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes ); -int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUCS2, int cubDestSizeInBytes ); -int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) ucs2 *pUCS2, int cubDestSizeInBytes ); +int _V_UCS2ToUnicode( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pUnicode, int cubDestSizeInBytes ); +template< typename T > inline int V_UCS2ToUnicode( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) wchar_t *pUnicode, T cubDestSizeInBytes ) +{ + return _V_UCS2ToUnicode( pUCS2, pUnicode, static_cast(cubDestSizeInBytes) ); +} + +int _V_UCS2ToUTF8( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, int cubDestSizeInBytes ); +template< typename T > inline int V_UCS2ToUTF8( const ucs2 *pUCS2, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUTF8, T cubDestSizeInBytes ) +{ + return _V_UCS2ToUTF8( pUCS2, pUTF8, static_cast(cubDestSizeInBytes) ); +} + +int _V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUCS2, int cubDestSizeInBytes ); +template< typename T, typename U > inline int V_UnicodeToUCS2( const wchar_t *pUnicode, T cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) char *pUCS2, U cubDestSizeInBytes ) +{ + return _V_UnicodeToUCS2( pUnicode, static_cast(cubSrcInBytes), pUCS2, static_cast(cubDestSizeInBytes) ); +} + +int _V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) ucs2 *pUCS2, int cubDestSizeInBytes ); +template< typename T, typename U > inline int V_UTF8ToUCS2( const char *pUTF8, T cubSrcInBytes, OUT_Z_BYTECAP(cubDestSizeInBytes) ucs2 *pUCS2, U cubDestSizeInBytes ) +{ + return _V_UTF8ToUCS2( pUTF8, static_cast(cubSrcInBytes), pUCS2, static_cast(cubDestSizeInBytes) ); +} // strips leading and trailing whitespace; returns true if any characters were removed. UTF-8 and UTF-16 versions. bool Q_StripPrecedingAndTrailingWhitespace( char *pch ); @@ -573,6 +776,7 @@ public: m_pwch = NULL; #if !defined( WIN32 ) && !defined(_WIN32) m_pucs2 = NULL; + m_bCreatedUCS2 = false; #endif m_bCreatedUTF16 = false; } @@ -584,6 +788,7 @@ public: m_pwch = pwch; #if !defined( WIN32 ) && !defined(_WIN32) m_pucs2 = NULL; + m_bCreatedUCS2 = false; #endif m_bCreatedUTF16 = true; } @@ -594,7 +799,8 @@ public: m_pch = NULL; m_pwch = NULL; m_pucs2 = pwch; - m_bCreatedUTF16 = true; + m_bCreatedUCS2 = true; + m_bCreatedUTF16 = false; } #endif @@ -652,6 +858,10 @@ public: { delete [] m_pwch; } +#if !defined( WIN32 ) && !defined(_WIN32) + if ( !m_bCreatedUCS2 && m_pucs2 ) + delete [] m_pucs2; +#endif } private: @@ -730,6 +940,8 @@ private: // so we perform a second allocation that's just the size we need. void PopulateUCS2() { + if ( m_bCreatedUCS2 ) + return; if ( m_pch == NULL ) return; // no UTF-8 string to convert if ( m_pucs2 != NULL ) @@ -760,6 +972,7 @@ private: const wchar_t *m_pwch; #if !defined( WIN32 ) && !defined(_WIN32) const ucs2 *m_pucs2; + bool m_bCreatedUCS2; #endif // "created as UTF-16", means our owned string is the UTF-8 string not the UTF-16 one. bool m_bCreatedUTF16; @@ -868,4 +1081,11 @@ size_t Q_URLDecode( OUT_CAP(nDecodeDestLen) char *pchDecodeDest, int nDecodeDest #endif // !defined( VSTDLIB_DLL_EXPORT ) +#ifdef POSIX +#define FMT_WS L"%ls" +#else +#define FMT_WS L"%s" +#endif + + #endif // TIER1_STRTOOLS_H diff --git a/mp/src/public/tier1/utlarray.h b/mp/src/public/tier1/utlarray.h index 36850860..ce5ffe8b 100644 --- a/mp/src/public/tier1/utlarray.h +++ b/mp/src/public/tier1/utlarray.h @@ -43,6 +43,8 @@ class CUtlArray : public base_array_t { public: typedef T ElemType_t; + typedef T* iterator; + typedef const T* const_iterator; CUtlArray(); CUtlArray( T* pMemory, size_t count ); @@ -59,6 +61,13 @@ public: T& Random(); const T& Random() const; + // STL compatible member functions. These allow easier use of std::sort + // and they are forward compatible with the C++ 11 range-based for loops. + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + T* Base(); const T* Base() const; @@ -130,6 +139,30 @@ inline CUtlArray::CUtlArray( CUtlArray const& vec ) } } +template< typename T, size_t MAX_SIZE > +typename CUtlArray::iterator CUtlArray::begin() +{ + return Base(); +} + +template< typename T, size_t MAX_SIZE > +typename CUtlArray::const_iterator CUtlArray::begin() const +{ + return Base(); +} + +template< typename T, size_t MAX_SIZE > +typename CUtlArray::iterator CUtlArray::end() +{ + return Base() + Count(); +} + +template< typename T, size_t MAX_SIZE > +typename CUtlArray::const_iterator CUtlArray::end() const +{ + return Base() + Count(); +} + template< typename T, size_t MAX_SIZE > inline T *CUtlArray::Base() { diff --git a/mp/src/public/tier1/utlbuffer.h b/mp/src/public/tier1/utlbuffer.h index 4213dd6a..0de85fda 100644 --- a/mp/src/public/tier1/utlbuffer.h +++ b/mp/src/public/tier1/utlbuffer.h @@ -189,7 +189,16 @@ public: unsigned int GetUnsignedInt( ); float GetFloat( ); double GetDouble( ); - void GetString( char* pString, int nMaxChars = 0 ); + template void GetString( char( &pString )[maxLenInChars] ) + { + GetStringInternal( pString, maxLenInChars ); + } + + void GetStringManualCharCount( char *pString, size_t maxLenInChars ) + { + GetStringInternal( pString, maxLenInChars ); + } + void Get( void* pMem, int size ); void GetLine( char* pLine, int nMaxChars = 0 ); @@ -384,6 +393,7 @@ protected: // Call this to peek arbitrarily long into memory. It doesn't fail unless // it can't read *anything* new bool CheckArbitraryPeekGet( int nOffset, int &nIncrement ); + void GetStringInternal( char *pString, size_t maxLenInChars ); template void GetType( T& dest, const char *pszFmt ); template void GetTypeBin( T& dest ); diff --git a/mp/src/public/tier1/utllinkedlist.h b/mp/src/public/tier1/utllinkedlist.h index 822f0b36..46ac4a6f 100644 --- a/mp/src/public/tier1/utllinkedlist.h +++ b/mp/src/public/tier1/utllinkedlist.h @@ -679,7 +679,8 @@ I CUtlLinkedList::AllocInternal( bool multilist ) Assert( m_Memory.IsValidIterator( it ) ); if ( !m_Memory.IsValidIterator( it ) ) { - ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted memory allocator)\n" ) ); + // We rarely if ever handle alloc failure. Continuing leads to corruption. + Error( "CUtlLinkedList overflow! (exhausted memory allocator)\n" ); return InvalidIndex(); } } @@ -687,7 +688,8 @@ I CUtlLinkedList::AllocInternal( bool multilist ) // We can overflow before the utlmemory overflows, since S != I if ( !IndexInRange( m_Memory.GetIndex( it ) ) ) { - ExecuteNTimes( 10, Warning( "CUtlLinkedList overflow! (exhausted index range)\n" ) ); + // We rarely if ever handle alloc failure. Continuing leads to corruption. + Error( "CUtlLinkedList overflow! (exhausted index range)\n" ); return InvalidIndex(); } diff --git a/mp/src/public/tier1/utlmultilist.h b/mp/src/public/tier1/utlmultilist.h index c677746c..72a970ff 100644 --- a/mp/src/public/tier1/utlmultilist.h +++ b/mp/src/public/tier1/utlmultilist.h @@ -399,7 +399,8 @@ I CUtlMultiList::Alloc( ) // We can overflow before the utlmemory overflows, since we have have I != int if ( !IndexInRange( m_MaxElementIndex ) ) { - ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted index range)\n" ) ); + // We rarely if ever handle alloc failure. Continuing leads to corruption. + Error( "CUtlMultiList overflow! (exhausted index range)\n" ); return InvalidIndex(); } @@ -413,7 +414,8 @@ I CUtlMultiList::Alloc( ) if ( m_MaxElementIndex >= m_Memory.NumAllocated() ) { - ExecuteNTimes( 10, Warning( "CUtlMultiList overflow! (exhausted memory allocator)\n" ) ); + // We rarely if ever handle alloc failure. Continuing leads to corruption. + Error( "CUtlMultiList overflow! (exhausted memory allocator)\n" ); return InvalidIndex(); } } diff --git a/mp/src/public/tier1/utlqueue.h b/mp/src/public/tier1/utlqueue.h index 8624a3db..05c89ee3 100644 --- a/mp/src/public/tier1/utlqueue.h +++ b/mp/src/public/tier1/utlqueue.h @@ -11,104 +11,541 @@ #pragma once #endif -#include "utlvector.h" +#include "utlmemory.h" -// T is the type stored in the stack -template< class T > +//#define TEST_UTLQUEUE + +enum QueueIter_t { QUEUE_ITERATOR_INVALID = 0xffffffff }; + +// T is the type stored in the queue +template< class T, class M = CUtlMemory< T > > class CUtlQueue { public: - // constructor: lessfunc is required, but may be set after the constructor with - // SetLessFunc CUtlQueue( int growSize = 0, int initSize = 0 ); CUtlQueue( T *pMemory, int numElements ); // return the item from the front of the queue and delete it - T const& RemoveAtHead(); + T RemoveAtHead(); + bool RemoveAtHead( T &removedElement ); + // return the item from the end of the queue and delete it - T const& RemoveAtTail(); + T RemoveAtTail(); + bool RemoveAtTail( T &removedElement ); // return item at the front of the queue - T const& Head(); + T const& Head() const; // return item at the end of the queue - T const& Tail(); + T const& Tail() const; // Add a new item to the end of the queue void Insert( T const &element ); // checks if an element of this value already exists on the stack, returns true if it does - bool Check( T const element ); + bool Check( T const element ) const; + + // iterators may be invalidated by Insert() + QueueIter_t First() const; + QueueIter_t Next( QueueIter_t it ) const; + QueueIter_t Last() const; + QueueIter_t Previous( QueueIter_t it ) const; + bool IsValid( QueueIter_t it ) const; + T const& Element( QueueIter_t it ) const; + + // Returns the count of elements in the queue + int Count() const; + + // Return whether the queue is empty or not, faster than Count(). + bool IsEmpty() const; - // Returns the count of elements in the stack - int Count() const { return m_heap.Count(); } - // doesn't deallocate memory - void RemoveAll() { m_heap.RemoveAll(); } + void RemoveAll(); // Memory deallocation - void Purge() { m_heap.Purge(); } + void Purge(); protected: - CUtlVector m_heap; - T m_current; + QueueIter_t Next_Unchecked( QueueIter_t it ) const; + QueueIter_t Previous_Unchecked( QueueIter_t it ) const; + + M m_memory; + + // if m_head == m_tail == QUEUE_ITERATOR_INVALID, then the queue is empty + QueueIter_t m_head; + QueueIter_t m_tail; + +#ifdef TEST_UTLQUEUE + friend void CUtlQueue_Test(); +#endif }; -template< class T > -inline CUtlQueue::CUtlQueue( int growSize, int initSize ) : - m_heap(growSize, initSize) +//----------------------------------------------------------------------------- +// The CUtlQueueFixed class: +// A queue class with a fixed allocation scheme +//----------------------------------------------------------------------------- +template< class T, size_t MAX_SIZE > +class CUtlQueueFixed : public CUtlQueue< T, CUtlMemoryFixed > +{ + typedef CUtlQueue< T, CUtlMemoryFixed > BaseClass; +public: + + // constructor, destructor + CUtlQueueFixed( int growSize = 0, int initSize = 0 ) : BaseClass( growSize, initSize ) {} + CUtlQueueFixed( T* pMemory, int numElements ) : BaseClass( pMemory, numElements ) {} +}; + +template< class T, class M > +inline CUtlQueue::CUtlQueue( int growSize, int initSize ) : + m_memory( growSize, initSize ), m_head( QUEUE_ITERATOR_INVALID ), m_tail( QUEUE_ITERATOR_INVALID ) { } -template< class T > -inline CUtlQueue::CUtlQueue( T *pMemory, int numElements ) : - m_heap(pMemory, numElements) +template< class T, class M > +inline CUtlQueue::CUtlQueue( T *pMemory, int numElements ) : + m_memory( pMemory, numElements ), m_head( QUEUE_ITERATOR_INVALID ), m_tail( QUEUE_ITERATOR_INVALID ) { } -template -inline T const& CUtlQueue::RemoveAtHead() +template +inline T CUtlQueue::RemoveAtHead() { - m_current = m_heap[0]; - m_heap.Remove((int)0); - return m_current; + T temp; + RemoveAtHead( temp ); + return temp; } -template -inline T const& CUtlQueue::RemoveAtTail() +template +inline bool CUtlQueue::RemoveAtHead( T &removedElement ) { - m_current = m_heap[ m_heap.Count() - 1 ]; - m_heap.Remove((int)(m_heap.Count() - 1)); - return m_current; + Assert( m_head != QUEUE_ITERATOR_INVALID ); + if ( m_head == QUEUE_ITERATOR_INVALID ) + { + Construct( &removedElement ); + return false; + } + + QueueIter_t it = m_head; + removedElement = m_memory[ it ]; + Destruct( &m_memory[ it ] ); + if ( m_head == m_tail ) + { + m_head = m_tail = QUEUE_ITERATOR_INVALID; + } + else + { + m_head = Next_Unchecked( m_head ); + } + return true; } -template -inline T const& CUtlQueue::Head() +template +inline T CUtlQueue::RemoveAtTail() { - m_current = m_heap[0]; - return m_current; + T temp; + RemoveAtTail( temp ); + return temp; } -template -inline T const& CUtlQueue::Tail() +template +inline bool CUtlQueue::RemoveAtTail( T &removedElement ) { - m_current = m_heap[ m_heap.Count() - 1 ]; - return m_current; + Assert( m_tail != QUEUE_ITERATOR_INVALID ); + if ( m_tail == QUEUE_ITERATOR_INVALID ) + { + Construct( &removedElement ); + return false; + } + + removedElement = m_memory[ m_tail ]; + Destruct( &m_memory[ m_tail ] ); + if ( m_head == m_tail ) + { + m_head = m_tail = QUEUE_ITERATOR_INVALID; + } + else + { + m_tail = Previous_Unchecked( m_tail ); + } + return true; } -template -void CUtlQueue::Insert( T const &element ) +template +inline T const& CUtlQueue::Head() const { - int index = m_heap.AddToTail(); - m_heap[index] = element; + Assert( m_head != QUEUE_ITERATOR_INVALID ); + if ( m_head == QUEUE_ITERATOR_INVALID ) + { + static T dummy; + return dummy; + } + + return m_memory[ m_head ]; } -template -bool CUtlQueue::Check( T const element ) +template +inline T const& CUtlQueue::Tail() const { - int index = m_heap.Find(element); - return ( index != -1 ); + Assert( m_tail != QUEUE_ITERATOR_INVALID ); + if ( m_tail == QUEUE_ITERATOR_INVALID ) + { + static T dummy; + return dummy; + } + + return m_memory[ m_tail ]; } +template +void CUtlQueue::Insert( T const &element ) +{ + if ( m_tail == QUEUE_ITERATOR_INVALID ) + { + // empty + m_memory.EnsureCapacity( 1 ); + m_head = m_tail = QueueIter_t( 0 ); + } + else + { + // non-empty + QueueIter_t nextTail = Next_Unchecked( m_tail ); + if ( nextTail == m_head ) // if non-empty, and growing by 1 appears to make the queue of length 1, then we were already full before the Insert + { + int nOldAllocCount = m_memory.NumAllocated(); + m_memory.Grow(); + int nNewAllocCount = m_memory.NumAllocated(); + int nGrowAmount = nNewAllocCount - nOldAllocCount; + + nextTail = Next_Unchecked( m_tail ); // if nextTail was 0, then it now should be nOldAllocCount + + if ( m_head != QueueIter_t( 0 ) ) + { + // if the queue wraps around the end of m_memory, move the part at the end of memory to the new end of memory + Q_memmove( &m_memory[ m_head + nGrowAmount ], &m_memory[ m_head ], ( nOldAllocCount - m_head ) * sizeof( T ) ); +#ifdef _DEBUG + Q_memset( &m_memory[ m_head ], 0xdd, nGrowAmount * sizeof( T ) ); +#endif + m_head = QueueIter_t( m_head + nGrowAmount ); + } + } + m_tail = nextTail; + } + + CopyConstruct( &m_memory[ m_tail ], element ); +} + +template +bool CUtlQueue::Check( T const element ) const +{ + for ( QueueIter_t it = First(); it != QUEUE_ITERATOR_INVALID; it = Next( it ) ) + { + if ( m_memory[ it ] == element ) + return true; + } + return false; +} + +template +QueueIter_t CUtlQueue::First() const +{ + return m_head; +} + +template +QueueIter_t CUtlQueue::Next( QueueIter_t it ) const +{ + if ( it == QUEUE_ITERATOR_INVALID ) + return QUEUE_ITERATOR_INVALID; + + if ( it == m_tail ) + return QUEUE_ITERATOR_INVALID; + + Assert( IsValid( it ) ); + if ( !IsValid( it ) ) + return QUEUE_ITERATOR_INVALID; + + return Next_Unchecked( it ); +} + +template +QueueIter_t CUtlQueue::Last() const +{ + return m_tail; +} + +template +QueueIter_t CUtlQueue::Previous( QueueIter_t it ) const +{ + if ( it == QUEUE_ITERATOR_INVALID ) + return QUEUE_ITERATOR_INVALID; + + if ( it == m_head ) + return QUEUE_ITERATOR_INVALID; + + Assert( IsValid( it ) ); + if ( !IsValid( it ) ) + return QUEUE_ITERATOR_INVALID; + + return Previous_Unchecked( it ); +} + +template +QueueIter_t CUtlQueue::Next_Unchecked( QueueIter_t it ) const +{ + return it == m_memory.Count() - 1 ? QueueIter_t( 0 ) : QueueIter_t( it + 1 ); +} + +template +QueueIter_t CUtlQueue::Previous_Unchecked( QueueIter_t it ) const +{ + return it == 0 ? QueueIter_t( m_memory.Count() - 1 ) : QueueIter_t( it - 1 ); +} + +template +bool CUtlQueue::IsValid( QueueIter_t it ) const +{ + if ( it == QUEUE_ITERATOR_INVALID ) + return false; + + if ( m_head == QUEUE_ITERATOR_INVALID ) + return false; + + if ( m_head <= m_tail ) + return it >= m_head && it <= m_tail; + + return ( it >= m_head && it < m_memory.Count() ) || ( it >= 0 && it <= m_tail ); +} + +template +T const& CUtlQueue::Element( QueueIter_t it ) const +{ + Assert( it != QUEUE_ITERATOR_INVALID ); + if ( it == QUEUE_ITERATOR_INVALID ) + { + static T dummy; + return dummy; + } + + Assert( IsValid( it ) ); + return m_memory[ it ]; +} + +template +int CUtlQueue::Count() const +{ + if ( m_head == QUEUE_ITERATOR_INVALID ) + { + Assert( m_tail == QUEUE_ITERATOR_INVALID ); + return 0; + } + Assert( m_tail != QUEUE_ITERATOR_INVALID ); + + if ( m_head <= m_tail ) + return m_tail + 1 - m_head; + + return m_tail + 1 - m_head + m_memory.Count(); +} + +template +bool CUtlQueue::IsEmpty() const +{ + Assert( ( m_head == QUEUE_ITERATOR_INVALID ) == ( m_tail == QUEUE_ITERATOR_INVALID ) ); + return ( m_head == QUEUE_ITERATOR_INVALID ); +} + +template +void CUtlQueue::RemoveAll() +{ + m_head = m_tail = QUEUE_ITERATOR_INVALID; +} + +template +void CUtlQueue::Purge() +{ + m_head = m_tail = QUEUE_ITERATOR_INVALID; + m_memory.Purge(); +} + + +#ifdef TEST_UTLQUEUE + +#include + +struct Data_t +{ + Data_t( int i = 0xffffffff ) : m_id( i ) {} + Data_t( const Data_t &that ) : m_id( that.m_id ) {} + ~Data_t() { m_id = 0xdddddddd; } + Data_t &operator=( const Data_t &that ) { m_id = that.m_id; return *this; } + + int m_id; +}; + +inline void CUtlQueue_Test() +{ + CUtlQueue< Data_t > queue; + + for ( int n = 1; n < 100; ++n ) + { + Assert( queue.Count() == 0 ); + Assert( queue.m_head == QUEUE_ITERATOR_INVALID ); + Assert( queue.m_tail == QUEUE_ITERATOR_INVALID ); + + int w = rand() % n; + for ( int i = 0; i < w; ++i ) + { + queue.Insert( Data_t( i ) ); + } + + if ( w > 0 ) + { + Assert( queue.Head().m_id == queue.First() ); + Assert( queue.Tail().m_id == queue.Last() ); + Assert( queue.Head().m_id == 0 ); + Assert( queue.Tail().m_id == w - 1 ); + } + Assert( queue.Count() == w ); + + for ( int j = 0; j < n; ++j ) + { + queue.Insert( Data_t( w + j ) ); + + if ( j == 0 ) + { + Assert( queue.Count() == w + j + 1 ); + + for ( int i = 0; i < w; ++i ) + { + queue.RemoveAtHead(); + } + } + + Assert( queue.Count() == j + 1 ); + + Assert( queue.m_head != QUEUE_ITERATOR_INVALID ); + Assert( queue.m_tail != QUEUE_ITERATOR_INVALID ); + + int id = queue.Head().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.First(); it != QUEUE_ITERATOR_INVALID; it = queue.Next( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + 1 ) % queue.m_memory.Count(); + } + + id = queue.Tail().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.Last(); it != QUEUE_ITERATOR_INVALID; it = queue.Previous( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + queue.m_memory.Count() - 1 ) % queue.m_memory.Count(); + } + + for ( int i = 0; i < j; ++i ) + { + int id = queue.m_memory[ i ].m_id; + if ( queue.IsValid( QueueIter_t( i ) ) ) + { + Assert( ( id & 0xff000000 ) == 0 ); + } + else + { + Assert( id == 0xdddddddd ); + } + } + } + + Assert( queue.Count() == n ); +#if 0 + for ( int j = 0; j < n; ++j ) + { + Assert( queue.m_head != QUEUE_ITERATOR_INVALID ); + Assert( queue.m_tail != QUEUE_ITERATOR_INVALID ); + + Assert( queue.Count() == n - j ); + + Data_t data = queue.RemoveAtHead(); + + Assert( queue.Count() == n - j - 1 ); + + if ( queue.Count() > 0 ) + { + int id = queue.Head().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.First(); it != QUEUE_ITERATOR_INVALID; it = queue.Next( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + 1 ) % queue.m_memory.Count(); + } + + id = queue.Tail().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.Last(); it != QUEUE_ITERATOR_INVALID; it = queue.Previous( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + queue.m_memory.Count() - 1 ) % queue.m_memory.Count(); + } + } + + for ( int i = 0; i < j; ++i ) + { + int id = queue.m_memory[ i ].m_id; + if ( queue.IsValid( QueueIter_t( i ) ) ) + { + Assert( ( id & 0xff000000 ) == 0 ); + } + else + { + Assert( id == 0xdddddddd ); + } + } + } +#else + for ( int j = n - 1; j >= 0; --j ) + { + Assert( queue.m_head != QUEUE_ITERATOR_INVALID ); + Assert( queue.m_tail != QUEUE_ITERATOR_INVALID ); + + Assert( queue.Count() == j + 1 ); + + Data_t data = queue.RemoveAtTail(); + + Assert( queue.Count() == j ); + + if ( queue.Count() > 0 ) + { + int id = queue.Head().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.First(); it != QUEUE_ITERATOR_INVALID; it = queue.Next( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + 1 ) % queue.m_memory.Count(); + } + + id = queue.Tail().m_id % queue.m_memory.Count(); + for ( QueueIter_t it = queue.Last(); it != QUEUE_ITERATOR_INVALID; it = queue.Previous( it ) ) + { + Assert( queue.Element( it ).m_id % queue.m_memory.Count() == id ); + id = ( id + queue.m_memory.Count() - 1 ) % queue.m_memory.Count(); + } + } + + for ( int i = 0; i < j; ++i ) + { + int id = queue.m_memory[ i ].m_id; + if ( queue.IsValid( QueueIter_t( i ) ) ) + { + Assert( ( id & 0xff000000 ) == 0 ); + } + else + { + Assert( id == 0xdddddddd ); + } + } + } +#endif + + Assert( queue.Count() == 0 ); + Assert( queue.m_head == QUEUE_ITERATOR_INVALID ); + Assert( queue.m_tail == QUEUE_ITERATOR_INVALID ); + } +} + +#endif // TEST_UTLQUEUE #endif // UTLQUEUE_H diff --git a/mp/src/public/tier1/utlrbtree.h b/mp/src/public/tier1/utlrbtree.h index 273ee958..ded22bf5 100644 --- a/mp/src/public/tier1/utlrbtree.h +++ b/mp/src/public/tier1/utlrbtree.h @@ -1150,6 +1150,11 @@ void CUtlRBTree::RemoveAll() // Clear everything else out m_Root = InvalidIndex(); + // Technically, this iterator could become invalid. It will not, because it's + // always the same iterator. If we don't clear this here, the state of this + // container will be invalid after we start inserting elements again. + m_LastAlloc = m_Elements.InvalidIterator(); + m_FirstFree = InvalidIndex(); m_NumElements = 0; Assert( IsValid() ); @@ -1163,9 +1168,7 @@ template < class T, class I, typename L, class M > void CUtlRBTree::Purge() { RemoveAll(); - m_FirstFree = InvalidIndex(); m_Elements.Purge(); - m_LastAlloc = m_Elements.InvalidIterator(); } diff --git a/mp/src/public/tier1/utlvector.h b/mp/src/public/tier1/utlvector.h index 0ddf4ad0..7313bc99 100644 --- a/mp/src/public/tier1/utlvector.h +++ b/mp/src/public/tier1/utlvector.h @@ -23,6 +23,7 @@ #include "tier1/utlmemory.h" #include "tier1/utlblockmemory.h" #include "tier1/strtools.h" +#include "vstdlib/random.h" #define FOR_EACH_VEC( vecName, iteratorName ) \ for ( int iteratorName = 0; iteratorName < (vecName).Count(); iteratorName++ ) @@ -63,6 +64,8 @@ public: const T& Head() const; T& Tail(); const T& Tail() const; + T& Random(); + const T& Random() const; // STL compatible member functions. These allow easier use of std::sort // and they are forward compatible with the C++ 11 range-based for loops. @@ -159,6 +162,8 @@ public: void Sort( int (__cdecl *pfnCompare)(const T *, const T *) ); + void Shuffle( IUniformRandomStream* pSteam = NULL ); + #ifdef DBGFLAG_VALIDATE void Validate( CValidator &validator, char *pchName ); // Validate our internal structures #endif // DBGFLAG_VALIDATE @@ -676,6 +681,37 @@ inline int CUtlVector::Size() const return m_Size; } +template< typename T, class A > +inline T& CUtlVector::Random() +{ + Assert( m_Size > 0 ); + return m_Memory[ RandomInt( 0, m_Size - 1 ) ]; +} + +template< typename T, class A > +inline const T& CUtlVector::Random() const +{ + Assert( m_Size > 0 ); + return m_Memory[ RandomInt( 0, m_Size - 1 ) ]; +} + + +//----------------------------------------------------------------------------- +// Shuffle - Knuth/Fisher-Yates +//----------------------------------------------------------------------------- +template< typename T, class A > +void CUtlVector::Shuffle( IUniformRandomStream* pSteam ) +{ + for ( int i = 0; i < m_Size; i++ ) + { + int j = pSteam ? pSteam->RandomInt( i, m_Size - 1 ) : RandomInt( i, m_Size - 1 ); + if ( i != j ) + { + V_swap( m_Memory[ i ], m_Memory[ j ] ); + } + } +} + template< typename T, class A > inline int CUtlVector::Count() const { diff --git a/mp/src/public/tier2/p4helpers.h b/mp/src/public/tier2/p4helpers.h index 8d4b3b3f..61c70c81 100644 --- a/mp/src/public/tier2/p4helpers.h +++ b/mp/src/public/tier2/p4helpers.h @@ -33,6 +33,9 @@ public: // Opens the file for add virtual bool Add( void ); + // Reverts the file + virtual bool Revert( void ); + // Is the file in perforce? virtual bool IsFileInPerforce(); @@ -158,4 +161,19 @@ protected: }; +// +// CP4AutoRevert - reverts the file upon construction +// +class CP4AutoRevertFile +{ +public: + explicit CP4AutoRevertFile( char const *szFilename ) : m_spImpl( g_p4factory->AccessFile( szFilename ) ) { m_spImpl->Revert(); } + + CP4File * File() const { return m_spImpl.Get(); } + +protected: + CPlainAutoPtr< CP4File > m_spImpl; +}; + + #endif // #ifndef P4HELPERS_H diff --git a/mp/src/public/togl/glfuncs.inl b/mp/src/public/togl/glfuncs.inl index 55a24f45..1f6b3b45 100644 --- a/mp/src/public/togl/glfuncs.inl +++ b/mp/src/public/togl/glfuncs.inl @@ -1,7 +1,2 @@ -#if defined(LINUX) || defined(_WIN32) #include "togl/linuxwin/glfuncs.h" -#endif -#if defined(OSX) -#include "togl/osx/glfuncs.h" -#endif diff --git a/mp/src/public/togl/linuxwin/cglmbuffer.h b/mp/src/public/togl/linuxwin/cglmbuffer.h index 45c99882..10782243 100644 --- a/mp/src/public/togl/linuxwin/cglmbuffer.h +++ b/mp/src/public/togl/linuxwin/cglmbuffer.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // cglmprogram.h // GLMgr buffers (index / vertex) @@ -44,6 +66,51 @@ struct GLMBuffLockParams extern void glBufferSubDataMaxSize( GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data, uint nMaxSizePerCall = 128 * 1024 ); +//===========================================================================// + +// Creates an immutable storage for a buffer object +// https://www.opengl.org/registry/specs/ARB/buffer_storage.txt +class CPersistentBuffer +{ +public: + + CPersistentBuffer(); + ~CPersistentBuffer(); + + void Init( EGLMBufferType type,uint nSize ); + void Deinit(); + + void InsertFence(); + void BlockUntilNotBusy(); + + void Append( uint nSize ); + + inline uint GetBytesRemaining() const { return m_nSize - m_nOffset; } + inline uint GetOffset() const { return m_nOffset; } + inline void *GetPtr() const { return m_pImmutablePersistentBuf; } + inline GLuint GetHandle() const { return m_nHandle; } + +private: + + CPersistentBuffer( const CPersistentBuffer & ); + CPersistentBuffer & operator= (const CPersistentBuffer &); + + uint m_nSize; + + EGLMBufferType m_type; + GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB + GLuint m_nHandle; // handle of this program in the GL context + + // Holds a pointer to the persistently mapped buffer + void* m_pImmutablePersistentBuf; + + uint m_nOffset; + +#ifdef HAVE_GL_ARB_SYNC + GLsync m_nSyncObj; +#endif +}; + //=============================================================================== #if GL_ENABLE_INDEX_VERIFICATION @@ -92,7 +159,7 @@ public: void DiscardAllSpans(); bool IsValid( uint nOffset, uint nSize ) const; - + private: bool AllocDynamicBuf( uint nSize, GLDynamicBuf_t &buf ); void ReleaseDynamicBuf( GLDynamicBuf_t &buf ); @@ -120,6 +187,8 @@ class CGLMBuffer public: void Lock( GLMBuffLockParams *pParams, char **pAddressOut ); void Unlock( int nActualSize = -1, const void *pActualData = NULL ); + + GLuint GetHandle() const; friend class GLMContext; // only GLMContext can make CGLMBuffer objects friend class GLMTester; @@ -159,6 +228,9 @@ public: float *m_pLastMappedAddress; int m_nPinnedMemoryOfs; + + uint m_nPersistentBufferStartOffset; + bool m_bUsingPersistentBuffer; bool m_bPseudo; // true if the m_name is 0, and the backing is plain RAM diff --git a/mp/src/public/togl/linuxwin/cglmfbo.h b/mp/src/public/togl/linuxwin/cglmfbo.h index 0cfd4226..93ebb11f 100644 --- a/mp/src/public/togl/linuxwin/cglmfbo.h +++ b/mp/src/public/togl/linuxwin/cglmfbo.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // cglmfbo.h // GLMgr FBO's (render targets) diff --git a/mp/src/public/togl/linuxwin/cglmprogram.h b/mp/src/public/togl/linuxwin/cglmprogram.h index 8fa09fa2..e3f4f60a 100644 --- a/mp/src/public/togl/linuxwin/cglmprogram.h +++ b/mp/src/public/togl/linuxwin/cglmprogram.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // cglmprogram.h // GLMgr programs (ARBVP/ARBfp) @@ -110,8 +132,8 @@ public: void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program void SetShaderName ( const char *name ); // only used for debugging/telemetry markup - bool CompileActiveSources ( void ); // compile only the flavors that were provided. - bool Compile ( EGLMProgramLang lang ); + void CompileActiveSources ( void ); // compile only the flavors that were provided. + void Compile ( EGLMProgramLang lang ); bool CheckValidity ( EGLMProgramLang lang ); void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that @@ -145,6 +167,9 @@ public: uint m_samplerMask; // (1<> 16; + float fWidth = (float)( nWidthHeight & 0xFFFF ), fHeight = (float)( nWidthHeight >> 16 ); // Apply half pixel offset to output vertices to account for the pixel center difference between D3D9 and OpenGL. // We output vertices in clip space, which ranges from [-1,1], so 1.0/width in clip space transforms into .5/width in screenspace, see: "Viewports and Clipping (Direct3D 9)" in the DXSDK - float v[4] = { 1.0f / (float)nWidth, 1.0f / (float)nHeight, (float)nWidth, (float)nHeight }; + float v[4] = { 1.0f / fWidth, 1.0f / fHeight, fWidth, fHeight }; if ( m_locVertexScreenParams >= 0 ) gGL->glUniform4fv( m_locVertexScreenParams, 1, v ); } @@ -227,10 +264,10 @@ public: GLint m_locVertexBoneParams; // "vcbones" GLint m_locVertexInteger0; // "i0" - GLint m_locVertexBool0; // "b0" - GLint m_locVertexBool1; // "b1" - GLint m_locVertexBool2; // "b2" - GLint m_locVertexBool3; // "b3" + enum { cMaxVertexShaderBoolUniforms = 4, cMaxFragmentShaderBoolUniforms = 1 }; + + GLint m_locVertexBool[cMaxVertexShaderBoolUniforms]; // "b0", etc. + GLint m_locFragmentBool[cMaxFragmentShaderBoolUniforms]; // "fb0", etc. bool m_bHasBoolOrIntUniforms; // fragment stage uniforms @@ -243,10 +280,11 @@ public: float m_fakeSRGBEnableValue; // shadow to avoid redundant sets of the m_locFragmentFakeSRGBEnable uniform // init it to -1.0 at link or relink, so it will trip on any legit incoming value (0.0 or 1.0) - GLint m_locSamplers[ 16 ]; // "sampler0 ... sampler1..." + GLint m_locSamplers[ GLM_SAMPLER_COUNT ]; // "sampler0 ... sampler1..." // other stuff bool m_valid; // true on successful link + bool m_bCheckLinkStatus; uint m_revision; // if this pair is relinked, bump this number. GLint m_locVertexScreenParams; // vcscreen diff --git a/mp/src/public/togl/linuxwin/cglmquery.h b/mp/src/public/togl/linuxwin/cglmquery.h index ff1ccfe9..168e3f7c 100644 --- a/mp/src/public/togl/linuxwin/cglmquery.h +++ b/mp/src/public/togl/linuxwin/cglmquery.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // cglmquery.h // GLMgr queries @@ -10,10 +32,6 @@ #pragma once -#ifdef OSX -#include "glmgr/glmgrbasics.h" -#endif - //=============================================================================== // forward declarations diff --git a/mp/src/public/togl/linuxwin/cglmtex.h b/mp/src/public/togl/linuxwin/cglmtex.h index cafdd1c7..90870a7f 100644 --- a/mp/src/public/togl/linuxwin/cglmtex.h +++ b/mp/src/public/togl/linuxwin/cglmtex.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // cglmtex.h // GLMgr textures @@ -11,7 +33,7 @@ #pragma once #ifdef OSX -#include "glmgr/glmgrbasics.h" +#include "glmgrbasics.h" #endif #include "tier1/utlhash.h" #include "tier1/utlmap.h" @@ -199,6 +221,8 @@ struct GLMTexLockDesc #define GLM_SAMPLER_COUNT 16 +#define GLM_MAX_PIXEL_TEX_SAMPLERS 16 +#define GLM_MAX_VERTEX_TEX_SAMPLERS 0 typedef CBitVec CTexBindMask; enum EGLMTexSliceFlag @@ -263,9 +287,11 @@ struct GLMTexSamplingParams m_packed.m_magFilter = D3DTEXF_POINT; m_packed.m_mipFilter = D3DTEXF_NONE; m_packed.m_maxAniso = 1; + m_packed.m_compareMode = 0; m_packed.m_isValid = true; } +#ifndef OSX FORCEINLINE void SetToSamplerObject( GLuint nSamplerObject ) const { static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; @@ -305,6 +331,7 @@ struct GLMTexSamplingParams gGL->glSamplerParameteri( nSamplerObject, GL_TEXTURE_SRGB_DECODE_EXT, m_packed.m_srgb ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT ); } } +#endif // !OSX inline void DeltaSetToTarget( GLenum target, const GLMTexSamplingParams &curState ) { @@ -377,7 +404,7 @@ struct GLMTexSamplingParams } } - inline void SetToTargetTexture( GLenum target ) + inline void SetToTarget( GLenum target ) { static const GLenum dxtogl_addressMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, (GLenum)-1 }; static const GLenum dxtogl_magFilter[4] = { GL_NEAREST, GL_NEAREST, GL_LINEAR, GL_LINEAR }; @@ -427,6 +454,7 @@ public: void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); void Unlock( GLMTexLockParams *params ); + GLuint GetTexName() { return m_texName; } protected: friend class GLMContext; // only GLMContext can make CGLMTex objects @@ -440,7 +468,7 @@ protected: friend struct IDirect3DCubeTexture9; friend struct IDirect3DVolumeTexture9; - CGLMTex( GLMContext *ctx, GLMTexLayout *layout, const char *debugLabel = NULL ); + CGLMTex( GLMContext *ctx, GLMTexLayout *layout, uint levels, const char *debugLabel = NULL ); ~CGLMTex( ); int CalcSliceIndex( int face, int mip ); @@ -450,13 +478,17 @@ protected: void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) // this helps out ResetSRGB. + +#if defined( OSX ) + void HandleSRGBMismatch( bool srgb, int &srgbFlipCount ); + void ResetSRGB( bool srgb, bool noDataWrite ); + // re-specify texture format to match desired sRGB form + // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's +#endif bool IsRBODirty() const; void ForceRBONonDirty(); void ForceRBODirty(); - - void AllocBacking(); - void ReleaseBacking(); // re-specify texture format to match desired sRGB form // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's @@ -464,25 +496,26 @@ protected: GLuint m_texName; // name of this texture in the context GLenum m_texGLTarget; uint m_nSamplerType; // SAMPLER_2D, etc. + GLMTexSamplingParams m_SamplingParams; + GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) uint m_nLastResolvedBatchCounter; int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. - int m_mipCount; GLMContext *m_ctx; // link back to parent context + CGLMFBO *m_pBlitSrcFBO; CGLMFBO *m_pBlitDstFBO; - GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) int m_rtAttachCount; // how many RT's have this texture attached somewhere - char *m_pBacking; // backing storage if available + char *m_backing; // backing storage if available int m_lockCount; // lock reqs are stored in the GLMContext for tracking @@ -493,6 +526,7 @@ protected: bool m_texClientStorage; // was CS selected for texture bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet + int m_srgbFlipCount; #if GLMDEBUG CGLMTex *m_pPrevTex; CGLMTex *m_pNextTex; diff --git a/mp/src/public/togl/linuxwin/dxabstract.h b/mp/src/public/togl/linuxwin/dxabstract.h index 0e367329..b601e78d 100644 --- a/mp/src/public/togl/linuxwin/dxabstract.h +++ b/mp/src/public/togl/linuxwin/dxabstract.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // dxabstract.h // @@ -18,8 +40,10 @@ #define IUNKNOWN_ALLOC_SPEW 0 #define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 + TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); + struct TOGL_CLASS IUnknown { int m_refcount[2]; @@ -138,7 +162,6 @@ struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A T { D3DSURFACE_DESC m_descZero; // desc of top level. CGLMTex *m_tex; // a CGLMTex can represent all forms of tex - int m_srgbFlipCount; virtual ~IDirect3DBaseTexture9(); D3DRESOURCETYPE TOGLMETHODCALLTYPE GetType(); @@ -270,7 +293,8 @@ struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnkno uint m_pixHighWater; // count of active constant slots referenced by shader. uint m_pixSamplerMask; // (1<SetSamplerDirty( Sampler ); @@ -747,7 +780,7 @@ FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerState( DWORD m_ctx->SetSamplerMaxAnisotropy( Sampler, Value); break; case D3DSAMP_SRGBTEXTURE: - m_samplers[ Sampler ].m_srgb = Value; + //m_samplers[ Sampler ].m_srgb = Value; m_ctx->SetSamplerSRGBTexture(Sampler, Value); break; case D3DSAMP_SHADOWFILTER: @@ -768,7 +801,7 @@ FORCEINLINE void TOGLMETHODCALLTYPE IDirect3DDevice9::SetSamplerStates( SetSamplerStatesNonInline( Sampler, AddressU, AddressV, AddressW, MinFilter, MagFilter, MipFilter ); #else Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); - Assert( Sampler < 16); + Assert( Sampler < GLM_SAMPLER_COUNT); m_ctx->SetSamplerDirty( Sampler ); @@ -782,6 +815,7 @@ FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetTexture(DWORD Stage, return SetTextureNonInline( Stage, pTexture ); #else Assert( GetCurrentOwnerThreadId() == ThreadGetCurrentId() ); + Assert( Stage < GLM_SAMPLER_COUNT ); m_textures[Stage] = pTexture; m_ctx->SetSamplerTex( Stage, pTexture ? pTexture->m_tex : NULL ); return S_OK; @@ -809,13 +843,10 @@ FORCEINLINE GLenum D3DBlendOperationToGL( DWORD operation ) switch (operation) { case D3DBLENDOP_ADD : return GL_FUNC_ADD; // The result is the destination added to the source. Result = Source + Destination - - /* not covered by dxabstract.h.. - case D3DBLENDOP_SUBTRACT : return GL_FUNC_SUBTRACT; // The result is the destination subtracted from to the source. Result = Source - Destination - case D3DBLENDOP_REVSUBTRACT : return GL_FUNC_REVERSE_SUBTRACT; // The result is the source subtracted from the destination. Result = Destination - Source - case D3DBLENDOP_MIN : return GL_MIN; // The result is the minimum of the source and destination. Result = MIN(Source, Destination) - case D3DBLENDOP_MAX : return GL_MAX; // The result is the maximum of the source and destination. Result = MAX(Source, Destination) - */ + case D3DBLENDOP_SUBTRACT : return GL_FUNC_SUBTRACT; // The result is the destination subtracted from to the source. Result = Source - Destination + case D3DBLENDOP_REVSUBTRACT : return GL_FUNC_REVERSE_SUBTRACT; // The result is the source subtracted from the destination. Result = Destination - Source + case D3DBLENDOP_MIN : return GL_MIN; // The result is the minimum of the source and destination. Result = MIN(Source, Destination) + case D3DBLENDOP_MAX : return GL_MAX; // The result is the maximum of the source and destination. Result = MAX(Source, Destination) default: DXABSTRACT_BREAK_ON_ERROR(); return 0xFFFFFFFF; @@ -1174,7 +1205,7 @@ FORCEINLINE HRESULT TOGLMETHODCALLTYPE IDirect3DDevice9::SetStreamSource(UINT St // OK, we are being given the stride, we don't need to calc it.. GLMPRINTF(("-X- IDirect3DDevice9::SetStreamSource setting stream #%d to D3D buf %p (GL name %d); offset %d, stride %d", StreamNumber, pStreamData, (pStreamData) ? pStreamData->m_vtxBuffer->m_name: -1, OffsetInBytes, Stride)); - + if ( !pStreamData ) { OffsetInBytes = 0; diff --git a/mp/src/public/togl/linuxwin/dxabstract_types.h b/mp/src/public/togl/linuxwin/dxabstract_types.h index 5f2ccba3..9713ec71 100644 --- a/mp/src/public/togl/linuxwin/dxabstract_types.h +++ b/mp/src/public/togl/linuxwin/dxabstract_types.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // dxabstract_types.h // @@ -50,10 +72,6 @@ class CGLMFBO; #define TOGL_GLOBAL DLL_GLOBAL_IMPORT #endif -#ifdef OSX -#error "Do not use this header's types on OSX until togo is ported to Mac!" -#endif - #define TOGLMETHODCALLTYPE __stdcall //#define TOGLMETHODCALLTYPE @@ -176,6 +194,25 @@ typedef enum _D3DFORMAT D3DFORMAT; #define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 #define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 +// Comparison for dynamic conditional instruction opcodes (i.e. if, breakc) +typedef enum _D3DSHADER_COMPARISON +{ + // < = > + D3DSPC_RESERVED0= 0, // 0 0 0 + D3DSPC_GT = 1, // 0 0 1 + D3DSPC_EQ = 2, // 0 1 0 + D3DSPC_GE = 3, // 0 1 1 + D3DSPC_LT = 4, // 1 0 0 + D3DSPC_NE = 5, // 1 0 1 + D3DSPC_LE = 6, // 1 1 0 + D3DSPC_RESERVED1= 7 // 1 1 1 +} D3DSHADER_COMPARISON; + + +// Comparison is part of instruction opcode token: +#define D3DSHADER_COMPARISON_SHIFT D3DSP_OPCODESPECIFICCONTROL_SHIFT +#define D3DSHADER_COMPARISON_MASK (0x7< - #include - #include - #include - #include - #include - #include - #include -#elif defined(DX_TO_GL_ABSTRACTION) - #include - #include -#else - #error +#include +#include #endif #ifdef DX_TO_GL_ABSTRACTION @@ -37,20 +52,18 @@ #endif #undef CurrentTime - // prevent some conflicts in SDL headers... - #undef M_PI - #include - #ifndef _STDINT_H_ - #define _STDINT_H_ 1 + #if defined( USE_SDL ) + #include "SDL.h" #endif #endif //=============================================================================== // glue to call out to Obj-C land (these are in glmgrcocoa.mm) #ifdef OSX - bool NewNSGLContext( unsigned long *attribs, PseudoNSGLContextPtr nsglShareCtx, PseudoNSGLContextPtr *nsglCtxOut, CGLContextObj *cglCtxOut ); + typedef void _PseudoNSGLContext; // aka NSOpenGLContext + typedef _PseudoNSGLContext *PseudoNSGLContextPtr; + CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); - void DelNSGLContext( PseudoNSGLContextPtr nsglCtx ); #endif // Set TOGL_SUPPORT_NULL_DEVICE to 1 to support the NULL ref device diff --git a/mp/src/public/togl/linuxwin/glentrypoints.h b/mp/src/public/togl/linuxwin/glentrypoints.h index cff42928..9b55c00a 100644 --- a/mp/src/public/togl/linuxwin/glentrypoints.h +++ b/mp/src/public/togl/linuxwin/glentrypoints.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // glentrypoints.h // @@ -12,10 +34,8 @@ #ifdef DX_TO_GL_ABSTRACTION #include "tier0/platform.h" -#include "tier0/dynfunction.h" #include "tier0/vprof_telemetry.h" #include "interface.h" - #include "togl/rendermechanism.h" void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); @@ -277,7 +297,6 @@ public: ~COpenGLEntryPoints(); void ClearEntryPoints(); - uint64 m_nTotalGLCycles, m_nTotalGLCalls; int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. @@ -288,20 +307,26 @@ public: char *m_pGLDriverStrings[cGLTotalDriverStrings]; GLDriverProvider_t m_nDriverProvider; - #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; - #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; - #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; +#ifdef OSX +#define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; +#define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (*) arg, ret > fn; +#define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (*) arg, void > fn; +#else +#define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; +#define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; +#define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; +#endif #include "togl/glfuncs.inl" #undef GL_FUNC_VOID #undef GL_FUNC #undef GL_EXT - + bool HasSwapTearExtension() const { #ifdef _WIN32 - return m_bHave_WGL_EXT_swap_control_tear; + return m_bHave_WGL_EXT_swap_control_tear; #else - return m_bHave_GLX_EXT_swap_control_tear; + return m_bHave_GLX_EXT_swap_control_tear; #endif } }; diff --git a/mp/src/public/togl/linuxwin/glfuncs.h b/mp/src/public/togl/linuxwin/glfuncs.h index f5795139..f543b4af 100644 --- a/mp/src/public/togl/linuxwin/glfuncs.h +++ b/mp/src/public/togl/linuxwin/glfuncs.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. // !!! FIXME: Also, look up these -1, -1 versions numbers. GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) @@ -39,8 +61,11 @@ GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) +GL_FUNC_VOID(OpenGL,true,glDrawBuffers,(GLsizei a,const GLenum *b),(a,b)) GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) +#ifndef OSX // 10.6/GL 2.1 compatability GL_FUNC_VOID(OpenGL,true,glDrawRangeElementsBaseVertex,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f, GLenum g),(a,b,c,d,e,f,g)) +#endif GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) @@ -185,17 +210,24 @@ GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(G GL_EXT(GL_GREMEDY_string_marker,-1,-1) GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) GL_EXT(GL_ARB_debug_output,-1,-1) +#ifdef OSX +GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void ( *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b)) +#else GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageCallbackARB,(void (APIENTRY *a)(GLenum, GLenum , GLuint , GLenum , GLsizei , const GLchar* , GLvoid*) ,void* b),(a,b)) +#endif GL_FUNC_VOID(GL_ARB_debug_output,false,glDebugMessageControlARB,(GLenum a, GLenum b, GLenum c, GLsizei d, const GLuint* e, GLboolean f),(a,b,c,d,e,f)) + GL_EXT(GL_EXT_direct_state_access,-1,-1) GL_FUNC_VOID(GL_EXT_direct_state_access,false,glBindMultiTextureEXT,(GLenum a,GLuint b, GLuint c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glGenSamplers,(GLuint a,GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDeleteSamplers,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBindSampler,(GLuint a, GLuint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glSamplerParameteri,(GLuint a, GLenum b, GLint c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glSamplerParameterf,(GLuint a, GLenum b, GLfloat c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glSamplerParameterfv,(GLuint a, GLenum b, const GLfloat *c),(a,b,c)) GL_EXT(GL_NV_bindless_texture,-1,-1) + +#ifndef OSX +GL_FUNC_VOID(OpenGL, true, glGenSamplers, (GLuint a, GLuint *b), (a, b)) +GL_FUNC_VOID(OpenGL, true, glDeleteSamplers, (GLsizei a, const GLuint *b), (a, b)) +GL_FUNC_VOID(OpenGL, true, glBindSampler, (GLuint a, GLuint b), (a, b)) +GL_FUNC_VOID(OpenGL, true, glSamplerParameteri, (GLuint a, GLenum b, GLint c), (a, b, c)) +GL_FUNC_VOID(OpenGL, true, glSamplerParameterf, (GLuint a, GLenum b, GLfloat c), (a, b, c)) +GL_FUNC_VOID(OpenGL, true, glSamplerParameterfv, (GLuint a, GLenum b, const GLfloat *c), (a, b, c)) GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureHandleNV, (GLuint texture), (texture)) GL_FUNC(GL_NV_bindless_texture, false, GLuint64, glGetTextureSamplerHandleNV, (GLuint texture, GLuint sampler), (texture, sampler)) GL_FUNC_VOID(GL_NV_bindless_texture, false, glMakeTextureHandleResidentNV, (GLuint64 handle), (handle)) @@ -213,11 +245,17 @@ GL_FUNC_VOID(OpenGL,true,glQueryCounter,(GLuint id, GLenum target), (id, target) GL_FUNC_VOID(OpenGL,true,glGetQueryObjectiv,(GLuint id, GLenum pname, GLint *params), (id, pname, params)) GL_FUNC_VOID(OpenGL,true,glGetQueryObjectui64v,(GLuint id, GLenum pname, GLuint64 *params), (id, pname, params)) GL_FUNC_VOID(OpenGL,true,glCopyBufferSubData,(GLenum readtarget, GLenum writetarget, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size),(readtarget, writetarget, readoffset, writeoffset, size)) +#endif // !OSX + GL_EXT(GL_AMD_pinned_memory,-1,-1) GL_EXT(GL_EXT_framebuffer_multisample_blit_scaled,-1,-1) + +#ifndef OSX GL_FUNC_VOID(OpenGL,true,glGenVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) GL_FUNC_VOID(OpenGL,true,glDeleteVertexArrays,(GLsizei n, GLuint *arrays),(n, arrays)) GL_FUNC_VOID(OpenGL,true,glBindVertexArray,(GLuint a),(a)) +#endif // !OSX + GL_EXT(GL_EXT_texture_sRGB_decode,-1,-1) GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) @@ -228,6 +266,9 @@ GL_EXT(GL_EXT_texture_compression_dxt1,-1,-1) GL_EXT(GL_ANGLE_texture_compression_dxt3,-1,-1) GL_EXT(GL_ANGLE_texture_compression_dxt5,-1,-1) +GL_EXT( GL_ARB_buffer_storage, 4, 4 ) +GL_FUNC_VOID( GL_ARB_buffer_storage, false, glBufferStorage, (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags), (target, size, data, flags) ) + // This one is an OS extension. We'll add a little helper function to look for it. #ifdef _WIN32 GL_EXT(WGL_EXT_swap_control_tear,-1,-1) diff --git a/mp/src/public/togl/linuxwin/glmdebug.h b/mp/src/public/togl/linuxwin/glmdebug.h index 8efba8b4..08cb6f91 100644 --- a/mp/src/public/togl/linuxwin/glmdebug.h +++ b/mp/src/public/togl/linuxwin/glmdebug.h @@ -1,8 +1,33 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. #ifndef GLMDEBUG_H #define GLMDEBUG_H #include "tier0/platform.h" +#if defined( OSX ) +#include +#endif // include this anywhere you need to be able to compile-out code related specifically to GLM debugging. @@ -132,11 +157,7 @@ inline void GLMDebugger( void ) { if (GLMDebugChannelMask() & (1< #include -#include #include #include #include -#include -#elif defined(DX_TO_GL_ABSTRACTION) -#include -#include -#include "tier0/platform.h" -#else -#error +#endif + +#ifdef MAC_OS_X_VERSION_10_9 +typedef uint32_t CGDirectDisplayID; +typedef uint32_t CGOpenGLDisplayMask; +typedef double CGRefreshRate; #endif typedef void _PseudoNSGLContext; // aka NSOpenGLContext @@ -125,7 +149,7 @@ struct GLMRendererInfoFields bool m_intel; bool m_intel95x; bool m_intel3100; - bool m_intelNewer; + bool m_intelHD4000; bool m_nv; bool m_nvG7x; @@ -169,6 +193,7 @@ struct GLMRendererInfoFields //--------------------------- " bads " - known bad drivers bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues + bool m_badDriver108Intel; // this is the bad Intel HD4000 driver on 10.8 - intermittent crash on GLSL compilation. }; diff --git a/mp/src/public/togl/linuxwin/glmdisplaydb.h b/mp/src/public/togl/linuxwin/glmdisplaydb.h index d9f64d80..686c792d 100644 --- a/mp/src/public/togl/linuxwin/glmdisplaydb.h +++ b/mp/src/public/togl/linuxwin/glmdisplaydb.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. #ifndef GLMDISPLAYDB_H #define GLMDISPLAYDB_H @@ -32,13 +54,24 @@ class GLMDisplayInfo public: GLMDisplayInfoFields m_info; CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes + GLMDisplayMode m_DesktopMode; +#ifdef OSX + GLMDisplayInfo( CGDirectDisplayID displayID, CGOpenGLDisplayMask displayMask ); +#else GLMDisplayInfo( void ); +#endif + ~GLMDisplayInfo( void ); void PopulateModes( void ); void Dump( int which ); + +#ifdef OSX +private: + int m_display; +#endif }; //=============================================================================== @@ -48,23 +81,55 @@ public: class GLMRendererInfo { public: - GLMRendererInfoFields m_info; - GLMDisplayInfo *m_display; + GLMRendererInfoFields m_info; +#ifdef OSX + CUtlVector< GLMDisplayInfo* > *m_displays; // starts out NULL, set by PopulateDisplays +#else + GLMDisplayInfo *m_display; +#endif +#ifdef OSX + GLMRendererInfo ( GLMRendererInfoFields *info ); +#else GLMRendererInfo (); +#endif ~GLMRendererInfo ( void ); +#ifndef OSX void Init( GLMRendererInfoFields *info ); +#endif void PopulateDisplays(); void Dump( int which ); }; //=============================================================================== +#ifdef OSX +// this is just a tuple describing fake adapters which are really renderer/display pairings. +// dxabstract bridges the gap between the d3d adapter-centric world and the GL renderer+display world. +// this makes it straightforward to handle cases like two video cards with two displays on one, and one on the other - +// you get three fake adapters which represent each useful screen. + +// the constraint that dxa will have to follow though, is that if the user wants to change their +// display selection for full screen, they would only be able to pick on that has the same underlying renderer. +// can't change fakeAdapter from one to another with different GL renderer under it. Screen hop but no card hop. + +struct GLMFakeAdapter +{ + int m_rendererIndex; + int m_displayIndex; +}; +#endif + class GLMDisplayDB { public: +#ifdef OSX + CUtlVector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers + CUtlVector< GLMFakeAdapter > m_fakeAdapters; +#else GLMRendererInfo m_renderer; +#endif GLMDisplayDB ( void ); ~GLMDisplayDB ( void ); diff --git a/mp/src/public/togl/linuxwin/glmgr.h b/mp/src/public/togl/linuxwin/glmgr.h index 2f555db9..aabcd708 100644 --- a/mp/src/public/togl/linuxwin/glmgr.h +++ b/mp/src/public/togl/linuxwin/glmgr.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // glmgr.h // singleton class, common basis for managing GL contexts @@ -11,6 +33,11 @@ #pragma once +#undef HAVE_GL_ARB_SYNC +#ifndef OSX +#define HAVE_GL_ARB_SYNC 1 +#endif + #include "glbase.h" #include "glentrypoints.h" #include "glmdebug.h" @@ -28,6 +55,9 @@ #include "dxabstract_types.h" #include "tier0/icommandline.h" +#undef FORCEINLINE +#define FORCEINLINE inline + //=============================================================================== #define GLM_OPENGL_VENDOR_ID 1 @@ -1066,7 +1096,7 @@ struct GLMVertexSetup #define kGLMProgramParamInt4Limit 16 #define kGLMVertexProgramParamFloat4Limit 256 -#define kGLMFragmentProgramParamFloat4Limit 32 +#define kGLMFragmentProgramParamFloat4Limit 256 struct GLMProgramParamsF { @@ -1174,6 +1204,7 @@ public: }; //===========================================================================// +#ifndef OSX #ifndef GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD #define GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD 0x9160 @@ -1187,7 +1218,16 @@ class CPinnedMemoryBuffer CPinnedMemoryBuffer & operator= ( const CPinnedMemoryBuffer & ); public: - CPinnedMemoryBuffer() : m_pRawBuf( NULL ), m_pBuf( NULL ), m_nSize( 0 ), m_nOfs( 0 ), m_nBufferObj( 0 ), m_nSyncObj( 0 ) + CPinnedMemoryBuffer() + : + m_pRawBuf( NULL ) + , m_pBuf( NULL ) + , m_nSize( 0 ) + , m_nOfs( 0 ) + , m_nBufferObj( 0 ) +#ifdef HAVE_GL_ARB_SYNC + , m_nSyncObj( 0 ) +#endif { } @@ -1199,7 +1239,7 @@ public: bool Init( uint nSize ) { Deinit(); - + // Guarantee 64KB alignment m_pRawBuf = malloc( nSize + 65535 ); m_pBuf = reinterpret_cast((reinterpret_cast(m_pRawBuf) + 65535) & (~65535)); @@ -1210,7 +1250,7 @@ public: gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nSize, m_pBuf, GL_STREAM_COPY ); - + return true; } @@ -1218,22 +1258,22 @@ public: { if ( !m_pRawBuf ) return; - + BlockUntilNotBusy(); - + gGL->glBindBufferARB(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, m_nBufferObj ); gGL->glBufferDataARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0, (void*)NULL, GL_STREAM_COPY ); - + gGL->glBindBufferARB( GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0 ); - + gGL->glDeleteBuffersARB( 1, &m_nBufferObj ); m_nBufferObj = 0; free( m_pRawBuf ); m_pRawBuf = NULL; m_pBuf = NULL; - + m_nSize = 0; m_nOfs = 0; } @@ -1246,43 +1286,49 @@ public: void InsertFence() { +#ifdef HAVE_GL_ARB_SYNC if ( m_nSyncObj ) { gGL->glDeleteSync( m_nSyncObj ); } m_nSyncObj = gGL->glFenceSync( GL_SYNC_GPU_COMMANDS_COMPLETE, 0 ); +#endif } void BlockUntilNotBusy() { +#ifdef HAVE_GL_ARB_SYNC if ( m_nSyncObj ) { gGL->glClientWaitSync( m_nSyncObj, GL_SYNC_FLUSH_COMMANDS_BIT, 3000000000000ULL ); - - gGL->glDeleteSync( m_nSyncObj ); + gGL->glDeleteSync( m_nSyncObj ); + m_nSyncObj = 0; } +#endif m_nOfs = 0; } - + void Append( uint nSize ) { m_nOfs += nSize; Assert( m_nOfs <= m_nSize ); } - + private: void *m_pRawBuf; void *m_pBuf; uint m_nSize; uint m_nOfs; - - GLuint m_nBufferObj; + GLuint m_nBufferObj; +#ifdef HAVE_GL_ARB_SYNC GLsync m_nSyncObj; +#endif }; +#endif // !OSX //===========================================================================// @@ -1310,7 +1356,7 @@ class GLMContext // textures // Lock and Unlock reqs go directly to the tex object - CGLMTex *NewTex( GLMTexLayoutKey *key, const char *debugLabel=NULL ); + CGLMTex *NewTex( GLMTexLayoutKey *key, uint levels=1, const char *debugLabel=NULL ); void DelTex( CGLMTex *tex ); // options for Blit (replacement for ResolveTex and BlitTex) @@ -1347,7 +1393,7 @@ class GLMContext // render targets (FBO's) CGLMFBO *NewFBO( void ); void DelFBO( CGLMFBO *fbo ); - + // programs CGLMProgram *NewProgram( EGLMProgramType type, char *progString, const char *pShaderName ); void DelProgram( CGLMProgram *pProg ); @@ -1360,6 +1406,7 @@ class GLMContext void SetDrawingLang( EGLMProgramLang lang, bool immediate=false ); // choose ARB or GLSL. immediate=false defers lang change to top of frame void LinkShaderPair( CGLMProgram *vp, CGLMProgram *fp ); // ensure this combo has been linked and is in the GLSL pair cache + void ValidateShaderPair( CGLMProgram *vp, CGLMProgram *fp ); void ClearShaderPairCache( void ); // call this to shoot down all the linked pairs void QueryShaderPair( int index, GLMShaderPairInfo *infoOut ); // this lets you query the shader pair cache for saving its state @@ -1403,8 +1450,12 @@ class GLMContext void FlushDrawStatesNoShaders(); // drawing +#ifndef OSX FORCEINLINE void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); void DrawRangeElementsNonInline( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ); +#else + void DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, CGLMBuffer *pIndexBuf ); +#endif void CheckNative( void ); @@ -1421,7 +1472,7 @@ class GLMContext // Called when IDirect3DDevice9::Reset() is called. void Reset(); - + // writers for the state block inputs FORCEINLINE void WriteAlphaTestEnable( GLAlphaTestEnable_t *src ) { m_AlphaTestEnable.Write( src ); } @@ -1482,7 +1533,6 @@ class GLMContext #endif FORCEINLINE void SetMaxUsedVertexShaderConstantsHint( uint nMaxConstants ); - FORCEINLINE DWORD GetCurrentOwnerThreadId() const { return m_nCurOwnerThreadId; } protected: @@ -1507,8 +1557,10 @@ class GLMContext GLMContext( IDirect3DDevice9 *pDevice, GLMDisplayParams *params ); ~GLMContext(); +#ifndef OSX FORCEINLINE GLuint FindSamplerObject( const GLMTexSamplingParams &desiredParams ); - +#endif + FORCEINLINE void SetBufAndVertexAttribPointer( uint nIndex, GLuint nGLName, GLuint stride, GLuint datatype, GLboolean normalized, GLuint nCompCount, const void *pBuf, uint nRevision ) { VertexAttribs_t &curAttribs = m_boundVertexAttribs[nIndex]; @@ -1518,7 +1570,7 @@ class GLMContext gGL->glBindBufferARB( GL_ARRAY_BUFFER_ARB, nGLName ); } else if ( ( curAttribs.m_pPtr == pBuf ) && - ( curAttribs.m_revision == nRevision ) && + ( curAttribs.m_revision == nRevision ) && ( curAttribs.m_stride == stride ) && ( curAttribs.m_datatype == datatype ) && ( curAttribs.m_normalized == normalized ) && @@ -1533,7 +1585,7 @@ class GLMContext curAttribs.m_stride = stride; curAttribs.m_pPtr = pBuf; curAttribs.m_revision = nRevision; - + gGL->glVertexAttribPointer( nIndex, nCompCount, datatype, normalized, stride, pBuf ); } @@ -1555,7 +1607,7 @@ class GLMContext m_CurAttribs.m_vtxAttribMap[0] = 0xBBBBBBBBBBBBBBBBULL; m_CurAttribs.m_vtxAttribMap[1] = 0xBBBBBBBBBBBBBBBBULL; } - + FORCEINLINE void ReleasedShader() { NullProgram(); } // textures @@ -1572,7 +1624,7 @@ class GLMContext // render targets / FBO's void BindFBOToCtx( CGLMFBO *fbo, GLenum bindPoint = GL_FRAMEBUFFER_EXT ); // you can also choose GL_READ_FRAMEBUFFER_EXT / GL_DRAW_FRAMEBUFFER_EXT - + // buffers FORCEINLINE void BindGLBufferToCtx( GLenum nGLBufType, GLuint nGLName, bool bForce = false ) { @@ -1585,40 +1637,48 @@ class GLMContext gGL->glBindBufferARB( nGLBufType, nGLName ); } } - + void BindBufferToCtx( EGLMBufferType type, CGLMBuffer *buff, bool force = false ); // does not twiddle any enables. FORCEINLINE void BindIndexBufferToCtx( CGLMBuffer *buff ); FORCEINLINE void BindVertexBufferToCtx( CGLMBuffer *buff ); - - CPinnedMemoryBuffer *GetCurPinnedMemoryBuffer( ) { return &m_PinnedMemoryBuffers[m_nCurPinnedMemoryBuffer]; } - - // members------------------------------------------ + GLuint CreateTex( GLenum texBind, GLenum internalFormat ); + void CleanupTex( GLenum texBind, GLMTexLayout* pLayout, GLuint tex ); + void DestroyTex( GLenum texBind, GLMTexLayout* pLayout, GLuint tex ); + GLuint FillTexCache( bool holdOne, int newTextures ); + void PurgeTexCache( ); + + // debug font + void GenDebugFontTex( void ); + void DrawDebugText( float x, float y, float z, float drawCharWidth, float drawCharHeight, char *string ); + +#ifndef OSX + CPinnedMemoryBuffer *GetCurPinnedMemoryBuffer( ) { return &m_PinnedMemoryBuffers[m_nCurPinnedMemoryBuffer]; } +#endif + + CPersistentBuffer* GetCurPersistentBuffer( EGLMBufferType type ) { return &( m_persistentBuffer[m_nCurPersistentBuffer][type] ); } + + // members------------------------------------------ + // context DWORD m_nCurOwnerThreadId; uint m_nThreadOwnershipReleaseCounter; bool m_bUseSamplerObjects; - bool m_bPreferMapBufferRange; + bool m_bTexClientStorage; IDirect3DDevice9 *m_pDevice; GLMRendererInfoFields m_caps; - + bool m_displayParamsValid; // is there a param block copied in yet GLMDisplayParams m_displayParams; // last known display config, either via constructor, or by SetDisplayParams... -#ifdef OSX - CGLPixelFormatAttribute m_pixelFormatAttribs[100]; // more than enough - PseudoNSGLContextPtr m_nsctx; - CGLContextObj m_ctx; -#elif defined( USE_SDL ) +#if defined( USE_SDL ) int m_pixelFormatAttribs[100]; // more than enough PseudoNSGLContextPtr m_nsctx; void * m_ctx; #endif - bool m_oneCtxEnable; // true if we use the window's context directly instead of making a second one shared against it - bool m_bUseBoneUniformBuffers; // if true, we use two uniform buffers for vertex shader constants vs. one // texture form table @@ -1712,15 +1772,17 @@ class GLMContext CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table + + uint m_fragDataMask; // program bindings EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; bool m_bDirtyPrograms; - + GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; - GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used + GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used EGLMParamWriteMode m_paramWriteMode; @@ -1730,7 +1792,11 @@ class GLMContext CGLMProgram *m_preload2DTexFragmentProgram; CGLMProgram *m_preload3DTexFragmentProgram; CGLMProgram *m_preloadCubeTexFragmentProgram; - + +#if defined( OSX ) && defined( GLMDEBUG ) + CGLMProgram *m_boundProgram[ kGLMNumProgramTypes ]; +#endif + CGLMShaderPairCache *m_pairCache; // GLSL only CGLMShaderPair *m_pBoundPair; // GLSL only @@ -1741,7 +1807,7 @@ class GLMContext // buffer bindings GLuint m_nBoundGLBuffer[kGLMNumBufferTypes]; - + struct VertexAttribs_t { GLuint m_nCompCount; @@ -1773,23 +1839,39 @@ class GLMContext // batch/frame debugging support int m_debugFrameIndex; // init to -1. Increment at BeginFrame - + int m_nMaxUsedVertexProgramConstantsHint; uint32 m_dwRenderThreadId; volatile bool m_bIsThreading; - + uint m_nCurFrame; uint m_nBatchCounter; + struct TextureEntry_t + { + GLenum m_nTexBind; + GLenum m_nInternalFormat; + GLuint m_nTexName; + }; + + GLuint m_destroyPBO; + CUtlVector< TextureEntry_t > m_availableTextures; + +#ifndef OSX enum { cNumPinnedMemoryBuffers = 4 }; CPinnedMemoryBuffer m_PinnedMemoryBuffers[cNumPinnedMemoryBuffers]; uint m_nCurPinnedMemoryBuffer; - +#endif + + enum { cNumPersistentBuffers = 3 }; + CPersistentBuffer m_persistentBuffer[cNumPersistentBuffers][kGLMNumBufferTypes]; + uint m_nCurPersistentBuffer; + void SaveColorMaskAndSetToDefault(); void RestoreSavedColorMask(); GLColorMaskSingle_t m_SavedColorMask; - + #if GLMDEBUG // interactive (DebugHook) debug support @@ -1825,6 +1907,8 @@ class GLMContext #endif }; +#ifndef OSX + FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices, uint baseVertex, CGLMBuffer *pIndexBuf ) { #if GL_ENABLE_INDEX_VERIFICATION @@ -1836,20 +1920,25 @@ FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuin #else //tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d-%d count:%d mode:%d type:%d", __FUNCTION__, start, end, count, mode, type ); #endif - + ++m_nBatchCounter; SetIndexBuffer( pIndexBuf ); void *indicesActual = (void*)indices; - + if ( pIndexBuf->m_bPseudo ) { // you have to pass actual address, not offset indicesActual = (void*)( (int)indicesActual + (int)pIndexBuf->m_pPseudoBuf ); } + if (pIndexBuf->m_bUsingPersistentBuffer) + { + indicesActual = (void*)( (int)indicesActual + (int)pIndexBuf->m_nPersistentBufferStartOffset ); + } -#if GLMDEBUG +//#if GLMDEBUG +#if 0 bool hasVP = m_drawingProgram[ kGLMVertexProgram ] != NULL; bool hasFP = m_drawingProgram[ kGLMFragmentProgram ] != NULL; @@ -1931,6 +2020,8 @@ FORCEINLINE void GLMContext::DrawRangeElements( GLenum mode, GLuint start, GLuin #endif // GL_ENABLE_INDEX_VERIFICATION } +#endif // #ifndef OSX + FORCEINLINE void GLMContext::SetVertexProgram( CGLMProgram *pProg ) { m_drawingProgram[kGLMVertexProgram] = pProg; @@ -1969,23 +2060,53 @@ FORCEINLINE void GLMContext::SetProgramParametersF( EGLMProgramType type, uint b if ( ( type == kGLMVertexProgram ) && ( m_bUseBoneUniformBuffers ) ) { - if ( ( baseSlot + slotCount ) > DXABSTRACT_VS_FIRST_BONE_SLOT ) + // changes here to handle vertex shaders which use constants before and after the bone array i.e. before c58 and after c216 + // a better change may be to modify the shaders and place the bone consts at either start or end - would simplify this and the flush code + // the current supporting code (shader translator(dx9asmtogl2), param setting(here) and flushing(glmgr_flush.inl) should work unchanged, even if the const mapping is changed. + int firstDirty = (int)baseSlot; + int highWater = (int)(baseSlot + slotCount); + + if ( highWater <= DXABSTRACT_VS_FIRST_BONE_SLOT ) { - if ( baseSlot < DXABSTRACT_VS_FIRST_BONE_SLOT ) + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater ); + } + else if ( highWater <= (DXABSTRACT_VS_LAST_BONE_SLOT+1) ) + { + if ( firstDirty < DXABSTRACT_VS_FIRST_BONE_SLOT ) { - // The register set crosses between the constant buffers - should only happen at startup during init. - m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); - m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)MIN( baseSlot + slotCount, DXABSTRACT_VS_FIRST_BONE_SLOT ) ); - baseSlot = DXABSTRACT_VS_FIRST_BONE_SLOT; + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, MIN( DXABSTRACT_VS_FIRST_BONE_SLOT, highWater ) ); + firstDirty = DXABSTRACT_VS_FIRST_BONE_SLOT; } - int nNumActualBones = ( baseSlot + slotCount ) - DXABSTRACT_VS_FIRST_BONE_SLOT; + int nNumActualBones = ( firstDirty + slotCount ) - DXABSTRACT_VS_FIRST_BONE_SLOT; m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones ); } else { - m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, (int)baseSlot ); - m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, (int)(baseSlot + slotCount) ); + const int maxBoneSlots = ( DXABSTRACT_VS_LAST_BONE_SLOT + 1 ) - DXABSTRACT_VS_FIRST_BONE_SLOT; + + if ( firstDirty > DXABSTRACT_VS_LAST_BONE_SLOT ) + { + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty - maxBoneSlots ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots ); + } + else if ( firstDirty >= DXABSTRACT_VS_FIRST_BONE_SLOT ) + { + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = DXABSTRACT_VS_LAST_BONE_SLOT + 1; + + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, DXABSTRACT_VS_FIRST_BONE_SLOT ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots ); + } + else + { + int nNumActualBones = ( DXABSTRACT_VS_LAST_BONE_SLOT + 1 ) - DXABSTRACT_VS_FIRST_BONE_SLOT; + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterBone, nNumActualBones ); + + m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone = MIN( m_programParamsF[kGLMVertexProgram].m_firstDirtySlotNonBone, firstDirty ); + m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone = MAX( m_programParamsF[kGLMVertexProgram].m_dirtySlotHighWaterNonBone, highWater - maxBoneSlots ); + } } } else @@ -2002,7 +2123,7 @@ FORCEINLINE void GLMContext::SetProgramParametersB( EGLMProgramType type, uint b #endif Assert( m_drawingLang == kGLMGLSL ); - Assert( type==kGLMVertexProgram ); + Assert( type==kGLMVertexProgram || type==kGLMFragmentProgram ); Assert( baseSlot < kGLMProgramParamBoolLimit ); Assert( baseSlot+boolCount <= kGLMProgramParamBoolLimit ); @@ -2069,21 +2190,21 @@ FORCEINLINE void GLMContext::SetSamplerTex( int sampler, CGLMTex *tex ) m_samplers[sampler].m_pBoundTex = tex; if ( tex ) { - if ( !gGL->m_bHave_GL_EXT_direct_state_access ) - { - if ( sampler != m_activeTexture ) + if ( !gGL->m_bHave_GL_EXT_direct_state_access ) { - gGL->glActiveTexture( GL_TEXTURE0 + sampler ); - m_activeTexture = sampler; - } + if ( sampler != m_activeTexture ) + { + gGL->glActiveTexture( GL_TEXTURE0 + sampler ); + m_activeTexture = sampler; + } - gGL->glBindTexture( tex->m_texGLTarget, tex->m_texName ); + gGL->glBindTexture( tex->m_texGLTarget, tex->m_texName ); + } + else + { + gGL->glBindMultiTextureEXT( GL_TEXTURE0 + sampler, tex->m_texGLTarget, tex->m_texName ); + } } - else - { - gGL->glBindMultiTextureEXT( GL_TEXTURE0 + sampler, tex->m_texGLTarget, tex->m_texName ); - } - } if ( !m_bUseSamplerObjects ) { @@ -2184,8 +2305,8 @@ FORCEINLINE void GLMContext::BindIndexBufferToCtx( CGLMBuffer *buff ) GLMPRINTF(( "--- GLMContext::BindIndexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); Assert( !buff || ( buff->m_buffGLTarget == GL_ELEMENT_ARRAY_BUFFER_ARB ) ); - - GLuint nGLName = buff ? buff->m_nHandle : 0; + + GLuint nGLName = buff ? buff->GetHandle() : 0; if ( m_nBoundGLBuffer[ kGLMIndexBuffer] == nGLName ) return; @@ -2199,8 +2320,8 @@ FORCEINLINE void GLMContext::BindVertexBufferToCtx( CGLMBuffer *buff ) GLMPRINTF(( "--- GLMContext::BindVertexBufferToCtx buff %p, GL name %d", buff, (buff) ? buff->m_nHandle : -1 )); Assert( !buff || ( buff->m_buffGLTarget == GL_ARRAY_BUFFER_ARB ) ); - - GLuint nGLName = buff ? buff->m_nHandle : 0; + + GLuint nGLName = buff ? buff->GetHandle() : 0; if ( m_nBoundGLBuffer[ kGLMVertexBuffer] == nGLName ) return; @@ -2232,6 +2353,45 @@ struct GLMTestParams int m_frameCount; // how many frames to test. }; +class GLMTester +{ + public: + + GLMTester(GLMTestParams *params); + ~GLMTester(); + + + // optionally callable by test routines to get basic drawables wired up + void StdSetup( void ); + void StdCleanup( void ); + + // callable by test routines to clear the frame or present it + void Clear( void ); + void Present( int seed ); + + // error reporting + void CheckGLError( const char *comment ); // obey m_params setting for console / debugger response + void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response + + void RunTests(); + + void RunOneTest( int testindex ); + + // test routines themselves + void Test0(); + void Test1(); + void Test2(); + void Test3(); + + GLMTestParams m_params; // copy of caller's params, do not mutate... + + // std-setup stuff + int m_drawWidth, m_drawHeight; + CGLMFBO *m_drawFBO; + CGLMTex *m_drawColorTex; + CGLMTex *m_drawDepthTex; +}; + class CShowPixelsParams { public: diff --git a/mp/src/public/togl/linuxwin/glmgrbasics.h b/mp/src/public/togl/linuxwin/glmgrbasics.h index ed380de4..a32938ad 100644 --- a/mp/src/public/togl/linuxwin/glmgrbasics.h +++ b/mp/src/public/togl/linuxwin/glmgrbasics.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // glmgrbasics.h // types, common headers, forward declarations, utilities @@ -10,20 +32,20 @@ #pragma once +#ifdef USE_SDL +#include "SDL_opengl.h" +#endif + #ifdef OSX - #include - #include - #include #include #include #include + #include + +#ifndef MAC_OS_X_VERSION_10_9 #include #include -#elif defined(DX_TO_GL_ABSTRACTION) - #include - #include -#else - #error +#endif #endif #include "tier0/platform.h" @@ -301,8 +323,10 @@ public: CUtlVector< GLMTextSection > m_sectionTable; }; +#ifndef OSX void GLMGPUTimestampManagerInit(); void GLMGPUTimestampManagerDeinit(); void GLMGPUTimestampManagerTick(); +#endif #endif // GLMBASICS_H diff --git a/mp/src/public/togl/linuxwin/glmgrext.h b/mp/src/public/togl/linuxwin/glmgrext.h index 8f1aba94..393942a7 100644 --- a/mp/src/public/togl/linuxwin/glmgrext.h +++ b/mp/src/public/togl/linuxwin/glmgrext.h @@ -1,4 +1,26 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // // glmgrext.h // helper file for extension testing and runtime importing of entry points @@ -91,3 +113,11 @@ #define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 #endif +#ifndef GL_MAP_PERSISTENT_BIT +#define GL_MAP_PERSISTENT_BIT 0x0040 +#endif + +#ifndef GL_MAP_COHERENT_BIT +#define GL_MAP_COHERENT_BIT 0x0080 +#endif + diff --git a/mp/src/public/togl/osx/cglmbuffer.h b/mp/src/public/togl/osx/cglmbuffer.h deleted file mode 100644 index 0b161000..00000000 --- a/mp/src/public/togl/osx/cglmbuffer.h +++ /dev/null @@ -1,99 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// cglmprogram.h -// GLMgr buffers (index / vertex) -// ... maybe add PBO later as well -//=============================================================================== - -#ifndef CGLMBUFFER_H -#define CGLMBUFFER_H - -#pragma once - -// ext links - -// http://www.opengl.org/registry/specs/ARB/vertex_buffer_object.txt - -//=============================================================================== - -// tokens not in the SDK headers - -//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT -// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 -//#endif - -//=============================================================================== - -// forward declarations - -class GLMContext; - -enum EGLMBufferType -{ - kGLMVertexBuffer, - kGLMIndexBuffer, - kGLMUniformBuffer, // for bindable uniform - kGLMPixelBuffer, // for PBO - - kGLMNumBufferTypes -}; - - // pass this in "options" to constructor to make a dynamic buffer -#define GLMBufferOptionDynamic 0x00000001 - -struct GLMBuffLockParams -{ - uint m_offset; - uint m_size; - bool m_nonblocking; - bool m_discard; -}; - -class CGLMBuffer -{ - -public: - void Lock( GLMBuffLockParams *params, char **addressOut ); - void Unlock( void ); - -//protected: - friend class GLMContext; // only GLMContext can make CGLMBuffer objects - friend class GLMTester; - friend class IDirect3D9; - friend class IDirect3DDevice9; - - CGLMBuffer ( GLMContext *ctx, EGLMBufferType type, uint size, uint options ); - ~CGLMBuffer ( ); - - void SetModes ( bool asyncMap, bool explicitFlush, bool force = false ); - void FlushRange ( uint offset, uint size ); - - GLMContext *m_ctx; // link back to parent context - EGLMBufferType m_type; - uint m_size; - GLenum m_buffGLTarget; // GL_ARRAY_BUFFER_ARB / GL_ELEMENT_BUFFER_ARB - GLuint m_name; // name of this program in the context - uint m_revision; // bump anytime the size changes or buffer is orphaned - bool m_enableAsyncMap; // mirror of the buffer state - bool m_enableExplicitFlush; // mirror of the buffer state - - bool m_bound; // true if bound to context - bool m_mapped; // is it currently mapped - uint m_dirtyMinOffset; // when equal, range is empty - uint m_dirtyMaxOffset; - - float *m_lastMappedAddress; - - // --------------------- pseudo-VBO support below here (explicitly for dynamic index buffers) - bool m_pseudo; // true if the m_name is 0, and the backing is plain RAM - - // in pseudo mode, there is just one RAM buffer that acts as the backing. - // expectation is that this mode would only be used for dynamic indices. - // since indices have to be consumed (copied to command stream) prior to return from a drawing call, - // there's no need to do any fencing or multibuffering. orphaning in particular becomes a no-op. - - char *m_pseudoBuf; // storage for pseudo buffer -}; - - -#endif \ No newline at end of file diff --git a/mp/src/public/togl/osx/cglmfbo.h b/mp/src/public/togl/osx/cglmfbo.h deleted file mode 100644 index ccf3e970..00000000 --- a/mp/src/public/togl/osx/cglmfbo.h +++ /dev/null @@ -1,91 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// cglmfbo.h -// GLMgr FBO's (render targets) -// -//=============================================================================== - -#ifndef CGLMFBO_H -#define CGLMFBO_H - -#pragma once - -#include "togl/rendermechanism.h" - -// good FBO references / recaps -// http://www.songho.ca/opengl/gl_fbo.html -// http://www.gamedev.net/reference/articles/article2331.asp - -// ext links - -// http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt -// http://www.opengl.org/registry/specs/EXT/framebuffer_multisample.txt - -//=============================================================================== - -// tokens not in the SDK headers - -#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT - #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 -#endif - -//=============================================================================== - -// forward declarations - -class GLMContext; - -// implicitly 16 maximum color attachments possible -enum EGLMFBOAttachment { - kAttColor0, kAttColor1, kAttColor2, kAttColor3, - kAttColor4, kAttColor5, kAttColor6, kAttColor7, - kAttColor8, kAttColor9, kAttColor10, kAttColor11, - kAttColor12, kAttColor13, kAttColor14, kAttColor15, - kAttDepth, kAttStencil, kAttDepthStencil, - kAttCount -}; - -struct GLMFBOTexAttachParams -{ - CGLMTex *m_tex; - int m_face; // keep zero if not cube map - int m_mip; // keep zero if notmip mapped - int m_zslice; // keep zero if not a 3D tex -}; - -class CGLMFBO -{ - -public: - -protected: - friend class GLMContext; // only GLMContext can make CGLMFBO objects - friend class GLMTester; - friend class CGLMTex; - - friend class IDirect3D9; - friend class IDirect3DDevice9; - - CGLMFBO( GLMContext *ctx ); - ~CGLMFBO( ); - - void TexAttach( GLMFBOTexAttachParams *params, EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); - void TexDetach( EGLMFBOAttachment attachIndex, GLenum fboBindPoint = GL_FRAMEBUFFER_EXT ); - // you can also pass GL_READ_FRAMEBUFFER_EXT or GL_DRAW_FRAMEBUFFER_EXT to selectively bind the receiving FBO to one or the other. - - void TexScrub( CGLMTex *tex ); - // search and destroy any attachment for the named texture - - bool IsReady( void ); // aka FBO completeness check - ready to draw - - GLMContext *m_ctx; // link back to parent context - - GLuint m_name; // name of this FBO in the context - - GLMFBOTexAttachParams m_attach[ kAttCount ]; // indexed by EGLMFBOAttachment - - int m_sizeX,m_sizeY; -}; - - -#endif diff --git a/mp/src/public/togl/osx/cglmprogram.h b/mp/src/public/togl/osx/cglmprogram.h deleted file mode 100644 index ee7f4de2..00000000 --- a/mp/src/public/togl/osx/cglmprogram.h +++ /dev/null @@ -1,291 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// cglmprogram.h -// GLMgr programs (ARBVP/ARBfp) -// -//=============================================================================== - -#ifndef CGLMPROGRAM_H -#define CGLMPROGRAM_H - -#include - -#pragma once - -// good ARB program references -// http://petewarden.com/notes/archives/2005/05/fragment_progra_2.html -// http://petewarden.com/notes/archives/2005/06/fragment_progra_3.html - -// ext links - -// http://www.opengl.org/registry/specs/ARB/vertex_program.txt -// http://www.opengl.org/registry/specs/ARB/fragment_program.txt -// http://www.opengl.org/registry/specs/EXT/gpu_program_parameters.txt - - -//=============================================================================== - -// tokens not in the SDK headers - -//#ifndef GL_DEPTH_STENCIL_ATTACHMENT_EXT -// #define GL_DEPTH_STENCIL_ATTACHMENT_EXT 0x84F9 -//#endif - -//=============================================================================== - -// forward declarations - -class GLMContext; -class CGLMShaderPair; -class CGLMShaderPairCache; - -// CGLMProgram can contain two flavors of the same program, one in assembler, one in GLSL. -// these flavors are pretty different in terms of the API's that are used to activate them - -// for example, assembler programs can just get bound to the context, whereas GLSL programs -// have to be linked. To some extent we try to hide that detail inside GLM. - -// for now, make CGLMProgram a container, it does not set policy or hold a preference as to which -// flavor you want to use. GLMContext has to handle that. - -enum EGLMProgramType -{ - kGLMVertexProgram, - kGLMFragmentProgram, - - kGLMNumProgramTypes -}; - -enum EGLMProgramLang -{ - kGLMARB, - kGLMGLSL, - - kGLMNumProgramLangs -}; - -struct GLMShaderDesc -{ - union - { - GLuint arb; // ARB program object name - GLhandleARB glsl; // GLSL shader object handle (void*) - } m_object; - - // these can change if shader text is edited - bool m_textPresent; // is this flavor(lang) of text present in the buffer? - int m_textOffset; // where is it - int m_textLength; // how big - - bool m_compiled; // has this text been through a compile attempt - bool m_valid; // and if so, was the compile successful - - int m_slowMark; // has it been flagged during a non native draw batch before. increment every time it's slow. - - int m_highWater; // vount of vec4's in the major uniform array ("vc" on vs, "pc" on ps) - // written by dxabstract.... gross! -}; - -GLenum GLMProgTypeToARBEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target -GLenum GLMProgTypeToGLSLEnum( EGLMProgramType type ); // map vert/frag to ARB asm bind target - -class CGLMProgram -{ -public: - friend class CGLMShaderPairCache; - friend class CGLMShaderPair; - friend class GLMContext; // only GLMContext can make CGLMProgram objects - friend class GLMTester; - friend class IDirect3D9; - friend class IDirect3DDevice9; - - //=============================== - - // constructor is very light, it just makes one empty program object per flavor. - CGLMProgram( GLMContext *ctx, EGLMProgramType type ); - ~CGLMProgram( ); - - void SetProgramText ( char *text ); // import text to GLM object - invalidate any prev compiled program - - bool CompileActiveSources ( void ); // compile only the flavors that were provided. - bool Compile ( EGLMProgramLang lang ); - bool CheckValidity ( EGLMProgramLang lang ); - - void LogSlow ( EGLMProgramLang lang ); // detailed spew when called for first time; one liner or perhaps silence after that - - void GetLabelIndexCombo ( char *labelOut, int labelOutMaxChars, int *indexOut, int *comboOut ); - void GetComboIndexNameString ( char *stringOut, int stringOutMaxChars ); // mmmmmmmm-nnnnnnnn-filename - -#if GLMDEBUG - bool PollForChanges( void ); // check mirror for changes. - void ReloadStringFromEditable( void ); // populate m_string from editable item (react to change) - bool SyncWithEditable( void ); -#endif - - //=============================== - - // common stuff - - GLMContext *m_ctx; // link back to parent context - - EGLMProgramType m_type; // vertex or pixel - - uint m_serial; // serial number for hashing - - char *m_text; // copy of text passed into constructor. Can change if editable shaders is enabled. - // note - it can contain multiple flavors, so use CGLMTextSectioner to scan it and locate them -#if GLMDEBUG - CGLMEditableTextItem *m_editable; // editable text item for debugging -#endif - - GLMShaderDesc m_descs[ kGLMNumProgramLangs ]; - - uint m_samplerMask; // (1< m_layoutMap; -}; - -//=============================================================================== - -// a sampler specifies desired state for drawing on a given sampler index -// this is the combination of a texture choice and a set of sampler parameters -// see http://msdn.microsoft.com/en-us/library/bb172602(VS.85).aspx - - -struct GLMTexSamplingParams -{ - GLenum m_addressModes[3]; // S, T, R - GLfloat m_borderColor[4]; // R,G,B,A - - GLenum m_magFilter; - GLenum m_minFilter; - - GLfloat m_mipmapBias; - GLint m_minMipLevel; - GLint m_maxMipLevel; - GLint m_maxAniso; - GLenum m_compareMode; // only used for depth and stencil type textures - bool m_srgb; // srgb texture read... -}; - -struct GLMTexLockParams -{ - // input params which identify the slice of interest - CGLMTex *m_tex; - int m_face; - int m_mip; - - // identifies the region of the slice - GLMRegion m_region; - - // tells GLM to force re-read of the texels back from GL - // i.e. "I know I stepped on those texels with a draw or blit - the GLM copy is stale" - bool m_readback; -}; - -struct GLMTexLockDesc -{ - GLMTexLockParams m_req; // form of the lock request - - bool m_active; // set true at lock time. cleared at unlock time. - - int m_sliceIndex; // which slice in the layout - int m_sliceBaseOffset; // where is that in the texture data - int m_sliceRegionOffset; // offset to the start (lowest address corner) of the region requested -}; - -//=============================================================================== - -#define GLM_SAMPLER_COUNT 16 - -typedef CBitVec CTexBindMask; - -enum EGLMTexSliceFlag -{ - kSliceValid = 0x01, // slice has been teximage'd in whole at least once - set to 0 initially - kSliceStorageValid = 0x02, // if backing store is available, this slice's data is a valid copy - set to 0 initially - kSliceLocked = 0x04, // are one or more locks outstanding on this slice - kSliceFullyDirty = 0x08, // does the slice need to be fully downloaded at unlock time (disregard dirty rects) -}; - -class CGLMTex -{ - -public: - - void Lock( GLMTexLockParams *params, char** addressOut, int* yStrideOut, int *zStrideOut ); - void Unlock( GLMTexLockParams *params ); - -protected: - friend class GLMContext; // only GLMContext can make CGLMTex objects - friend class GLMTester; - friend class CGLMFBO; - - friend class IDirect3DDevice9; - friend class IDirect3DBaseTexture9; - friend class IDirect3DTexture9; - friend class IDirect3DSurface9; - friend class IDirect3DCubeTexture9; - friend class IDirect3DVolumeTexture9; - - CGLMTex( GLMContext *ctx, GLMTexLayout *layout, GLMTexSamplingParams *sampling, char *debugLabel = NULL ); - ~CGLMTex( ); - - int CalcSliceIndex( int face, int mip ); - void CalcTexelDataOffsetAndStrides( int sliceIndex, int x, int y, int z, int *offsetOut, int *yStrideOut, int *zStrideOut ); - - void ApplySamplingParams( GLMTexSamplingParams *params, bool noCheck=FALSE ); - - void ReadTexels( GLMTexLockDesc *desc, bool readWholeSlice=true ); - void WriteTexels( GLMTexLockDesc *desc, bool writeWholeSlice=true, bool noDataWrite=false ); - // last param lets us send NULL data ptr (only legal with uncompressed formats, beware) - // this helps out ResetSRGB. - - void ResetSRGB( bool srgb, bool noDataWrite ); - // re-specify texture format to match desired sRGB form - // noWrite means send NULL for texel source addresses instead of actual data - ideal for RT's - - GLMTexLayout *m_layout; // layout of texture (shared across all tex with same layout) - int m_minActiveMip;//index of lowest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. - int m_maxActiveMip;//index of highest mip that has been written. used to drive setting of GL_TEXTURE_MAX_LEVEL. - - GLMTexSamplingParams m_sampling; // mirror of sampling params currently embodied in the texture - // (consult this at draw time, in order to know if changes need to be made) - - GLMContext *m_ctx; // link back to parent context - - GLuint m_texName; // name of this texture in the context - bool m_texClientStorage; // was CS selecetd for texture - bool m_texPreloaded; // has it been kicked into VRAM with GLMContext::PreloadTex yet - - GLuint m_rboName; // name of MSAA RBO backing the tex if MSAA enabled (or zero) - bool m_rboDirty; // has RBO been drawn on - i.e. needs to be blitted back to texture if texture is going to be sampled from - - CTexBindMask m_bindPoints; // true for each place in the parent ctx where currently - // bound (indexed via EGLMTexCtxBindingIndex) - - int m_rtAttachCount; // how many RT's have this texture attached somewhere - - char *m_backing; // backing storage if available - - int m_lockCount; // lock reqs are stored in the GLMContext for tracking - - CUtlVector m_sliceFlags; - - char *m_debugLabel; // strdup() of debugLabel passed in, or NULL -}; - - -#endif diff --git a/mp/src/public/togl/osx/dxabstract.h b/mp/src/public/togl/osx/dxabstract.h deleted file mode 100644 index 92f6bc32..00000000 --- a/mp/src/public/togl/osx/dxabstract.h +++ /dev/null @@ -1,804 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// -// -//================================================================================================== - -#ifndef DXABSTRACT_H -#define DXABSTRACT_H -#ifdef _WIN32 -#pragma once -#endif - -#include "togl/rendermechanism.h" - -#include "materialsystem/ishader.h" - -// Uncomment this on Windows if you want to compile the Windows GL version. -// #undef USE_ACTUAL_DX - -#ifdef USE_ACTUAL_DX - -#ifndef WIN32 -#error sorry man -#endif -#ifdef _X360 -#include "d3d9.h" -#include "d3dx9.h" -#else -#include -#include "../../dx9sdk/include/d3d9.h" -#include "../../dx9sdk/include/d3dx9.h" -#endif -typedef HWND VD3DHWND; - -#else - -#ifdef WIN32 -#error Gl on win32? -#endif - -#include "tier0/platform.h" - -#ifndef DX_TO_GL_ABSTRACTION -#define DX_TO_GL_ABSTRACTION -#endif - -#include "bitmap/imageformat.h" -#include "togl/rendermechanism.h" - -#ifdef OSX -extern "C" void Debugger(void); -#endif - -// turn this on to get refcount logging from IUnknown -#define IUNKNOWN_ALLOC_SPEW 0 -#define IUNKNOWN_ALLOC_SPEW_MARK_ALL 0 - - -// ------------------------------------------------------------------------------------------------------------------------------ // -// DEFINES -// ------------------------------------------------------------------------------------------------------------------------------ // - -typedef void* VD3DHWND; -typedef void* VD3DHANDLE; - - -TOGL_INTERFACE void toglGetClientRect( VD3DHWND hWnd, RECT *destRect ); - -struct TOGL_CLASS IUnknown -{ - int m_refcount[2]; - bool m_mark; - - IUnknown( void ) - { - m_refcount[0] = 1; - m_refcount[1] = 0; - m_mark = (IUNKNOWN_ALLOC_SPEW_MARK_ALL != 0); // either all are marked, or only the ones that have SetMark(true) called on them - - #if IUNKNOWN_ALLOC_SPEW - if (m_mark) - { - GLMPRINTF(("-A- IUnew (%08x) refc -> (%d,%d) ",this,m_refcount[0],m_refcount[1])); - } - #endif - }; - - virtual ~IUnknown( void ) - { - #if IUNKNOWN_ALLOC_SPEW - if (m_mark) - { - GLMPRINTF(("-A- IUdel (%08x) ",this )); - } - #endif - }; - - void AddRef( int which=0, char *comment = NULL ) - { - Assert( which >= 0 ); - Assert( which < 2 ); - m_refcount[which]++; - - #if IUNKNOWN_ALLOC_SPEW - if (m_mark) - { - GLMPRINTF(("-A- IUAddRef (%08x,%d) refc -> (%d,%d) [%s]",this,which,m_refcount[0],m_refcount[1],comment?comment:"...")) ; - if (!comment) - { - GLMPRINTF(("")) ; // place to hang a breakpoint - } - } - #endif - }; - - ULONG __stdcall Release( int which=0, char *comment = NULL ) - { - Assert( which >= 0 ); - Assert( which < 2 ); - - //int oldrefcs[2] = { m_refcount[0], m_refcount[1] }; - bool deleting = false; - - m_refcount[which]--; - if ( (!m_refcount[0]) && (!m_refcount[1]) ) - { - deleting = true; - } - - #if IUNKNOWN_ALLOC_SPEW - if (m_mark) - { - GLMPRINTF(("-A- IURelease (%08x,%d) refc -> (%d,%d) [%s] %s",this,which,m_refcount[0],m_refcount[1],comment?comment:"...",deleting?"->DELETING":"")); - if (!comment) - { - GLMPRINTF(("")) ; // place to hang a breakpoint - } - } - #endif - - if (deleting) - { - if (m_mark) - { - GLMPRINTF(("")) ; // place to hang a breakpoint - } - delete this; - return 0; - } - else - { - return m_refcount[0]; - } - }; - - void SetMark( bool markValue, char *comment=NULL ) - { - #if IUNKNOWN_ALLOC_SPEW - if (!m_mark && markValue) // leading edge detect - { - // print the same thing that the constructor would have printed if it had been marked from the beginning - // i.e. it's anticipated that callers asking for marking will do so right at create time - GLMPRINTF(("-A- IUSetMark (%08x) refc -> (%d,%d) (%s) ",this,m_refcount[0],m_refcount[1],comment?comment:"...")); - } - #endif - - m_mark = markValue; - } -}; - - -// ------------------------------------------------------------------------------------------------------------------------------ // -// INTERFACES -// ------------------------------------------------------------------------------------------------------------------------------ // - -struct TOGL_CLASS IDirect3DResource9 : public IUnknown -{ - IDirect3DDevice9 *m_device; // parent device - D3DRESOURCETYPE m_restype; - - DWORD SetPriority(DWORD PriorityNew); -}; - -struct TOGL_CLASS IDirect3DBaseTexture9 : public IDirect3DResource9 // "A Texture.." -{ - D3DSURFACE_DESC m_descZero; // desc of top level. - CGLMTex *m_tex; // a CGLMTex can represent all forms of tex - int m_srgbFlipCount; - - virtual ~IDirect3DBaseTexture9(); - D3DRESOURCETYPE GetType(); - DWORD GetLevelCount(); - HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); -}; - -struct TOGL_CLASS IDirect3DTexture9 : public IDirect3DBaseTexture9 // "Texture 2D" -{ - IDirect3DSurface9 *m_surfZero; // surf of top level. - - virtual ~IDirect3DTexture9(); - - HRESULT LockRect(UINT Level,D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); - HRESULT UnlockRect(UINT Level); - HRESULT GetSurfaceLevel(UINT Level,IDirect3DSurface9** ppSurfaceLevel); -}; - -struct TOGL_CLASS IDirect3DCubeTexture9 : public IDirect3DBaseTexture9 // "Texture Cube Map" -{ - IDirect3DSurface9 *m_surfZero[6]; // surfs of top level. - - virtual ~IDirect3DCubeTexture9(); - - HRESULT GetCubeMapSurface(D3DCUBEMAP_FACES FaceType,UINT Level,IDirect3DSurface9** ppCubeMapSurface); - HRESULT GetLevelDesc(UINT Level,D3DSURFACE_DESC *pDesc); -}; - -struct TOGL_CLASS IDirect3DVolumeTexture9 : public IDirect3DBaseTexture9 // "Texture 3D" -{ - IDirect3DSurface9 *m_surfZero; // surf of top level. - D3DVOLUME_DESC m_volDescZero; // volume desc top level - - virtual ~IDirect3DVolumeTexture9(); - - HRESULT LockBox(UINT Level,D3DLOCKED_BOX* pLockedVolume,CONST D3DBOX* pBox,DWORD Flags); - HRESULT UnlockBox(UINT Level); - HRESULT GetLevelDesc( UINT level, D3DVOLUME_DESC *pDesc ); -}; - - -// for the moment, a "D3D surface" is modeled as a GLM tex, a face, and a mip. -// no Create method, these are filled in by the various create surface methods. - -struct TOGL_CLASS IDirect3DSurface9 : public IDirect3DResource9 -{ - virtual ~IDirect3DSurface9(); - - HRESULT LockRect(D3DLOCKED_RECT* pLockedRect,CONST RECT* pRect,DWORD Flags); - HRESULT UnlockRect(); - HRESULT GetDesc(D3DSURFACE_DESC *pDesc); - - D3DSURFACE_DESC m_desc; - CGLMTex *m_tex; - int m_face; - int m_mip; -}; - - - -struct TOGL_CLASS IDirect3D9 : public IUnknown -{ -public: - virtual ~IDirect3D9(); - - UINT GetAdapterCount(); //cheese: returns 1 - - HRESULT GetDeviceCaps (UINT Adapter,D3DDEVTYPE DeviceType,D3DCAPS9* pCaps); - HRESULT GetAdapterIdentifier (UINT Adapter,DWORD Flags,D3DADAPTER_IDENTIFIER9* pIdentifier); - HRESULT CheckDeviceFormat (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,DWORD Usage,D3DRESOURCETYPE RType,D3DFORMAT CheckFormat); - UINT GetAdapterModeCount (UINT Adapter,D3DFORMAT Format); - HRESULT EnumAdapterModes (UINT Adapter,D3DFORMAT Format,UINT Mode,D3DDISPLAYMODE* pMode); - HRESULT CheckDeviceType (UINT Adapter,D3DDEVTYPE DevType,D3DFORMAT AdapterFormat,D3DFORMAT BackBufferFormat,BOOL bWindowed); - HRESULT GetAdapterDisplayMode (UINT Adapter,D3DDISPLAYMODE* pMode); - HRESULT CheckDepthStencilMatch (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT AdapterFormat,D3DFORMAT RenderTargetFormat,D3DFORMAT DepthStencilFormat); - HRESULT CheckDeviceMultiSampleType (UINT Adapter,D3DDEVTYPE DeviceType,D3DFORMAT SurfaceFormat,BOOL Windowed,D3DMULTISAMPLE_TYPE MultiSampleType,DWORD* pQualityLevels); - - HRESULT CreateDevice (UINT Adapter,D3DDEVTYPE DeviceType,VD3DHWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface); -}; - -struct TOGL_CLASS IDirect3DSwapChain9 : public IUnknown -{ -}; - - - - // typedef enum D3DDECLUSAGE - // { - // D3DDECLUSAGE_POSITION = 0, - // D3DDECLUSAGE_BLENDWEIGHT = 1, - // D3DDECLUSAGE_BLENDINDICES = 2, - // D3DDECLUSAGE_NORMAL = 3, - // D3DDECLUSAGE_PSIZE = 4, - // D3DDECLUSAGE_TEXCOORD = 5, - // D3DDECLUSAGE_TANGENT = 6, - // D3DDECLUSAGE_BINORMAL = 7, - // D3DDECLUSAGE_TESSFACTOR = 8, - // D3DDECLUSAGE_POSITIONT = 9, - // D3DDECLUSAGE_COLOR = 10, - // D3DDECLUSAGE_FOG = 11, - // D3DDECLUSAGE_DEPTH = 12, - // D3DDECLUSAGE_SAMPLE = 13, - // } D3DDECLUSAGE, *LPD3DDECLUSAGE; - // Constants - // - // D3DDECLUSAGE_POSITION - // Position data ranging from (-1,-1) to (1,1). Use D3DDECLUSAGE_POSITION with - // a usage index of 0 to specify untransformed position for fixed function - // vertex processing and the n-patch tessellator. Use D3DDECLUSAGE_POSITION - // with a usage index of 1 to specify untransformed position in the fixed - // function vertex shader for vertex tweening. - // - // D3DDECLUSAGE_BLENDWEIGHT - // Blending weight data. Use D3DDECLUSAGE_BLENDWEIGHT with a usage index of 0 - // to specify the blend weights used in indexed and nonindexed vertex - // blending. - // - // D3DDECLUSAGE_BLENDINDICES - // Blending indices data. Use D3DDECLUSAGE_BLENDINDICES with a usage index of - // 0 to specify matrix indices for indexed paletted skinning. - // - // D3DDECLUSAGE_NORMAL - // Vertex normal data. Use D3DDECLUSAGE_NORMAL with a usage index of 0 to - // specify vertex normals for fixed function vertex processing and the n-patch - // tessellator. Use D3DDECLUSAGE_NORMAL with a usage index of 1 to specify - // vertex normals for fixed function vertex processing for vertex tweening. - // - // D3DDECLUSAGE_PSIZE - // Point size data. Use D3DDECLUSAGE_PSIZE with a usage index of 0 to specify - // the point-size attribute used by the setup engine of the rasterizer to - // expand a point into a quad for the point-sprite functionality. - // - // D3DDECLUSAGE_TEXCOORD - // Texture coordinate data. Use D3DDECLUSAGE_TEXCOORD, n to specify texture - // coordinates in fixed function vertex processing and in pixel shaders prior - // to ps_3_0. These can be used to pass user defined data. - // - // D3DDECLUSAGE_TANGENT - // Vertex tangent data. - // - // D3DDECLUSAGE_BINORMAL - // Vertex binormal data. - // - // D3DDECLUSAGE_TESSFACTOR - // Single positive floating point value. Use D3DDECLUSAGE_TESSFACTOR with a - // usage index of 0 to specify a tessellation factor used in the tessellation - // unit to control the rate of tessellation. For more information about the - // data type, see D3DDECLTYPE_FLOAT1. - // - // D3DDECLUSAGE_POSITIONT - // Vertex data contains transformed position data ranging from (0,0) to - // (viewport width, viewport height). Use D3DDECLUSAGE_POSITIONT with a usage - // index of 0 to specify transformed position. When a declaration containing - // this is set, the pipeline does not perform vertex processing. - // - // D3DDECLUSAGE_COLOR - // Vertex data contains diffuse or specular color. Use D3DDECLUSAGE_COLOR with - // a usage index of 0 to specify the diffuse color in the fixed function - // vertex shader and pixel shaders prior to ps_3_0. Use D3DDECLUSAGE_COLOR - // with a usage index of 1 to specify the specular color in the fixed function - // vertex shader and pixel shaders prior to ps_3_0. - // - // D3DDECLUSAGE_FOG - // Vertex data contains fog data. Use D3DDECLUSAGE_FOG with a usage index of 0 - // to specify a fog blend value used after pixel shading finishes. This - // applies to pixel shaders prior to version ps_3_0. - // - // D3DDECLUSAGE_DEPTH - // Vertex data contains depth data. - // - // D3DDECLUSAGE_SAMPLE - // Vertex data contains sampler data. Use D3DDECLUSAGE_SAMPLE with a usage - // index of 0 to specify the displacement value to look up. It can be used - // only with D3DDECLUSAGE_LOOKUPPRESAMPLED or D3DDECLUSAGE_LOOKUP. - - //note the form of the list terminator.. - - // #define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0} - // typedef struct _D3DVERTEXELEMENT9 - // { - // WORD Stream; // Stream index - // WORD Offset; // Offset in the stream in bytes - // BYTE Type; // Data type - // BYTE Method; // Processing method - // BYTE Usage; // Semantics - // BYTE UsageIndex; // Semantic index - // } D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; - -#define MAX_D3DVERTEXELEMENTS 16 - -struct TOGL_CLASS IDirect3DVertexDeclaration9 : public IUnknown -{ -//public: - uint m_elemCount; - D3DVERTEXELEMENT9_GL m_elements[ MAX_D3DVERTEXELEMENTS ]; - - virtual ~IDirect3DVertexDeclaration9(); -}; - -struct TOGL_CLASS IDirect3DQuery9 : public IDirect3DResource9 //was IUnknown -{ -//public: - D3DQUERYTYPE m_type; // D3DQUERYTYPE_OCCLUSION or D3DQUERYTYPE_EVENT - GLMContext *m_ctx; - CGLMQuery *m_query; - - virtual ~IDirect3DQuery9(); - - HRESULT Issue(DWORD dwIssueFlags); - HRESULT GetData(void* pData,DWORD dwSize,DWORD dwGetDataFlags); -}; - -struct TOGL_CLASS IDirect3DVertexBuffer9 : public IDirect3DResource9 //was IUnknown -{ -//public: - GLMContext *m_ctx; - CGLMBuffer *m_vtxBuffer; - D3DVERTEXBUFFER_DESC m_vtxDesc; // to satisfy GetDesc - - virtual ~IDirect3DVertexBuffer9(); - HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); - HRESULT Unlock(); - HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); - -}; - -struct TOGL_CLASS IDirect3DIndexBuffer9 : public IDirect3DResource9 //was IUnknown -{ -//public: - GLMContext *m_ctx; - CGLMBuffer *m_idxBuffer; - D3DINDEXBUFFER_DESC m_idxDesc; // to satisfy GetDesc - - virtual ~IDirect3DIndexBuffer9(); - - HRESULT Lock(UINT OffsetToLock,UINT SizeToLock,void** ppbData,DWORD Flags); - HRESULT Unlock(); - HRESULT UnlockActualSize( uint nActualSize, const void *pActualData = NULL ); - HRESULT GetDesc(D3DINDEXBUFFER_DESC *pDesc); -}; - -struct TOGL_CLASS IDirect3DPixelShader9 : public IDirect3DResource9 //was IUnknown -{ -//public: - CGLMProgram *m_pixProgram; - uint m_pixHighWater; // count of active constant slots referenced by shader. - uint m_pixSamplerMask; // (1< m_stack; - int m_stackTop; // top of stack is at the highest index, this is that index. push increases, pop decreases. - - HRESULT Create( void ); - - D3DXMATRIX* GetTop(); - void Push(); - void Pop(); - void LoadIdentity(); - void LoadMatrix( const D3DXMATRIX *pMat ); - void MultMatrix( const D3DXMATRIX *pMat ); - void MultMatrixLocal( const D3DXMATRIX *pMat ); - HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); - - // Left multiply the current matrix with the computed rotation - // matrix, counterclockwise about the given axis with the given angle. - // (rotation is about the local origin of the object) - HRESULT RotateAxisLocal(CONST D3DXVECTOR3* pV, FLOAT Angle); - - // Left multiply the current matrix with the computed translation - // matrix. (transformation is about the local origin of the object) - HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); -}; -typedef ID3DXMatrixStack* LPD3DXMATRIXSTACK; - -struct TOGL_CLASS IDirect3DDevice9 : public IUnknown -{ -public: - // members - - IDirect3DDevice9Params m_params; // mirror of the creation inputs - - // D3D flavor stuff - IDirect3DSurface9 *m_rtSurfaces[16]; // current color RT surfaces. [0] is initially == m_defaultColorSurface - IDirect3DSurface9 *m_dsSurface; // current DS RT surface. can be changed! - - IDirect3DSurface9 *m_defaultColorSurface; // default color surface. - IDirect3DSurface9 *m_defaultDepthStencilSurface; // queried by GetDepthStencilSurface. - - IDirect3DVertexDeclaration9 *m_vertDecl; // Set by SetVertexDeclaration... - D3DStreamDesc m_streams[ D3D_MAX_STREAMS ]; // Set by SetStreamSource.. - D3DIndexDesc m_indices; // Set by SetIndices.. - - IDirect3DVertexShader9 *m_vertexShader; // Set by SetVertexShader... - IDirect3DPixelShader9 *m_pixelShader; // Set by SetPixelShader... - - IDirect3DBaseTexture9 *m_textures[16]; // set by SetTexture... NULL if stage inactive - D3DSamplerDesc m_samplers[16]; // set by SetSamplerState.. - // GLM flavor stuff - GLMContext *m_ctx; - CGLMFBO *m_drawableFBO; // this FBO should have all the attachments set to match m_rtSurfaces and m_dsSurface. - - // GL state - struct - { - // render state buckets - GLAlphaTestEnable_t m_AlphaTestEnable; - GLAlphaTestFunc_t m_AlphaTestFunc; - - GLAlphaToCoverageEnable_t m_AlphaToCoverageEnable; - - GLDepthTestEnable_t m_DepthTestEnable; - GLDepthMask_t m_DepthMask; - GLDepthFunc_t m_DepthFunc; - - GLClipPlaneEnable_t m_ClipPlaneEnable[kGLMUserClipPlanes]; - GLClipPlaneEquation_t m_ClipPlaneEquation[kGLMUserClipPlanes]; - - GLColorMaskSingle_t m_ColorMaskSingle; - GLColorMaskMultiple_t m_ColorMaskMultiple; - - GLCullFaceEnable_t m_CullFaceEnable; - GLCullFrontFace_t m_CullFrontFace; - GLPolygonMode_t m_PolygonMode; - GLDepthBias_t m_DepthBias; - GLScissorEnable_t m_ScissorEnable; - GLScissorBox_t m_ScissorBox; - GLViewportBox_t m_ViewportBox; - GLViewportDepthRange_t m_ViewportDepthRange; - - GLBlendEnable_t m_BlendEnable; - GLBlendFactor_t m_BlendFactor; - GLBlendEquation_t m_BlendEquation; - GLBlendColor_t m_BlendColor; - GLBlendEnableSRGB_t m_BlendEnableSRGB; - - GLStencilTestEnable_t m_StencilTestEnable; - GLStencilFunc_t m_StencilFunc; - GLStencilOp_t m_StencilOp; - GLStencilWriteMask_t m_StencilWriteMask; - - GLClearColor_t m_ClearColor; - GLClearDepth_t m_ClearDepth; - GLClearStencil_t m_ClearStencil; - - bool m_FogEnable; // not really pushed to GL, just latched here - - // samplers - GLMTexSamplingParams m_samplers[ 16 ]; - - // bindings...hmmm... - - // dirty-bits - uint m_stateDirtyMask; // covers the state blocks, indexed by 1<m_nCurOwnerThreadId; } - -}; - -struct ID3DXInclude -{ - virtual HRESULT Open(D3DXINCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) = 0; - virtual HRESULT Close(LPCVOID pData) = 0; -}; -typedef ID3DXInclude* LPD3DXINCLUDE; - - -struct TOGL_CLASS ID3DXBuffer : public IUnknown -{ - void* GetBufferPointer(); - DWORD GetBufferSize(); -}; - -typedef ID3DXBuffer* LPD3DXBUFFER; - -class TOGL_CLASS ID3DXConstantTable : public IUnknown -{ -}; -typedef ID3DXConstantTable* LPD3DXCONSTANTTABLE; - - - -// ------------------------------------------------------------------------------------------------------------------------------ // -// D3DX stuff. -// ------------------------------------------------------------------------------------------------------------------------------ // - -TOGL_INTERFACE const char* D3DXGetPixelShaderProfile( IDirect3DDevice9 *pDevice ); - - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixMultiply( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM1, CONST D3DXMATRIX *pM2 ); -TOGL_INTERFACE D3DXVECTOR3* D3DXVec3TransformCoord( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV, CONST D3DXMATRIX *pM ); - -TOGL_INTERFACE HRESULT D3DXCreateMatrixStack( DWORD Flags, LPD3DXMATRIXSTACK* ppStack); -TOGL_INTERFACE void D3DXMatrixIdentity( D3DXMATRIX * ); - -TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Subtract( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) -{ - pOut->x = pV1->x - pV2->x; - pOut->y = pV1->y - pV2->y; - pOut->z = pV1->z - pV2->z; - return pOut; -} - -TOGL_INTERFACE D3DXINLINE D3DXVECTOR3* D3DXVec3Cross( D3DXVECTOR3 *pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) -{ - D3DXVECTOR3 v; - - v.x = pV1->y * pV2->z - pV1->z * pV2->y; - v.y = pV1->z * pV2->x - pV1->x * pV2->z; - v.z = pV1->x * pV2->y - pV1->y * pV2->x; - - *pOut = v; - return pOut; -} - -TOGL_INTERFACE D3DXINLINE FLOAT D3DXVec3Dot( CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2 ) -{ - return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z; -} - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixInverse( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM ); - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranspose( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM ); - -TOGL_INTERFACE D3DXPLANE* D3DXPlaneNormalize( D3DXPLANE *pOut, CONST D3DXPLANE *pP); - -TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Transform( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV, CONST D3DXMATRIX *pM ); - - -TOGL_INTERFACE D3DXVECTOR4* D3DXVec4Normalize( D3DXVECTOR4 *pOut, CONST D3DXVECTOR4 *pV ); - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z ); - -// Build an ortho projection matrix. (right-handed) -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixOrthoOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn,FLOAT zf ); - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveRH( D3DXMATRIX *pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf ); - -TOGL_INTERFACE D3DXMATRIX* D3DXMatrixPerspectiveOffCenterRH( D3DXMATRIX *pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf ); - -// Transform a plane by a matrix. The vector (a,b,c) must be normal. -// M should be the inverse transpose of the transformation desired. -TOGL_INTERFACE D3DXPLANE* D3DXPlaneTransform( D3DXPLANE *pOut, CONST D3DXPLANE *pP, CONST D3DXMATRIX *pM ); - -TOGL_INTERFACE IDirect3D9 *Direct3DCreate9(UINT SDKVersion); - -TOGL_INTERFACE void D3DPERF_SetOptions( DWORD dwOptions ); - -TOGL_INTERFACE HRESULT D3DXCompileShader( - LPCSTR pSrcData, - UINT SrcDataLen, - CONST D3DXMACRO* pDefines, - LPD3DXINCLUDE pInclude, - LPCSTR pFunctionName, - LPCSTR pProfile, - DWORD Flags, - LPD3DXBUFFER* ppShader, - LPD3DXBUFFER* ppErrorMsgs, - LPD3DXCONSTANTTABLE* ppConstantTable); - - -#endif // USE_ACTUAL_DX - -// fake D3D usage constant for SRGB tex creation -#define D3DUSAGE_TEXTURE_SRGB (0x80000000L) - -#endif // DXABSTRACT_H diff --git a/mp/src/public/togl/osx/dxabstract_types.h b/mp/src/public/togl/osx/dxabstract_types.h deleted file mode 100644 index 6ecc82f0..00000000 --- a/mp/src/public/togl/osx/dxabstract_types.h +++ /dev/null @@ -1,1710 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// dxabstract_types.h -// -//================================================================================================== -#ifndef DXABSTRACT_TYPES_H -#define DXABSTRACT_TYPES_H - -#pragma once - -#if GL_BATCH_PERF_ANALYSIS - class simple_bitmap; -#endif - -struct IUnknown; -struct IDirect3D9; -struct IDirect3DDevice9; -struct IDirect3DResource9; -struct IDirect3DBaseTexture9; -struct IDirect3DTexture9; -struct IDirect3DCubeTexture9; -struct IDirect3DVolumeTexture9; -struct IDirect3DSurface9; -struct IDirect3DVertexDeclaration9; -struct IDirect3DQuery9; -struct IDirect3DVertexBuffer9; -struct IDirect3DIndexBuffer9; -struct IDirect3DPixelShader9; -struct IDirect3DVertexShader9; -struct IDirect3DDevice9Params; - -class GLMContext; -struct GLMRect; -struct GLMShaderPairInfo; -class CGLMBuffer; -class CGLMQuery; -class CGLMTex; -class CGLMProgram; -class CGLMFBO; - -#ifdef TOGL_DLL_EXPORT - #define TOGL_INTERFACE DLL_EXPORT - #define TOGL_OVERLOAD DLL_GLOBAL_EXPORT - #define TOGL_CLASS DLL_CLASS_EXPORT - #define TOGL_GLOBAL DLL_GLOBAL_EXPORT -#else - #define TOGL_INTERFACE DLL_IMPORT - #define TOGL_OVERLOAD DLL_GLOBAL_IMPORT - #define TOGL_CLASS DLL_CLASS_IMPORT - #define TOGL_GLOBAL DLL_GLOBAL_IMPORT -#endif - -#define TOGLMETHODCALLTYPE __stdcall -//#define TOGLMETHODCALLTYPE - -#define DXABSTRACT_BREAK_ON_ERROR() DebuggerBreak() - -typedef void* VD3DHWND; -typedef void* VD3DHANDLE; - -#define MAKEFOURCC(ch0, ch1, ch2, ch3) ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 )) - -// -// -// Stuff that would be in windows.h -// -// -#if !defined(_WINNT_) - - typedef int INT; - typedef unsigned long ULONG; - typedef long LONG; - typedef float FLOAT; - typedef unsigned short WORD; - typedef long long LONGLONG; - typedef unsigned int UINT; - typedef long HRESULT; - typedef unsigned char BYTE; - #define CONST const - - #if defined(POSIX) - typedef size_t ULONG_PTR; - #else - typedef unsigned long ULONG_PTR; - #endif - - typedef ULONG_PTR SIZE_T; - - typedef const char* LPCSTR; - typedef char* LPSTR; -#ifndef OSX - typedef unsigned int DWORD; - typedef DWORD* LPDWORD; -#endif - - - #define ZeroMemory RtlZeroMemory - #define RtlZeroMemory(Destination,Length) memset((Destination),0,(Length)) - - typedef union _LARGE_INTEGER - { - struct - { - DWORD LowPart; - LONG HighPart; - }; - struct - { - DWORD LowPart; - LONG HighPart; - } u; - LONGLONG QuadPart; - } LARGE_INTEGER; - - typedef struct _GUID - { - bool operator==( const struct _GUID &other ) const; - - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[ 8 ]; - } GUID; - - typedef struct _RECT - { - int left; - int top; - int right; - int bottom; - } RECT; - - typedef struct tagPOINT - { - LONG x; - LONG y; - } POINT, *PPOINT, *LPPOINT; - - typedef struct _MEMORYSTATUS - { - DWORD dwLength; - SIZE_T dwTotalPhys; - } MEMORYSTATUS, *LPMEMORYSTATUS; - - typedef DWORD COLORREF; - #define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) - - #define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) ) - - -// Mac header files like to define these -#ifdef S_FALSE -#undef S_FALSE -#endif -#ifdef S_OK -#undef S_OK -#endif -#ifdef E_FAIL -#undef E_FAIL -#endif -#ifdef E_OUTOFMEMORY -#undef E_OUTOFMEMORY -#endif -#ifdef FAILED -#undef FAILED -#endif -#ifdef SUCCEEDED -#undef SUCCEEDED -#endif - - #define S_FALSE ((HRESULT)0x00000001L) - #define S_OK 0 - #define E_FAIL ((HRESULT)0x80004005L) - #define E_OUTOFMEMORY ((HRESULT)0x8007000EL) - - #define FAILED(hr) ((HRESULT)(hr) < 0) - #define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) - - struct RGNDATA - { - }; - - typedef const void* LPCVOID; -#endif - -//----------------------------------------------------------------------------- - -typedef enum _D3DFORMAT D3DFORMAT; - -#define D3DSI_OPCODE_MASK 0x0000FFFF -#define D3DSP_TEXTURETYPE_MASK 0x78000000 - -#define D3DUSAGE_AUTOGENMIPMAP 0x00000400L -#define D3DSP_DCL_USAGE_MASK 0x0000000f - -#define D3DSP_OPCODESPECIFICCONTROL_MASK 0x00ff0000 -#define D3DSP_OPCODESPECIFICCONTROL_SHIFT 16 - - -/* Flags to construct D3DRS_COLORWRITEENABLE */ -#define D3DCOLORWRITEENABLE_RED (1L<<0) -#define D3DCOLORWRITEENABLE_GREEN (1L<<1) -#define D3DCOLORWRITEENABLE_BLUE (1L<<2) -#define D3DCOLORWRITEENABLE_ALPHA (1L<<3) - -#define D3DSGR_NO_CALIBRATION 0x00000000L - -#define D3DXINLINE inline - -#define D3D_SDK_VERSION 32 - -#define _FACD3D 0x876 -#define MAKE_D3DHRESULT( code ) MAKE_HRESULT( 1, _FACD3D, code ) - -#define D3DERR_NOTFOUND MAKE_D3DHRESULT(2150) -#define D3DERR_DEVICELOST MAKE_D3DHRESULT(2152) -#define D3DERR_NOTAVAILABLE MAKE_D3DHRESULT(2154) -#define D3DERR_DEVICENOTRESET MAKE_D3DHRESULT(2153) -#define D3DERR_INVALIDCALL MAKE_D3DHRESULT(2156) -#define D3DERR_DRIVERINTERNALERROR MAKE_D3DHRESULT(2087) -#define D3DERR_OUTOFVIDEOMEMORY MAKE_D3DHRESULT(380) -#define D3D_OK S_OK - -#define D3DPRESENT_RATE_DEFAULT 0x00000000 - -// -// DevCaps -// -// we need to see who in Source land is interested in these values, as dxabstract is currently reporting zero for the whole Caps word -#define D3DDEVCAPS_EXECUTESYSTEMMEMORY 0x00000010L /* Device can use execute buffers from system memory */ -#define D3DDEVCAPS_TLVERTEXSYSTEMMEMORY 0x00000040L /* Device can use TL buffers from system memory */ -#define D3DDEVCAPS_TLVERTEXVIDEOMEMORY 0x00000080L /* Device can use TL buffers from video memory */ -#define D3DDEVCAPS_TEXTURESYSTEMMEMORY 0x00000100L /* Device can texture from system memory */ -#define D3DDEVCAPS_TEXTUREVIDEOMEMORY 0x00000200L /* Device can texture from device memory */ -#define D3DDEVCAPS_DRAWPRIMTLVERTEX 0x00000400L /* Device can draw TLVERTEX primitives */ -#define D3DDEVCAPS_CANRENDERAFTERFLIP 0x00000800L /* Device can render without waiting for flip to complete */ -#define D3DDEVCAPS_TEXTURENONLOCALVIDMEM 0x00001000L /* Device can texture from nonlocal video memory */ -#define D3DDEVCAPS_SEPARATETEXTUREMEMORIES 0x00004000L /* Device is texturing from separate memory pools */ -#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ -#define D3DDEVCAPS_CANBLTSYSTONONLOCAL 0x00020000L /* Device supports a Tex Blt from system memory to non-local vidmem */ -#define D3DDEVCAPS_HWRASTERIZATION 0x00080000L /* Device has HW acceleration for rasterization */ -#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ -#define D3DDEVCAPS_QUINTICRTPATCHES 0x00200000L /* Device supports quintic Beziers and BSplines */ -#define D3DDEVCAPS_RTPATCHHANDLEZERO 0x00800000L /* Indicates that RT Patches may be drawn efficiently using handle 0 */ -#define D3DDEVCAPS_NPATCHES 0x01000000L /* Device supports N-Patches */ - -// -// PrimitiveMiscCaps -// -#define D3DPMISCCAPS_MASKZ 0x00000002L -#define D3DPMISCCAPS_CULLNONE 0x00000010L -#define D3DPMISCCAPS_CULLCW 0x00000020L -#define D3DPMISCCAPS_CULLCCW 0x00000040L -#define D3DPMISCCAPS_COLORWRITEENABLE 0x00000080L -#define D3DPMISCCAPS_CLIPPLANESCALEDPOINTS 0x00000100L /* Device correctly clips scaled points to clip planes */ -#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L /* device will clip post-transformed vertex primitives */ -#define D3DPMISCCAPS_TSSARGTEMP 0x00000400L /* device supports D3DTA_TEMP for temporary register */ -#define D3DPMISCCAPS_BLENDOP 0x00000800L /* device supports D3DRS_BLENDOP */ -#define D3DPMISCCAPS_NULLREFERENCE 0x00001000L /* Reference Device that doesnt render */ -#define D3DPMISCCAPS_PERSTAGECONSTANT 0x00008000L /* Device supports per-stage constants */ -#define D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000L /* Device supports different bit depths for MRT */ -#define D3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000L /* Device clamps fog blend factor per vertex */ - -// Flags field for Issue -#define D3DISSUE_END (1 << 0) // Tells the runtime to issue the end of a query, changing it's state to "non-signaled". -#define D3DISSUE_BEGIN (1 << 1) // Tells the runtime to issue the beginng of a query. - - -#define D3DPRESENT_INTERVAL_ONE 0x00000001L -#define D3DPRESENT_INTERVAL_IMMEDIATE 0x80000000L - -/* - * Options for clearing - */ -#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ -#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ -#define D3DCLEAR_STENCIL 0x00000004l /* Clear stencil planes */ - - -#define D3DENUM_WHQL_LEVEL 0x00000002L - - - - -#define D3DPTEXTURECAPS_NOPROJECTEDBUMPENV 0x00200000L /* Device does not support projected bump env lookup operation - in programmable and fixed function pixel shaders */ -#define D3DDEVCAPS2_STREAMOFFSET 0x00000001L /* Device supports offsets in streams. Must be set by DX9 drivers */ - -#define D3DDEVCAPS_PUREDEVICE 0x00100000L /* Device supports D3DCREATE_PUREDEVICE */ - -#define D3DCREATE_PUREDEVICE 0x00000010L -#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L -#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L -#define D3DCREATE_FPU_PRESERVE 0x00000002L -#define D3DPRASTERCAPS_FOGRANGE 0x00010000L -#define D3DPRASTERCAPS_FOGTABLE 0x00000100L -#define D3DPRASTERCAPS_FOGVERTEX 0x00000080L -#define D3DPRASTERCAPS_WFOG 0x00100000L -#define D3DPRASTERCAPS_ZFOG 0x00200000L -#define D3DPRASTERCAPS_MIPMAPLODBIAS 0x00002000L -#define D3DPRASTERCAPS_WBUFFER 0x00040000L -#define D3DPRASTERCAPS_ZTEST 0x00000010L - -// -// Caps2 -// -#define D3DCAPS2_CANCALIBRATEGAMMA 0x00100000L -#define D3DPRASTERCAPS_SCISSORTEST 0x01000000L -#define D3DPTEXTURECAPS_MIPCUBEMAP 0x00010000L /* Device can do mipmapped cube maps */ -#define D3DPTEXTURECAPS_ALPHA 0x00000004L /* Alpha in texture pixels is supported */ -#define D3DPTEXTURECAPS_SQUAREONLY 0x00000020L /* Only square textures are supported */ -#define D3DCREATE_MULTITHREADED 0x00000004L -#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L /* Device can support transformation and lighting in hardware and DRAWPRIMITIVES2EX must be also */ -#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L -#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L -#define D3DPTEXTURECAPS_CUBEMAP 0x00000800L /* Device can do cubemap textures */ -#define D3DPTEXTURECAPS_POW2 0x00000002L /* Power-of-2 texture dimensions are required - applies to non-Cube/Volume textures only. */ -#define D3DPTEXTURECAPS_NONPOW2CONDITIONAL 0x00000100L -#define D3DPTEXTURECAPS_PROJECTED 0x00000400L /* Device can do D3DTTFF_PROJECTED */ -#define D3DTEXOPCAPS_ADD 0x00000040L -#define D3DTEXOPCAPS_MODULATE2X 0x00000010L -#define D3DPRASTERCAPS_DEPTHBIAS 0x04000000L -#define D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS 0x02000000L -#define D3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L /* device supports D3DTSS_TCI_SPHEREMAP */ -#define D3DCAPS2_DYNAMICTEXTURES 0x20000000L - -// The following usages are valid only for querying CheckDeviceFormat -#define D3DUSAGE_QUERY_SRGBREAD (0x00010000L) -#define D3DUSAGE_QUERY_FILTER (0x00020000L) -#define D3DUSAGE_QUERY_SRGBWRITE (0x00040000L) -#define D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING (0x00080000L) -#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) - -/* Usages for Vertex/Index buffers */ -#define D3DUSAGE_WRITEONLY (0x00000008L) -#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) -#define D3DUSAGE_DONOTCLIP (0x00000020L) -#define D3DUSAGE_POINTS (0x00000040L) -#define D3DUSAGE_RTPATCHES (0x00000080L) -#define D3DUSAGE_NPATCHES (0x00000100L) - - -// Flags field for GetData -#define D3DGETDATA_FLUSH (1 << 0) // Tells the runtime to flush if the query is outstanding. - -#define D3DFVF_XYZ 0x002 - - -#define D3DTA_SELECTMASK 0x0000000f // mask for arg selector -#define D3DTA_DIFFUSE 0x00000000 // select diffuse color (read only) -#define D3DTA_CURRENT 0x00000001 // select stage destination register (read/write) -#define D3DTA_TEXTURE 0x00000002 // select texture color (read only) -#define D3DTA_TFACTOR 0x00000003 // select D3DRS_TEXTUREFACTOR (read only) -#define D3DTA_SPECULAR 0x00000004 // select specular color (read only) -#define D3DTA_TEMP 0x00000005 // select temporary register color (read/write) -#define D3DTA_CONSTANT 0x00000006 // select texture stage constant -#define D3DTA_COMPLEMENT 0x00000010 // take 1.0 - x (read modifier) -#define D3DTA_ALPHAREPLICATE 0x00000020 // replicate alpha to color components (read modifier) - - -#define D3DUSAGE_RENDERTARGET (0x00000001L) -#define D3DUSAGE_QUERY_VERTEXTEXTURE (0x00100000L) -#define D3DUSAGE_QUERY_FILTER (0x00020000L) -#define D3DUSAGE_DEPTHSTENCIL (0x00000002L) -#define D3DUSAGE_WRITEONLY (0x00000008L) -#define D3DUSAGE_SOFTWAREPROCESSING (0x00000010L) -#define D3DUSAGE_DYNAMIC (0x00000200L) - -#define D3DSI_INSTLENGTH_MASK 0x0F000000 -#define D3DSI_INSTLENGTH_SHIFT 24 -#define D3DSP_TEXTURETYPE_SHIFT 27 -#define D3DSP_REGTYPE_SHIFT 28 -#define D3DSP_REGTYPE_SHIFT2 8 -#define D3DSP_REGTYPE_MASK 0x70000000 -#define D3DSP_REGTYPE_MASK2 0x00001800 - -#define D3DSP_REGNUM_MASK 0x000007FF - -#define D3DSP_DSTMOD_SHIFT 20 -#define D3DSP_DSTMOD_MASK 0x00F00000 -#define D3DSPDM_MSAMPCENTROID (4<>8)&0xFF) -#define D3DSHADER_VERSION_MINOR(_Version) (((_Version)>>0)&0xFF) - -#define D3DSHADER_ADDRESSMODE_SHIFT 13 -#define D3DSHADER_ADDRESSMODE_MASK (1 << D3DSHADER_ADDRESSMODE_SHIFT) - -#define D3DPS_END() 0x0000FFFF - -// ps_2_0 texld controls -#define D3DSI_TEXLD_PROJECT (0x01 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) -#define D3DSI_TEXLD_BIAS (0x02 << D3DSP_OPCODESPECIFICCONTROL_SHIFT) - - -// destination parameter write mask -#define D3DSP_WRITEMASK_0 0x00010000 // Component 0 (X;Red) -#define D3DSP_WRITEMASK_1 0x00020000 // Component 1 (Y;Green) -#define D3DSP_WRITEMASK_2 0x00040000 // Component 2 (Z;Blue) -#define D3DSP_WRITEMASK_3 0x00080000 // Component 3 (W;Alpha) -#define D3DSP_WRITEMASK_ALL 0x000F0000 // All Components - -#define D3DVS_SWIZZLE_SHIFT 16 -#define D3DVS_SWIZZLE_MASK 0x00FF0000 - -// The following bits define where to take component X from: - -#define D3DVS_X_X (0 << D3DVS_SWIZZLE_SHIFT) -#define D3DVS_X_Y (1 << D3DVS_SWIZZLE_SHIFT) -#define D3DVS_X_Z (2 << D3DVS_SWIZZLE_SHIFT) -#define D3DVS_X_W (3 << D3DVS_SWIZZLE_SHIFT) - -// The following bits define where to take component Y from: - -#define D3DVS_Y_X (0 << (D3DVS_SWIZZLE_SHIFT + 2)) -#define D3DVS_Y_Y (1 << (D3DVS_SWIZZLE_SHIFT + 2)) -#define D3DVS_Y_Z (2 << (D3DVS_SWIZZLE_SHIFT + 2)) -#define D3DVS_Y_W (3 << (D3DVS_SWIZZLE_SHIFT + 2)) - -// The following bits define where to take component Z from: - -#define D3DVS_Z_X (0 << (D3DVS_SWIZZLE_SHIFT + 4)) -#define D3DVS_Z_Y (1 << (D3DVS_SWIZZLE_SHIFT + 4)) -#define D3DVS_Z_Z (2 << (D3DVS_SWIZZLE_SHIFT + 4)) -#define D3DVS_Z_W (3 << (D3DVS_SWIZZLE_SHIFT + 4)) - -// The following bits define where to take component W from: - -#define D3DVS_W_X (0 << (D3DVS_SWIZZLE_SHIFT + 6)) -#define D3DVS_W_Y (1 << (D3DVS_SWIZZLE_SHIFT + 6)) -#define D3DVS_W_Z (2 << (D3DVS_SWIZZLE_SHIFT + 6)) -#define D3DVS_W_W (3 << (D3DVS_SWIZZLE_SHIFT + 6)) - -// source parameter modifiers -#define D3DSP_SRCMOD_SHIFT 24 -#define D3DSP_SRCMOD_MASK 0x0F000000 - -// ------------------------------------------------------------------------------------------------------------------------------ // -// ENUMS -// ------------------------------------------------------------------------------------------------------------------------------ // - -typedef enum _D3DSHADER_PARAM_SRCMOD_TYPE -{ - D3DSPSM_NONE = 0<= 2.0 - - - D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0 - D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) - D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) - D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) - D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) - D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) - D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) - D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1) - D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values - D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused. -} D3DDECLTYPE; - -typedef enum _D3DDECLMETHOD -{ - D3DDECLMETHOD_DEFAULT = 0, - D3DDECLMETHOD_PARTIALU, - D3DDECLMETHOD_PARTIALV, - D3DDECLMETHOD_CROSSUV, // Normal - D3DDECLMETHOD_UV, - D3DDECLMETHOD_LOOKUP, // Lookup a displacement map - D3DDECLMETHOD_LOOKUPPRESAMPLED, // Lookup a pre-sampled displacement map -} D3DDECLMETHOD; - -typedef enum _D3DDECLUSAGE -{ - D3DDECLUSAGE_POSITION = 0, - D3DDECLUSAGE_BLENDWEIGHT = 1, - D3DDECLUSAGE_BLENDINDICES = 2, - D3DDECLUSAGE_NORMAL = 3, - D3DDECLUSAGE_PSIZE = 4, - D3DDECLUSAGE_TEXCOORD = 5, - D3DDECLUSAGE_TANGENT = 6, - D3DDECLUSAGE_BINORMAL = 7, - D3DDECLUSAGE_TESSFACTOR = 8, - D3DDECLUSAGE_PLUGH = 9, // mystery value - D3DDECLUSAGE_COLOR = 10, - D3DDECLUSAGE_FOG = 11, - D3DDECLUSAGE_DEPTH = 12, - D3DDECLUSAGE_SAMPLE = 13, -} D3DDECLUSAGE; - -typedef enum _D3DPRIMITIVETYPE -{ - D3DPT_POINTLIST = 1, - D3DPT_LINELIST = 2, - D3DPT_TRIANGLELIST = 4, - D3DPT_TRIANGLESTRIP = 5, - D3DPT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ -} D3DPRIMITIVETYPE; - -// ------------------------------------------------------------------------------------------------------------------------------ // -// STRUCTURES -// ------------------------------------------------------------------------------------------------------------------------------ // - -typedef struct TOGL_CLASS D3DXPLANE -{ - float& operator[]( int i ); - bool operator==( const D3DXPLANE &o ); - bool operator!=( const D3DXPLANE &o ); - operator float*(); - operator const float*() const; - - float a, b, c, d; -} D3DXPLANE; - -typedef enum _D3DVERTEXBLENDFLAGS -{ - D3DVBF_DISABLE = 0, // Disable vertex blending - D3DVBF_1WEIGHTS = 1, // 2 matrix blending - D3DVBF_2WEIGHTS = 2, // 3 matrix blending - D3DVBF_3WEIGHTS = 3, // 4 matrix blending - D3DVBF_TWEENING = 255, // blending using D3DRS_TWEENFACTOR - D3DVBF_0WEIGHTS = 256, // one matrix is used with weight 1.0 - D3DVBF_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum -} D3DVERTEXBLENDFLAGS; - -typedef struct _D3DINDEXBUFFER_DESC -{ - D3DFORMAT Format; - D3DRESOURCETYPE Type; - DWORD Usage; - D3DPOOL Pool; - UINT Size; -} D3DINDEXBUFFER_DESC; - -typedef struct _D3DVERTEXELEMENT9 -{ - WORD Stream; // Stream index - WORD Offset; // Offset in the stream in bytes - BYTE Type; // Data type - BYTE Method; // Processing method - BYTE Usage; // Semantics - BYTE UsageIndex; // Semantic index -} D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9; - - -#define MAX_DEVICE_IDENTIFIER_STRING 512 -typedef struct _D3DADAPTER_IDENTIFIER9 -{ - char Driver[MAX_DEVICE_IDENTIFIER_STRING]; - char Description[MAX_DEVICE_IDENTIFIER_STRING]; - char DeviceName[32]; /* Device name for GDI (ex. \\.\DISPLAY1) */ - - LARGE_INTEGER DriverVersion; /* Defined for 32 bit components */ - - DWORD VendorId; - DWORD DeviceId; - DWORD SubSysId; - DWORD Revision; - DWORD VideoMemory; - -} D3DADAPTER_IDENTIFIER9; - -typedef struct _D3DCOLORVALUE -{ - float r; - float g; - float b; - float a; -} D3DCOLORVALUE; - -typedef struct _D3DMATERIAL9 -{ - D3DCOLORVALUE Diffuse; /* Diffuse color RGBA */ - D3DCOLORVALUE Ambient; /* Ambient color RGB */ - D3DCOLORVALUE Specular; /* Specular 'shininess' */ - D3DCOLORVALUE Emissive; /* Emissive color RGB */ - float Power; /* Sharpness if specular highlight */ -} D3DMATERIAL9; - -typedef struct _D3DVOLUME_DESC -{ - D3DFORMAT Format; - D3DRESOURCETYPE Type; - DWORD Usage; - D3DPOOL Pool; - - UINT Width; - UINT Height; - UINT Depth; -} D3DVOLUME_DESC; - -typedef struct _D3DVIEWPORT9 -{ - DWORD X; - DWORD Y; /* Viewport Top left */ - DWORD Width; - DWORD Height; /* Viewport Dimensions */ - float MinZ; /* Min/max of clip Volume */ - float MaxZ; -} D3DVIEWPORT9; - -typedef struct _D3DPSHADERCAPS2_0 -{ - DWORD Caps; - INT DynamicFlowControlDepth; - INT NumTemps; - INT StaticFlowControlDepth; - INT NumInstructionSlots; -} D3DPSHADERCAPS2_0; - -typedef struct _D3DCAPS9 -{ - /* Device Info */ - D3DDEVTYPE DeviceType; - - /* Caps from DX7 Draw */ - DWORD Caps; - DWORD Caps2; - - /* Cursor Caps */ - DWORD CursorCaps; - - /* 3D Device Caps */ - DWORD DevCaps; - - DWORD PrimitiveMiscCaps; - DWORD RasterCaps; - DWORD TextureCaps; - DWORD TextureFilterCaps; // D3DPTFILTERCAPS for IDirect3DTexture9's - - DWORD MaxTextureWidth, MaxTextureHeight; - DWORD MaxVolumeExtent; - - DWORD MaxTextureAspectRatio; - DWORD MaxAnisotropy; - - DWORD TextureOpCaps; - DWORD MaxTextureBlendStages; - DWORD MaxSimultaneousTextures; - - DWORD VertexProcessingCaps; - DWORD MaxActiveLights; - DWORD MaxUserClipPlanes; - DWORD MaxVertexBlendMatrices; - DWORD MaxVertexBlendMatrixIndex; - - DWORD MaxPrimitiveCount; // max number of primitives per DrawPrimitive call - DWORD MaxStreams; - - DWORD VertexShaderVersion; - DWORD MaxVertexShaderConst; // number of vertex shader constant registers - - DWORD PixelShaderVersion; - - // Here are the DX9 specific ones - DWORD DevCaps2; - D3DPSHADERCAPS2_0 PS20Caps; - - DWORD NumSimultaneousRTs; // Will be at least 1 - DWORD MaxVertexShader30InstructionSlots; - DWORD MaxPixelShader30InstructionSlots; - - // only on Posix/GL - DWORD FakeSRGBWrite; // 1 for parts which can't support SRGB writes due to driver issues - 0 for others - DWORD MixedSizeTargets; // 1 for parts which can mix attachment sizes (RT's color vs depth) - DWORD CanDoSRGBReadFromRTs; // 0 when we're on Leopard, 1 when on Snow Leopard -} D3DCAPS9; - -typedef struct _D3DDISPLAYMODE -{ - UINT Width; - UINT Height; - UINT RefreshRate; - D3DFORMAT Format; -} D3DDISPLAYMODE; - -typedef struct _D3DGAMMARAMP -{ - WORD red [256]; - WORD green[256]; - WORD blue [256]; -} D3DGAMMARAMP; - - -/* Resize Optional Parameters */ -typedef struct _D3DPRESENT_PARAMETERS_ -{ - UINT BackBufferWidth; - UINT BackBufferHeight; - D3DFORMAT BackBufferFormat; - UINT BackBufferCount; - - D3DMULTISAMPLE_TYPE MultiSampleType; - DWORD MultiSampleQuality; - - D3DSWAPEFFECT SwapEffect; - VD3DHWND hDeviceWindow; - BOOL Windowed; - BOOL EnableAutoDepthStencil; - D3DFORMAT AutoDepthStencilFormat; - DWORD Flags; - - /* FullScreen_RefreshRateInHz must be zero for Windowed mode */ - UINT FullScreen_RefreshRateInHz; - UINT PresentationInterval; -} D3DPRESENT_PARAMETERS; - -typedef struct _D3DDEVICE_CREATION_PARAMETERS -{ - UINT AdapterOrdinal; - D3DDEVTYPE DeviceType; - VD3DHWND hFocusWindow; - DWORD BehaviorFlags; -} D3DDEVICE_CREATION_PARAMETERS; - -/* Structures for LockBox */ -typedef struct _D3DBOX -{ - UINT Left; - UINT Top; - UINT Right; - UINT Bottom; - UINT Front; - UINT Back; -} D3DBOX; - -typedef struct _D3DLOCKED_BOX -{ - INT RowPitch; - INT SlicePitch; - void* pBits; -} D3DLOCKED_BOX; - -typedef struct _D3DSURFACE_DESC -{ - D3DFORMAT Format; - D3DRESOURCETYPE Type; - DWORD Usage; - D3DPOOL Pool; - - D3DMULTISAMPLE_TYPE MultiSampleType; - DWORD MultiSampleQuality; - UINT Width; - UINT Height; -} D3DSURFACE_DESC; - - -typedef struct _D3DLOCKED_RECT -{ - INT Pitch; - void* pBits; -} D3DLOCKED_RECT; - - -typedef struct _D3DRASTER_STATUS -{ - BOOL InVBlank; - UINT ScanLine; -} D3DRASTER_STATUS; - -typedef enum _D3DLIGHTTYPE -{ - D3DLIGHT_POINT = 1, - D3DLIGHT_SPOT = 2, - D3DLIGHT_DIRECTIONAL = 3, - D3DLIGHT_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ -} D3DLIGHTTYPE; - -typedef struct TOGL_CLASS _D3DVECTOR -{ - float x; - float y; - float z; -} D3DVECTOR; - -class TOGL_CLASS D3DXVECTOR2 -{ -public: - operator FLOAT* (); - operator CONST FLOAT* () const; - - float x,y; -}; - -class TOGL_CLASS D3DXVECTOR3 : public D3DVECTOR -{ -public: - D3DXVECTOR3() {} - D3DXVECTOR3( float a, float b, float c ); - operator FLOAT* (); - operator CONST FLOAT* () const; -}; - -typedef enum _D3DXINCLUDE_TYPE -{ - D3DXINC_LOCAL, - - // force 32-bit size enum - D3DXINC_FORCE_DWORD = 0x7fffffff - -} D3DXINCLUDE_TYPE; - -typedef struct _D3DLIGHT9 -{ - D3DLIGHTTYPE Type; /* Type of light source */ - D3DCOLORVALUE Diffuse; /* Diffuse color of light */ - D3DCOLORVALUE Specular; /* Specular color of light */ - D3DCOLORVALUE Ambient; /* Ambient color of light */ - D3DVECTOR Position; /* Position in world space */ - D3DVECTOR Direction; /* Direction in world space */ - float Range; /* Cutoff range */ - float Falloff; /* Falloff */ - float Attenuation0; /* Constant attenuation */ - float Attenuation1; /* Linear attenuation */ - float Attenuation2; /* Quadratic attenuation */ - float Theta; /* Inner angle of spotlight cone */ - float Phi; /* Outer angle of spotlight cone */ -} D3DLIGHT9; - -class TOGL_CLASS D3DXVECTOR4 -{ -public: - D3DXVECTOR4() {} - D3DXVECTOR4( float a, float b, float c, float d ); - - float x,y,z,w; -}; - -//---------------------------------------------------------------------------- -// D3DXMACRO: -// ---------- -// Preprocessor macro definition. The application pass in a NULL-terminated -// array of this structure to various D3DX APIs. This enables the application -// to #define tokens at runtime, before the file is parsed. -//---------------------------------------------------------------------------- - -typedef struct _D3DXMACRO -{ - LPCSTR Name; - LPCSTR Definition; - -} D3DXMACRO, *LPD3DXMACRO; - -// ------------------------------------------------------------------------------------------------------------------------------ // -// ------------------------------------------------------------------------------------------------------------------------------ // -// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. -// -// Also look for any functions marked with "**** FIXED FUNCTION STUFF" -// -// It's only laying around here so we don't have to chop up the shader system a lot to strip out the fixed function code paths. -// ------------------------------------------------------------------------------------------------------------------------------ // -// ------------------------------------------------------------------------------------------------------------------------------ // - -// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. -typedef enum _D3DTRANSFORMSTATETYPE -{ - D3DTS_VIEW = 2, - D3DTS_PROJECTION = 3, - D3DTS_TEXTURE0 = 16, - D3DTS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ -} D3DTRANSFORMSTATETYPE; - -// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. -typedef enum _D3DTEXTUREOP -{ - // Control - D3DTOP_DISABLE = 1, // disables stage - D3DTOP_SELECTARG1 = 2, // the default - D3DTOP_SELECTARG2 = 3, - - // Modulate - D3DTOP_MODULATE = 4, // multiply args together - D3DTOP_MODULATE2X = 5, // multiply and 1 bit - D3DTOP_MODULATE4X = 6, // multiply and 2 bits - - // Add - D3DTOP_ADD = 7, // add arguments together - D3DTOP_ADDSIGNED = 8, // add with -0.5 bias - D3DTOP_ADDSIGNED2X = 9, // as above but left 1 bit - D3DTOP_SUBTRACT = 10, // Arg1 - Arg2, with no saturation - D3DTOP_ADDSMOOTH = 11, // add 2 args, subtract product - // Arg1 + Arg2 - Arg1*Arg2 - // = Arg1 + (1-Arg1)*Arg2 - - // Linear alpha blend: Arg1*(Alpha) + Arg2*(1-Alpha) - D3DTOP_BLENDDIFFUSEALPHA = 12, // iterated alpha - D3DTOP_BLENDTEXTUREALPHA = 13, // texture alpha - D3DTOP_BLENDFACTORALPHA = 14, // alpha from D3DRS_TEXTUREFACTOR - - // Linear alpha blend with pre-multiplied arg1 input: Arg1 + Arg2*(1-Alpha) - D3DTOP_BLENDTEXTUREALPHAPM = 15, // texture alpha - D3DTOP_BLENDCURRENTALPHA = 16, // by alpha of current color - - // Specular mapping - D3DTOP_PREMODULATE = 17, // modulate with next texture before use - D3DTOP_MODULATEALPHA_ADDCOLOR = 18, // Arg1.RGB + Arg1.A*Arg2.RGB - // COLOROP only - D3DTOP_MODULATECOLOR_ADDALPHA = 19, // Arg1.RGB*Arg2.RGB + Arg1.A - // COLOROP only - D3DTOP_MODULATEINVALPHA_ADDCOLOR = 20, // (1-Arg1.A)*Arg2.RGB + Arg1.RGB - // COLOROP only - D3DTOP_MODULATEINVCOLOR_ADDALPHA = 21, // (1-Arg1.RGB)*Arg2.RGB + Arg1.A - // COLOROP only - - // Bump mapping - D3DTOP_BUMPENVMAP = 22, // per pixel env map perturbation - D3DTOP_BUMPENVMAPLUMINANCE = 23, // with luminance channel - - // This can do either diffuse or specular bump mapping with correct input. - // Performs the function (Arg1.R*Arg2.R + Arg1.G*Arg2.G + Arg1.B*Arg2.B) - // where each component has been scaled and offset to make it signed. - // The result is replicated into all four (including alpha) channels. - // This is a valid COLOROP only. - D3DTOP_DOTPRODUCT3 = 24, - - // Triadic ops - D3DTOP_MULTIPLYADD = 25, // Arg0 + Arg1*Arg2 - D3DTOP_LERP = 26, // (Arg0)*Arg1 + (1-Arg0)*Arg2 - - D3DTOP_FORCE_DWORD = 0x7fffffff, -} D3DTEXTUREOP; - -// **** FIXED FUNCTION STUFF - None of this stuff needs support in GL. -typedef enum _D3DTEXTURESTAGESTATETYPE -{ - D3DTSS_COLOROP = 1, /* D3DTEXTUREOP - per-stage blending controls for color channels */ - D3DTSS_COLORARG1 = 2, /* D3DTA_* (texture arg) */ - D3DTSS_COLORARG2 = 3, /* D3DTA_* (texture arg) */ - D3DTSS_ALPHAOP = 4, /* D3DTEXTUREOP - per-stage blending controls for alpha channel */ - D3DTSS_ALPHAARG1 = 5, /* D3DTA_* (texture arg) */ - D3DTSS_ALPHAARG2 = 6, /* D3DTA_* (texture arg) */ - D3DTSS_BUMPENVMAT00 = 7, /* float (bump mapping matrix) */ - D3DTSS_BUMPENVMAT01 = 8, /* float (bump mapping matrix) */ - D3DTSS_BUMPENVMAT10 = 9, /* float (bump mapping matrix) */ - D3DTSS_BUMPENVMAT11 = 10, /* float (bump mapping matrix) */ - D3DTSS_TEXCOORDINDEX = 11, /* identifies which set of texture coordinates index this texture */ - D3DTSS_BUMPENVLOFFSET = 23, /* float offset for bump map luminance */ - D3DTSS_TEXTURETRANSFORMFLAGS = 24, /* D3DTEXTURETRANSFORMFLAGS controls texture transform */ - D3DTSS_COLORARG0 = 26, /* D3DTA_* third arg for triadic ops */ - D3DTSS_RESULTARG = 28, /* D3DTA_* arg for result (CURRENT or TEMP) */ - - - D3DTSS_FORCE_DWORD = 0x7fffffff, /* force 32-bit size enum */ -} D3DTEXTURESTAGESTATETYPE; - -//===========================================================================// - -enum GLMVertexAttributeIndex -{ - kGLMGenericAttr00 = 0, - kGLMGenericAttr01, - kGLMGenericAttr02, - kGLMGenericAttr03, - kGLMGenericAttr04, - kGLMGenericAttr05, - kGLMGenericAttr06, - kGLMGenericAttr07, - kGLMGenericAttr08, - kGLMGenericAttr09, - kGLMGenericAttr10, - kGLMGenericAttr11, - kGLMGenericAttr12, - kGLMGenericAttr13, - kGLMGenericAttr14, - kGLMGenericAttr15, - - kGLMVertexAttributeIndexMax // ideally < 32 -}; - -struct GLMVertexAttributeDesc // all the info you need to do vertex setup for one attribute -{ - CGLMBuffer *m_buffer; // NULL allowed in which case m_offset is the full 32-bit pointer.. so you can draw from plain RAM if desired - GLuint m_datasize; // comp count of the attribute (1-4) - GLenum m_datatype; // data type of the attribute (GL_FLOAT, GL_UNSIGNED_BYTE, etc) - GLuint m_stride; - GLuint m_offset; // net offset to attribute 'zero' within the buffer. - GLboolean m_normalized; // apply to any fixed point data that needs normalizing, esp color bytes - - // may need a seed value at some point to be able to disambiguate re-lifed buffers holding same pointer - // simpler alternative is to do shoot-down inside the vertex/index buffer free calls. - // I'd rather not have to have each attribute fiddling a ref count on the buffer to which it refers.. - -#define EQ(fff) ( (src.fff) == (fff) ) - // test in decreasing order of likelihood of difference, but do not include the buffer revision as caller is not supplying it.. - bool operator==(const GLMVertexAttributeDesc& src) const { return EQ(m_buffer) && EQ(m_offset) && EQ(m_stride) && EQ(m_datatype) && EQ(m_normalized) && EQ(m_datasize); } -#undef EQ - - uint m_bufferRevision; // only set in GLM context's copy, to disambiguate references that are same offset / same buffer but cross an orphan event -}; - - -#define MAX_D3DVERTEXELEMENTS 16 - -struct D3DVERTEXELEMENT9_GL -{ - // fields right out of the original decl element (copied) - D3DVERTEXELEMENT9 m_dxdecl; // d3d info - // WORD Stream; // Stream index - // WORD Offset; // Offset in the stream in bytes - // BYTE Type; // Data type - // BYTE Method; // Processing method - // BYTE Usage; // Semantics - // BYTE UsageIndex; // Semantic index - - GLMVertexAttributeDesc m_gldecl; - // CGLMBuffer *m_buffer; // late-dropped from selected stream desc (left NULL, will replace with stream source buffer at sync time) - // GLuint m_datasize; // component count (1,2,3,4) of the attrib - // GLenum m_datatype; // data type of the attribute (GL_FLOAT et al) - // GLuint m_stride; // late-dropped from stream desc - // GLuint m_offset; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. - // GLuint m_normalized; // net offset to attribute 'zero' within the stream data. Add the stream offset before passing to GL. -}; - -struct IDirect3DDevice9Params -{ - UINT m_adapter; - D3DDEVTYPE m_deviceType; - VD3DHWND m_focusWindow; - DWORD m_behaviorFlags; - D3DPRESENT_PARAMETERS m_presentationParameters; -}; - -#define D3D_MAX_STREAMS 4 -struct D3DStreamDesc -{ - IDirect3DVertexBuffer9 *m_vtxBuffer; - uint m_offset; - uint m_stride; -}; - -struct D3DIndexDesc -{ - IDirect3DIndexBuffer9 *m_idxBuffer; -}; - -// we latch sampler values until draw time and then convert them all to GL form -// note these are similar in name to the fields of a GLMTexSamplingParams but contents are not -// particularly in the texture filtering area - -struct D3DSamplerDesc -{ - D3DTEXTUREADDRESS m_addressModes[3]; // D3DTEXTUREADDRESS modes for S,T,R - DWORD m_borderColor; // DWORD bordercolor - D3DTEXTUREFILTERTYPE m_magFilter; // mag filter - D3DTEXTUREFILTERTYPE m_minFilter; // min filter - D3DTEXTUREFILTERTYPE m_mipFilter; // mip filter - float m_mipmapBias; // float: mipmap bias - DWORD m_maxMipLevel; // DWORD 0..(n-1) LOD index of largest map to use (0 == largest) - DWORD m_maxAniso; // D3DSAMP_MAXANISOTROPY max aniso - DWORD m_srgb; // D3DSAMP_SRGBTEXTURE 0 = no SRGB sampling - DWORD m_shadowFilter; // D3DSAMP_SHADOWFILTER -}; - -// Tracking and naming sampler dimensions -#define SAMPLER_TYPE_2D 0 -#define SAMPLER_TYPE_CUBE 1 -#define SAMPLER_TYPE_3D 2 -#define SAMPLER_TYPE_UNUSED 3 - -#endif // DXABSTRACT_TYPES_H diff --git a/mp/src/public/togl/osx/glentrypoints.h b/mp/src/public/togl/osx/glentrypoints.h deleted file mode 100644 index be8d5446..00000000 --- a/mp/src/public/togl/osx/glentrypoints.h +++ /dev/null @@ -1,329 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// glentrypoints.h -// -//=============================================================================== - -#ifndef GLENTRYPOINTS_H -#define GLENTRYPOINTS_H - -#pragma once - -#ifdef DX_TO_GL_ABSTRACTION - -#include "tier0/platform.h" -#include "tier0/dynfunction.h" -#include "tier0/vprof_telemetry.h" -#include "interface.h" - -#include "togl/rendermechanism.h" - -#ifndef APIENTRY -#define APIENTRY -#endif - -#ifndef CALLBACK -#define CALLBACK -#endif - - -void *VoidFnPtrLookup_GlMgr(const char *fn, bool &okay, const bool bRequired, void *fallback=NULL); - -#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME -class CGLExecuteHelperBase -{ -public: - inline void StartCall(const char *pName); - inline void StopCall(const char *pName); -#if GL_TRACK_API_TIME - TmU64 m_nStartTime; -#endif -}; - -template < class FunctionType, typename Result > -class CGLExecuteHelper : public CGLExecuteHelperBase -{ -public: - inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); m_Result = (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } - - inline operator Result() const { return m_Result; } - inline operator char*() const { return (char*)m_Result; } - - FunctionType m_pFn; - - Result m_Result; -}; - -template < class FunctionType> -class CGLExecuteHelper : public CGLExecuteHelperBase -{ -public: - inline CGLExecuteHelper(FunctionType pFn, const char *pName ) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i); StopCall(pName); } - template inline CGLExecuteHelper(FunctionType pFn, const char *pName, A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) : m_pFn( pFn ) { StartCall(pName); (*m_pFn)(a, b, c, d, e, f, g, h, i, j); StopCall(pName); } - - FunctionType m_pFn; -}; -#endif - -template < class FunctionType, typename Result > -class CDynamicFunctionOpenGLBase -{ -public: - // Construct with a NULL function pointer. You must manually call - // Lookup() before you can call a dynamic function through this interface. - CDynamicFunctionOpenGLBase() : m_pFn(NULL) {} - - // Construct and do a lookup right away. You will need to make sure that - // the lookup actually succeeded, as the gl library might have failed to load - // or (fn) might not exist in it. - CDynamicFunctionOpenGLBase(const char *fn, FunctionType fallback=NULL) : m_pFn(NULL) - { - Lookup(fn, fallback); - } - - // Construct and do a lookup right away. See comments in Lookup() about what (okay) does. - CDynamicFunctionOpenGLBase(const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL) - { - Lookup(fn, okay, fallback); - } - - // Load library if necessary, look up symbol. Returns true and sets - // m_pFn on successful lookup, returns false otherwise. If the - // function pointer is already looked up, this return true immediately. - // Use Reset() first if you want to look up the symbol again. - // This function will return false immediately unless (okay) is true. - // This allows you to chain lookups like this: - // bool okay = true; - // x.Lookup(lib, "x", okay); - // y.Lookup(lib, "y", okay); - // z.Lookup(lib, "z", okay); - // if (okay) { printf("All functions were loaded successfully!\n"); } - // If you supply a fallback, it'll be used if the lookup fails (and if - // non-NULL, means this will always return (okay)). - bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) - { - if (!okay) - return false; - else if (this->m_pFn == NULL) - { - this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, false, (void *) fallback); - this->SetFuncName( fn ); - } - return okay; - } - - // Load library if necessary, look up symbol. Returns true and sets - // m_pFn on successful lookup, returns false otherwise. If the - // function pointer is already looked up, this return true immediately. - // Use Reset() first if you want to look up the symbol again. - // This function will return false immediately unless (okay) is true. - // If you supply a fallback, it'll be used if the lookup fails (and if - // non-NULL, means this will always return true). - bool Lookup(const char *fn, FunctionType fallback=NULL) - { - bool okay = true; - return Lookup(fn, okay, fallback); - } - - // Invalidates the current lookup. Makes the function pointer NULL. You - // will need to call Lookup() before you can call a dynamic function - // through this interface again. - void Reset() { m_pFn = NULL; } - - // Force this to be a specific function pointer. - void Force(FunctionType ptr) { m_pFn = ptr; } - - // Retrieve the actual function pointer. - FunctionType Pointer() const { return m_pFn; } - -#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME - #if GL_TELEMETRY_ZONES - #define GL_FUNC_NAME m_szName - #else - #define GL_FUNC_NAME "" - #endif - - inline CGLExecuteHelper operator() () const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME ); } - - template - inline CGLExecuteHelper operator() (T a) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a); } - - template - inline CGLExecuteHelper operator() (T a, U b) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c ) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i); } - - template - inline CGLExecuteHelper operator() (T a, U b, V c, W d, X e, Y f, Z g, A h, B i, C j) const { return CGLExecuteHelper(m_pFn, GL_FUNC_NAME, a, b, c, d, e, f, g, h, i, j); } -#else - operator FunctionType() const { return m_pFn; } -#endif - - // Can be used to verify that we have an actual function looked up and - // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); } - operator bool () const { return m_pFn != NULL; } - bool operator !() const { return m_pFn == NULL; } - -protected: - FunctionType m_pFn; - -#if GL_TELEMETRY_ZONES - char m_szName[32]; - inline void SetFuncName(const char *pFn) { V_strncpy( m_szName, pFn, sizeof( m_szName ) ); } -#else - inline void SetFuncName(const char *pFn) { (void)pFn; } -#endif -}; - -// This works a lot like CDynamicFunctionMustInit, but we use SDL_GL_GetProcAddress(). -template < const bool bRequired, class FunctionType, typename Result > -class CDynamicFunctionOpenGL : public CDynamicFunctionOpenGLBase< FunctionType, Result > -{ -private: // forbid default constructor. - CDynamicFunctionOpenGL() {} - -public: - CDynamicFunctionOpenGL(const char *fn, FunctionType fallback=NULL) - { - bool okay = true; - Lookup(fn, okay, fallback); - this->SetFuncName( fn ); - } - - CDynamicFunctionOpenGL(const char *fn, bool &okay, FunctionType fallback=NULL) - { - Lookup(fn, okay, fallback); - this->SetFuncName( fn ); - } - - // Please note this is not virtual. - // !!! FIXME: we might want to fall back and try "EXT" or "ARB" versions in some case. - bool Lookup(const char *fn, bool &okay, FunctionType fallback=NULL) - { - if (this->m_pFn == NULL) - { - this->m_pFn = (FunctionType) VoidFnPtrLookup_GlMgr(fn, okay, bRequired, (void *) fallback); - this->SetFuncName( fn ); - } - return okay; - } -}; - - -// This provides all the entry points for a given OpenGL context. -// ENTRY POINTS ARE ONLY VALID FOR THE CONTEXT THAT WAS CURRENT WHEN -// YOU LOOKED THEM UP. 99% of the time, this is not a problem, but -// that 1% is really hard to track down. Always access the GL -// through this class! -class COpenGLEntryPoints -{ -public: - // The GL context you are looking up entry points for must be current when you construct this object! - COpenGLEntryPoints(); - - uint64 m_nTotalGLCycles, m_nTotalGLCalls; - - int m_nOpenGLVersionMajor; // if GL_VERSION is 2.1.0, this will be set to 2. - int m_nOpenGLVersionMinor; // if GL_VERSION is 2.1.0, this will be set to 1. - int m_nOpenGLVersionPatch; // if GL_VERSION is 2.1.0, this will be set to 0. - bool m_bHave_OpenGL; - - #define GL_EXT(x,glmajor,glminor) bool m_bHave_##x; - #define GL_FUNC(ext,req,ret,fn,arg,call) CDynamicFunctionOpenGL< req, ret (APIENTRY *) arg, ret > fn; - #define GL_FUNC_VOID(ext,req,fn,arg,call) CDynamicFunctionOpenGL< req, void (APIENTRY *) arg, void > fn; - #include "togl/glfuncs.inl" - #undef GL_FUNC_VOID - #undef GL_FUNC - #undef GL_EXT -}; - -// This will be set to the current OpenGL context's entry points. -extern COpenGLEntryPoints *gGL; -typedef void * (*GL_GetProcAddressCallbackFunc_t)(const char *, bool &, const bool, void *); - -#ifdef TOGL_DLL_EXPORT - DLL_EXPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); - DLL_EXPORT void ToGLDisconnectLibraries(); - DLL_EXPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); -#else - DLL_IMPORT COpenGLEntryPoints *ToGLConnectLibraries( CreateInterfaceFn factory ); - DLL_IMPORT void ToGLDisconnectLibraries(); - DLL_IMPORT COpenGLEntryPoints *GetOpenGLEntryPoints(GL_GetProcAddressCallbackFunc_t callback); -#endif - -#if GL_TELEMETRY_ZONES || GL_TRACK_API_TIME -inline void CGLExecuteHelperBase::StartCall(const char *pName) -{ - (void)pName; - -#if GL_TELEMETRY_ZONES - tmEnter( TELEMETRY_LEVEL3, TMZF_NONE, pName ); -#endif - -#if GL_TRACK_API_TIME - m_nStartTime = tmFastTime(); -#endif -} - -inline void CGLExecuteHelperBase::StopCall(const char *pName) -{ -#if GL_TRACK_API_TIME - uint64 nTotalCycles = tmFastTime() - m_nStartTime; -#endif - -#if GL_TELEMETRY_ZONES - tmLeave( TELEMETRY_LEVEL3 ); -#endif - -#if GL_TRACK_API_TIME - //double flMilliseconds = g_Telemetry.flRDTSCToMilliSeconds * nTotalCycles; - if (gGL) - { - gGL->m_nTotalGLCycles += nTotalCycles; - gGL->m_nTotalGLCalls++; - } -#endif -} -#endif - -#endif // DX_TO_GL_ABSTRACTION - -#endif // GLENTRYPOINTS_H diff --git a/mp/src/public/togl/osx/glfuncs.h b/mp/src/public/togl/osx/glfuncs.h deleted file mode 100644 index 78184bef..00000000 --- a/mp/src/public/togl/osx/glfuncs.h +++ /dev/null @@ -1,184 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// !!! FIXME: Some of these aren't base OpenGL...pick out the extensions. -// !!! FIXME: Also, look up these -1, -1 versions numbers. -GL_FUNC(OpenGL,true,GLenum,glGetError,(void),()) -GL_FUNC_VOID(OpenGL,true,glActiveTexture,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glAlphaFunc,(GLenum a,GLclampf b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glAttachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBegin,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glBindAttribLocationARB,(GLhandleARB a,GLuint b,const GLcharARB *c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glBindBufferARB,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBindProgramARB,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBindTexture,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBlendColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glBlendEquation,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glBlendFunc,(GLenum a,GLenum b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glBufferDataARB,(GLenum a,GLsizeiptrARB b,const GLvoid *c,GLenum d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glClear,(GLbitfield a),(a)) -GL_FUNC_VOID(OpenGL,true,glClearColor,(GLclampf a,GLclampf b,GLclampf c,GLclampf d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glClearDepth,(GLclampd a),(a)) -GL_FUNC_VOID(OpenGL,true,glClearStencil,(GLint a),(a)) -GL_FUNC_VOID(OpenGL,true,glClipPlane,(GLenum a,const GLdouble *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glColorMask,(GLboolean a,GLboolean b,GLboolean c,GLboolean d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glCompileShaderARB,(GLhandleARB a),(a)) -GL_FUNC_VOID(OpenGL,true,glCompressedTexImage2D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLint f,GLsizei g,const GLvoid *h),(a,b,c,d,e,f,g,h)) -GL_FUNC_VOID(OpenGL,true,glCompressedTexImage3D,(GLenum a,GLint b,GLenum c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLsizei h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) -GL_FUNC(OpenGL,true,GLhandleARB,glCreateProgramObjectARB,(void),()) -GL_FUNC(OpenGL,true,GLhandleARB,glCreateShaderObjectARB,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glDeleteBuffersARB,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDeleteObjectARB,(GLhandleARB a),(a)) -GL_FUNC_VOID(OpenGL,true,glDeleteProgramsARB,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDeleteQueriesARB,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDeleteShader,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glDeleteTextures,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDepthFunc,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glDepthMask,(GLboolean a),(a)) -GL_FUNC_VOID(OpenGL,true,glDepthRange,(GLclampd a,GLclampd b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDetachObjectARB,(GLhandleARB a,GLhandleARB b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glDisable,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glDisableVertexAttribArray,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glDrawArrays,(GLenum a,GLint b,GLsizei c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glDrawBuffer,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glDrawRangeElements,(GLenum a,GLuint b,GLuint c,GLsizei d,GLenum e,const GLvoid *f),(a,b,c,d,e,f)) -GL_FUNC_VOID(OpenGL,true,glEnable,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glEnableVertexAttribArray,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glEnd,(void),()) -GL_FUNC_VOID(OpenGL,true,glFinish,(void),()) -GL_FUNC_VOID(OpenGL,true,glFlush,(void),()) -GL_FUNC_VOID(OpenGL,true,glFrontFace,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glGenBuffersARB,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGenProgramsARB,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGenQueriesARB,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGenTextures,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGetBooleanv,(GLenum a,GLboolean *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGetCompressedTexImage,(GLenum a,GLint b,GLvoid *c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glGetDoublev,(GLenum a,GLdouble *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGetFloatv,(GLenum a,GLfloat *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGetInfoLogARB,(GLhandleARB a,GLsizei b,GLsizei *c,GLcharARB *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glGetIntegerv,(GLenum a,GLint *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glGetObjectParameterivARB,(GLhandleARB a,GLenum b,GLint *c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glGetProgramivARB,(GLenum a,GLenum b,GLint *c),(a,b,c)) -GL_FUNC(OpenGL,true,const GLubyte *,glGetString,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glGetTexImage,(GLenum a,GLint b,GLenum c,GLenum d,GLvoid *e),(a,b,c,d,e)) -GL_FUNC(OpenGL,true,GLint,glGetUniformLocationARB,(GLhandleARB a,const GLcharARB *b),(a,b)) -GL_FUNC(OpenGL,true,GLboolean,glIsEnabled,(GLenum a),(a)) -GL_FUNC(OpenGL,true,GLboolean,glIsTexture,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glLinkProgramARB,(GLhandleARB a),(a)) -GL_FUNC(OpenGL,true,GLvoid*,glMapBufferARB,(GLenum a,GLenum b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glOrtho,(GLdouble a,GLdouble b,GLdouble c,GLdouble d,GLdouble e,GLdouble f),(a,b,c,d,e,f)) -GL_FUNC_VOID(OpenGL,true,glPixelStorei,(GLenum a,GLint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glPolygonMode,(GLenum a,GLenum b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glPolygonOffset,(GLfloat a,GLfloat b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glPopAttrib,(void),()) -GL_FUNC_VOID(OpenGL,true,glProgramStringARB,(GLenum a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glPushAttrib,(GLbitfield a),(a)) -GL_FUNC_VOID(OpenGL,true,glReadBuffer,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glScissor,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glShaderSourceARB,(GLhandleARB a,GLsizei b,const GLcharARB **c,const GLint *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glStencilFunc,(GLenum a,GLint b,GLuint c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glStencilMask,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glStencilOp,(GLenum a,GLenum b,GLenum c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glTexCoord2f,(GLfloat a,GLfloat b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glTexImage2D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLint f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) -GL_FUNC_VOID(OpenGL,true,glTexImage3D,(GLenum a,GLint b,GLint c,GLsizei d,GLsizei e,GLsizei f,GLint g,GLenum h,GLenum i,const GLvoid *j),(a,b,c,d,e,f,g,h,i,j)) -GL_FUNC_VOID(OpenGL,true,glTexParameterfv,(GLenum a,GLenum b,const GLfloat *c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glTexParameteri,(GLenum a,GLenum b,GLint c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glTexSubImage2D,(GLenum a,GLint b,GLint c,GLint d,GLsizei e,GLsizei f,GLenum g,GLenum h,const GLvoid *i),(a,b,c,d,e,f,g,h,i)) -GL_FUNC_VOID(OpenGL,true,glUniform1f,(GLint a,GLfloat b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glUniform1i,(GLint a,GLint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glUniform1iARB,(GLint a,GLint b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glUniform4fv,(GLint a,GLsizei b,const GLfloat *c),(a,b,c)) -GL_FUNC(OpenGL,true,GLboolean,glUnmapBuffer,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glUseProgram,(GLuint a),(a)) -GL_FUNC_VOID(OpenGL,true,glVertex3f,(GLfloat a,GLfloat b,GLfloat c),(a,b,c)) -GL_FUNC_VOID(OpenGL,true,glVertexAttribPointer,(GLuint a,GLint b,GLenum c,GLboolean d,GLsizei e,const GLvoid *f),(a,b,c,d,e,f)) -GL_FUNC_VOID(OpenGL,true,glViewport,(GLint a,GLint b,GLsizei c,GLsizei d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glEnableClientState,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glDisableClientState,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glClientActiveTexture,(GLenum a),(a)) -GL_FUNC_VOID(OpenGL,true,glVertexPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glTexCoordPointer,(GLint a,GLenum b,GLsizei c,const GLvoid *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glProgramEnvParameters4fvEXT,(GLenum a,GLuint b,GLsizei c,const GLfloat *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glColor4sv,(const GLshort *a),(a)) -GL_FUNC_VOID(OpenGL,true,glStencilOpSeparate,(GLenum a,GLenum b,GLenum c,GLenum d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glStencilFuncSeparate,(GLenum a,GLenum b,GLint c,GLuint d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glGetTexLevelParameteriv,(GLenum a,GLint b,GLenum c,GLint *d),(a,b,c,d)) -GL_FUNC_VOID(OpenGL,true,glColor4f,(GLfloat a,GLfloat b,GLfloat c,GLfloat d),(a,b,c,d)) -GL_EXT(GL_EXT_framebuffer_object,-1,-1) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindFramebufferEXT,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glBindRenderbufferEXT,(GLenum a,GLuint b),(a,b)) -GL_FUNC(GL_EXT_framebuffer_object,false,GLenum,glCheckFramebufferStatusEXT,(GLenum a),(a)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteRenderbuffersEXT,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferRenderbufferEXT,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture2DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glFramebufferTexture3DEXT,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenFramebuffersEXT,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glGenRenderbuffersEXT,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(GL_EXT_framebuffer_object,false,glDeleteFramebuffersEXT,(GLsizei a,const GLuint *b),(a,b)) -GL_EXT(GL_EXT_framebuffer_blit,-1,-1) -GL_FUNC_VOID(GL_EXT_framebuffer_blit,false,glBlitFramebufferEXT,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) -GL_EXT(GL_EXT_framebuffer_multisample,-1,-1) -GL_FUNC_VOID(GL_EXT_framebuffer_multisample,false,glRenderbufferStorageMultisampleEXT,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) -GL_EXT(GL_APPLE_fence,-1,-1) -GL_FUNC(GL_APPLE_fence,false,GLboolean,glTestFenceAPPLE,(GLuint a),(a)) -GL_FUNC_VOID(GL_APPLE_fence,false,glSetFenceAPPLE,(GLuint a),(a)) -GL_FUNC_VOID(GL_APPLE_fence,false,glFinishFenceAPPLE,(GLuint a),(a)) -GL_FUNC_VOID(GL_APPLE_fence,false,glDeleteFencesAPPLE,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(GL_APPLE_fence,false,glGenFencesAPPLE,(GLsizei a,GLuint *b),(a,b)) -GL_EXT(GL_NV_fence,-1,-1) -GL_FUNC(GL_NV_fence,false,GLboolean,glTestFenceNV,(GLuint a),(a)) -GL_FUNC_VOID(GL_NV_fence,false,glSetFenceNV,(GLuint a,GLenum b),(a,b)) -GL_FUNC_VOID(GL_NV_fence,false,glFinishFenceNV,(GLuint a),(a)) -GL_FUNC_VOID(GL_NV_fence,false,glDeleteFencesNV,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(GL_NV_fence,false,glGenFencesNV,(GLsizei a,GLuint *b),(a,b)) -GL_EXT(GL_ARB_sync,3,2) -#ifdef HAVE_GL_ARB_SYNC -GL_FUNC_VOID(GL_ARB_sync,false,glGetSynciv,(GLsync a, GLenum b, GLsizei c, GLsizei *d, GLint *e),(a,b,c,d,e)) -GL_FUNC(GL_ARB_sync,false,GLenum,glClientWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) -GL_FUNC_VOID(GL_ARB_sync,false,glWaitSync,(GLsync a, GLbitfield b, GLuint64 c),(a,b,c)) -GL_FUNC_VOID(GL_ARB_sync,false,glDeleteSync,(GLsync a),(a)) -GL_FUNC(GL_ARB_sync,false,GLsync,glFenceSync,(GLenum a, GLbitfield b),(a,b)) -#endif -GL_EXT(GL_EXT_draw_buffers2,-1,-1) -GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glColorMaskIndexedEXT,(GLuint a,GLboolean b,GLboolean c,GLboolean d,GLboolean e),(a,b,c,d,e)) -GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glEnableIndexedEXT,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glDisableIndexedEXT,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(GL_EXT_draw_buffers2,false,glGetBooleanIndexedvEXT,(GLenum a,GLuint b,GLboolean *c),(a,b,c)) -GL_EXT(GL_EXT_bindable_uniform,-1,-1) -GL_FUNC_VOID(GL_EXT_bindable_uniform,false,glUniformBufferEXT,(GLuint a,GLint b,GLuint c),(a,b,c)) -GL_EXT(GL_APPLE_flush_buffer_range,-1,-1) -GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glBufferParameteriAPPLE,(GLenum a,GLenum b,GLint c),(a,b,c)) -GL_FUNC_VOID(GL_APPLE_flush_buffer_range,false,glFlushMappedBufferRangeAPPLE,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) -GL_EXT(GL_ARB_map_buffer_range,-1,-1) -GL_FUNC(GL_ARB_map_buffer_range,false,void*,glMapBufferRange,(GLenum a,GLintptr b,GLsizeiptr c,GLbitfield d),(a,b,c,d)) -GL_FUNC_VOID(GL_ARB_map_buffer_range,false,glFlushMappedBufferRange,(GLenum a,GLintptr b,GLsizeiptr c),(a,b,c)) -GL_EXT(GL_ARB_occlusion_query,-1,-1) -GL_FUNC_VOID(GL_ARB_occlusion_query,false,glBeginQueryARB,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(GL_ARB_occlusion_query,false,glEndQueryARB,(GLenum a),(a)) -GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectivARB,(GLuint a,GLenum b,GLint *c),(a,b,c)) -GL_FUNC_VOID(GL_ARB_occlusion_query,false,glGetQueryObjectuivARB,(GLuint a,GLenum b,GLuint *c),(a,b,c)) -GL_EXT(GL_APPLE_texture_range,-1,-1) -GL_FUNC_VOID(GL_APPLE_texture_range,false,glTextureRangeAPPLE,(GLenum a,GLsizei b,void *c),(a,b,c)) -GL_FUNC_VOID(GL_APPLE_texture_range,false,glGetTexParameterPointervAPPLE,(GLenum a,GLenum b,void* *c),(a,b,c)) -GL_EXT(GL_APPLE_client_storage,-1,-1) -GL_EXT(GL_ARB_uniform_buffer,-1,-1) -GL_EXT(GL_ARB_vertex_array_bgra,-1,-1) -GL_EXT(GL_EXT_vertex_array_bgra,-1,-1) -GL_EXT(GL_ARB_framebuffer_object,3,0) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindFramebuffer,(GLenum a,GLuint b),(a,b)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBindRenderbuffer,(GLenum a,GLuint b),(a,b)) -GL_FUNC(GL_ARB_framebuffer_object,false,GLenum,glCheckFramebufferStatus,(GLenum a),(a)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteRenderbuffers,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferRenderbuffer,(GLenum a,GLenum b,GLenum c,GLuint d),(a,b,c,d)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture2D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e),(a,b,c,d,e)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glFramebufferTexture3D,(GLenum a,GLenum b,GLenum c,GLuint d,GLint e,GLint f),(a,b,c,d,e,f)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenFramebuffers,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glGenRenderbuffers,(GLsizei a,GLuint *b),(a,b)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glDeleteFramebuffers,(GLsizei a,const GLuint *b),(a,b)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glBlitFramebuffer,(GLint a,GLint b,GLint c,GLint d,GLint e,GLint f,GLint g,GLint h,GLbitfield i,GLenum j),(a,b,c,d,e,f,g,h,i,j)) -GL_FUNC_VOID(GL_ARB_framebuffer_object,false,glRenderbufferStorageMultisample,(GLenum a,GLsizei b,GLenum c,GLsizei d,GLsizei e),(a,b,c,d,e)) -GL_EXT(GL_GREMEDY_string_marker,-1,-1) -GL_FUNC_VOID(GL_GREMEDY_string_marker,false,glStringMarkerGREMEDY,(GLsizei a,const void *b),(a,b)) -GL_FUNC_VOID(OpenGL,true,glPushClientAttrib,(GLbitfield a),(a)) -GL_FUNC_VOID(OpenGL,true,glPopClientAttrib,(void),()) - diff --git a/mp/src/public/togl/osx/glmdebug.h b/mp/src/public/togl/osx/glmdebug.h deleted file mode 100644 index ee60a3a4..00000000 --- a/mp/src/public/togl/osx/glmdebug.h +++ /dev/null @@ -1,157 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -#ifndef GLMDEBUG_H -#define GLMDEBUG_H - -#include "tier0/platform.h" -#include - -// include this anywhere you need to be able to compile-out code related specifically to GLM debugging. - -// we expect DEBUG to be driven by the build system so you can include this header anywhere. -// when we come out, GLMDEBUG will be defined to a value - 0, 1, or 2 -// 0 means no GLM debugging is possible -// 1 means it's possible and resulted from being a debug build -// 2 means it's possible and resulted from being manually forced on for a release build - -#ifdef POSIX - #ifndef GLMDEBUG - #ifdef DEBUG - #define GLMDEBUG 1 // normally 1 here, testing - #else - // #define GLMDEBUG 2 // don't check this in enabled.. - #endif - - #ifndef GLMDEBUG - #define GLMDEBUG 0 - #endif - #endif -#else - #ifndef GLMDEBUG - #define GLMDEBUG 0 - #endif -#endif - - -//=============================================================================== -// debug channels - -enum EGLMDebugChannel -{ - ePrintf, - eDebugger, - eGLProfiler -}; - -#if GLMDEBUG - // make all these prototypes disappear in non GLMDEBUG - void GLMDebugInitialize( bool forceReinit=false ); - - bool GLMDetectOGLP( void ); - bool GLMDetectGDB( void ); - uint GLMDetectAvailableChannels( void ); - - uint GLMDebugChannelMask( uint *newValue = NULL ); - // note that GDB and OGLP can both come and go during run - forceCheck will allow that to be detected. - // mask returned is in form of 1< < - eComment, // 3 one off messages --- - eMatrixData, // 4 matrix data -M- - eShaderData, // 5 shader data (params) -S- - eFrameBufData, // 6 FBO data (attachments) -F- - eDXStuff, // 7 dxabstract spew -X- - eAllocations, // 8 tracking allocs and frees -A- - eSlowness, // 9 slow things happening (srgb flips..) -Z- - eDefaultFlavor, // not specified (no marker) - eFlavorCount -}; -uint GLMDebugFlavorMask( uint *newValue = NULL ); - -// make all these prototypes disappear in non GLMDEBUG -#if GLMDEBUG - // these are unconditional outputs, they don't interrogate the string - void GLMStringOut( const char *string ); - void GLMStringOutIndented( const char *string, int indentColumns ); - - #ifdef TOGL_DLL_EXPORT - // these will look at the string to guess its flavor: <, >, ---, -M-, -S- - DLL_EXPORT void GLMPrintfVA( const char *fmt, va_list vargs ); - DLL_EXPORT void GLMPrintf( const char *fmt, ... ); - #else - DLL_IMPORT void GLMPrintfVA( const char *fmt, va_list vargs ); - DLL_IMPORT void GLMPrintf( const char *fmt, ... ); - #endif - - // these take an explicit flavor with a default value - void GLMPrintStr( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor ); - - #define GLMPRINTTEXT_NUMBEREDLINES 0x80000000 - void GLMPrintText( const char *str, EGLMDebugFlavor flavor = eDefaultFlavor, uint options=0 ); // indent each newline - - int GLMIncIndent( int indentDelta ); - int GLMGetIndent( void ); - void GLMSetIndent( int indent ); - -#endif - -// helpful macro if you are in a position to call GLM functions directly (i.e. you live in materialsystem / shaderapidx9) -#if GLMDEBUG - #define GLMPRINTF(args) GLMPrintf args - #define GLMPRINTSTR(args) GLMPrintStr args - #define GLMPRINTTEXT(args) GLMPrintText args -#else - #define GLMPRINTF(args) - #define GLMPRINTSTR(args) - #define GLMPRINTTEXT(args) -#endif - - -//=============================================================================== -// knob twiddling -#ifdef TOGL_DLL_EXPORT - DLL_EXPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value - DLL_EXPORT float GLMKnobToggle( char *knobname ); -#else - DLL_IMPORT float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value - DLL_IMPORT float GLMKnobToggle( char *knobname ); -#endif - -//=============================================================================== -// other stuff - -#if GLMDEBUG -void GLMTriggerDebuggerBreak(); -inline void GLMDebugger( void ) -{ - if (GLMDebugChannelMask() & (1< -#include -#include -#include -#include -#include - -typedef uint32_t CGDirectDisplayID; -typedef uint32_t CGOpenGLDisplayMask; -typedef double CGRefreshRate; - -//#include -#elif defined(LINUX) -#include "tier0/platform.h" -#include -#include -#else -#error -#endif - -typedef void _PseudoNSGLContext; // aka NSOpenGLContext -typedef _PseudoNSGLContext *PseudoNSGLContextPtr; - -struct GLMDisplayModeInfoFields -{ - uint m_modePixelWidth; - uint m_modePixelHeight; - uint m_modeRefreshHz; - // are we even going to talk about bit depth... not yet -}; - -struct GLMDisplayInfoFields -{ -#ifdef OSX - CGDirectDisplayID m_cgDisplayID; - CGOpenGLDisplayMask m_glDisplayMask; // result of CGDisplayIDToOpenGLDisplayMask on the cg_displayID. -#endif - uint m_displayPixelWidth; - uint m_displayPixelHeight; -}; - -struct GLMRendererInfoFields -{ - /*properties of interest and their desired values. - - kCGLRPFullScreen = 54, true - kCGLRPAccelerated = 73, true - kCGLRPWindow = 80, true - - kCGLRPRendererID = 70, informational - kCGLRPDisplayMask = 84, informational - kCGLRPBufferModes = 100, informational - kCGLRPColorModes = 103, informational - kCGLRPAccumModes = 104, informational - kCGLRPDepthModes = 105, informational - kCGLRPStencilModes = 106, informational - kCGLRPMaxAuxBuffers = 107, informational - kCGLRPMaxSampleBuffers = 108, informational - kCGLRPMaxSamples = 109, informational - kCGLRPSampleModes = 110, informational - kCGLRPSampleAlpha = 111, informational - kCGLRPVideoMemory = 120, informational - kCGLRPTextureMemory = 121, informational - kCGLRPRendererCount = 128 number of renderers in the CGLRendererInfoObj under examination - - kCGLRPOffScreen = 53, D/C - kCGLRPRobust = 75, FALSE or D/C - aka we're asking for no-fallback - kCGLRPBackingStore = 76, D/C - kCGLRPMPSafe = 78, D/C - kCGLRPMultiScreen = 81, D/C - kCGLRPCompliant = 83, D/C - */ - - - //--------------------------- info we have from CGL renderer queries, IOKit, Gestalt - //--------------------------- these are set up in the displayDB by CocoaMgr - GLint m_fullscreen; - GLint m_accelerated; - GLint m_windowed; - - GLint m_rendererID; - GLint m_displayMask; - GLint m_bufferModes; - GLint m_colorModes; - GLint m_accumModes; - GLint m_depthModes; - GLint m_stencilModes; - - GLint m_maxAuxBuffers; - GLint m_maxSampleBuffers; - GLint m_maxSamples; - GLint m_sampleModes; - GLint m_sampleAlpha; - - GLint m_vidMemory; - GLint m_texMemory; - - uint m_pciVendorID; - uint m_pciDeviceID; - char m_pciModelString[64]; - char m_driverInfoString[64]; - - //--------------------------- OS version related - set up by CocoaMgr - - // OS version found - uint m_osComboVersion; // 0x00XXYYZZ : XX major, YY minor, ZZ minor minor : 10.6.3 --> 0x000A0603. 10.5.8 --> 0x000A0508. - - //--------------------------- shorthands - also set up by CocoaMgr - driven by vendorid / deviceid - - bool m_ati; - bool m_atiR5xx; - bool m_atiR6xx; - bool m_atiR7xx; - bool m_atiR8xx; - bool m_atiNewer; - - bool m_intel; - bool m_intel95x; - bool m_intel3100; - bool m_intelNewer; - - bool m_nv; - bool m_nvG7x; - bool m_nvG8x; - bool m_nvNewer; - - //--------------------------- context query results - left blank in the display DB - but valid in a GLMContext (call ctx->Caps() to get a const ref) - - // booleans - bool m_hasGammaWrites; // aka glGetBooleanv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT) / glEnable(GL_FRAMEBUFFER_SRGB_EXT) - bool m_hasMixedAttachmentSizes; // aka ARB_fbo in 10.6.3 - test for min OS vers, then exported ext string - bool m_hasBGRA; // aka GL_BGRA vertex attribs in 10.6.3 - - test for min OS vers, then exported ext string - bool m_hasNewFullscreenMode; // aka 10.6.x "big window" fullscreen mode - bool m_hasNativeClipVertexMode; // aka GLSL gl_ClipVertex does not fall back to SW- OS version and folklore-based - bool m_hasOcclusionQuery; // occlusion query: do you speak it ?! - bool m_hasFramebufferBlit; // framebuffer blit: know what I'm sayin?! - bool m_hasPerfPackage1; // means new MTGL, fast OQ, fast uniform upload, NV can resolve flipped (late summer 2010 post 10.6.4 update) - - // counts - int m_maxAniso; // aniso limit - context query - - // other exts - bool m_hasBindableUniforms; - bool m_hasUniformBuffers; - - // runtime options that aren't negotiable once set - bool m_hasDualShaders; // must supply CLI arg "-glmdualshaders" or we go GLSL only - - //--------------------------- " can'ts " - specific problems that need to be worked around - - bool m_cantBlitReliably; // Intel chipsets have problems blitting sRGB sometimes - bool m_cantAttachSRGB; // NV G8x on 10.5.8 can't have srgb tex on FBO color - separate issue from hasGammaWrites - bool m_cantResolveFlipped; // happens on NV in 10.6.4 and prior - console variable "gl_can_resolve_flipped" can overrule - bool m_cantResolveScaled; // happens everywhere per GL spec but may be relaxed some day - console variable "gl_can_resolve_scaled" can overrule - bool m_costlyGammaFlips; // this means that sRGB sampling state affects shader code gen, resulting in state-dependent code regen - - - //--------------------------- " bads " - known bad drivers - bool m_badDriver1064NV; // this is the bad NVIDIA driver on 10.6.4 - stutter, tex corruption, black screen issues -}; - - - -#endif diff --git a/mp/src/public/togl/osx/glmdisplaydb.h b/mp/src/public/togl/osx/glmdisplaydb.h deleted file mode 100644 index 05c98dc8..00000000 --- a/mp/src/public/togl/osx/glmdisplaydb.h +++ /dev/null @@ -1,115 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -#ifndef GLMDISPLAYDB_H -#define GLMDISPLAYDB_H - -#include "tier1/utlvector.h" - -//=============================================================================== - -// modes, displays, and renderers -// think of renderers as being at the top of a tree. -// each renderer has displays hanging off of it. -// each display has modes hanging off of it. -// the tree is populated on demand and then queried as needed. - -//=============================================================================== - -// GLMDisplayModeInfoFields is in glmdisplay.h - -class GLMDisplayMode -{ -public: - GLMDisplayModeInfoFields m_info; - - GLMDisplayMode( uint width, uint height, uint refreshHz ); - GLMDisplayMode() { }; - ~GLMDisplayMode( void ); - - - void Init( uint width, uint height, uint refreshHz ); - void Dump( int which ); -}; - -//=============================================================================== - -// GLMDisplayInfoFields is in glmdisplay.h - -class GLMDisplayInfo -{ -public: - GLMDisplayInfoFields m_info; - CUtlVector< GLMDisplayMode* > *m_modes; // starts out NULL, set by PopulateModes - - GLMDisplayInfo( void ); - ~GLMDisplayInfo( void ); - - void PopulateModes( void ); - - void Dump( int which ); -}; - -//=============================================================================== - -// GLMRendererInfoFields is in glmdisplay.h - -class GLMRendererInfo -{ -public: - GLMRendererInfoFields m_info; - GLMDisplayInfo *m_display; // starts out NULL, set by PopulateDisplays - - GLMRendererInfo ( GLMRendererInfoFields *info ); - ~GLMRendererInfo ( void ); - - void PopulateDisplays(); - void Dump( int which ); -}; - -//=============================================================================== - -// this is just a tuple describing fake adapters which are really renderer/display pairings. -// dxabstract bridges the gap between the d3d adapter-centric world and the GL renderer+display world. -// this makes it straightforward to handle cases like two video cards with two displays on one, and one on the other - -// you get three fake adapters which represent each useful screen. - -// the constraint that dxa will have to follow though, is that if the user wants to change their -// display selection for full screen, they would only be able to pick on that has the same underlying renderer. -// can't change fakeAdapter from one to another with different GL renderer under it. Screen hop but no card hop. - -struct GLMFakeAdapter -{ - int m_rendererIndex; - int m_displayIndex; -}; - -class GLMDisplayDB -{ -public: - CUtlVector< GLMRendererInfo* > *m_renderers; // starts out NULL, set by PopulateRenderers - - CUtlVector< GLMFakeAdapter > m_fakeAdapters; - - GLMDisplayDB ( void ); - ~GLMDisplayDB ( void ); - - virtual void PopulateRenderers( void ); - virtual void PopulateFakeAdapters( uint realRendererIndex ); // fake adapters = one real adapter times however many displays are on it - virtual void Populate( void ); - - // The info-get functions return false on success. - virtual int GetFakeAdapterCount( void ); - virtual bool GetFakeAdapterInfo( int fakeAdapterIndex, int *rendererOut, int *displayOut, GLMRendererInfoFields *rendererInfoOut, GLMDisplayInfoFields *displayInfoOut ); - - virtual int GetRendererCount( void ); - virtual bool GetRendererInfo( int rendererIndex, GLMRendererInfoFields *infoOut ); - - virtual int GetDisplayCount( int rendererIndex ); - virtual bool GetDisplayInfo( int rendererIndex, int displayIndex, GLMDisplayInfoFields *infoOut ); - - virtual int GetModeCount( int rendererIndex, int displayIndex ); - virtual bool GetModeInfo( int rendererIndex, int displayIndex, int modeIndex, GLMDisplayModeInfoFields *infoOut ); - - virtual void Dump( void ); -}; - -#endif // GLMDISPLAYDB_H diff --git a/mp/src/public/togl/osx/glmgr.h b/mp/src/public/togl/osx/glmgr.h deleted file mode 100644 index cdf64206..00000000 --- a/mp/src/public/togl/osx/glmgr.h +++ /dev/null @@ -1,1088 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// glmgr.h -// singleton class, common basis for managing GL contexts -// responsible for tracking adapters and contexts -// -//=============================================================================== - -#ifndef GLMGR_H -#define GLMGR_H - -#pragma once - -#undef HAVE_GL_ARB_SYNC -#ifdef LINUX -#define HAVE_GL_ARB_SYNC 1 -#endif - -#include "glentrypoints.h" -#include "glmdebug.h" -#include "glmdisplay.h" -#include "glmgrext.h" -#include "glmgrbasics.h" -#include "cglmtex.h" -#include "cglmfbo.h" -#include "cglmprogram.h" -#include "cglmbuffer.h" -#include "cglmquery.h" - -#include "tier0/vprof_telemetry.h" -#include "materialsystem/ishader.h" -#include "dxabstract_types.h" - - -#ifdef LINUX -#define Debugger DebuggerBreak -#undef CurrentTime - -// prevent some conflicts in SDL headers... -#undef M_PI -#include -#ifndef _STDINT_H_ -#define _STDINT_H_ 1 -#endif - -#include "SDL/SDL.h" -#endif - -//=============================================================================== -// glue to call out to Obj-C land (these are in glmgrcocoa.mm) -#ifdef OSX -PseudoNSGLContextPtr GetCurrentNSGLContext( ); -CGLContextObj GetCGLContextFromNSGL( PseudoNSGLContextPtr nsglCtx ); -#endif - -#include "tier0/dynfunction.h" - -//=============================================================================== - -// parrot the D3D present parameters, more or less... "adapter" translates into "active display index" per the m_activeDisplayCount below. -class GLMDisplayParams -{ - public: - - // presumption, these indices are in sync with the current display DB that GLMgr has handy - //int m_rendererIndex; // index of renderer (-1 if root context) - //int m_displayIndex; // index of display in renderer - for FS - //int m_modeIndex; // index of mode in display - for FS - - void *m_focusWindow; // (VD3DHWND aka WindowRef) - what window does this context display into - - bool m_fsEnable; // fullscreen on or not - bool m_vsyncEnable; // vsync on or not - - // height and width have to match the display mode info if full screen. - - uint m_backBufferWidth; // pixel width (aka screen h-resolution if full screen) - uint m_backBufferHeight; // pixel height (aka screen v-resolution if full screen) - D3DFORMAT m_backBufferFormat; // pixel format - uint m_multiSampleCount; // 0 means no MSAA, 2 means 2x MSAA, etc - // uint m_multiSampleQuality; // no MSAA quality control yet - - bool m_enableAutoDepthStencil; // generally set to 'TRUE' per CShaderDeviceDx8::SetPresentParameters - D3DFORMAT m_autoDepthStencilFormat; - - uint m_fsRefreshHz; // if full screen, this refresh rate (likely 0 for LCD's) - - //uint m_rootRendererID; // only used if m_rendererIndex is -1. - //uint m_rootDisplayMask; // only used if m_rendererIndex is -1. - - bool m_mtgl; // enable multi threaded GL driver -}; - -//=============================================================================== - -class GLMgr -{ -public: - - //=========================================================================== - // class methods - singleton - static void NewGLMgr( void ); // instantiate singleton.. - static GLMgr *aGLMgr( void ); // return singleton.. - static void DelGLMgr( void ); // tear down singleton.. - - //=========================================================================== - // plain methods - - #if 0 // turned all these off while new approach is coded - void RefreshDisplayDB( void ); // blow away old display DB, make a new one - GLMDisplayDB *GetDisplayDB( void ); // get a ptr to the one GLMgr keeps. only valid til next refresh. - - // eligible renderers will be ranked by desirability starting at index 0 within the db - // within each renderer, eligible displays will be ranked some kind of desirability (area? dist from menu bar?) - // within each display, eligible modes will be ranked by descending areas - - // calls supplying indices are implicitly making reference to the current DB - bool CaptureDisplay( int rendIndex, int displayIndex, bool captureAll ); // capture one display or all displays - void ReleaseDisplays( void ); // release all captures - - int GetDisplayMode( int rendIndex, int displayIndex ); // retrieve current display res (returns modeIndex) - void SetDisplayMode( GLMDisplayParams *params ); // set the display res (only useful for FS) - #endif - - GLMContext *NewContext( GLMDisplayParams *params ); // this will have to change - void DelContext( GLMContext *context ); - - // with usage of CGLMacro.h we could dispense with the "current context" thing - // and just declare a member variable of GLMContext, allowing each glXXX call to be routed directly - // to the correct context - void SetCurrentContext( GLMContext *context ); // make current in calling thread only - GLMContext *GetCurrentContext( void ); - -protected: - friend class GLMContext; - - GLMgr(); - ~GLMgr(); -}; - - -//===========================================================================// - -// helper function to do enable or disable in one step -inline void glSetEnable( GLenum which, bool enable ) -{ - if (enable) - gGL->glEnable(which); - else - gGL->glDisable(which); -} - -// helper function for int vs enum clarity -inline void glGetEnumv( GLenum which, GLenum *dst ) -{ - gGL->glGetIntegerv( which, (int*)dst ); -} - -//===========================================================================// -// -// types to support the GLMContext -// -//===========================================================================// - -// Each state set/get path we are providing caching for, needs its own struct and a comparison operator. -// we also provide an enum of how many such types there are, handy for building dirty masks etc. - -// shorthand macros -#define EQ(fff) ( (src.fff) == (fff) ) - -//rasterizer -struct GLAlphaTestEnable_t { GLint enable; bool operator==(const GLAlphaTestEnable_t& src) const { return EQ(enable); } }; -struct GLAlphaTestFunc_t { GLenum func; GLclampf ref; bool operator==(const GLAlphaTestFunc_t& src) const { return EQ(func) && EQ(ref); } }; -struct GLCullFaceEnable_t { GLint enable; bool operator==(const GLCullFaceEnable_t& src) const { return EQ(enable); } }; -struct GLCullFrontFace_t { GLenum value; bool operator==(const GLCullFrontFace_t& src) const { return EQ(value); } }; -struct GLPolygonMode_t { GLenum values[2]; bool operator==(const GLPolygonMode_t& src) const { return EQ(values[0]) && EQ(values[1]); } }; -struct GLDepthBias_t { GLfloat factor; GLfloat units; bool operator==(const GLDepthBias_t& src) const { return EQ(factor) && EQ(units); } }; -struct GLScissorEnable_t { GLint enable; bool operator==(const GLScissorEnable_t& src) const { return EQ(enable); } }; -struct GLScissorBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLScissorBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; -struct GLAlphaToCoverageEnable_t{ GLint enable; bool operator==(const GLAlphaToCoverageEnable_t& src) const { return EQ(enable); } }; -struct GLViewportBox_t { GLint x,y; GLsizei width, height; bool operator==(const GLViewportBox_t& src) const { return EQ(x) && EQ(y) && EQ(width) && EQ(height); } }; -struct GLViewportDepthRange_t { GLdouble near,far; bool operator==(const GLViewportDepthRange_t& src) const { return EQ(near) && EQ(far); } }; -struct GLClipPlaneEnable_t { GLint enable; bool operator==(const GLClipPlaneEnable_t& src) const { return EQ(enable); } }; -struct GLClipPlaneEquation_t { GLfloat x,y,z,w; bool operator==(const GLClipPlaneEquation_t& src) const { return EQ(x) && EQ(y) && EQ(z) && EQ(w); } }; - -//blend -struct GLColorMaskSingle_t { char r,g,b,a; bool operator==(const GLColorMaskSingle_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; -struct GLColorMaskMultiple_t { char r,g,b,a; bool operator==(const GLColorMaskMultiple_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; -struct GLBlendEnable_t { GLint enable; bool operator==(const GLBlendEnable_t& src) const { return EQ(enable); } }; -struct GLBlendFactor_t { GLenum srcfactor,dstfactor; bool operator==(const GLBlendFactor_t& src) const { return EQ(srcfactor) && EQ(dstfactor); } }; -struct GLBlendEquation_t { GLenum equation; bool operator==(const GLBlendEquation_t& src) const { return EQ(equation); } }; -struct GLBlendColor_t { GLfloat r,g,b,a; bool operator==(const GLBlendColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; -struct GLBlendEnableSRGB_t { GLint enable; bool operator==(const GLBlendEnableSRGB_t& src) const { return EQ(enable); } }; - -//depth -struct GLDepthTestEnable_t { GLint enable; bool operator==(const GLDepthTestEnable_t& src) const { return EQ(enable); } }; -struct GLDepthFunc_t { GLenum func; bool operator==(const GLDepthFunc_t& src) const { return EQ(func); } }; -struct GLDepthMask_t { char mask; bool operator==(const GLDepthMask_t& src) const { return EQ(mask); } }; - -//stencil -struct GLStencilTestEnable_t { GLint enable; bool operator==(const GLStencilTestEnable_t& src) const { return EQ(enable); } }; -struct GLStencilFunc_t { GLenum frontfunc, backfunc; GLint ref; GLuint mask; bool operator==(const GLStencilFunc_t& src) const { return EQ(frontfunc) && EQ(backfunc) && EQ(ref) && EQ(mask); } }; -struct GLStencilOp_t { GLenum sfail; GLenum dpfail; GLenum dppass; bool operator==(const GLStencilOp_t& src) const { return EQ(sfail) && EQ(dpfail) && EQ(dppass); } }; -struct GLStencilWriteMask_t { GLint mask; bool operator==(const GLStencilWriteMask_t& src) const { return EQ(mask); } }; - -//clearing -struct GLClearColor_t { GLfloat r,g,b,a; bool operator==(const GLClearColor_t& src) const { return EQ(r) && EQ(g) && EQ(b) && EQ(a); } }; -struct GLClearDepth_t { GLdouble d; bool operator==(const GLClearDepth_t& src) const { return EQ(d); } }; -struct GLClearStencil_t { GLint s; bool operator==(const GLClearStencil_t& src) const { return EQ(s); } }; - -#undef EQ - -enum EGLMStateBlockType -{ - kGLAlphaTestEnable, - kGLAlphaTestFunc, - - kGLCullFaceEnable, - kGLCullFrontFace, - - kGLPolygonMode, - - kGLDepthBias, - - kGLScissorEnable, - kGLScissorBox, - - kGLViewportBox, - kGLViewportDepthRange, - - kGLClipPlaneEnable, - kGLClipPlaneEquation, - - kGLColorMaskSingle, - kGLColorMaskMultiple, - - kGLBlendEnable, - kGLBlendFactor, - kGLBlendEquation, - kGLBlendColor, - kGLBlendEnableSRGB, - - kGLDepthTestEnable, - kGLDepthFunc, - kGLDepthMask, - - kGLStencilTestEnable, - kGLStencilFunc, - kGLStencilOp, - kGLStencilWriteMask, - - kGLClearColor, - kGLClearDepth, - kGLClearStencil, - - kGLAlphaToCoverageEnable, - - kGLMStateBlockLimit -}; - -//===========================================================================// - -// templated functions representing GL R/W bottlenecks -// one set of set/get/getdefault is instantiated for each of the GL*** types above. - -// use these from the non array state objects -template void GLContextSet( T *src ); -template void GLContextGet( T *dst ); -template void GLContextGetDefault( T *dst ); - -// use these from the array state objects -template void GLContextSetIndexed( T *src, int index ); -template void GLContextGetIndexed( T *dst, int index ); -template void GLContextGetDefaultIndexed( T *dst, int index ); - -//===========================================================================// - -// caching state object template. One of these is instantiated in the context per unique struct type above -template class GLState -{ - public: - - GLState() - { - dirty = false; - memset( &data, 0, sizeof(data) ); - }; - - // write: client src into cache - // common case is both false. dirty is calculated, context write is deferred. - void Write( T *src, bool noCompare=false, bool noDefer=false ) - { - if (noCompare) - { - dirty = true; - } - else - { - // only == is implemented, so test for equal and negate - // note, you only set dirty if mismatch, you never clear it until flush - if ( !(data == *src) ) - { - dirty = true; - } - } - - data = *src; - - if (noDefer) - { - Flush( true ); // dirty becomes false - } - }; - - // write cache->context if dirty or forced. - void Flush( bool noDefer=false ) - { - if (dirty || noDefer) - { - GLContextSet( &data ); - GLMCheckError(); - // good place for some error checking here - dirty = false; - } - }; - - // default: write default value to cache, optionally write through - void Default( bool noDefer=false ) - { - GLContextGetDefault( &data ); // read default values directly to our cache copy - dirty = true; - Flush(noDefer); - }; - - // read: sel = 0 for cache, 1 for context - void Read( T *dst, int sel ) - { - if (sel==0) - { - *dst = data; - } - else - { - GLContextGet( dst ); - GLMCheckError(); - } - }; - - // check: verify that context equals cache, return true if mismatched or if illegal values seen - bool Check ( void ) - { - T temp; - bool result; - - GLContextGet( &temp ); - GLMCheckError(); - result = !(temp == data); - return result; - }; - - protected: - T data; - bool dirty; -}; - -// caching state object template - with multiple values behind it that are indexed -template class GLStateArray -{ - public: - - GLStateArray() - { - memset( &dirty, 0, sizeof(dirty) ); - memset( &data, 0, sizeof(data) ); - }; - - // write: client src into cache - // common case is both false. dirty is calculated, context write is deferred. - void WriteIndex( T *src, int index, bool noCompare=false, bool noDefer=false ) - { - if (noCompare) - { - dirty[index] = true; - } - else - { - // only == is implemented, so test for equal and negate - // note, you only set dirty if mismatch, you never clear it until flush - if (! (data[index] == *src) ) - { - dirty[index] = true; - } - } - - data[index] = *src; - - if (noDefer) - { - FlushIndex( index, true ); // dirty becomes false - } - }; - - // write cache->context if dirty or forced. - void FlushIndex( int index, bool noDefer=false ) - { - if (dirty[index] || noDefer) - { - GLContextSetIndexed( &data[index], index ); - GLMCheckError(); - dirty[index] = false; - } - }; - - // write all slots in the array - void Flush( bool noDefer=false ) - { - for( int i=0; i m_AlphaTestEnable; - - GLState m_AlphaTestFunc; - - GLState m_CullFaceEnable; - GLState m_CullFrontFace; - GLState m_PolygonMode; - - GLState m_DepthBias; - - GLStateArray m_ClipPlaneEnable; - GLStateArray m_ClipPlaneEquation; // dxabstract puts them directly into param slot 253(0) and 254(1) - - GLState m_ScissorEnable; - GLState m_ScissorBox; - - GLState m_AlphaToCoverageEnable; - - GLState m_ViewportBox; - GLState m_ViewportDepthRange; - - GLState m_ColorMaskSingle; - GLStateArray m_ColorMaskMultiple; // need an official constant for the color buffers limit - - GLState m_BlendEnable; - GLState m_BlendFactor; - GLState m_BlendEquation; - GLState m_BlendColor; - GLState m_BlendEnableSRGB; // write to this one to transmit intent to write SRGB encoded pixels to drawing FB - bool m_FakeBlendEnableSRGB; // writes to above will be shunted here if fake SRGB is in effect. - - GLState m_DepthTestEnable; - GLState m_DepthFunc; - GLState m_DepthMask; - - GLState m_StencilTestEnable; // global stencil test enable - GLState m_StencilFunc; // holds front and back stencil funcs - GLStateArray m_StencilOp; // indexed: 0=front 1=back - GLState m_StencilWriteMask; - - GLState m_ClearColor; - GLState m_ClearDepth; - GLState m_ClearStencil; - - // texture bindings and sampler setup - int m_activeTexture; // mirror for glActiveTexture - GLMTexSampler m_samplers[GLM_SAMPLER_COUNT]; - - // texture lock tracking - CGLMTex objects share usage of this - CUtlVector< GLMTexLockDesc > m_texLocks; - - // render target binding - check before draw - // similar to tex sampler mechanism, we track "bound" from "chosen for drawing" separately, - // so binding for creation/setup need not disrupt any notion of what will be used at draw time - - CGLMFBO *m_boundDrawFBO; // FBO on GL_DRAW_FRAMEBUFFER bind point - CGLMFBO *m_boundReadFBO; // FBO on GL_READ_FRAMEBUFFER bind point - // ^ both are set if you bind to GL_FRAMEBUFFER_EXT - - CGLMFBO *m_drawingFBO; // what FBO should be bound at draw time (to both read/draw bp's). - - CGLMFBO *m_blitReadFBO; - CGLMFBO *m_blitDrawFBO; // scratch FBO's for framebuffer blit - - CGLMFBO *m_scratchFBO[ kGLMScratchFBOCount ]; // general purpose FBO's for internal use - - CUtlVector< CGLMFBO* > m_fboTable; // each live FBO goes in the table - - // program bindings - EGLMProgramLang m_drawingLangAtFrameStart; // selector for start of frame (spills into m_drawingLang) - EGLMProgramLang m_drawingLang; // selector for which language we desire to draw with on the next batch - CGLMProgram *m_drawingProgram[ kGLMNumProgramTypes ]; - - GLMProgramParamsF m_programParamsF[ kGLMNumProgramTypes ]; - GLMProgramParamsB m_programParamsB[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used - GLMProgramParamsI m_programParamsI[ kGLMNumProgramTypes ]; // two banks, but only the vertex one is used - EGLMParamWriteMode m_paramWriteMode; - - CGLMProgram *m_nullFragmentProgram; // write opaque black. Activate when caller asks for null FP - - CGLMProgram *m_preloadTexVertexProgram; // programs to help preload textures (dummies) - CGLMProgram *m_preload2DTexFragmentProgram; - CGLMProgram *m_preload3DTexFragmentProgram; - CGLMProgram *m_preloadCubeTexFragmentProgram; - - CGLMProgram *m_boundProgram[ kGLMNumProgramTypes ]; - - CGLMShaderPairCache *m_pairCache; // GLSL only - CGLMShaderPair *m_boundPair; // GLSL only - uint m_boundPairRevision; // GLSL only - GLhandleARB m_boundPairProgram; // GLSL only - - // buffer bindings - CGLMBuffer *m_lastKnownBufferBinds[ kGLMNumBufferTypes ]; // tracked per bind point for dupe-bind-absorb - GLMVertexAttributeDesc m_lastKnownVertexAttribs[ kGLMVertexAttributeIndexMax ]; // tracked per attrib for dupe-set-absorb - uint m_lastKnownVertexAttribMask; // tracked for dupe-enable-absorb - - CGLMBuffer *m_drawIndexBuffer; // ... ? do we need dupe tracking for index buffer setup? ? - - GLMVertexSetup m_drawVertexSetup; - - EGLMAttribWriteMode m_attribWriteMode; - - bool m_slowCheckEnable; // turn this on or no native checking is done ("-glmassertslow" or "-glmsspewslow") - bool m_slowAssertEnable; // turn this on to assert on a non-native batch "-glmassertslow" - bool m_slowSpewEnable; // turn this on to log non-native batches to stdout "-glmspewslow" - - // debug font texture - CGLMTex *m_debugFontTex; // might be NULL unless you call GenDebugFontTex - CGLMBuffer *m_debugFontIndices; // up to 1024 indices (256 chars times 4) - CGLMBuffer *m_debugFontVertices; // up to 1024 verts - - // batch/frame debugging support - int m_debugFrameIndex; // init to -1. Increment at BeginFrame - int m_debugBatchIndex; // init to -1. Increment at any draw call - -#if GLMDEBUG - // interactive (DebugHook) debug support - - // using these you can implement frame advance, batch single step, and batch rewind (let it run til next frame and hold on prev batch #) - int m_holdFrameBegin; // -1 if no hold req'd, otherwise # of frame to hold at (at beginframe time) - int m_holdFrameEnd; // -1 if no hold req'd, otherwise # of frame to hold at (at endframe time) - - int m_holdBatch,m_holdBatchFrame; // -1 if no hold, else # of batch&frame to hold at (both must be set) - // these can be expired/cleared to -1 if the frame passes without a hit - // may be desirable to re-pause in that event, as user was expecting a hold to occur - - bool m_debugDelayEnable; // allow sleep delay - uint m_debugDelay; // sleep time per hook call in microseconds (for usleep()) - - // pre-draw global toggles / options - bool m_autoClearColor,m_autoClearDepth,m_autoClearStencil; - float m_autoClearColorValues[4]; - - // debug knobs - int m_selKnobIndex; - float m_selKnobMinValue,m_selKnobMaxValue,m_selKnobIncrement; -#endif - -}; - -struct GLMTestParams -{ - GLMContext *m_ctx; - int *m_testList; // -1 termed - - bool m_glErrToDebugger; - bool m_glErrToConsole; - - bool m_intlErrToDebugger; - bool m_intlErrToConsole; - - int m_frameCount; // how many frames to test. -}; - -class GLMTester -{ - public: - - GLMTester(GLMTestParams *params); - ~GLMTester(); - - - // optionally callable by test routines to get basic drawables wired up - void StdSetup( void ); - void StdCleanup( void ); - - // callable by test routines to clear the frame or present it - void Clear( void ); - void Present( int seed ); - - // error reporting - void CheckGLError( char *comment ); // obey m_params setting for console / debugger response - void InternalError( int errcode, char *comment ); // if errcode!=0, obey m_params setting for console / debugger response - - void RunTests(); - - void RunOneTest( int testindex ); - - // test routines themselves - void Test0(); - void Test1(); - void Test2(); - void Test3(); - - GLMTestParams m_params; // copy of caller's params, do not mutate... - - // std-setup stuff - int m_drawWidth, m_drawHeight; - CGLMFBO *m_drawFBO; - CGLMTex *m_drawColorTex; - CGLMTex *m_drawDepthTex; -}; - -class CShowPixelsParams -{ -public: - GLuint m_srcTexName; - int m_width,m_height; - bool m_vsyncEnable; - bool m_fsEnable; // want receiving view to be full screen. for now, just target the main screen. extend later. - bool m_useBlit; // use FBO blit - sending context says it is available. - bool m_noBlit; // the back buffer has already been populated by the caller (perhaps via direct MSAA resolve from multisampled RT tex) - bool m_onlySyncView; // react to full/windowed state change only, do not present bits -}; - - -#define kMaxCrawlFrames 100 -#define kMaxCrawlText (kMaxCrawlFrames * 256) -class CStackCrawlParams -{ - public: - uint m_frameLimit; // input: max frames to retrieve - uint m_frameCount; // output: frames found - void *m_crawl[kMaxCrawlFrames]; // call site addresses - char *m_crawlNames[kMaxCrawlFrames]; // pointers into text following, one per decoded name - char m_crawlText[kMaxCrawlText]; -}; - -#endif diff --git a/mp/src/public/togl/osx/glmgrbasics.h b/mp/src/public/togl/osx/glmgrbasics.h deleted file mode 100644 index d6476b3d..00000000 --- a/mp/src/public/togl/osx/glmgrbasics.h +++ /dev/null @@ -1,299 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// glmgrbasics.h -// types, common headers, forward declarations, utilities -// -//=============================================================================== - -#ifndef GLMBASICS_H -#define GLMBASICS_H - -#pragma once - -#ifdef OSX -#include -#include -#include -#include -#include -#include -//#include -//#include -#elif defined(LINUX) -#include -#include -#else -#error -#endif - -#include "tier0/platform.h" - -#include "bitmap/imageformat.h" -#include "bitvec.h" -#include "tier1/checksum_md5.h" -#include "tier1/utlvector.h" -#include "tier1/convar.h" - -#include - -#include "dxabstract_types.h" - -// types -struct GLMRect; -typedef void *PseudoGLContextPtr; - - - // 3-d integer box (used for texture lock/unlock etc) -struct GLMRegion -{ - int xmin,xmax; - int ymin,ymax; - int zmin,zmax; -}; - -struct GLMRect // follows GL convention - if coming from the D3D rect you will need to fiddle the Y's -{ - int xmin; // left - int ymin; // bottom - int xmax; // right - int ymax; // top -}; - -// macros - -//#define GLMassert(x) assert(x) - -// forward decls -class GLMgr; // singleton -class GLMContext; // GL context -class CGLMContextTester; // testing class -class CGLMTex; -class CGLMFBO; -class CGLMProgram; -class CGLMBuffer; - - -// utilities - -typedef enum -{ - // D3D codes - eD3D_DEVTYPE, - eD3D_FORMAT, - eD3D_RTYPE, - eD3D_USAGE, - eD3D_RSTATE, // render state - eD3D_SIO, // D3D shader bytecode - eD3D_VTXDECLUSAGE, - - // CGL codes - eCGL_RENDID, - - // OpenGL error codes - eGL_ERROR, - - // OpenGL enums - eGL_ENUM, - eGL_RENDERER - -} GLMThing_t; - -const char* GLMDecode( GLMThing_t type, unsigned long value ); // decode a numeric const -const char* GLMDecodeMask( GLMThing_t type, unsigned long value ); // decode a bitmask - -void GLMStop( void ); // aka Debugger() -void GLMCheckError( bool noStop = false, bool noLog= false ); -void GLMEnableTrace( bool on ); - -// expose these in release now -// Mimic PIX events so we can decorate debug spew -void GLMBeginPIXEvent( const char *str ); -void GLMEndPIXEvent( void ); - -//=============================================================================== -// knob twiddling -//float GLMKnob( char *knobname, float *setvalue ); // Pass NULL to not-set the knob value -//float GLMKnobToggle( char *knobname ); - -//=============================================================================== -// other stuff - -// helpers for CGLSetOption - no op if no profiler -void GLMProfilerClearTrace( void ); -void GLMProfilerEnableTrace( bool enable ); - -// helpers for CGLSetParameter - no op if no profiler -void GLMProfilerDumpState( void ); - - -//=============================================================================== -// classes - -// helper class making function tracking easier to wire up -#if GLMDEBUG -class GLMFuncLogger -{ - public: - - // simple function log - GLMFuncLogger( const char *funcName ) - { - m_funcName = funcName; - m_earlyOut = false; - - GLMPrintf( ">%s", m_funcName ); - }; - - // more advanced version lets you pass args (i.e. called parameters or anything else of interest) - // no macro for this one, since no easy way to pass through the args as well as the funcname - GLMFuncLogger( const char *funcName, char *fmt, ... ) - { - m_funcName = funcName; - m_earlyOut = false; - - // this acts like GLMPrintf here - // all the indent policy is down in GLMPrintfVA - // which means we need to inject a ">" at the front of the format string to make this work... sigh. - - char modifiedFmt[2000]; - modifiedFmt[0] = '>'; - strcpy( modifiedFmt+1, fmt ); - - va_list vargs; - va_start(vargs, fmt); - GLMPrintfVA( modifiedFmt, vargs ); - va_end( vargs ); - } - - ~GLMFuncLogger( ) - { - if (m_earlyOut) - { - GLMPrintf( "<%s (early out)", m_funcName ); - } - else - { - GLMPrintf( "<%s", m_funcName ); - } - }; - - void EarlyOut( void ) - { - m_earlyOut = true; - }; - - const char *m_funcName; // set at construction time - bool m_earlyOut; -}; - -// handy macro to go with the function tracking class -#define GLM_FUNC GLMFuncLogger _logger_ ( __FUNCTION__ ) -#else -#define GLM_FUNC -#endif - - -// class to keep an in-memory mirror of a file which may be getting edited during run -class CGLMFileMirror -{ -public: - CGLMFileMirror( char *fullpath ); // just associates mirror with file. if file exists it will be read. - //if non existent it will be created with size zero - ~CGLMFileMirror( ); - - bool HasData( void ); // see if data avail - void GetData( char **dataPtr, uint *dataSizePtr ); // read it out - void SetData( char *data, uint dataSize ); // put data in (and write it to disk) - bool PollForChanges( void ); // check disk copy. If different, read it back in and return true. - - void UpdateStatInfo( void ); // make sure stat info is current for our file - void ReadFile( void ); - void WriteFile( void ); - - void OpenInEditor( bool foreground=false ); // pass TRUE if you would like the editor to pop to foreground - - /// how about a "wait for change" method.. - - char *m_path; // fullpath to file - bool m_exists; - struct stat m_stat; // stat results for the file (last time checked) - - char *m_data; // content of file - uint m_size; // length of content - -}; - -// class based on the file mirror, that makes it easy to edit them outside the app. - -// it receives an initial block of text from the engine, and hashes it. ("orig") -// it munges it by duplicating all the text after the "!!" line, and appending it in commented form. ("munged") -// a mirror file is activated, using a filename based on the hash from the orig text. -// if there is already content on disk matching that filename, use that content *unless* the 'blitz' parameter is set. -// (i.e. engine is instructing this subsystem to wipe out any old/modified variants of the text) - - -class CGLMEditableTextItem -{ -public: - CGLMEditableTextItem( char *text, uint size, bool forceOverwrite, char *prefix, char *suffix = NULL ); // create a text blob from text source, optional filename suffix - ~CGLMEditableTextItem( ); - - bool HasData( void ); - bool PollForChanges( void ); // return true if stale i.e. you need to get a new edition - void GetCurrentText( char **textOut, uint *sizeOut ); // query for read access to the active blob (could be the original, could be external edited copy) - void OpenInEditor( bool foreground=false ); // call user attention to this text - - // internal methods - void GenHashOfOrigText( void ); - void GenBaseNameAndFullPath( char *prefix, char *suffix ); - void GenMungedText( bool fromMirror ); - - // members - // orig - uint m_origSize; - char *m_origText; // what was submitted - unsigned char m_origDigest[MD5_DIGEST_LENGTH]; // digest of what was submitted - - // munged - uint m_mungedSize; - char *m_mungedText; // re-processed edition, initial content submission to the file mirror - - // mirror - char *m_mirrorBaseName; // generated from the hash of the orig text, plus the label / prefix - char *m_mirrorFullPath; // base name - CGLMFileMirror *m_mirror; // file mirror itself. holds "official" copy for GetCurrentText to return. -}; - - -// debug font -extern unsigned char g_glmDebugFontMap[16384]; - -// class for cracking multi-part text blobs -// sections are demarcated by beginning-of-line markers submitted in a table by the caller - -struct GLMTextSection -{ - int m_markerIndex; // based on table of markers passed in to constructor - uint m_textOffset; // where is the text - offset - int m_textLength; // how big is the section -}; - -class CGLMTextSectioner -{ -public: - CGLMTextSectioner( char *text, int textSize, char **markers ); // constructor finds all the sections - ~CGLMTextSectioner( ); - - int Count( void ); // how many sections found - void GetSection( int index, uint *offsetOut, uint *lengthOut, int *markerIndexOut ); - // find section, size, what marker - // note that more than one section can be marked similarly. - // so policy isn't made here, you walk the sections and decide what to do if there are dupes. - - //members - - //section table - CUtlVector< GLMTextSection > m_sectionTable; -}; - -#endif diff --git a/mp/src/public/togl/osx/glmgrext.h b/mp/src/public/togl/osx/glmgrext.h deleted file mode 100644 index 02939bb6..00000000 --- a/mp/src/public/togl/osx/glmgrext.h +++ /dev/null @@ -1,93 +0,0 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// glmgrext.h -// helper file for extension testing and runtime importing of entry points -// -//=============================================================================== - -#pragma once - -#ifdef OSX -#include -#include -#elif defined(LINUX) -#include -#include -#else -#error -#endif - -#ifndef GL_EXT_framebuffer_sRGB - #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 - #define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA -#endif - -#ifndef ARB_texture_rg - #define GL_COMPRESSED_RED 0x8225 - #define GL_COMPRESSED_RG 0x8226 - #define GL_RG 0x8227 - #define GL_RG_INTEGER 0x8228 - #define GL_R8 0x8229 - #define GL_R16 0x822A - #define GL_RG8 0x822B - #define GL_RG16 0x822C - #define GL_R16F 0x822D - #define GL_R32F 0x822E - #define GL_RG16F 0x822F - #define GL_RG32F 0x8230 - #define GL_R8I 0x8231 - #define GL_R8UI 0x8232 - #define GL_R16I 0x8233 - #define GL_R16UI 0x8234 - #define GL_R32I 0x8235 - #define GL_R32UI 0x8236 - #define GL_RG8I 0x8237 - #define GL_RG8UI 0x8238 - #define GL_RG16I 0x8239 - #define GL_RG16UI 0x823A - #define GL_RG32I 0x823B - #define GL_RG32UI 0x823C -#endif - -#ifndef GL_EXT_bindable_uniform - #define GL_UNIFORM_BUFFER_EXT 0x8DEE -#endif - -// unpublished extension enums (thus the "X") - -// from EXT_framebuffer_multisample_blit_scaled.. -#define XGL_SCALED_RESOLVE_FASTEST_EXT 0x90BA -#define XGL_SCALED_RESOLVE_NICEST_EXT 0x90BB - -#ifndef GL_TEXTURE_MINIMIZE_STORAGE_APPLE -#define GL_TEXTURE_MINIMIZE_STORAGE_APPLE 0x85B6 -#endif - -#ifndef GL_ALL_COMPLETED_NV -#define GL_ALL_COMPLETED_NV 0x84F2 -#endif - -#ifndef GL_MAP_READ_BIT -#define GL_MAP_READ_BIT 0x0001 -#endif - -#ifndef GL_MAP_WRITE_BIT -#define GL_MAP_WRITE_BIT 0x0002 -#endif - -#ifndef GL_MAP_INVALIDATE_RANGE_BIT -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#endif - -#ifndef GL_MAP_INVALIDATE_BUFFER_BIT -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#endif - -#ifndef GL_MAP_FLUSH_EXPLICIT_BIT -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#endif - -#ifndef GL_MAP_UNSYNCHRONIZED_BIT -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 -#endif - diff --git a/mp/src/public/togl/rendermechanism.h b/mp/src/public/togl/rendermechanism.h index 928021a5..47be332d 100644 --- a/mp/src/public/togl/rendermechanism.h +++ b/mp/src/public/togl/rendermechanism.h @@ -1,4 +1,27 @@ //========= Copyright Valve Corporation, All rights reserved. ============// +// TOGL CODE LICENSE +// +// Copyright 2011-2014 Valve Corporation +// All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// #ifndef RENDERMECHANISM_H #define RENDERMECHANISM_H @@ -8,11 +31,10 @@ #include #include + #include "tier0/basetypes.h" #include "tier0/platform.h" -#if defined(LINUX) || defined(_WIN32) - #include "togl/linuxwin/glmdebug.h" #include "togl/linuxwin/glbase.h" #include "togl/linuxwin/glentrypoints.h" @@ -29,25 +51,6 @@ #include "togl/linuxwin/dxabstract_types.h" #include "togl/linuxwin/dxabstract.h" -#elif defined(OSX) -#include "togl/osx/glmdebug.h" -//#include "togl/osx/glbase.h" -#include "togl/osx/glentrypoints.h" -#include "togl/osx/glmdisplay.h" -#include "togl/osx/glmdisplaydb.h" -#include "togl/osx/glmgrbasics.h" -#include "togl/osx/glmgrext.h" -#include "togl/osx/cglmbuffer.h" -#include "togl/osx/cglmtex.h" -#include "togl/osx/cglmfbo.h" -#include "togl/osx/cglmprogram.h" -#include "togl/osx/cglmquery.h" -#include "togl/osx/glmgr.h" -#include "togl/osx/dxabstract_types.h" -#include "togl/osx/dxabstract.h" - -#endif - #else //USE_ACTUAL_DX #ifdef WIN32 diff --git a/mp/src/public/vgui/VGUI.h b/mp/src/public/vgui/VGUI.h index cd2e9650..34fddfeb 100644 --- a/mp/src/public/vgui/VGUI.h +++ b/mp/src/public/vgui/VGUI.h @@ -66,12 +66,10 @@ const HFont INVALID_FONT = 0; // the value of an invalid font handle #include "tier1/strtools.h" -#if defined( OSX ) // || defined( LINUX ) -// Set to 1 to use GetKernedCharWidth() instead of GetCharABCwide(). Alfred -// initially started using that code on the Mac because it did better -// kerning, but he was a leery about switching win32 over. I enabled this -// for Linux, but it causes some strings to look different than Windows. So -// I've disabled it for now. mikesart - 12/2012. +#if 0 // defined( OSX ) // || defined( LINUX ) +// Disabled all platforms. Did a major cleanup of osxfont.cpp, and having this +// turned off renders much closer to Windows and Linux and also uses the same +// code paths (which is good). #define USE_GETKERNEDCHARWIDTH 1 #else #define USE_GETKERNEDCHARWIDTH 0 diff --git a/mp/src/public/vgui_controls/AnimationController.h b/mp/src/public/vgui_controls/AnimationController.h index e418f329..93ae7096 100644 --- a/mp/src/public/vgui_controls/AnimationController.h +++ b/mp/src/public/vgui_controls/AnimationController.h @@ -52,6 +52,9 @@ public: bool StartAnimationSequence(const char *sequenceName); bool StartAnimationSequence(Panel *pWithinParent, const char *sequenceName); + bool StopAnimationSequence( Panel *pWithinParent, const char *sequenceName ); + void CancelAnimationsForPanel( Panel *pWithinParent ); + // gets the length of an animation sequence, in seconds float GetAnimationSequenceLength(const char *sequenceName); @@ -96,6 +99,9 @@ private: CMD_SETFONT, CMD_SETTEXTURE, CMD_SETSTRING, + CMD_RUNEVENTCHILD, + CMD_FIRECOMMAND, + CMD_SETVISIBLE, }; enum RelativeAlignment @@ -223,6 +229,7 @@ private: // variable names UtlSymId_t m_sPosition, m_sSize, m_sFgColor, m_sBgColor; UtlSymId_t m_sXPos, m_sYPos, m_sWide, m_sTall; + UtlSymId_t m_sModelPos; // file name CUtlVector m_ScriptFileNames; diff --git a/mp/src/public/vgui_controls/ComboBox.h b/mp/src/public/vgui_controls/ComboBox.h index c5c3eba0..266f4dc2 100644 --- a/mp/src/public/vgui_controls/ComboBox.h +++ b/mp/src/public/vgui_controls/ComboBox.h @@ -63,7 +63,7 @@ public: virtual int AddItem(const char *itemText, const KeyValues *userData); virtual int AddItem(const wchar_t *itemText, const KeyValues *userData); - virtual int GetItemCount(); + virtual int GetItemCount() const; int GetItemIDFromRow( int row ); // update the item diff --git a/mp/src/public/vgui_controls/HTML.h b/mp/src/public/vgui_controls/HTML.h index 59e76770..ad786d20 100644 --- a/mp/src/public/vgui_controls/HTML.h +++ b/mp/src/public/vgui_controls/HTML.h @@ -24,7 +24,6 @@ #endif #include "steam/steam_api.h" -class HTMLComboBoxHost; namespace vgui { @@ -80,7 +79,7 @@ public: // overridden to paint our special web browser texture virtual void Paint(); - + // pass messages to the texture component to tell it about resizes virtual void OnSizeChanged(int wide,int tall); @@ -124,7 +123,7 @@ public: void AddHeader( const char *pchHeader, const char *pchValue ); void OnKillFocus(); void OnSetFocus(); - + void Find( const char *pchSubStr ); void StopFind(); void FindNext(); @@ -147,7 +146,6 @@ public: } #endif // DBGFLAG_VALIDATE - void PaintComboBox(); ISteamHTMLSurface *SteamHTMLSurface() { return m_SteamAPIContext.SteamHTMLSurface(); } void OnHTMLMouseMoved( int x, int y ) @@ -159,20 +157,13 @@ public: protected: virtual void ApplySchemeSettings( IScheme *pScheme ); - friend class HTMLComboBoxHost; vgui::Menu *m_pContextMenu; - private: STEAM_CALLBACK( HTML, BrowserNeedsPaint, HTML_NeedsPaint_t, m_NeedsPaint ); - STEAM_CALLBACK( HTML, BrowserComboNeedsPaint, HTML_ComboNeedsPaint_t, m_ComboNeedsPaint ); STEAM_CALLBACK( HTML, BrowserStartRequest, HTML_StartRequest_t, m_StartRequest ); STEAM_CALLBACK( HTML, BrowserURLChanged, HTML_URLChanged_t, m_URLChanged ); STEAM_CALLBACK( HTML, BrowserFinishedRequest, HTML_FinishedRequest_t, m_FinishedRequest ); - STEAM_CALLBACK( HTML, BrowserShowPopup, HTML_ShowPopup_t, m_ShowPopup ); - STEAM_CALLBACK( HTML, BrowserHidePopup, HTML_HidePopup_t, m_HidePopup ); - STEAM_CALLBACK( HTML, BrowserSizePopup, HTML_SizePopup_t, m_SizePopup ); - STEAM_CALLBACK( HTML, BrowserOpenNewTab, HTML_OpenLinkInNewTab_t, m_LinkInNewTab ); STEAM_CALLBACK( HTML, BrowserSetHTMLTitle, HTML_ChangedTitle_t, m_ChangeTitle ); STEAM_CALLBACK( HTML, BrowserPopupHTMLWindow, HTML_NewWindow_t, m_NewWindow ); @@ -227,7 +218,6 @@ private: }; CHTMLFindBar *m_pFindBar; - HTMLComboBoxHost *m_pComboBoxHost; int m_iMouseX,m_iMouseY; // where the mouse is on the control @@ -255,10 +245,7 @@ private: // when the size has changed and reallocate the texture. int m_allocedTextureWidth; int m_allocedTextureHeight; - int m_iComboBoxTextureID; // vgui texture id of the combo box - bool m_bNeedsFullTextureUpload; - int m_allocedComboBoxWidth; - int m_allocedComboBoxHeight; + bool m_bNeedsFullTextureUpload; CUtlString m_sCurrentURL; // the url of our current page // find in page state bool m_bInFind; diff --git a/mp/src/public/vgui_controls/Menu.h b/mp/src/public/vgui_controls/Menu.h index 2b374373..77937335 100644 --- a/mp/src/public/vgui_controls/Menu.h +++ b/mp/src/public/vgui_controls/Menu.h @@ -216,7 +216,7 @@ public: virtual int GetActiveItem(); // returns the itemID (not the row) of the active item // Return the number of items currently in the menu list - virtual int GetItemCount(); + virtual int GetItemCount() const; // return the menuID of the n'th item in the menu list, valid from [0, GetItemCount) virtual int GetMenuID(int index); @@ -351,6 +351,29 @@ private: double m_fLastTypeAheadTime; }; + +//----------------------------------------------------------------------------- +// Helper class to create menu +//----------------------------------------------------------------------------- +class MenuBuilder +{ +public: + + MenuBuilder( Menu *pMenu, Panel *pActionTarget ); + + MenuItem* AddMenuItem( const char *pszButtonText, const char *pszCommand, const char *pszCategoryName ); + + MenuItem* AddCascadingMenuItem( const char *pszButtonText, Menu *pSubMenu, const char *pszCategoryName ); + +private: + + void AddSepratorIfNeeded( const char *pszCategoryName ); + + Menu *m_pMenu; + Panel *m_pActionTarget; + const char *m_pszLastCategory; +}; + } // namespace vgui #endif // MENU_H diff --git a/mp/src/public/vgui_controls/Panel.h b/mp/src/public/vgui_controls/Panel.h index 07b63d8d..174dea42 100644 --- a/mp/src/public/vgui_controls/Panel.h +++ b/mp/src/public/vgui_controls/Panel.h @@ -180,6 +180,8 @@ public: // all units are in pixels void SetPos(int x,int y); // sets position of panel, in local space (ie. relative to parent's position) void GetPos(int &x,int &y); // gets local position of panel + int GetXPos(); + int GetYPos(); void SetSize(int wide,int tall); // sets size of panel void GetSize(int &wide, int &tall); // gets size of panel void SetBounds(int x, int y, int wide, int tall); // combination of SetPos/SetSize @@ -232,7 +234,7 @@ public: Panel *FindSiblingByName(const char *siblingName); void CallParentFunction(KeyValues *message); - template + template < class T > T *FindControl( const char *pszName, bool recurseDown = false ) { return dynamic_cast( FindChildByName( pszName, recurseDown ) ); } virtual void SetAutoDelete(bool state); // if set to true, panel automatically frees itself when parent is deleted @@ -274,6 +276,8 @@ public: PIN_CENTER_RIGHT, PIN_CENTER_BOTTOM, PIN_CENTER_LEFT, + + PIN_LAST }; // specifies the auto-resize directions for the panel @@ -398,6 +402,7 @@ public: virtual void OnMousePressed(MouseCode code); virtual void OnMouseDoublePressed(MouseCode code); virtual void OnMouseReleased(MouseCode code); + virtual void OnMouseMismatchedRelease( MouseCode code, Panel* pPressedPanel ); virtual void OnMouseWheeled(int delta); // Trip pressing (e.g., select all text in a TextEntry) requires this to be enabled @@ -667,6 +672,8 @@ protected: virtual void PaintTraverse(bool Repaint, bool allowForce = true); protected: + virtual void OnChildSettingsApplied( KeyValues *pInResourceData, Panel *pChild ); + MESSAGE_FUNC_ENUM_ENUM( OnRequestFocus, "OnRequestFocus", VPANEL, subFocus, VPANEL, defaultPanel); MESSAGE_FUNC_INT_INT( OnScreenSizeChanged, "OnScreenSizeChanged", oldwide, oldtall ); virtual void *QueryInterface(EInterfaceID id); @@ -913,6 +920,8 @@ private: bool m_bForceStereoRenderToFrameBuffer; + static Panel* m_sMousePressedPanels[ ( MOUSE_MIDDLE - MOUSE_LEFT ) + 1 ]; + CPanelAnimationVar( float, m_flAlpha, "alpha", "255" ); // 1 == Textured (TextureId1 only) diff --git a/mp/src/public/vgui_controls/SectionedListPanel.h b/mp/src/public/vgui_controls/SectionedListPanel.h index c38f6c74..6fafedd3 100644 --- a/mp/src/public/vgui_controls/SectionedListPanel.h +++ b/mp/src/public/vgui_controls/SectionedListPanel.h @@ -210,6 +210,8 @@ public: void MoveSelectionDown( void ); void MoveSelectionUp( void ); + ScrollBar *GetScrollBar( void ) { return m_pScrollBar; } + protected: virtual void PerformLayout(); virtual void ApplySchemeSettings(IScheme *pScheme); diff --git a/mp/src/public/vgui_controls/TextImage.h b/mp/src/public/vgui_controls/TextImage.h index 499785ff..20446e7b 100644 --- a/mp/src/public/vgui_controls/TextImage.h +++ b/mp/src/public/vgui_controls/TextImage.h @@ -105,6 +105,9 @@ public: void SetColorChangeStream( CUtlSortVector *pUtlVecStream ); void ClearColorChangeStream( void ) { m_ColorChangeStream.Purge(); } + const wchar_t *GetEllipsesPosition( void ) const { return m_pwszEllipsesPosition; } + bool IsWrapping() const { return m_LineBreaks.Count() != 0; } + protected: // truncate the _text string to fit into the draw width void SizeText(wchar_t *tempText, int stringLength); diff --git a/mp/src/public/vstdlib/IKeyValuesSystem.h b/mp/src/public/vstdlib/IKeyValuesSystem.h index 1bd5a8ab..e999dd81 100644 --- a/mp/src/public/vstdlib/IKeyValuesSystem.h +++ b/mp/src/public/vstdlib/IKeyValuesSystem.h @@ -16,6 +16,9 @@ typedef int HKeySymbol; #define INVALID_KEY_SYMBOL (-1) +class IBaseFileSystem; +class KeyValues; + //----------------------------------------------------------------------------- // Purpose: Interface to shared data repository for KeyValues (included in vgui_controls.lib) // allows for central data storage point of KeyValues symbol table @@ -39,6 +42,12 @@ public: // for debugging, adds KeyValues record into global list so we can track memory leaks virtual void AddKeyValuesToMemoryLeakList(void *pMem, HKeySymbol name) = 0; virtual void RemoveKeyValuesFromMemoryLeakList(void *pMem) = 0; + + // maintain a cache of KeyValues we load from disk. This saves us quite a lot of time on app startup. + virtual void AddFileKeyValuesToCache( const KeyValues* _kv, const char *resourceName, const char *pathID ) = 0; + virtual bool LoadFileKeyValuesFromCache( KeyValues* _outKv, const char *resourceName, const char *pathID, IBaseFileSystem *filesystem ) const = 0; + virtual void InvalidateCache( ) = 0; + virtual void InvalidateCacheForFile( const char *resourceName, const char *pathID ) = 0; }; VSTDLIB_INTERFACE IKeyValuesSystem *KeyValuesSystem(); diff --git a/mp/src/public/vstdlib/random.h b/mp/src/public/vstdlib/random.h index 88188031..fdfd09c6 100644 --- a/mp/src/public/vstdlib/random.h +++ b/mp/src/public/vstdlib/random.h @@ -22,9 +22,11 @@ //----------------------------------------------------------------------------- // A generator of uniformly distributed random numbers //----------------------------------------------------------------------------- -class IUniformRandomStream +class VSTDLIB_CLASS IUniformRandomStream { public: + //virtual ~IUniformRandomStream() { } + // Sets the seed of the random number generator virtual void SetSeed( int iSeed ) = 0; @@ -86,7 +88,6 @@ private: CThreadFastMutex m_mutex; }; - //----------------------------------------------------------------------------- // A couple of convenience functions to access the library's global uniform stream //----------------------------------------------------------------------------- @@ -96,6 +97,17 @@ VSTDLIB_INTERFACE float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = VSTDLIB_INTERFACE int RandomInt( int iMinVal, int iMaxVal ); VSTDLIB_INTERFACE float RandomGaussianFloat( float flMean = 0.0f, float flStdDev = 1.0f ); +//----------------------------------------------------------------------------- +// IUniformRandomStream interface for free functions +//----------------------------------------------------------------------------- +class VSTDLIB_CLASS CDefaultUniformRandomStream : public IUniformRandomStream +{ +public: + virtual void SetSeed( int iSeed ) OVERRIDE { RandomSeed( iSeed ); } + virtual float RandomFloat( float flMinVal, float flMaxVal ) OVERRIDE { return ::RandomFloat( flMinVal, flMaxVal ); } + virtual int RandomInt( int iMinVal, int iMaxVal ) OVERRIDE { return ::RandomInt( iMinVal, iMaxVal ); } + virtual float RandomFloatExp( float flMinVal, float flMaxVal, float flExponent ) OVERRIDE { return ::RandomFloatExp( flMinVal, flMaxVal, flExponent ); } +}; //----------------------------------------------------------------------------- // Installs a global random number generator, which will affect the Random functions above diff --git a/mp/src/public/vtf/vtf.h b/mp/src/public/vtf/vtf.h index ecf10c88..a77e7fb1 100644 --- a/mp/src/public/vtf/vtf.h +++ b/mp/src/public/vtf/vtf.h @@ -56,9 +56,9 @@ enum CompiledVtfFlags TEXTUREFLAGS_NODEBUGOVERRIDE = 0x00020000, TEXTUREFLAGS_SINGLECOPY = 0x00040000, - TEXTUREFLAGS_UNUSED_00080000 = 0x00080000, - TEXTUREFLAGS_UNUSED_00100000 = 0x00100000, - TEXTUREFLAGS_UNUSED_00200000 = 0x00200000, + TEXTUREFLAGS_STAGING_MEMORY = 0x00080000, + TEXTUREFLAGS_IMMEDIATE_CLEANUP = 0x00100000, + TEXTUREFLAGS_IGNORE_PICMIP = 0x00200000, TEXTUREFLAGS_UNUSED_00400000 = 0x00400000, TEXTUREFLAGS_NODEPTHBUFFER = 0x00800000, diff --git a/mp/src/public/zip_uncompressed.h b/mp/src/public/zip_uncompressed.h index 0c8a45e6..11f4e86d 100644 --- a/mp/src/public/zip_uncompressed.h +++ b/mp/src/public/zip_uncompressed.h @@ -14,6 +14,10 @@ #define PKID( a, b ) (((b)<<24)|((a)<<16)|('K'<<8)|'P') +// compressionMethod field +#define ZIP_COMPRESSION_NONE 0 +#define ZIP_COMPRESSION_LZMA 14 + #pragma pack(1) struct ZIP_EndOfCentralDirRecord diff --git a/mp/src/public/zip_utils.cpp b/mp/src/public/zip_utils.cpp index 79f51c5c..848e7a79 100644 --- a/mp/src/public/zip_utils.cpp +++ b/mp/src/public/zip_utils.cpp @@ -23,6 +23,13 @@ #include "byteswap.h" #include "utlstring.h" +#include "tier1/lzmaDecoder.h" + +// Not every user of zip utils wants to link LZMA encoder +#ifdef ZIP_SUPPORT_LZMA_ENCODE +#include "lzma/lzma.h" +#endif + // Data descriptions for byte swapping - only needed // for structures that are written to file for use by the game. BEGIN_BYTESWAP_DATADESC( ZIP_EndOfCentralDirRecord ) @@ -248,7 +255,7 @@ public: CBufferStream( CUtlBuffer& buff ) : IWriteStream(), m_buff( &buff ) {} // Implementing IWriteStream method - virtual void Put( const void* pMem, int size ) { m_buff->Put( pMem, size ); } + virtual void Put( const void* pMem, int size ) {m_buff->Put( pMem, size );} // Implementing IWriteStream method virtual unsigned int Tell( void ) { return m_buff->TellPut(); } @@ -321,13 +328,13 @@ public: void Reset( void ); // Add file to zip under relative name - void AddFileToZip( const char *relativename, const char *fullpath ); + void AddFileToZip( const char *relativename, const char *fullpath, IZip::eCompressionType compressionType ); // Delete file from zip void RemoveFileFromZip( const char *relativename ); // Add buffer to zip as a file with given name - void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ); + void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType ); // Check if a file already exists in the zip. bool FileExistsInZip( const char *relativename ); @@ -373,9 +380,12 @@ private: typedef struct { - CUtlSymbol m_Name; - unsigned int filepos; - int filelen; + CUtlSymbol m_Name; + unsigned int filepos; + int filelen; + int uncompressedLen; + CRC32_t crc32; + IZip::eCompressionType compressionType; } TmpFileInfo_t; CByteswap m_Swap; @@ -405,18 +415,25 @@ private: CUtlSymbol m_Name; // Lenth of data element - int m_Length; + int m_nCompressedSize; + + // Original, uncompressed size + int m_nUncompressedSize; + // Raw data, could be null and data may be in disk write cache void *m_pData; // Offset in Zip ( set and valid during final write ) unsigned int m_ZipOffset; - // CRC of blob ( set and valid during final write ) + // CRC of blob CRC32_t m_ZipCRC; // Location of data in disk cache unsigned int m_DiskCacheOffset; unsigned int m_SourceDiskOffset; + + // The compression used on the data if any + IZip::eCompressionType m_eCompressionType; }; // For fast name lookup and sorting @@ -435,12 +452,14 @@ private: CZipFile::CZipEntry::CZipEntry( void ) { m_Name = ""; - m_Length = 0; + m_nCompressedSize = 0; + m_nUncompressedSize = 0; m_pData = NULL; m_ZipOffset = 0; m_ZipCRC = 0; m_DiskCacheOffset = 0; m_SourceDiskOffset = 0; + m_eCompressionType = IZip::eCompressionType_None; } //----------------------------------------------------------------------------- @@ -450,12 +469,14 @@ CZipFile::CZipEntry::CZipEntry( void ) CZipFile::CZipEntry::CZipEntry( const CZipFile::CZipEntry& src ) { m_Name = src.m_Name; - m_Length = src.m_Length; + m_nCompressedSize = src.m_nCompressedSize; + m_nUncompressedSize = src.m_nUncompressedSize; + m_eCompressionType = src.m_eCompressionType; - if ( src.m_Length > 0 && src.m_pData ) + if ( src.m_nCompressedSize > 0 && src.m_pData ) { - m_pData = malloc( src.m_Length ); - memcpy( m_pData, src.m_pData, src.m_Length ); + m_pData = malloc( src.m_nCompressedSize ); + memcpy( m_pData, src.m_pData, src.m_nCompressedSize ); } else { @@ -674,20 +695,27 @@ void CZipFile::ParseFromBuffer( void *buffer, int bufferlength ) ZIP_FileHeader zipFileHeader; buf.GetObjects( &zipFileHeader ); Assert( zipFileHeader.signature == PKID( 1, 2 ) ); - Assert( zipFileHeader.compressionMethod == 0 ); - - char tmpString[1024]; - buf.Get( tmpString, zipFileHeader.fileNameLength ); - tmpString[zipFileHeader.fileNameLength] = '\0'; + if ( zipFileHeader.compressionMethod != IZip::eCompressionType_None && + zipFileHeader.compressionMethod != IZip::eCompressionType_LZMA ) + { + Assert( false ); + Warning( "Opening ZIP file with unsupported compression type\n"); + } + + char tmpString[1024] = { 0 }; + buf.Get( tmpString, Min( (unsigned int)zipFileHeader.fileNameLength, (unsigned int)sizeof( tmpString ) ) ); Q_strlower( tmpString ); // can determine actual filepos, assuming a well formed zip newfiles[i].m_Name = tmpString; newfiles[i].filelen = zipFileHeader.compressedSize; + newfiles[i].uncompressedLen = zipFileHeader.uncompressedSize; + newfiles[i].crc32 = zipFileHeader.crc32; newfiles[i].filepos = zipFileHeader.relativeOffsetOfLocalHeader + - sizeof( ZIP_LocalFileHeader ) + - zipFileHeader.fileNameLength + - zipFileHeader.extraFieldLength; + sizeof( ZIP_LocalFileHeader ) + + zipFileHeader.fileNameLength + + zipFileHeader.extraFieldLength; + newfiles[i].compressionType = (IZip::eCompressionType)zipFileHeader.compressionMethod; int nextOffset; if ( m_bCompatibleFormat ) @@ -706,16 +734,19 @@ void CZipFile::ParseFromBuffer( void *buffer, int bufferlength ) { CZipEntry e; e.m_Name = newfiles[i].m_Name; - e.m_Length = newfiles[i].filelen; - + e.m_nCompressedSize = newfiles[i].filelen; + e.m_ZipCRC = newfiles[i].crc32; + e.m_nUncompressedSize = newfiles[i].uncompressedLen; + e.m_eCompressionType = newfiles[i].compressionType; + // Make sure length is reasonable - if ( e.m_Length > 0 ) + if ( e.m_nCompressedSize > 0 ) { - e.m_pData = malloc( e.m_Length ); + e.m_pData = malloc( e.m_nCompressedSize ); // Copy in data buf.SeekGet( CUtlBuffer::SEEK_HEAD, newfiles[i].filepos ); - buf.Get( e.m_pData, e.m_Length ); + buf.Get( e.m_pData, e.m_nCompressedSize ); } else { @@ -826,7 +857,9 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename ) ZIP_FileHeader zipFileHeader; zipDirBuff.GetObjects( &zipFileHeader ); - if ( zipFileHeader.signature != PKID( 1, 2 ) || zipFileHeader.compressionMethod != 0 ) + if ( zipFileHeader.signature != PKID( 1, 2 ) + || ( zipFileHeader.compressionMethod != IZip::eCompressionType_None + && zipFileHeader.compressionMethod != IZip::eCompressionType_LZMA ) ) { // bad contents #ifdef WIN32 @@ -836,7 +869,7 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename ) #endif return NULL; } - + char fileName[1024]; zipDirBuff.Get( fileName, zipFileHeader.fileNameLength ); fileName[zipFileHeader.fileNameLength] = '\0'; @@ -845,11 +878,15 @@ HANDLE CZipFile::ParseFromDisk( const char *pFilename ) // can determine actual filepos, assuming a well formed zip CZipEntry e; e.m_Name = fileName; - e.m_Length = zipFileHeader.compressedSize; + e.m_nCompressedSize = zipFileHeader.compressedSize; + e.m_nUncompressedSize = zipFileHeader.uncompressedSize; + e.m_ZipCRC = zipFileHeader.crc32; e.m_SourceDiskOffset = zipFileHeader.relativeOffsetOfLocalHeader + - sizeof( ZIP_LocalFileHeader ) + - zipFileHeader.fileNameLength + - zipFileHeader.extraFieldLength; + sizeof( ZIP_LocalFileHeader ) + + zipFileHeader.fileNameLength + + zipFileHeader.extraFieldLength; + e.m_eCompressionType = (IZip::eCompressionType)zipFileHeader.compressionMethod; + // Add to tree m_Files.Insert( e ); @@ -954,19 +991,85 @@ static void CopyTextData( char *pDst, const char *pSrc, int dstSize, int srcSize // *data - // length - //----------------------------------------------------------------------------- -void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ) +void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType ) { // Lower case only char name[512]; Q_strcpy( name, relativename ); Q_strlower( name ); - int dstLength = length; + int outLength = length; + int uncompressedLength = length; + void *outData = data; + CUtlBuffer textTransform; + CUtlBuffer compressionTransform; + if ( bTextMode ) { - dstLength = GetLengthOfBinStringAsText( ( const char * )data, length ); + int textLen = GetLengthOfBinStringAsText( ( const char * )outData, outLength ); + textTransform.EnsureCapacity( textLen ); + CopyTextData( (char *)textTransform.Base(), (char *)outData, textLen, outLength ); + + outData = (void *)textTransform.Base(); + outLength = textLen; + uncompressedLength = textLen; } - + + // uncompressed data final at this point (CRC is before compression) + CRC32_t zipCRC; + CRC32_Init( &zipCRC ); + CRC32_ProcessBuffer( &zipCRC, outData, outLength ); + CRC32_Final( &zipCRC ); + +#ifdef ZIP_SUPPORT_LZMA_ENCODE + if ( compressionType == IZip::eCompressionType_LZMA ) + { + unsigned int compressedSize = 0; + unsigned char *pCompressedOutput = LZMA_Compress( (unsigned char *)outData, outLength, &compressedSize ); + if ( !pCompressedOutput || compressedSize < sizeof( lzma_header_t ) ) + { + Warning( "ZipFile: LZMA compression failed\n" ); + return; + } + + // Fixup LZMA header for ZIP payload usage + // The output of LZMA_Compress uses lzma_header_t, defined alongside it. + // + // ZIP payload format, see ZIP spec 5.8.8: + // LZMA Version Information 2 bytes + // LZMA Properties Size 2 bytes + // LZMA Properties Data variable, defined by "LZMA Properties Size" + unsigned int nZIPHeader = 2 + 2 + sizeof( lzma_header_t().properties ); + unsigned int finalCompressedSize = compressedSize - sizeof( lzma_header_t ) + nZIPHeader; + compressionTransform.EnsureCapacity( finalCompressedSize ); + + // LZMA version + compressionTransform.PutUnsignedChar( LZMA_SDK_VERSION_MAJOR ); + compressionTransform.PutUnsignedChar( LZMA_SDK_VERSION_MINOR ); + // properties size + uint16 nSwappedPropertiesSize = LittleWord( sizeof( lzma_header_t().properties ) ); + compressionTransform.Put( &nSwappedPropertiesSize, sizeof( nSwappedPropertiesSize ) ); + // properties + compressionTransform.Put( &(((lzma_header_t *)pCompressedOutput)->properties), sizeof( lzma_header_t().properties ) ); + // payload + compressionTransform.Put( pCompressedOutput + sizeof( lzma_header_t ), compressedSize - sizeof( lzma_header_t ) ); + + // Free original + free( pCompressedOutput ); + pCompressedOutput = NULL; + + outData = (void *)compressionTransform.Base(); + outLength = finalCompressedSize; + // (Not updating uncompressedLength) + } + else +#endif + /* else from ifdef */ if ( compressionType != IZip::eCompressionType_None ) + { + Error( "Calling AddBufferToZip with unknown compression type\n" ); + return; + } + // See if entry is in list already CZipEntry e; e.m_Name = name; @@ -981,23 +1084,17 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, free( update->m_pData ); } - if ( bTextMode ) - { - update->m_pData = malloc( dstLength ); - CopyTextData( ( char * )update->m_pData, ( char * )data, dstLength, length ); - update->m_Length = dstLength; - } - else - { - update->m_pData = malloc( length ); - memcpy( update->m_pData, data, length ); - update->m_Length = length; - } + update->m_eCompressionType = compressionType; + update->m_pData = malloc( outLength ); + memcpy( update->m_pData, outData, outLength ); + update->m_nCompressedSize = outLength; + update->m_nUncompressedSize = uncompressedLength; + update->m_ZipCRC = zipCRC; if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) { update->m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile ); - CWin32File::FileWrite( m_hDiskCacheWriteFile, update->m_pData, update->m_Length ); + CWin32File::FileWrite( m_hDiskCacheWriteFile, update->m_pData, update->m_nCompressedSize ); free( update->m_pData ); update->m_pData = NULL; } @@ -1005,24 +1102,19 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, else { // Create a new entry - e.m_Length = dstLength; - if ( dstLength > 0 ) + e.m_nCompressedSize = outLength; + e.m_nUncompressedSize = uncompressedLength; + e.m_eCompressionType = compressionType; + e.m_ZipCRC = zipCRC; + if ( outLength > 0 ) { - if ( bTextMode ) - { - e.m_pData = malloc( dstLength ); - CopyTextData( (char *)e.m_pData, ( char * )data, dstLength, length ); - } - else - { - e.m_pData = malloc( length ); - memcpy( e.m_pData, data, length ); - } - + e.m_pData = malloc( outLength ); + memcpy( e.m_pData, outData, outLength ); + if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) { e.m_DiskCacheOffset = CWin32File::FileTell( m_hDiskCacheWriteFile ); - CWin32File::FileWrite( m_hDiskCacheWriteFile, e.m_pData, e.m_Length ); + CWin32File::FileWrite( m_hDiskCacheWriteFile, e.m_pData, e.m_nCompressedSize ); free( e.m_pData ); e.m_pData = NULL; } @@ -1042,38 +1134,11 @@ void CZipFile::AddBufferToZip( const char *relativename, void *data, int length, //----------------------------------------------------------------------------- bool CZipFile::ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) { - // Lower case only - char pName[512]; - Q_strncpy( pName, pRelativeName, 512 ); - Q_strlower( pName ); - - // See if entry is in list already - CZipEntry e; - e.m_Name = pName; - int nIndex = m_Files.Find( e ); - if ( nIndex == m_Files.InvalidIndex() ) - { - // not found - return false; - } - - CZipEntry *pEntry = &m_Files[ nIndex ]; - if ( bTextMode ) - { - buf.SetBufferType( true, false ); - ReadTextData( (char*)pEntry->m_pData, pEntry->m_Length, buf ); - } - else - { - buf.SetBufferType( false, false ); - buf.Put( pEntry->m_pData, pEntry->m_Length ); - } - - return true; + return ReadFileFromZip( 0, pRelativeName, bTextMode, buf ); } //----------------------------------------------------------------------------- -// Reads a file from the zip +// Reads a file from the zip. Requires the zip file handle if this zip was loaded via ParseFromDisk //----------------------------------------------------------------------------- bool CZipFile::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) { @@ -1094,27 +1159,63 @@ bool CZipFile::ReadFileFromZip( HANDLE hZipFile, const char *pRelativeName, bool CZipEntry *pEntry = &m_Files[nIndex]; - void *pData = malloc( pEntry->m_Length ); - CWin32File::FileSeek( hZipFile, pEntry->m_SourceDiskOffset, FILE_BEGIN ); - if ( !CWin32File::FileRead( hZipFile, pData, pEntry->m_Length ) ) + void *pData = pEntry->m_pData; + CUtlBuffer readBuffer; + if ( !pData && hZipFile ) { - free( pData ); - return false; + readBuffer.EnsureCapacity( pEntry->m_nCompressedSize ); + CWin32File::FileSeek( hZipFile, pEntry->m_SourceDiskOffset, FILE_BEGIN ); + if ( !CWin32File::FileRead( hZipFile, readBuffer.Base(), pEntry->m_nCompressedSize ) ) + { + return false; + } + + pData = readBuffer.Base(); + } + + CUtlBuffer decompressTransform; + if ( pEntry->m_eCompressionType != IZip::eCompressionType_None ) + { + if ( pEntry->m_eCompressionType == IZip::eCompressionType_LZMA ) + { + decompressTransform.EnsureCapacity( pEntry->m_nUncompressedSize ); + + CLZMAStream decompressStream; + decompressStream.InitZIPHeader( pEntry->m_nCompressedSize, pEntry->m_nUncompressedSize ); + + unsigned int nCompressedBytesRead = 0; + unsigned int nOutputBytesWritten = 0; + bool bSuccess = decompressStream.Read( (unsigned char *)pData, pEntry->m_nCompressedSize, + (unsigned char *)decompressTransform.Base(), decompressTransform.Size(), + nCompressedBytesRead, nOutputBytesWritten ); + if ( !bSuccess || + (int)nCompressedBytesRead != pEntry->m_nCompressedSize || + (int)nOutputBytesWritten != pEntry->m_nUncompressedSize ) + { + Error( "Zip: Failed decompressing LZMA data\n" ); + return false; + } + + pData = decompressTransform.Base(); + } + else + { + Error( "Unsupported compression type in Zip file: %u\n", pEntry->m_eCompressionType ); + return false; + } } if ( bTextMode ) { buf.SetBufferType( true, false ); - ReadTextData( (const char *)pData, pEntry->m_Length, buf ); + ReadTextData( (const char *)pData, pEntry->m_nUncompressedSize, buf ); } else { buf.SetBufferType( false, false ); - buf.Put( pData, pEntry->m_Length ); + buf.Put( pData, pEntry->m_nUncompressedSize ); } - free( pData ); - return true; } @@ -1142,7 +1243,7 @@ bool CZipFile::FileExistsInZip( const char *pRelativeName ) //----------------------------------------------------------------------------- // Purpose: Adds a new file to the zip. //----------------------------------------------------------------------------- -void CZipFile::AddFileToZip( const char *relativename, const char *fullpath ) +void CZipFile::AddFileToZip( const char *relativename, const char *fullpath, IZip::eCompressionType compressionType ) { FILE *temp = fopen( fullpath, "rb" ); if ( !temp ) @@ -1159,8 +1260,8 @@ void CZipFile::AddFileToZip( const char *relativename, const char *fullpath ) fclose( temp ); // Now add as a buffer - AddBufferToZip( relativename, buf, size, false ); - + AddBufferToZip( relativename, buf, size, false, compressionType ); + free( buf ); } @@ -1252,8 +1353,8 @@ unsigned int CZipFile::CalculateSize( void ) for ( int i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) { CZipEntry *e = &m_Files[ i ]; - - if ( e->m_Length == 0 ) + + if ( e->m_nCompressedSize == 0 ) continue; // local file header @@ -1268,7 +1369,7 @@ unsigned int CZipFile::CalculateSize( void ) { // round up to next boundary unsigned int nextBoundary = ( size + m_AlignmentSize ) & ~( m_AlignmentSize - 1 ); - + // the directory header also duplicates the padding dirHeaders += nextBoundary - size; @@ -1276,7 +1377,7 @@ unsigned int CZipFile::CalculateSize( void ) } // data size - size += e->m_Length; + size += e->m_nCompressedSize; } size += dirHeaders; @@ -1322,7 +1423,7 @@ int CZipFile::GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileS CZipEntry *e = &m_Files[id]; Q_strncpy( pBuffer, e->m_Name.String(), bufferSize ); - fileSize = e->m_Length; + fileSize = e->m_nUncompressedSize; return id; } @@ -1373,6 +1474,9 @@ void CZipFile::SaveDirectory( IWriteStream& stream ) #endif } + // Might be writing a zip into a larger stream + unsigned int zipOffsetInStream = stream.Tell(); + int i; for ( i = m_Files.FirstInorder(); i != m_Files.InvalidIndex(); i = m_Files.NextInorder( i ) ) { @@ -1380,47 +1484,50 @@ void CZipFile::SaveDirectory( IWriteStream& stream ) Assert( e ); // Fix up the offset - e->m_ZipOffset = stream.Tell(); + e->m_ZipOffset = stream.Tell() - zipOffsetInStream; - if ( e->m_Length > 0 && ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) ) - { + if ( e->m_nCompressedSize > 0 && ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) ) + { // get the data back from the write cache - e->m_pData = malloc( e->m_Length ); + e->m_pData = malloc( e->m_nCompressedSize ); if ( e->m_pData ) { CWin32File::FileSeek( m_hDiskCacheWriteFile, e->m_DiskCacheOffset, FILE_BEGIN ); - CWin32File::FileRead( m_hDiskCacheWriteFile, e->m_pData, e->m_Length ); + CWin32File::FileRead( m_hDiskCacheWriteFile, e->m_pData, e->m_nCompressedSize ); } } - if ( e->m_Length > 0 && e->m_pData != NULL ) + if ( e->m_nCompressedSize > 0 && e->m_pData != NULL ) { ZIP_LocalFileHeader hdr = { 0 }; hdr.signature = PKID( 3, 4 ); - hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes. + hdr.versionNeededToExtract = 10; // No special features or even compression here, set to 1.0 +#ifdef ZIP_SUPPORT_LZMA_ENCODE + if ( e->m_eCompressionType == IZip::eCompressionType_LZMA ) + { + // Per ZIP spec 5.8.8 + hdr.versionNeededToExtract = 63; + } +#endif hdr.flags = 0; - hdr.compressionMethod = 0; // NO COMPRESSION! + hdr.compressionMethod = e->m_eCompressionType; hdr.lastModifiedTime = 0; hdr.lastModifiedDate = 0; - - CRC32_Init( &e->m_ZipCRC ); - CRC32_ProcessBuffer( &e->m_ZipCRC, e->m_pData, e->m_Length ); - CRC32_Final( &e->m_ZipCRC ); hdr.crc32 = e->m_ZipCRC; - + const char *pFilename = e->m_Name.String(); - hdr.compressedSize = e->m_Length; - hdr.uncompressedSize = e->m_Length; + hdr.compressedSize = e->m_nCompressedSize; + hdr.uncompressedSize = e->m_nUncompressedSize; hdr.fileNameLength = strlen( pFilename ); hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset ); int extraFieldLength = hdr.extraFieldLength; - + // Swap header in place m_Swap.SwapFieldsToTargetEndian( &hdr ); stream.Put( &hdr, sizeof( hdr ) ); stream.Put( pFilename, strlen( pFilename ) ); stream.Put( pPaddingBuffer, extraFieldLength ); - stream.Put( e->m_pData, e->m_Length ); + stream.Put( e->m_pData, e->m_nCompressedSize ); if ( m_hDiskCacheWriteFile != INVALID_HANDLE_VALUE ) { @@ -1437,7 +1544,7 @@ void CZipFile::SaveDirectory( IWriteStream& stream ) CWin32File::FileSeek( m_hDiskCacheWriteFile, 0, FILE_END ); } - unsigned int centralDirStart = stream.Tell(); + unsigned int centralDirStart = stream.Tell() - zipOffsetInStream; if ( m_AlignmentSize ) { // align the central directory starting position @@ -1455,21 +1562,28 @@ void CZipFile::SaveDirectory( IWriteStream& stream ) { CZipEntry *e = &m_Files[i]; Assert( e ); - - if ( e->m_Length > 0 && e->m_pData != NULL ) + + if ( e->m_nCompressedSize > 0 && e->m_pData != NULL ) { ZIP_FileHeader hdr = { 0 }; hdr.signature = PKID( 1, 2 ); hdr.versionMadeBy = 20; // This is the version that the winzip that I have writes. - hdr.versionNeededToExtract = 10; // This is the version that the winzip that I have writes. + hdr.versionNeededToExtract = 10; // No special features or even compression here, set to 1.0 +#ifdef ZIP_SUPPORT_LZMA_ENCODE + if ( e->m_eCompressionType == IZip::eCompressionType_LZMA ) + { + // Per ZIP spec 5.8.8 + hdr.versionNeededToExtract = 63; + } +#endif hdr.flags = 0; - hdr.compressionMethod = 0; + hdr.compressionMethod = e->m_eCompressionType; hdr.lastModifiedTime = 0; hdr.lastModifiedDate = 0; hdr.crc32 = e->m_ZipCRC; - hdr.compressedSize = e->m_Length; - hdr.uncompressedSize = e->m_Length; + hdr.compressedSize = e->m_nCompressedSize; + hdr.uncompressedSize = e->m_nUncompressedSize; hdr.fileNameLength = strlen( e->m_Name.String() ); hdr.extraFieldLength = CalculatePadding( hdr.fileNameLength, e->m_ZipOffset ); hdr.fileCommentLength = 0; @@ -1498,7 +1612,7 @@ void CZipFile::SaveDirectory( IWriteStream& stream ) } } - unsigned int centralDirEnd = stream.Tell(); + unsigned int centralDirEnd = stream.Tell() - zipOffsetInStream; if ( m_AlignmentSize ) { // align the central directory starting position @@ -1541,56 +1655,57 @@ public: CZip( const char *pDiskCacheWritePath, bool bSortByName ); virtual ~CZip(); - virtual void Reset(); + virtual void Reset() OVERRIDE; // Add a single file to a zip - maintains the zip's previous alignment state - virtual void AddFileToZip( const char *relativename, const char *fullpath ); + virtual void AddFileToZip( const char *relativename, const char *fullpath, eCompressionType compressionType ) OVERRIDE; // Whether a file is contained in a zip - maintains alignment - virtual bool FileExistsInZip( const char *pRelativeName ); + virtual bool FileExistsInZip( const char *pRelativeName ) OVERRIDE; // Reads a file from the zip - maintains alignement - virtual bool ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ); - virtual bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf ); + virtual bool ReadFileFromZip( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) OVERRIDE; + virtual bool ReadFileFromZip( HANDLE hZipFile, const char *relativename, bool bTextMode, CUtlBuffer &buf ) OVERRIDE; // Removes a single file from the zip - maintains alignment - virtual void RemoveFileFromZip( const char *relativename ); + virtual void RemoveFileFromZip( const char *relativename ) OVERRIDE; // Gets next filename in zip, for walking the directory - maintains alignment - virtual int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ); + virtual int GetNextFilename( int id, char *pBuffer, int bufferSize, int &fileSize ) OVERRIDE; // Prints the zip's contents - maintains alignment - virtual void PrintDirectory( void ); + virtual void PrintDirectory( void ) OVERRIDE; // Estimate the size of the Zip (including header, padding, etc.) - virtual unsigned int EstimateSize( void ); + virtual unsigned int EstimateSize( void ) OVERRIDE; // Add buffer to zip as a file with given name - uses current alignment size, default 0 (no alignment) - virtual void AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ); + virtual void AddBufferToZip( const char *relativename, void *data, int length, + bool bTextMode, eCompressionType compressionType ) OVERRIDE; - // Writes out zip file to a buffer - uses current alignment size + // Writes out zip file to a buffer - uses current alignment size // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToBuffer( CUtlBuffer& outbuf ); + virtual void SaveToBuffer( CUtlBuffer& outbuf ) OVERRIDE; - // Writes out zip file to a filestream - uses current alignment size + // Writes out zip file to a filestream - uses current alignment size // (set by file's previous alignment, or a call to ForceAlignment) - virtual void SaveToDisk( FILE *fout ); - virtual void SaveToDisk( HANDLE hOutFile ); + virtual void SaveToDisk( FILE *fout ) OVERRIDE; + virtual void SaveToDisk( HANDLE hOutFile ) OVERRIDE; - // Reads a zip file from a buffer into memory - sets current alignment size to + // Reads a zip file from a buffer into memory - sets current alignment size to // the file's alignment size, unless overridden by a ForceAlignment call) - virtual void ParseFromBuffer( void *buffer, int bufferlength ); - virtual HANDLE ParseFromDisk( const char *pFilename ); + virtual void ParseFromBuffer( void *buffer, int bufferlength ) OVERRIDE; + virtual HANDLE ParseFromDisk( const char *pFilename ) OVERRIDE; // Forces a specific alignment size for all subsequent file operations, overriding files' previous alignment size. // Return to using files' individual alignment sizes by passing FALSE. - virtual void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ); + virtual void ForceAlignment( bool aligned, bool bCompatibleFormat, unsigned int alignmentSize ) OVERRIDE; // Sets the endianess of the zip - virtual void SetBigEndian( bool bigEndian ); - virtual void ActivateByteSwapping( bool bActivate ); + virtual void SetBigEndian( bool bigEndian ) OVERRIDE; + virtual void ActivateByteSwapping( bool bActivate ) OVERRIDE; - virtual unsigned int GetAlignment(); + virtual unsigned int GetAlignment() OVERRIDE; private: CZipFile m_ZipFile; @@ -1599,11 +1714,11 @@ private: static CUtlLinkedList< CZip* > g_ZipUtils; IZip *IZip::CreateZip( const char *pDiskCacheWritePath, bool bSortByName ) -{ +{ CZip *pZip = new CZip( pDiskCacheWritePath, bSortByName ); g_ZipUtils.AddToTail( pZip ); - return pZip; + return pZip; } void IZip::ReleaseZip( IZip *pZip ) @@ -1632,9 +1747,9 @@ void CZip::ActivateByteSwapping( bool bActivate ) m_ZipFile.ActivateByteSwapping( bActivate ); } -void CZip::AddFileToZip( const char *relativename, const char *fullpath ) +void CZip::AddFileToZip( const char *relativename, const char *fullpath, eCompressionType compressionType ) { - m_ZipFile.AddFileToZip( relativename, fullpath ); + m_ZipFile.AddFileToZip( relativename, fullpath, compressionType ); } bool CZip::FileExistsInZip( const char *pRelativeName ) @@ -1678,9 +1793,9 @@ unsigned int CZip::EstimateSize( void ) } // Add buffer to zip as a file with given name -void CZip::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode ) +void CZip::AddBufferToZip( const char *relativename, void *data, int length, bool bTextMode, eCompressionType compressionType ) { - m_ZipFile.AddBufferToZip( relativename, data, length, bTextMode ); + m_ZipFile.AddBufferToZip( relativename, data, length, bTextMode, compressionType ); } void CZip::SaveToBuffer( CUtlBuffer& outbuf ) diff --git a/mp/src/public/zip_utils.h b/mp/src/public/zip_utils.h index be1cc8dd..2ac20052 100644 --- a/mp/src/public/zip_utils.h +++ b/mp/src/public/zip_utils.h @@ -1,6 +1,6 @@ //========= Copyright Valve Corporation, All rights reserved. ============// // -// Purpose: +// Purpose: // //=============================================================================// @@ -18,15 +18,22 @@ class CUtlBuffer; abstract_class IZip { public: + enum eCompressionType + { + // Type of compression used for this file in the zip + eCompressionType_Unknown = -1, + eCompressionType_None = 0, + eCompressionType_LZMA = 14 + }; virtual void Reset() = 0; - // Add a single file to a zip - maintains the zip's previous alignment state - virtual void AddFileToZip ( const char *relativename, const char *fullpath ) = 0; + // Add a single file to a zip - maintains the zip's previous alignment state. + virtual void AddFileToZip ( const char *relativename, const char *fullpath, eCompressionType compressionType = eCompressionType_None ) = 0; // Whether a file is contained in a zip - maintains alignment virtual bool FileExistsInZip ( const char *pRelativeName ) = 0; - // Reads a file from the zip - maintains alignement + // Reads a file from the zip - maintains alignement. virtual bool ReadFileFromZip ( const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) = 0; virtual bool ReadFileFromZip ( HANDLE hFile, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ) = 0; @@ -43,18 +50,18 @@ public: virtual unsigned int EstimateSize ( void ) = 0; // Add buffer to zip as a file with given name - uses current alignment size, default 0 (no alignment) - virtual void AddBufferToZip ( const char *relativename, void *data, int length, bool bTextMode ) = 0; + virtual void AddBufferToZip ( const char *relativename, void *data, int length, bool bTextMode, eCompressionType compressionType = eCompressionType_None ) = 0; - // Writes out zip file to a buffer - uses current alignment size + // Writes out zip file to a buffer - uses current alignment size // (set by file's previous alignment, or a call to ForceAlignment) virtual void SaveToBuffer ( CUtlBuffer& outbuf ) = 0; - // Writes out zip file to a filestream - uses current alignment size + // Writes out zip file to a filestream - uses current alignment size // (set by file's previous alignment, or a call to ForceAlignment) virtual void SaveToDisk ( FILE *fout ) = 0; virtual void SaveToDisk ( HANDLE hFileOut ) = 0; - - // Reads a zip file from a buffer into memory - sets current alignment size to + + // Reads a zip file from a buffer into memory - sets current alignment size to // the file's alignment size, unless overridden by a ForceAlignment call) virtual void ParseFromBuffer ( void *buffer, int bufferlength ) = 0; diff --git a/mp/src/tier1/KeyValues.cpp b/mp/src/tier1/KeyValues.cpp index c72172ca..ad4af096 100644 --- a/mp/src/tier1/KeyValues.cpp +++ b/mp/src/tier1/KeyValues.cpp @@ -18,14 +18,16 @@ #include #include "filesystem.h" #include +#include "tier0/icommandline.h" #include #include #include "tier0/dbg.h" #include "tier0/mem.h" -#include "utlvector.h" #include "utlbuffer.h" #include "utlhash.h" +#include "utlvector.h" +#include "utlqueue.h" #include "UtlSortVector.h" #include "convar.h" @@ -84,16 +86,19 @@ public: { Assert( stackLevel >= 0 ); Assert( stackLevel < m_errorIndex ); - m_errorStack[stackLevel] = symName; + if ( stackLevel < MAX_ERROR_STACK ) + m_errorStack[stackLevel] = symName; } // Hit an error, report it and the parsing stack for context void ReportError( const char *pError ) { + bool bSpewCR = false; + Warning( "KeyValues Error: %s in file %s\n", pError, m_pFilename ); for ( int i = 0; i < m_maxErrorIndex; i++ ) { - if ( m_errorStack[i] != INVALID_KEY_SYMBOL ) + if ( i < MAX_ERROR_STACK && m_errorStack[i] != INVALID_KEY_SYMBOL ) { if ( i < m_errorIndex ) { @@ -103,9 +108,13 @@ public: { Warning( "(*%s*), ", KeyValues::CallGetStringForSymbol(m_errorStack[i]) ); } + + bSpewCR = true; } } - Warning( "\n" ); + + if ( bSpewCR ) + Warning( "\n" ); } private: @@ -137,6 +146,10 @@ public: { g_KeyValuesErrorStack.Reset( m_stackLevel, symName ); } + int GetStackLevel() const + { + return m_stackLevel; + } private: void Init( int symName ) { @@ -630,15 +643,62 @@ void KeyValues::UsesConditionals(bool state) //----------------------------------------------------------------------------- // Purpose: Load keyValues from disk //----------------------------------------------------------------------------- -bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID ) +bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID, bool refreshCache ) { Assert(filesystem); #ifdef WIN32 Assert( IsX360() || ( IsPC() && _heapchk() == _HEAPOK ) ); #endif + +#ifdef STAGING_ONLY + static bool s_bCacheEnabled = !!CommandLine()->FindParm( "-enable_keyvalues_cache" ); + const bool bUseCache = s_bCacheEnabled && ( s_pfGetSymbolForString == KeyValues::GetSymbolForStringClassic ); +#else + /* + People are cheating with the keyvalue cache enabled by doing the below, so disable it. + + For example if one is to allow a blue demoman texture on sv_pure they + change it to this, "$basetexture" "temp/demoman_blue". Remember to move the + demoman texture to the temp folder in the materials folder. It will likely + not be there so make a new folder for it. Once the directory in the + demoman_blue vmt is changed to the temp folder and the vtf texture is in + the temp folder itself you are finally done. + + I packed my mods into a vpk but I don't think it's required. Once in game + you must create a server via the create server button and select the map + that will load the custom texture before you join a valve server. I suggest + you only do this with player textures and such as they are always loaded. + After you load the map you join the valve server and the textures should + appear and work on valve servers. + + This can be done on any sv_pure 1 server but it depends on what is type of + files are allowed. All valve servers allow temp files so that is the + example I used here." + + So all vmt's files can bypass sv_pure 1. And I believe this mod is mostly + made of vmt files, so valve's sv_pure 1 bull is pretty redundant. + */ + const bool bUseCache = false; +#endif + + // If pathID is null, we cannot cache the result because that has a weird iterate-through-a-bunch-of-locations behavior. + const bool bUseCacheForRead = bUseCache && !refreshCache && pathID != NULL; + const bool bUseCacheForWrite = bUseCache && pathID != NULL; + + COM_TimestampedLog( "KeyValues::LoadFromFile(%s%s%s): Begin", pathID ? pathID : "", pathID && resourceName ? "/" : "", resourceName ? resourceName : "" ); + + // Keep a cache of keyvalues, try to load it here. + if ( bUseCacheForRead && KeyValuesSystem()->LoadFileKeyValuesFromCache( this, resourceName, pathID, filesystem ) ) { + COM_TimestampedLog( "KeyValues::LoadFromFile(%s%s%s): End / CacheHit", pathID ? pathID : "", pathID && resourceName ? "/" : "", resourceName ? resourceName : "" ); + return true; + } + FileHandle_t f = filesystem->Open(resourceName, "rb", pathID); if ( !f ) + { + COM_TimestampedLog("KeyValues::LoadFromFile(%s%s%s): End / FileNotFound", pathID ? pathID : "", pathID && resourceName ? "/" : "", resourceName ? resourceName : ""); return false; + } s_LastFileLoadingFrom = (char*)resourceName; @@ -660,28 +720,41 @@ bool KeyValues::LoadFromFile( IBaseFileSystem *filesystem, const char *resourceN buffer[fileSize+1] = 0; // double NULL terminating in case this is a unicode file bRetOK = LoadFromBuffer( resourceName, buffer, filesystem ); } + + // The cache relies on the KeyValuesSystem string table, which will only be valid if we're + // using classic mode. + if ( bUseCacheForWrite && bRetOK ) + { + KeyValuesSystem()->AddFileKeyValuesToCache( this, resourceName, pathID ); + } - ((IFileSystem *)filesystem)->FreeOptimalReadBuffer( buffer ); + ( (IFileSystem *)filesystem )->FreeOptimalReadBuffer( buffer ); + + COM_TimestampedLog("KeyValues::LoadFromFile(%s%s%s): End / Success", pathID ? pathID : "", pathID && resourceName ? "/" : "", resourceName ? resourceName : ""); return bRetOK; } //----------------------------------------------------------------------------- // Purpose: Save the keyvalues to disk -// Creates the path to the file if it doesn't exist +// Creates the path to the file if it doesn't exist //----------------------------------------------------------------------------- -bool KeyValues::SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID, bool sortKeys /*= false*/, bool bAllowEmptyString /*= false*/ ) +bool KeyValues::SaveToFile( IBaseFileSystem *filesystem, const char *resourceName, const char *pathID, bool sortKeys /*= false*/, bool bAllowEmptyString /*= false*/, bool bCacheResult /*= false*/ ) { // create a write file FileHandle_t f = filesystem->Open(resourceName, "wb", pathID); if ( f == FILESYSTEM_INVALID_HANDLE ) { - DevMsg(1, "KeyValues::SaveToFile: couldn't open file \"%s\" in path \"%s\".\n", + DevMsg(1, "KeyValues::SaveToFile: couldn't open file \"%s\" in path \"%s\".\n", resourceName?resourceName:"NULL", pathID?pathID:"NULL" ); return false; } + KeyValuesSystem()->InvalidateCacheForFile( resourceName, pathID ); + if ( bCacheResult ) { + KeyValuesSystem()->AddFileKeyValuesToCache( this, resourceName, pathID ); + } RecursiveSaveToFile(filesystem, f, NULL, 0, sortKeys, bAllowEmptyString ); filesystem->Close(f); @@ -1671,115 +1744,138 @@ void KeyValues::SetPtr( const char *keyName, void *value ) } } -void KeyValues::RecursiveCopyKeyValues( KeyValues& src ) +//----------------------------------------------------------------------------- +// Purpose: Copies the tree from the other KeyValues into this one, recursively +// beginning with the root specified by rootSrc. +//----------------------------------------------------------------------------- +void KeyValues::CopyKeyValuesFromRecursive( const KeyValues& rootSrc ) { - // garymcthack - need to check this code for possible buffer overruns. - - m_iKeyName = src.GetNameSymbol(); + // This code used to be recursive, which was more elegant. Unfortunately, it also blew the stack for large + // KeyValues. So now we have the iterative version which is uglier but doesn't blow the stack. + // This uses breadth-first traversal. - if( !src.m_pSub ) + struct CopyStruct { - m_iDataType = src.m_iDataType; - char buf[256]; - switch( src.m_iDataType ) + KeyValues* dst; + const KeyValues* src; + }; + + char tmp[256]; + KeyValues* localDst = NULL; + + CUtlQueue nodeQ; + nodeQ.Insert({ this, &rootSrc }); + + while ( nodeQ.Count() > 0 ) + { + CopyStruct cs = nodeQ.RemoveAtHead(); + + // Process all the siblings of the current node. If anyone has a child, add it to the queue. + while (cs.src) { - case TYPE_NONE: - break; - case TYPE_STRING: - if( src.m_sValue ) - { - int len = Q_strlen(src.m_sValue) + 1; - m_sValue = new char[len]; - Q_strncpy( m_sValue, src.m_sValue, len ); - } - break; - case TYPE_INT: - { - m_iValue = src.m_iValue; - Q_snprintf( buf,sizeof(buf), "%d", m_iValue ); - int len = Q_strlen(buf) + 1; - m_sValue = new char[len]; - Q_strncpy( m_sValue, buf, len ); - } - break; - case TYPE_FLOAT: - { - m_flValue = src.m_flValue; - Q_snprintf( buf,sizeof(buf), "%f", m_flValue ); - int len = Q_strlen(buf) + 1; - m_sValue = new char[len]; - Q_strncpy( m_sValue, buf, len ); - } - break; - case TYPE_PTR: - { - m_pValue = src.m_pValue; - } - break; - case TYPE_UINT64: - { - m_sValue = new char[sizeof(uint64)]; - Q_memcpy( m_sValue, src.m_sValue, sizeof(uint64) ); - } - break; - case TYPE_COLOR: - { - m_Color[0] = src.m_Color[0]; - m_Color[1] = src.m_Color[1]; - m_Color[2] = src.m_Color[2]; - m_Color[3] = src.m_Color[3]; - } - break; - - default: - { - // do nothing . .what the heck is this? - Assert( 0 ); - } - break; - } + Assert( (cs.src != NULL) == (cs.dst != NULL) ); - } -#if 0 - KeyValues *pDst = this; - for ( KeyValues *pSrc = src.m_pSub; pSrc; pSrc = pSrc->m_pPeer ) - { - if ( pSrc->m_pSub ) - { - pDst->m_pSub = new KeyValues( pSrc->m_pSub->getName() ); - pDst->m_pSub->RecursiveCopyKeyValues( *pSrc->m_pSub ); - } - else - { - // copy non-empty keys - if ( pSrc->m_sValue && *(pSrc->m_sValue) ) - { - pDst->m_pPeer = new KeyValues( + // Copy the node contents + cs.dst->CopyKeyValue( *cs.src, sizeof(tmp), tmp ); + + // Add children to the queue to process later. + if (cs.src->m_pSub) { + cs.dst->m_pSub = localDst = new KeyValues( NULL ); + nodeQ.Insert({ localDst, cs.src->m_pSub }); } + + // Process siblings until we hit the end of the line. + if (cs.src->m_pPeer) { + cs.dst->m_pPeer = new KeyValues( NULL ); + } + else { + cs.dst->m_pPeer = NULL; + } + + // Advance to the next peer. + cs.src = cs.src->m_pPeer; + cs.dst = cs.dst->m_pPeer; } } -#endif - - // Handle the immediate child - if( src.m_pSub ) - { - m_pSub = new KeyValues( NULL ); - m_pSub->RecursiveCopyKeyValues( *src.m_pSub ); - } - - // Handle the immediate peer - if( src.m_pPeer ) - { - m_pPeer = new KeyValues( NULL ); - m_pPeer->RecursiveCopyKeyValues( *src.m_pPeer ); - } } -KeyValues& KeyValues::operator=( KeyValues& src ) +//----------------------------------------------------------------------------- +// Purpose: Copies a single KeyValue from src to this, using the provided temporary +// buffer if the keytype requires it. Does NOT recurse. +//----------------------------------------------------------------------------- +void KeyValues::CopyKeyValue( const KeyValues& src, size_t tmpBufferSizeB, char* tmpBuffer ) +{ + m_iKeyName = src.GetNameSymbol(); + + if ( src.m_pSub ) + return; + + m_iDataType = src.m_iDataType; + + switch( src.m_iDataType ) + { + case TYPE_NONE: + break; + case TYPE_STRING: + if( src.m_sValue ) + { + int len = Q_strlen(src.m_sValue) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, src.m_sValue, len ); + } + break; + case TYPE_INT: + { + m_iValue = src.m_iValue; + Q_snprintf( tmpBuffer, tmpBufferSizeB, "%d", m_iValue ); + int len = Q_strlen(tmpBuffer) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, tmpBuffer, len ); + } + break; + case TYPE_FLOAT: + { + m_flValue = src.m_flValue; + Q_snprintf( tmpBuffer, tmpBufferSizeB, "%f", m_flValue ); + int len = Q_strlen(tmpBuffer) + 1; + m_sValue = new char[len]; + Q_strncpy( m_sValue, tmpBuffer, len ); + } + break; + case TYPE_PTR: + { + m_pValue = src.m_pValue; + } + break; + case TYPE_UINT64: + { + m_sValue = new char[sizeof(uint64)]; + Q_memcpy( m_sValue, src.m_sValue, sizeof(uint64) ); + } + break; + case TYPE_COLOR: + { + m_Color[0] = src.m_Color[0]; + m_Color[1] = src.m_Color[1]; + m_Color[2] = src.m_Color[2]; + m_Color[3] = src.m_Color[3]; + } + break; + + default: + { + // do nothing . .what the heck is this? + Assert( 0 ); + } + break; + } +} + +KeyValues& KeyValues::operator=( const KeyValues& src ) { RemoveEverything(); Init(); // reset all values - RecursiveCopyKeyValues( src ); + CopyKeyValuesFromRecursive( src ); return *this; } @@ -1878,6 +1974,25 @@ KeyValues *KeyValues::MakeCopy( void ) const return newKeyValue; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +KeyValues *KeyValues::MakeCopy( bool copySiblings ) const +{ + KeyValues* rootDest = MakeCopy(); + if ( !copySiblings ) + return rootDest; + + const KeyValues* curSrc = GetNextKey(); + KeyValues* curDest = rootDest; + while (curSrc) { + curDest->SetNextKey( curSrc->MakeCopy() ); + curDest = curDest->GetNextKey(); + curSrc = curSrc->GetNextKey(); + } + + return rootDest; +} //----------------------------------------------------------------------------- // Purpose: Check if a keyName has no value assigned to it. @@ -2243,6 +2358,8 @@ bool KeyValues::LoadFromBuffer( char const *resourceName, const char *pBuffer, I if ( !pBuffer ) return true; + COM_TimestampedLog("KeyValues::LoadFromBuffer(%s%s%s): Begin", pPathID ? pPathID : "", pPathID && resourceName ? "/" : "", resourceName ? resourceName : ""); + int nLen = Q_strlen( pBuffer ); CUtlBuffer buf( pBuffer, nLen, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER ); @@ -2255,7 +2372,11 @@ bool KeyValues::LoadFromBuffer( char const *resourceName, const char *pBuffer, I buf.AssumeMemory( pUTF8Buf, nUTF8Len, nUTF8Len, CUtlBuffer::READ_ONLY | CUtlBuffer::TEXT_BUFFER ); } - return LoadFromBuffer( resourceName, buf, pFileSystem, pPathID ); + bool retVal = LoadFromBuffer( resourceName, buf, pFileSystem, pPathID ); + + COM_TimestampedLog("KeyValues::LoadFromBuffer(%s%s%s): End", pPathID ? pPathID : "", pPathID && resourceName ? "/" : "", resourceName ? resourceName : ""); + + return retVal; } //----------------------------------------------------------------------------- @@ -2266,6 +2387,12 @@ void KeyValues::RecursiveLoadFromBuffer( char const *resourceName, CUtlBuffer &b CKeyErrorContext errorReport(this); bool wasQuoted; bool wasConditional; + if ( errorReport.GetStackLevel() > 100 ) + { + g_KeyValuesErrorStack.ReportError( "RecursiveLoadFromBuffer: recursion overflow" ); + return; + } + // keep this out of the stack until a key is parsed CKeyErrorContext errorKey( INVALID_KEY_SYMBOL ); @@ -2570,7 +2697,7 @@ bool KeyValues::ReadAsBinary( CUtlBuffer &buffer, int nStackDepth ) { char token[KEYVALUES_TOKEN_SIZE]; - buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + buffer.GetString( token ); token[KEYVALUES_TOKEN_SIZE-1] = 0; dat->SetName( token ); } @@ -2586,7 +2713,7 @@ bool KeyValues::ReadAsBinary( CUtlBuffer &buffer, int nStackDepth ) case TYPE_STRING: { char token[KEYVALUES_TOKEN_SIZE]; - buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + buffer.GetString( token ); token[KEYVALUES_TOKEN_SIZE-1] = 0; int len = Q_strlen( token ); @@ -3039,4 +3166,4 @@ bool CKeyValuesDumpContextAsDevMsg::KvWriteText( char const *szText ) Msg( "%s", szText ); } return true; -} \ No newline at end of file +} diff --git a/mp/src/tier1/convar.cpp b/mp/src/tier1/convar.cpp index 956ad91d..772586f2 100644 --- a/mp/src/tier1/convar.cpp +++ b/mp/src/tier1/convar.cpp @@ -592,7 +592,7 @@ void ConCommand::Dispatch( const CCommand &command ) } // Command without callback!!! - AssertMsg( 0, ( "Encountered ConCommand '%s' without a callback!\n", GetName() ) ); + AssertMsg( 0, "Encountered ConCommand '%s' without a callback!\n", GetName() ); } @@ -777,10 +777,10 @@ void ConVar::InternalSetValue( const char *value ) Q_snprintf( tempVal,sizeof(tempVal), "%f", fNewValue ); val = tempVal; } - + // Redetermine value m_fValue = fNewValue; - m_nValue = ( int )( m_fValue ); + m_nValue = ( int )( fNewValue ); if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) ) { @@ -821,13 +821,17 @@ void ConVar::ChangeStringValue( const char *tempVal, float flOldValue ) *m_pszString = 0; } - // Invoke any necessary callback function - if ( m_fnChangeCallback ) + // If nothing has changed, don't do the callbacks. + if (V_strcmp(pszOldValue, m_pszString) != 0) { - m_fnChangeCallback( this, pszOldValue, flOldValue ); - } + // Invoke any necessary callback function + if ( m_fnChangeCallback ) + { + m_fnChangeCallback( this, pszOldValue, flOldValue ); + } - g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); + g_pCVar->CallGlobalChangeCallbacks( this, pszOldValue, flOldValue ); + } stackfree( pszOldValue ); } diff --git a/mp/src/tier1/ilocalize.cpp b/mp/src/tier1/ilocalize.cpp index d95bbf29..66673e64 100644 --- a/mp/src/tier1/ilocalize.cpp +++ b/mp/src/tier1/ilocalize.cpp @@ -17,7 +17,8 @@ int ILocalize::ConvertANSIToUnicode(const char *ansi, wchar_t *unicode, int unicodeBufferSizeInBytes) { #ifdef POSIX - return Q_UTF8ToUnicode(ansi, unicode, unicodeBufferSizeInBytes); + // Q_UTF8ToUnicode returns the number of bytes. This function is expected to return the number of chars. + return Q_UTF8ToUnicode(ansi, unicode, unicodeBufferSizeInBytes) / sizeof( wchar_t ); #else int chars = MultiByteToWideChar(CP_UTF8, 0, ansi, -1, unicode, unicodeBufferSizeInBytes / sizeof(wchar_t)); unicode[(unicodeBufferSizeInBytes / sizeof(wchar_t)) - 1] = 0; @@ -256,4 +257,4 @@ void ILocalize::ConstructStringKeyValuesInternal(char *unicodeOutput, int unicod void ILocalize::ConstructStringKeyValuesInternal(wchar_t *unicodeOutput, int unicodeBufferSizeInBytes, const wchar_t *formatString, KeyValues *localizationVariables) { ConstructStringKeyValuesInternal_Impl( unicodeOutput, unicodeBufferSizeInBytes, formatString, localizationVariables ); -} \ No newline at end of file +} diff --git a/mp/src/tier1/interface.cpp b/mp/src/tier1/interface.cpp index c970e5c6..031a49a7 100644 --- a/mp/src/tier1/interface.cpp +++ b/mp/src/tier1/interface.cpp @@ -284,7 +284,7 @@ CSysModule *Sys_LoadModule( const char *pModuleName, Sys_Flags flags /* = SYS_NO int i = CommandLine()->FindParm( "-basedir" ); if ( i ) { - strcpy( szCwd, CommandLine()->GetParm( i+1 ) ); + V_strcpy_safe( szCwd, CommandLine()->GetParm( i + 1 ) ); } } if (szCwd[strlen(szCwd) - 1] == '/' || szCwd[strlen(szCwd) - 1] == '\\' ) diff --git a/mp/src/tier1/kvpacker.cpp b/mp/src/tier1/kvpacker.cpp index 3672a2d0..53f7672e 100644 --- a/mp/src/tier1/kvpacker.cpp +++ b/mp/src/tier1/kvpacker.cpp @@ -181,7 +181,7 @@ bool KVPacker::ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer ) if ( ePackType == PACKTYPE_NULLMARKER ) break; // no more peers - buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + buffer.GetString( token ); token[KEYVALUES_TOKEN_SIZE-1] = 0; dat->SetName( token ); @@ -198,7 +198,7 @@ bool KVPacker::ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer ) } case PACKTYPE_STRING: { - buffer.GetString( token, KEYVALUES_TOKEN_SIZE-1 ); + buffer.GetString( token ); token[KEYVALUES_TOKEN_SIZE-1] = 0; dat->SetStringValue( token ); break; @@ -206,15 +206,26 @@ bool KVPacker::ReadAsBinary( KeyValues *pNode, CUtlBuffer &buffer ) case PACKTYPE_WSTRING: { int nLength = buffer.GetShort(); - wchar_t *pTemp = (wchar_t *)stackalloc( sizeof(wchar_t) * ( 1 + nLength ) ); - - for( int k = 0; k < nLength; ++ k ) + if ( nLength >= 0 && nLength*sizeof( uint16 ) <= (uint)buffer.GetBytesRemaining() ) { - pTemp[k] = buffer.GetShort(); - } - pTemp[ nLength ] = 0; + if ( nLength > 0 ) + { + wchar_t *pTemp = (wchar_t *)malloc( sizeof( wchar_t ) * (1 + nLength) ); - dat->SetWString( NULL, pTemp ); + for ( int k = 0; k < nLength; ++k ) + { + pTemp[k] = buffer.GetShort(); // ugly, but preserving existing behavior + } + + pTemp[nLength] = 0; + dat->SetWString( NULL, pTemp ); + + free( pTemp ); + } + else + dat->SetWString( NULL, L"" ); + + } break; } diff --git a/mp/src/tier1/lzmaDecoder.cpp b/mp/src/tier1/lzmaDecoder.cpp index d547c2bc..473f9c36 100644 --- a/mp/src/tier1/lzmaDecoder.cpp +++ b/mp/src/tier1/lzmaDecoder.cpp @@ -1,702 +1,39 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// // -// LZMA Codec. +// LZMA Codec interface for engine. // -// LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) -// http://www.7-zip.org/ +// LZMA SDK 9.38 beta +// 2015-01-03 : Igor Pavlov : Public domain +// http://www.7-zip.org/ // -// Modified to use Source platform utilities and memory allocation overrides. -//=====================================================================================// +//========================================================================// + +#define _LZMADECODER_CPP #include "tier0/platform.h" +#include "tier0/basetypes.h" #include "tier0/dbg.h" + +#include "../utils/lzma/C/7zTypes.h" +#include "../utils/lzma/C/LzmaEnc.h" +#include "../utils/lzma/C/LzmaDec.h" + +// Ugly define to let us forward declare the anonymous-struct-typedef that is CLzmaDec in the header. +#define CLzmaDec_t CLzmaDec #include "tier1/lzmaDecoder.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" -#ifndef _7ZIP_BYTE_DEFINED -#define _7ZIP_BYTE_DEFINED -typedef unsigned char Byte; -#endif - -#ifndef _7ZIP_UINT16_DEFINED -#define _7ZIP_UINT16_DEFINED -typedef unsigned short UInt16; -#endif - -#ifndef _7ZIP_UINT32_DEFINED -#define _7ZIP_UINT32_DEFINED -#ifdef _LZMA_UINT32_IS_ULONG -typedef unsigned long UInt32; -#else -typedef unsigned int UInt32; -#endif -#endif - -/* #define _LZMA_SYSTEM_SIZE_T */ -/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ - -#ifndef _7ZIP_SIZET_DEFINED -#define _7ZIP_SIZET_DEFINED -#ifdef _LZMA_SYSTEM_SIZE_T -#include -typedef size_t SizeT; -#else -typedef UInt32 SizeT; -#endif -#endif - -/* #define _LZMA_IN_CB */ -/* Use callback for input data */ - -/* #define _LZMA_OUT_READ */ -/* Use read function for output data */ - -#define _LZMA_PROB32 -/* It can increase speed on some 32-bit CPUs, -but memory usage will be doubled in that case */ - -/* #define _LZMA_LOC_OPT */ -/* Enable local speed optimizations inside code */ - -#ifdef _LZMA_PROB32 -#define CProb UInt32 -#else -#define CProb UInt16 -#endif - -#define LZMA_RESULT_OK 0 -#define LZMA_RESULT_DATA_ERROR 1 - -#ifdef _LZMA_IN_CB -typedef struct _ILzmaInCallback -{ - int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); -} ILzmaInCallback; -#endif - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LZMA_PROPERTIES_SIZE 5 - -typedef struct _CLzmaProperties -{ - int lc; - int lp; - int pb; -#ifdef _LZMA_OUT_READ - UInt32 DictionarySize; -#endif -}CLzmaProperties; - -int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); - -#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) - -#define kLzmaNeedInitId (-2) - -typedef struct _CLzmaDecoderState -{ - CLzmaProperties Properties; - CProb *Probs; - -#ifdef _LZMA_IN_CB - const unsigned char *Buffer; - const unsigned char *BufferLim; -#endif - -#ifdef _LZMA_OUT_READ - unsigned char *Dictionary; - UInt32 Range; - UInt32 Code; - UInt32 DictionaryPos; - UInt32 GlobalPos; - UInt32 DistanceLimit; - UInt32 Reps[4]; - int State; - int RemainLen; - unsigned char TempDictionary[4]; -#endif -} CLzmaDecoderState; - -#ifdef _LZMA_OUT_READ -#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } -#endif - -int LzmaDecode(CLzmaDecoderState *vs, -#ifdef _LZMA_IN_CB - ILzmaInCallback *inCallback, -#else - const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, -#endif - unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_READ_BYTE (*Buffer++) - -#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ -{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} - -#ifdef _LZMA_IN_CB - -#define RC_TEST { if (Buffer == BufferLim) \ -{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ - BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} - -#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 - -#else - -#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } - -#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 - -#endif - -#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } - -#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) -#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; -#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; - -#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ -{ UpdateBit0(p); mi <<= 1; A0; } else \ -{ UpdateBit1(p); mi = (mi + mi) + 1; A1; } - -#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) - -#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ -{ int i = numLevels; res = 1; \ - do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ - res -= (1 << numLevels); } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) -{ - unsigned char prop0; - if (size < LZMA_PROPERTIES_SIZE) - return LZMA_RESULT_DATA_ERROR; - prop0 = propsData[0]; - if (prop0 >= (9 * 5 * 5)) - return LZMA_RESULT_DATA_ERROR; - { - for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); - for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); - propsRes->lc = prop0; - /* - unsigned char remainder = (unsigned char)(prop0 / 9); - propsRes->lc = prop0 % 9; - propsRes->pb = remainder / 5; - propsRes->lp = remainder % 5; - */ - } - -#ifdef _LZMA_OUT_READ - { - int i; - propsRes->DictionarySize = 0; - for (i = 0; i < 4; i++) - propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); - if (propsRes->DictionarySize == 0) - propsRes->DictionarySize = 1; - } -#endif - return LZMA_RESULT_OK; -} - -#define kLzmaStreamWasFinishedId (-1) - -int LzmaDecode(CLzmaDecoderState *vs, -#ifdef _LZMA_IN_CB - ILzmaInCallback *InCallback, -#else - const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, -#endif - unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) -{ - CProb *p = vs->Probs; - SizeT nowPos = 0; - Byte previousByte = 0; - UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; - UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; - int lc = vs->Properties.lc; - -#ifdef _LZMA_OUT_READ - - UInt32 Range = vs->Range; - UInt32 Code = vs->Code; -#ifdef _LZMA_IN_CB - const Byte *Buffer = vs->Buffer; - const Byte *BufferLim = vs->BufferLim; -#else - const Byte *Buffer = inStream; - const Byte *BufferLim = inStream + inSize; -#endif - int state = vs->State; - UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; - int len = vs->RemainLen; - UInt32 globalPos = vs->GlobalPos; - UInt32 distanceLimit = vs->DistanceLimit; - - Byte *dictionary = vs->Dictionary; - UInt32 dictionarySize = vs->Properties.DictionarySize; - UInt32 dictionaryPos = vs->DictionaryPos; - - Byte tempDictionary[4]; - -#ifndef _LZMA_IN_CB - *inSizeProcessed = 0; -#endif - *outSizeProcessed = 0; - if (len == kLzmaStreamWasFinishedId) - return LZMA_RESULT_OK; - - if (dictionarySize == 0) - { - dictionary = tempDictionary; - dictionarySize = 1; - tempDictionary[0] = vs->TempDictionary[0]; - } - - if (len == kLzmaNeedInitId) - { - { - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); - UInt32 i; - for (i = 0; i < numProbs; i++) - p[i] = kBitModelTotal >> 1; - rep0 = rep1 = rep2 = rep3 = 1; - state = 0; - globalPos = 0; - distanceLimit = 0; - dictionaryPos = 0; - dictionary[dictionarySize - 1] = 0; -#ifdef _LZMA_IN_CB - RC_INIT; -#else - RC_INIT(inStream, inSize); -#endif - } - len = 0; - } - while(len != 0 && nowPos < outSize) - { - UInt32 pos = dictionaryPos - rep0; - if (pos >= dictionarySize) - pos += dictionarySize; - outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; - if (++dictionaryPos == dictionarySize) - dictionaryPos = 0; - len--; - } - if (dictionaryPos == 0) - previousByte = dictionary[dictionarySize - 1]; - else - previousByte = dictionary[dictionaryPos - 1]; - -#else /* if !_LZMA_OUT_READ */ - - int state = 0; - UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; - int len = 0; - const Byte *Buffer; - const Byte *BufferLim; - UInt32 Range; - UInt32 Code; - -#ifndef _LZMA_IN_CB - *inSizeProcessed = 0; -#endif - *outSizeProcessed = 0; - - { - UInt32 i; - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); - for (i = 0; i < numProbs; i++) - p[i] = kBitModelTotal >> 1; - } - -#ifdef _LZMA_IN_CB - RC_INIT; -#else - RC_INIT(inStream, inSize); -#endif - -#endif /* _LZMA_OUT_READ */ - - while(nowPos < outSize) - { - CProb *prob; - UInt32 bound; - int posState = (int)( - (nowPos -#ifdef _LZMA_OUT_READ - + globalPos -#endif - ) - & posStateMask); - - prob = p + IsMatch + (state << kNumPosBitsMax) + posState; - IfBit0(prob) - { - int symbol = 1; - UpdateBit0(prob) - prob = p + Literal + (LZMA_LIT_SIZE * - ((( - (nowPos -#ifdef _LZMA_OUT_READ - + globalPos -#endif - ) - & literalPosMask) << lc) + (previousByte >> (8 - lc)))); - - if (state >= kNumLitStates) - { - int matchByte; -#ifdef _LZMA_OUT_READ - UInt32 pos = dictionaryPos - rep0; - if (pos >= dictionarySize) - pos += dictionarySize; - matchByte = dictionary[pos]; -#else - matchByte = outStream[nowPos - rep0]; -#endif - do - { - int bit; - CProb *probLit; - matchByte <<= 1; - bit = (matchByte & 0x100); - probLit = prob + 0x100 + bit + symbol; - RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) - } - while (symbol < 0x100); - } - while (symbol < 0x100) - { - CProb *probLit = prob + symbol; - RC_GET_BIT(probLit, symbol) - } - previousByte = (Byte)symbol; - - outStream[nowPos++] = previousByte; -#ifdef _LZMA_OUT_READ - if (distanceLimit < dictionarySize) - distanceLimit++; - - dictionary[dictionaryPos] = previousByte; - if (++dictionaryPos == dictionarySize) - dictionaryPos = 0; -#endif - if (state < 4) state = 0; - else if (state < 10) state -= 3; - else state -= 6; - } -else -{ - UpdateBit1(prob); - prob = p + IsRep + state; - IfBit0(prob) - { - UpdateBit0(prob); - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - state = state < kNumLitStates ? 0 : 3; - prob = p + LenCoder; - } - else - { - UpdateBit1(prob); - prob = p + IsRepG0 + state; - IfBit0(prob) - { - UpdateBit0(prob); - prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; - IfBit0(prob) - { -#ifdef _LZMA_OUT_READ - UInt32 pos; -#endif - UpdateBit0(prob); - -#ifdef _LZMA_OUT_READ - if (distanceLimit == 0) -#else - if (nowPos == 0) -#endif - return LZMA_RESULT_DATA_ERROR; - - state = state < kNumLitStates ? 9 : 11; -#ifdef _LZMA_OUT_READ - pos = dictionaryPos - rep0; - if (pos >= dictionarySize) - pos += dictionarySize; - previousByte = dictionary[pos]; - dictionary[dictionaryPos] = previousByte; - if (++dictionaryPos == dictionarySize) - dictionaryPos = 0; -#else - previousByte = outStream[nowPos - rep0]; -#endif - outStream[nowPos++] = previousByte; -#ifdef _LZMA_OUT_READ - if (distanceLimit < dictionarySize) - distanceLimit++; -#endif - - continue; - } - else - { - UpdateBit1(prob); - } - } - else - { - UInt32 distance; - UpdateBit1(prob); - prob = p + IsRepG1 + state; - IfBit0(prob) - { - UpdateBit0(prob); - distance = rep1; - } - else - { - UpdateBit1(prob); - prob = p + IsRepG2 + state; - IfBit0(prob) - { - UpdateBit0(prob); - distance = rep2; - } - else - { - UpdateBit1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = p + RepLenCoder; - } - { - int numBits, offset; - CProb *probLen = prob + LenChoice; - IfBit0(probLen) - { - UpdateBit0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - numBits = kLenNumLowBits; - } - else - { - UpdateBit1(probLen); - probLen = prob + LenChoice2; - IfBit0(probLen) - { - UpdateBit0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - numBits = kLenNumMidBits; - } - else - { - UpdateBit1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - numBits = kLenNumHighBits; - } - } - RangeDecoderBitTreeDecode(probLen, numBits, len); - len += offset; - } - - if (state < 4) - { - int posSlot; - state += kNumLitStates; - prob = p + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - rep0 = (2 | ((UInt32)posSlot & 1)); - if (posSlot < kEndPosModelIndex) - { - rep0 <<= numDirectBits; - prob = p + SpecPos + rep0 - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - RC_NORMALIZE - Range >>= 1; - rep0 <<= 1; - if (Code >= Range) - { - Code -= Range; - rep0 |= 1; - } - } - while (--numDirectBits != 0); - prob = p + Align; - rep0 <<= kNumAlignBits; - numDirectBits = kNumAlignBits; - } - { - int i = 1; - int mi = 1; - do - { - CProb *prob3 = prob + mi; - RC_GET_BIT2(prob3, mi, ; , rep0 |= i); - i <<= 1; - } - while(--numDirectBits != 0); - } - } - else - rep0 = posSlot; - if (++rep0 == (UInt32)(0)) - { - /* it's for stream version */ - len = kLzmaStreamWasFinishedId; - break; - } - } - - len += kMatchMinLen; -#ifdef _LZMA_OUT_READ - if (rep0 > distanceLimit) -#else - if (rep0 > nowPos) -#endif - return LZMA_RESULT_DATA_ERROR; - -#ifdef _LZMA_OUT_READ - if (dictionarySize - distanceLimit > (UInt32)len) - distanceLimit += len; - else - distanceLimit = dictionarySize; -#endif - - do - { -#ifdef _LZMA_OUT_READ - UInt32 pos = dictionaryPos - rep0; - if (pos >= dictionarySize) - pos += dictionarySize; - previousByte = dictionary[pos]; - dictionary[dictionaryPos] = previousByte; - if (++dictionaryPos == dictionarySize) - dictionaryPos = 0; -#else - previousByte = outStream[nowPos - rep0]; -#endif - len--; - outStream[nowPos++] = previousByte; - } - while(len != 0 && nowPos < outSize); -} - } - RC_NORMALIZE; - -#ifdef _LZMA_OUT_READ - vs->Range = Range; - vs->Code = Code; - vs->DictionaryPos = dictionaryPos; - vs->GlobalPos = globalPos + (UInt32)nowPos; - vs->DistanceLimit = distanceLimit; - vs->Reps[0] = rep0; - vs->Reps[1] = rep1; - vs->Reps[2] = rep2; - vs->Reps[3] = rep3; - vs->State = state; - vs->RemainLen = len; - vs->TempDictionary[0] = tempDictionary[0]; -#endif - -#ifdef _LZMA_IN_CB - vs->Buffer = Buffer; - vs->BufferLim = BufferLim; -#else - *inSizeProcessed = (SizeT)(Buffer - inStream); -#endif - *outSizeProcessed = nowPos; - return LZMA_RESULT_OK; -} +// Allocator to pass to LZMA functions +static void *SzAlloc(void *p, size_t size) { return malloc(size); } +static void SzFree(void *p, void *address) { free(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; //----------------------------------------------------------------------------- // Returns true if buffer is compressed. //----------------------------------------------------------------------------- +/* static */ bool CLZMA::IsCompressed( unsigned char *pInput ) { lzma_header_t *pHeader = (lzma_header_t *)pInput; @@ -713,6 +50,7 @@ bool CLZMA::IsCompressed( unsigned char *pInput ) // Returns uncompressed size of compressed input buffer. Used for allocating output // buffer for decompression. Returns 0 if input buffer is not compressed. //----------------------------------------------------------------------------- +/* static */ unsigned int CLZMA::GetActualSize( unsigned char *pInput ) { lzma_header_t *pHeader = (lzma_header_t *)pInput; @@ -729,36 +67,282 @@ unsigned int CLZMA::GetActualSize( unsigned char *pInput ) // Uncompress a buffer, Returns the uncompressed size. Caller must provide an // adequate sized output buffer or memory corruption will occur. //----------------------------------------------------------------------------- +/* static */ unsigned int CLZMA::Uncompress( unsigned char *pInput, unsigned char *pOutput ) { - unsigned int actualSize = GetActualSize( pInput ); - if ( !actualSize ) + lzma_header_t *pHeader = (lzma_header_t *)pInput; + if ( pHeader->id != LZMA_ID ) { - // unrecognized + // not ours + return false; + } + + CLzmaDec state; + + LzmaDec_Construct(&state); + + if ( LzmaDec_Allocate(&state, pHeader->properties, LZMA_PROPS_SIZE, &g_Alloc) != SZ_OK ) + { + Assert( false ); return 0; } - CLzmaDecoderState state; - if ( LzmaDecodeProperties( &state.Properties, ((lzma_header_t *)pInput)->properties, LZMA_PROPERTIES_SIZE ) != LZMA_RESULT_OK ) + // These are in/out variables + SizeT outProcessed = pHeader->actualSize; + SizeT inProcessed = pHeader->lzmaSize; + ELzmaStatus status; + SRes result = LzmaDecode( (Byte *)pOutput, &outProcessed, (Byte *)(pInput + sizeof( lzma_header_t ) ), + &inProcessed, (Byte *)pHeader->properties, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc ); + + + LzmaDec_Free(&state, &g_Alloc); + + if ( result != SZ_OK || pHeader->actualSize != outProcessed ) { - Assert( 0 ); - } - state.Probs = (CProb *)malloc( LzmaGetNumProbs( &state.Properties ) * sizeof( CProb ) ); - - unsigned int lzmaSize = LittleLong( ((lzma_header_t *)pInput)->lzmaSize ); - - SizeT inProcessed; - SizeT outProcessed; - int result = LzmaDecode( &state, pInput + sizeof( lzma_header_t ), lzmaSize, &inProcessed, pOutput, actualSize, &outProcessed ); - - free( state.Probs ); - - if ( result != LZMA_RESULT_OK || outProcessed != (SizeT)actualSize ) - { - Assert( 0 ); + Warning( "LZMA Decompression failed (%i)\n", result ); return 0; } return outProcessed; } +CLZMAStream::CLZMAStream() + : m_pDecoderState( NULL ), + m_nActualSize( 0 ), + m_nActualBytesRead ( 0 ), + m_nCompressedSize( 0 ), + m_nCompressedBytesRead ( 0 ), + m_bParsedHeader( false ), + m_bZIPStyleHeader( false ) +{} + +CLZMAStream::~CLZMAStream() +{ + FreeDecoderState(); +} + +void CLZMAStream::FreeDecoderState() +{ + if ( m_pDecoderState ) + { + LzmaDec_Free( m_pDecoderState, &g_Alloc ); + m_pDecoderState = NULL; + } +} + +bool CLZMAStream::CreateDecoderState( const unsigned char *pProperties ) +{ + if ( m_pDecoderState ) + { + Assert( !m_pDecoderState ); + FreeDecoderState(); + } + + m_pDecoderState = new CLzmaDec(); + + LzmaDec_Construct( m_pDecoderState ); + if ( LzmaDec_Allocate( m_pDecoderState, pProperties, LZMA_PROPS_SIZE, &g_Alloc) != SZ_OK ) + { + AssertMsg( false, "Failed to allocate lzma decoder state" ); + m_pDecoderState = NULL; + return false; + } + + LzmaDec_Init( m_pDecoderState ); + + return true; +} + +// Attempt to read up to nMaxInputBytes from the compressed stream, writing up to nMaxOutputBytes to pOutput. +// Returns false if read stops due to an error. +bool CLZMAStream::Read( unsigned char *pInput, unsigned int nMaxInputBytes, + unsigned char *pOutput, unsigned int nMaxOutputBytes, + /* out */ unsigned int &nCompressedBytesRead, + /* out */ unsigned int &nOutputBytesWritten ) +{ + nCompressedBytesRead = 0; + nOutputBytesWritten = 0; + bool bStartedWithHeader = m_bParsedHeader; + + // Check for initial chunk of data + if ( !m_bParsedHeader ) + { + unsigned int nBytesConsumed = 0; + eHeaderParse parseResult = TryParseHeader( pInput, nMaxInputBytes, nBytesConsumed ); + + if ( parseResult == eHeaderParse_NeedMoreBytes ) + { + // Not an error, just need more data to continue + return true; + } + else if ( parseResult != eHeaderParse_OK ) + { + Assert( parseResult == eHeaderParse_Fail ); + // Invalid header + return false; + } + + // Header consumed, fall through to continue read after it + nCompressedBytesRead += nBytesConsumed; + pInput += nBytesConsumed; + nMaxInputBytes -= nBytesConsumed; + } + + // These are input ( available size ) *and* output ( size processed ) vars for lzma + SizeT expectedInputRemaining = m_nCompressedSize - Min( m_nCompressedBytesRead + nCompressedBytesRead, m_nCompressedSize ); + SizeT expectedOutputRemaining = m_nActualSize - m_nActualBytesRead; + SizeT inSize = Min( (SizeT)nMaxInputBytes, expectedInputRemaining ); + SizeT outSize = Min( (SizeT)nMaxOutputBytes, expectedOutputRemaining ); + ELzmaStatus status; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if ( inSize == expectedInputRemaining && outSize == expectedOutputRemaining ) + { + // Expect to finish decoding this call. + finishMode = LZMA_FINISH_END; + } + SRes result = LzmaDec_DecodeToBuf( m_pDecoderState, pOutput, &outSize, + pInput, &inSize, finishMode, &status ); + + // DevMsg("[%p] Running lzmaDecode:\n" + // " pInput: %p\n" + // " nMaxInputBytes: %i\n" + // " pOutput: %p\n" + // " nMaxOutputBytes: %u\n" + // " inSize: %u\n" + // " outSize: %u\n" + // " result: %u\n" + // " status: %i\n" + // " m_nActualSize: %u\n" + // " m_nActualBytesRead: %u\n", + // this, pInput, nMaxInputBytes, pOutput, nMaxOutputBytes, + // inSize, outSize, result, status, m_nActualSize, m_nActualBytesRead); + + if ( result != SZ_OK ) + { + if ( !bStartedWithHeader ) + { + // If we're returning false, we need to pretend we didn't consume anything. + FreeDecoderState(); + m_bParsedHeader = false; + } + return false; + } + + nCompressedBytesRead += inSize; + nOutputBytesWritten += outSize; + + m_nCompressedBytesRead += nCompressedBytesRead; + m_nActualBytesRead += nOutputBytesWritten; + + Assert( m_nCompressedBytesRead <= m_nCompressedSize ); + return true; +} + +bool CLZMAStream::GetExpectedBytesRemaining( /* out */ unsigned int &nBytesRemaining ) +{ + if ( !m_bParsedHeader && !m_bZIPStyleHeader ) { + return false; + } + + nBytesRemaining = m_nActualSize - m_nActualBytesRead; + + return true; +} + +void CLZMAStream::InitZIPHeader( unsigned int nCompressedSize, unsigned int nOriginalSize ) +{ + if ( m_bParsedHeader || m_bZIPStyleHeader ) + { + AssertMsg( !m_bParsedHeader && !m_bZIPStyleHeader, + "LZMA Stream: InitZIPHeader() called on stream past header" ); + return; + } + + m_nCompressedSize = nCompressedSize; + m_nActualSize = nOriginalSize; + // Signal to TryParseHeader to expect a zip-style header (which wont have the size values) + m_bZIPStyleHeader = true; +} + +CLZMAStream::eHeaderParse CLZMAStream::TryParseHeader( unsigned char *pInput, unsigned int nBytesAvailable, /* out */ unsigned int &nBytesConsumed ) +{ + nBytesConsumed = 0; + + if ( m_bParsedHeader ) + { + AssertMsg( !m_bParsedHeader, "CLZMAStream::ReadSourceHeader called on already initialized stream" ); + return eHeaderParse_Fail; + } + + if ( m_bZIPStyleHeader ) + { + // ZIP Spec, 5.8.8 + // LZMA Version Information 2 bytes + // LZMA Properties Size 2 bytes + // LZMA Properties Data variable, defined by "LZMA Properties Size" + + if ( nBytesAvailable < 4 ) + { + // No error, but need more input to continue + return eHeaderParse_NeedMoreBytes; + } + + // Should probably check this + // unsigned char nLZMAVer[2] = { pInput[0], pInput[1] }; + + uint16 nLZMAPropertiesSize = LittleWord( *(uint16 *)(pInput + 2) ); + + nBytesConsumed += 4; + + if ( nLZMAPropertiesSize != LZMA_PROPS_SIZE ) + { + Warning( "LZMA stream: Unexpected LZMA properties size: %hu, expecting %u. Version mismatch?\n", + nLZMAPropertiesSize, LZMA_PROPS_SIZE ); + return eHeaderParse_Fail; + } + + if ( nBytesAvailable < static_cast(nLZMAPropertiesSize) + 4 ) + { + return eHeaderParse_NeedMoreBytes; + } + + // Looks reasonable, try to parse + if ( !CreateDecoderState( (Byte *)pInput + 4 ) ) + { + AssertMsg( false, "Failed decoding Lzma properties" ); + return eHeaderParse_Fail; + } + + nBytesConsumed += nLZMAPropertiesSize; + } + else + { + // Else native source engine style header + if ( nBytesAvailable < sizeof( lzma_header_t ) ) + { + // need more input to continue + return eHeaderParse_NeedMoreBytes; + } + + m_nActualSize = CLZMA::GetActualSize( pInput ); + + if ( !m_nActualSize ) + { + // unrecognized + Warning( "Unrecognized LZMA data\n" ); + return eHeaderParse_Fail; + } + + if ( !CreateDecoderState( ((lzma_header_t *)pInput)->properties ) ) + { + AssertMsg( false, "Failed decoding Lzma properties" ); + return eHeaderParse_Fail; + } + + m_nCompressedSize = LittleLong( ((lzma_header_t *)pInput)->lzmaSize ) + sizeof( lzma_header_t ); + nBytesConsumed += sizeof( lzma_header_t ); + } + + m_bParsedHeader = true; + return eHeaderParse_OK; +} diff --git a/mp/src/tier1/strtools.cpp b/mp/src/tier1/strtools.cpp index ad301750..2c5f72fa 100644 --- a/mp/src/tier1/strtools.cpp +++ b/mp/src/tier1/strtools.cpp @@ -1251,7 +1251,7 @@ bool Q_RemoveAllEvilCharacters( char *pch ) int cch = Q_strlen( pch ); int cubDest = (cch + 1 ) * sizeof( wchar_t ); wchar_t *pwch = (wchar_t *)stackalloc( cubDest ); - int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ); + int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t ); bool bStrippedWhitespace = false; @@ -1289,8 +1289,13 @@ bool Q_RemoveAllEvilCharacters( char *pch ) //----------------------------------------------------------------------------- bool Q_StripPrecedingAndTrailingWhitespaceW( wchar_t *pwch ) { - // duplicate on stack int cch = Q_wcslen( pwch ); + + // Early out and don't convert if we don't have any chars or leading/trailing ws. + if ( ( cch < 1 ) || ( !iswspace( pwch[ 0 ] ) && !iswspace( pwch[ cch - 1 ] ) ) ) + return false; + + // duplicate on stack int cubDest = ( cch + 1 ) * sizeof( wchar_t ); wchar_t *pwchT = (wchar_t *)stackalloc( cubDest ); Q_wcsncpy( pwchT, pwch, cubDest ); @@ -1340,11 +1345,16 @@ bool Q_AggressiveStripPrecedingAndTrailingWhitespaceW( wchar_t *pwch ) //----------------------------------------------------------------------------- bool Q_StripPrecedingAndTrailingWhitespace( char *pch ) { - // convert to unicode int cch = Q_strlen( pch ); + + // Early out and don't convert if we don't have any chars or leading/trailing ws. + if ( ( cch < 1 ) || ( !isspace( (unsigned char)pch[ 0 ] ) && !isspace( (unsigned char)pch[ cch - 1 ] ) ) ) + return false; + + // convert to unicode int cubDest = (cch + 1 ) * sizeof( wchar_t ); wchar_t *pwch = (wchar_t *)stackalloc( cubDest ); - int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ); + int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t ); bool bStrippedWhitespace = false; pwch = StripWhitespaceWorker( cwch-1, pwch, &bStrippedWhitespace, false /* not aggressive */ ); @@ -1367,7 +1377,7 @@ bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch ) int cch = Q_strlen( pch ); int cubDest = (cch + 1 ) * sizeof( wchar_t ); wchar_t *pwch = (wchar_t *)stackalloc( cubDest ); - int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ); + int cwch = Q_UTF8ToUnicode( pch, pwch, cubDest ) / sizeof( wchar_t ); bool bStrippedWhitespace = false; pwch = StripWhitespaceWorker( cwch-1, pwch, &bStrippedWhitespace, true /* is aggressive */ ); @@ -1381,72 +1391,10 @@ bool Q_AggressiveStripPrecedingAndTrailingWhitespace( char *pch ) return bStrippedWhitespace; } - -//----------------------------------------------------------------------------- -// Purpose: Converts a UTF8 string into a unicode string -//----------------------------------------------------------------------------- -int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ) -{ - // pwchDest can be null to allow for getting the length of the string - if ( cubDestSizeInBytes > 0 ) - { - AssertValidWritePtr(pwchDest); - pwchDest[0] = 0; - } - - if ( !pUTF8 ) - return 0; - - AssertValidStringPtr(pUTF8); - -#ifdef _WIN32 - int cchResult = MultiByteToWideChar( CP_UTF8, 0, pUTF8, -1, pwchDest, cubDestSizeInBytes / sizeof(wchar_t) ); -#elif POSIX - int cchResult = mbstowcs( pwchDest, pUTF8, cubDestSizeInBytes / sizeof(wchar_t) ) + 1; -#endif - - if ( cubDestSizeInBytes > 0 ) - { - pwchDest[(cubDestSizeInBytes / sizeof(wchar_t)) - 1] = 0; - } - - return cchResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Converts a unicode string into a UTF8 (standard) string -//----------------------------------------------------------------------------- -int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ) -{ - //AssertValidStringPtr(pUTF8, cubDestSizeInBytes); // no, we are sometimes pasing in NULL to fetch the length of the buffer needed. - AssertValidReadPtr(pUnicode); - - if ( cubDestSizeInBytes > 0 ) - { - pUTF8[0] = 0; - } - -#ifdef _WIN32 - int cchResult = WideCharToMultiByte( CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL ); -#elif POSIX - int cchResult = 0; - if ( pUnicode && pUTF8 ) - cchResult = wcstombs( pUTF8, pUnicode, cubDestSizeInBytes ) + 1; -#endif - - if ( cubDestSizeInBytes > 0 ) - { - pUTF8[cubDestSizeInBytes - 1] = 0; - } - - return cchResult; -} - - //----------------------------------------------------------------------------- // Purpose: Converts a ucs2 string to a unicode (wchar_t) one, no-op on win32 //----------------------------------------------------------------------------- -int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInBytes ) +int _V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInBytes ) { Assert( cubDestSizeInBytes >= sizeof( *pUnicode ) ); AssertValidWritePtr(pUnicode); @@ -1455,7 +1403,7 @@ int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInByte pUnicode[0] = 0; #ifdef _WIN32 int cchResult = V_wcslen( pUCS2 ); - Q_memcpy( pUnicode, pUCS2, cubDestSizeInBytes ); + V_memcpy( pUnicode, pUCS2, cubDestSizeInBytes ); #else iconv_t conv_t = iconv_open( "UCS-4LE", "UCS-2LE" ); int cchResult = -1; @@ -1486,7 +1434,7 @@ int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInByte //----------------------------------------------------------------------------- // Purpose: Converts a wchar_t string into a UCS2 string -noop on windows //----------------------------------------------------------------------------- -int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, int cubDestSizeInBytes ) +int _V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, int cubDestSizeInBytes ) { #ifdef _WIN32 // Figure out which buffer is smaller and convert from bytes to character @@ -1512,6 +1460,8 @@ int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, in else cchResult = cubSrcInBytes / sizeof( wchar_t ); } +#else + #error Must be implemented for this platform #endif return cchResult; } @@ -1520,7 +1470,7 @@ int V_UnicodeToUCS2( const wchar_t *pUnicode, int cubSrcInBytes, char *pUCS2, in //----------------------------------------------------------------------------- // Purpose: Converts a ucs-2 (windows wchar_t) string into a UTF8 (standard) string //----------------------------------------------------------------------------- -int V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes ) +int _V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes ) { AssertValidStringPtr(pUTF8, cubDestSizeInBytes); AssertValidReadPtr(pUCS2); @@ -1574,7 +1524,7 @@ int V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes ) //----------------------------------------------------------------------------- // Purpose: Converts a UTF8 to ucs-2 (windows wchar_t) //----------------------------------------------------------------------------- -int V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, ucs2 *pUCS2, int cubDestSizeInBytes ) +int _V_UTF8ToUCS2( const char *pUTF8, int cubSrcInBytes, ucs2 *pUCS2, int cubDestSizeInBytes ) { Assert( cubDestSizeInBytes >= sizeof(pUCS2[0]) ); AssertValidStringPtr(pUTF8, cubDestSizeInBytes); diff --git a/mp/src/tier1/strtools_unicode.cpp b/mp/src/tier1/strtools_unicode.cpp new file mode 100644 index 00000000..77685ec3 --- /dev/null +++ b/mp/src/tier1/strtools_unicode.cpp @@ -0,0 +1,572 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#include +#include "tier0/dbg.h" +#include "tier1/strtools.h" + +// This code was copied from steam +#define DbgAssert Assert + +//----------------------------------------------------------------------------- +// Purpose: determine if a uchar32 represents a valid Unicode code point +//----------------------------------------------------------------------------- +bool Q_IsValidUChar32( uchar32 uVal ) +{ + // Values > 0x10FFFF are explicitly invalid; ditto for UTF-16 surrogate halves, + // values ending in FFFE or FFFF, or values in the 0x00FDD0-0x00FDEF reserved range + return ( uVal < 0x110000u ) && ( (uVal - 0x00D800u) > 0x7FFu ) && ( (uVal & 0xFFFFu) < 0xFFFEu ) && ( ( uVal - 0x00FDD0u ) > 0x1Fu ); +} + +//----------------------------------------------------------------------------- +// Purpose: return number of UTF-8 bytes required to encode a Unicode code point +//----------------------------------------------------------------------------- +int Q_UChar32ToUTF8Len( uchar32 uVal ) +{ + DbgAssert( Q_IsValidUChar32( uVal ) ); + if ( uVal <= 0x7F ) + return 1; + if ( uVal <= 0x7FF ) + return 2; + if ( uVal <= 0xFFFF ) + return 3; + return 4; +} + + +//----------------------------------------------------------------------------- +// Purpose: return number of UTF-16 elements required to encode a Unicode code point +//----------------------------------------------------------------------------- +int Q_UChar32ToUTF16Len( uchar32 uVal ) +{ + DbgAssert( Q_IsValidUChar32( uVal ) ); + if ( uVal <= 0xFFFF ) + return 1; + return 2; +} + + +//----------------------------------------------------------------------------- +// Purpose: encode Unicode code point as UTF-8, returns number of bytes written +//----------------------------------------------------------------------------- +int Q_UChar32ToUTF8( uchar32 uVal, char *pUTF8Out ) +{ + DbgAssert( Q_IsValidUChar32( uVal ) ); + if ( uVal <= 0x7F ) + { + pUTF8Out[0] = (unsigned char) uVal; + return 1; + } + if ( uVal <= 0x7FF ) + { + pUTF8Out[0] = (unsigned char)(uVal >> 6) | 0xC0; + pUTF8Out[1] = (unsigned char)(uVal & 0x3F) | 0x80; + return 2; + } + if ( uVal <= 0xFFFF ) + { + pUTF8Out[0] = (unsigned char)(uVal >> 12) | 0xE0; + pUTF8Out[1] = (unsigned char)((uVal >> 6) & 0x3F) | 0x80; + pUTF8Out[2] = (unsigned char)(uVal & 0x3F) | 0x80; + return 3; + } + pUTF8Out[0] = (unsigned char)((uVal >> 18) & 0x07) | 0xF0; + pUTF8Out[1] = (unsigned char)((uVal >> 12) & 0x3F) | 0x80; + pUTF8Out[2] = (unsigned char)((uVal >> 6) & 0x3F) | 0x80; + pUTF8Out[3] = (unsigned char)(uVal & 0x3F) | 0x80; + return 4; +} + +//----------------------------------------------------------------------------- +// Purpose: encode Unicode code point as UTF-16, returns number of elements written +//----------------------------------------------------------------------------- +int Q_UChar32ToUTF16( uchar32 uVal, uchar16 *pUTF16Out ) +{ + DbgAssert( Q_IsValidUChar32( uVal ) ); + if ( uVal <= 0xFFFF ) + { + pUTF16Out[0] = (uchar16) uVal; + return 1; + } + uVal -= 0x010000; + pUTF16Out[0] = (uchar16)(uVal >> 10) | 0xD800; + pUTF16Out[1] = (uchar16)(uVal & 0x3FF) | 0xDC00; + return 2; +} + + +// Decode one character from a UTF-8 encoded string. Treats 6-byte CESU-8 sequences +// as a single character, as if they were a correctly-encoded 4-byte UTF-8 sequence. +int Q_UTF8ToUChar32( const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut ) +{ + const uint8 *pUTF8 = (const uint8 *)pUTF8_; + + int nBytes = 1; + uint32 uValue = pUTF8[0]; + uint32 uMinValue = 0; + + // 0....... single byte + if ( uValue < 0x80 ) + goto decodeFinishedNoCheck; + + // Expecting at least a two-byte sequence with 0xC0 <= first <= 0xF7 (110...... and 11110...) + if ( (uValue - 0xC0u) > 0x37u || ( pUTF8[1] & 0xC0 ) != 0x80 ) + goto decodeError; + + uValue = (uValue << 6) - (0xC0 << 6) + pUTF8[1] - 0x80; + nBytes = 2; + uMinValue = 0x80; + + // 110..... two-byte lead byte + if ( !( uValue & (0x20 << 6) ) ) + goto decodeFinished; + + // Expecting at least a three-byte sequence + if ( ( pUTF8[2] & 0xC0 ) != 0x80 ) + goto decodeError; + + uValue = (uValue << 6) - (0x20 << 12) + pUTF8[2] - 0x80; + nBytes = 3; + uMinValue = 0x800; + + // 1110.... three-byte lead byte + if ( !( uValue & (0x10 << 12) ) ) + goto decodeFinishedMaybeCESU8; + + // Expecting a four-byte sequence, longest permissible in UTF-8 + if ( ( pUTF8[3] & 0xC0 ) != 0x80 ) + goto decodeError; + + uValue = (uValue << 6) - (0x10 << 18) + pUTF8[3] - 0x80; + nBytes = 4; + uMinValue = 0x10000; + + // 11110... four-byte lead byte. fall through to finished. + +decodeFinished: + if ( uValue >= uMinValue && Q_IsValidUChar32( uValue ) ) + { +decodeFinishedNoCheck: + uValueOut = uValue; + bErrorOut = false; + return nBytes; + } +decodeError: + uValueOut = '?'; + bErrorOut = true; + return nBytes; + +decodeFinishedMaybeCESU8: + // Do we have a full UTF-16 surrogate pair that's been UTF-8 encoded afterwards? + // That is, do we have 0xD800-0xDBFF followed by 0xDC00-0xDFFF? If so, decode it all. + if ( ( uValue - 0xD800u ) < 0x400u && pUTF8[3] == 0xED && (uint8)( pUTF8[4] - 0xB0 ) < 0x10 && ( pUTF8[5] & 0xC0 ) == 0x80 ) + { + uValue = 0x10000 + ( ( uValue - 0xD800u ) << 10 ) + ( (uint8)( pUTF8[4] - 0xB0 ) << 6 ) + pUTF8[5] - 0x80; + nBytes = 6; + uMinValue = 0x10000; + } + goto decodeFinished; +} + +// Decode one character from a UTF-16 encoded string. +int Q_UTF16ToUChar32( const uchar16 *pUTF16, uchar32 &uValueOut, bool &bErrorOut ) +{ + if ( Q_IsValidUChar32( pUTF16[0] ) ) + { + uValueOut = pUTF16[0]; + bErrorOut = false; + return 1; + } + else if ( (pUTF16[0] - 0xD800u) < 0x400u && (pUTF16[1] - 0xDC00u) < 0x400u ) + { + // Valid surrogate pair, but maybe not encoding a valid Unicode code point... + uchar32 uVal = 0x010000 + ((pUTF16[0] - 0xD800u) << 10) + (pUTF16[1] - 0xDC00); + if ( Q_IsValidUChar32( uVal ) ) + { + uValueOut = uVal; + bErrorOut = false; + return 2; + } + else + { + uValueOut = '?'; + bErrorOut = true; + return 2; + } + } + else + { + uValueOut = '?'; + bErrorOut = true; + return 1; + } +} + +namespace // internal use only +{ + // Identity transformations and validity tests for use with Q_UnicodeConvertT + int Q_UTF32ToUChar32( const uchar32 *pUTF32, uchar32 &uVal, bool &bErr ) + { + bErr = !Q_IsValidUChar32( *pUTF32 ); + uVal = bErr ? '?' : *pUTF32; + return 1; + } + + int Q_UChar32ToUTF32Len( uchar32 uVal ) + { + return 1; + } + + int Q_UChar32ToUTF32( uchar32 uVal, uchar32 *pUTF32 ) + { + *pUTF32 = uVal; + return 1; + } + + // A generic Unicode processing loop: decode one character from input to uchar32, handle errors, encode uchar32 to output + template < typename SrcType, typename DstType, bool bStopAtNull, int (&DecodeSrc)( const SrcType*, uchar32&, bool& ), int (&EncodeDstLen)( uchar32 ), int (&EncodeDst)( uchar32, DstType* ) > + int Q_UnicodeConvertT( const SrcType *pIn, int nInChars, DstType *pOut, int nOutBytes, EStringConvertErrorPolicy ePolicy ) + { + if ( !pIn ) + { + // For now, assert and return 0. Once these are cleaned out a bit + // we should remove this return and just leave in the assert... + AssertMsg( pIn, "We shouldn't be passing in NULL!" ); + return 0; + } + + int nOut = 0; + + if ( !pOut ) + { + while ( bStopAtNull ? ( *pIn ) : ( nInChars-- > 0 ) ) + { + uchar32 uVal; + // Initialize in order to avoid /analyze warnings. + bool bErr = false; + pIn += DecodeSrc( pIn, uVal, bErr ); + nOut += EncodeDstLen( uVal ); + if ( bErr ) + { +#ifdef _DEBUG + AssertMsg( !(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence" ); +#endif + if ( ePolicy & _STRINGCONVERTFLAG_SKIP ) + { + nOut -= EncodeDstLen( uVal ); + } + else if ( ePolicy & _STRINGCONVERTFLAG_FAIL ) + { + pOut[0] = 0; + return 0; + } + } + } + } + else + { + int nOutElems = nOutBytes / sizeof( DstType ); + if ( nOutElems <= 0 ) + return 0; + + int nMaxOut = nOutElems - 1; + while ( bStopAtNull ? ( *pIn ) : ( nInChars-- > 0 ) ) + { + uchar32 uVal; + // Initialize in order to avoid /analyze warnings. + bool bErr = false; + pIn += DecodeSrc( pIn, uVal, bErr ); + if ( nOut + EncodeDstLen( uVal ) > nMaxOut ) + break; + nOut += EncodeDst( uVal, pOut + nOut ); + if ( bErr ) + { +#ifdef _DEBUG + AssertMsg( !(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence" ); +#endif + if ( ePolicy & _STRINGCONVERTFLAG_SKIP ) + { + nOut -= EncodeDstLen( uVal ); + } + else if ( ePolicy & _STRINGCONVERTFLAG_FAIL ) + { + pOut[0] = 0; + return 0; + } + } + } + pOut[nOut] = 0; + } + + return (nOut + 1) * sizeof( DstType ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if UTF-8 string contains invalid sequences. +//----------------------------------------------------------------------------- +bool Q_UnicodeValidate( const char *pUTF8 ) +{ + bool bError = false; + while ( *pUTF8 ) + { + uchar32 uVal; + // Our UTF-8 decoder silently fixes up 6-byte CESU-8 (improperly re-encoded UTF-16) sequences. + // However, these are technically not valid UTF-8. So if we eat 6 bytes at once, it's an error. + int nCharSize = Q_UTF8ToUChar32( pUTF8, uVal, bError ); + if ( bError || nCharSize == 6 ) + return false; + pUTF8 += nCharSize; + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if UTF-16 string contains invalid sequences. +//----------------------------------------------------------------------------- +bool Q_UnicodeValidate( const uchar16 *pUTF16 ) +{ + bool bError = false; + while ( *pUTF16 ) + { + uchar32 uVal; + pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError ); + if ( bError ) + return false; + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns true if UTF-32 string contains invalid sequences. +//----------------------------------------------------------------------------- +bool Q_UnicodeValidate( const uchar32 *pUTF32 ) +{ + while ( *pUTF32 ) + { + if ( !Q_IsValidUChar32( *pUTF32++ ) ) + return false; + ++pUTF32; + } + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-8 string +//----------------------------------------------------------------------------- +int Q_UnicodeLength( const char *pUTF8 ) +{ + int nChars = 0; + while ( *pUTF8 ) + { + bool bError; + uchar32 uVal; + pUTF8 += Q_UTF8ToUChar32( pUTF8, uVal, bError ); + ++nChars; + } + return nChars; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-16 string +//----------------------------------------------------------------------------- +int Q_UnicodeLength( const uchar16 *pUTF16 ) +{ + int nChars = 0; + while ( *pUTF16 ) + { + bool bError; + uchar32 uVal; + pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError ); + ++nChars; + } + return nChars; +} + +//----------------------------------------------------------------------------- +// Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-32 string +//----------------------------------------------------------------------------- +int Q_UnicodeLength( const uchar32 *pUTF32 ) +{ + int nChars = 0; + while ( *pUTF32++ ) + ++nChars; + return nChars; +} + +//----------------------------------------------------------------------------- +// Purpose: Advance a UTF-8 string pointer by a certain number of Unicode code points, stopping at end of string +//----------------------------------------------------------------------------- +char *Q_UnicodeAdvance( char *pUTF8, int nChars ) +{ + while ( nChars > 0 && *pUTF8 ) + { + uchar32 uVal; + bool bError; + pUTF8 += Q_UTF8ToUChar32( pUTF8, uVal, bError ); + --nChars; + } + return pUTF8; +} + +//----------------------------------------------------------------------------- +// Purpose: Advance a UTF-16 string pointer by a certain number of Unicode code points, stopping at end of string +//----------------------------------------------------------------------------- +uchar16 *Q_UnicodeAdvance( uchar16 *pUTF16, int nChars ) +{ + while ( nChars > 0 && *pUTF16 ) + { + uchar32 uVal; + bool bError; + pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError ); + --nChars; + } + return pUTF16; +} + +//----------------------------------------------------------------------------- +// Purpose: Advance a UTF-32 string pointer by a certain number of Unicode code points, stopping at end of string +//----------------------------------------------------------------------------- +uchar32 *Q_UnicodeAdvance( uchar32 *pUTF32, int nChars ) +{ + while ( nChars > 0 && *pUTF32 ) + { + ++pUTF32; + --nChars; + } + return pUTF32; +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF8ToUTF16( const char *pUTF8, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< char, uchar16, true, Q_UTF8ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF8, 0, pUTF16, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF8ToUTF32( const char *pUTF8, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< char, uchar32, true, Q_UTF8ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF8, 0, pUTF32, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF16ToUTF8( const uchar16 *pUTF16, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar16, char, true, Q_UTF16ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF16, 0, pUTF8, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF16ToUTF32( const uchar16 *pUTF16, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar16, uchar32, true, Q_UTF16ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF16, 0, pUTF32, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF32ToUTF8( const uchar32 *pUTF32, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, char, true, Q_UTF32ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF32, 0, pUTF8, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF32ToUTF16( const uchar32 *pUTF32, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, uchar16, true, Q_UTF32ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF32, 0, pUTF16, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF32ToUTF32( const uchar32 *pUTF32Source, uchar32 *pUTF32Dest, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, uchar32, true, Q_UTF32ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF32Source, 0, pUTF32Dest, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF8CharsToUTF16( const char *pUTF8, int nElements, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< char, uchar16, false, Q_UTF8ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF8, nElements, pUTF16, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF8CharsToUTF32( const char *pUTF8, int nElements, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< char, uchar32, false, Q_UTF8ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF8, nElements, pUTF32, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF16CharsToUTF8( const uchar16 *pUTF16, int nElements, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar16, char, false, Q_UTF16ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF16, nElements, pUTF8, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF16CharsToUTF32( const uchar16 *pUTF16, int nElements, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar16, uchar32, false, Q_UTF16ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF16, nElements, pUTF32, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF32CharsToUTF8( const uchar32 *pUTF32, int nElements, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, char, false, Q_UTF32ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF32, nElements, pUTF8, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL. +//----------------------------------------------------------------------------- +int Q_UTF32CharsToUTF16( const uchar32 *pUTF32, int nElements, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, uchar16, false, Q_UTF32ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF32, nElements, pUTF16, cubDestSizeInBytes, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Repair a UTF-8 string by removing or replacing invalid seqeuences. Returns non-zero on success. +//----------------------------------------------------------------------------- +int Q_UnicodeRepair( char *pUTF8, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< char, char, true, Q_UTF8ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF8, 0, pUTF8, INT_MAX, ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Repair a UTF-16 string by removing or replacing invalid seqeuences. Returns non-zero on success. +//----------------------------------------------------------------------------- +int Q_UnicodeRepair( uchar16 *pUTF16, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar16, uchar16, true, Q_UTF16ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF16, 0, pUTF16, INT_MAX/sizeof(uchar16), ePolicy ); +} + +//----------------------------------------------------------------------------- +// Purpose: Repair a UTF-32 string by removing or replacing invalid seqeuences. Returns non-zero on success. +//----------------------------------------------------------------------------- +int Q_UnicodeRepair( uchar32 *pUTF32, EStringConvertErrorPolicy ePolicy ) +{ + return Q_UnicodeConvertT< uchar32, uchar32, true, Q_UTF32ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF32, 0, pUTF32, INT_MAX/sizeof(uchar32), ePolicy ); +} + diff --git a/mp/src/tier1/tier1.vpc b/mp/src/tier1/tier1.vpc index bc3438a7..6f163a8b 100644 --- a/mp/src/tier1/tier1.vpc +++ b/mp/src/tier1/tier1.vpc @@ -64,6 +64,7 @@ $Project "tier1" $File "reliabletimer.cpp" $File "stringpool.cpp" $File "strtools.cpp" + $File "strtools_unicode.cpp" $File "tier1.cpp" $File "tokenreader.cpp" $File "sparsematrix.cpp" @@ -79,6 +80,15 @@ $Project "tier1" $File "snappy-stubs-internal.cpp" } + // Select bits from the LZMA SDK to support lzmaDecoder.h + // Encoding support requires the full lzma project + $Folder "LZMA Decompression Support" + { + $File "$SRCDIR\utils\lzma\C\LzmaDec.h" + $File "$SRCDIR\utils\lzma\C\LzmaDec.c" + $File "$SRCDIR\utils\lzma\C\7zTypes.h" + } + $Folder "Header Files" { $Folder "Internal Header Files" diff --git a/mp/src/tier1/uniqueid.cpp b/mp/src/tier1/uniqueid.cpp index 0d51c4cf..d75e4fd9 100644 --- a/mp/src/tier1/uniqueid.cpp +++ b/mp/src/tier1/uniqueid.cpp @@ -163,7 +163,7 @@ bool Unserialize( CUtlBuffer &buf, UniqueId_t &dest ) { int nTextLen = buf.PeekStringLength(); char *pBuf = (char*)stackalloc( nTextLen ); - buf.GetString( pBuf, nTextLen ); + buf.GetStringManualCharCount( pBuf, nTextLen ); UniqueIdFromString( &dest, pBuf, nTextLen ); } else diff --git a/mp/src/tier1/utlbuffer.cpp b/mp/src/tier1/utlbuffer.cpp index 55dd8f6b..fc89d773 100644 --- a/mp/src/tier1/utlbuffer.cpp +++ b/mp/src/tier1/utlbuffer.cpp @@ -607,17 +607,19 @@ int CUtlBuffer::PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActu //----------------------------------------------------------------------------- // Reads a null-terminated string //----------------------------------------------------------------------------- -void CUtlBuffer::GetString( char* pString, int nMaxChars ) +void CUtlBuffer::GetStringInternal( char *pString, size_t maxLenInChars ) { - if (!IsValid()) + if ( !IsValid() ) { *pString = 0; return; } - if ( nMaxChars == 0 ) + Assert( maxLenInChars != 0 ); + + if ( maxLenInChars == 0 ) { - nMaxChars = INT_MAX; + return; } // Remember, this *includes* the null character @@ -629,24 +631,21 @@ void CUtlBuffer::GetString( char* pString, int nMaxChars ) EatWhiteSpace(); } - if ( nLen == 0 ) + if ( nLen <= 0 ) { *pString = 0; m_Error |= GET_OVERFLOW; return; } - - // Strip off the terminating NULL - if ( nLen <= nMaxChars ) + + const size_t nCharsToRead = min( (size_t)nLen, maxLenInChars ) - 1; + + Get( pString, nCharsToRead ); + pString[nCharsToRead] = 0; + + if ( (size_t)nLen > (nCharsToRead + 1) ) { - Get( pString, nLen - 1 ); - pString[ nLen - 1 ] = 0; - } - else - { - Get( pString, nMaxChars - 1 ); - pString[ nMaxChars - 1 ] = 0; - SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars ); + SeekGet( SEEK_CURRENT, nLen - (nCharsToRead + 1) ); } // Read the terminating NULL in binary formats @@ -731,7 +730,7 @@ void CUtlBuffer::GetDelimitedString( CUtlCharConversion *pConv, char *pString, i { if ( !IsText() || !pConv ) { - GetString( pString, nMaxChars ); + GetStringInternal( pString, nMaxChars ); return; } @@ -1041,7 +1040,7 @@ int CUtlBuffer::VaScanf( const char* pFmt, va_list list ) case 's': { char* s = va_arg( list, char * ); - GetString( s ); + GetStringInternal( s, 256 ); } break; diff --git a/mp/src/utils/common/bsplib.cpp b/mp/src/utils/common/bsplib.cpp index c3ad433e..cadf7af5 100644 --- a/mp/src/utils/common/bsplib.cpp +++ b/mp/src/utils/common/bsplib.cpp @@ -26,11 +26,13 @@ #include "tier0/dbg.h" #include "lumpfiles.h" #include "vtf/vtf.h" +#include "lzma/lzma.h" +#include "tier1/lzmaDecoder.h" //============================================================================= // Boundary each lump should be aligned to -#define LUMP_ALIGNMENT 4 +#define LUMP_ALIGNMENT 4 // Data descriptions for byte swapping - only needed // for structures that are written to file for use by the game. @@ -45,7 +47,7 @@ BEGIN_BYTESWAP_DATADESC( lump_t ) DEFINE_FIELD( fileofs, FIELD_INTEGER ), DEFINE_FIELD( filelen, FIELD_INTEGER ), DEFINE_FIELD( version, FIELD_INTEGER ), - DEFINE_ARRAY( fourCC, FIELD_CHARACTER, 4 ), + DEFINE_FIELD( uncompressedSize, FIELD_INTEGER ), END_BYTESWAP_DATADESC() BEGIN_BYTESWAP_DATADESC( dflagslump_t ) @@ -815,9 +817,10 @@ void ClearPakFile( IZip *pak ) // Input : *relativename - // *fullpath - //----------------------------------------------------------------------------- -void AddFileToPak( IZip *pak, const char *relativename, const char *fullpath ) +void AddFileToPak( IZip *pak, const char *relativename, const char *fullpath, IZip::eCompressionType compressionType ) { - pak->AddFileToZip( relativename, fullpath ); + DevMsg( "Adding file to pakfile [ %s ]\n", fullpath ); + pak->AddFileToZip( relativename, fullpath, compressionType ); } //----------------------------------------------------------------------------- @@ -826,9 +829,65 @@ void AddFileToPak( IZip *pak, const char *relativename, const char *fullpath ) // *data - // length - //----------------------------------------------------------------------------- -void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode ) +void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType ) { - pak->AddBufferToZip( pRelativeName, data, length, bTextMode ); + pak->AddBufferToZip( pRelativeName, data, length, bTextMode, compressionType ); +} + +//----------------------------------------------------------------------------- +// Purpose: Add entire directory to .bsp PAK lump as named file +// Input : *relativename - +// *data - +// length - +//----------------------------------------------------------------------------- +void AddDirToPak( IZip *pak, const char *pDirPath, const char *pPakPrefix ) +{ + if ( !g_pFullFileSystem->IsDirectory( pDirPath ) ) + { + Warning( "Passed non-directory to AddDirToPak [ %s ]\n", pDirPath ); + return; + } + + DevMsg( "Adding directory to pakfile [ %s ]\n", pDirPath ); + + // Enumerate dir + char szEnumerateDir[MAX_PATH] = { 0 }; + V_snprintf( szEnumerateDir, sizeof( szEnumerateDir ), "%s/*.*", pDirPath ); + V_FixSlashes( szEnumerateDir ); + + FileFindHandle_t handle; + const char *szFindResult = g_pFullFileSystem->FindFirst( szEnumerateDir, &handle ); + do + { + if ( szFindResult[0] != '.' ) + { + char szPakName[MAX_PATH] = { 0 }; + char szFullPath[MAX_PATH] = { 0 }; + if ( pPakPrefix ) + { + V_snprintf( szPakName, sizeof( szPakName ), "%s/%s", pPakPrefix, szFindResult ); + } + else + { + V_strncpy( szPakName, szFindResult, sizeof( szPakName ) ); + } + V_snprintf( szFullPath, sizeof( szFullPath ), "%s/%s", pDirPath, szFindResult ); + V_FixDoubleSlashes( szFullPath ); + V_FixDoubleSlashes( szPakName ); + + if ( g_pFullFileSystem->FindIsDirectory( handle ) ) + { + // Recurse + AddDirToPak( pak, szFullPath, szPakName ); + } + else + { + // Just add this file + AddFileToPak( pak, szPakName, szFullPath ); + } + } + szFindResult = g_pFullFileSystem->FindNext( handle ); + } while ( szFindResult); } //----------------------------------------------------------------------------- @@ -1290,14 +1349,11 @@ static void AddOcclusionLump( ) 3 * sizeof(int); lump_t *lump = &g_pBSPHeader->lumps[LUMP_OCCLUSION]; - + lump->fileofs = g_pFileSystem->Tell( g_hBSPFile ); lump->filelen = nLumpLength; lump->version = LUMP_OCCLUSION_VERSION; - lump->fourCC[0] = ( char )0; - lump->fourCC[1] = ( char )0; - lump->fourCC[2] = ( char )0; - lump->fourCC[3] = ( char )0; + lump->uncompressedSize = 0; // Data is swapped in place, so the 'Count' variables aren't safe to use after they're written WriteData( FIELD_INTEGER, &nOccluderCount ); @@ -2484,14 +2540,11 @@ static void AddLumpInternal( int lumpnum, void *data, int len, int version ) g_Lumps.size[lumpnum] = 0; // mark it written lump = &g_pBSPHeader->lumps[lumpnum]; - + lump->fileofs = g_pFileSystem->Tell( g_hBSPFile ); lump->filelen = len; lump->version = version; - lump->fourCC[0] = ( char )0; - lump->fourCC[1] = ( char )0; - lump->fourCC[2] = ( char )0; - lump->fourCC[3] = ( char )0; + lump->uncompressedSize = 0; SafeWrite( g_hBSPFile, data, len ); @@ -3705,19 +3758,6 @@ void BuildClusterTable( void ) } } -// There's a version of this in host.cpp!!! Make sure that they match. -void GetPlatformMapPath( const char *pMapPath, char *pPlatformMapPath, int dxlevel, int maxLength ) -{ - Q_StripExtension( pMapPath, pPlatformMapPath, maxLength ); - -// if( dxlevel <= 60 ) -// { -// Q_strncat( pPlatformMapPath, "_dx60", maxLength, COPY_ALL_CHARACTERS ); -// } - - Q_strncat( pPlatformMapPath, ".bsp", maxLength, COPY_ALL_CHARACTERS ); -} - // There's a version of this in checksum_engine.cpp!!! Make sure that they match. static bool CRC_MapFile(CRC32_t *crcvalue, const char *pszFileName) { @@ -3979,7 +4019,7 @@ void ConvertPakFileContents( const char *pInFilename ) if ( !bConverted ) { // straight copy - AddBufferToPak( newPakFile, relativeName, sourceBuf.Base(), sourceBuf.TellMaxPut(), false ); + AddBufferToPak( newPakFile, relativeName, sourceBuf.Base(), sourceBuf.TellMaxPut(), false, IZip::eCompressionType_None ); } else { @@ -3987,7 +4027,7 @@ void ConvertPakFileContents( const char *pInFilename ) V_StripExtension( relativeName, relativeName, sizeof( relativeName ) ); V_strcat( relativeName, ".360", sizeof( relativeName ) ); V_strcat( relativeName, pExt, sizeof( relativeName ) ); - AddBufferToPak( newPakFile, relativeName, targetBuf.Base(), targetBuf.TellMaxPut(), false ); + AddBufferToPak( newPakFile, relativeName, targetBuf.Base(), targetBuf.TellMaxPut(), false, IZip::eCompressionType_None ); } if ( V_stristr( relativeName, ".hdr" ) || V_stristr( relativeName, "_hdr" ) ) @@ -4407,21 +4447,28 @@ bool CompressGameLump( dheader_t *pInBSPHeader, dheader_t *pOutBSPHeader, CUtlBu dgamelumpheader_t* pInGameLumpHeader = (dgamelumpheader_t*)(((byte *)pInBSPHeader) + pInBSPHeader->lumps[LUMP_GAME_LUMP].fileofs); dgamelump_t* pInGameLump = (dgamelump_t*)(pInGameLumpHeader + 1); - byteSwap.ActivateByteSwapping( true ); - byteSwap.SwapFieldsToTargetEndian( pInGameLumpHeader ); - byteSwap.SwapFieldsToTargetEndian( pInGameLump, pInGameLumpHeader->lumpCount ); + if ( IsX360() ) + { + byteSwap.ActivateByteSwapping( true ); + byteSwap.SwapFieldsToTargetEndian( pInGameLumpHeader ); + byteSwap.SwapFieldsToTargetEndian( pInGameLump, pInGameLumpHeader->lumpCount ); + } unsigned int newOffset = outputBuffer.TellPut(); - outputBuffer.Put( pInGameLumpHeader, sizeof( dgamelumpheader_t ) ); - outputBuffer.Put( pInGameLump, pInGameLumpHeader->lumpCount * sizeof( dgamelump_t ) ); + // Make room for gamelump header and gamelump structs, which we'll write at the end + outputBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, sizeof( dgamelumpheader_t ) ); + outputBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, pInGameLumpHeader->lumpCount * sizeof( dgamelump_t ) ); - dgamelumpheader_t* pOutGameLumpHeader = (dgamelumpheader_t*)((byte *)outputBuffer.Base() + newOffset); - dgamelump_t* pOutGameLump = (dgamelump_t*)(pOutGameLumpHeader + 1); + // Start with input lumps, and fixup + dgamelumpheader_t sOutGameLumpHeader = *pInGameLumpHeader; + CUtlBuffer sOutGameLumpBuf; + sOutGameLumpBuf.Put( pInGameLump, pInGameLumpHeader->lumpCount * sizeof( dgamelump_t ) ); + dgamelump_t *sOutGameLump = (dgamelump_t *)sOutGameLumpBuf.Base(); // add a dummy terminal gamelump // purposely NOT updating the .filelen to reflect the compressed size, but leaving as original size // callers use the next entry offset to determine compressed size - pOutGameLumpHeader->lumpCount++; + sOutGameLumpHeader.lumpCount++; dgamelump_t dummyLump = { 0 }; outputBuffer.Put( &dummyLump, sizeof( dgamelump_t ) ); @@ -4430,62 +4477,130 @@ bool CompressGameLump( dheader_t *pInBSPHeader, dheader_t *pOutBSPHeader, CUtlBu CUtlBuffer inputBuffer; CUtlBuffer compressedBuffer; - pOutGameLump[i].fileofs = AlignBuffer( outputBuffer, 4 ); + sOutGameLump[i].fileofs = AlignBuffer( outputBuffer, 4 ); if ( pInGameLump[i].filelen ) { - inputBuffer.SetExternalBuffer( ((byte *)pInBSPHeader) + pInGameLump[i].fileofs, pInGameLump[i].filelen, pInGameLump[i].filelen ); + if ( pInGameLump[i].flags & GAMELUMPFLAG_COMPRESSED ) + { + byte *pCompressedLump = ((byte *)pInBSPHeader) + pInGameLump[i].fileofs; + if ( CLZMA::IsCompressed( pCompressedLump ) ) + { + inputBuffer.EnsureCapacity( CLZMA::GetActualSize( pCompressedLump ) ); + unsigned int outSize = CLZMA::Uncompress( pCompressedLump, (unsigned char *)inputBuffer.Base() ); + inputBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, outSize ); + if ( outSize != CLZMA::GetActualSize( pCompressedLump ) ) + { + Warning( "Decompressed size differs from header, BSP may be corrupt\n" ); + } + } + else + { + Assert( CLZMA::IsCompressed( pCompressedLump ) ); + Warning( "Unsupported BSP: Unrecognized compressed game lump\n" ); + } - bool bCompressed = pCompressFunc( inputBuffer, compressedBuffer ); + } + else + { + inputBuffer.SetExternalBuffer( ((byte *)pInBSPHeader) + pInGameLump[i].fileofs, + pInGameLump[i].filelen, pInGameLump[i].filelen ); + } + + bool bCompressed = pCompressFunc ? pCompressFunc( inputBuffer, compressedBuffer ) : false; if ( bCompressed ) { - pOutGameLump[i].flags |= GAMELUMPFLAG_COMPRESSED; + sOutGameLump[i].flags |= GAMELUMPFLAG_COMPRESSED; outputBuffer.Put( compressedBuffer.Base(), compressedBuffer.TellPut() ); compressedBuffer.Purge(); } else { - // as is + // as is, clear compression flag from input lump + sOutGameLump[i].flags &= ~GAMELUMPFLAG_COMPRESSED; outputBuffer.Put( inputBuffer.Base(), inputBuffer.TellPut() ); } } } // fix the dummy terminal lump - int lastLump = pOutGameLumpHeader->lumpCount-1; - pOutGameLump[lastLump].fileofs = outputBuffer.TellPut(); + int lastLump = sOutGameLumpHeader.lumpCount-1; + sOutGameLump[lastLump].fileofs = outputBuffer.TellPut(); - // fix the output for 360, swapping it back - byteSwap.SwapFieldsToTargetEndian( pOutGameLump, pOutGameLumpHeader->lumpCount ); - byteSwap.SwapFieldsToTargetEndian( pOutGameLumpHeader ); + if ( IsX360() ) + { + // fix the output for 360, swapping it back + byteSwap.SwapFieldsToTargetEndian( sOutGameLump, sOutGameLumpHeader.lumpCount ); + byteSwap.SwapFieldsToTargetEndian( &sOutGameLumpHeader ); + } pOutBSPHeader->lumps[LUMP_GAME_LUMP].fileofs = newOffset; pOutBSPHeader->lumps[LUMP_GAME_LUMP].filelen = outputBuffer.TellPut() - newOffset; + // We set GAMELUMPFLAG_COMPRESSED and handle compression at the sub-lump level, this whole lump is not + // decompressable as a block. + pOutBSPHeader->lumps[LUMP_GAME_LUMP].uncompressedSize = 0; + + // Rewind to start and write lump headers + unsigned int endOffset = outputBuffer.TellPut(); + outputBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, newOffset ); + outputBuffer.Put( &sOutGameLumpHeader, sizeof( dgamelumpheader_t ) ); + outputBuffer.Put( sOutGameLumpBuf.Base(), sOutGameLumpBuf.TellPut() ); + outputBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, endOffset ); return true; } -bool CompressBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFunc_t pCompressFunc ) +//----------------------------------------------------------------------------- +// Compress callback for RepackBSP +//----------------------------------------------------------------------------- +bool RepackBSPCallback_LZMA( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer ) { - CByteswap byteSwap; - - dheader_t *pInBSPHeader = (dheader_t *)inputBuffer.Base(); - if ( pInBSPHeader->ident != BigLong( IDBSPHEADER ) || !pCompressFunc ) + if ( !inputBuffer.TellPut() ) { - // only compress 360 bsp's + // nothing to do return false; } - // bsp is 360, swap the header back - byteSwap.ActivateByteSwapping( true ); - byteSwap.SwapFieldsToTargetEndian( pInBSPHeader ); + unsigned int originalSize = inputBuffer.TellPut() - inputBuffer.TellGet(); + unsigned int compressedSize = 0; + unsigned char *pCompressedOutput = LZMA_Compress( (unsigned char *)inputBuffer.Base() + inputBuffer.TellGet(), + originalSize, &compressedSize ); + if ( pCompressedOutput ) + { + outputBuffer.Put( pCompressedOutput, compressedSize ); + DevMsg( "Compressed bsp lump %u -> %u bytes\n", originalSize, compressedSize ); + free( pCompressedOutput ); + return true; + } - // output will be smaller, use input size as upper bound - outputBuffer.EnsureCapacity( inputBuffer.TellMaxPut() ); + return false; +} + + +bool RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFunc_t pCompressFunc, IZip::eCompressionType packfileCompression ) +{ + dheader_t *pInBSPHeader = (dheader_t *)inputBuffer.Base(); + // The 360 swaps this header to disk. For some reason. + if ( pInBSPHeader->ident != ( IsX360() ? BigLong( IDBSPHEADER ) : IDBSPHEADER ) ) + { + Warning( "RepackBSP given invalid input data\n" ); + return false; + } + + CByteswap byteSwap; + if ( IsX360() ) + { + // bsp is 360, swap the header back + byteSwap.ActivateByteSwapping( true ); + byteSwap.SwapFieldsToTargetEndian( pInBSPHeader ); + } + + unsigned int headerOffset = outputBuffer.TellPut(); outputBuffer.Put( pInBSPHeader, sizeof( dheader_t ) ); - dheader_t *pOutBSPHeader = (dheader_t *)outputBuffer.Base(); + // This buffer grows dynamically, don't keep pointers to it around. Write out header at end. + dheader_t sOutBSPHeader = *pInBSPHeader; // must adhere to input lump's offset order and process according to that, NOT lump num // sort by offset order @@ -4504,12 +4619,13 @@ bool CompressBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFun SortedLump_t *pSortedLump = &sortedLumps[i]; int lumpNum = pSortedLump->lumpNum; - if ( !pSortedLump->pLump->filelen ) - { - // degenerate - pOutBSPHeader->lumps[lumpNum].fileofs = 0; - } - else + // Should be set below, don't copy over old data + sOutBSPHeader.lumps[lumpNum].fileofs = 0; + sOutBSPHeader.lumps[lumpNum].filelen = 0; + // Only set by compressed lumps + sOutBSPHeader.lumps[lumpNum].uncompressedSize = 0; + + if ( pSortedLump->pLump->filelen ) // Otherwise its degenerate { int alignment = 4; if ( lumpNum == LUMP_PAKFILE ) @@ -4518,49 +4634,114 @@ bool CompressBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFun } unsigned int newOffset = AlignBuffer( outputBuffer, alignment ); - // only set by compressed lumps, hides the uncompressed size - *((unsigned int *)pOutBSPHeader->lumps[lumpNum].fourCC) = 0; - CUtlBuffer inputBuffer; - inputBuffer.SetExternalBuffer( ((byte *)pInBSPHeader) + pSortedLump->pLump->fileofs, pSortedLump->pLump->filelen, pSortedLump->pLump->filelen ); + if ( pSortedLump->pLump->uncompressedSize ) + { + byte *pCompressedLump = ((byte *)pInBSPHeader) + pSortedLump->pLump->fileofs; + if ( CLZMA::IsCompressed( pCompressedLump ) && pSortedLump->pLump->uncompressedSize == CLZMA::GetActualSize( pCompressedLump ) ) + { + inputBuffer.EnsureCapacity( CLZMA::GetActualSize( pCompressedLump ) ); + unsigned int outSize = CLZMA::Uncompress( pCompressedLump, (unsigned char *)inputBuffer.Base() ); + inputBuffer.SeekPut( CUtlBuffer::SEEK_CURRENT, outSize ); + if ( outSize != pSortedLump->pLump->uncompressedSize ) + { + Warning( "Decompressed size differs from header, BSP may be corrupt\n" ); + } + } + else + { + Assert( CLZMA::IsCompressed( pCompressedLump ) && + pSortedLump->pLump->uncompressedSize == CLZMA::GetActualSize( pCompressedLump ) ); + Warning( "Unsupported BSP: Unrecognized compressed lump\n" ); + } + } + else + { + // Just use input + inputBuffer.SetExternalBuffer( ((byte *)pInBSPHeader) + pSortedLump->pLump->fileofs, + pSortedLump->pLump->filelen, pSortedLump->pLump->filelen ); + } if ( lumpNum == LUMP_GAME_LUMP ) { // the game lump has to have each of its components individually compressed - CompressGameLump( pInBSPHeader, pOutBSPHeader, outputBuffer, pCompressFunc ); + CompressGameLump( pInBSPHeader, &sOutBSPHeader, outputBuffer, pCompressFunc ); } else if ( lumpNum == LUMP_PAKFILE ) { - // add as is - pOutBSPHeader->lumps[lumpNum].fileofs = newOffset; - outputBuffer.Put( inputBuffer.Base(), inputBuffer.TellPut() ); + IZip *newPakFile = IZip::CreateZip( NULL ); + IZip *oldPakFile = IZip::CreateZip( NULL ); + oldPakFile->ParseFromBuffer( inputBuffer.Base(), inputBuffer.Size() ); + + int id = -1; + int fileSize; + while ( 1 ) + { + char relativeName[MAX_PATH]; + id = GetNextFilename( oldPakFile, id, relativeName, sizeof( relativeName ), fileSize ); + if ( id == -1 ) + break; + + CUtlBuffer sourceBuf; + CUtlBuffer targetBuf; + + bool bOK = ReadFileFromPak( oldPakFile, relativeName, false, sourceBuf ); + if ( !bOK ) + { + Error( "Failed to load '%s' from lump pak for repacking.\n", relativeName ); + continue; + } + + AddBufferToPak( newPakFile, relativeName, sourceBuf.Base(), sourceBuf.TellMaxPut(), false, packfileCompression ); + + DevMsg( "Repacking BSP: Created '%s' in lump pak\n", relativeName ); + } + + // save new pack to buffer + newPakFile->SaveToBuffer( outputBuffer ); + sOutBSPHeader.lumps[lumpNum].fileofs = newOffset; + sOutBSPHeader.lumps[lumpNum].filelen = outputBuffer.TellPut() - newOffset; + // Note that this *lump* is uncompressed, it just contains a packfile that uses compression, so we're + // not setting lumps[lumpNum].uncompressedSize + + IZip::ReleaseZip( oldPakFile ); + IZip::ReleaseZip( newPakFile ); } else { CUtlBuffer compressedBuffer; - bool bCompressed = pCompressFunc( inputBuffer, compressedBuffer ); + bool bCompressed = pCompressFunc ? pCompressFunc( inputBuffer, compressedBuffer ) : false; if ( bCompressed ) { - // placing the uncompressed size in the unused fourCC, will decode at runtime - *((unsigned int *)pOutBSPHeader->lumps[lumpNum].fourCC) = BigLong( inputBuffer.TellPut() ); - pOutBSPHeader->lumps[lumpNum].filelen = compressedBuffer.TellPut(); - pOutBSPHeader->lumps[lumpNum].fileofs = newOffset; + sOutBSPHeader.lumps[lumpNum].uncompressedSize = inputBuffer.TellPut(); + sOutBSPHeader.lumps[lumpNum].filelen = compressedBuffer.TellPut(); + sOutBSPHeader.lumps[lumpNum].fileofs = newOffset; outputBuffer.Put( compressedBuffer.Base(), compressedBuffer.TellPut() ); compressedBuffer.Purge(); } else { // add as is - pOutBSPHeader->lumps[lumpNum].fileofs = newOffset; + sOutBSPHeader.lumps[lumpNum].fileofs = newOffset; + sOutBSPHeader.lumps[lumpNum].filelen = inputBuffer.TellPut(); outputBuffer.Put( inputBuffer.Base(), inputBuffer.TellPut() ); } } } } - // fix the output for 360, swapping it back - byteSwap.SetTargetBigEndian( true ); - byteSwap.SwapFieldsToTargetEndian( pOutBSPHeader ); + if ( IsX360() ) + { + // fix the output for 360, swapping it back + byteSwap.SetTargetBigEndian( true ); + byteSwap.SwapFieldsToTargetEndian( &sOutBSPHeader ); + } + + // Write out header + unsigned int endOffset = outputBuffer.TellPut(); + outputBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, headerOffset ); + outputBuffer.Put( &sOutBSPHeader, sizeof( sOutBSPHeader ) ); + outputBuffer.SeekPut( CUtlBuffer::SEEK_HEAD, endOffset ); return true; } @@ -4768,12 +4949,12 @@ bool SwapBSPFile( const char *pInFilename, const char *pOutFilename, bool bSwapO } CUtlBuffer outputBuffer; - if ( !CompressBSP( inputBuffer, outputBuffer, pCompressFunc ) ) + if ( !RepackBSP( inputBuffer, outputBuffer, pCompressFunc, IZip::eCompressionType_None ) ) { - Warning( "Error! Failed to compress BSP '%s'!\n", pOutFilename ); + Warning( "Error! Failed to compress BSP '%s'!\n", pOutFilename ); return false; } - + g_hBSPFile = SafeOpenWrite( pOutFilename ); if ( !g_hBSPFile ) { diff --git a/mp/src/utils/common/bsplib.h b/mp/src/utils/common/bsplib.h index 80952ba9..f7e50f3f 100644 --- a/mp/src/utils/common/bsplib.h +++ b/mp/src/utils/common/bsplib.h @@ -14,7 +14,7 @@ #pragma once #endif - +#include "zip_utils.h" #include "bspfile.h" #include "utlvector.h" #include "utlstring.h" @@ -196,8 +196,9 @@ extern int g_PhysDispSize; IZip *GetPakFile( void ); IZip *GetSwapPakFile( void ); void ClearPakFile( IZip *pak ); -void AddFileToPak( IZip *pak, const char *pRelativeName, const char *fullpath ); -void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode ); +void AddFileToPak( IZip *pak, const char *pRelativeName, const char *fullpath, IZip::eCompressionType compressionType = IZip::eCompressionType_None ); +void AddBufferToPak( IZip *pak, const char *pRelativeName, void *data, int length, bool bTextMode, IZip::eCompressionType compressionType = IZip::eCompressionType_None ); +void AddDirToPak( IZip *pak, const char *pDirPath, const char *pPakPrefix = NULL ); bool FileExistsInPak( IZip *pak, const char *pRelativeName ); bool ReadFileFromPak( IZip *pak, const char *pRelativeName, bool bTextMode, CUtlBuffer &buf ); void RemoveFileFromPak( IZip *pak, const char *pRelativeName ); @@ -295,7 +296,11 @@ void WriteBSPFile( const char *filename, char *pUnused = NULL ); void PrintBSPFileSizes(void); void PrintBSPPackDirectory(void); void ReleasePakFileLumps(void); + +bool RepackBSPCallback_LZMA( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer ); +bool RepackBSP( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer, CompressFunc_t pCompressFunc, IZip::eCompressionType packfileCompression ); bool SwapBSPFile( const char *filename, const char *swapFilename, bool bSwapOnLoad, VTFConvertFunc_t pVTFConvertFunc, VHVFixupFunc_t pVHVFixupFunc, CompressFunc_t pCompressFunc ); + bool GetPakFileLump( const char *pBSPFilename, void **pPakData, int *pPakSize ); bool SetPakFileLump( const char *pBSPFilename, const char *pNewFilename, void *pPakData, int pakSize ); void WriteLumpToFile( char *filename, int lump ); @@ -382,8 +387,6 @@ extern CUtlVector g_ClusterLeaves; // Call this to build the mapping from cluster to leaves void BuildClusterTable( ); -void GetPlatformMapPath( const char *pMapPath, char *pPlatformMapPath, int dxlevel, int maxLength ); - void SetHDRMode( bool bHDR ); // ----------------------------------------------------------------------------- // diff --git a/mp/src/utils/common/filesystem_tools.cpp b/mp/src/utils/common/filesystem_tools.cpp index b1306c59..9401c4ad 100644 --- a/mp/src/utils/common/filesystem_tools.cpp +++ b/mp/src/utils/common/filesystem_tools.cpp @@ -84,9 +84,6 @@ bool FileSystem_Init_Normal( const char *pFilename, FSInitType_t initType, bool if ( FileSystem_GetFileSystemDLLName( fileSystemDLLName, MAX_PATH, bSteam ) != FS_OK ) return false; - // If we're under Steam we need extra setup to let us find the proper modules - FileSystem_SetupSteamInstallPath(); - // Next, load the module, call Connect/Init. CFSLoadModuleInfo loadModuleInfo; loadModuleInfo.m_pFileSystemDLLName = fileSystemDLLName; diff --git a/mp/src/utils/lzma/C/7z.h b/mp/src/utils/lzma/C/7z.h new file mode 100644 index 00000000..ca4a2233 --- /dev/null +++ b/mp/src/utils/lzma/C/7z.h @@ -0,0 +1,216 @@ +/* 7z.h -- 7z interface +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_H +#define __7Z_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define k7zStartHeaderSize 0x20 +#define k7zSignatureSize 6 + +extern Byte k7zSignature[k7zSignatureSize]; + +typedef struct +{ + const Byte *Data; + size_t Size; +} CSzData; + +/* CSzCoderInfo & CSzFolder support only default methods */ + +typedef struct +{ + size_t PropsOffset; + UInt32 MethodID; + Byte NumInStreams; + Byte NumOutStreams; + Byte PropsSize; +} CSzCoderInfo; + +typedef struct +{ + UInt32 InIndex; + UInt32 OutIndex; +} CSzBindPair; + +#define SZ_NUM_CODERS_IN_FOLDER_MAX 4 +#define SZ_NUM_BINDS_IN_FOLDER_MAX 3 +#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4 +#define SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX 4 + +typedef struct +{ + UInt32 NumCoders; + UInt32 NumBindPairs; + UInt32 NumPackStreams; + UInt32 MainOutStream; + UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX]; + CSzBindPair BindPairs[SZ_NUM_BINDS_IN_FOLDER_MAX]; + CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX]; + UInt64 CodersUnpackSizes[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX]; +} CSzFolder; + +/* +typedef struct +{ + size_t CodersDataOffset; + size_t UnpackSizeDataOffset; + // UInt32 StartCoderUnpackSizesIndex; + UInt32 StartPackStreamIndex; + // UInt32 IndexOfMainOutStream; +} CSzFolder2; +*/ + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes); + +typedef struct +{ + UInt32 Low; + UInt32 High; +} CNtfsFileTime; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + UInt32 *Vals; +} CSzBitUi32s; + +typedef struct +{ + Byte *Defs; /* MSB 0 bit numbering */ + // UInt64 *Vals; + CNtfsFileTime *Vals; +} CSzBitUi64s; + +#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0) + +typedef struct +{ + UInt32 NumPackStreams; + UInt32 NumFolders; + + UInt64 *PackPositions; // NumPackStreams + 1 + CSzBitUi32s FolderCRCs; + + size_t *FoCodersOffsets; + size_t *FoSizesOffsets; + // UInt32 StartCoderUnpackSizesIndex; + UInt32 *FoStartPackStreamIndex; + + // CSzFolder2 *Folders; // +1 item for sum values + Byte *CodersData; + Byte *UnpackSizesData; + size_t UnpackSizesDataSize; + // UInt64 *CoderUnpackSizes; +} CSzAr; + + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *stream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAlloc *allocMain); + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +typedef struct +{ + CSzAr db; + + UInt64 startPosAfterHeader; + UInt64 dataPos; + + UInt32 NumFiles; + + UInt64 *UnpackPositions; + // Byte *IsEmptyFiles; + Byte *IsDirs; + CSzBitUi32s CRCs; + + CSzBitUi32s Attribs; + // CSzBitUi32s Parents; + CSzBitUi64s MTime; + CSzBitUi64s CTime; + + // UInt32 *FolderStartPackStreamIndex; + UInt32 *FolderStartFileIndex; // + 1 + UInt32 *FileIndexToFolderIndexMap; + + size_t *FileNameOffsets; /* in 2-byte steps */ + Byte *FileNames; /* UTF-16-LE */ +} CSzArEx; + +#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i)) + +#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i]) + +void SzArEx_Init(CSzArEx *p); +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); +UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); +int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); + +/* +if dest == NULL, the return value specifies the required size of the buffer, + in 16-bit characters, including the null-terminating character. +if dest != NULL, the return value specifies the number of 16-bit characters that + are written to the dest, including the null-terminating character. */ + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest); + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex); +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest); +*/ + +SRes SzArEx_Extract( + const CSzArEx *db, + ILookInStream *inStream, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + + +/* +SzArEx_Open Errors: +SZ_ERROR_NO_ARCHIVE +SZ_ERROR_ARCHIVE +SZ_ERROR_UNSUPPORTED +SZ_ERROR_MEM +SZ_ERROR_CRC +SZ_ERROR_INPUT_EOF +SZ_ERROR_FAIL +*/ + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAlloc *allocMain, ISzAlloc *allocTemp); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/7zAlloc.c b/mp/src/utils/lzma/C/7zAlloc.c new file mode 100644 index 00000000..97cea299 --- /dev/null +++ b/mp/src/utils/lzma/C/7zAlloc.c @@ -0,0 +1,78 @@ +/* 7zAlloc.c -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif + +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; + +#endif + +void *SzAlloc(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(void *p, size_t size) +{ + p = p; + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *p, void *address) +{ + p = p; + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/mp/src/utils/lzma/C/7zAlloc.h b/mp/src/utils/lzma/C/7zAlloc.h new file mode 100644 index 00000000..3344e937 --- /dev/null +++ b/mp/src/utils/lzma/C/7zAlloc.h @@ -0,0 +1,15 @@ +/* 7zAlloc.h -- Allocation functions +2010-10-29 : Igor Pavlov : Public domain */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include + +void *SzAlloc(void *p, size_t size); +void SzFree(void *p, void *address); + +void *SzAllocTemp(void *p, size_t size); +void SzFreeTemp(void *p, void *address); + +#endif diff --git a/mp/src/utils/lzma/C/7zArcIn.c b/mp/src/utils/lzma/C/7zArcIn.c new file mode 100644 index 00000000..cdca6564 --- /dev/null +++ b/mp/src/utils/lzma/C/7zArcIn.c @@ -0,0 +1,1839 @@ +/* 7zArcIn.c -- 7z Input functions +2014-06-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7z.h" +#include "7zBuf.h" +#include "7zCrc.h" +#include "CpuArch.h" + +#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } + +#define k7zMajorVersion 0 + +enum EIdEnum +{ + k7zIdEnd, + k7zIdHeader, + k7zIdArchiveProperties, + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + k7zIdPackInfo, + k7zIdUnpackInfo, + k7zIdSubStreamsInfo, + k7zIdSize, + k7zIdCRC, + k7zIdFolder, + k7zIdCodersUnpackSize, + k7zIdNumUnpackStream, + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + k7zIdName, + k7zIdCTime, + k7zIdATime, + k7zIdMTime, + k7zIdWinAttrib, + k7zIdComment, + k7zIdEncodedHeader, + k7zIdStartPos, + k7zIdDummy + // k7zNtSecure, + // k7zParent, + // k7zIsReal +}; + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + +#define NUM_FOLDER_CODERS_MAX 32 +#define NUM_CODER_STREAMS_MAX 32 + +/* +static int SzFolder_FindBindPairForInStream(const CSzFolder *p, UInt32 inStreamIndex) +{ + UInt32 i; + for (i = 0; i < p->NumBindPairs; i++) + if (p->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} +*/ + +#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } + +static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc) +{ + MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc); + MY_ALLOC(UInt32, p->Vals, num, alloc); + return SZ_OK; +} + +void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->Defs); p->Defs = 0; + IAlloc_Free(alloc, p->Vals); p->Vals = 0; +} + +#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; } + +void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->Defs); p->Defs = 0; + IAlloc_Free(alloc, p->Vals); p->Vals = 0; +} + +static void SzAr_Init(CSzAr *p) +{ + p->NumPackStreams = 0; + p->NumFolders = 0; + p->PackPositions = 0; + SzBitUi32s_Init(&p->FolderCRCs); + // p->Folders = 0; + p->FoCodersOffsets = 0; + p->FoSizesOffsets = 0; + p->FoStartPackStreamIndex = 0; + + p->CodersData = 0; + // p->CoderUnpackSizes = 0; + p->UnpackSizesData = 0; +} + +static void SzAr_Free(CSzAr *p, ISzAlloc *alloc) +{ + IAlloc_Free(alloc, p->UnpackSizesData); + IAlloc_Free(alloc, p->CodersData); + // IAlloc_Free(alloc, p->CoderUnpackSizes); + + IAlloc_Free(alloc, p->PackPositions); + + // IAlloc_Free(alloc, p->Folders); + IAlloc_Free(alloc, p->FoCodersOffsets); + IAlloc_Free(alloc, p->FoSizesOffsets); + IAlloc_Free(alloc, p->FoStartPackStreamIndex); + + SzBitUi32s_Free(&p->FolderCRCs, alloc); + + SzAr_Init(p); +} + + +void SzArEx_Init(CSzArEx *p) +{ + SzAr_Init(&p->db); + p->NumFiles = 0; + p->dataPos = 0; + // p->Files = 0; + p->UnpackPositions = 0; + // p->IsEmptyFiles = 0; + p->IsDirs = 0; + // p->FolderStartPackStreamIndex = 0; + // p->PackStreamStartPositions = 0; + p->FolderStartFileIndex = 0; + p->FileIndexToFolderIndexMap = 0; + p->FileNameOffsets = 0; + p->FileNames = 0; + SzBitUi32s_Init(&p->CRCs); + SzBitUi32s_Init(&p->Attribs); + // SzBitUi32s_Init(&p->Parents); + SzBitUi64s_Init(&p->MTime); + SzBitUi64s_Init(&p->CTime); +} + +void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) +{ + // IAlloc_Free(alloc, p->FolderStartPackStreamIndex); + // IAlloc_Free(alloc, p->PackStreamStartPositions); + IAlloc_Free(alloc, p->FolderStartFileIndex); + IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); + + IAlloc_Free(alloc, p->FileNameOffsets); + IAlloc_Free(alloc, p->FileNames); + + SzBitUi64s_Free(&p->CTime, alloc); + SzBitUi64s_Free(&p->MTime, alloc); + SzBitUi32s_Free(&p->CRCs, alloc); + // SzBitUi32s_Free(&p->Parents, alloc); + SzBitUi32s_Free(&p->Attribs, alloc); + IAlloc_Free(alloc, p->IsDirs); + // IAlloc_Free(alloc, p->IsEmptyFiles); + IAlloc_Free(alloc, p->UnpackPositions); + // IAlloc_Free(alloc, p->Files); + + SzAr_Free(&p->db, alloc); + SzArEx_Init(p); +} + +static int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; } + +static SRes SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++; +#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest) +#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++; + +#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); } +#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); } + +#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \ + dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4); + +static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte, mask; + unsigned i; + UInt32 v; + + SZ_READ_BYTE(firstByte); + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + return SZ_OK; + } + SZ_READ_BYTE(v); + if ((firstByte & 0x40) == 0) + { + *value = (((UInt32)firstByte & 0x3F) << 8) | v; + return SZ_OK; + } + SZ_READ_BYTE(mask); + *value = v | ((UInt32)mask << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value |= (highPart << (8 * i)); + return SZ_OK; + } + SZ_READ_BYTE(b); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +/* +static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num) +{ + for (; num != 0; num--) + { + Byte firstByte; + Byte mask; + + unsigned i; + UInt32 v; + UInt64 value; + + if (data == dataLim) + return NULL; + firstByte = *data++; + + if ((firstByte & 0x80) == 0) + { + *values++ = firstByte; + continue; + } + if (data == dataLim) + return NULL; + v = *data++; + if ((firstByte & 0x40) == 0) + { + *values++ = (((UInt32)firstByte & 0x3F) << 8) | v; + continue; + } + if (data == dataLim) + return NULL; + value = v | ((UInt32)*data++ << 8); + mask = 0x20; + for (i = 2; i < 8; i++) + { + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + value |= (highPart << (8 * i)); + break; + } + if (data == dataLim) + return NULL; + value |= ((UInt64)*data++ << (8 * i)); + mask >>= 1; + } + *values++ = value; + } + return data; +} +*/ + +static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value) +{ + Byte firstByte; + UInt64 value64; + if (sd->Size == 0) + return SZ_ERROR_ARCHIVE; + firstByte = *sd->Data; + if ((firstByte & 0x80) == 0) + { + *value = firstByte; + sd->Data++; + sd->Size--; + return SZ_OK; + } + RINOK(ReadNumber(sd, &value64)); + if (value64 >= (UInt32)0x80000000 - 1) + return SZ_ERROR_UNSUPPORTED; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4))) + return SZ_ERROR_UNSUPPORTED; + *value = (UInt32)value64; + return SZ_OK; +} + +#define ReadID(sd, value) ReadNumber(sd, value) + +static SRes SkipData(CSzData *sd) +{ + UInt64 size; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, size); + return SZ_OK; +} + +static SRes WaitId(CSzData *sd, UInt64 id) +{ + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == id) + return SZ_OK; + if (type == k7zIdEnd) + return SZ_ERROR_ARCHIVE; + RINOK(SkipData(sd)); + } +} + +static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) +{ + UInt32 numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + *v = sd->Data; + SKIP_DATA(sd, numBytes); + return SZ_OK; +} + +static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) +{ + Byte b = 0; + unsigned m = 0; + UInt32 sum = 0; + for (; numItems != 0; numItems--) + { + if (m == 0) + { + b = *bits++; + m = 8; + } + m--; + sum += ((b >> m) & 1); + } + return sum ; +} + +static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc) +{ + Byte allAreDefined; + UInt32 i; + Byte *v2; + UInt32 numBytes = (numItems + 7) >> 3; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + { + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(Byte, *v, numBytes, alloc); + memcpy(*v, sd->Data, numBytes); + SKIP_DATA(sd, numBytes); + return SZ_OK; + } + MY_ALLOC(Byte, *v, numBytes, alloc); + v2 = *v; + for (i = 0; i < numBytes; i++) + v2[i] = 0xFF; + { + unsigned numBits = (unsigned)numItems & 7; + if (numBits != 0) + v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits)); + } + return SZ_OK; +} + +static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) +{ + UInt32 i; + CSzData sd; + UInt32 *vals; + const Byte *defs; + MY_ALLOC(UInt32, crcs->Vals, numItems, alloc); + sd = *sd2; + defs = crcs->Defs; + vals = crcs->Vals; + for (i = 0; i < numItems; i++) + if (SzBitArray_Check(defs, i)) + { + SZ_READ_32(vals[i]); + } + else + vals[i] = 0; + *sd2 = sd; + return SZ_OK; +} + +static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc) +{ + SzBitUi32s_Free(crcs, alloc); + RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)); + return ReadUi32s(sd, numItems, crcs, alloc); +} + +static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems) +{ + Byte allAreDefined; + UInt32 numDefined = numItems; + RINOK(SzReadByte(sd, &allAreDefined)); + if (!allAreDefined) + { + size_t numBytes = (numItems + 7) >> 3; + if (numBytes > sd->Size) + return SZ_ERROR_ARCHIVE; + numDefined = CountDefinedBits(sd->Data, numItems); + SKIP_DATA(sd, numBytes); + } + if (numDefined > (sd->Size >> 2)) + return SZ_ERROR_ARCHIVE; + SKIP_DATA(sd, (size_t)numDefined * 4); + return SZ_OK; +} + +static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc) +{ + RINOK(SzReadNumber32(sd, &p->NumPackStreams)); + + RINOK(WaitId(sd, k7zIdSize)); + MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc); + { + UInt64 sum = 0; + UInt32 i; + UInt32 numPackStreams = p->NumPackStreams; + for (i = 0; i < numPackStreams; i++) + { + UInt64 packSize; + p->PackPositions[i] = sum; + RINOK(ReadNumber(sd, &packSize)); + sum += packSize; + if (sum < packSize) + return SZ_ERROR_ARCHIVE; + } + p->PackPositions[i] = sum; + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + /* CRC of packed streams is unused now */ + RINOK(SkipBitUi32s(sd, p->NumPackStreams)); + continue; + } + RINOK(SkipData(sd)); + } +} + +/* +static SRes SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; +} +*/ + +#define SZ_NUM_IN_STREAMS_IN_FOLDER_MAX 16 + +SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes) +{ + UInt32 numCoders, numBindPairs, numPackStreams, i; + UInt32 numInStreams = 0, numOutStreams = 0; + const Byte *dataStart = sd->Data; + Byte inStreamUsed[SZ_NUM_IN_STREAMS_IN_FOLDER_MAX]; + + RINOK(SzReadNumber32(sd, &numCoders)); + if (numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->NumCoders = numCoders; + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CSzCoderInfo *coder = f->Coders + i; + unsigned idSize, j; + UInt64 id; + RINOK(SzReadByte(sd, &mainByte)); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (unsigned)(mainByte & 0xF); + if (idSize > sizeof(id)) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd->Size) + return SZ_ERROR_ARCHIVE; + id = 0; + for (j = 0; j < idSize; j++) + { + id = ((id << 8) | *sd->Data); + sd->Data++; + sd->Size--; + } + if (id > (UInt32)0xFFFFFFFF) + return SZ_ERROR_UNSUPPORTED; + coder->MethodID = (UInt32)id; + + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + coder->PropsOffset = 0; + coder->PropsSize = 0; + + if ((mainByte & 0x10) != 0) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumInStreams = (Byte)numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + coder->NumOutStreams = (Byte)numStreams; + } + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize = 0; + RINOK(SzReadNumber32(sd, &propsSize)); + if (propsSize >= 0x40) + return SZ_ERROR_UNSUPPORTED; + if (propsSize > sd->Size) + return SZ_ERROR_ARCHIVE; + coder->PropsOffset = sd->Data - dataStart; + coder->PropsSize = (Byte)propsSize; + sd->Data += (size_t)propsSize; + sd->Size -= (size_t)propsSize; + } + numInStreams += coder->NumInStreams; + numOutStreams += coder->NumOutStreams; + } + + if (numOutStreams == 0) + return SZ_ERROR_UNSUPPORTED; + + f->NumBindPairs = numBindPairs = numOutStreams - 1; + if (numInStreams < numBindPairs) + return SZ_ERROR_ARCHIVE; + if (numInStreams > SZ_NUM_IN_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + f->MainOutStream = 0; + f->NumPackStreams = numPackStreams = numInStreams - numBindPairs; + if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + for (i = 0; i < numInStreams; i++) + inStreamUsed[i] = False; + if (numBindPairs != 0) + { + Byte outStreamUsed[SZ_NUM_CODERS_OUT_STREAMS_IN_FOLDER_MAX]; + + if (numBindPairs > SZ_NUM_BINDS_IN_FOLDER_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numOutStreams; i++) + outStreamUsed[i] = False; + + for (i = 0; i < numBindPairs; i++) + { + CSzBindPair *bp = f->BindPairs + i; + RINOK(SzReadNumber32(sd, &bp->InIndex)); + if (bp->InIndex >= numInStreams) + return SZ_ERROR_ARCHIVE; + inStreamUsed[bp->InIndex] = True; + RINOK(SzReadNumber32(sd, &bp->OutIndex)); + if (bp->OutIndex >= numInStreams) + return SZ_ERROR_ARCHIVE; + outStreamUsed[bp->OutIndex] = True; + } + for (i = 0; i < numOutStreams; i++) + if (!outStreamUsed[i]) + { + f->MainOutStream = i; + break; + } + if (i == numOutStreams) + return SZ_ERROR_ARCHIVE; + } + + if (numPackStreams == 1) + { + for (i = 0; i < numInStreams; i++) + if (!inStreamUsed[i]) + break; + if (i == numInStreams) + return SZ_ERROR_ARCHIVE; + f->PackStreams[0] = i; + } + else + for (i = 0; i < numPackStreams; i++) + { + RINOK(SzReadNumber32(sd, f->PackStreams + i)); + } + + for (i = 0; i < numOutStreams; i++) + { + RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i)); + } + + return SZ_OK; +} + +static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num) +{ + CSzData sd; + sd = *sd2; + for (; num != 0; num--) + { + Byte firstByte, mask; + unsigned i; + SZ_READ_BYTE_2(firstByte); + if ((firstByte & 0x80) == 0) + continue; + if ((firstByte & 0x40) == 0) + { + if (sd.Size == 0) + return SZ_ERROR_ARCHIVE; + sd.Size--; + sd.Data++; + continue; + } + mask = 0x20; + for (i = 2; i < 8 && (firstByte & mask) != 0; i++) + mask >>= 1; + if (i > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, i); + } + *sd2 = sd; + return SZ_OK; +} + +#define k_InStreamUsed_MAX 64 +#define k_OutStreamUsed_MAX 64 + +static SRes ReadUnpackInfo(CSzAr *p, + CSzData *sd2, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + ISzAlloc *alloc) +{ + CSzData sd; + Byte inStreamUsed[k_InStreamUsed_MAX]; + Byte outStreamUsed[k_OutStreamUsed_MAX]; + UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex; + const Byte *startBufPtr; + Byte external; + + RINOK(WaitId(sd2, k7zIdFolder)); + RINOK(SzReadNumber32(sd2, &numFolders)); + if (p->NumFolders > numFoldersMax) + return SZ_ERROR_UNSUPPORTED; + p->NumFolders = numFolders; + + SZ_READ_BYTE_SD(sd2, external); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + SzReadNumber32(sd2, &index); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + + MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc); + MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc); + + startBufPtr = sd.Data; + + packStreamIndex = 0; + numCodersOutStreams = 0; + + for (fo = 0; fo < numFolders; fo++) + { + UInt32 numCoders, ci, numInStreams = 0, numOutStreams = 0; + + p->FoCodersOffsets[fo] = sd.Data - startBufPtr; + RINOK(SzReadNumber32(&sd, &numCoders)); + if (numCoders > NUM_FOLDER_CODERS_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (ci = 0; ci < numCoders; ci++) + { + Byte mainByte; + unsigned idSize; + UInt32 coderInStreams, coderOutStreams; + + SZ_READ_BYTE_2(mainByte); + if ((mainByte & 0xC0) != 0) + return SZ_ERROR_UNSUPPORTED; + idSize = (mainByte & 0xF); + if (idSize > 8) + return SZ_ERROR_UNSUPPORTED; + if (idSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, idSize); + + coderInStreams = 1; + coderOutStreams = 1; + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(&sd, &coderInStreams)); + RINOK(SzReadNumber32(&sd, &coderOutStreams)); + if (coderInStreams > NUM_CODER_STREAMS_MAX || + coderOutStreams > NUM_CODER_STREAMS_MAX) + return SZ_ERROR_UNSUPPORTED; + } + numInStreams += coderInStreams; + numOutStreams += coderOutStreams; + if ((mainByte & 0x20) != 0) + { + UInt32 propsSize; + RINOK(SzReadNumber32(&sd, &propsSize)); + if (propsSize > sd.Size) + return SZ_ERROR_ARCHIVE; + SKIP_DATA2(sd, propsSize); + } + } + + { + UInt32 indexOfMainStream = 0; + UInt32 numPackStreams = 1; + if (numOutStreams != 1 || numInStreams != 1) + { + UInt32 i; + UInt32 numBindPairs = numOutStreams - 1; + if (numOutStreams == 0 || numInStreams < numBindPairs) + return SZ_ERROR_ARCHIVE; + + if (numInStreams > k_InStreamUsed_MAX || + numOutStreams > k_OutStreamUsed_MAX) + return SZ_ERROR_UNSUPPORTED; + + for (i = 0; i < numInStreams; i++) + inStreamUsed[i] = False; + for (i = 0; i < numOutStreams; i++) + outStreamUsed[i] = False; + + for (i = 0; i < numBindPairs; i++) + { + UInt32 index; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || inStreamUsed[index]) + return SZ_ERROR_ARCHIVE; + inStreamUsed[index] = True; + RINOK(SzReadNumber32(&sd, &index)); + if (index >= numInStreams || outStreamUsed[index]) + return SZ_ERROR_ARCHIVE; + outStreamUsed[index] = True; + } + + numPackStreams = numInStreams - numBindPairs; + + if (numPackStreams != 1) + for (i = 0; i < numPackStreams; i++) + { + UInt32 temp; + RINOK(SzReadNumber32(&sd, &temp)); + if (temp >= numInStreams) + return SZ_ERROR_ARCHIVE; + } + + for (i = 0; i < numOutStreams; i++) + if (!outStreamUsed[i]) + { + indexOfMainStream = i; + break; + } + + if (i == numOutStreams) + return SZ_ERROR_ARCHIVE; + } + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoSizesOffsets[fo] = (numOutStreams << 8) | indexOfMainStream; + numCodersOutStreams += numOutStreams; + if (numCodersOutStreams < numOutStreams) + return SZ_ERROR_UNSUPPORTED; + packStreamIndex += numPackStreams; + if (packStreamIndex < numPackStreams) + return SZ_ERROR_UNSUPPORTED; + if (packStreamIndex > p->NumPackStreams) + return SZ_ERROR_ARCHIVE; + } + } + + { + size_t dataSize = sd.Data - startBufPtr; + p->FoStartPackStreamIndex[fo] = packStreamIndex; + p->FoCodersOffsets[fo] = dataSize; + MY_ALLOC(Byte, p->CodersData, dataSize, alloc); + memcpy(p->CodersData, startBufPtr, dataSize); + } + + if (external != 0) + { + if (sd.Size != 0) + return SZ_ERROR_ARCHIVE; + sd = *sd2; + } + + RINOK(WaitId(&sd, k7zIdCodersUnpackSize)); + + // MY_ALLOC(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc); + { + size_t dataSize = sd.Size; + /* + UInt32 i; + for (i = 0; i < numCodersOutStreams; i++) + { + RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i)); + } + */ + RINOK(SkipNumbers(&sd, numCodersOutStreams)); + dataSize -= sd.Size; + MY_ALLOC(Byte, p->UnpackSizesData, dataSize, alloc); + memcpy(p->UnpackSizesData, sd.Data - dataSize, dataSize); + p->UnpackSizesDataSize = dataSize; + /* + const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams); + if (data == NULL) + return SZ_ERROR_ARCHIVE; + sd.Size = sd.Data + sd.Size - data; + sd.Data = data; + */ + } + + for (;;) + { + UInt64 type; + RINOK(ReadID(&sd, &type)); + if (type == k7zIdEnd) + { + *sd2 = sd; + return SZ_OK; + } + if (type == k7zIdCRC) + { + RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc)); + continue; + } + RINOK(SkipData(&sd)); + } +} + +typedef struct +{ + UInt32 NumTotalSubStreams; + UInt32 NumSubDigests; + CSzData sdNumSubStreams; + CSzData sdSizes; + CSzData sdCRCs; +} CSubStreamInfo; + +#define SzUi32IndexMax (((UInt32)1 << 31) - 2) + +static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi) +{ + UInt64 type = 0; + UInt32 i; + UInt32 numSubDigests = 0; + UInt32 numFolders = p->NumFolders; + UInt32 numUnpackStreams = numFolders; + UInt32 numUnpackSizesInData = 0; + + for (;;) + { + RINOK(ReadID(sd, &type)); + if (type == k7zIdNumUnpackStream) + { + ssi->sdNumSubStreams.Data = sd->Data; + numUnpackStreams = 0; + numSubDigests = 0; + for (i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + if (numUnpackStreams > numUnpackStreams + numStreams) + return SZ_ERROR_UNSUPPORTED; + numUnpackStreams += numStreams; + if (numStreams != 0) + numUnpackSizesInData += (numStreams - 1); + if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i)) + numSubDigests += numStreams; + } + ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data; + continue; + } + if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + if (!ssi->sdNumSubStreams.Data) + { + numSubDigests = numFolders; + if (p->FolderCRCs.Defs) + numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders); + } + + ssi->NumTotalSubStreams = numUnpackStreams; + ssi->NumSubDigests = numSubDigests; + + if (type == k7zIdSize) + { + ssi->sdSizes.Data = sd->Data; + RINOK(SkipNumbers(sd, numUnpackSizesInData)); + ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data; + RINOK(ReadID(sd, &type)); + } + + for (;;) + { + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + ssi->sdCRCs.Data = sd->Data; + RINOK(SkipBitUi32s(sd, numSubDigests)); + ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data; + } + else + { + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } +} + +static SRes SzReadStreamsInfo(CSzAr *p, + CSzData *sd, + UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs, + UInt64 *dataOffset, + CSubStreamInfo *ssi, + ISzAlloc *alloc) +{ + UInt64 type; + + SzData_Clear(&ssi->sdSizes); + SzData_Clear(&ssi->sdCRCs); + SzData_Clear(&ssi->sdNumSubStreams); + + *dataOffset = 0; + RINOK(ReadID(sd, &type)); + if (type == k7zIdPackInfo) + { + RINOK(ReadNumber(sd, dataOffset)); + RINOK(ReadPackInfo(p, sd, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdUnpackInfo) + { + RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc)); + RINOK(ReadID(sd, &type)); + } + if (type == k7zIdSubStreamsInfo) + { + RINOK(ReadSubStreamsInfo(p, sd, ssi)); + RINOK(ReadID(sd, &type)); + } + else + { + ssi->NumTotalSubStreams = p->NumFolders; + // ssi->NumSubDigests = 0; + } + + return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED); +} + +static SRes SzReadAndDecodePackedStreams( + ILookInStream *inStream, + CSzData *sd, + CBuf *tempBufs, + UInt32 numFoldersMax, + UInt64 baseOffset, + CSzAr *p, + ISzAlloc *allocTemp) +{ + UInt64 dataStartPos; + UInt32 fo; + CSubStreamInfo ssi; + CSzData sdCodersUnpSizes; + + RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp)); + + dataStartPos += baseOffset; + if (p->NumFolders == 0) + return SZ_ERROR_ARCHIVE; + + sdCodersUnpSizes.Data = p->UnpackSizesData; + sdCodersUnpSizes.Size = p->UnpackSizesDataSize; + for (fo = 0; fo < p->NumFolders; fo++) + Buf_Init(tempBufs + fo); + for (fo = 0; fo < p->NumFolders; fo++) + { + CBuf *tempBuf = tempBufs + fo; + // folder = p->Folders; + // unpackSize = SzAr_GetFolderUnpackSize(p, 0); + UInt32 mix = (UInt32)p->FoSizesOffsets[fo]; + UInt32 mainIndex = mix & 0xFF; + UInt32 numOutStreams = mix >> 8; + UInt32 si; + UInt64 unpackSize = 0; + p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); + if (si == mainIndex) + { + unpackSize = curSize; + break; + } + } + if (si == numOutStreams) + return SZ_ERROR_FAIL; + if ((size_t)unpackSize != unpackSize) + return SZ_ERROR_MEM; + if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp)) + return SZ_ERROR_MEM; + } + p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData; + + for (fo = 0; fo < p->NumFolders; fo++) + { + const CBuf *tempBuf = tempBufs + fo; + RINOK(LookInStream_SeekTo(inStream, dataStartPos)); + RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp)); + if (SzBitWithVals_Check(&p->FolderCRCs, fo)) + if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo]) + return SZ_ERROR_CRC; + } + return SZ_OK; +} + +static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) +{ + size_t pos = 0; + *offsets++ = 0; + if (numFiles == 0) + return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; + if (data[size - 2] != 0 || data[size - 1] != 0) + return SZ_ERROR_ARCHIVE; + do + { + const Byte *p; + if (pos == size) + return SZ_ERROR_ARCHIVE; + for (p = data + pos; + #ifdef _WIN32 + *(const UInt16 *)p != 0 + #else + p[0] != 0 || p[1] != 0 + #endif + ; p += 2); + pos = p - data + 2; + *offsets++ = (pos >> 1); + } + while (--numFiles); + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, + CSzData *sd2, + const CBuf *tempBufs, UInt32 numTempBufs, + ISzAlloc *alloc) +{ + CSzData sd; + UInt32 i; + CNtfsFileTime *vals; + Byte *defs; + Byte external; + RINOK(ReadBitVector(sd2, num, &p->Defs, alloc)); + RINOK(SzReadByte(sd2, &external)); + if (external == 0) + sd = *sd2; + else + { + UInt32 index; + SzReadNumber32(sd2, &index); + if (index >= numTempBufs) + return SZ_ERROR_ARCHIVE; + sd.Data = tempBufs[index].data; + sd.Size = tempBufs[index].size; + } + MY_ALLOC(CNtfsFileTime, p->Vals, num, alloc); + vals = p->Vals; + defs = p->Defs; + for (i = 0; i < num; i++) + if (SzBitArray_Check(defs, i)) + { + if (sd.Size < 8) + return SZ_ERROR_ARCHIVE; + vals[i].Low = GetUi32(sd.Data); + vals[i].High = GetUi32(sd.Data + 4); + SKIP_DATA2(sd, 8); + } + else + vals[i].High = vals[i].Low = 0; + if (external == 0) + *sd2 = sd; + return SZ_OK; +} + +#define NUM_ADDITIONAL_STREAMS_MAX 8 + +static SRes SzReadHeader2( + CSzArEx *p, /* allocMain */ + CSzData *sd, + // Byte **emptyStreamVector, /* allocTemp */ + // Byte **emptyFileVector, /* allocTemp */ + // Byte **lwtVector, /* allocTemp */ + ILookInStream *inStream, + CBuf *tempBufs, + UInt32 *numTempBufs, + ISzAlloc *allocMain, + ISzAlloc *allocTemp + ) +{ + UInt64 type; + UInt32 numFiles = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + CSubStreamInfo ssi; + const Byte *emptyStreams = 0; + const Byte *emptyFiles = 0; + + SzData_Clear(&ssi.sdSizes); + SzData_Clear(&ssi.sdCRCs); + SzData_Clear(&ssi.sdNumSubStreams); + + ssi.NumSubDigests = 0; + ssi.NumTotalSubStreams = 0; + + RINOK(ReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + RINOK(ReadID(sd, &type)); + } + + // if (type == k7zIdAdditionalStreamsInfo) return SZ_ERROR_UNSUPPORTED; + + if (type == k7zIdAdditionalStreamsInfo) + { + CSzAr tempAr; + SRes res; + UInt32 numTempFolders; + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX, + p->startPosAfterHeader, &tempAr, allocTemp); + numTempFolders = tempAr.NumFolders; + SzAr_Free(&tempAr, allocTemp); + if (res != SZ_OK) + return res; + *numTempBufs = numTempFolders; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs, + &p->dataPos, &ssi, allocMain)); + p->dataPos += p->startPosAfterHeader; + RINOK(ReadID(sd, &type)); + } + + if (type == k7zIdEnd) + { + // *sd2 = sd; + return SZ_OK; + } + if (type != k7zIdFilesInfo) + return SZ_ERROR_ARCHIVE; + + RINOK(SzReadNumber32(sd, &numFiles)); + p->NumFiles = numFiles; + + for (;;) + { + UInt64 type; + UInt64 size; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(ReadNumber(sd, &size)); + if (size > sd->Size) + return SZ_ERROR_ARCHIVE; + if ((UInt64)(int)type != type) + { + SKIP_DATA(sd, size); + } + else switch((int)type) + { + case k7zIdName: + { + size_t namesSize; + const Byte *namesData; + Byte external; + + SZ_READ_BYTE(external); + if (external == 0) + { + namesSize = (size_t)size - 1; + namesData = sd->Data; + } + else + { + UInt32 index; + SzReadNumber32(sd, &index); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + namesData = (tempBufs)[index].data; + namesSize = (tempBufs)[index].size; + } + + if ((namesSize & 1) != 0) + return SZ_ERROR_ARCHIVE; + MY_ALLOC(Byte, p->FileNames, namesSize, allocMain); + MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain); + memcpy(p->FileNames, namesData, namesSize); + RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) + if (external == 0) + { + SKIP_DATA(sd, namesSize); + } + break; + } + case k7zIdEmptyStream: + { + RINOK(RememberBitVector(sd, numFiles, &emptyStreams)); + numEmptyStreams = CountDefinedBits(emptyStreams, numFiles); + break; + } + case k7zIdEmptyFile: + { + RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles)); + break; + } + case k7zIdWinAttrib: + { + Byte external; + CSzData sdSwitch; + CSzData *sdPtr; + SzBitUi32s_Free(&p->Attribs, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain)); + + SZ_READ_BYTE(external); + if (external == 0) + sdPtr = sd; + else + { + UInt32 index; + SzReadNumber32(sd, &index); + if (index >= *numTempBufs) + return SZ_ERROR_ARCHIVE; + sdSwitch.Data = (tempBufs)[index].data; + sdSwitch.Size = (tempBufs)[index].size; + sdPtr = &sdSwitch; + } + RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain)); + break; + } + /* + case k7zParent: + { + SzBitUi32s_Free(&p->Parents, allocMain); + RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain)); + RINOK(SzReadSwitch(sd)); + RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain)); + break; + } + */ + case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break; + default: + { + SKIP_DATA(sd, size); + } + } + } + + if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams) + return SZ_ERROR_ARCHIVE; + + for (;;) + { + UInt64 type; + RINOK(ReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SkipData(sd)); + } + + { + UInt32 emptyFileIndex = 0; + + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + UInt64 unpackPos = 0; + const Byte *digestsDefs = 0; + const Byte *digestsVals = 0; + UInt32 digestsValsIndex = 0; + UInt32 digestIndex; + Byte allDigestsDefined = 0; + UInt32 curNumSubStreams = (UInt32)(Int32)-1; + Byte isDirMask = 0; + Byte crcMask = 0; + Byte mask = 0x80; + // size_t unpSizesOffset = 0; + CSzData sdCodersUnpSizes; + sdCodersUnpSizes.Data = p->db.UnpackSizesData; + sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize; + + MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain); + MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain); + MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain); + MY_ALLOC(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain); + + RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain)); + + if (ssi.sdCRCs.Size != 0) + { + RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined)); + if (allDigestsDefined) + digestsVals = ssi.sdCRCs.Data; + else + { + size_t numBytes = (ssi.NumSubDigests + 7) >> 3; + digestsDefs = ssi.sdCRCs.Data; + digestsVals = digestsDefs + numBytes; + } + } + + digestIndex = 0; + for (i = 0; i < numFiles; i++, mask >>= 1) + { + if (mask == 0) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + isDirMask = 0; + crcMask = 0; + mask = 0x80; + } + + p->UnpackPositions[i] = unpackPos; + p->CRCs.Vals[i] = 0; + // p->CRCs.Defs[i] = 0; + if (emptyStreams && SzBitArray_Check(emptyStreams , i)) + { + if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex)) + isDirMask |= mask; + emptyFileIndex++; + if (indexInFolder == 0) + { + p->FileIndexToFolderIndexMap[i] = (UInt32)-1; + continue; + } + } + if (indexInFolder == 0) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: Loop for skipping empty folders + */ + for (;;) + { + if (folderIndex >= p->db.NumFolders) + return SZ_ERROR_ARCHIVE; + p->FolderStartFileIndex[folderIndex] = i; + if (curNumSubStreams == (UInt32)(Int32)-1); + { + curNumSubStreams = 1; + if (ssi.sdNumSubStreams.Data != 0) + { + RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams)); + } + } + if (curNumSubStreams != 0) + break; + curNumSubStreams = (UInt32)(Int32)-1; + folderIndex++; // check it + } + } + p->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStreams && SzBitArray_Check(emptyStreams , i)) + continue; + + indexInFolder++; + if (indexInFolder >= curNumSubStreams) + { + UInt64 folderUnpackSize = 0; + UInt64 startFolderUnpackPos; + { + UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex]; + UInt32 mainIndex = mix & 0xFF; + UInt32 numOutStreams = mix >> 8; + UInt32 si; + p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + RINOK(ReadNumber(&sdCodersUnpSizes, &curSize)); + if (si == mainIndex) + { + folderUnpackSize = curSize; + break; + } + } + if (si == numOutStreams) + return SZ_ERROR_FAIL; + } + + // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; + if (folderUnpackSize < unpackPos - startFolderUnpackPos) + return SZ_ERROR_ARCHIVE; + unpackPos = startFolderUnpackPos + folderUnpackSize; + + if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i)) + { + p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex]; + crcMask |= mask; + } + else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + folderIndex++; + indexInFolder = 0; + } + else + { + UInt64 v; + RINOK(ReadNumber(&ssi.sdSizes, &v)); + unpackPos += v; + if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex))) + { + p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4); + digestsValsIndex++; + crcMask |= mask; + } + } + } + if (mask != 0x80) + { + UInt32 byteIndex = (i - 1) >> 3; + p->IsDirs[byteIndex] = isDirMask; + p->CRCs.Defs[byteIndex] = crcMask; + } + p->UnpackPositions[i] = unpackPos; + p->FolderStartFileIndex[folderIndex] = i; + p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData; + } + return SZ_OK; +} + +static SRes SzReadHeader( + CSzArEx *p, + CSzData *sd, + ILookInStream *inStream, + ISzAlloc *allocMain + ,ISzAlloc *allocTemp + ) +{ + // Byte *emptyStreamVector = 0; + // Byte *emptyFileVector = 0; + // Byte *lwtVector = 0; + UInt32 i; + UInt32 numTempBufs = 0; + SRes res; + CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX]; + + for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++) + Buf_Init(tempBufs + i); + // SzBitUi32s_Init(&digests); + + res = SzReadHeader2(p, sd, + // &emptyStreamVector, + // &emptyFileVector, + // &lwtVector, + inStream, + tempBufs, &numTempBufs, + allocMain, allocTemp + ); + + for (i = 0; i < numTempBufs; i++) + Buf_Free(tempBufs + i, allocTemp); + + // IAlloc_Free(allocTemp, emptyStreamVector); + // IAlloc_Free(allocTemp, emptyFileVector); + // IAlloc_Free(allocTemp, lwtVector); + + RINOK(res); + { + if (sd->Size != 0) + return SZ_ERROR_FAIL; + } + + return res; +} + +/* +static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex) +{ + const CSzFolder2 *f = p->Folders + folderIndex; + + // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream]; + + UInt32 si; + CSzData sdCodersUnpSizes; + sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset; + sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset; + for (si = 0; si < numOutStreams; si++) + { + UInt64 curSize; + ReadNumber(&sdCodersUnpSizes, &curSize); + if (si == mainIndex) + return curSize; + } + return 0; +} +*/ + +static SRes SzArEx_Open2( + CSzArEx *p, + ILookInStream *inStream, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + Byte header[k7zStartHeaderSize]; + Int64 startArcPos; + UInt64 nextHeaderOffset, nextHeaderSize; + size_t nextHeaderSizeT; + UInt32 nextHeaderCRC; + CBuf buf; + SRes res; + + startArcPos = 0; + RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR)); + + RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); + + if (!TestSignatureCandidate(header)) + return SZ_ERROR_NO_ARCHIVE; + if (header[6] != k7zMajorVersion) + return SZ_ERROR_UNSUPPORTED; + + nextHeaderOffset = GetUi64(header + 12); + nextHeaderSize = GetUi64(header + 20); + nextHeaderCRC = GetUi32(header + 28); + + p->startPosAfterHeader = startArcPos + k7zStartHeaderSize; + + if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) + return SZ_ERROR_CRC; + + nextHeaderSizeT = (size_t)nextHeaderSize; + if (nextHeaderSizeT != nextHeaderSize) + return SZ_ERROR_MEM; + if (nextHeaderSizeT == 0) + return SZ_OK; + if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || + nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) + return SZ_ERROR_NO_ARCHIVE; + + { + Int64 pos = 0; + RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); + if ((UInt64)pos < startArcPos + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset || + (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) + return SZ_ERROR_INPUT_EOF; + } + + RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset)); + + if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp)) + return SZ_ERROR_MEM; + + res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT); + if (res == SZ_OK) + { + res = SZ_ERROR_ARCHIVE; + if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC) + { + CSzData sd; + UInt64 type; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + if (res == SZ_OK && type == k7zIdEncodedHeader) + { + CSzAr tempAr; + CBuf tempBuf; + Buf_Init(&tempBuf); + + SzAr_Init(&tempAr); + res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp); + SzAr_Free(&tempAr, allocTemp); + + if (res != SZ_OK) + { + Buf_Free(&tempBuf, allocTemp); + } + else + { + Buf_Free(&buf, allocTemp); + buf.data = tempBuf.data; + buf.size = tempBuf.size; + sd.Data = buf.data; + sd.Size = buf.size; + res = ReadID(&sd, &type); + } + } + if (res == SZ_OK) + { + if (type == k7zIdHeader) + { + CSzData sd2; + int ttt; + for (ttt = 0; ttt < 1; ttt++) + // for (ttt = 0; ttt < 40000; ttt++) + { + SzArEx_Free(p, allocMain); + sd2 = sd; + res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp + ); + if (res != SZ_OK) + break; + } + + // res = SzReadHeader(p, &sd, allocMain, allocTemp); + } + else + res = SZ_ERROR_UNSUPPORTED; + } + } + } + Buf_Free(&buf, allocTemp); + return res; +} + +// #include + +SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, + ISzAlloc *allocMain, ISzAlloc *allocTemp) +{ + SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); + if (res != SZ_OK) + SzArEx_Free(p, allocMain); + // printf ("\nrrr=%d\n", rrr); + return res; +} + +SRes SzArEx_Extract( + const CSzArEx *p, + ILookInStream *inStream, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **tempBuf, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; + SRes res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + IAlloc_Free(allocMain, *tempBuf); + *blockIndex = folderIndex; + *tempBuf = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*tempBuf == 0 || *blockIndex != folderIndex) + { + // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex); + UInt64 unpackSizeSpec = + p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] - + p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]; + size_t unpackSize = (size_t)unpackSizeSpec; + + if (unpackSize != unpackSizeSpec) + return SZ_ERROR_MEM; + *blockIndex = folderIndex; + IAlloc_Free(allocMain, *tempBuf); + *tempBuf = 0; + + // RINOK(LookInStream_SeekTo(inStream, startOffset)); + + if (res == SZ_OK) + { + *outBufferSize = unpackSize; + if (unpackSize != 0) + { + *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize); + if (*tempBuf == 0) + res = SZ_ERROR_MEM; + } + if (res == SZ_OK) + { + res = SzAr_DecodeFolder(&p->db, folderIndex, + inStream, + p->dataPos, + *tempBuf, unpackSize, allocTemp); + if (res == SZ_OK) + { + if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex)) + { + if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex]) + res = SZ_ERROR_CRC; + } + } + } + } + } + if (res == SZ_OK) + { + UInt64 unpackPos = p->UnpackPositions[fileIndex]; + *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]); + *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos); + if (*offset + *outSizeProcessed > *outBufferSize) + return SZ_ERROR_FAIL; + if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex]) + res = SZ_ERROR_CRC; + } + return res; +} + + +size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + size_t offs = p->FileNameOffsets[fileIndex]; + size_t len = p->FileNameOffsets[fileIndex + 1] - offs; + if (dest != 0) + { + size_t i; + const Byte *src = p->FileNames + offs * 2; + for (i = 0; i < len; i++) + dest[i] = GetUi16(src + i * 2); + } + return len; +} + +/* +size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex) +{ + size_t len; + if (!p->FileNameOffsets) + return 1; + len = 0; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return len; + fileIndex = parent; + } +} + +UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest) +{ + Bool needSlash; + if (!p->FileNameOffsets) + { + *(--dest) = 0; + return dest; + } + needSlash = False; + for (;;) + { + UInt32 parent = (UInt32)(Int32)-1; + size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex]; + SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen); + if (needSlash) + *(dest - 1) = '/'; + needSlash = True; + dest -= curLen; + + if SzBitWithVals_Check(&p->Parents, fileIndex) + parent = p->Parents.Vals[fileIndex]; + if (parent == (UInt32)(Int32)-1) + return dest; + fileIndex = parent; + } +} +*/ diff --git a/mp/src/utils/lzma/C/7zBuf.c b/mp/src/utils/lzma/C/7zBuf.c new file mode 100644 index 00000000..089a5c4f --- /dev/null +++ b/mp/src/utils/lzma/C/7zBuf.c @@ -0,0 +1,36 @@ +/* 7zBuf.c -- Byte Buffer +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zBuf.h" + +void Buf_Init(CBuf *p) +{ + p->data = 0; + p->size = 0; +} + +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) +{ + p->size = 0; + if (size == 0) + { + p->data = 0; + return 1; + } + p->data = (Byte *)alloc->Alloc(alloc, size); + if (p->data != 0) + { + p->size = size; + return 1; + } + return 0; +} + +void Buf_Free(CBuf *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->data); + p->data = 0; + p->size = 0; +} diff --git a/mp/src/utils/lzma/C/7zBuf.h b/mp/src/utils/lzma/C/7zBuf.h new file mode 100644 index 00000000..65f1d7a7 --- /dev/null +++ b/mp/src/utils/lzma/C/7zBuf.h @@ -0,0 +1,35 @@ +/* 7zBuf.h -- Byte Buffer +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_BUF_H +#define __7Z_BUF_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef struct +{ + Byte *data; + size_t size; +} CBuf; + +void Buf_Init(CBuf *p); +int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); +void Buf_Free(CBuf *p, ISzAlloc *alloc); + +typedef struct +{ + Byte *data; + size_t size; + size_t pos; +} CDynBuf; + +void DynBuf_Construct(CDynBuf *p); +void DynBuf_SeekToBeg(CDynBuf *p); +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/7zBuf2.c b/mp/src/utils/lzma/C/7zBuf2.c new file mode 100644 index 00000000..e14e65f4 --- /dev/null +++ b/mp/src/utils/lzma/C/7zBuf2.c @@ -0,0 +1,48 @@ +/* 7zBuf2.c -- Byte Buffer +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zBuf.h" + +void DynBuf_Construct(CDynBuf *p) +{ + p->data = 0; + p->size = 0; + p->pos = 0; +} + +void DynBuf_SeekToBeg(CDynBuf *p) +{ + p->pos = 0; +} + +int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc) +{ + if (size > p->size - p->pos) + { + size_t newSize = p->pos + size; + Byte *data; + newSize += newSize / 4; + data = (Byte *)alloc->Alloc(alloc, newSize); + if (data == 0) + return 0; + p->size = newSize; + memcpy(data, p->data, p->pos); + alloc->Free(alloc, p->data); + p->data = data; + } + memcpy(p->data + p->pos, buf, size); + p->pos += size; + return 1; +} + +void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->data); + p->data = 0; + p->size = 0; + p->pos = 0; +} diff --git a/mp/src/utils/lzma/C/7zCrc.c b/mp/src/utils/lzma/C/7zCrc.c new file mode 100644 index 00000000..503e3591 --- /dev/null +++ b/mp/src/utils/lzma/C/7zCrc.c @@ -0,0 +1,85 @@ +/* 7zCrc.c -- CRC32 init +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" + +#define kCrcPoly 0xEDB88320 + +#ifdef MY_CPU_X86_OR_AMD64 + #define CRC_NUM_TABLES 8 + UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table); +#elif defined(MY_CPU_LE) + #define CRC_NUM_TABLES 4 +#else + #define CRC_NUM_TABLES 5 + #define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +#ifndef MY_CPU_BE + UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table); +#endif + +typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table); + +CRC_FUNC g_CrcUpdate; +UInt32 g_CrcTable[256 * CRC_NUM_TABLES]; + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) +{ + return g_CrcUpdate(v, data, size, g_CrcTable); +} + +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) +{ + return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL; +} + +void MY_FAST_CALL CrcGenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + g_CrcTable[i] = r; + } + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt32 r = g_CrcTable[i - 256]; + g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE + + g_CrcUpdate = CrcUpdateT4; + + #if CRC_NUM_TABLES == 8 + if (!CPU_Is_InOrder()) + g_CrcUpdate = CrcUpdateT8; + #endif + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_CrcUpdate = CrcUpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt32 x = g_CrcTable[i - 256]; + g_CrcTable[i] = CRC_UINT32_SWAP(x); + } + g_CrcUpdate = CrcUpdateT1_BeT4; + } + } + #endif +} diff --git a/mp/src/utils/lzma/C/7zCrc.h b/mp/src/utils/lzma/C/7zCrc.h new file mode 100644 index 00000000..8fd57958 --- /dev/null +++ b/mp/src/utils/lzma/C/7zCrc.h @@ -0,0 +1,25 @@ +/* 7zCrc.h -- CRC32 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt32 g_CrcTable[]; + +/* Call CrcGenerateTable one time before other CRC functions */ +void MY_FAST_CALL CrcGenerateTable(void); + +#define CRC_INIT_VAL 0xFFFFFFFF +#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL) +#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); +UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/7zCrcOpt.c b/mp/src/utils/lzma/C/7zCrcOpt.c new file mode 100644 index 00000000..ce132b5d --- /dev/null +++ b/mp/src/utils/lzma/C/7zCrcOpt.c @@ -0,0 +1,66 @@ +/* 7zCrcOpt.c -- CRC32 calculation +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +#ifndef MY_CPU_BE + +UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x300 + (v & 0xFF)] ^ + table[0x200 + ((v >> 8) & 0xFF)] ^ + table[0x100 + ((v >> 16) & 0xFF)] ^ + table[0x000 + ((v >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + return CrcUpdateT4(v, data, size, table); +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24)) + +UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT32_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + v ^= *(const UInt32 *)p; + v = + table[0x000 + (v & 0xFF)] ^ + table[0x100 + ((v >> 8) & 0xFF)] ^ + table[0x200 + ((v >> 16) & 0xFF)] ^ + table[0x300 + ((v >> 24))]; + } + table -= 0x100; + v = CRC_UINT32_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/mp/src/utils/lzma/C/7zDec.c b/mp/src/utils/lzma/C/7zDec.c new file mode 100644 index 00000000..2c7c2cd0 --- /dev/null +++ b/mp/src/utils/lzma/C/7zDec.c @@ -0,0 +1,493 @@ +/* 7zDec.c -- Decoding from 7z folder +2014-06-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define _7ZIP_PPMD_SUPPPORT */ + +#include "7z.h" + +#include "Bcj2.h" +#include "Bra.h" +#include "CpuArch.h" +#include "LzmaDec.h" +#include "Lzma2Dec.h" +#ifdef _7ZIP_PPMD_SUPPPORT +#include "Ppmd7.h" +#endif + +#define k_Copy 0 +#define k_LZMA2 0x21 +#define k_LZMA 0x30101 +#define k_BCJ 0x03030103 +#define k_PPC 0x03030205 +#define k_ARM 0x03030501 +#define k_ARMT 0x03030701 +#define k_SPARC 0x03030805 +#define k_BCJ2 0x0303011B + +#ifdef _7ZIP_PPMD_SUPPPORT + +#define k_PPMD 0x30401 + +typedef struct +{ + IByteIn p; + const Byte *cur; + const Byte *end; + const Byte *begin; + UInt64 processed; + Bool extra; + SRes res; + ILookInStream *inStream; +} CByteInToLook; + +static Byte ReadByte(void *pp) +{ + CByteInToLook *p = (CByteInToLook *)pp; + if (p->cur != p->end) + return *p->cur++; + if (p->res == SZ_OK) + { + size_t size = p->cur - p->begin; + p->processed += size; + p->res = p->inStream->Skip(p->inStream, size); + size = (1 << 25); + p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); + p->cur = p->begin; + p->end = p->begin + size; + if (size != 0) + return *p->cur++;; + } + p->extra = True; + return 0; +} + +static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CPpmd7 ppmd; + CByteInToLook s; + SRes res = SZ_OK; + + s.p.Read = ReadByte; + s.inStream = inStream; + s.begin = s.end = s.cur = NULL; + s.extra = False; + s.res = SZ_OK; + s.processed = 0; + + if (propsSize != 5) + return SZ_ERROR_UNSUPPORTED; + + { + unsigned order = props[0]; + UInt32 memSize = GetUi32(props + 1); + if (order < PPMD7_MIN_ORDER || + order > PPMD7_MAX_ORDER || + memSize < PPMD7_MIN_MEM_SIZE || + memSize > PPMD7_MAX_MEM_SIZE) + return SZ_ERROR_UNSUPPORTED; + Ppmd7_Construct(&ppmd); + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) + return SZ_ERROR_MEM; + Ppmd7_Init(&ppmd, order); + } + { + CPpmd7z_RangeDec rc; + Ppmd7z_RangeDec_CreateVTable(&rc); + rc.Stream = &s.p; + if (!Ppmd7z_RangeDec_Init(&rc)) + res = SZ_ERROR_DATA; + else if (s.extra) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else + { + SizeT i; + for (i = 0; i < outSize; i++) + { + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); + if (s.extra || sym < 0) + break; + outBuffer[i] = (Byte)sym; + } + if (i != outSize) + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) + res = SZ_ERROR_DATA; + } + } + Ppmd7_Free(&ppmd, allocMain); + return res; +} + +#endif + + +static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzmaDec state; + SRes res = SZ_OK; + + LzmaDec_Construct(&state); + RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); + state.dic = outBuffer; + state.dicBufSize = outSize; + LzmaDec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; + ELzmaStatus status; + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) + { + if (state.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK && + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + LzmaDec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) +{ + CLzma2Dec state; + SRes res = SZ_OK; + + Lzma2Dec_Construct(&state); + if (propsSize != 1) + return SZ_ERROR_DATA; + RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); + state.decoder.dic = outBuffer; + state.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&state); + + for (;;) + { + Byte *inBuf = NULL; + size_t lookahead = (1 << 18); + if (lookahead > inSize) + lookahead = (size_t)inSize; + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); + if (res != SZ_OK) + break; + + { + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; + ELzmaStatus status; + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); + lookahead -= inProcessed; + inSize -= inProcessed; + if (res != SZ_OK) + break; + if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) + { + if (state.decoder.dicBufSize != outSize || lookahead != 0 || + (status != LZMA_STATUS_FINISHED_WITH_MARK)) + res = SZ_ERROR_DATA; + break; + } + res = inStream->Skip((void *)inStream, inProcessed); + if (res != SZ_OK) + break; + } + } + + Lzma2Dec_FreeProbs(&state, allocMain); + return res; +} + +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) +{ + while (inSize > 0) + { + void *inBuf; + size_t curSize = (1 << 18); + if (curSize > inSize) + curSize = (size_t)inSize; + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); + if (curSize == 0) + return SZ_ERROR_INPUT_EOF; + memcpy(outBuffer, inBuf, curSize); + outBuffer += curSize; + inSize -= curSize; + RINOK(inStream->Skip((void *)inStream, curSize)); + } + return SZ_OK; +} + +static Bool IS_MAIN_METHOD(UInt32 m) +{ + switch (m) + { + case k_Copy: + case k_LZMA: + case k_LZMA2: + #ifdef _7ZIP_PPMD_SUPPPORT + case k_PPMD: + #endif + return True; + } + return False; +} + +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) +{ + return + c->NumInStreams == 1 && + c->NumOutStreams == 1 && + /* c->MethodID <= (UInt32)0xFFFFFFFF && */ + IS_MAIN_METHOD((UInt32)c->MethodID); +} + +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) + +static SRes CheckSupportedFolder(const CSzFolder *f) +{ + if (f->NumCoders < 1 || f->NumCoders > 4) + return SZ_ERROR_UNSUPPORTED; + if (!IS_SUPPORTED_CODER(&f->Coders[0])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumCoders == 1) + { + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + if (f->NumCoders == 2) + { + const CSzCoderInfo *c = &f->Coders[1]; + if ( + /* c->MethodID > (UInt32)0xFFFFFFFF || */ + c->NumInStreams != 1 || + c->NumOutStreams != 1 || + f->NumPackStreams != 1 || + f->PackStreams[0] != 0 || + f->NumBindPairs != 1 || + f->BindPairs[0].InIndex != 1 || + f->BindPairs[0].OutIndex != 0) + return SZ_ERROR_UNSUPPORTED; + switch ((UInt32)c->MethodID) + { + case k_BCJ: + case k_ARM: + break; + default: + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; + } + if (f->NumCoders == 4) + { + if (!IS_SUPPORTED_CODER(&f->Coders[1]) || + !IS_SUPPORTED_CODER(&f->Coders[2]) || + !IS_BCJ2(&f->Coders[3])) + return SZ_ERROR_UNSUPPORTED; + if (f->NumPackStreams != 4 || + f->PackStreams[0] != 2 || + f->PackStreams[1] != 6 || + f->PackStreams[2] != 1 || + f->PackStreams[3] != 0 || + f->NumBindPairs != 3 || + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) + return SZ_ERROR_UNSUPPORTED; + return SZ_OK; + } + return SZ_ERROR_UNSUPPORTED; +} + +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; + +static SRes SzFolder_Decode2(const CSzFolder *folder, + const Byte *propsData, + const UInt64 *unpackSizes, + const UInt64 *packPositions, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, + Byte *tempBuf[]) +{ + UInt32 ci; + SizeT tempSizes[3] = { 0, 0, 0}; + SizeT tempSize3 = 0; + Byte *tempBuf3 = 0; + + RINOK(CheckSupportedFolder(folder)); + + for (ci = 0; ci < folder->NumCoders; ci++) + { + const CSzCoderInfo *coder = &folder->Coders[ci]; + + if (IS_MAIN_METHOD((UInt32)coder->MethodID)) + { + UInt32 si = 0; + UInt64 offset; + UInt64 inSize; + Byte *outBufCur = outBuffer; + SizeT outSizeCur = outSize; + if (folder->NumCoders == 4) + { + UInt32 indices[] = { 3, 2, 0 }; + UInt64 unpackSize = unpackSizes[ci]; + si = indices[ci]; + if (ci < 2) + { + Byte *temp; + outSizeCur = (SizeT)unpackSize; + if (outSizeCur != unpackSize) + return SZ_ERROR_MEM; + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); + if (temp == 0 && outSizeCur != 0) + return SZ_ERROR_MEM; + outBufCur = tempBuf[1 - ci] = temp; + tempSizes[1 - ci] = outSizeCur; + } + else if (ci == 2) + { + if (unpackSize > outSize) /* check it */ + return SZ_ERROR_PARAM; + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); + tempSize3 = outSizeCur = (SizeT)unpackSize; + } + else + return SZ_ERROR_UNSUPPORTED; + } + offset = packPositions[si]; + inSize = packPositions[si + 1] - offset; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + + if (coder->MethodID == k_Copy) + { + if (inSize != outSizeCur) /* check it */ + return SZ_ERROR_DATA; + RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); + } + else if (coder->MethodID == k_LZMA) + { + RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else if (coder->MethodID == k_LZMA2) + { + RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + } + else + { + #ifdef _7ZIP_PPMD_SUPPPORT + RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); + #else + return SZ_ERROR_UNSUPPORTED; + #endif + } + } + else if (coder->MethodID == k_BCJ2) + { + UInt64 offset = packPositions[1]; + UInt64 s3Size = packPositions[2] - offset; + SRes res; + if (ci != 3) + return SZ_ERROR_UNSUPPORTED; + RINOK(LookInStream_SeekTo(inStream, startPos + offset)); + tempSizes[2] = (SizeT)s3Size; + if (tempSizes[2] != s3Size) + return SZ_ERROR_MEM; + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); + if (tempBuf[2] == 0 && tempSizes[2] != 0) + return SZ_ERROR_MEM; + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); + RINOK(res) + + res = Bcj2_Decode( + tempBuf3, tempSize3, + tempBuf[0], tempSizes[0], + tempBuf[1], tempSizes[1], + tempBuf[2], tempSizes[2], + outBuffer, outSize); + RINOK(res) + } + else + { + if (ci != 1) + return SZ_ERROR_UNSUPPORTED; + switch (coder->MethodID) + { + case k_BCJ: + { + UInt32 state; + x86_Convert_Init(state); + x86_Convert(outBuffer, outSize, 0, &state, 0); + break; + } + CASE_BRA_CONV(ARM) + default: + return SZ_ERROR_UNSUPPORTED; + } + } + } + return SZ_OK; +} + +SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, + ILookInStream *inStream, UInt64 startPos, + Byte *outBuffer, size_t outSize, + ISzAlloc *allocMain) +{ + SRes res; + CSzFolder folder; + CSzData sd; + CSzData sdSizes; + + const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; + sd.Data = data; + sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; + + sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; + sdSizes.Size = + p->FoSizesOffsets[folderIndex + 1] - + p->FoSizesOffsets[folderIndex]; + + res = SzGetNextFolderItem(&folder, &sd, &sdSizes); + + if (res != SZ_OK) + return res; + + if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.MainOutStream]) + return SZ_ERROR_FAIL; + { + int i; + Byte *tempBuf[3] = { 0, 0, 0}; + res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes, + p->PackPositions + p->FoStartPackStreamIndex[folderIndex], + inStream, startPos, + outBuffer, (SizeT)outSize, allocMain, tempBuf); + for (i = 0; i < 3; i++) + IAlloc_Free(allocMain, tempBuf[i]); + return res; + } +} diff --git a/mp/src/utils/lzma/C/7zFile.c b/mp/src/utils/lzma/C/7zFile.c new file mode 100644 index 00000000..041e5b15 --- /dev/null +++ b/mp/src/utils/lzma/C/7zFile.c @@ -0,0 +1,286 @@ +/* 7zFile.c -- File IO +2009-11-24 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + +#ifndef UNDER_CE +#include +#endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#define kChunkSizeMax (1 << 22) + +#endif + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #else + p->file = NULL; + #endif +} + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + #else + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } +WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } +#endif + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + #else + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + return res; + p->file = NULL; + } + #endif + return 0; +} + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fread(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fwrite(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + LARGE_INTEGER value; + DWORD moveMethod; + value.LowPart = (DWORD)*pos; + value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)value.HighPart << 32) | value.LowPart; + return 0; + + #else + + int moveMethod; + int res; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return 1; + } + res = fseek(p->file, (long)*pos, moveMethod); + *pos = ftell(p->file); + return res; + + #endif +} + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #else + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = (CFileSeqInStream *)pp; + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->s.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(void *pp, void *buf, size_t *size) +{ + CFileInStream *p = (CFileInStream *)pp; + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = (CFileInStream *)pp; + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->s.Read = FileInStream_Read; + p->s.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(void *pp, const void *data, size_t size) +{ + CFileOutStream *p = (CFileOutStream *)pp; + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->s.Write = FileOutStream_Write; +} diff --git a/mp/src/utils/lzma/C/7zFile.h b/mp/src/utils/lzma/C/7zFile.h new file mode 100644 index 00000000..658987ed --- /dev/null +++ b/mp/src/utils/lzma/C/7zFile.h @@ -0,0 +1,83 @@ +/* 7zFile.h -- File IO +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +#include +#else +#include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream s; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream s; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream s; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/7zStream.c b/mp/src/utils/lzma/C/7zStream.c new file mode 100644 index 00000000..88f9c42b --- /dev/null +++ b/mp/src/utils/lzma/C/7zStream.c @@ -0,0 +1,171 @@ +/* 7zStream.c -- 7z Stream functions +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zTypes.h" + +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(stream->Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return stream->Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(stream->Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return stream->Skip(stream, *size); +} + +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(stream->Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + size2 = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + CLookToRead *p = (CLookToRead *)pp; + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size > 0) + { + p->pos = 0; + if (*size > LookToRead_BUF_SIZE) + *size = LookToRead_BUF_SIZE; + res = p->realStream->Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (size2 < *size) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead_Skip(void *pp, size_t offset) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead_Read(void *pp, void *buf, size_t *size) +{ + CLookToRead *p = (CLookToRead *)pp; + size_t rem = p->size - p->pos; + if (rem == 0) + return p->realStream->Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) +{ + CLookToRead *p = (CLookToRead *)pp; + p->pos = p->size = 0; + return p->realStream->Seek(p->realStream, pos, origin); +} + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead) +{ + p->s.Look = lookahead ? + LookToRead_Look_Lookahead : + LookToRead_Look_Exact; + p->s.Skip = LookToRead_Skip; + p->s.Read = LookToRead_Read; + p->s.Seek = LookToRead_Seek; +} + +void LookToRead_Init(CLookToRead *p) +{ + p->pos = p->size = 0; +} + +static SRes SecToLook_Read(void *pp, void *buf, size_t *size) +{ + CSecToLook *p = (CSecToLook *)pp; + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->s.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(void *pp, void *buf, size_t *size) +{ + CSecToRead *p = (CSecToRead *)pp; + return p->realStream->Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->s.Read = SecToRead_Read; +} diff --git a/mp/src/utils/lzma/C/7zTypes.h b/mp/src/utils/lzma/C/7zTypes.h new file mode 100644 index 00000000..778413ef --- /dev/null +++ b/mp/src/utils/lzma/C/7zTypes.h @@ -0,0 +1,256 @@ +/* 7zTypes.h -- Basic types +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_NO_INLINE +#define MY_CDECL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/7zVersion.h b/mp/src/utils/lzma/C/7zVersion.h new file mode 100644 index 00000000..47591835 --- /dev/null +++ b/mp/src/utils/lzma/C/7zVersion.h @@ -0,0 +1,10 @@ +#define MY_VER_MAJOR 9 +#define MY_VER_MINOR 38 +#define MY_VER_BUILD 00 +#define MY_VERSION "9.38 beta" +// #define MY_7ZIP_VERSION "9.38" +#define MY_DATE "2015-01-03" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE +#define MY_COPYRIGHT ": Igor Pavlov : Public domain" +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE diff --git a/mp/src/utils/lzma/C/7zVersion.rc b/mp/src/utils/lzma/C/7zVersion.rc new file mode 100644 index 00000000..e520995d --- /dev/null +++ b/mp/src/utils/lzma/C/7zVersion.rc @@ -0,0 +1,55 @@ +#define MY_VS_FFI_FILEFLAGSMASK 0x0000003FL +#define MY_VOS_NT_WINDOWS32 0x00040004L +#define MY_VOS_CE_WINDOWS32 0x00050004L + +#define MY_VFT_APP 0x00000001L +#define MY_VFT_DLL 0x00000002L + +// #include + +#ifndef MY_VERSION +#include "7zVersion.h" +#endif + +#define MY_VER MY_VER_MAJOR,MY_VER_MINOR,MY_VER_BUILD,0 + +#ifdef DEBUG +#define DBG_FL VS_FF_DEBUG +#else +#define DBG_FL 0 +#endif + +#define MY_VERSION_INFO(fileType, descr, intName, origName) \ +LANGUAGE 9, 1 \ +1 VERSIONINFO \ + FILEVERSION MY_VER \ + PRODUCTVERSION MY_VER \ + FILEFLAGSMASK MY_VS_FFI_FILEFLAGSMASK \ + FILEFLAGS DBG_FL \ + FILEOS MY_VOS_NT_WINDOWS32 \ + FILETYPE fileType \ + FILESUBTYPE 0x0L \ +BEGIN \ + BLOCK "StringFileInfo" \ + BEGIN \ + BLOCK "040904b0" \ + BEGIN \ + VALUE "CompanyName", "Igor Pavlov" \ + VALUE "FileDescription", descr \ + VALUE "FileVersion", MY_VERSION \ + VALUE "InternalName", intName \ + VALUE "LegalCopyright", MY_COPYRIGHT \ + VALUE "OriginalFilename", origName \ + VALUE "ProductName", "7-Zip" \ + VALUE "ProductVersion", MY_VERSION \ + END \ + END \ + BLOCK "VarFileInfo" \ + BEGIN \ + VALUE "Translation", 0x409, 1200 \ + END \ +END + +#define MY_VERSION_INFO_APP(descr, intName) MY_VERSION_INFO(MY_VFT_APP, descr, intName, intName ".exe") + +#define MY_VERSION_INFO_DLL(descr, intName) MY_VERSION_INFO(MY_VFT_DLL, descr, intName, intName ".dll") diff --git a/mp/src/utils/lzma/C/Aes.c b/mp/src/utils/lzma/C/Aes.c new file mode 100644 index 00000000..6c49dc98 --- /dev/null +++ b/mp/src/utils/lzma/C/Aes.c @@ -0,0 +1,284 @@ +/* Aes.c -- AES encryption / decryption +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Aes.h" +#include "CpuArch.h" + +static UInt32 T[256 * 4]; +static Byte Sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; + +void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks); + +void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); + +AES_CODE_FUNC g_AesCbc_Encode; +AES_CODE_FUNC g_AesCbc_Decode; +AES_CODE_FUNC g_AesCtr_Code; + +static UInt32 D[256 * 4]; +static Byte InvS[256]; + +static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; + +#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF) + +#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24)) + +#define gb0(x) ( (x) & 0xFF) +#define gb1(x) (((x) >> ( 8)) & 0xFF) +#define gb2(x) (((x) >> (16)) & 0xFF) +#define gb3(x) (((x) >> (24)) & 0xFF) + +void AesGenTables(void) +{ + unsigned i; + for (i = 0; i < 256; i++) + InvS[Sbox[i]] = (Byte)i; + for (i = 0; i < 256; i++) + { + { + UInt32 a1 = Sbox[i]; + UInt32 a2 = xtime(a1); + UInt32 a3 = a2 ^ a1; + T[ i] = Ui32(a2, a1, a1, a3); + T[0x100 + i] = Ui32(a3, a2, a1, a1); + T[0x200 + i] = Ui32(a1, a3, a2, a1); + T[0x300 + i] = Ui32(a1, a1, a3, a2); + } + { + UInt32 a1 = InvS[i]; + UInt32 a2 = xtime(a1); + UInt32 a4 = xtime(a2); + UInt32 a8 = xtime(a4); + UInt32 a9 = a8 ^ a1; + UInt32 aB = a8 ^ a2 ^ a1; + UInt32 aD = a8 ^ a4 ^ a1; + UInt32 aE = a8 ^ a4 ^ a2; + D[ i] = Ui32(aE, a9, aD, aB); + D[0x100 + i] = Ui32(aB, aE, a9, aD); + D[0x200 + i] = Ui32(aD, aB, aE, a9); + D[0x300 + i] = Ui32(a9, aD, aB, aE); + } + } + g_AesCbc_Encode = AesCbc_Encode; + g_AesCbc_Decode = AesCbc_Decode; + g_AesCtr_Code = AesCtr_Code; + #ifdef MY_CPU_X86_OR_AMD64 + if (CPU_Is_Aes_Supported()) + { + g_AesCbc_Encode = AesCbc_Encode_Intel; + g_AesCbc_Decode = AesCbc_Decode_Intel; + g_AesCtr_Code = AesCtr_Code_Intel; + } + #endif +} + +#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])] +#define HT4(m, i, s, p) m[i] = \ + HT(i, 0, s) ^ \ + HT(i, 1, s) ^ \ + HT(i, 2, s) ^ \ + HT(i, 3, s) ^ w[p + i] +/* such order (2031) in HT16 is for VC6/K8 speed optimization) */ +#define HT16(m, s, p) \ + HT4(m, 2, s, p); \ + HT4(m, 0, s, p); \ + HT4(m, 3, s, p); \ + HT4(m, 1, s, p); \ + +#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])] +#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i]; + +#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])] +#define HD4(m, i, s, p) m[i] = \ + HD(i, 0, s) ^ \ + HD(i, 1, s) ^ \ + HD(i, 2, s) ^ \ + HD(i, 3, s) ^ w[p + i]; +/* such order (0231) in HD16 is for VC6/K8 speed optimization) */ +#define HD16(m, s, p) \ + HD4(m, 0, s, p); \ + HD4(m, 2, s, p); \ + HD4(m, 3, s, p); \ + HD4(m, 1, s, p); \ + +#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])] +#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i]; + +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, wSize; + wSize = keySize + 28; + keySize /= 4; + w[0] = ((UInt32)keySize / 2) + 3; + w += 4; + + for (i = 0; i < keySize; i++, key += 4) + w[i] = GetUi32(key); + + for (; i < wSize; i++) + { + UInt32 t = w[i - 1]; + unsigned rem = i % keySize; + if (rem == 0) + t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]); + else if (keySize > 6 && rem == 4) + t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]); + w[i] = w[i - keySize] ^ t; + } +} + +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *w, const Byte *key, unsigned keySize) +{ + unsigned i, num; + Aes_SetKey_Enc(w, key, keySize); + num = keySize + 20; + w += 8; + for (i = 0; i < num; i++) + { + UInt32 r = w[i]; + w[i] = + D[ Sbox[gb0(r)]] ^ + D[0x100 + Sbox[gb1(r)]] ^ + D[0x200 + Sbox[gb2(r)]] ^ + D[0x300 + Sbox[gb3(r)]]; + } +} + +/* Aes_Encode and Aes_Decode functions work with little-endian words. + src and dest are pointers to 4 UInt32 words. + arc and dest can point to same block */ + +static void Aes_Encode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + w += 4; + for (;;) + { + HT16(m, s, 0); + if (--numRounds2 == 0) + break; + HT16(s, m, 4); + w += 8; + } + w += 4; + FT4(0); FT4(1); FT4(2); FT4(3); +} + +static void Aes_Decode(const UInt32 *w, UInt32 *dest, const UInt32 *src) +{ + UInt32 s[4]; + UInt32 m[4]; + UInt32 numRounds2 = w[0]; + w += 4 + numRounds2 * 8; + s[0] = src[0] ^ w[0]; + s[1] = src[1] ^ w[1]; + s[2] = src[2] ^ w[2]; + s[3] = src[3] ^ w[3]; + for (;;) + { + w -= 8; + HD16(m, s, 4); + if (--numRounds2 == 0) + break; + HD16(s, m, 0); + } + FD4(0); FD4(1); FD4(2); FD4(3); +} + +void AesCbc_Init(UInt32 *p, const Byte *iv) +{ + unsigned i; + for (i = 0; i < 4; i++) + p[i] = GetUi32(iv + i * 4); +} + +void MY_FAST_CALL AesCbc_Encode(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + p[0] ^= GetUi32(data); + p[1] ^= GetUi32(data + 4); + p[2] ^= GetUi32(data + 8); + p[3] ^= GetUi32(data + 12); + + Aes_Encode(p + 4, p, p); + + SetUi32(data, p[0]); + SetUi32(data + 4, p[1]); + SetUi32(data + 8, p[2]); + SetUi32(data + 12, p[3]); + } +} + +void MY_FAST_CALL AesCbc_Decode(UInt32 *p, Byte *data, size_t numBlocks) +{ + UInt32 in[4], out[4]; + for (; numBlocks != 0; numBlocks--, data += AES_BLOCK_SIZE) + { + in[0] = GetUi32(data); + in[1] = GetUi32(data + 4); + in[2] = GetUi32(data + 8); + in[3] = GetUi32(data + 12); + + Aes_Decode(p + 4, out, in); + + SetUi32(data, p[0] ^ out[0]); + SetUi32(data + 4, p[1] ^ out[1]); + SetUi32(data + 8, p[2] ^ out[2]); + SetUi32(data + 12, p[3] ^ out[3]); + + p[0] = in[0]; + p[1] = in[1]; + p[2] = in[2]; + p[3] = in[3]; + } +} + +void MY_FAST_CALL AesCtr_Code(UInt32 *p, Byte *data, size_t numBlocks) +{ + for (; numBlocks != 0; numBlocks--) + { + UInt32 temp[4]; + Byte buf[16]; + int i; + if (++p[0] == 0) + p[1]++; + Aes_Encode(p + 4, temp, p); + SetUi32(buf, temp[0]); + SetUi32(buf + 4, temp[1]); + SetUi32(buf + 8, temp[2]); + SetUi32(buf + 12, temp[3]); + for (i = 0; i < 16; i++) + *data++ ^= buf[i]; + } +} diff --git a/mp/src/utils/lzma/C/Aes.h b/mp/src/utils/lzma/C/Aes.h new file mode 100644 index 00000000..64979b5b --- /dev/null +++ b/mp/src/utils/lzma/C/Aes.h @@ -0,0 +1,38 @@ +/* Aes.h -- AES encryption / decryption +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __AES_H +#define __AES_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define AES_BLOCK_SIZE 16 + +/* Call AesGenTables one time before other AES functions */ +void AesGenTables(void); + +/* UInt32 pointers must be 16-byte aligned */ + +/* 16-byte (4 * 32-bit words) blocks: 1 (IV) + 1 (keyMode) + 15 (AES-256 roundKeys) */ +#define AES_NUM_IVMRK_WORDS ((1 + 1 + 15) * 4) + +/* aes - 16-byte aligned pointer to keyMode+roundKeys sequence */ +/* keySize = 16 or 24 or 32 (bytes) */ +typedef void (MY_FAST_CALL *AES_SET_KEY_FUNC)(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Enc(UInt32 *aes, const Byte *key, unsigned keySize); +void MY_FAST_CALL Aes_SetKey_Dec(UInt32 *aes, const Byte *key, unsigned keySize); + +/* ivAes - 16-byte aligned pointer to iv+keyMode+roundKeys sequence: UInt32[AES_NUM_IVMRK_WORDS] */ +void AesCbc_Init(UInt32 *ivAes, const Byte *iv); /* iv size is AES_BLOCK_SIZE */ +/* data - 16-byte aligned pointer to data */ +/* numBlocks - the number of 16-byte blocks in data array */ +typedef void (MY_FAST_CALL *AES_CODE_FUNC)(UInt32 *ivAes, Byte *data, size_t numBlocks); +extern AES_CODE_FUNC g_AesCbc_Encode; +extern AES_CODE_FUNC g_AesCbc_Decode; +extern AES_CODE_FUNC g_AesCtr_Code; + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/AesOpt.c b/mp/src/utils/lzma/C/AesOpt.c new file mode 100644 index 00000000..10a8fb25 --- /dev/null +++ b/mp/src/utils/lzma/C/AesOpt.c @@ -0,0 +1,184 @@ +/* AesOpt.c -- Intel's AES +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 +#if _MSC_VER >= 1500 +#define USE_INTEL_AES +#endif +#endif + +#ifdef USE_INTEL_AES + +#include + +void MY_FAST_CALL AesCbc_Encode_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i m = *p; + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p + 3; + m = _mm_xor_si128(m, *data); + m = _mm_xor_si128(m, p[2]); + do + { + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenc_si128(m, w[1]); + w += 2; + } + while (--numRounds2 != 0); + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenclast_si128(m, w[1]); + *data = m; + } + *p = m; +} + +#define NUM_WAYS 3 + +#define AES_OP_W(op, n) { \ + const __m128i t = w[n]; \ + m0 = op(m0, t); \ + m1 = op(m1, t); \ + m2 = op(m2, t); \ + } + +#define AES_DEC(n) AES_OP_W(_mm_aesdec_si128, n) +#define AES_DEC_LAST(n) AES_OP_W(_mm_aesdeclast_si128, n) +#define AES_ENC(n) AES_OP_W(_mm_aesenc_si128, n) +#define AES_ENC_LAST(n) AES_OP_W(_mm_aesenclast_si128, n) + +void MY_FAST_CALL AesCbc_Decode_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i iv = *p; + for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1); + const __m128i *w = p + numRounds2 * 2; + __m128i m0, m1, m2; + { + const __m128i t = w[2]; + m0 = _mm_xor_si128(t, data[0]); + m1 = _mm_xor_si128(t, data[1]); + m2 = _mm_xor_si128(t, data[2]); + } + numRounds2--; + do + { + AES_DEC(1) + AES_DEC(0) + w -= 2; + } + while (--numRounds2 != 0); + AES_DEC(1) + AES_DEC_LAST(0) + + { + __m128i t; + t = _mm_xor_si128(m0, iv); iv = data[0]; data[0] = t; + t = _mm_xor_si128(m1, iv); iv = data[1]; data[1] = t; + t = _mm_xor_si128(m2, iv); iv = data[2]; data[2] = t; + } + } + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1); + const __m128i *w = p + numRounds2 * 2; + __m128i m = _mm_xor_si128(w[2], *data); + numRounds2--; + do + { + m = _mm_aesdec_si128(m, w[1]); + m = _mm_aesdec_si128(m, w[0]); + w -= 2; + } + while (--numRounds2 != 0); + m = _mm_aesdec_si128(m, w[1]); + m = _mm_aesdeclast_si128(m, w[0]); + + m = _mm_xor_si128(m, iv); + iv = *data; + *data = m; + } + *p = iv; +} + +void MY_FAST_CALL AesCtr_Code_Intel(__m128i *p, __m128i *data, size_t numBlocks) +{ + __m128i ctr = *p; + __m128i one; + one.m128i_u64[0] = 1; + one.m128i_u64[1] = 0; + for (; numBlocks >= NUM_WAYS; numBlocks -= NUM_WAYS, data += NUM_WAYS) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p; + __m128i m0, m1, m2; + { + const __m128i t = w[2]; + ctr = _mm_add_epi64(ctr, one); m0 = _mm_xor_si128(ctr, t); + ctr = _mm_add_epi64(ctr, one); m1 = _mm_xor_si128(ctr, t); + ctr = _mm_add_epi64(ctr, one); m2 = _mm_xor_si128(ctr, t); + } + w += 3; + do + { + AES_ENC(0) + AES_ENC(1) + w += 2; + } + while (--numRounds2 != 0); + AES_ENC(0) + AES_ENC_LAST(1) + data[0] = _mm_xor_si128(data[0], m0); + data[1] = _mm_xor_si128(data[1], m1); + data[2] = _mm_xor_si128(data[2], m2); + } + for (; numBlocks != 0; numBlocks--, data++) + { + UInt32 numRounds2 = *(const UInt32 *)(p + 1) - 1; + const __m128i *w = p; + __m128i m; + ctr = _mm_add_epi64(ctr, one); + m = _mm_xor_si128(ctr, p[2]); + w += 3; + do + { + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenc_si128(m, w[1]); + w += 2; + } + while (--numRounds2 != 0); + m = _mm_aesenc_si128(m, w[0]); + m = _mm_aesenclast_si128(m, w[1]); + *data = _mm_xor_si128(*data, m); + } + *p = ctr; +} + +#else + +void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks); +void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks); + +void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *p, Byte *data, size_t numBlocks) +{ + AesCbc_Encode(p, data, numBlocks); +} + +void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *p, Byte *data, size_t numBlocks) +{ + AesCbc_Decode(p, data, numBlocks); +} + +void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *p, Byte *data, size_t numBlocks) +{ + AesCtr_Code(p, data, numBlocks); +} + +#endif diff --git a/mp/src/utils/lzma/C/Alloc.c b/mp/src/utils/lzma/C/Alloc.c new file mode 100644 index 00000000..a9a69575 --- /dev/null +++ b/mp/src/utils/lzma/C/Alloc.c @@ -0,0 +1,127 @@ +/* Alloc.c -- Memory allocation functions +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifdef _WIN32 +#include +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + fprintf(stderr, "\nAlloc %10d bytes, count = %10d, addr = %8X", size, g_allocCount++, (unsigned)p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d, addr = %8X", --g_allocCount, (unsigned)address); + #endif + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size = 0; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + #ifdef _7ZIP_LARGE_PAGES + if (g_LargePageSize != 0 && g_LargePageSize <= (1 << 30) && size >= (1 << 18)) + { + void *res = VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + #endif + return VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/mp/src/utils/lzma/C/Alloc.h b/mp/src/utils/lzma/C/Alloc.h new file mode 100644 index 00000000..b8e41436 --- /dev/null +++ b/mp/src/utils/lzma/C/Alloc.h @@ -0,0 +1,38 @@ +/* Alloc.h -- Memory allocation functions +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mp/src/utils/lzma/C/Bcj2.c b/mp/src/utils/lzma/C/Bcj2.c new file mode 100644 index 00000000..4e81cdc2 --- /dev/null +++ b/mp/src/utils/lzma/C/Bcj2.c @@ -0,0 +1,134 @@ +/* Bcj2.c -- Converter for x86 code (BCJ2) +2008-10-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bcj2.h" + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) +#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*buffer++) +#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } +#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ + { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} + +#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } + +#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize) +{ + CProb p[256 + 2]; + SizeT inPos = 0, outPos = 0; + + const Byte *buffer, *bufferLim; + UInt32 range, code; + Byte prevByte = 0; + + unsigned int i; + for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) + p[i] = kBitModelTotal >> 1; + + buffer = buf3; + bufferLim = buffer + size3; + RC_INIT2 + + if (outSize == 0) + return SZ_OK; + + for (;;) + { + Byte b; + CProb *prob; + UInt32 bound; + UInt32 ttt; + + SizeT limit = size0 - inPos; + if (outSize - outPos < limit) + limit = outSize - outPos; + while (limit != 0) + { + Byte b = buf0[inPos]; + outBuf[outPos++] = b; + if (IsJ(prevByte, b)) + break; + inPos++; + prevByte = b; + limit--; + } + + if (limit == 0 || outPos == outSize) + break; + + b = buf0[inPos++]; + + if (b == 0xE8) + prob = p + prevByte; + else if (b == 0xE9) + prob = p + 256; + else + prob = p + 257; + + IF_BIT_0(prob) + { + UPDATE_0(prob) + prevByte = b; + } + else + { + UInt32 dest; + const Byte *v; + UPDATE_1(prob) + if (b == 0xE8) + { + v = buf1; + if (size1 < 4) + return SZ_ERROR_DATA; + buf1 += 4; + size1 -= 4; + } + else + { + v = buf2; + if (size2 < 4) + return SZ_ERROR_DATA; + buf2 += 4; + size2 -= 4; + } + dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | + ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); + outBuf[outPos++] = (Byte)dest; + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 8); + if (outPos == outSize) + break; + outBuf[outPos++] = (Byte)(dest >> 16); + if (outPos == outSize) + break; + outBuf[outPos++] = prevByte = (Byte)(dest >> 24); + } + } + return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; +} diff --git a/mp/src/utils/lzma/C/Bcj2.h b/mp/src/utils/lzma/C/Bcj2.h new file mode 100644 index 00000000..1db8ea0a --- /dev/null +++ b/mp/src/utils/lzma/C/Bcj2.h @@ -0,0 +1,34 @@ +/* Bcj2.h -- Converter for x86 code (BCJ2) +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __BCJ2_H +#define __BCJ2_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +Conditions: + outSize <= FullOutputSize, + where FullOutputSize is full size of output stream of x86_2 filter. + +If buf0 overlaps outBuf, there are two required conditions: + 1) (buf0 >= outBuf) + 2) (buf0 + size0 >= outBuf + FullOutputSize). + +Returns: + SZ_OK + SZ_ERROR_DATA - Data error +*/ + +int Bcj2_Decode( + const Byte *buf0, SizeT size0, + const Byte *buf1, SizeT size1, + const Byte *buf2, SizeT size2, + const Byte *buf3, SizeT size3, + Byte *outBuf, SizeT outSize); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Bra.c b/mp/src/utils/lzma/C/Bra.c new file mode 100644 index 00000000..cdb94569 --- /dev/null +++ b/mp/src/utils/lzma/C/Bra.c @@ -0,0 +1,135 @@ +/* Bra.c -- Converters for RISC code +2010-04-16 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 8; + for (i = 0; i <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 dest; + UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 2; + data[i + 2] = (Byte)(dest >> 16); + data[i + 1] = (Byte)(dest >> 8); + data[i + 0] = (Byte)dest; + } + } + return i; +} + +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + ip += 4; + for (i = 0; i <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 dest; + UInt32 src = + (((UInt32)data[i + 1] & 0x7) << 19) | + ((UInt32)data[i + 0] << 11) | + (((UInt32)data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + dest >>= 1; + + data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7)); + data[i + 0] = (Byte)(dest >> 11); + data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7)); + data[i + 2] = (Byte)dest; + i += 2; + } + } + return i; +} + +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1) + { + UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3)); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} + +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + UInt32 i; + if (size < 4) + return 0; + size -= 4; + for (i = 0; i <= size; i += 4) + { + if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) || + (data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0)) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + UInt32 dest; + + src <<= 2; + if (encoding) + dest = ip + i + src; + else + dest = src - (ip + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/mp/src/utils/lzma/C/Bra.h b/mp/src/utils/lzma/C/Bra.h new file mode 100644 index 00000000..855e37a6 --- /dev/null +++ b/mp/src/utils/lzma/C/Bra.h @@ -0,0 +1,64 @@ +/* Bra.h -- Branch converters for executables +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Bra86.c b/mp/src/utils/lzma/C/Bra86.c new file mode 100644 index 00000000..6db15e7e --- /dev/null +++ b/mp/src/utils/lzma/C/Bra86.c @@ -0,0 +1,82 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT pos = 0; + UInt32 mask = *state & 7; + if (size < 5) + return 0; + size -= 4; + ip += 5; + + for (;;) + { + Byte *p = data + pos; + const Byte *limit = data + size; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + + { + SizeT d = (SizeT)(p - data - pos); + pos = (SizeT)(p - data); + if (p >= limit) + { + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(mask >> 1) + 1]))) + { + mask = (mask >> 1) | 4; + pos++; + continue; + } + } + } + + if (Test86MSByte(p[4])) + { + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) + { + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; + } + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); + } + else + { + mask = (mask >> 1) | 4; + pos++; + } + } +} diff --git a/mp/src/utils/lzma/C/BraIA64.c b/mp/src/utils/lzma/C/BraIA64.c new file mode 100644 index 00000000..fa60356b --- /dev/null +++ b/mp/src/utils/lzma/C/BraIA64.c @@ -0,0 +1,69 @@ +/* BraIA64.c -- Converter for IA-64 code +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +static const Byte kBranchTable[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 7, 7, + 4, 4, 0, 0, 4, 4, 0, 0 +}; + +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding) +{ + SizeT i; + if (size < 16) + return 0; + size -= 16; + for (i = 0; i <= size; i += 16) + { + UInt32 instrTemplate = data[i] & 0x1F; + UInt32 mask = kBranchTable[instrTemplate]; + UInt32 bitPos = 5; + int slot; + for (slot = 0; slot < 3; slot++, bitPos += 41) + { + UInt32 bytePos, bitRes; + UInt64 instruction, instNorm; + int j; + if (((mask >> slot) & 1) == 0) + continue; + bytePos = (bitPos >> 3); + bitRes = bitPos & 0x7; + instruction = 0; + for (j = 0; j < 6; j++) + instruction += (UInt64)data[i + j + bytePos] << (8 * j); + + instNorm = instruction >> bitRes; + if (((instNorm >> 37) & 0xF) == 0x5 && ((instNorm >> 9) & 0x7) == 0) + { + UInt32 src = (UInt32)((instNorm >> 13) & 0xFFFFF); + UInt32 dest; + src |= ((UInt32)(instNorm >> 36) & 1) << 20; + + src <<= 4; + + if (encoding) + dest = ip + (UInt32)i + src; + else + dest = src - (ip + (UInt32)i); + + dest >>= 4; + + instNorm &= ~((UInt64)(0x8FFFFF) << 13); + instNorm |= ((UInt64)(dest & 0xFFFFF) << 13); + instNorm |= ((UInt64)(dest & 0x100000) << (36 - 20)); + + instruction &= (1 << bitRes) - 1; + instruction |= (instNorm << bitRes); + for (j = 0; j < 6; j++) + data[i + j + bytePos] = (Byte)(instruction >> (8 * j)); + } + } + } + return i; +} diff --git a/mp/src/utils/lzma/C/Compiler.h b/mp/src/utils/lzma/C/Compiler.h new file mode 100644 index 00000000..6e964897 --- /dev/null +++ b/mp/src/utils/lzma/C/Compiler.h @@ -0,0 +1,28 @@ +/* Compiler.h -- Compiler ypes +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + +#endif + +#endif diff --git a/mp/src/utils/lzma/C/CpuArch.c b/mp/src/utils/lzma/C/CpuArch.c new file mode 100644 index 00000000..d7f8b1d8 --- /dev/null +++ b/mp/src/utils/lzma/C/CpuArch.c @@ -0,0 +1,190 @@ +/* CpuArch.c -- CPU specific code +2012-05-29: Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#ifdef MY_CPU_X86_OR_AMD64 + +#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__) +#define USE_ASM +#endif + +#if !defined(USE_ASM) && _MSC_VER >= 1500 +#include +#endif + +#if defined(USE_ASM) && !defined(MY_CPU_AMD64) +static UInt32 CheckFlag(UInt32 flag) +{ + #ifdef _MSC_VER + __asm pushfd; + __asm pop EAX; + __asm mov EDX, EAX; + __asm xor EAX, flag; + __asm push EAX; + __asm popfd; + __asm pushfd; + __asm pop EAX; + __asm xor EAX, EDX; + __asm push EDX; + __asm popfd; + __asm and flag, EAX; + #else + __asm__ __volatile__ ( + "pushf\n\t" + "pop %%EAX\n\t" + "movl %%EAX,%%EDX\n\t" + "xorl %0,%%EAX\n\t" + "push %%EAX\n\t" + "popf\n\t" + "pushf\n\t" + "pop %%EAX\n\t" + "xorl %%EDX,%%EAX\n\t" + "push %%EDX\n\t" + "popf\n\t" + "andl %%EAX, %0\n\t": + "=c" (flag) : "c" (flag)); + #endif + return flag; +} +#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False; +#else +#define CHECK_CPUID_IS_SUPPORTED +#endif + +static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d) +{ + #ifdef USE_ASM + + #ifdef _MSC_VER + + UInt32 a2, b2, c2, d2; + __asm xor EBX, EBX; + __asm xor ECX, ECX; + __asm xor EDX, EDX; + __asm mov EAX, function; + __asm cpuid; + __asm mov a2, EAX; + __asm mov b2, EBX; + __asm mov c2, ECX; + __asm mov d2, EDX; + + *a = a2; + *b = b2; + *c = c2; + *d = d2; + + #else + + __asm__ __volatile__ ( + #if defined(MY_CPU_X86) && defined(__PIC__) + "mov %%ebx, %%edi;" + "cpuid;" + "xchgl %%ebx, %%edi;" + : "=a" (*a) , + "=D" (*b) , + #else + "cpuid" + : "=a" (*a) , + "=b" (*b) , + #endif + "=c" (*c) , + "=d" (*d) + : "0" (function)) ; + + #endif + + #else + + int CPUInfo[4]; + __cpuid(CPUInfo, function); + *a = CPUInfo[0]; + *b = CPUInfo[1]; + *c = CPUInfo[2]; + *d = CPUInfo[3]; + + #endif +} + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p) +{ + CHECK_CPUID_IS_SUPPORTED + MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]); + MyCPUID(1, &p->ver, &p->b, &p->c, &p->d); + return True; +} + +static UInt32 kVendors[][3] = +{ + { 0x756E6547, 0x49656E69, 0x6C65746E}, + { 0x68747541, 0x69746E65, 0x444D4163}, + { 0x746E6543, 0x48727561, 0x736C7561} +}; + +int x86cpuid_GetFirm(const Cx86cpuid *p) +{ + unsigned i; + for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++) + { + const UInt32 *v = kVendors[i]; + if (v[0] == p->vendor[0] && + v[1] == p->vendor[1] && + v[2] == p->vendor[2]) + return (int)i; + } + return -1; +} + +Bool CPU_Is_InOrder() +{ + Cx86cpuid p; + int firm; + UInt32 family, model; + if (!x86cpuid_CheckAndRead(&p)) + return True; + family = x86cpuid_GetFamily(&p); + model = x86cpuid_GetModel(&p); + firm = x86cpuid_GetFirm(&p); + switch (firm) + { + case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && ( + /* Atom CPU */ + model == 0x100C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */ + || model == 0x2006 /* 45 nm, Z6xx */ + || model == 0x2007 /* 32 nm, Z2460 */ + || model == 0x3005 /* 32 nm, Z2760 */ + || model == 0x3006 /* 32 nm, N2xxx, D2xxx */ + ))); + case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA))); + case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF)); + } + return True; +} + +#if !defined(MY_CPU_AMD64) && defined(_WIN32) +#include +static Bool CPU_Sys_Is_SSE_Supported() +{ + OSVERSIONINFO vi; + vi.dwOSVersionInfoSize = sizeof(vi); + if (!GetVersionEx(&vi)) + return False; + return (vi.dwMajorVersion >= 5); +} +#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False; +#else +#define CHECK_SYS_SSE_SUPPORT +#endif + +Bool CPU_Is_Aes_Supported() +{ + Cx86cpuid p; + CHECK_SYS_SSE_SUPPORT + if (!x86cpuid_CheckAndRead(&p)) + return False; + return (p.c >> 25) & 1; +} + +#endif diff --git a/mp/src/utils/lzma/C/CpuArch.h b/mp/src/utils/lzma/C/CpuArch.h new file mode 100644 index 00000000..4fee0093 --- /dev/null +++ b/mp/src/utils/lzma/C/CpuArch.h @@ -0,0 +1,157 @@ +/* CpuArch.h -- CPU specific code +2013-11-12: Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. +*/ + +#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) +#define MY_CPU_AMD64 +#endif + +#if defined(MY_CPU_AMD64) || defined(_M_IA64) +#define MY_CPU_64BIT +#endif + +#if defined(_M_IX86) || defined(__i386__) +#define MY_CPU_X86 +#endif + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + +#if defined(MY_CPU_X86) || defined(_M_ARM) +#define MY_CPU_32BIT +#endif + +#if defined(_WIN32) && defined(_M_ARM) +#define MY_CPU_ARM_LE +#endif + +#if defined(_WIN32) && defined(_M_IA64) +#define MY_CPU_IA64_LE +#endif + +#if defined(MY_CPU_X86_OR_AMD64) +#define MY_CPU_LE_UNALIGN +#endif + +#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) +#define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) || defined(__m68k__) || defined(__ARMEB__) || defined(__MIPSEB__) +#define MY_CPU_BE +#endif + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) +Stop_Compiling_Bad_Endian +#endif + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) +#define SetUi16(p, d) *(UInt16 *)(p) = (d); +#define SetUi32(p, d) *(UInt32 *)(p) = (d); +#define SetUi64(p, d) *(UInt64 *)(p) = (d); + +#else + +#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi16(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } + +#define SetUi32(p, d) { UInt32 _x_ = (d); \ + ((Byte *)(p))[0] = (Byte)_x_; \ + ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ + ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ + ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } + +#define SetUi64(p, d) { UInt64 _x64_ = (d); \ + SetUi32(p, (UInt32)_x64_); \ + SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } + +#endif + +#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) + +#include + +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#endif + +#define GetBe16(p) ((UInt16)(((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])) + + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +Bool x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) +#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) +#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) + +Bool CPU_Is_InOrder(); +Bool CPU_Is_Aes_Supported(); + +#endif + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Delta.c b/mp/src/utils/lzma/C/Delta.c new file mode 100644 index 00000000..e3edd21e --- /dev/null +++ b/mp/src/utils/lzma/C/Delta.c @@ -0,0 +1,64 @@ +/* Delta.c -- Delta converter +2009-05-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Delta.h" + +void Delta_Init(Byte *state) +{ + unsigned i; + for (i = 0; i < DELTA_STATE_SIZE; i++) + state[i] = 0; +} + +static void MyMemCpy(Byte *dest, const Byte *src, unsigned size) +{ + unsigned i; + for (i = 0; i < size; i++) + dest[i] = src[i]; +} + +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + Byte buf[DELTA_STATE_SIZE]; + unsigned j = 0; + MyMemCpy(buf, state, delta); + { + SizeT i; + for (i = 0; i < size;) + { + for (j = 0; j < delta && i < size; i++, j++) + { + Byte b = data[i]; + data[i] = (Byte)(b - buf[j]); + buf[j] = b; + } + } + } + if (j == delta) + j = 0; + MyMemCpy(state, buf + j, delta - j); + MyMemCpy(state + delta - j, buf, j); +} + +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size) +{ + Byte buf[DELTA_STATE_SIZE]; + unsigned j = 0; + MyMemCpy(buf, state, delta); + { + SizeT i; + for (i = 0; i < size;) + { + for (j = 0; j < delta && i < size; i++, j++) + { + buf[j] = data[i] = (Byte)(buf[j] + data[i]); + } + } + } + if (j == delta) + j = 0; + MyMemCpy(state, buf + j, delta - j); + MyMemCpy(state + delta - j, buf, j); +} diff --git a/mp/src/utils/lzma/C/Delta.h b/mp/src/utils/lzma/C/Delta.h new file mode 100644 index 00000000..2fa54ad6 --- /dev/null +++ b/mp/src/utils/lzma/C/Delta.h @@ -0,0 +1,19 @@ +/* Delta.h -- Delta converter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __DELTA_H +#define __DELTA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define DELTA_STATE_SIZE 256 + +void Delta_Init(Byte *state); +void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size); +void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/LzFind.c b/mp/src/utils/lzma/C/LzFind.c new file mode 100644 index 00000000..262b395b --- /dev/null +++ b/mp/src/utils/lzma/C/LzFind.c @@ -0,0 +1,763 @@ +/* LzFind.c -- Match finder for LZ algorithms +2009-04-22 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)3 << 30) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + if (!p->directInput) + { + alloc->Free(alloc, p->bufferBase); + p->bufferBase = 0; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (p->bufferBase == 0 || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != 0); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } +Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - p->streamPos; + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + p->result = p->stream->Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos + p->keepSizeBefore)); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + if (p->directInput) + return 0; + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + UInt32 i; + p->bufferBase = 0; + p->directInput = 0; + p->hash = 0; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hash); + p->hash = 0; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return 0; + return (CLzRef *)alloc->Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc) +{ + UInt32 sizeReserv; + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + sizeReserv = historySize >> 1; + if (historySize > ((UInt32)2 << 30)) + sizeReserv = historySize >> 2; + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = historySize + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + UInt32 prevSize = p->hashSizeSum + p->numSons; + UInt32 newSize; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize); + newSize = p->hashSizeSum + p->numSons; + if (p->hash != 0 && prevSize == newSize) + return 1; + MatchFinder_FreeThisClassMemory(p, alloc); + p->hash = AllocRefs(newSize, alloc); + if (p->hash != 0) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + if (limit2 < limit) + limit = limit2; + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + +void MatchFinder_Init(CMatchFinder *p) +{ + UInt32 i; + for (i = 0; i < p->hashSizeSum; i++) + p->hash[i] = kEmptyHashValue; + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + MatchFinder_ReadBlock(p); + MatchFinder_SetLimits(p); +} + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems) +{ + UInt32 i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons); + MatchFinder_ReduceOffsets(p, subValue); +} + +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + +static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } +} + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \ + lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, delta2, maxLen, offset; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + delta2 = p->pos - p->hash[hash2Value]; + curMatch = p->hash[kFix3HashSize + hashValue]; + + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + + + maxLen = 2; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[0] = maxLen; + distances[1] = delta2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + delta2 = p->pos - p->hash[ hash2Value]; + delta3 = p->pos - p->hash[kFix3HashSize + hash3Value]; + curMatch = p->hash[kFix4HashSize + hashValue]; + + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + + maxLen = 1; + offset = 0; + if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = delta2 - 1; + offset = 2; + } + if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur) + { + maxLen = 3; + distances[offset + 1] = delta3 - 1; + offset += 2; + delta2 = delta3; + } + if (offset != 0) + { + for (; maxLen != lenLimit; maxLen++) + if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen]) + break; + distances[offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + if (maxLen < 3) + maxLen = 3; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value; + SKIP_HEADER(3) + HASH3_CALC; + curMatch = p->hash[kFix3HashSize + hashValue]; + p->hash[hash2Value] = + p->hash[kFix3HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = p->pos; + p->hash[kFix4HashSize + hashValue] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 hash2Value, hash3Value; + SKIP_HEADER(4) + HASH4_CALC; + curMatch = p->hash[kFix4HashSize + hashValue]; + p->hash[ hash2Value] = + p->hash[kFix3HashSize + hash3Value] = + p->hash[kFix4HashSize + hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hashValue]; + p->hash[hashValue] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } +} diff --git a/mp/src/utils/lzma/C/LzFind.h b/mp/src/utils/lzma/C/LzFind.h new file mode 100644 index 00000000..706143d2 --- /dev/null +++ b/mp/src/utils/lzma/C/LzFind.h @@ -0,0 +1,111 @@ +/* LzFind.h -- Match finder for LZ algorithms +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_H +#define __LZ_FIND_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + int streamEndWasReached; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + int directInput; + size_t directInputRem; + int btMode; + int bigHash; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + UInt32 numSons; + SRes result; + UInt32 crc[256]; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) +#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)]) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAlloc *alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetIndexByte_Func GetIndexByte; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init(CMatchFinder *p); +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/LzFindMt.c b/mp/src/utils/lzma/C/LzFindMt.c new file mode 100644 index 00000000..cee8ea74 --- /dev/null +++ b/mp/src/utils/lzma/C/LzFindMt.c @@ -0,0 +1,794 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2014-12-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "LzHash.h" + +#include "LzFindMt.h" + +void MtSync_Construct(CMtSync *p) +{ + p->wasCreated = False; + p->csWasInitialized = False; + p->csWasEntered = False; + Thread_Construct(&p->thread); + Event_Construct(&p->canStart); + Event_Construct(&p->wasStarted); + Event_Construct(&p->wasStopped); + Semaphore_Construct(&p->freeSemaphore); + Semaphore_Construct(&p->filledSemaphore); +} + +void MtSync_GetNextBlock(CMtSync *p) +{ + if (p->needStart) + { + p->numProcessedBlocks = 1; + p->needStart = False; + p->stopWriting = False; + p->exit = False; + Event_Reset(&p->wasStarted); + Event_Reset(&p->wasStopped); + + Event_Set(&p->canStart); + Event_Wait(&p->wasStarted); + } + else + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + p->numProcessedBlocks++; + Semaphore_Release1(&p->freeSemaphore); + } + Semaphore_Wait(&p->filledSemaphore); + CriticalSection_Enter(&p->cs); + p->csWasEntered = True; +} + +/* MtSync_StopWriting must be called if Writing was started */ + +void MtSync_StopWriting(CMtSync *p) +{ + UInt32 myNumBlocks = p->numProcessedBlocks; + if (!Thread_WasCreated(&p->thread) || p->needStart) + return; + p->stopWriting = True; + if (p->csWasEntered) + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + } + Semaphore_Release1(&p->freeSemaphore); + + Event_Wait(&p->wasStopped); + + while (myNumBlocks++ != p->numProcessedBlocks) + { + Semaphore_Wait(&p->filledSemaphore); + Semaphore_Release1(&p->freeSemaphore); + } + p->needStart = True; +} + +void MtSync_Destruct(CMtSync *p) +{ + if (Thread_WasCreated(&p->thread)) + { + MtSync_StopWriting(p); + p->exit = True; + if (p->needStart) + Event_Set(&p->canStart); + Thread_Wait(&p->thread); + Thread_Close(&p->thread); + } + if (p->csWasInitialized) + { + CriticalSection_Delete(&p->cs); + p->csWasInitialized = False; + } + + Event_Close(&p->canStart); + Event_Close(&p->wasStarted); + Event_Close(&p->wasStopped); + Semaphore_Close(&p->freeSemaphore); + Semaphore_Close(&p->filledSemaphore); + + p->wasCreated = False; +} + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + +static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + if (p->wasCreated) + return SZ_OK; + + RINOK_THREAD(CriticalSection_Init(&p->cs)); + p->csWasInitialized = True; + + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + + RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); + RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); + + p->needStart = True; + + RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->wasCreated = True; + return SZ_OK; +} + +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); + if (res != SZ_OK) + MtSync_Destruct(p); + return res; +} + +void MtSync_Init(CMtSync *p) { p->needStart = True; } + +#define kMtMaxValForNormalize 0xFFFFFFFF + +#define DEF_GetHeads2(name, v, action) \ +static void GetHeads ## name(const Byte *p, UInt32 pos, \ +UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ +{ action; for (; numHeads != 0; numHeads--) { \ +const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } + +#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) + +DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc; ) +DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) +DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ + +void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + for (;;) + { + UInt32 numProcessedBlocks = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = numProcessedBlocks; + Event_Set(&p->wasStopped); + break; + } + + { + CMatchFinder *mf = mt->MatchFinder; + if (MatchFinder_NeedMove(mf)) + { + CriticalSection_Enter(&mt->btSync.cs); + CriticalSection_Enter(&mt->hashSync.cs); + { + const Byte *beforePtr = MatchFinder_GetPointerToCurrentPos(mf); + const Byte *afterPtr; + MatchFinder_MoveBlock(mf); + afterPtr = MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= beforePtr - afterPtr; + mt->buffer -= beforePtr - afterPtr; + } + CriticalSection_Leave(&mt->btSync.cs); + CriticalSection_Leave(&mt->hashSync.cs); + continue; + } + + Semaphore_Wait(&p->freeSemaphore); + + MatchFinder_ReadIfRequired(mf); + if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) + { + UInt32 subValue = (mf->pos - mf->historySize - 1); + MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, mf->hashMask + 1); + } + { + UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; + UInt32 num = mf->streamPos - mf->pos; + heads[0] = 2; + heads[1] = num; + if (num >= mf->numHashBytes) + { + num = num - mf->numHashBytes + 1; + if (num > kMtHashBlockSize - 2) + num = kMtHashBlockSize - 2; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + heads[0] += num; + } + mf->pos += num; + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) +{ + MtSync_GetNextBlock(&p->hashSync); + p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; + p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; + p->hashNumAvail = p->hashBuf[p->hashBufPos++]; +} + +#define kEmptyHashValue 0 + +/* #define MFMT_GM_INLINE */ + +#ifdef MFMT_GM_INLINE + +#define NO_INLINE MY_FAST_CALL + +Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes) +{ + do + { + UInt32 *distances = _distances + 1; + UInt32 curMatch = pos - *hash++; + + CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + (_cyclicBufferPos << 1); + UInt32 len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + UInt32 maxLen = _maxLen; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + { + CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + UInt32 len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + *distances++ = maxLen = len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } + pos++; + _cyclicBufferPos++; + cur++; + { + UInt32 num = (UInt32)(distances - _distances); + *_distances = num - 1; + _distances += num; + limit -= num; + } + } + while (limit > 0 && --size != 0); + *posRes = pos; + return limit; +} + +#endif + +void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + UInt32 numProcessed = 0; + UInt32 curPos = 2; + UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); + distances[1] = p->hashNumAvail; + while (curPos < limit) + { + if (p->hashBufPos == p->hashBufPosLimit) + { + MatchFinderMt_GetNextBlock_Hash(p); + distances[1] = numProcessed + p->hashNumAvail; + if (p->hashNumAvail >= p->numHashBytes) + continue; + for (; p->hashNumAvail != 0; p->hashNumAvail--) + distances[curPos++] = 0; + break; + } + { + UInt32 size = p->hashBufPosLimit - p->hashBufPos; + UInt32 lenLimit = p->matchMaxLen; + UInt32 pos = p->pos; + UInt32 cyclicBufferPos = p->cyclicBufferPos; + if (lenLimit >= p->hashNumAvail) + lenLimit = p->hashNumAvail; + { + UInt32 size2 = p->hashNumAvail - lenLimit + 1; + if (size2 < size) + size = size2; + size2 = p->cyclicBufferSize - cyclicBufferPos; + if (size2 < size) + size = size2; + } + #ifndef MFMT_GM_INLINE + while (curPos < limit && size-- != 0) + { + UInt32 *startDistances = distances + curPos; + UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], + pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + startDistances + 1, p->numHashBytes - 1) - startDistances); + *startDistances = num - 1; + curPos += num; + cyclicBufferPos++; + pos++; + p->buffer++; + } + #else + { + UInt32 posRes; + curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos) , size, &posRes); + p->hashBufPos += posRes - pos; + cyclicBufferPos += posRes - pos; + p->buffer += posRes - pos; + pos = posRes; + } + #endif + + numProcessed += pos - p->pos; + p->hashNumAvail -= pos - p->pos; + p->pos = pos; + if (cyclicBufferPos == p->cyclicBufferSize) + cyclicBufferPos = 0; + p->cyclicBufferPos = cyclicBufferPos; + } + } + distances[0] = curPos; +} + +void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) +{ + CMtSync *sync = &p->hashSync; + if (!sync->needStart) + { + CriticalSection_Enter(&sync->cs); + sync->csWasEntered = True; + } + + BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + + if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) + { + UInt32 subValue = p->pos - p->cyclicBufferSize; + MatchFinder_Normalize3(subValue, p->son, p->cyclicBufferSize * 2); + p->pos -= subValue; + } + + if (!sync->needStart) + { + CriticalSection_Leave(&sync->cs); + sync->csWasEntered = False; + } +} + +void BtThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->btSync; + for (;;) + { + UInt32 blockIndex = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = blockIndex; + MtSync_StopWriting(&mt->hashSync); + Event_Set(&p->wasStopped); + break; + } + Semaphore_Wait(&p->freeSemaphore); + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_Construct(CMatchFinderMt *p) +{ + p->hashBuf = 0; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->hashBuf); + p->hashBuf = 0; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc) +{ + MtSync_Destruct(&p->hashSync); + MtSync_Destruct(&p->btSync); + MatchFinderMt_FreeMem(p, alloc); +} + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc) +{ + CMatchFinder *mf = p->MatchFinder; + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (p->hashBuf == 0) + { + p->hashBuf = (UInt32 *)alloc->Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + if (p->hashBuf == 0) + return SZ_ERROR_MEM; + p->btBuf = p->hashBuf + kHashBufferSize; + } + keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); + keepAddBufferAfter += kMtHashBlockSize; + if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) + return SZ_ERROR_MEM; + + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + return SZ_OK; +} + +/* Call it after ReleaseStream / SetStream */ +void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = p->MatchFinder; + p->btBufPos = p->btBufPosLimit = 0; + p->hashBufPos = p->hashBufPosLimit = 0; + MatchFinder_Init(mf); + p->pointerToCurPos = MatchFinder_GetPointerToCurrentPos(mf); + p->btNumAvailBytes = 0; + p->lzPos = p->historySize + 1; + + p->hash = mf->hash; + p->fixedHashSize = mf->fixedHashSize; + p->crc = mf->crc; + + p->son = mf->son; + p->matchMaxLen = mf->matchMaxLen; + p->numHashBytes = mf->numHashBytes; + p->pos = mf->pos; + p->buffer = mf->buffer; + p->cyclicBufferPos = mf->cyclicBufferPos; + p->cyclicBufferSize = mf->cyclicBufferSize; + p->cutValue = mf->cutValue; +} + +/* ReleaseStream is required to finish multithreading */ +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) +{ + MtSync_StopWriting(&p->btSync); + /* p->MatchFinder->ReleaseStream(); */ +} + +void MatchFinderMt_Normalize(CMatchFinderMt *p) +{ + MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); + p->lzPos = p->historySize + 1; +} + +void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + UInt32 blockIndex; + MtSync_GetNextBlock(&p->btSync); + blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); + p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; + p->btBufPosLimit += p->btBuf[p->btBufPos++]; + p->btNumAvailBytes = p->btBuf[p->btBufPos++]; + if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) + MatchFinderMt_Normalize(p); +} + +const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + +UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + GET_NEXT_BLOCK_IF_REQUIRED; + return p->btNumAvailBytes; +} + +Byte MatchFinderMt_GetIndexByte(CMatchFinderMt *p, Int32 index) +{ + return p->pointerToCurPos[index]; +} + +UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, curMatch2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH2_CALC + + curMatch2 = hash[hash2Value]; + hash[hash2Value] = lzPos; + + if (curMatch2 >= matchMinPos) + if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + *distances++ = 2; + *distances++ = lzPos - curMatch2 - 1; + } + return distances; +} + +UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, curMatch2, curMatch3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH3_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + *distances++ = 3; + *distances++ = lzPos - curMatch3 - 1; + } + return distances; +} + +/* +UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 hash2Value, hash3Value, hash4Value, curMatch2, curMatch3, curMatch4; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH4_CALC + + curMatch2 = hash[ hash2Value]; + curMatch3 = hash[kFix3HashSize + hash3Value]; + curMatch4 = hash[kFix4HashSize + hash4Value]; + + hash[ hash2Value] = + hash[kFix3HashSize + hash3Value] = + hash[kFix4HashSize + hash4Value] = + lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch3 - 1; + if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) + { + distances[0] = 4; + return distances + 2; + } + distances[0] = 3; + distances += 2; + } + + if (curMatch4 >= matchMinPos) + if ( + cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && + cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] + ) + { + *distances++ = 4; + *distances++ = lzPos - curMatch4 - 1; + } + return distances; +} +*/ + +#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; + +UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + p->btNumAvailBytes--; + { + UInt32 i; + for (i = 0; i < len; i += 2) + { + *distances++ = *btBuf++; + *distances++ = *btBuf++; + } + } + INCREASE_LZ_POS + return len; +} + +UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + + if (len == 0) + { + if (p->btNumAvailBytes-- >= 4) + len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + } + else + { + /* Condition: there are matches in btBuf with length < p->numHashBytes */ + UInt32 *distances2; + p->btNumAvailBytes--; + distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + do + { + *distances2++ = *btBuf++; + *distances2++ = *btBuf++; + } + while ((len -= 2) != 0); + len = (UInt32)(distances2 - (distances)); + } + INCREASE_LZ_POS + return len; +} + +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); + +void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT +} + +void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(2) + UInt32 hash2Value; + MT_HASH2_CALC + hash[hash2Value] = p->lzPos; + SKIP_FOOTER_MT +} + +void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(3) + UInt32 hash2Value, hash3Value; + MT_HASH3_CALC + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER_MT +} + +/* +void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(4) + UInt32 hash2Value, hash3Value, hash4Value; + MT_HASH4_CALC + hash[kFix4HashSize + hash4Value] = + hash[kFix3HashSize + hash3Value] = + hash[ hash2Value] = + p->lzPos; + SKIP_FOOTER_MT +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinderMt_GetIndexByte; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + switch(p->MatchFinder->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)0; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; + break; + case 3: + p->GetHeadsFunc = GetHeads3; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; + break; + default: + /* case 4: */ + p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + /* p->GetHeadsFunc = GetHeads4; */ + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; + break; + /* + default: + p->GetHeadsFunc = GetHeads5; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + break; + */ + } +} diff --git a/mp/src/utils/lzma/C/LzFindMt.h b/mp/src/utils/lzma/C/LzFindMt.h new file mode 100644 index 00000000..6a7095b0 --- /dev/null +++ b/mp/src/utils/lzma/C/LzFindMt.h @@ -0,0 +1,101 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H + +#include "LzFind.h" +#include "Threads.h" + +EXTERN_C_BEGIN + +#define kMtHashBlockSize (1 << 13) +#define kMtHashNumBlocks (1 << 3) +#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) + +#define kMtBtBlockSize (1 << 14) +#define kMtBtNumBlocks (1 << 6) +#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) + +typedef struct _CMtSync +{ + Bool wasCreated; + Bool needStart; + Bool exit; + Bool stopWriting; + + CThread thread; + CAutoResetEvent canStart; + CAutoResetEvent wasStarted; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + Bool csWasInitialized; + Bool csWasEntered; + CCriticalSection cs; + UInt32 numProcessedBlocks; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + UInt32 btBufPos; + UInt32 btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; +} CMatchFinderMt; + +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAlloc *alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/LzHash.h b/mp/src/utils/lzma/C/LzHash.h new file mode 100644 index 00000000..f3e89966 --- /dev/null +++ b/mp/src/utils/lzma/C/LzHash.h @@ -0,0 +1,54 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2009-02-07 : Igor Pavlov : Public domain */ + +#ifndef __LZ_HASH_H +#define __LZ_HASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \ + hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \ + hash4Value &= (kHash4Size - 1); } + +/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \ + hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/mp/src/utils/lzma/C/Lzma2Dec.c b/mp/src/utils/lzma/C/Lzma2Dec.c new file mode 100644 index 00000000..502a1588 --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma2Dec.c @@ -0,0 +1,352 @@ +/* Lzma2Dec.c -- LZMA2 Decoder +2010-12-15 : Igor Pavlov : Public domain */ + +/* #define SHOW_DEBUG_INFO */ + +#include "Precomp.h" + +#ifdef SHOW_DEBUG_INFO +#include +#endif + +#include + +#include "Lzma2Dec.h" + +/* +00000000 - EOS +00000001 U U - Uncompressed Reset Dic +00000010 U U - Uncompressed No Reset +100uuuuu U U P P - LZMA no reset +101uuuuu U U P P - LZMA reset state +110uuuuu U U P P S - LZMA reset state + new prop +111uuuuu U U P P S - LZMA reset state + new prop + reset dic + + u, U - Unpack Size + P - Pack Size + S - Props +*/ + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0) + +#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3) +#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2) + +#define LZMA2_LCLP_MAX 4 +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#ifdef SHOW_DEBUG_INFO +#define PRF(x) x +#else +#define PRF(x) +#endif + +typedef enum +{ + LZMA2_STATE_CONTROL, + LZMA2_STATE_UNPACK0, + LZMA2_STATE_UNPACK1, + LZMA2_STATE_PACK0, + LZMA2_STATE_PACK1, + LZMA2_STATE_PROP, + LZMA2_STATE_DATA, + LZMA2_STATE_DATA_CONT, + LZMA2_STATE_FINISHED, + LZMA2_STATE_ERROR +} ELzma2State; + +static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) +{ + UInt32 dicSize; + if (prop > 40) + return SZ_ERROR_UNSUPPORTED; + dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); + props[0] = (Byte)LZMA2_LCLP_MAX; + props[1] = (Byte)(dicSize); + props[2] = (Byte)(dicSize >> 8); + props[3] = (Byte)(dicSize >> 16); + props[4] = (Byte)(dicSize >> 24); + return SZ_OK; +} + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc) +{ + Byte props[LZMA_PROPS_SIZE]; + RINOK(Lzma2Dec_GetOldProps(prop, props)); + return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); +} + +void Lzma2Dec_Init(CLzma2Dec *p) +{ + p->state = LZMA2_STATE_CONTROL; + p->needInitDic = True; + p->needInitState = True; + p->needInitProp = True; + LzmaDec_Init(&p->decoder); +} + +static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) +{ + switch(p->state) + { + case LZMA2_STATE_CONTROL: + p->control = b; + PRF(printf("\n %4X ", p->decoder.dicPos)); + PRF(printf(" %2X", b)); + if (p->control == 0) + return LZMA2_STATE_FINISHED; + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if ((p->control & 0x7F) > 2) + return LZMA2_STATE_ERROR; + p->unpackSize = 0; + } + else + p->unpackSize = (UInt32)(p->control & 0x1F) << 16; + return LZMA2_STATE_UNPACK0; + + case LZMA2_STATE_UNPACK0: + p->unpackSize |= (UInt32)b << 8; + return LZMA2_STATE_UNPACK1; + + case LZMA2_STATE_UNPACK1: + p->unpackSize |= (UInt32)b; + p->unpackSize++; + PRF(printf(" %8d", p->unpackSize)); + return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; + + case LZMA2_STATE_PACK0: + p->packSize = (UInt32)b << 8; + return LZMA2_STATE_PACK1; + + case LZMA2_STATE_PACK1: + p->packSize |= (UInt32)b; + p->packSize++; + PRF(printf(" %8d", p->packSize)); + return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP: + (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA); + + case LZMA2_STATE_PROP: + { + int lc, lp; + if (b >= (9 * 5 * 5)) + return LZMA2_STATE_ERROR; + lc = b % 9; + b /= 9; + p->decoder.prop.pb = b / 5; + lp = b % 5; + if (lc + lp > LZMA2_LCLP_MAX) + return LZMA2_STATE_ERROR; + p->decoder.prop.lc = lc; + p->decoder.prop.lp = lp; + p->needInitProp = False; + return LZMA2_STATE_DATA; + } + } + return LZMA2_STATE_ERROR; +} + +static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) +{ + memcpy(p->dic + p->dicPos, src, size); + p->dicPos += size; + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) + p->checkDicSize = p->prop.dicSize; + p->processedPos += (UInt32)size; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->state != LZMA2_STATE_FINISHED) + { + SizeT dicPos = p->decoder.dicPos; + if (p->state == LZMA2_STATE_ERROR) + return SZ_ERROR_DATA; + if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + (*srcLen)++; + p->state = Lzma2Dec_UpdateState(p, *src++); + continue; + } + { + SizeT destSizeCur = dicLimit - dicPos; + SizeT srcSizeCur = inSize - *srcLen; + ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; + + if (p->unpackSize <= destSizeCur) + { + destSizeCur = (SizeT)p->unpackSize; + curFinishMode = LZMA_FINISH_END; + } + + if (LZMA2_IS_UNCOMPRESSED_STATE(p)) + { + if (*srcLen == inSize) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + if (p->state == LZMA2_STATE_DATA) + { + Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); + if (initDic) + p->needInitProp = p->needInitState = True; + else if (p->needInitDic) + return SZ_ERROR_DATA; + p->needInitDic = False; + LzmaDec_InitDicAndState(&p->decoder, initDic, False); + } + + if (srcSizeCur > destSizeCur) + srcSizeCur = destSizeCur; + + if (srcSizeCur == 0) + return SZ_ERROR_DATA; + + LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->unpackSize -= (UInt32)srcSizeCur; + p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; + } + else + { + SizeT outSizeProcessed; + SRes res; + + if (p->state == LZMA2_STATE_DATA) + { + int mode = LZMA2_GET_LZMA_MODE(p); + Bool initDic = (mode == 3); + Bool initState = (mode > 0); + if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) + return SZ_ERROR_DATA; + + LzmaDec_InitDicAndState(&p->decoder, initDic, initState); + p->needInitDic = False; + p->needInitState = False; + p->state = LZMA2_STATE_DATA_CONT; + } + if (srcSizeCur > p->packSize) + srcSizeCur = (SizeT)p->packSize; + + res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); + + src += srcSizeCur; + *srcLen += srcSizeCur; + p->packSize -= (UInt32)srcSizeCur; + + outSizeProcessed = p->decoder.dicPos - dicPos; + p->unpackSize -= (UInt32)outSizeProcessed; + + RINOK(res); + if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) + return res; + + if (srcSizeCur == 0 && outSizeProcessed == 0) + { + if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || + p->unpackSize != 0 || p->packSize != 0) + return SZ_ERROR_DATA; + p->state = LZMA2_STATE_CONTROL; + } + if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + *status = LZMA_STATUS_NOT_FINISHED; + } + } + } + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen, inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT srcSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->decoder.dicPos == p->decoder.dicBufSize) + p->decoder.dicPos = 0; + dicPos = p->decoder.dicPos; + if (outSize > p->decoder.dicBufSize - dicPos) + { + outSizeCur = p->decoder.dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); + src += srcSizeCur; + inSize -= srcSizeCur; + *srcLen += srcSizeCur; + outSizeCur = p->decoder.dicPos - dicPos; + memcpy(dest, p->decoder.dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzma2Dec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + Lzma2Dec_Construct(&p); + RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); + p.decoder.dic = dest; + p.decoder.dicBufSize = outSize; + Lzma2Dec_Init(&p); + *srcLen = inSize; + res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.decoder.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + Lzma2Dec_FreeProbs(&p, alloc); + return res; +} diff --git a/mp/src/utils/lzma/C/Lzma2Dec.h b/mp/src/utils/lzma/C/Lzma2Dec.h new file mode 100644 index 00000000..367daf6b --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma2Dec.h @@ -0,0 +1,80 @@ +/* Lzma2Dec.h -- LZMA2 Decoder +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_DEC_H +#define __LZMA2_DEC_H + +#include "LzmaDec.h" + +EXTERN_C_BEGIN + +/* ---------- State Interface ---------- */ + +typedef struct +{ + CLzmaDec decoder; + UInt32 packSize; + UInt32 unpackSize; + int state; + Byte control; + Bool needInitDic; + Bool needInitState; + Bool needInitProp; +} CLzma2Dec; + +#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder) +#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc); +#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc); + +SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc); +void Lzma2Dec_Init(CLzma2Dec *p); + + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen or dicLimit). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + SZ_ERROR_DATA - Data error +*/ + +SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + +SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - use smallest number of input bytes + LZMA_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Lzma2Enc.c b/mp/src/utils/lzma/C/Lzma2Enc.c new file mode 100644 index 00000000..0c8e02e9 --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma2Enc.c @@ -0,0 +1,493 @@ +/* Lzma2Enc.c -- LZMA2 Encoder +2012-06-19 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #include */ +#include + +/* #define _7ZIP_ST */ + +#include "Lzma2Enc.h" + +#ifndef _7ZIP_ST +#include "MtCoder.h" +#else +#define NUM_MT_CODER_THREADS_MAX 1 +#endif + +#define LZMA2_CONTROL_LZMA (1 << 7) +#define LZMA2_CONTROL_COPY_NO_RESET 2 +#define LZMA2_CONTROL_COPY_RESET_DIC 1 +#define LZMA2_CONTROL_EOF 0 + +#define LZMA2_LCLP_MAX 4 + +#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) + +#define LZMA2_PACK_SIZE_MAX (1 << 16) +#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX +#define LZMA2_UNPACK_SIZE_MAX (1 << 21) +#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX + +#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16) + + +#define PRF(x) /* x */ + +/* ---------- CLzma2EncInt ---------- */ + +typedef struct +{ + CLzmaEncHandle enc; + UInt64 srcPos; + Byte props; + Bool needInitState; + Bool needInitProp; +} CLzma2EncInt; + +static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props) +{ + Byte propsEncoded[LZMA_PROPS_SIZE]; + SizeT propsSize = LZMA_PROPS_SIZE; + RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps)); + RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize)); + p->srcPos = 0; + p->props = propsEncoded[0]; + p->needInitState = True; + p->needInitProp = True; + return SZ_OK; +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize); +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp); +void LzmaEnc_Finish(CLzmaEncHandle pp); +void LzmaEnc_SaveState(CLzmaEncHandle pp); +void LzmaEnc_RestoreState(CLzmaEncHandle pp); + + +static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf, + size_t *packSizeRes, ISeqOutStream *outStream) +{ + size_t packSizeLimit = *packSizeRes; + size_t packSize = packSizeLimit; + UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX; + unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0); + Bool useCopyBlock; + SRes res; + + *packSizeRes = 0; + if (packSize < lzHeaderSize) + return SZ_ERROR_OUTPUT_EOF; + packSize -= lzHeaderSize; + + LzmaEnc_SaveState(p->enc); + res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState, + outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize); + + PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize)); + + if (unpackSize == 0) + return res; + + if (res == SZ_OK) + useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16)); + else + { + if (res != SZ_ERROR_OUTPUT_EOF) + return res; + res = SZ_OK; + useCopyBlock = True; + } + + if (useCopyBlock) + { + size_t destPos = 0; + PRF(printf("################# COPY ")); + while (unpackSize > 0) + { + UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE; + if (packSizeLimit - destPos < u + 3) + return SZ_ERROR_OUTPUT_EOF; + outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET); + outBuf[destPos++] = (Byte)((u - 1) >> 8); + outBuf[destPos++] = (Byte)(u - 1); + memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u); + unpackSize -= u; + destPos += u; + p->srcPos += u; + if (outStream) + { + *packSizeRes += destPos; + if (outStream->Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + destPos = 0; + } + else + *packSizeRes = destPos; + /* needInitState = True; */ + } + LzmaEnc_RestoreState(p->enc); + return SZ_OK; + } + { + size_t destPos = 0; + UInt32 u = unpackSize - 1; + UInt32 pm = (UInt32)(packSize - 1); + unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0); + + PRF(printf(" ")); + + outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | ((u >> 16) & 0x1F)); + outBuf[destPos++] = (Byte)(u >> 8); + outBuf[destPos++] = (Byte)u; + outBuf[destPos++] = (Byte)(pm >> 8); + outBuf[destPos++] = (Byte)pm; + + if (p->needInitProp) + outBuf[destPos++] = p->props; + + p->needInitProp = False; + p->needInitState = False; + destPos += packSize; + p->srcPos += unpackSize; + + if (outStream) + if (outStream->Write(outStream, outBuf, destPos) != destPos) + return SZ_ERROR_WRITE; + *packSizeRes = destPos; + return SZ_OK; + } +} + +/* ---------- Lzma2 Props ---------- */ + +void Lzma2EncProps_Init(CLzma2EncProps *p) +{ + LzmaEncProps_Init(&p->lzmaProps); + p->numTotalThreads = -1; + p->numBlockThreads = -1; + p->blockSize = 0; +} + +void Lzma2EncProps_Normalize(CLzma2EncProps *p) +{ + int t1, t1n, t2, t3; + { + CLzmaEncProps lzmaProps = p->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + t1n = lzmaProps.numThreads; + } + + t1 = p->lzmaProps.numThreads; + t2 = p->numBlockThreads; + t3 = p->numTotalThreads; + + if (t2 > NUM_MT_CODER_THREADS_MAX) + t2 = NUM_MT_CODER_THREADS_MAX; + + if (t3 <= 0) + { + if (t2 <= 0) + t2 = 1; + t3 = t1n * t2; + } + else if (t2 <= 0) + { + t2 = t3 / t1n; + if (t2 == 0) + { + t1 = 1; + t2 = t3; + } + if (t2 > NUM_MT_CODER_THREADS_MAX) + t2 = NUM_MT_CODER_THREADS_MAX; + } + else if (t1 <= 0) + { + t1 = t3 / t2; + if (t1 == 0) + t1 = 1; + } + else + t3 = t1n * t2; + + p->lzmaProps.numThreads = t1; + + LzmaEncProps_Normalize(&p->lzmaProps); + + if (p->blockSize == 0) + { + UInt32 dictSize = p->lzmaProps.dictSize; + UInt64 blockSize = (UInt64)dictSize << 2; + const UInt32 kMinSize = (UInt32)1 << 20; + const UInt32 kMaxSize = (UInt32)1 << 28; + if (blockSize < kMinSize) blockSize = kMinSize; + if (blockSize > kMaxSize) blockSize = kMaxSize; + if (blockSize < dictSize) blockSize = dictSize; + p->blockSize = (size_t)blockSize; + } + if (t2 > 1) + { + UInt64 temp = p->lzmaProps.reduceSize + p->blockSize - 1; + if (temp > p->lzmaProps.reduceSize) + { + UInt64 numBlocks = temp / p->blockSize; + if (numBlocks < t2) + { + t2 = (UInt32)numBlocks; + t3 = t1 * t2; + } + } + } + p->numBlockThreads = t2; + p->numTotalThreads = t3; +} + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + +/* ---------- Lzma2 ---------- */ + +typedef struct +{ + Byte propEncoded; + CLzma2EncProps props; + + Byte *outBuf; + + ISzAlloc *alloc; + ISzAlloc *allocBig; + + CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX]; + + #ifndef _7ZIP_ST + CMtCoder mtCoder; + #endif + +} CLzma2Enc; + + +/* ---------- Lzma2EncThread ---------- */ + +static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + UInt64 packTotal = 0; + SRes res = SZ_OK; + + if (mainEncoder->outBuf == 0) + { + mainEncoder->outBuf = (Byte *)IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX); + if (mainEncoder->outBuf == 0) + return SZ_ERROR_MEM; + } + RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); + RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE, + mainEncoder->alloc, mainEncoder->allocBig)); + for (;;) + { + size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX; + res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream); + if (res != SZ_OK) + break; + packTotal += packSize; + res = Progress(progress, p->srcPos, packTotal); + if (res != SZ_OK) + break; + if (packSize == 0) + break; + } + LzmaEnc_Finish(p->enc); + if (res == SZ_OK) + { + Byte b = 0; + if (outStream->Write(outStream, &b, 1) != 1) + return SZ_ERROR_WRITE; + } + return res; +} + +#ifndef _7ZIP_ST + +typedef struct +{ + IMtCoderCallback funcTable; + CLzma2Enc *lzma2Enc; +} CMtCallbackImp; + +static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize, + const Byte *src, size_t srcSize, int finished) +{ + CMtCallbackImp *imp = (CMtCallbackImp *)pp; + CLzma2Enc *mainEncoder = imp->lzma2Enc; + CLzma2EncInt *p = &mainEncoder->coders[index]; + + SRes res = SZ_OK; + { + size_t destLim = *destSize; + *destSize = 0; + + if (srcSize != 0) + { + RINOK(Lzma2EncInt_Init(p, &mainEncoder->props)); + + RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE, + mainEncoder->alloc, mainEncoder->allocBig)); + + while (p->srcPos < srcSize) + { + size_t packSize = destLim - *destSize; + res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL); + if (res != SZ_OK) + break; + *destSize += packSize; + + if (packSize == 0) + { + res = SZ_ERROR_FAIL; + break; + } + + if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + LzmaEnc_Finish(p->enc); + if (res != SZ_OK) + return res; + } + if (finished) + { + if (*destSize == destLim) + return SZ_ERROR_OUTPUT_EOF; + dest[(*destSize)++] = 0; + } + } + return res; +} + +#endif + +/* ---------- Lzma2Enc ---------- */ + +CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc)); + if (p == 0) + return NULL; + Lzma2EncProps_Init(&p->props); + Lzma2EncProps_Normalize(&p->props); + p->outBuf = 0; + p->alloc = alloc; + p->allocBig = allocBig; + { + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + p->coders[i].enc = 0; + } + #ifndef _7ZIP_ST + MtCoder_Construct(&p->mtCoder); + #endif + + return p; +} + +void Lzma2Enc_Destroy(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc) + { + LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig); + t->enc = 0; + } + } + + #ifndef _7ZIP_ST + MtCoder_Destruct(&p->mtCoder); + #endif + + IAlloc_Free(p->alloc, p->outBuf); + IAlloc_Free(p->alloc, pp); +} + +SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + CLzmaEncProps lzmaProps = props->lzmaProps; + LzmaEncProps_Normalize(&lzmaProps); + if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX) + return SZ_ERROR_PARAM; + p->props = *props; + Lzma2EncProps_Normalize(&p->props); + return SZ_OK; +} + +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + unsigned i; + UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps); + for (i = 0; i < 40; i++) + if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i)) + break; + return (Byte)i; +} + +SRes Lzma2Enc_Encode(CLzma2EncHandle pp, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress) +{ + CLzma2Enc *p = (CLzma2Enc *)pp; + int i; + + for (i = 0; i < p->props.numBlockThreads; i++) + { + CLzma2EncInt *t = &p->coders[i]; + if (t->enc == NULL) + { + t->enc = LzmaEnc_Create(p->alloc); + if (t->enc == NULL) + return SZ_ERROR_MEM; + } + } + + #ifndef _7ZIP_ST + if (p->props.numBlockThreads <= 1) + #endif + return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress); + + #ifndef _7ZIP_ST + + { + CMtCallbackImp mtCallback; + + mtCallback.funcTable.Code = MtCallbackImp_Code; + mtCallback.lzma2Enc = p; + + p->mtCoder.progress = progress; + p->mtCoder.inStream = inStream; + p->mtCoder.outStream = outStream; + p->mtCoder.alloc = p->alloc; + p->mtCoder.mtCallback = &mtCallback.funcTable; + + p->mtCoder.blockSize = p->props.blockSize; + p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16; + p->mtCoder.numThreads = p->props.numBlockThreads; + + return MtCoder_Code(&p->mtCoder); + } + #endif +} diff --git a/mp/src/utils/lzma/C/Lzma2Enc.h b/mp/src/utils/lzma/C/Lzma2Enc.h new file mode 100644 index 00000000..f409f184 --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma2Enc.h @@ -0,0 +1,62 @@ +/* Lzma2Enc.h -- LZMA2 Encoder +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA2_ENC_H +#define __LZMA2_ENC_H + +#include "LzmaEnc.h" + +EXTERN_C_BEGIN + +typedef struct +{ + CLzmaEncProps lzmaProps; + size_t blockSize; + int numBlockThreads; + int numTotalThreads; +} CLzma2EncProps; + +void Lzma2EncProps_Init(CLzma2EncProps *p); +void Lzma2EncProps_Normalize(CLzma2EncProps *p); + +/* ---------- CLzmaEnc2Handle Interface ---------- */ + +/* Lzma2Enc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzma2EncHandle; + +CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig); +void Lzma2Enc_Destroy(CLzma2EncHandle p); +SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props); +Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p); +SRes Lzma2Enc_Encode(CLzma2EncHandle p, + ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress); + +/* ---------- One Call Interface ---------- */ + +/* Lzma2Encode +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +/* +SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +*/ + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Lzma86.h b/mp/src/utils/lzma/C/Lzma86.h new file mode 100644 index 00000000..bebed5cb --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma86.h @@ -0,0 +1,111 @@ +/* Lzma86.h -- LZMA + x86 (BCJ) Filter +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA86_H +#define __LZMA86_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA86_SIZE_OFFSET (1 + 5) +#define LZMA86_HEADER_SIZE (LZMA86_SIZE_OFFSET + 8) + +/* +It's an example for LZMA + x86 Filter use. +You can use .lzma86 extension, if you write that stream to file. +.lzma86 header adds one additional byte to standard .lzma header. +.lzma86 header (14 bytes): + Offset Size Description + 0 1 = 0 - no filter, pure LZMA + = 1 - x86 filter + LZMA + 1 1 lc, lp and pb in encoded form + 2 4 dictSize (little endian) + 6 8 uncompressed size (little endian) + + +Lzma86_Encode +------------- +level - compression level: 0 <= level <= 9, the default value for "level" is 5. + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes, for level = 5. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + For better compression ratio dictSize must be >= inSize. + +filterMode: + SZ_FILTER_NO - no Filter + SZ_FILTER_YES - x86 Filter + SZ_FILTER_AUTO - it tries both alternatives to select best. + Encoder will use 2 or 3 passes: + 2 passes when FILTER_NO provides better compression. + 3 passes when FILTER_YES provides better compression. + +Lzma86Encode allocates Data with MyAlloc functions. +RAM Requirements for compressing: + RamSize = dictionarySize * 11.5 + 6MB + FilterBlockSize + filterMode FilterBlockSize + SZ_FILTER_NO 0 + SZ_FILTER_YES inSize + SZ_FILTER_AUTO inSize + + +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +enum ESzFilterMode +{ + SZ_FILTER_NO, + SZ_FILTER_YES, + SZ_FILTER_AUTO +}; + +SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode); + + +/* +Lzma86_GetUnpackSize: + In: + src - input data + srcLen - input data size + Out: + unpackSize - size of uncompressed stream + Return code: + SZ_OK - OK + SZ_ERROR_INPUT_EOF - Error in headers +*/ + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize); + +/* +Lzma86_Decode: + In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size + Out: + destLen - processed output size + srcLen - processed input size + Return code: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - unsupported file + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer +*/ + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Lzma86Dec.c b/mp/src/utils/lzma/C/Lzma86Dec.c new file mode 100644 index 00000000..fe772609 --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma86Dec.c @@ -0,0 +1,56 @@ +/* Lzma86Dec.c -- LZMA + x86 (BCJ) Filter Decoder +2009-08-14 : Igor Pavlov : Public domain */ + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaDec.h" + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } + +SRes Lzma86_GetUnpackSize(const Byte *src, SizeT srcLen, UInt64 *unpackSize) +{ + unsigned i; + if (srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + *unpackSize = 0; + for (i = 0; i < sizeof(UInt64); i++) + *unpackSize += ((UInt64)src[LZMA86_SIZE_OFFSET + i]) << (8 * i); + return SZ_OK; +} + +SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen) +{ + ISzAlloc g_Alloc = { SzAlloc, SzFree }; + SRes res; + int useFilter; + SizeT inSizePure; + ELzmaStatus status; + + if (*srcLen < LZMA86_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + + useFilter = src[0]; + + if (useFilter > 1) + { + *destLen = 0; + return SZ_ERROR_UNSUPPORTED; + } + + inSizePure = *srcLen - LZMA86_HEADER_SIZE; + res = LzmaDecode(dest, destLen, src + LZMA86_HEADER_SIZE, &inSizePure, + src + 1, LZMA_PROPS_SIZE, LZMA_FINISH_ANY, &status, &g_Alloc); + *srcLen = inSizePure + LZMA86_HEADER_SIZE; + if (res != SZ_OK) + return res; + if (useFilter == 1) + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(dest, *destLen, 0, &x86State, 0); + } + return SZ_OK; +} diff --git a/mp/src/utils/lzma/C/Lzma86Enc.c b/mp/src/utils/lzma/C/Lzma86Enc.c new file mode 100644 index 00000000..16467149 --- /dev/null +++ b/mp/src/utils/lzma/C/Lzma86Enc.c @@ -0,0 +1,108 @@ +/* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder +2009-08-14 : Igor Pavlov : Public domain */ + +#include + +#include "Lzma86.h" + +#include "Alloc.h" +#include "Bra.h" +#include "LzmaEnc.h" + +#define SZE_OUT_OVERFLOW SZE_DATA_ERROR + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } + +int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen, + int level, UInt32 dictSize, int filterMode) +{ + ISzAlloc g_Alloc = { SzAlloc, SzFree }; + size_t outSize2 = *destLen; + Byte *filteredStream; + Bool useFilter; + int mainResult = SZ_ERROR_OUTPUT_EOF; + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + + *destLen = 0; + if (outSize2 < LZMA86_HEADER_SIZE) + return SZ_ERROR_OUTPUT_EOF; + + { + int i; + UInt64 t = srcLen; + for (i = 0; i < 8; i++, t >>= 8) + dest[LZMA86_SIZE_OFFSET + i] = (Byte)t; + } + + filteredStream = 0; + useFilter = (filterMode != SZ_FILTER_NO); + if (useFilter) + { + if (srcLen != 0) + { + filteredStream = (Byte *)MyAlloc(srcLen); + if (filteredStream == 0) + return SZ_ERROR_MEM; + memcpy(filteredStream, src, srcLen); + } + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(filteredStream, srcLen, 0, &x86State, 1); + } + } + + { + size_t minSize = 0; + Bool bestIsFiltered = False; + + /* passes for SZ_FILTER_AUTO: + 0 - BCJ + LZMA + 1 - LZMA + 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better. + */ + int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; + + int i; + for (i = 0; i < numPasses; i++) + { + size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE; + size_t outPropsSize = 5; + SRes curRes; + Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1); + if (curModeIsFiltered && !bestIsFiltered) + break; + if (useFilter && i == 0) + curModeIsFiltered = True; + + curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed, + curModeIsFiltered ? filteredStream : src, srcLen, + &props, dest + 1, &outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); + + if (curRes != SZ_ERROR_OUTPUT_EOF) + { + if (curRes != SZ_OK) + { + mainResult = curRes; + break; + } + if (outSizeProcessed <= minSize || mainResult != SZ_OK) + { + minSize = outSizeProcessed; + bestIsFiltered = curModeIsFiltered; + mainResult = SZ_OK; + } + } + } + dest[0] = (Byte)(bestIsFiltered ? 1 : 0); + *destLen = LZMA86_HEADER_SIZE + minSize; + } + if (useFilter) + MyFree(filteredStream); + return mainResult; +} diff --git a/mp/src/utils/lzma/C/LzmaDec.c b/mp/src/utils/lzma/C/LzmaDec.c new file mode 100644 index 00000000..bbf650de --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaDec.c @@ -0,0 +1,1025 @@ +/* LzmaDec.c -- LZMA Decoder +2015-01-01 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "LzmaDec.h" + +#include + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } +#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) + +#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol) +#define MATCHED_LITER_DEC \ + matchByte <<= 1; \ + bit = (matchByte & offs); \ + probLit = prob + offs + bit + symbol; \ + GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +#define LZMA_DIC_MIN (1 << 12) + +/* First LZMA-symbol is always decoded. +And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization +Out: + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : Flush marker + = kMatchSpecLenStart + 2 : State Init Marker +*/ + +static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = p->probs; + + unsigned state = p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; + unsigned lc = p->prop.lc; + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = processedPos & pbMask; + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (checkDicSize != 0 || processedPos != 0) + prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + + (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif + } + else + { + unsigned matchByte = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + } + while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif + } + dic[dicPos++] = (Byte)symbol; + processedPos++; + continue; + } + else + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = (1 << kLenNumMidBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, limit, len); + len += offset; + } + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + int numDirectBits = (int)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos + distance - posSlot - 1; + { + UInt32 mask = 1; + unsigned i = 1; + do + { + GET_BIT2(prob + i, i, ; , distance |= mask); + mask <<= 1; + } + while (--numDirectBits != 0); + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits != 0); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + GET_BIT2(prob + i, i, ; , distance |= 1); + GET_BIT2(prob + i, i, ; , distance |= 2); + GET_BIT2(prob + i, i, ; , distance |= 4); + GET_BIT2(prob + i, i, ; , distance |= 8); + } + if (distance == (UInt32)0xFFFFFFFF) + { + len += kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + if (checkDicSize == 0) + { + if (distance >= processedPos) + return SZ_ERROR_DATA; + } + else if (distance >= checkDicSize) + return SZ_ERROR_DATA; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + } + + len += kMatchMinLen; + + if (limit == dicPos) + return SZ_ERROR_DATA; + { + SizeT rem = limit - dicPos; + unsigned curLen = ((rem < len) ? (unsigned)rem : len); + SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); + + processedPos += curLen; + + len -= curLen; + if (pos + curLen <= dicBufSize) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + NORMALIZE; + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = state; + + return SZ_OK; +} + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = p->remainLen; + UInt32 rep0 = p->reps[0]; + if (limit - dicPos < len) + len = (unsigned)(limit - dicPos); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += len; + p->remainLen -= len; + while (len != 0) + { + len--; + dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + } + RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); + if (p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + if (p->remainLen > kMatchSpecLenStart) + { + p->remainLen = kMatchSpecLenStart; + } + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + CLzmaProb *probs = p->probs; + unsigned state = p->state; + ELzmaDummy res; + + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); + + prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += (LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + CLzmaProb *probLit; + matchByte <<= 1; + bit = (matchByte & offs); + probLit = prob + offs + bit + symbol; + GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumMidBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits != 0); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + do + { + GET_BIT_CHECK(prob + i, i); + } + while (--numDirectBits != 0); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) +{ + p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); + p->range = 0xFFFFFFFF; + p->needFlush = 0; +} + +void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +{ + p->needFlush = 1; + p->remainLen = 0; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->needInitState = 1; + } + if (initState) + p->needInitState = 1; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + +static void LzmaDec_InitStateReal(CLzmaDec *p) +{ + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); + UInt32 i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + p->needInitState = 0; +} + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + LzmaDec_WriteRem(p, dicLimit); + + *status = LZMA_STATUS_NOT_SPECIFIED; + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow; + + if (p->needFlush != 0) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + + LzmaDec_InitRc(p, p->tempBuf); + p->tempBufSize = 0; + } + + checkEndMarkNow = 0; + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->needInitState) + LzmaDec_InitStateReal(p); + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); + (*srcLen) += lookAhead; + src += lookAhead; + inSize -= lookAhead; + p->tempBufSize = 0; + } + } + if (p->code == 0) + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; +} + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->probs); + p->probs = 0; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->dic); + p->dic = 0; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = d % 9; + d /= 9; + p->pb = d / 5; + p->lp = d % 5; + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (p->probs == 0 || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); + p->numProbs = numProbs; + if (p->probs == 0) + return SZ_ERROR_MEM; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + dicBufSize = propNew.dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc) +{ + CLzmaDec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + LzmaDec_Construct(&p); + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); + p.dic = dest; + p.dicBufSize = outSize; + LzmaDec_Init(&p); + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/mp/src/utils/lzma/C/LzmaDec.h b/mp/src/utils/lzma/C/LzmaDec.h new file mode 100644 index 00000000..cc44daef --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaDec.h @@ -0,0 +1,227 @@ +/* LzmaDec.h -- LZMA Decoder +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + unsigned lc, lp, pb; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + CLzmaProps prop; + CLzmaProb *probs; + Byte *dic; + const Byte *buf; + UInt32 range, code; + SizeT dicPos; + SizeT dicBufSize; + UInt32 processedPos; + UInt32 checkDicSize; + unsigned state; + UInt32 reps[4]; + unsigned remainLen; + int needFlush; + int needInitState; + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. + 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); + +SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); +void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Constr() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAlloc *alloc); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/LzmaEnc.c b/mp/src/utils/lzma/C/LzmaEnc.c new file mode 100644 index 00000000..37e05a95 --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaEnc.c @@ -0,0 +1,2278 @@ +/* LzmaEnc.c -- LZMA Encoder +2014-12-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifndef _7ZIP_ST +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static unsigned g_STAT_OFFSET = 0; +#endif + +#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1) + +#define kBlockSize (9 << 10) +#define kUnpackBlockSize (1 << 18) +#define kMatchArraySize (1 << 21) +#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX) + +#define kNumMaxDirectBits (31) + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->reduceSize = (UInt64)(Int64)-1; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + for (i = 11; i <= 30; i++) + { + if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + if (p->numThreads < 0) + p->numThreads = + #ifndef _7ZIP_ST + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +/* #define LZMA_LOG_BSR */ +/* Define it for Intel's CPU */ + + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 30 + +#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); } + +UInt32 GetPosSlot1(UInt32 pos) +{ + UInt32 res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + (int)sizeof(size_t) / 2) +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + int c = 2, slotFast; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + UInt32 j; + for (j = 0; j < k; j++, c++) + g_FastPos[c] = (Byte)slotFast; + } +} + +#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> i] + (i * 2); } +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef unsigned CState; + +typedef struct +{ + UInt32 price; + + CState state; + int prev1IsChar; + int prev2; + + UInt32 posPrev2; + UInt32 backPrev2; + + UInt32 posPrev; + UInt32 backPrev; + UInt32 backs[LZMA_NUM_REPS]; +} COptimal; + +#define kNumOpts (1 << 12) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex) + +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#ifdef _LZMA_PROB32 +#define CLzmaProb UInt32 +#else +#define CLzmaProb UInt16 +#endif + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + +typedef struct +{ + CLzmaProb choice; + CLzmaProb choice2; + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits]; + CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + +typedef struct +{ + CLenEnc p; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + UInt32 tableSize; + UInt32 counters[LZMA_NUM_PB_STATES_MAX]; +} CLenPriceEnc; + +typedef struct +{ + UInt32 range; + Byte cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + +typedef struct +{ + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; +} CSaveState; + +typedef struct +{ + IMatchFinder matchFinder; + void *matchFinderObj; + + #ifndef _7ZIP_ST + Bool mtMode; + CMatchFinderMt matchFinderMt; + #endif + + CMatchFinder matchFinderBase; + + #ifndef _7ZIP_ST + Byte pad[128]; + #endif + + UInt32 optimumEndIndex; + UInt32 optimumCurrentIndex; + + UInt32 longestMatchLength; + UInt32 numPairs; + UInt32 numAvail; + COptimal opt[kNumOpts]; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + UInt32 numFastBytes; + UInt32 additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + UInt32 state; + + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + UInt32 alignPrices[kAlignTableSize]; + UInt32 alignPriceCount; + + UInt32 distTableSize; + + unsigned lc, lp, pb; + unsigned lpMask, pbMask; + + CLzmaProb *litProbs; + + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex]; + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + unsigned lclp; + + Bool fastMode; + + CRangeEnc rc; + + Bool writeEndMark; + UInt64 nowPos64; + UInt32 matchPriceCount; + Bool finished; + Bool multiThread; + + SRes result; + UInt32 dictSize; + + int needInit; + + CSaveState saveState; +} CLzmaEnc; + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); +} + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + int i; + dest->lenEnc = p->lenEnc; + dest->repLenEnc = p->repLenEnc; + dest->state = p->state; + + for (i = 0; i < kNumStates; i++) + { + memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); + memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); + } + for (i = 0; i < kNumLenToPosStates; i++) + memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); + memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); + memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); + memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); + memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); + memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); + memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); + memcpy(dest->reps, p->reps, sizeof(p->reps)); + memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX || + props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30)) + return SZ_ERROR_PARAM; + p->dictSize = props.dictSize; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + p->matchFinderBase.btMode = props.btMode; + { + UInt32 numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifndef _7ZIP_ST + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + +static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsCharState(s) ((s) < 7) + +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = 0; + p->bufBase = 0; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) +static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc) +{ + if (p->bufBase == 0) + { + p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE); + if (p->bufBase == 0) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->low = 0; + p->range = 0xFFFFFFFF; + p->cacheSize = 1; + p->cache = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != p->outStream->Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0) + { + Byte temp = p->cache; + do + { + Byte *buf = p->buf; + *buf++ = (Byte)(temp + (Byte)(p->low >> 32)); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + temp = 0xFF; + } + while (--p->cacheSize != 0); + p->cache = (Byte)((UInt32)p->low >> 24); + } + p->cacheSize++; + p->low = (UInt32)p->low << 8; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits) +{ + do + { + p->range >>= 1; + p->low += p->range & (0 - ((value >> --numBits) & 1)); + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } + } + while (numBits != 0); +} + +static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol) +{ + UInt32 ttt = *prob; + UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt; + if (symbol == 0) + { + p->range = newBound; + ttt += (kBitModelTotal - ttt) >> kNumMoveBits; + } + else + { + p->low += newBound; + p->range -= newBound; + ttt -= ttt >> kNumMoveBits; + } + *prob = (CLzmaProb)ttt; + if (p->range < kTopValue) + { + p->range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol) +{ + symbol |= 0x100; + do + { + RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte) +{ + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); +} + +void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +{ + UInt32 i; + for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) + { + const int kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = i; + UInt32 bitCount = 0; + int j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + } +} + + +#define GET_PRICE(prob, symbol) \ + p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, symbol) \ + ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= 0x100; + do + { + price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1); + symbol <<= 1; + } + while (symbol < 0x10000); + return price; +} + +static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + symbol |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1); + symbol <<= 1; + offs &= ~(matchByte ^ symbol); + } + while (symbol < 0x10000); + return price; +} + + +static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0;) + { + UInt32 bit; + i--; + bit = (symbol >> i) & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + } +} + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol) +{ + UInt32 m = 1; + int i; + for (i = 0; i < numBitLevels; i++) + { + UInt32 bit = symbol & 1; + RangeEnc_EncodeBit(rc, probs + m, bit); + m = (m << 1) | bit; + symbol >>= 1; + } +} + +static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + symbol |= (1 << numBitLevels); + while (symbol != 1) + { + price += GET_PRICEa(probs[symbol >> 1], symbol & 1); + symbol >>= 1; + } + return price; +} + +static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices) +{ + UInt32 price = 0; + UInt32 m = 1; + int i; + for (i = numBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) | bit; + } + return price; +} + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + p->choice = p->choice2 = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++) + p->mid[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState) +{ + if (symbol < kLenNumLowSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice, 0); + RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice, 1); + if (symbol < kLenNumLowSymbols + kLenNumMidSymbols) + { + RangeEnc_EncodeBit(rc, &p->choice2, 0); + RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols); + } + else + { + RangeEnc_EncodeBit(rc, &p->choice2, 1); + RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols); + } + } +} + +static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices) +{ + UInt32 a0 = GET_PRICE_0a(p->choice); + UInt32 a1 = GET_PRICE_1a(p->choice); + UInt32 b0 = a1 + GET_PRICE_0a(p->choice2); + UInt32 b1 = a1 + GET_PRICE_1a(p->choice2); + UInt32 i = 0; + for (i = 0; i < kLenNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices); + } + for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices); + } + for (; i < numSymbols; i++) + prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices); +} + +static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices) +{ + LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices); + p->counters[posState] = p->tableSize; +} + +static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices) +{ + UInt32 posState; + for (posState = 0; posState < numPosStates; posState++) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + +static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices) +{ + LenEnc_Encode(&p->p, rc, symbol, posState); + if (updatePrice) + if (--p->counters[posState] == 0) + LenPriceEnc_UpdateTable(p, posState, ProbPrices); +} + + + + +static void MovePos(CLzmaEnc *p, UInt32 num) +{ + #ifdef SHOW_STAT + g_STAT_OFFSET += num; + printf("\n MovePos %d", num); + #endif + + if (num != 0) + { + p->additionalOffset += num; + p->matchFinder.Skip(p->matchFinderObj, num); + } +} + +static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes) +{ + UInt32 lenRes = 0, numPairs; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + + #ifdef SHOW_STAT + printf("\n i = %d numPairs = %d ", g_STAT_OFFSET, numPairs / 2); + g_STAT_OFFSET++; + { + UInt32 i; + for (i = 0; i < numPairs; i += 2) + printf("%2d %6d | ", p->matches[i], p->matches[i + 1]); + } + #endif + + if (numPairs > 0) + { + lenRes = p->matches[numPairs - 2]; + if (lenRes == p->numFastBytes) + { + const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + UInt32 distance = p->matches[numPairs - 1] + 1; + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *pby2 = pby - distance; + for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++); + } + } + } + p->additionalOffset++; + *numDistancePairsRes = numPairs; + return lenRes; +} + + +#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False; +#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False; +#define IsShortRep(p) ((p)->backPrev == 0) + +static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState) +{ + return + GET_PRICE_0(p->isRepG0[state]) + + GET_PRICE_0(p->isRep0Long[state][posState]); +} + +static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState) +{ + UInt32 price; + if (repIndex == 0) + { + price = GET_PRICE_0(p->isRepG0[state]); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(p->isRepG0[state]); + if (repIndex == 1) + price += GET_PRICE_0(p->isRepG1[state]); + else + { + price += GET_PRICE_1(p->isRepG1[state]); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + +static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState) +{ + return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] + + GetPureRepPrice(p, repIndex, state, posState); +} + +static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) +{ + UInt32 posMem = p->opt[cur].posPrev; + UInt32 backMem = p->opt[cur].backPrev; + p->optimumEndIndex = cur; + do + { + if (p->opt[cur].prev1IsChar) + { + MakeAsChar(&p->opt[posMem]) + p->opt[posMem].posPrev = posMem - 1; + if (p->opt[cur].prev2) + { + p->opt[posMem - 1].prev1IsChar = False; + p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2; + p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2; + } + } + { + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = p->opt[posPrev].backPrev; + posMem = p->opt[posPrev].posPrev; + + p->opt[posPrev].backPrev = backCur; + p->opt[posPrev].posPrev = cur; + cur = posPrev; + } + } + while (cur != 0); + *backRes = p->opt[0].backPrev; + p->optimumCurrentIndex = p->opt[0].posPrev; + return p->optimumCurrentIndex; +} + +#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) + +static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur; + UInt32 matchPrice, repMatchPrice, normalMatchPrice; + UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS]; + UInt32 *matches; + const Byte *data; + Byte curByte, matchByte; + if (p->optimumEndIndex != p->optimumCurrentIndex) + { + const COptimal *opt = &p->opt[p->optimumCurrentIndex]; + UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex; + *backRes = opt->backPrev; + p->optimumCurrentIndex = opt->posPrev; + return lenRes; + } + p->optimumCurrentIndex = p->optimumEndIndex = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + *backRes = (UInt32)(-1); + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 lenTest; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - (reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= p->numFastBytes) + { + UInt32 lenRes; + *backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + MovePos(p, lenRes - 1); + return lenRes; + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2) + { + *backRes = (UInt32)-1; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsCharState(p->state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAsChar(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + if (matchByte == curByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAsShortRep(&p->opt[1]); + } + } + lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]); + + if (lenEnd < 2) + { + *backRes = p->opt[1].backPrev; + return 1; + } + + p->opt[1].posPrev = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + p->opt[0].backs[i] = reps[i]; + + len = lenEnd; + do + p->opt[len--].price = kInfinityPrice; + while (len >= 2); + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2]; + COptimal *opt = &p->opt[repLen]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = i; + opt->prev1IsChar = False; + } + } + while (--repLen >= 2); + } + + normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= mainLen) + { + UInt32 offs = 0; + while (len > matches[offs]) + offs += 2; + for (; ; len++) + { + COptimal *opt; + UInt32 distance = matches[offs + 1]; + + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(len); + if (distance < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][distance]; + else + { + UInt32 slot; + GetPosSlot2(distance, slot); + curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot]; + } + opt = &p->opt[len]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = 0; + opt->backPrev = distance + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + + cur = 0; + + #ifdef SHOW_STAT2 + if (position >= 0) + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= lenEnd; i++) + printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price); + } + #endif + + for (;;) + { + UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen; + UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice; + Bool nextIsChar; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt; + COptimal *nextOpt; + + cur++; + if (cur == lenEnd) + return Backward(p, backRes, cur); + + newLen = ReadMatchDistances(p, &numPairs); + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLength = newLen; + return Backward(p, backRes, cur); + } + position++; + curOpt = &p->opt[cur]; + posPrev = curOpt->posPrev; + if (curOpt->prev1IsChar) + { + posPrev--; + if (curOpt->prev2) + { + state = p->opt[curOpt->posPrev2].state; + if (curOpt->backPrev2 < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + else + state = p->opt[posPrev].state; + state = kLiteralNextStates[state]; + } + else + state = p->opt[posPrev].state; + if (posPrev == cur - 1) + { + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + UInt32 pos; + const COptimal *prevOpt; + if (curOpt->prev1IsChar && curOpt->prev2) + { + posPrev = curOpt->posPrev2; + pos = curOpt->backPrev2; + state = kRepNextStates[state]; + } + else + { + pos = curOpt->backPrev; + if (pos < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + prevOpt = &p->opt[posPrev]; + if (pos < LZMA_NUM_REPS) + { + UInt32 i; + reps[0] = prevOpt->backs[pos]; + for (i = 1; i <= pos; i++) + reps[i] = prevOpt->backs[i - 1]; + for (; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i]; + } + else + { + UInt32 i; + reps[0] = (pos - LZMA_NUM_REPS); + for (i = 1; i < LZMA_NUM_REPS; i++) + reps[i] = prevOpt->backs[i - 1]; + } + } + curOpt->state = (CState)state; + + curOpt->backs[0] = reps[0]; + curOpt->backs[1] = reps[1]; + curOpt->backs[2] = reps[2]; + curOpt->backs[3] = reps[3]; + + curPrice = curOpt->price; + nextIsChar = False; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - (reps[0] + 1)); + + posState = (position & p->pbMask); + + curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]); + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + curAnd1Price += + (!IsCharState(state) ? + LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + nextOpt = &p->opt[cur + 1]; + + if (curAnd1Price < nextOpt->price) + { + nextOpt->price = curAnd1Price; + nextOpt->posPrev = cur; + MakeAsChar(nextOpt); + nextIsChar = True; + } + + matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState); + if (shortRepPrice <= nextOpt->price) + { + nextOpt->price = shortRepPrice; + nextOpt->posPrev = cur; + MakeAsShortRep(nextOpt); + nextIsChar = True; + } + } + numAvailFull = p->numAvail; + { + UInt32 temp = kNumOpts - 1 - cur; + if (temp < numAvailFull) + numAvailFull = temp; + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + if (!nextIsChar && matchByte != curByte) /* speed optimization */ + { + /* try Literal + rep0 */ + UInt32 temp; + UInt32 lenTest2; + const Byte *data2 = data - (reps[0] + 1); + UInt32 limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + + for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++); + lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kLiteralNextStates[state]; + UInt32 posStateNext = (position + 1) & p->pbMask; + UInt32 nextRepMatchPrice = curAnd1Price + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = False; + } + } + } + } + + startLen = 2; /* speed optimization */ + { + UInt32 repIndex; + for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++) + { + UInt32 lenTest; + UInt32 lenTestTemp; + UInt32 price; + const Byte *data2 = data - (reps[repIndex] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++); + while (lenEnd < cur + lenTest) + p->opt[++lenEnd].price = kInfinityPrice; + lenTestTemp = lenTest; + price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2]; + COptimal *opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = repIndex; + opt->prev1IsChar = False; + } + } + while (--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + /* if (_maxMode) */ + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kRepNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = + price + p->repLenEnc.prices[posState][lenTest - 2] + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (position + lenTest + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 curAndLenPrice; + COptimal *opt; + UInt32 offset = cur + lenTest + 1 + lenTest2; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = repIndex; + } + } + } + } + } + } + /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = newLen; + numPairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 offs, curBack, posSlot; + UInt32 lenTest; + while (lenEnd < cur + newLen) + p->opt[++lenEnd].price = kInfinityPrice; + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + curBack = matches[offs + 1]; + GetPosSlot2(curBack, posSlot); + for (lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN]; + UInt32 lenToPosState = GetLenToPosState(lenTest); + COptimal *opt; + if (curBack < kNumFullDistances) + curAndLenPrice += p->distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask]; + + opt = &p->opt[cur + lenTest]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur; + opt->backPrev = curBack + LZMA_NUM_REPS; + opt->prev1IsChar = False; + } + + if (/*_maxMode && */lenTest == matches[offs]) + { + /* Try Match + Literal + Rep0 */ + const Byte *data2 = data - (curBack + 1); + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = lenTest2 + p->numFastBytes; + UInt32 nextRepMatchPrice; + if (limit > numAvailFull) + limit = numAvailFull; + for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + UInt32 state2 = kMatchNextStates[state]; + UInt32 posStateNext = (position + lenTest) & p->pbMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + GET_PRICE_0(p->isMatch[state2][posStateNext]) + + LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]), + data[lenTest], data2[lenTest], p->ProbPrices); + state2 = kLiteralNextStates[state2]; + posStateNext = (posStateNext + 1) & p->pbMask; + nextRepMatchPrice = curAndLenCharPrice + + GET_PRICE_1(p->isMatch[state2][posStateNext]) + + GET_PRICE_1(p->isRep[state2]); + + /* for (; lenTest2 >= 2; lenTest2--) */ + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + UInt32 curAndLenPrice; + COptimal *opt; + while (lenEnd < offset) + p->opt[++lenEnd].price = kInfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext); + opt = &p->opt[offset]; + if (curAndLenPrice < opt->price) + { + opt->price = curAndLenPrice; + opt->posPrev = cur + lenTest + 1; + opt->backPrev = 0; + opt->prev1IsChar = True; + opt->prev2 = True; + opt->posPrev2 = cur; + opt->backPrev2 = curBack + LZMA_NUM_REPS; + } + } + } + offs += 2; + if (offs == numPairs) + break; + curBack = matches[offs + 1]; + if (curBack >= kNumFullDistances) + GetPosSlot2(curBack, posSlot); + } + } + } + } +} + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + +static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes) +{ + UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i; + const Byte *data; + const UInt32 *matches; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLength; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + *backRes = (UInt32)-1; + if (numAvail < 2) + return 1; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + repLen = repIndex = 0; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++); + if (len >= p->numFastBytes) + { + *backRes = i; + MovePos(p, len - 1); + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + matches = p->matches; + if (mainLen >= p->numFastBytes) + { + *backRes = matches[numPairs - 1] + LZMA_NUM_REPS; + MovePos(p, mainLen - 1); + return mainLen; + } + + mainDist = 0; /* for GCC */ + if (mainLen >= 2) + { + mainDist = matches[numPairs - 1]; + while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1) + { + if (!ChangePair(matches[numPairs - 3], mainDist)) + break; + numPairs -= 2; + mainLen = matches[numPairs - 2]; + mainDist = matches[numPairs - 1]; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2 && ( + (repLen + 1 >= mainLen) || + (repLen + 2 >= mainLen && mainDist >= (1 << 9)) || + (repLen + 3 >= mainLen && mainDist >= (1 << 15)))) + { + *backRes = repIndex; + MovePos(p, repLen - 1); + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + p->longestMatchLength = ReadMatchDistances(p, &p->numPairs); + if (p->longestMatchLength >= 2) + { + UInt32 newDistance = matches[p->numPairs - 1]; + if ((p->longestMatchLength >= mainLen && newDistance < mainDist) || + (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) || + (p->longestMatchLength > mainLen + 1) || + (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist))) + return 1; + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + for (i = 0; i < LZMA_NUM_REPS; i++) + { + UInt32 len, limit; + const Byte *data2 = data - (p->reps[i] + 1); + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2; len < limit && data[len] == data2[len]; len++); + if (len >= limit) + return 1; + } + *backRes = mainDist + LZMA_NUM_REPS; + MovePos(p, mainLen - 2); + return mainLen; +} + +static void WriteEndMarker(CLzmaEnc *p, UInt32 posState) +{ + UInt32 len; + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + len = LZMA_MATCH_LEN_MIN; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1); + RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); +} + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + +static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + +static void FillAlignPrices(CLzmaEnc *p) +{ + UInt32 i; + for (i = 0; i < kAlignTableSize; i++) + p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + p->alignPriceCount = 0; +} + +static void FillDistancesPrices(CLzmaEnc *p) +{ + UInt32 tempPrices[kNumFullDistances]; + UInt32 i, lenToPosState; + for (i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot1(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices); + } + + for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices); + for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + + { + UInt32 *distancesPrices = p->distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i]; + } + } + p->matchPriceCount = 0; +} + +void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + #ifndef _7ZIP_ST + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) +{ + void *p; + p = alloc->Alloc(alloc, sizeof(CLzmaEnc)); + if (p != 0) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->litProbs); + alloc->Free(alloc, p->saveState.litProbs); + p->litProbs = 0; + p->saveState.litProbs = 0; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + alloc->Free(alloc, p); +} + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->needInit) + { + p->matchFinder.Init(p->matchFinderObj); + p->needInit = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + UInt32 numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0); + p->state = kLiteralNextStates[p->state]; + curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + for (;;) + { + UInt32 pos, len, posState; + + if (p->fastMode) + len = GetOptimumFast(p, &pos); + else + len = GetOptimum(p, nowPos32, &pos); + + #ifdef SHOW_STAT2 + printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos); + #endif + + posState = nowPos32 & p->pbMask; + if (len == 1 && pos == (UInt32)-1) + { + Byte curByte; + CLzmaProb *probs; + const Byte *data; + + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0); + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + curByte = *data; + probs = LIT_PROBS(nowPos32, *(data - 1)); + if (IsCharState(p->state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1)); + p->state = kLiteralNextStates[p->state]; + } + else + { + RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1); + if (pos < LZMA_NUM_REPS) + { + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1); + if (pos == 0) + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0); + RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = p->reps[pos]; + RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1); + if (pos == 1) + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0); + else + { + RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1); + RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2); + if (pos == 3) + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = distance; + } + if (len == 1) + p->state = kShortRepNextStates[p->state]; + else + { + LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + p->state = kRepNextStates[p->state]; + } + } + else + { + UInt32 posSlot; + RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); + p->state = kMatchNextStates[p->state]; + LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); + pos -= LZMA_NUM_REPS; + GetPosSlot(pos, posSlot); + RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced); + else + { + RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + p->alignPriceCount++; + } + } + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = pos; + p->matchPriceCount++; + } + } + p->additionalOffset -= len; + nowPos32 += len; + if (p->additionalOffset == 0) + { + UInt32 processed; + if (!p->fastMode) + { + if (p->matchPriceCount >= (1 << 7)) + FillDistancesPrices(p); + if (p->alignPriceCount >= kAlignTableSize) + FillAlignPrices(p); + } + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + if (useLimits) + { + if (processed + kNumOpts + 300 >= maxUnpackSize || + RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize) + break; + } + else if (processed >= (1 << 15)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 beforeSize = kNumOpts; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + #ifndef _7ZIP_ST + p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb)); + if (p->litProbs == 0 || p->saveState.litProbs == 0) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)); + p->matchFinderObj = &p->matchFinderMt; + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + return SZ_OK; +} + +void LzmaEnc_Init(CLzmaEnc *p) +{ + UInt32 i; + p->state = 0; + for (i = 0 ; i < LZMA_NUM_REPS; i++) + p->reps[i] = 0; + + RangeEnc_Init(&p->rc); + + + for (i = 0; i < kNumStates; i++) + { + UInt32 j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + UInt32 num = 0x300 << (p->lp + p->lc); + for (i = 0; i < num; i++) + p->litProbs[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + UInt32 j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + p->posEncoders[i] = kProbInitValue; + } + + LenEnc_Init(&p->lenEnc.p); + LenEnc_Init(&p->repLenEnc.p); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + p->optimumEndIndex = 0; + p->optimumCurrentIndex = 0; + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = (1 << p->lp) - 1; +} + +void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + UInt32 i; + for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->needInit = 1; + + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifndef _7ZIP_ST + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + pp = pp; + #endif +} + +typedef struct +{ + ISeqOutStream funcTable; + Byte *data; + SizeT rem; + Bool overflow; +} CSeqOutStreamBuf; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp; + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CSeqOutStreamBuf outStream; + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.funcTable; + + res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +{ + SRes res = SZ_OK; + + #ifndef _7ZIP_ST + Byte allocaDummy[0x300]; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; + #endif + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, False, 0, 0); + if (res != SZ_OK || p->finished != 0) + break; + if (progress != 0) + { + res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + LzmaEnc_Finish(p); + return res; +} + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAlloc *alloc, ISzAlloc *allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + int i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) + { + dictSize = (2 << i); + break; + } + if (dictSize <= ((UInt32)3 << i)) + { + dictSize = (3 << i); + break; + } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CSeqOutStreamBuf outStream; + + LzmaEnc_SetInputBuf(p, src, srcLen); + + outStream.funcTable.Write = MyWrite; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + + p->rc.outStream = &outStream.funcTable; + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + if (res == SZ_OK) + res = LzmaEnc_Encode2(p, progress); + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (p == 0) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/mp/src/utils/lzma/C/LzmaEnc.h b/mp/src/utils/lzma/C/LzmaEnc.h new file mode 100644 index 00000000..cffe220b --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaEnc.h @@ -0,0 +1,78 @@ +/* LzmaEnc.h -- LZMA Encoder +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (1 << 30) for 64-bit version + default = (1 << 24) */ + UInt64 reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF. + Encoder uses this value to reduce dictionary size */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc_* functions can return the following exit codes: +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater in props + SZ_ERROR_WRITE - Write callback error. + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +/* ---------- One Call Interface ---------- */ + +/* LzmaEncode +Return code: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/LzmaLib.c b/mp/src/utils/lzma/C/LzmaLib.c new file mode 100644 index 00000000..02a51185 --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaLib.c @@ -0,0 +1,46 @@ +/* LzmaLib.c -- LZMA library wrapper +2008-08-05 +Igor Pavlov +Public domain */ + +#include "LzmaEnc.h" +#include "LzmaDec.h" +#include "Alloc.h" +#include "LzmaLib.h" + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ +) +{ + CLzmaEncProps props; + LzmaEncProps_Init(&props); + props.level = level; + props.dictSize = dictSize; + props.lc = lc; + props.lp = lp; + props.pb = pb; + props.fb = fb; + props.numThreads = numThreads; + + return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); +} + + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t *srcLen, + const unsigned char *props, size_t propsSize) +{ + ELzmaStatus status; + return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY, &status, &g_Alloc); +} diff --git a/mp/src/utils/lzma/C/LzmaLib.h b/mp/src/utils/lzma/C/LzmaLib.h new file mode 100644 index 00000000..88fa87d3 --- /dev/null +++ b/mp/src/utils/lzma/C/LzmaLib.h @@ -0,0 +1,131 @@ +/* LzmaLib.h -- LZMA library interface +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_LIB_H +#define __LZMA_LIB_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define MY_STDAPI int MY_STD_CALL + +#define LZMA_PROPS_SIZE 5 + +/* +RAM requirements for LZMA: + for compression: (dictSize * 11.5 + 6 MB) + state_size + for decompression: dictSize + state_size + state_size = (4 + (1.5 << (lc + lp))) KB + by default (lc=3, lp=0), state_size = 16 KB. + +LZMA properties (5 bytes) format + Offset Size Description + 0 1 lc, lp and pb in encoded form. + 1 4 dictSize (little endian). +*/ + +/* +LzmaCompress +------------ + +outPropsSize - + In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + Out: the pointer to the size of written properties in outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5. + + LZMA Encoder will use defult values for any parameter, if it is + -1 for any from: level, loc, lp, pb, fb, numThreads + 0 for dictSize + +level - compression level: 0 <= level <= 9; + + level dictSize algo fb + 0: 16 KB 0 32 + 1: 64 KB 0 32 + 2: 256 KB 0 32 + 3: 1 MB 0 32 + 4: 4 MB 0 32 + 5: 16 MB 1 32 + 6: 32 MB 1 32 + 7+: 64 MB 1 64 + + The default value for "level" is 5. + + algo = 0 means fast method + algo = 1 means normal method + +dictSize - The dictionary size in bytes. The maximum value is + 128 MB = (1 << 27) bytes for 32-bit version + 1 GB = (1 << 30) bytes for 64-bit version + The default value is 16 MB = (1 << 24) bytes. + It's recommended to use the dictionary that is larger than 4 KB and + that can be calculated as (1 << N) or (3 << N) sizes. + +lc - The number of literal context bits (high bits of previous literal). + It can be in the range from 0 to 8. The default value is 3. + Sometimes lc=4 gives the gain for big files. + +lp - The number of literal pos bits (low bits of current position for literals). + It can be in the range from 0 to 4. The default value is 0. + The lp switch is intended for periodical data when the period is equal to 2^lp. + For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's + better to set lc=0, if you change lp switch. + +pb - The number of pos bits (low bits of current position). + It can be in the range from 0 to 4. The default value is 2. + The pb switch is intended for periodical data when the period is equal 2^pb. + +fb - Word size (the number of fast bytes). + It can be in the range from 5 to 273. The default value is 32. + Usually, a big number gives a little bit better compression ratio and + slower compression process. + +numThreads - The number of thereads. 1 or 2. The default value is 2. + Fast mode (algo = 0) can use only 1 thread. + +Out: + destLen - processed output size +Returns: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect paramater + SZ_ERROR_OUTPUT_EOF - output buffer overflow + SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) +*/ + +MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen, + unsigned char *outProps, size_t *outPropsSize, /* *outPropsSize must be = 5 */ + int level, /* 0 <= level <= 9, default = 5 */ + unsigned dictSize, /* default = (1 << 24) */ + int lc, /* 0 <= lc <= 8, default = 3 */ + int lp, /* 0 <= lp <= 4, default = 0 */ + int pb, /* 0 <= pb <= 4, default = 2 */ + int fb, /* 5 <= fb <= 273, default = 32 */ + int numThreads /* 1 or 2, default = 2 */ + ); + +/* +LzmaUncompress +-------------- +In: + dest - output data + destLen - output data size + src - input data + srcLen - input data size +Out: + destLen - processed output size + srcLen - processed input size +Returns: + SZ_OK - OK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation arror + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src) +*/ + +MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen, + const unsigned char *props, size_t propsSize); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/MtCoder.c b/mp/src/utils/lzma/C/MtCoder.c new file mode 100644 index 00000000..616f0b41 --- /dev/null +++ b/mp/src/utils/lzma/C/MtCoder.c @@ -0,0 +1,329 @@ +/* MtCoder.c -- Multi-thread Coder +2010-09-24 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "MtCoder.h" + +void LoopThread_Construct(CLoopThread *p) +{ + Thread_Construct(&p->thread); + Event_Construct(&p->startEvent); + Event_Construct(&p->finishedEvent); +} + +void LoopThread_Close(CLoopThread *p) +{ + Thread_Close(&p->thread); + Event_Close(&p->startEvent); + Event_Close(&p->finishedEvent); +} + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp) +{ + CLoopThread *p = (CLoopThread *)pp; + for (;;) + { + if (Event_Wait(&p->startEvent) != 0) + return SZ_ERROR_THREAD; + if (p->stop) + return 0; + p->res = p->func(p->param); + if (Event_Set(&p->finishedEvent) != 0) + return SZ_ERROR_THREAD; + } +} + +WRes LoopThread_Create(CLoopThread *p) +{ + p->stop = 0; + RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent)); + RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent)); + return Thread_Create(&p->thread, LoopThreadFunc, p); +} + +WRes LoopThread_StopAndWait(CLoopThread *p) +{ + p->stop = 1; + if (Event_Set(&p->startEvent) != 0) + return SZ_ERROR_THREAD; + return Thread_Wait(&p->thread); +} + +WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); } +WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); } + +static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize) +{ + return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK; +} + +static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress) +{ + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + p->inSizes[i] = p->outSizes[i] = 0; + p->totalInSize = p->totalOutSize = 0; + p->progress = progress; + p->res = SZ_OK; +} + +static void MtProgress_Reinit(CMtProgress *p, unsigned index) +{ + p->inSizes[index] = 0; + p->outSizes[index] = 0; +} + +#define UPDATE_PROGRESS(size, prev, total) \ + if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; } + +SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize) +{ + SRes res; + CriticalSection_Enter(&p->cs); + UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize) + UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize) + if (p->res == SZ_OK) + p->res = Progress(p->progress, p->totalInSize, p->totalOutSize); + res = p->res; + CriticalSection_Leave(&p->cs); + return res; +} + +static void MtProgress_SetError(CMtProgress *p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + +static void MtCoder_SetError(CMtCoder* p, SRes res) +{ + CriticalSection_Enter(&p->cs); + if (p->res == SZ_OK) + p->res = res; + CriticalSection_Leave(&p->cs); +} + +/* ---------- MtThread ---------- */ + +void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder) +{ + p->mtCoder = mtCoder; + p->outBuf = 0; + p->inBuf = 0; + Event_Construct(&p->canRead); + Event_Construct(&p->canWrite); + LoopThread_Construct(&p->thread); +} + +#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; } + +static void CMtThread_CloseEvents(CMtThread *p) +{ + Event_Close(&p->canRead); + Event_Close(&p->canWrite); +} + +static void CMtThread_Destruct(CMtThread *p) +{ + CMtThread_CloseEvents(p); + + if (Thread_WasCreated(&p->thread.thread)) + { + LoopThread_StopAndWait(&p->thread); + LoopThread_Close(&p->thread); + } + + if (p->mtCoder->alloc) + IAlloc_Free(p->mtCoder->alloc, p->outBuf); + p->outBuf = 0; + + if (p->mtCoder->alloc) + IAlloc_Free(p->mtCoder->alloc, p->inBuf); + p->inBuf = 0; +} + +#define MY_BUF_ALLOC(buf, size, newSize) \ + if (buf == 0 || size != newSize) \ + { IAlloc_Free(p->mtCoder->alloc, buf); \ + size = newSize; buf = (Byte *)IAlloc_Alloc(p->mtCoder->alloc, size); \ + if (buf == 0) return SZ_ERROR_MEM; } + +static SRes CMtThread_Prepare(CMtThread *p) +{ + MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize) + MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize) + + p->stopReading = False; + p->stopWriting = False; + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite)); + + return SZ_OK; +} + +static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize) +{ + size_t size = *processedSize; + *processedSize = 0; + while (size != 0) + { + size_t curSize = size; + SRes res = stream->Read(stream, data, &curSize); + *processedSize += curSize; + data += curSize; + size -= curSize; + RINOK(res); + if (curSize == 0) + return SZ_OK; + } + return SZ_OK; +} + +#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1] + +static SRes MtThread_Process(CMtThread *p, Bool *stop) +{ + CMtThread *next; + *stop = True; + if (Event_Wait(&p->canRead) != 0) + return SZ_ERROR_THREAD; + + next = GET_NEXT_THREAD(p); + + if (p->stopReading) + { + next->stopReading = True; + return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } + + { + size_t size = p->mtCoder->blockSize; + size_t destSize = p->outBufSize; + + RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size)); + next->stopReading = *stop = (size != p->mtCoder->blockSize); + if (Event_Set(&next->canRead) != 0) + return SZ_ERROR_THREAD; + + RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index, + p->outBuf, &destSize, p->inBuf, size, *stop)); + + MtProgress_Reinit(&p->mtCoder->mtProgress, p->index); + + if (Event_Wait(&p->canWrite) != 0) + return SZ_ERROR_THREAD; + if (p->stopWriting) + return SZ_ERROR_FAIL; + if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize) + return SZ_ERROR_WRITE; + return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD; + } +} + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp) +{ + CMtThread *p = (CMtThread *)pp; + for (;;) + { + Bool stop; + CMtThread *next = GET_NEXT_THREAD(p); + SRes res = MtThread_Process(p, &stop); + if (res != SZ_OK) + { + MtCoder_SetError(p->mtCoder, res); + MtProgress_SetError(&p->mtCoder->mtProgress, res); + next->stopReading = True; + next->stopWriting = True; + Event_Set(&next->canRead); + Event_Set(&next->canWrite); + return res; + } + if (stop) + return 0; + } +} + +void MtCoder_Construct(CMtCoder* p) +{ + unsigned i; + p->alloc = 0; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + { + CMtThread *t = &p->threads[i]; + t->index = i; + CMtThread_Construct(t, p); + } + CriticalSection_Init(&p->cs); + CriticalSection_Init(&p->mtProgress.cs); +} + +void MtCoder_Destruct(CMtCoder* p) +{ + unsigned i; + for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++) + CMtThread_Destruct(&p->threads[i]); + CriticalSection_Delete(&p->cs); + CriticalSection_Delete(&p->mtProgress.cs); +} + +SRes MtCoder_Code(CMtCoder *p) +{ + unsigned i, numThreads = p->numThreads; + SRes res = SZ_OK; + p->res = SZ_OK; + + MtProgress_Init(&p->mtProgress, p->progress); + + for (i = 0; i < numThreads; i++) + { + RINOK(CMtThread_Prepare(&p->threads[i])); + } + + for (i = 0; i < numThreads; i++) + { + CMtThread *t = &p->threads[i]; + CLoopThread *lt = &t->thread; + + if (!Thread_WasCreated(<->thread)) + { + lt->func = ThreadFunc; + lt->param = t; + + if (LoopThread_Create(lt) != SZ_OK) + { + res = SZ_ERROR_THREAD; + break; + } + } + } + + if (res == SZ_OK) + { + unsigned j; + for (i = 0; i < numThreads; i++) + { + CMtThread *t = &p->threads[i]; + if (LoopThread_StartSubThread(&t->thread) != SZ_OK) + { + res = SZ_ERROR_THREAD; + p->threads[0].stopReading = True; + break; + } + } + + Event_Set(&p->threads[0].canWrite); + Event_Set(&p->threads[0].canRead); + + for (j = 0; j < i; j++) + LoopThread_WaitSubThread(&p->threads[j].thread); + } + + for (i = 0; i < numThreads; i++) + CMtThread_CloseEvents(&p->threads[i]); + return (res == SZ_OK) ? p->res : res; +} diff --git a/mp/src/utils/lzma/C/MtCoder.h b/mp/src/utils/lzma/C/MtCoder.h new file mode 100644 index 00000000..f0f06da2 --- /dev/null +++ b/mp/src/utils/lzma/C/MtCoder.h @@ -0,0 +1,98 @@ +/* MtCoder.h -- Multi-thread Coder +2009-11-19 : Igor Pavlov : Public domain */ + +#ifndef __MT_CODER_H +#define __MT_CODER_H + +#include "Threads.h" + +EXTERN_C_BEGIN + +typedef struct +{ + CThread thread; + CAutoResetEvent startEvent; + CAutoResetEvent finishedEvent; + int stop; + + THREAD_FUNC_TYPE func; + LPVOID param; + THREAD_FUNC_RET_TYPE res; +} CLoopThread; + +void LoopThread_Construct(CLoopThread *p); +void LoopThread_Close(CLoopThread *p); +WRes LoopThread_Create(CLoopThread *p); +WRes LoopThread_StopAndWait(CLoopThread *p); +WRes LoopThread_StartSubThread(CLoopThread *p); +WRes LoopThread_WaitSubThread(CLoopThread *p); + +#ifndef _7ZIP_ST +#define NUM_MT_CODER_THREADS_MAX 32 +#else +#define NUM_MT_CODER_THREADS_MAX 1 +#endif + +typedef struct +{ + UInt64 totalInSize; + UInt64 totalOutSize; + ICompressProgress *progress; + SRes res; + CCriticalSection cs; + UInt64 inSizes[NUM_MT_CODER_THREADS_MAX]; + UInt64 outSizes[NUM_MT_CODER_THREADS_MAX]; +} CMtProgress; + +SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize); + +struct _CMtCoder; + +typedef struct +{ + struct _CMtCoder *mtCoder; + Byte *outBuf; + size_t outBufSize; + Byte *inBuf; + size_t inBufSize; + unsigned index; + CLoopThread thread; + + Bool stopReading; + Bool stopWriting; + CAutoResetEvent canRead; + CAutoResetEvent canWrite; +} CMtThread; + +typedef struct +{ + SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize, + const Byte *src, size_t srcSize, int finished); +} IMtCoderCallback; + +typedef struct _CMtCoder +{ + size_t blockSize; + size_t destBlockSize; + unsigned numThreads; + + ISeqInStream *inStream; + ISeqOutStream *outStream; + ICompressProgress *progress; + ISzAlloc *alloc; + + IMtCoderCallback *mtCallback; + CCriticalSection cs; + SRes res; + + CMtProgress mtProgress; + CMtThread threads[NUM_MT_CODER_THREADS_MAX]; +} CMtCoder; + +void MtCoder_Construct(CMtCoder* p); +void MtCoder_Destruct(CMtCoder* p); +SRes MtCoder_Code(CMtCoder *p); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Ppmd.h b/mp/src/utils/lzma/C/Ppmd.h new file mode 100644 index 00000000..4356dd1d --- /dev/null +++ b/mp/src/utils/lzma/C/Ppmd.h @@ -0,0 +1,85 @@ +/* Ppmd.h -- PPMD codec common code +2013-01-18 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#ifndef __PPMD_H +#define __PPMD_H + +#include "CpuArch.h" + +EXTERN_C_BEGIN + +#ifdef MY_CPU_32BIT + #define PPMD_32BIT +#endif + +#define PPMD_INT_BITS 7 +#define PPMD_PERIOD_BITS 7 +#define PPMD_BIN_SCALE (1 << (PPMD_INT_BITS + PPMD_PERIOD_BITS)) + +#define PPMD_GET_MEAN_SPEC(summ, shift, round) (((summ) + (1 << ((shift) - (round)))) >> (shift)) +#define PPMD_GET_MEAN(summ) PPMD_GET_MEAN_SPEC((summ), PPMD_PERIOD_BITS, 2) +#define PPMD_UPDATE_PROB_0(prob) ((prob) + (1 << PPMD_INT_BITS) - PPMD_GET_MEAN(prob)) +#define PPMD_UPDATE_PROB_1(prob) ((prob) - PPMD_GET_MEAN(prob)) + +#define PPMD_N1 4 +#define PPMD_N2 4 +#define PPMD_N3 4 +#define PPMD_N4 ((128 + 3 - 1 * PPMD_N1 - 2 * PPMD_N2 - 3 * PPMD_N3) / 4) +#define PPMD_NUM_INDEXES (PPMD_N1 + PPMD_N2 + PPMD_N3 + PPMD_N4) + +#pragma pack(push, 1) +/* Most compilers works OK here even without #pragma pack(push, 1), but some GCC compilers need it. */ + +/* SEE-contexts for PPM-contexts with masked symbols */ +typedef struct +{ + UInt16 Summ; /* Freq */ + Byte Shift; /* Speed of Freq change; low Shift is for fast change */ + Byte Count; /* Count to next change of Shift */ +} CPpmd_See; + +#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \ + { (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); } + +typedef struct +{ + Byte Symbol; + Byte Freq; + UInt16 SuccessorLow; + UInt16 SuccessorHigh; +} CPpmd_State; + +#pragma pack(pop) + +typedef + #ifdef PPMD_32BIT + CPpmd_State * + #else + UInt32 + #endif + CPpmd_State_Ref; + +typedef + #ifdef PPMD_32BIT + void * + #else + UInt32 + #endif + CPpmd_Void_Ref; + +typedef + #ifdef PPMD_32BIT + Byte * + #else + UInt32 + #endif + CPpmd_Byte_Ref; + +#define PPMD_SetAllBitsIn256Bytes(p) \ + { unsigned i; for (i = 0; i < 256 / sizeof(p[0]); i += 8) { \ + p[i+7] = p[i+6] = p[i+5] = p[i+4] = p[i+3] = p[i+2] = p[i+1] = p[i+0] = ~(size_t)0; }} + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Ppmd7.c b/mp/src/utils/lzma/C/Ppmd7.c new file mode 100644 index 00000000..bb5d175e --- /dev/null +++ b/mp/src/utils/lzma/C/Ppmd7.c @@ -0,0 +1,710 @@ +/* Ppmd7.c -- PPMdH codec +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include + +#include "Ppmd7.h" + +const Byte PPMD7_kExpEscape[16] = { 25, 14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; +static const UInt16 kInitBinEsc[] = { 0x3CDD, 0x1F3F, 0x59BF, 0x48F3, 0x64A1, 0x5ABC, 0x6632, 0x6051}; + +#define MAX_FREQ 124 +#define UNIT_SIZE 12 + +#define U2B(nu) ((UInt32)(nu) * UNIT_SIZE) +#define U2I(nu) (p->Units2Indx[(nu) - 1]) +#define I2U(indx) (p->Indx2Units[indx]) + +#ifdef PPMD_32BIT + #define REF(ptr) (ptr) +#else + #define REF(ptr) ((UInt32)((Byte *)(ptr) - (p)->Base)) +#endif + +#define STATS_REF(ptr) ((CPpmd_State_Ref)REF(ptr)) + +#define CTX(ref) ((CPpmd7_Context *)Ppmd7_GetContext(p, ref)) +#define STATS(ctx) Ppmd7_GetStats(p, ctx) +#define ONE_STATE(ctx) Ppmd7Context_OneState(ctx) +#define SUFFIX(ctx) CTX((ctx)->Suffix) + +typedef CPpmd7_Context * CTX_PTR; + +struct CPpmd7_Node_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Node_ * + #else + UInt32 + #endif + CPpmd7_Node_Ref; + +typedef struct CPpmd7_Node_ +{ + UInt16 Stamp; /* must be at offset 0 as CPpmd7_Context::NumStats. Stamp=0 means free */ + UInt16 NU; + CPpmd7_Node_Ref Next; /* must be at offset >= 4 */ + CPpmd7_Node_Ref Prev; +} CPpmd7_Node; + +#ifdef PPMD_32BIT + #define NODE(ptr) (ptr) +#else + #define NODE(offs) ((CPpmd7_Node *)(p->Base + (offs))) +#endif + +void Ppmd7_Construct(CPpmd7 *p) +{ + unsigned i, k, m; + + p->Base = 0; + + for (i = 0, k = 0; i < PPMD_NUM_INDEXES; i++) + { + unsigned step = (i >= 12 ? 4 : (i >> 2) + 1); + do { p->Units2Indx[k++] = (Byte)i; } while(--step); + p->Indx2Units[i] = (Byte)k; + } + + p->NS2BSIndx[0] = (0 << 1); + p->NS2BSIndx[1] = (1 << 1); + memset(p->NS2BSIndx + 2, (2 << 1), 9); + memset(p->NS2BSIndx + 11, (3 << 1), 256 - 11); + + for (i = 0; i < 3; i++) + p->NS2Indx[i] = (Byte)i; + for (m = i, k = 1; i < 256; i++) + { + p->NS2Indx[i] = (Byte)m; + if (--k == 0) + k = (++m) - 2; + } + + memset(p->HB2Flag, 0, 0x40); + memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40); +} + +void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->Base); + p->Size = 0; + p->Base = 0; +} + +Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc) +{ + if (p->Base == 0 || p->Size != size) + { + Ppmd7_Free(p, alloc); + p->AlignOffset = + #ifdef PPMD_32BIT + (4 - size) & 3; + #else + 4 - (size & 3); + #endif + if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size + #ifndef PPMD_32BIT + + UNIT_SIZE + #endif + )) == 0) + return False; + p->Size = size; + } + return True; +} + +static void InsertNode(CPpmd7 *p, void *node, unsigned indx) +{ + *((CPpmd_Void_Ref *)node) = p->FreeList[indx]; + p->FreeList[indx] = REF(node); +} + +static void *RemoveNode(CPpmd7 *p, unsigned indx) +{ + CPpmd_Void_Ref *node = (CPpmd_Void_Ref *)Ppmd7_GetPtr(p, p->FreeList[indx]); + p->FreeList[indx] = *node; + return node; +} + +static void SplitBlock(CPpmd7 *p, void *ptr, unsigned oldIndx, unsigned newIndx) +{ + unsigned i, nu = I2U(oldIndx) - I2U(newIndx); + ptr = (Byte *)ptr + U2B(I2U(newIndx)); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, ((Byte *)ptr) + U2B(k), nu - k - 1); + } + InsertNode(p, ptr, i); +} + +static void GlueFreeBlocks(CPpmd7 *p) +{ + #ifdef PPMD_32BIT + CPpmd7_Node headItem; + CPpmd7_Node_Ref head = &headItem; + #else + CPpmd7_Node_Ref head = p->AlignOffset + p->Size; + #endif + + CPpmd7_Node_Ref n = head; + unsigned i; + + p->GlueCount = 255; + + /* create doubly-linked list of free blocks */ + for (i = 0; i < PPMD_NUM_INDEXES; i++) + { + UInt16 nu = I2U(i); + CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p->FreeList[i]; + p->FreeList[i] = 0; + while (next != 0) + { + CPpmd7_Node *node = NODE(next); + node->Next = n; + n = NODE(n)->Prev = next; + next = *(const CPpmd7_Node_Ref *)node; + node->Stamp = 0; + node->NU = (UInt16)nu; + } + } + NODE(head)->Stamp = 1; + NODE(head)->Next = n; + NODE(n)->Prev = head; + if (p->LoUnit != p->HiUnit) + ((CPpmd7_Node *)p->LoUnit)->Stamp = 1; + + /* Glue free blocks */ + while (n != head) + { + CPpmd7_Node *node = NODE(n); + UInt32 nu = (UInt32)node->NU; + for (;;) + { + CPpmd7_Node *node2 = NODE(n) + nu; + nu += node2->NU; + if (node2->Stamp != 0 || nu >= 0x10000) + break; + NODE(node2->Prev)->Next = node2->Next; + NODE(node2->Next)->Prev = node2->Prev; + node->NU = (UInt16)nu; + } + n = node->Next; + } + + /* Fill lists of free blocks */ + for (n = NODE(head)->Next; n != head;) + { + CPpmd7_Node *node = NODE(n); + unsigned nu; + CPpmd7_Node_Ref next = node->Next; + for (nu = node->NU; nu > 128; nu -= 128, node += 128) + InsertNode(p, node, PPMD_NUM_INDEXES - 1); + if (I2U(i = U2I(nu)) != nu) + { + unsigned k = I2U(--i); + InsertNode(p, node + k, nu - k - 1); + } + InsertNode(p, node, i); + n = next; + } +} + +static void *AllocUnitsRare(CPpmd7 *p, unsigned indx) +{ + unsigned i; + void *retVal; + if (p->GlueCount == 0) + { + GlueFreeBlocks(p); + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + } + i = indx; + do + { + if (++i == PPMD_NUM_INDEXES) + { + UInt32 numBytes = U2B(I2U(indx)); + p->GlueCount--; + return ((UInt32)(p->UnitsStart - p->Text) > numBytes) ? (p->UnitsStart -= numBytes) : (NULL); + } + } + while (p->FreeList[i] == 0); + retVal = RemoveNode(p, i); + SplitBlock(p, retVal, i, indx); + return retVal; +} + +static void *AllocUnits(CPpmd7 *p, unsigned indx) +{ + UInt32 numBytes; + if (p->FreeList[indx] != 0) + return RemoveNode(p, indx); + numBytes = U2B(I2U(indx)); + if (numBytes <= (UInt32)(p->HiUnit - p->LoUnit)) + { + void *retVal = p->LoUnit; + p->LoUnit += numBytes; + return retVal; + } + return AllocUnitsRare(p, indx); +} + +#define MyMem12Cpy(dest, src, num) \ + { UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \ + do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); } + +static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU) +{ + unsigned i0 = U2I(oldNU); + unsigned i1 = U2I(newNU); + if (i0 == i1) + return oldPtr; + if (p->FreeList[i1] != 0) + { + void *ptr = RemoveNode(p, i1); + MyMem12Cpy(ptr, oldPtr, newNU); + InsertNode(p, oldPtr, i0); + return ptr; + } + SplitBlock(p, oldPtr, i0, i1); + return oldPtr; +} + +#define SUCCESSOR(p) ((CPpmd_Void_Ref)((p)->SuccessorLow | ((UInt32)(p)->SuccessorHigh << 16))) + +static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v) +{ + (p)->SuccessorLow = (UInt16)((UInt32)(v) & 0xFFFF); + (p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF); +} + +static void RestartModel(CPpmd7 *p) +{ + unsigned i, k, m; + + memset(p->FreeList, 0, sizeof(p->FreeList)); + p->Text = p->Base + p->AlignOffset; + p->HiUnit = p->Text + p->Size; + p->LoUnit = p->UnitsStart = p->HiUnit - p->Size / 8 / UNIT_SIZE * 7 * UNIT_SIZE; + p->GlueCount = 0; + + p->OrderFall = p->MaxOrder; + p->RunLength = p->InitRL = -(Int32)((p->MaxOrder < 12) ? p->MaxOrder : 12) - 1; + p->PrevSuccess = 0; + + p->MinContext = p->MaxContext = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); /* AllocContext(p); */ + p->MinContext->Suffix = 0; + p->MinContext->NumStats = 256; + p->MinContext->SummFreq = 256 + 1; + p->FoundState = (CPpmd_State *)p->LoUnit; /* AllocUnits(p, PPMD_NUM_INDEXES - 1); */ + p->LoUnit += U2B(256 / 2); + p->MinContext->Stats = REF(p->FoundState); + for (i = 0; i < 256; i++) + { + CPpmd_State *s = &p->FoundState[i]; + s->Symbol = (Byte)i; + s->Freq = 1; + SetSuccessor(s, 0); + } + + for (i = 0; i < 128; i++) + for (k = 0; k < 8; k++) + { + UInt16 *dest = p->BinSumm[i] + k; + UInt16 val = (UInt16)(PPMD_BIN_SCALE - kInitBinEsc[k] / (i + 2)); + for (m = 0; m < 64; m += 8) + dest[m] = val; + } + + for (i = 0; i < 25; i++) + for (k = 0; k < 16; k++) + { + CPpmd_See *s = &p->See[i][k]; + s->Summ = (UInt16)((5 * i + 10) << (s->Shift = PPMD_PERIOD_BITS - 4)); + s->Count = 4; + } +} + +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder) +{ + p->MaxOrder = maxOrder; + RestartModel(p); + p->DummySee.Shift = PPMD_PERIOD_BITS; + p->DummySee.Summ = 0; /* unused */ + p->DummySee.Count = 64; /* unused */ +} + +static CTX_PTR CreateSuccessors(CPpmd7 *p, Bool skip) +{ + CPpmd_State upState; + CTX_PTR c = p->MinContext; + CPpmd_Byte_Ref upBranch = (CPpmd_Byte_Ref)SUCCESSOR(p->FoundState); + CPpmd_State *ps[PPMD7_MAX_ORDER]; + unsigned numPs = 0; + + if (!skip) + ps[numPs++] = p->FoundState; + + while (c->Suffix) + { + CPpmd_Void_Ref successor; + CPpmd_State *s; + c = SUFFIX(c); + if (c->NumStats != 1) + { + for (s = STATS(c); s->Symbol != p->FoundState->Symbol; s++); + } + else + s = ONE_STATE(c); + successor = SUCCESSOR(s); + if (successor != upBranch) + { + c = CTX(successor); + if (numPs == 0) + return c; + break; + } + ps[numPs++] = s; + } + + upState.Symbol = *(const Byte *)Ppmd7_GetPtr(p, upBranch); + SetSuccessor(&upState, upBranch + 1); + + if (c->NumStats == 1) + upState.Freq = ONE_STATE(c)->Freq; + else + { + UInt32 cf, s0; + CPpmd_State *s; + for (s = STATS(c); s->Symbol != upState.Symbol; s++); + cf = s->Freq - 1; + s0 = c->SummFreq - c->NumStats - cf; + upState.Freq = (Byte)(1 + ((2 * cf <= s0) ? (5 * cf > s0) : ((2 * cf + 3 * s0 - 1) / (2 * s0)))); + } + + do + { + /* Create Child */ + CTX_PTR c1; /* = AllocContext(p); */ + if (p->HiUnit != p->LoUnit) + c1 = (CTX_PTR)(p->HiUnit -= UNIT_SIZE); + else if (p->FreeList[0] != 0) + c1 = (CTX_PTR)RemoveNode(p, 0); + else + { + c1 = (CTX_PTR)AllocUnitsRare(p, 0); + if (!c1) + return NULL; + } + c1->NumStats = 1; + *ONE_STATE(c1) = upState; + c1->Suffix = REF(c); + SetSuccessor(ps[--numPs], REF(c1)); + c = c1; + } + while (numPs != 0); + + return c; +} + +static void SwapStates(CPpmd_State *t1, CPpmd_State *t2) +{ + CPpmd_State tmp = *t1; + *t1 = *t2; + *t2 = tmp; +} + +static void UpdateModel(CPpmd7 *p) +{ + CPpmd_Void_Ref successor, fSuccessor = SUCCESSOR(p->FoundState); + CTX_PTR c; + unsigned s0, ns; + + if (p->FoundState->Freq < MAX_FREQ / 4 && p->MinContext->Suffix != 0) + { + c = SUFFIX(p->MinContext); + + if (c->NumStats == 1) + { + CPpmd_State *s = ONE_STATE(c); + if (s->Freq < 32) + s->Freq++; + } + else + { + CPpmd_State *s = STATS(c); + if (s->Symbol != p->FoundState->Symbol) + { + do { s++; } while (s->Symbol != p->FoundState->Symbol); + if (s[0].Freq >= s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + s--; + } + } + if (s->Freq < MAX_FREQ - 9) + { + s->Freq += 2; + c->SummFreq += 2; + } + } + } + + if (p->OrderFall == 0) + { + p->MinContext = p->MaxContext = CreateSuccessors(p, True); + if (p->MinContext == 0) + { + RestartModel(p); + return; + } + SetSuccessor(p->FoundState, REF(p->MinContext)); + return; + } + + *p->Text++ = p->FoundState->Symbol; + successor = REF(p->Text); + if (p->Text >= p->UnitsStart) + { + RestartModel(p); + return; + } + + if (fSuccessor) + { + if (fSuccessor <= successor) + { + CTX_PTR cs = CreateSuccessors(p, False); + if (cs == NULL) + { + RestartModel(p); + return; + } + fSuccessor = REF(cs); + } + if (--p->OrderFall == 0) + { + successor = fSuccessor; + p->Text -= (p->MaxContext != p->MinContext); + } + } + else + { + SetSuccessor(p->FoundState, successor); + fSuccessor = REF(p->MinContext); + } + + s0 = p->MinContext->SummFreq - (ns = p->MinContext->NumStats) - (p->FoundState->Freq - 1); + + for (c = p->MaxContext; c != p->MinContext; c = SUFFIX(c)) + { + unsigned ns1; + UInt32 cf, sf; + if ((ns1 = c->NumStats) != 1) + { + if ((ns1 & 1) == 0) + { + /* Expand for one UNIT */ + unsigned oldNU = ns1 >> 1; + unsigned i = U2I(oldNU); + if (i != U2I(oldNU + 1)) + { + void *ptr = AllocUnits(p, i + 1); + void *oldPtr; + if (!ptr) + { + RestartModel(p); + return; + } + oldPtr = STATS(c); + MyMem12Cpy(ptr, oldPtr, oldNU); + InsertNode(p, oldPtr, i); + c->Stats = STATS_REF(ptr); + } + } + c->SummFreq = (UInt16)(c->SummFreq + (2 * ns1 < ns) + 2 * ((4 * ns1 <= ns) & (c->SummFreq <= 8 * ns1))); + } + else + { + CPpmd_State *s = (CPpmd_State*)AllocUnits(p, 0); + if (!s) + { + RestartModel(p); + return; + } + *s = *ONE_STATE(c); + c->Stats = REF(s); + if (s->Freq < MAX_FREQ / 4 - 1) + s->Freq <<= 1; + else + s->Freq = MAX_FREQ - 4; + c->SummFreq = (UInt16)(s->Freq + p->InitEsc + (ns > 3)); + } + cf = 2 * (UInt32)p->FoundState->Freq * (c->SummFreq + 6); + sf = (UInt32)s0 + c->SummFreq; + if (cf < 6 * sf) + { + cf = 1 + (cf > sf) + (cf >= 4 * sf); + c->SummFreq += 3; + } + else + { + cf = 4 + (cf >= 9 * sf) + (cf >= 12 * sf) + (cf >= 15 * sf); + c->SummFreq = (UInt16)(c->SummFreq + cf); + } + { + CPpmd_State *s = STATS(c) + ns1; + SetSuccessor(s, successor); + s->Symbol = p->FoundState->Symbol; + s->Freq = (Byte)cf; + c->NumStats = (UInt16)(ns1 + 1); + } + } + p->MaxContext = p->MinContext = CTX(fSuccessor); +} + +static void Rescale(CPpmd7 *p) +{ + unsigned i, adder, sumFreq, escFreq; + CPpmd_State *stats = STATS(p->MinContext); + CPpmd_State *s = p->FoundState; + { + CPpmd_State tmp = *s; + for (; s != stats; s--) + s[0] = s[-1]; + *s = tmp; + } + escFreq = p->MinContext->SummFreq - s->Freq; + s->Freq += 4; + adder = (p->OrderFall != 0); + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq = s->Freq; + + i = p->MinContext->NumStats - 1; + do + { + escFreq -= (++s)->Freq; + s->Freq = (Byte)((s->Freq + adder) >> 1); + sumFreq += s->Freq; + if (s[0].Freq > s[-1].Freq) + { + CPpmd_State *s1 = s; + CPpmd_State tmp = *s1; + do + s1[0] = s1[-1]; + while (--s1 != stats && tmp.Freq > s1[-1].Freq); + *s1 = tmp; + } + } + while (--i); + + if (s->Freq == 0) + { + unsigned numStats = p->MinContext->NumStats; + unsigned n0, n1; + do { i++; } while ((--s)->Freq == 0); + escFreq += i; + p->MinContext->NumStats = (UInt16)(p->MinContext->NumStats - i); + if (p->MinContext->NumStats == 1) + { + CPpmd_State tmp = *stats; + do + { + tmp.Freq = (Byte)(tmp.Freq - (tmp.Freq >> 1)); + escFreq >>= 1; + } + while (escFreq > 1); + InsertNode(p, stats, U2I(((numStats + 1) >> 1))); + *(p->FoundState = ONE_STATE(p->MinContext)) = tmp; + return; + } + n0 = (numStats + 1) >> 1; + n1 = (p->MinContext->NumStats + 1) >> 1; + if (n0 != n1) + p->MinContext->Stats = STATS_REF(ShrinkUnits(p, stats, n0, n1)); + } + p->MinContext->SummFreq = (UInt16)(sumFreq + escFreq - (escFreq >> 1)); + p->FoundState = STATS(p->MinContext); +} + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *escFreq) +{ + CPpmd_See *see; + unsigned nonMasked = p->MinContext->NumStats - numMasked; + if (p->MinContext->NumStats != 256) + { + see = p->See[p->NS2Indx[nonMasked - 1]] + + (nonMasked < (unsigned)SUFFIX(p->MinContext)->NumStats - p->MinContext->NumStats) + + 2 * (p->MinContext->SummFreq < 11 * p->MinContext->NumStats) + + 4 * (numMasked > nonMasked) + + p->HiBitsFlag; + { + unsigned r = (see->Summ >> see->Shift); + see->Summ = (UInt16)(see->Summ - r); + *escFreq = r + (r == 0); + } + } + else + { + see = &p->DummySee; + *escFreq = 1; + } + return see; +} + +static void NextContext(CPpmd7 *p) +{ + CTX_PTR c = CTX(SUCCESSOR(p->FoundState)); + if (p->OrderFall == 0 && (Byte *)c > p->Text) + p->MinContext = p->MaxContext = c; + else + UpdateModel(p); +} + +void Ppmd7_Update1(CPpmd7 *p) +{ + CPpmd_State *s = p->FoundState; + s->Freq += 4; + p->MinContext->SummFreq += 4; + if (s[0].Freq > s[-1].Freq) + { + SwapStates(&s[0], &s[-1]); + p->FoundState = --s; + if (s->Freq > MAX_FREQ) + Rescale(p); + } + NextContext(p); +} + +void Ppmd7_Update1_0(CPpmd7 *p) +{ + p->PrevSuccess = (2 * p->FoundState->Freq > p->MinContext->SummFreq); + p->RunLength += p->PrevSuccess; + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + NextContext(p); +} + +void Ppmd7_UpdateBin(CPpmd7 *p) +{ + p->FoundState->Freq = (Byte)(p->FoundState->Freq + (p->FoundState->Freq < 128 ? 1: 0)); + p->PrevSuccess = 1; + p->RunLength++; + NextContext(p); +} + +void Ppmd7_Update2(CPpmd7 *p) +{ + p->MinContext->SummFreq += 4; + if ((p->FoundState->Freq += 4) > MAX_FREQ) + Rescale(p); + p->RunLength = p->InitRL; + UpdateModel(p); +} diff --git a/mp/src/utils/lzma/C/Ppmd7.h b/mp/src/utils/lzma/C/Ppmd7.h new file mode 100644 index 00000000..96521c31 --- /dev/null +++ b/mp/src/utils/lzma/C/Ppmd7.h @@ -0,0 +1,140 @@ +/* Ppmd7.h -- PPMdH compression codec +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +/* This code supports virtual RangeDecoder and includes the implementation +of RangeCoder from 7z, instead of RangeCoder from original PPMd var.H. +If you need the compatibility with original PPMd var.H, you can use external RangeDecoder */ + +#ifndef __PPMD7_H +#define __PPMD7_H + +#include "Ppmd.h" + +EXTERN_C_BEGIN + +#define PPMD7_MIN_ORDER 2 +#define PPMD7_MAX_ORDER 64 + +#define PPMD7_MIN_MEM_SIZE (1 << 11) +#define PPMD7_MAX_MEM_SIZE (0xFFFFFFFF - 12 * 3) + +struct CPpmd7_Context_; + +typedef + #ifdef PPMD_32BIT + struct CPpmd7_Context_ * + #else + UInt32 + #endif + CPpmd7_Context_Ref; + +typedef struct CPpmd7_Context_ +{ + UInt16 NumStats; + UInt16 SummFreq; + CPpmd_State_Ref Stats; + CPpmd7_Context_Ref Suffix; +} CPpmd7_Context; + +#define Ppmd7Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq) + +typedef struct +{ + CPpmd7_Context *MinContext, *MaxContext; + CPpmd_State *FoundState; + unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder, HiBitsFlag; + Int32 RunLength, InitRL; /* must be 32-bit at least */ + + UInt32 Size; + UInt32 GlueCount; + Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart; + UInt32 AlignOffset; + + Byte Indx2Units[PPMD_NUM_INDEXES]; + Byte Units2Indx[128]; + CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES]; + Byte NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; + CPpmd_See DummySee, See[25][16]; + UInt16 BinSumm[128][64]; +} CPpmd7; + +void Ppmd7_Construct(CPpmd7 *p); +Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc); +void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc); +void Ppmd7_Init(CPpmd7 *p, unsigned maxOrder); +#define Ppmd7_WasAllocated(p) ((p)->Base != NULL) + + +/* ---------- Internal Functions ---------- */ + +extern const Byte PPMD7_kExpEscape[16]; + +#ifdef PPMD_32BIT + #define Ppmd7_GetPtr(p, ptr) (ptr) + #define Ppmd7_GetContext(p, ptr) (ptr) + #define Ppmd7_GetStats(p, ctx) ((ctx)->Stats) +#else + #define Ppmd7_GetPtr(p, offs) ((void *)((p)->Base + (offs))) + #define Ppmd7_GetContext(p, offs) ((CPpmd7_Context *)Ppmd7_GetPtr((p), (offs))) + #define Ppmd7_GetStats(p, ctx) ((CPpmd_State *)Ppmd7_GetPtr((p), ((ctx)->Stats))) +#endif + +void Ppmd7_Update1(CPpmd7 *p); +void Ppmd7_Update1_0(CPpmd7 *p); +void Ppmd7_Update2(CPpmd7 *p); +void Ppmd7_UpdateBin(CPpmd7 *p); + +#define Ppmd7_GetBinSumm(p) \ + &p->BinSumm[Ppmd7Context_OneState(p->MinContext)->Freq - 1][p->PrevSuccess + \ + p->NS2BSIndx[Ppmd7_GetContext(p, p->MinContext->Suffix)->NumStats - 1] + \ + (p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]) + \ + 2 * p->HB2Flag[Ppmd7Context_OneState(p->MinContext)->Symbol] + \ + ((p->RunLength >> 26) & 0x20)] + +CPpmd_See *Ppmd7_MakeEscFreq(CPpmd7 *p, unsigned numMasked, UInt32 *scale); + + +/* ---------- Decode ---------- */ + +typedef struct +{ + UInt32 (*GetThreshold)(void *p, UInt32 total); + void (*Decode)(void *p, UInt32 start, UInt32 size); + UInt32 (*DecodeBit)(void *p, UInt32 size0); +} IPpmd7_RangeDec; + +typedef struct +{ + IPpmd7_RangeDec p; + UInt32 Range; + UInt32 Code; + IByteIn *Stream; +} CPpmd7z_RangeDec; + +void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p); +Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p); +#define Ppmd7z_RangeDec_IsFinishedOK(p) ((p)->Code == 0) + +int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc); + + +/* ---------- Encode ---------- */ + +typedef struct +{ + UInt64 Low; + UInt32 Range; + Byte Cache; + UInt64 CacheSize; + IByteOut *Stream; +} CPpmd7z_RangeEnc; + +void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p); +void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p); + +void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Ppmd7Dec.c b/mp/src/utils/lzma/C/Ppmd7Dec.c new file mode 100644 index 00000000..04b4b09e --- /dev/null +++ b/mp/src/utils/lzma/C/Ppmd7Dec.c @@ -0,0 +1,189 @@ +/* Ppmd7Dec.c -- PPMdH Decoder +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +Bool Ppmd7z_RangeDec_Init(CPpmd7z_RangeDec *p) +{ + unsigned i; + p->Code = 0; + p->Range = 0xFFFFFFFF; + if (p->Stream->Read((void *)p->Stream) != 0) + return False; + for (i = 0; i < 4; i++) + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + return (p->Code < 0xFFFFFFFF); +} + +static UInt32 Range_GetThreshold(void *pp, UInt32 total) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + return (p->Code) / (p->Range /= total); +} + +static void Range_Normalize(CPpmd7z_RangeDec *p) +{ + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + p->Range <<= 8; + if (p->Range < kTopValue) + { + p->Code = (p->Code << 8) | p->Stream->Read((void *)p->Stream); + p->Range <<= 8; + } + } +} + +static void Range_Decode(void *pp, UInt32 start, UInt32 size) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + p->Code -= start * p->Range; + p->Range *= size; + Range_Normalize(p); +} + +static UInt32 Range_DecodeBit(void *pp, UInt32 size0) +{ + CPpmd7z_RangeDec *p = (CPpmd7z_RangeDec *)pp; + UInt32 newBound = (p->Range >> 14) * size0; + UInt32 symbol; + if (p->Code < newBound) + { + symbol = 0; + p->Range = newBound; + } + else + { + symbol = 1; + p->Code -= newBound; + p->Range -= newBound; + } + Range_Normalize(p); + return symbol; +} + +void Ppmd7z_RangeDec_CreateVTable(CPpmd7z_RangeDec *p) +{ + p->p.GetThreshold = Range_GetThreshold; + p->p.Decode = Range_Decode; + p->p.DecodeBit = Range_DecodeBit; +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +int Ppmd7_DecodeSymbol(CPpmd7 *p, IPpmd7_RangeDec *rc) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + unsigned i; + UInt32 count, hiCnt; + if ((count = rc->GetThreshold(rc, p->MinContext->SummFreq)) < (hiCnt = s->Freq)) + { + Byte symbol; + rc->Decode(rc, 0, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1_0(p); + return symbol; + } + p->PrevSuccess = 0; + i = p->MinContext->NumStats - 1; + do + { + if ((hiCnt += (++s)->Freq) > count) + { + Byte symbol; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update1(p); + return symbol; + } + } + while (--i); + if (count >= p->MinContext->SummFreq) + return -2; + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + rc->Decode(rc, hiCnt, p->MinContext->SummFreq - hiCnt); + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + if (rc->DecodeBit(rc, *prob) == 0) + { + Byte symbol; + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + symbol = (p->FoundState = Ppmd7Context_OneState(p->MinContext))->Symbol; + Ppmd7_UpdateBin(p); + return symbol; + } + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(Ppmd7Context_OneState(p->MinContext)->Symbol) = 0; + p->PrevSuccess = 0; + } + for (;;) + { + CPpmd_State *ps[256], *s; + UInt32 freqSum, count, hiCnt; + CPpmd_See *see; + unsigned i, num, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return -1; + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + hiCnt = 0; + s = Ppmd7_GetStats(p, p->MinContext); + i = 0; + num = p->MinContext->NumStats - numMasked; + do + { + int k = (int)(MASK(s->Symbol)); + hiCnt += (s->Freq & k); + ps[i] = s++; + i -= k; + } + while (i != num); + + see = Ppmd7_MakeEscFreq(p, numMasked, &freqSum); + freqSum += hiCnt; + count = rc->GetThreshold(rc, freqSum); + + if (count < hiCnt) + { + Byte symbol; + CPpmd_State **pps = ps; + for (hiCnt = 0; (hiCnt += (*pps)->Freq) <= count; pps++); + s = *pps; + rc->Decode(rc, hiCnt - s->Freq, s->Freq); + Ppmd_See_Update(see); + p->FoundState = s; + symbol = s->Symbol; + Ppmd7_Update2(p); + return symbol; + } + if (count >= freqSum) + return -2; + rc->Decode(rc, hiCnt, freqSum - hiCnt); + see->Summ = (UInt16)(see->Summ + freqSum); + do { MASK(ps[--i]->Symbol) = 0; } while (i != 0); + } +} diff --git a/mp/src/utils/lzma/C/Ppmd7Enc.c b/mp/src/utils/lzma/C/Ppmd7Enc.c new file mode 100644 index 00000000..51c19c9f --- /dev/null +++ b/mp/src/utils/lzma/C/Ppmd7Enc.c @@ -0,0 +1,187 @@ +/* Ppmd7Enc.c -- PPMdH Encoder +2010-03-12 : Igor Pavlov : Public domain +This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ + +#include "Precomp.h" + +#include "Ppmd7.h" + +#define kTopValue (1 << 24) + +void Ppmd7z_RangeEnc_Init(CPpmd7z_RangeEnc *p) +{ + p->Low = 0; + p->Range = 0xFFFFFFFF; + p->Cache = 0; + p->CacheSize = 1; +} + +static void RangeEnc_ShiftLow(CPpmd7z_RangeEnc *p) +{ + if ((UInt32)p->Low < (UInt32)0xFF000000 || (unsigned)(p->Low >> 32) != 0) + { + Byte temp = p->Cache; + do + { + p->Stream->Write(p->Stream, (Byte)(temp + (Byte)(p->Low >> 32))); + temp = 0xFF; + } + while(--p->CacheSize != 0); + p->Cache = (Byte)((UInt32)p->Low >> 24); + } + p->CacheSize++; + p->Low = (UInt32)p->Low << 8; +} + +static void RangeEnc_Encode(CPpmd7z_RangeEnc *p, UInt32 start, UInt32 size, UInt32 total) +{ + p->Low += start * (p->Range /= total); + p->Range *= size; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_0(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + p->Range = (p->Range >> 14) * size0; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +static void RangeEnc_EncodeBit_1(CPpmd7z_RangeEnc *p, UInt32 size0) +{ + UInt32 newBound = (p->Range >> 14) * size0; + p->Low += newBound; + p->Range -= newBound; + while (p->Range < kTopValue) + { + p->Range <<= 8; + RangeEnc_ShiftLow(p); + } +} + +void Ppmd7z_RangeEnc_FlushData(CPpmd7z_RangeEnc *p) +{ + unsigned i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + + +#define MASK(sym) ((signed char *)charMask)[sym] + +void Ppmd7_EncodeSymbol(CPpmd7 *p, CPpmd7z_RangeEnc *rc, int symbol) +{ + size_t charMask[256 / sizeof(size_t)]; + if (p->MinContext->NumStats != 1) + { + CPpmd_State *s = Ppmd7_GetStats(p, p->MinContext); + UInt32 sum; + unsigned i; + if (s->Symbol == symbol) + { + RangeEnc_Encode(rc, 0, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1_0(p); + return; + } + p->PrevSuccess = 0; + sum = s->Freq; + i = p->MinContext->NumStats - 1; + do + { + if ((++s)->Symbol == symbol) + { + RangeEnc_Encode(rc, sum, s->Freq, p->MinContext->SummFreq); + p->FoundState = s; + Ppmd7_Update1(p); + return; + } + sum += s->Freq; + } + while (--i); + + p->HiBitsFlag = p->HB2Flag[p->FoundState->Symbol]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + i = p->MinContext->NumStats - 1; + do { MASK((--s)->Symbol) = 0; } while (--i); + RangeEnc_Encode(rc, sum, p->MinContext->SummFreq - sum, p->MinContext->SummFreq); + } + else + { + UInt16 *prob = Ppmd7_GetBinSumm(p); + CPpmd_State *s = Ppmd7Context_OneState(p->MinContext); + if (s->Symbol == symbol) + { + RangeEnc_EncodeBit_0(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_0(*prob); + p->FoundState = s; + Ppmd7_UpdateBin(p); + return; + } + else + { + RangeEnc_EncodeBit_1(rc, *prob); + *prob = (UInt16)PPMD_UPDATE_PROB_1(*prob); + p->InitEsc = PPMD7_kExpEscape[*prob >> 10]; + PPMD_SetAllBitsIn256Bytes(charMask); + MASK(s->Symbol) = 0; + p->PrevSuccess = 0; + } + } + for (;;) + { + UInt32 escFreq; + CPpmd_See *see; + CPpmd_State *s; + UInt32 sum; + unsigned i, numMasked = p->MinContext->NumStats; + do + { + p->OrderFall++; + if (!p->MinContext->Suffix) + return; /* EndMarker (symbol = -1) */ + p->MinContext = Ppmd7_GetContext(p, p->MinContext->Suffix); + } + while (p->MinContext->NumStats == numMasked); + + see = Ppmd7_MakeEscFreq(p, numMasked, &escFreq); + s = Ppmd7_GetStats(p, p->MinContext); + sum = 0; + i = p->MinContext->NumStats; + do + { + int cur = s->Symbol; + if (cur == symbol) + { + UInt32 low = sum; + CPpmd_State *s1 = s; + do + { + sum += (s->Freq & (int)(MASK(s->Symbol))); + s++; + } + while (--i); + RangeEnc_Encode(rc, low, s1->Freq, sum + escFreq); + Ppmd_See_Update(see); + p->FoundState = s1; + Ppmd7_Update2(p); + return; + } + sum += (s->Freq & (int)(MASK(cur))); + MASK(cur) = 0; + s++; + } + while (--i); + + RangeEnc_Encode(rc, sum, escFreq, sum + escFreq); + see->Summ = (UInt16)(see->Summ + sum + escFreq); + } +} diff --git a/mp/src/utils/lzma/C/Precomp.h b/mp/src/utils/lzma/C/Precomp.h new file mode 100644 index 00000000..e8ff8b40 --- /dev/null +++ b/mp/src/utils/lzma/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/mp/src/utils/lzma/C/RotateDefs.h b/mp/src/utils/lzma/C/RotateDefs.h new file mode 100644 index 00000000..1b83e5ea --- /dev/null +++ b/mp/src/utils/lzma/C/RotateDefs.h @@ -0,0 +1,26 @@ +/* RotateDefs.h -- Rotate functions +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include + +// #if (_MSC_VER >= 1200) +#pragma intrinsic(_rotl) +#pragma intrinsic(_rotr) +// #endif + +#define rotlFixed(x, n) _rotl((x), (n)) +#define rotrFixed(x, n) _rotr((x), (n)) + +#else + +#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n)))) + +#endif + +#endif diff --git a/mp/src/utils/lzma/C/Sha256.c b/mp/src/utils/lzma/C/Sha256.c new file mode 100644 index 00000000..db0c7061 --- /dev/null +++ b/mp/src/utils/lzma/C/Sha256.c @@ -0,0 +1,206 @@ +/* Crypto/Sha256.c -- SHA-256 Hash +2010-06-11 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "Precomp.h" + +#include "RotateDefs.h" +#include "Sha256.h" + +/* define it for speed optimization */ +/* #define _SHA256_UNROLL */ +/* #define _SHA256_UNROLL2 */ + +void Sha256_Init(CSha256 *p) +{ + p->state[0] = 0x6a09e667; + p->state[1] = 0xbb67ae85; + p->state[2] = 0x3c6ef372; + p->state[3] = 0xa54ff53a; + p->state[4] = 0x510e527f; + p->state[5] = 0x9b05688c; + p->state[6] = 0x1f83d9ab; + p->state[7] = 0x5be0cd19; + p->count = 0; +} + +#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22)) +#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25)) +#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3)) +#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10)) + +#define blk0(i) (W[i] = data[i]) +#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#define a(i) T[(0-(i))&7] +#define b(i) T[(1-(i))&7] +#define c(i) T[(2-(i))&7] +#define d(i) T[(3-(i))&7] +#define e(i) T[(4-(i))&7] +#define f(i) T[(5-(i))&7] +#define g(i) T[(6-(i))&7] +#define h(i) T[(7-(i))&7] + + +#ifdef _SHA256_UNROLL2 + +#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\ + d += h; h += S0(a) + Maj(a, b, c) + +#define RX_8(i) \ + R(a,b,c,d,e,f,g,h, i); \ + R(h,a,b,c,d,e,f,g, i+1); \ + R(g,h,a,b,c,d,e,f, i+2); \ + R(f,g,h,a,b,c,d,e, i+3); \ + R(e,f,g,h,a,b,c,d, i+4); \ + R(d,e,f,g,h,a,b,c, i+5); \ + R(c,d,e,f,g,h,a,b, i+6); \ + R(b,c,d,e,f,g,h,a, i+7) + +#else + +#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ + d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) + +#ifdef _SHA256_UNROLL + +#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); + +#endif + +#endif + +static const UInt32 K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void Sha256_Transform(UInt32 *state, const UInt32 *data) +{ + UInt32 W[16]; + unsigned j; + #ifdef _SHA256_UNROLL2 + UInt32 a,b,c,d,e,f,g,h; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + #else + UInt32 T[8]; + for (j = 0; j < 8; j++) + T[j] = state[j]; + #endif + + for (j = 0; j < 64; j += 16) + { + #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) + RX_8(0); RX_8(8); + #else + unsigned i; + for (i = 0; i < 16; i++) { R(i); } + #endif + } + + #ifdef _SHA256_UNROLL2 + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + #else + for (j = 0; j < 8; j++) + state[j] += T[j]; + #endif + + /* Wipe variables */ + /* memset(W, 0, sizeof(W)); */ + /* memset(T, 0, sizeof(T)); */ +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 + +static void Sha256_WriteByteBlock(CSha256 *p) +{ + UInt32 data32[16]; + unsigned i; + for (i = 0; i < 16; i++) + data32[i] = + ((UInt32)(p->buffer[i * 4 ]) << 24) + + ((UInt32)(p->buffer[i * 4 + 1]) << 16) + + ((UInt32)(p->buffer[i * 4 + 2]) << 8) + + ((UInt32)(p->buffer[i * 4 + 3])); + Sha256_Transform(p->state, data32); +} + +void Sha256_Update(CSha256 *p, const Byte *data, size_t size) +{ + UInt32 curBufferPos = (UInt32)p->count & 0x3F; + while (size > 0) + { + p->buffer[curBufferPos++] = *data++; + p->count++; + size--; + if (curBufferPos == 64) + { + curBufferPos = 0; + Sha256_WriteByteBlock(p); + } + } +} + +void Sha256_Final(CSha256 *p, Byte *digest) +{ + UInt64 lenInBits = (p->count << 3); + UInt32 curBufferPos = (UInt32)p->count & 0x3F; + unsigned i; + p->buffer[curBufferPos++] = 0x80; + while (curBufferPos != (64 - 8)) + { + curBufferPos &= 0x3F; + if (curBufferPos == 0) + Sha256_WriteByteBlock(p); + p->buffer[curBufferPos++] = 0; + } + for (i = 0; i < 8; i++) + { + p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56); + lenInBits <<= 8; + } + Sha256_WriteByteBlock(p); + + for (i = 0; i < 8; i++) + { + *digest++ = (Byte)(p->state[i] >> 24); + *digest++ = (Byte)(p->state[i] >> 16); + *digest++ = (Byte)(p->state[i] >> 8); + *digest++ = (Byte)(p->state[i]); + } + Sha256_Init(p); +} diff --git a/mp/src/utils/lzma/C/Sha256.h b/mp/src/utils/lzma/C/Sha256.h new file mode 100644 index 00000000..3f455dbc --- /dev/null +++ b/mp/src/utils/lzma/C/Sha256.h @@ -0,0 +1,26 @@ +/* Sha256.h -- SHA-256 Hash +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __CRYPTO_SHA256_H +#define __CRYPTO_SHA256_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define SHA256_DIGEST_SIZE 32 + +typedef struct +{ + UInt32 state[8]; + UInt64 count; + Byte buffer[64]; +} CSha256; + +void Sha256_Init(CSha256 *p); +void Sha256_Update(CSha256 *p, const Byte *data, size_t size); +void Sha256_Final(CSha256 *p, Byte *digest); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Sort.c b/mp/src/utils/lzma/C/Sort.c new file mode 100644 index 00000000..e1097e38 --- /dev/null +++ b/mp/src/utils/lzma/C/Sort.c @@ -0,0 +1,141 @@ +/* Sort.c -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Sort.h" + +#define HeapSortDown(p, k, size, temp) \ + { for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && p[s + 1] > p[s]) s++; \ + if (temp >= p[s]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSort(UInt32 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt32 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt32 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +void HeapSort64(UInt64 *p, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt64 temp = p[i]; + size_t k = i; + HeapSortDown(p, k, size, temp) + } + while (--i != 0); + } + /* + do + { + size_t k = 1; + UInt64 temp = p[size]; + p[size--] = p[1]; + HeapSortDown(p, k, size, temp) + } + while (size > 1); + */ + while (size > 3) + { + UInt64 temp = p[size]; + size_t k = (p[3] > p[2]) ? 3 : 2; + p[size--] = p[1]; + p[1] = p[k]; + HeapSortDown(p, k, size, temp) + } + { + UInt64 temp = p[size]; + p[size] = p[1]; + if (size > 2 && p[2] < temp) + { + p[1] = p[2]; + p[2] = temp; + } + else + p[1] = temp; + } +} + +/* +#define HeapSortRefDown(p, vals, n, size, temp) \ + { size_t k = n; UInt32 val = vals[temp]; for (;;) { \ + size_t s = (k << 1); \ + if (s > size) break; \ + if (s < size && vals[p[s + 1]] > vals[p[s]]) s++; \ + if (val >= vals[p[s]]) break; \ + p[k] = p[s]; k = s; \ + } p[k] = temp; } + +void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size) +{ + if (size <= 1) + return; + p--; + { + size_t i = size / 2; + do + { + UInt32 temp = p[i]; + HeapSortRefDown(p, vals, i, size, temp); + } + while (--i != 0); + } + do + { + UInt32 temp = p[size]; + p[size--] = p[1]; + HeapSortRefDown(p, vals, 1, size, temp); + } + while (size > 1); +} +*/ diff --git a/mp/src/utils/lzma/C/Sort.h b/mp/src/utils/lzma/C/Sort.h new file mode 100644 index 00000000..2e2963a2 --- /dev/null +++ b/mp/src/utils/lzma/C/Sort.h @@ -0,0 +1,18 @@ +/* Sort.h -- Sort functions +2014-04-05 : Igor Pavlov : Public domain */ + +#ifndef __7Z_SORT_H +#define __7Z_SORT_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void HeapSort(UInt32 *p, size_t size); +void HeapSort64(UInt64 *p, size_t size); + +/* void HeapSortRef(UInt32 *p, UInt32 *vals, size_t size); */ + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Threads.c b/mp/src/utils/lzma/C/Threads.c new file mode 100644 index 00000000..d71e13a4 --- /dev/null +++ b/mp/src/utils/lzma/C/Threads.c @@ -0,0 +1,93 @@ +/* Threads.c -- multithreading library +2013-11-12 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef _WIN32_WCE +#include +#endif + +#include "Threads.h" + +static WRes GetError() +{ + DWORD res = GetLastError(); + return (res) ? (WRes)(res) : 1; +} + +WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); } +WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } + +WRes HandlePtr_Close(HANDLE *p) +{ + if (*p != NULL) + if (!CloseHandle(*p)) + return GetError(); + *p = NULL; + return 0; +} + +WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(*p); +} + +WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) +{ + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); +} + +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); +} + +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } + +WRes CriticalSection_Init(CCriticalSection *p) +{ + /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + #ifdef _MSC_VER + __try + #endif + { + InitializeCriticalSection(p); + /* InitializeCriticalSectionAndSpinCount(p, 0); */ + } + #ifdef _MSC_VER + __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + #endif + return 0; +} diff --git a/mp/src/utils/lzma/C/Threads.h b/mp/src/utils/lzma/C/Threads.h new file mode 100644 index 00000000..9b3e1c55 --- /dev/null +++ b/mp/src/utils/lzma/C/Threads.h @@ -0,0 +1,67 @@ +/* Threads.h -- multithreading library +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#ifdef _WIN32 +#include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +typedef HANDLE CThread; +#define Thread_Construct(p) *(p) = NULL +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +typedef +#ifdef UNDER_CE + DWORD +#else + unsigned +#endif + THREAD_FUNC_RET_TYPE; + +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); + +typedef HANDLE CEvent; +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); + +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) (*p) = NULL +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +WRes Semaphore_Release1(CSemaphore *p); + +typedef CRITICAL_SECTION CCriticalSection; +WRes CriticalSection_Init(CCriticalSection *p); +#define CriticalSection_Delete(p) DeleteCriticalSection(p) +#define CriticalSection_Enter(p) EnterCriticalSection(p) +#define CriticalSection_Leave(p) LeaveCriticalSection(p) + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/Util/7z/7z.dsp b/mp/src/utils/lzma/C/Util/7z/7z.dsp new file mode 100644 index 00000000..73122f75 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/7z.dsp @@ -0,0 +1,229 @@ +# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=7z - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "7z.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "7z.mak" CFG="7z - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "7z - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "7z - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /FAs /Yu"Precomp.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7zDec.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "7z - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "_SZ_ALLOC_DEBUG2" /D "_SZ_NO_INT_64_A" /D "WIN32" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7zDec.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z - Win32 Release" +# Name "7z - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# ADD CPP /D "_7ZIP_PPMD_SUPPPORT" +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.c +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7.h +# End Source File +# Begin Source File + +SOURCE=..\..\Ppmd7Dec.c +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compiler.h +# End Source File +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zMain.c +# End Source File +# End Target +# End Project diff --git a/mp/src/utils/lzma/C/Util/7z/7z.dsw b/mp/src/utils/lzma/C/Util/7z/7z.dsw new file mode 100644 index 00000000..23089fb7 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/7z.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "7z"=.\7z.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mp/src/utils/lzma/C/Util/7z/7zMain.c b/mp/src/utils/lzma/C/Util/7z/7zMain.c new file mode 100644 index 00000000..8ba02efd --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/7zMain.c @@ -0,0 +1,546 @@ +/* 7zMain.c - Test application for 7z Decoder +2015-01-02 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zBuf.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" + +#ifndef USE_WINDOWS_FILE +/* for mkdir */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#endif + +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +static int Buf_EnsureSize(CBuf *dest, size_t size) +{ + if (dest->size >= size) + return 1; + Buf_Free(dest, &g_Alloc); + return Buf_Create(dest, size, &g_Alloc); +} + +#ifndef _WIN32 + +static Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +static Bool Utf16_To_Utf8(Byte *dest, size_t *destLen, const UInt16 *src, size_t srcLen) +{ + size_t destPos = 0, srcPos = 0; + for (;;) + { + unsigned numAdds; + UInt32 value; + if (srcPos == srcLen) + { + *destLen = destPos; + return True; + } + value = src[srcPos++]; + if (value < 0x80) + { + if (dest) + dest[destPos] = (char)value; + destPos++; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00 || srcPos == srcLen) + break; + c2 = src[srcPos++]; + if (c2 < 0xDC00 || c2 >= 0xE000) + break; + value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000; + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + if (dest) + dest[destPos] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + destPos++; + do + { + numAdds--; + if (dest) + dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + destPos++; + } + while (numAdds != 0); + } + *destLen = destPos; + return False; +} + +static SRes Utf16_To_Utf8Buf(CBuf *dest, const UInt16 *src, size_t srcLen) +{ + size_t destLen = 0; + Bool res; + Utf16_To_Utf8(NULL, &destLen, src, srcLen); + destLen += 1; + if (!Buf_EnsureSize(dest, destLen)) + return SZ_ERROR_MEM; + res = Utf16_To_Utf8(dest->data, &destLen, src, srcLen); + dest->data[destLen] = 0; + return res ? SZ_OK : SZ_ERROR_FAIL; +} + +#endif + +static SRes Utf16_To_Char(CBuf *buf, const UInt16 *s + #ifdef _WIN32 + , UINT codePage + #endif + ) +{ + unsigned len = 0; + for (len = 0; s[len] != 0; len++); + + #ifdef _WIN32 + { + unsigned size = len * 3 + 100; + if (!Buf_EnsureSize(buf, size)) + return SZ_ERROR_MEM; + { + buf->data[0] = 0; + if (len != 0) + { + char defaultChar = '_'; + BOOL defUsed; + unsigned numChars = 0; + numChars = WideCharToMultiByte(codePage, 0, s, len, (char *)buf->data, size, &defaultChar, &defUsed); + if (numChars == 0 || numChars >= size) + return SZ_ERROR_FAIL; + buf->data[numChars] = 0; + } + return SZ_OK; + } + } + #else + return Utf16_To_Utf8Buf(buf, s, len); + #endif +} + +#ifdef _WIN32 + #ifndef USE_WINDOWS_FILE + static UINT g_FileCodePage = CP_ACP; + #endif + #define MY_FILE_CODE_PAGE_PARAM ,g_FileCodePage +#else + #define MY_FILE_CODE_PAGE_PARAM +#endif + +static WRes MyCreateDir(const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); + + #else + + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + + res = + #ifdef _WIN32 + _mkdir((const char *)buf.data) + #else + mkdir((const char *)buf.data, 0777) + #endif + == 0 ? 0 : errno; + Buf_Free(&buf, &g_Alloc); + return res; + + #endif +} + +static WRes OutFile_OpenUtf16(CSzFile *p, const UInt16 *name) +{ + #ifdef USE_WINDOWS_FILE + return OutFile_OpenW(p, name); + #else + CBuf buf; + WRes res; + Buf_Init(&buf); + RINOK(Utf16_To_Char(&buf, name MY_FILE_CODE_PAGE_PARAM)); + res = OutFile_Open(p, (const char *)buf.data); + Buf_Free(&buf, &g_Alloc); + return res; + #endif +} + +static SRes PrintString(const UInt16 *s) +{ + CBuf buf; + SRes res; + Buf_Init(&buf); + res = Utf16_To_Char(&buf, s + #ifdef _WIN32 + , CP_OEMCP + #endif + ); + if (res == SZ_OK) + fputs((const char *)buf.data, stdout); + Buf_Free(&buf, &g_Alloc); + return res; +} + +static void UInt64ToStr(UInt64 value, char *s) +{ + char temp[32]; + int pos = 0; + do + { + temp[pos++] = (char)('0' + (unsigned)(value % 10)); + value /= 10; + } + while (value != 0); + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; +} + +static char *UIntToStr(char *s, unsigned value, int numDigits) +{ + char temp[16]; + int pos = 0; + do + temp[pos++] = (char)('0' + (value % 10)); + while (value /= 10); + for (numDigits -= pos; numDigits > 0; numDigits--) + *s++ = '0'; + do + *s++ = temp[--pos]; + while (pos); + *s = '\0'; + return s; +} + +static void UIntToStr_2(char *s, unsigned value) +{ + s[0] = (char)('0' + (value / 10)); + s[1] = (char)('0' + (value % 10)); +} + +#define PERIOD_4 (4 * 365 + 1) +#define PERIOD_100 (PERIOD_4 * 25 - 1) +#define PERIOD_400 (PERIOD_100 * 4 + 1) + +static void ConvertFileTimeToString(const CNtfsFileTime *nt, char *s) +{ + unsigned year, mon, hour, min, sec; + Byte ms[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + unsigned t; + UInt32 v; + UInt64 v64 = nt->Low | ((UInt64)nt->High << 32); + v64 /= 10000000; + sec = (unsigned)(v64 % 60); v64 /= 60; + min = (unsigned)(v64 % 60); v64 /= 60; + hour = (unsigned)(v64 % 24); v64 /= 24; + + v = (UInt32)v64; + + year = (unsigned)(1601 + v / PERIOD_400 * 400); + v %= PERIOD_400; + + t = v / PERIOD_100; if (t == 4) t = 3; year += t * 100; v -= t * PERIOD_100; + t = v / PERIOD_4; if (t == 25) t = 24; year += t * 4; v -= t * PERIOD_4; + t = v / 365; if (t == 4) t = 3; year += t; v -= t * 365; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + ms[1] = 29; + for (mon = 0;; mon++) + { + unsigned s = ms[mon]; + if (v < s) + break; + v -= s; + } + s = UIntToStr(s, year, 4); *s++ = '-'; + UIntToStr_2(s, mon + 1); s[2] = '-'; s += 3; + UIntToStr_2(s, (unsigned)v + 1); s[2] = ' '; s += 3; + UIntToStr_2(s, hour); s[2] = ':'; s += 3; + UIntToStr_2(s, min); s[2] = ':'; s += 3; + UIntToStr_2(s, sec); s[2] = 0; +} + +void PrintError(const char *sz) +{ + printf("\nERROR: %s\n", sz); +} + +#ifdef USE_WINDOWS_FILE +static void GetAttribString(UInt32 wa, Bool isDir, char *s) +{ + s[0] = (char)(((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || isDir) ? 'D' : '.'); + s[1] = (char)(((wa & FILE_ATTRIBUTE_READONLY ) != 0) ? 'R': '.'); + s[2] = (char)(((wa & FILE_ATTRIBUTE_HIDDEN ) != 0) ? 'H': '.'); + s[3] = (char)(((wa & FILE_ATTRIBUTE_SYSTEM ) != 0) ? 'S': '.'); + s[4] = (char)(((wa & FILE_ATTRIBUTE_ARCHIVE ) != 0) ? 'A': '.'); + s[5] = '\0'; +} +#else +static void GetAttribString(UInt32, Bool, char *s) +{ + s[0] = '\0'; +} +#endif + +// #define NUM_PARENTS_MAX 128 + +int MY_CDECL main(int numargs, char *args[]) +{ + CFileInStream archiveStream; + CLookToRead lookStream; + CSzArEx db; + SRes res; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + UInt16 *temp = NULL; + size_t tempSize = 0; + // UInt32 parents[NUM_PARENTS_MAX]; + + printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n"); + if (numargs == 1) + { + printf( + "Usage: 7zDec \n\n" + "\n" + " e: Extract files from archive (without using directory names)\n" + " l: List contents of archive\n" + " t: Test integrity of archive\n" + " x: eXtract files with full paths\n"); + return 0; + } + if (numargs < 3) + { + PrintError("incorrect command"); + return 1; + } + + #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE) + g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + #endif + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + #ifdef UNDER_CE + if (InFile_OpenW(&archiveStream.file, L"\test.7z")) + #else + if (InFile_Open(&archiveStream.file, args[2])) + #endif + { + PrintError("can not open input file"); + return 1; + } + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + lookStream.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + + CrcGenerateTable(); + + SzArEx_Init(&db); + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + if (res == SZ_OK) + { + char *command = args[1]; + int listCommand = 0, testCommand = 0, fullPaths = 0; + if (strcmp(command, "l") == 0) listCommand = 1; + else if (strcmp(command, "t") == 0) testCommand = 1; + else if (strcmp(command, "e") == 0) { } + else if (strcmp(command, "x") == 0) { fullPaths = 1; } + else + { + PrintError("incorrect command"); + res = SZ_ERROR_FAIL; + } + + if (res == SZ_OK) + { + UInt32 i; + + /* + if you need cache, use these 3 variables. + if you use external function, you can make these variable as static. + */ + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + // const CSzFileItem *f = db.Files + i; + size_t len; + int isDir = SzArEx_IsDir(&db, i); + if (listCommand == 0 && isDir && !fullPaths) + continue; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + // len = SzArEx_GetFullNameLen(&db, i); + + if (len > tempSize) + { + SzFree(NULL, temp); + tempSize = len; + temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0])); + if (!temp) + { + res = SZ_ERROR_MEM; + break; + } + } + + SzArEx_GetFileNameUtf16(&db, i, temp); + /* + if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp) + { + res = SZ_ERROR_FAIL; + break; + } + */ + + if (listCommand) + { + char attr[8], s[32], t[32]; + UInt64 fileSize; + + GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr); + + fileSize = SzArEx_GetFileSize(&db, i); + UInt64ToStr(fileSize, s); + if (SzBitWithVals_Check(&db.MTime, i)) + ConvertFileTimeToString(&db.MTime.Vals[i], t); + else + { + size_t j; + for (j = 0; j < 19; j++) + t[j] = ' '; + t[j] = '\0'; + } + + printf("%s %s %10s ", t, attr, s); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (isDir) + printf("/"); + printf("\n"); + continue; + } + fputs(testCommand ? + "Testing ": + "Extracting ", + stdout); + res = PrintString(temp); + if (res != SZ_OK) + break; + if (isDir) + printf("/"); + else + { + res = SzArEx_Extract(&db, &lookStream.s, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + if (!testCommand) + { + CSzFile outFile; + size_t processedSize; + size_t j; + UInt16 *name = (UInt16 *)temp; + const UInt16 *destPath = (const UInt16 *)name; + for (j = 0; name[j] != 0; j++) + if (name[j] == '/') + { + if (fullPaths) + { + name[j] = 0; + MyCreateDir(name); + name[j] = CHAR_PATH_SEPARATOR; + } + else + destPath = name + j + 1; + } + + if (isDir) + { + MyCreateDir(destPath); + printf("\n"); + continue; + } + else if (OutFile_OpenUtf16(&outFile, destPath)) + { + PrintError("can not open output file"); + res = SZ_ERROR_FAIL; + break; + } + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + PrintError("can not write output file"); + res = SZ_ERROR_FAIL; + break; + } + if (File_Close(&outFile)) + { + PrintError("can not close output file"); + res = SZ_ERROR_FAIL; + break; + } + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(destPath, db.Attribs.Vals[i]); + #endif + } + printf("\n"); + } + IAlloc_Free(&allocImp, outBuffer); + } + } + SzArEx_Free(&db, &allocImp); + SzFree(NULL, temp); + + File_Close(&archiveStream.file); + if (res == SZ_OK) + { + printf("\nEverything is Ok\n"); + return 0; + } + if (res == SZ_ERROR_UNSUPPORTED) + PrintError("decoder doesn't support this archive"); + else if (res == SZ_ERROR_MEM) + PrintError("can not allocate memory"); + else if (res == SZ_ERROR_CRC) + PrintError("CRC error"); + else + printf("\nERROR #%d\n", res); + return 1; +} diff --git a/mp/src/utils/lzma/C/Util/7z/Precomp.c b/mp/src/utils/lzma/C/Util/7z/Precomp.c new file mode 100644 index 00000000..01605e3c --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/mp/src/utils/lzma/C/Util/7z/Precomp.h b/mp/src/utils/lzma/C/Util/7z/Precomp.h new file mode 100644 index 00000000..588a66f7 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/mp/src/utils/lzma/C/Util/7z/makefile b/mp/src/utils/lzma/C/Util/7z/makefile new file mode 100644 index 00000000..08e6f687 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/makefile @@ -0,0 +1,39 @@ +# MY_STATIC_LINK=1 +CFLAGS = $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT + +PROG = 7zDec.exe + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuf.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zArcIn.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + $O\Ppmd7.obj \ + $O\Ppmd7Dec.obj \ + +7Z_OBJS = \ + $O\7zMain.obj \ + +OBJS = \ + $O\Precomp.obj \ + $(7Z_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(CCOMPL_USE) +$(C_OBJS): ../../$(*B).c + $(CCOMPL_USE) +$O\Precomp.obj: Precomp.c + $(CCOMPL_PCH) diff --git a/mp/src/utils/lzma/C/Util/7z/makefile.gcc b/mp/src/utils/lzma/C/Util/7z/makefile.gcc new file mode 100644 index 00000000..63c59cab --- /dev/null +++ b/mp/src/utils/lzma/C/Util/7z/makefile.gcc @@ -0,0 +1,70 @@ +PROG = 7zDec +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall + +OBJS = 7zMain.o 7zAlloc.o 7zArcIn.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zCrcOpt.o 7zDec.o CpuArch.o LzmaDec.o Lzma2Dec.o Bra.o Bra86.o Bcj2.o Ppmd7.o Ppmd7Dec.o 7zFile.o 7zStream.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +7zMain.o: 7zMain.c + $(CXX) $(CFLAGS) 7zMain.c + +7zAlloc.o: ../../7zAlloc.c + $(CXX) $(CFLAGS) ../../7zAlloc.c + +7zArcIn.o: ../../7zArcIn.c + $(CXX) $(CFLAGS) ../../7zArcIn.c + +7zBuf.o: ../../7zBuf.c + $(CXX) $(CFLAGS) ../../7zBuf.c + +7zBuf2.o: ../../7zBuf2.c + $(CXX) $(CFLAGS) ../../7zBuf2.c + +7zCrc.o: ../../7zCrc.c + $(CXX) $(CFLAGS) ../../7zCrc.c + +7zCrcOpt.o: ../../7zCrc.c + $(CXX) $(CFLAGS) ../../7zCrcOpt.c + +7zDec.o: ../../7zDec.c + $(CXX) $(CFLAGS) -D_7ZIP_PPMD_SUPPPORT ../../7zDec.c + +CpuArch.o: ../../CpuArch.c + $(CXX) $(CFLAGS) ../../CpuArch.c + +LzmaDec.o: ../../LzmaDec.c + $(CXX) $(CFLAGS) ../../LzmaDec.c + +Lzma2Dec.o: ../../Lzma2Dec.c + $(CXX) $(CFLAGS) ../../Lzma2Dec.c + +Bra.o: ../../Bra.c + $(CXX) $(CFLAGS) ../../Bra.c + +Bra86.o: ../../Bra86.c + $(CXX) $(CFLAGS) ../../Bra86.c + +Bcj2.o: ../../Bcj2.c + $(CXX) $(CFLAGS) ../../Bcj2.c + +Ppmd7.o: ../../Ppmd7.c + $(CXX) $(CFLAGS) ../../Ppmd7.c + +Ppmd7Dec.o: ../../Ppmd7Dec.c + $(CXX) $(CFLAGS) ../../Ppmd7Dec.c + +7zFile.o: ../../7zFile.c + $(CXX) $(CFLAGS) ../../7zFile.c + +7zStream.o: ../../7zStream.c + $(CXX) $(CFLAGS) ../../7zStream.c + +clean: + -$(RM) $(PROG) $(OBJS) + diff --git a/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.c b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.c new file mode 100644 index 00000000..4606107e --- /dev/null +++ b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.c @@ -0,0 +1,254 @@ +/* LzmaUtil.c -- Test application for LZMA compression +2014-12-31 : Igor Pavlov : Public domain */ + +#include "../../Precomp.h" + +#include +#include +#include + +#include "../../Alloc.h" +#include "../../7zFile.h" +#include "../../7zVersion.h" +#include "../../LzmaDec.h" +#include "../../LzmaEnc.h" + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; +const char *kDataErrorMessage = "Data error"; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +void PrintHelp(char *buffer) +{ + strcat(buffer, "\nLZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" + "\nUsage: lzma inputFile outputFile\n" + " e: encode file\n" + " d: decode file\n"); +} + +int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); + return 1; +} + +int PrintUserError(char *buffer) +{ + return PrintError(buffer, "Incorrect command"); +} + +#define IN_BUF_SIZE (1 << 16) +#define OUT_BUF_SIZE (1 << 16) + +static SRes Decode2(CLzmaDec *state, ISeqOutStream *outStream, ISeqInStream *inStream, + UInt64 unpackSize) +{ + int thereIsSize = (unpackSize != (UInt64)(Int64)-1); + Byte inBuf[IN_BUF_SIZE]; + Byte outBuf[OUT_BUF_SIZE]; + size_t inPos = 0, inSize = 0, outPos = 0; + LzmaDec_Init(state); + for (;;) + { + if (inPos == inSize) + { + inSize = IN_BUF_SIZE; + RINOK(inStream->Read(inStream, inBuf, &inSize)); + inPos = 0; + } + { + SRes res; + SizeT inProcessed = inSize - inPos; + SizeT outProcessed = OUT_BUF_SIZE - outPos; + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + ELzmaStatus status; + if (thereIsSize && outProcessed > unpackSize) + { + outProcessed = (SizeT)unpackSize; + finishMode = LZMA_FINISH_END; + } + + res = LzmaDec_DecodeToBuf(state, outBuf + outPos, &outProcessed, + inBuf + inPos, &inProcessed, finishMode, &status); + inPos += inProcessed; + outPos += outProcessed; + unpackSize -= outProcessed; + + if (outStream) + if (outStream->Write(outStream, outBuf, outPos) != outPos) + return SZ_ERROR_WRITE; + + outPos = 0; + + if (res != SZ_OK || (thereIsSize && unpackSize == 0)) + return res; + + if (inProcessed == 0 && outProcessed == 0) + { + if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK) + return SZ_ERROR_DATA; + return res; + } + } + } +} + +static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream) +{ + UInt64 unpackSize; + int i; + SRes res = 0; + + CLzmaDec state; + + /* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */ + unsigned char header[LZMA_PROPS_SIZE + 8]; + + /* Read and parse header */ + + RINOK(SeqInStream_Read(inStream, header, sizeof(header))); + + unpackSize = 0; + for (i = 0; i < 8; i++) + unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8); + + LzmaDec_Construct(&state); + RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc)); + res = Decode2(&state, outStream, inStream, unpackSize); + LzmaDec_Free(&state, &g_Alloc); + return res; +} + +static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, char *rs) +{ + CLzmaEncHandle enc; + SRes res; + CLzmaEncProps props; + + rs = rs; + + enc = LzmaEnc_Create(&g_Alloc); + if (enc == 0) + return SZ_ERROR_MEM; + + LzmaEncProps_Init(&props); + res = LzmaEnc_SetProps(enc, &props); + + if (res == SZ_OK) + { + Byte header[LZMA_PROPS_SIZE + 8]; + size_t headerSize = LZMA_PROPS_SIZE; + int i; + + res = LzmaEnc_WriteProperties(enc, header, &headerSize); + for (i = 0; i < 8; i++) + header[headerSize++] = (Byte)(fileSize >> (8 * i)); + if (outStream->Write(outStream, header, headerSize) != headerSize) + res = SZ_ERROR_WRITE; + else + { + if (res == SZ_OK) + res = LzmaEnc_Encode(enc, outStream, inStream, NULL, &g_Alloc, &g_Alloc); + } + } + LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); + return res; +} + +int main2(int numArgs, const char *args[], char *rs) +{ + CFileSeqInStream inStream; + CFileOutStream outStream; + char c; + int res; + int encodeMode; + Bool useOutFile = False; + + FileSeqInStream_CreateVTable(&inStream); + File_Construct(&inStream.file); + + FileOutStream_CreateVTable(&outStream); + File_Construct(&outStream.file); + + if (numArgs == 1) + { + PrintHelp(rs); + return 0; + } + + if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1) + return PrintUserError(rs); + + c = args[1][0]; + encodeMode = (c == 'e' || c == 'E'); + if (!encodeMode && c != 'd' && c != 'D') + return PrintUserError(rs); + + { + size_t t4 = sizeof(UInt32); + size_t t8 = sizeof(UInt64); + if (t4 != 4 || t8 != 8) + return PrintError(rs, "Incorrect UInt32 or UInt64"); + } + + if (InFile_Open(&inStream.file, args[2]) != 0) + return PrintError(rs, "Can not open input file"); + + if (numArgs > 3) + { + useOutFile = True; + if (OutFile_Open(&outStream.file, args[3]) != 0) + return PrintError(rs, "Can not open output file"); + } + else if (encodeMode) + PrintUserError(rs); + + if (encodeMode) + { + UInt64 fileSize; + File_GetLength(&inStream.file, &fileSize); + res = Encode(&outStream.s, &inStream.s, fileSize, rs); + } + else + { + res = Decode(&outStream.s, useOutFile ? &inStream.s : NULL); + } + + if (useOutFile) + File_Close(&outStream.file); + File_Close(&inStream.file); + + if (res != SZ_OK) + { + if (res == SZ_ERROR_MEM) + return PrintError(rs, kCantAllocateMessage); + else if (res == SZ_ERROR_DATA) + return PrintError(rs, kDataErrorMessage); + else if (res == SZ_ERROR_WRITE) + return PrintError(rs, kCantWriteMessage); + else if (res == SZ_ERROR_READ) + return PrintError(rs, kCantReadMessage); + return PrintErrorNumber(rs, res); + } + return 0; +} + +int MY_CDECL main(int numArgs, const char *args[]) +{ + char rs[800] = { 0 }; + int res = main2(numArgs, args, rs); + fputs(rs, stdout); + return res; +} diff --git a/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsp b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsp new file mode 100644 index 00000000..df1f0cb0 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsp @@ -0,0 +1,168 @@ +# Microsoft Developer Studio Project File - Name="LzmaUtil" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=LzmaUtil - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LzmaUtil.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LzmaUtil.mak" CFG="LzmaUtil - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaUtil - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "LzmaUtil - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaUtil - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W4 /WX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\util\7lzma.exe" + +!ELSEIF "$(CFG)" == "LzmaUtil - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W4 /WX /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\util\7lzma.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaUtil - Win32 Release" +# Name "LzmaUtil - Win32 Debug" +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zVersion.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaUtil.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# Begin Source File + +SOURCE=..\..\Types.h +# End Source File +# End Target +# End Project diff --git a/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsw b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsw new file mode 100644 index 00000000..f4354875 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/Lzma/LzmaUtil.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaUtil"=.\LzmaUtil.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mp/src/utils/lzma/C/Util/Lzma/makefile b/mp/src/utils/lzma/C/Util/Lzma/makefile new file mode 100644 index 00000000..3b825f21 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/Lzma/makefile @@ -0,0 +1,28 @@ +# MY_STATIC_LINK=1 +PROG = LZMAc.exe + +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaUtil.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\7zFile.obj \ + $O\7zStream.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + +!include "../../../CPP/Build.mak" + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/mp/src/utils/lzma/C/Util/Lzma/makefile.gcc b/mp/src/utils/lzma/C/Util/Lzma/makefile.gcc new file mode 100644 index 00000000..12a72bb8 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/Lzma/makefile.gcc @@ -0,0 +1,44 @@ +PROG = lzma +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall -D_7ZIP_ST + +OBJS = \ + LzmaUtil.o \ + Alloc.o \ + LzFind.o \ + LzmaDec.o \ + LzmaEnc.o \ + 7zFile.o \ + 7zStream.o \ + + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) $(LIB2) + +LzmaUtil.o: LzmaUtil.c + $(CXX) $(CFLAGS) LzmaUtil.c + +Alloc.o: ../../Alloc.c + $(CXX) $(CFLAGS) ../../Alloc.c + +LzFind.o: ../../LzFind.c + $(CXX) $(CFLAGS) ../../LzFind.c + +LzmaDec.o: ../../LzmaDec.c + $(CXX) $(CFLAGS) ../../LzmaDec.c + +LzmaEnc.o: ../../LzmaEnc.c + $(CXX) $(CFLAGS) ../../LzmaEnc.c + +7zFile.o: ../../7zFile.c + $(CXX) $(CFLAGS) ../../7zFile.c + +7zStream.o: ../../7zStream.c + $(CXX) $(CFLAGS) ../../7zStream.c + +clean: + -$(RM) $(PROG) $(OBJS) diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.def b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.def new file mode 100644 index 00000000..8bc6add9 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.def @@ -0,0 +1,4 @@ +EXPORTS + LzmaCompress + LzmaUncompress + diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsp b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsp new file mode 100644 index 00000000..0d4c981c --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsp @@ -0,0 +1,178 @@ +# Microsoft Developer Studio Project File - Name="LzmaLib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=LzmaLib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "LzmaLib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "LzmaLib.mak" CFG="LzmaLib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "LzmaLib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "LzmaLib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "LzmaLib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gr /MT /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Util\LZMA.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "LzmaLib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LZMALIB_EXPORTS" /D "COMPRESS_MF_MT" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Util\LZMA.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "LzmaLib - Win32 Release" +# Name "LzmaLib - Win32 Debug" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\LzmaLib.def +# End Source File +# Begin Source File + +SOURCE=.\LzmaLibExports.c +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\IStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzFindMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzHash.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaEnc.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaLib.h +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.c +# End Source File +# Begin Source File + +SOURCE=..\..\Threads.h +# End Source File +# End Target +# End Project diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsw b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsw new file mode 100644 index 00000000..f6c55593 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "LzmaLib"=.\LzmaLib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLibExports.c b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLibExports.c new file mode 100644 index 00000000..845545db --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/LzmaLibExports.c @@ -0,0 +1,12 @@ +/* LzmaLibExports.c -- LZMA library DLL Entry point +2008-10-04 : Igor Pavlov : Public domain */ + +#include + +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + hInstance = hInstance; + dwReason = dwReason; + lpReserved = lpReserved; + return TRUE; +} diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/makefile b/mp/src/utils/lzma/C/Util/LzmaLib/makefile new file mode 100644 index 00000000..e0f31147 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/makefile @@ -0,0 +1,34 @@ +MY_STATIC_LINK=1 +SLIB = sLZMA.lib +PROG = LZMA.dll +SLIBPATH = $O\$(SLIB) + +DEF_FILE = LzmaLib.def +CFLAGS = $(CFLAGS) \ + +LIB_OBJS = \ + $O\LzmaLibExports.obj \ + +C_OBJS = \ + $O\Alloc.obj \ + $O\LzFind.obj \ + $O\LzFindMt.obj \ + $O\LzmaDec.obj \ + $O\LzmaEnc.obj \ + $O\LzmaLib.obj \ + $O\Threads.obj \ + +OBJS = \ + $(LIB_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(SLIBPATH): $O $(OBJS) + lib -out:$(SLIBPATH) $(OBJS) $(LIBS) + +$(LIB_OBJS): $(*B).c + $(COMPL_O2) +$(C_OBJS): ../../$(*B).c + $(COMPL_O2) diff --git a/mp/src/utils/lzma/C/Util/LzmaLib/resource.rc b/mp/src/utils/lzma/C/Util/LzmaLib/resource.rc new file mode 100644 index 00000000..674832e0 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/LzmaLib/resource.rc @@ -0,0 +1,3 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_DLL("LZMA library", "LZMA") diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.c b/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.c new file mode 100644 index 00000000..01605e3c --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.c @@ -0,0 +1,4 @@ +/* Precomp.c -- StdAfx +2013-01-21 : Igor Pavlov : Public domain */ + +#include "Precomp.h" diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.h b/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.h new file mode 100644 index 00000000..588a66f7 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-06-16 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "../../Compiler.h" +#include "../../7zTypes.h" + +#endif diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.c b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.c new file mode 100644 index 00000000..570bd70f --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.c @@ -0,0 +1,617 @@ +/* SfxSetup.c - 7z SFX Setup +2014-12-07 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef UNICODE +#define UNICODE +#endif + +#ifndef _UNICODE +#define _UNICODE +#endif + +#ifdef _CONSOLE +#include +#endif + +#include "../../7z.h" +#include "../../7zAlloc.h" +#include "../../7zCrc.h" +#include "../../7zFile.h" +#include "../../CpuArch.h" + +#define k_EXE_ExtIndex 2 + +static const char *kExts[] = +{ + "bat" + , "cmd" + , "exe" + , "inf" + , "msi" + #ifdef UNDER_CE + , "cab" + #endif + , "html" + , "htm" +}; + +static const char *kNames[] = +{ + "setup" + , "install" + , "run" + , "start" +}; + +static unsigned FindExt(const wchar_t *s, unsigned *extLen) +{ + unsigned len = (unsigned)wcslen(s); + unsigned i; + for (i = len; i > 0; i--) + { + if (s[i - 1] == '.') + { + *extLen = len - i; + return i - 1; + } + } + *extLen = 0; + return len; +} + +#define MAKE_CHAR_UPPER(c) ((((c) >= 'a' && (c) <= 'z') ? (c) -= 0x20 : (c))) + +static unsigned FindItem(const char **items, unsigned num, const wchar_t *s, unsigned len) +{ + unsigned i; + for (i = 0; i < num; i++) + { + const char *item = items[i]; + unsigned itemLen = (unsigned)strlen(item); + unsigned j; + if (len != itemLen) + continue; + for (j = 0; j < len; j++) + { + unsigned c = item[j]; + if (c != s[j] && MAKE_CHAR_UPPER(c) != s[j]) + break; + } + if (j == len) + return i; + } + return i; +} + +#ifdef _CONSOLE +static BOOL WINAPI HandlerRoutine(DWORD ctrlType) +{ + ctrlType = ctrlType; + return TRUE; +} +#endif + +static void PrintErrorMessage(const char *message) +{ + #ifdef _CONSOLE + printf("\n7-Zip Error: %s\n", message); + #else + #ifdef UNDER_CE + WCHAR messageW[256 + 4]; + unsigned i; + for (i = 0; i < 256 && message[i] != 0; i++) + messageW[i] = message[i]; + messageW[i] = 0; + MessageBoxW(0, messageW, L"7-Zip Error", MB_ICONERROR); + #else + MessageBoxA(0, message, "7-Zip Error", MB_ICONERROR); + #endif + #endif +} + +static WRes MyCreateDir(const WCHAR *name) +{ + return CreateDirectoryW(name, NULL) ? 0 : GetLastError(); +} + +#ifdef UNDER_CE +#define kBufferSize (1 << 13) +#else +#define kBufferSize (1 << 15) +#endif + +#define kSignatureSearchLimit (1 << 22) + +static Bool FindSignature(CSzFile *stream, UInt64 *resPos) +{ + Byte buf[kBufferSize]; + size_t numPrevBytes = 0; + *resPos = 0; + for (;;) + { + size_t processed, pos; + if (*resPos > kSignatureSearchLimit) + return False; + processed = kBufferSize - numPrevBytes; + if (File_Read(stream, buf + numPrevBytes, &processed) != 0) + return False; + processed += numPrevBytes; + if (processed < k7zStartHeaderSize || + (processed == k7zStartHeaderSize && numPrevBytes != 0)) + return False; + processed -= k7zStartHeaderSize; + for (pos = 0; pos <= processed; pos++) + { + for (; buf[pos] != '7' && pos <= processed; pos++); + if (pos > processed) + break; + if (memcmp(buf + pos, k7zSignature, k7zSignatureSize) == 0) + if (CrcCalc(buf + pos + 12, 20) == GetUi32(buf + pos + 8)) + { + *resPos += pos; + return True; + } + } + *resPos += processed; + numPrevBytes = k7zStartHeaderSize; + memmove(buf, buf + processed, k7zStartHeaderSize); + } +} + +static Bool DoesFileOrDirExist(const WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + handle = FindFirstFileW(path, &fd); + if (handle == INVALID_HANDLE_VALUE) + return False; + FindClose(handle); + return True; +} + +static WRes RemoveDirWithSubItems(WCHAR *path) +{ + WIN32_FIND_DATAW fd; + HANDLE handle; + WRes res = 0; + size_t len = wcslen(path); + wcscpy(path + len, L"*"); + handle = FindFirstFileW(path, &fd); + path[len] = L'\0'; + if (handle == INVALID_HANDLE_VALUE) + return GetLastError(); + for (;;) + { + if (wcscmp(fd.cFileName, L".") != 0 && + wcscmp(fd.cFileName, L"..") != 0) + { + wcscpy(path + len, fd.cFileName); + if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + res = RemoveDirWithSubItems(path); + } + else + { + SetFileAttributesW(path, 0); + if (DeleteFileW(path) == 0) + res = GetLastError(); + } + if (res != 0) + break; + } + if (!FindNextFileW(handle, &fd)) + { + res = GetLastError(); + if (res == ERROR_NO_MORE_FILES) + res = 0; + break; + } + } + path[len] = L'\0'; + FindClose(handle); + if (res == 0) + { + if (!RemoveDirectoryW(path)) + res = GetLastError(); + } + return res; +} + +#ifdef _CONSOLE +int MY_CDECL main() +#else +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + #ifdef UNDER_CE + LPWSTR + #else + LPSTR + #endif + lpCmdLine, int nCmdShow) +#endif +{ + CFileInStream archiveStream; + CLookToRead lookStream; + CSzArEx db; + SRes res = SZ_OK; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + WCHAR sfxPath[MAX_PATH + 2]; + WCHAR path[MAX_PATH * 3 + 2]; + #ifndef UNDER_CE + WCHAR workCurDir[MAX_PATH + 32]; + #endif + size_t pathLen; + DWORD winRes; + const wchar_t *cmdLineParams; + const char *errorMessage = NULL; + Bool useShellExecute = True; + + #ifdef _CONSOLE + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + #else + hInstance = hInstance; + hPrevInstance = hPrevInstance; + lpCmdLine = lpCmdLine; + nCmdShow = nCmdShow; + #endif + + CrcGenerateTable(); + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + FileInStream_CreateVTable(&archiveStream); + LookToRead_CreateVTable(&lookStream, False); + + winRes = GetModuleFileNameW(NULL, sfxPath, MAX_PATH); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + { + cmdLineParams = GetCommandLineW(); + #ifndef UNDER_CE + { + Bool quoteMode = False; + for (;; cmdLineParams++) + { + wchar_t c = *cmdLineParams; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == 0 || (c == L' ' && !quoteMode)) + break; + } + } + #endif + } + + { + unsigned i; + DWORD d; + winRes = GetTempPathW(MAX_PATH, path); + if (winRes == 0 || winRes > MAX_PATH) + return 1; + pathLen = wcslen(path); + d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); + + for (i = 0;; i++, d += GetTickCount()) + { + if (i >= 100) + { + res = SZ_ERROR_FAIL; + break; + } + wcscpy(path + pathLen, L"7z"); + + { + wchar_t *s = path + wcslen(path); + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[7 - k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + } + + if (DoesFileOrDirExist(path)) + continue; + if (CreateDirectoryW(path, NULL)) + { + wcscat(path, WSTRING_PATH_SEPARATOR); + pathLen = wcslen(path); + break; + } + if (GetLastError() != ERROR_ALREADY_EXISTS) + { + res = SZ_ERROR_FAIL; + break; + } + } + + #ifndef UNDER_CE + wcscpy(workCurDir, path); + #endif + if (res != SZ_OK) + errorMessage = "Can't create temp folder"; + } + + if (res != SZ_OK) + { + if (!errorMessage) + errorMessage = "Error"; + PrintErrorMessage(errorMessage); + return 1; + } + + if (InFile_OpenW(&archiveStream.file, sfxPath) != 0) + { + errorMessage = "can not open input file"; + res = SZ_ERROR_FAIL; + } + else + { + UInt64 pos = 0; + if (!FindSignature(&archiveStream.file, &pos)) + res = SZ_ERROR_FAIL; + else if (File_Seek(&archiveStream.file, (Int64 *)&pos, SZ_SEEK_SET) != 0) + res = SZ_ERROR_FAIL; + if (res != 0) + errorMessage = "Can't find 7z archive"; + } + + if (res == SZ_OK) + { + lookStream.realStream = &archiveStream.s; + LookToRead_Init(&lookStream); + } + + SzArEx_Init(&db); + if (res == SZ_OK) + { + res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp); + } + + if (res == SZ_OK) + { + UInt32 executeFileIndex = (UInt32)(Int32)-1; + UInt32 minPrice = 1 << 30; + UInt32 i; + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + for (i = 0; i < db.NumFiles; i++) + { + size_t offset = 0; + size_t outSizeProcessed = 0; + size_t len; + WCHAR *temp; + len = SzArEx_GetFileNameUtf16(&db, i, NULL); + + if (len >= MAX_PATH) + { + res = SZ_ERROR_FAIL; + break; + } + + temp = path + pathLen; + + SzArEx_GetFileNameUtf16(&db, i, temp); + { + res = SzArEx_Extract(&db, &lookStream.s, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + } + { + CSzFile outFile; + size_t processedSize; + size_t j; + size_t nameStartPos = 0; + for (j = 0; temp[j] != 0; j++) + { + if (temp[j] == '/') + { + temp[j] = 0; + MyCreateDir(path); + temp[j] = CHAR_PATH_SEPARATOR; + nameStartPos = j + 1; + } + } + + if (SzArEx_IsDir(&db, i)) + { + MyCreateDir(path); + continue; + } + else + { + unsigned extLen; + const WCHAR *name = temp + nameStartPos; + unsigned len = (unsigned)wcslen(name); + unsigned nameLen = FindExt(temp + nameStartPos, &extLen); + unsigned extPrice = FindItem(kExts, sizeof(kExts) / sizeof(kExts[0]), name + len - extLen, extLen); + unsigned namePrice = FindItem(kNames, sizeof(kNames) / sizeof(kNames[0]), name, nameLen); + + unsigned price = namePrice + extPrice * 64 + (nameStartPos == 0 ? 0 : (1 << 12)); + if (minPrice > price) + { + minPrice = price; + executeFileIndex = i; + useShellExecute = (extPrice != k_EXE_ExtIndex); + } + + if (DoesFileOrDirExist(path)) + { + errorMessage = "Duplicate file"; + res = SZ_ERROR_FAIL; + break; + } + if (OutFile_OpenW(&outFile, path)) + { + errorMessage = "Can't open output file"; + res = SZ_ERROR_FAIL; + break; + } + } + + processedSize = outSizeProcessed; + if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed) + { + errorMessage = "Can't write output file"; + res = SZ_ERROR_FAIL; + } + + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.MTime, i)) + { + const CNtfsFileTime *t = db.MTime.Vals + i; + FILETIME mTime; + mTime.dwLowDateTime = t->Low; + mTime.dwHighDateTime = t->High; + SetFileTime(outFile.handle, NULL, NULL, &mTime); + } + #endif + + { + SRes res2 = File_Close(&outFile); + if (res != SZ_OK) + break; + if (res2 != SZ_OK) + { + res = res2; + break; + } + } + #ifdef USE_WINDOWS_FILE + if (SzBitWithVals_Check(&db.Attribs, i)) + SetFileAttributesW(path, db.Attribs.Vals[i]); + #endif + } + } + + if (res == SZ_OK) + { + if (executeFileIndex == (UInt32)(Int32)-1) + { + errorMessage = "There is no file to execute"; + res = SZ_ERROR_FAIL; + } + else + { + WCHAR *temp = path + pathLen; + UInt32 j; + SzArEx_GetFileNameUtf16(&db, executeFileIndex, temp); + for (j = 0; temp[j] != 0; j++) + if (temp[j] == '/') + temp[j] = CHAR_PATH_SEPARATOR; + } + } + IAlloc_Free(&allocImp, outBuffer); + } + SzArEx_Free(&db, &allocImp); + + File_Close(&archiveStream.file); + + if (res == SZ_OK) + { + HANDLE hProcess = 0; + + #ifndef UNDER_CE + WCHAR oldCurDir[MAX_PATH + 2]; + oldCurDir[0] = 0; + { + DWORD needLen = GetCurrentDirectory(MAX_PATH + 1, oldCurDir); + if (needLen == 0 || needLen > MAX_PATH) + oldCurDir[0] = 0; + SetCurrentDirectory(workCurDir); + } + #endif + + if (useShellExecute) + { + SHELLEXECUTEINFO ei; + UINT32 executeRes; + BOOL success; + + memset(&ei, 0, sizeof(ei)); + ei.cbSize = sizeof(ei); + ei.lpFile = path; + ei.fMask = SEE_MASK_NOCLOSEPROCESS + #ifndef UNDER_CE + | SEE_MASK_FLAG_DDEWAIT + #endif + /* | SEE_MASK_NO_CONSOLE */ + ; + if (wcslen(cmdLineParams) != 0) + ei.lpParameters = cmdLineParams; + ei.nShow = SW_SHOWNORMAL; /* SW_HIDE; */ + success = ShellExecuteEx(&ei); + executeRes = (UINT32)(UINT_PTR)ei.hInstApp; + if (!success || (executeRes <= 32 && executeRes != 0)) /* executeRes = 0 in Windows CE */ + res = SZ_ERROR_FAIL; + else + hProcess = ei.hProcess; + } + else + { + STARTUPINFOW si; + PROCESS_INFORMATION pi; + WCHAR cmdLine[MAX_PATH * 3]; + + wcscpy(cmdLine, path); + wcscat(cmdLine, cmdLineParams); + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + if (CreateProcessW(NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) == 0) + res = SZ_ERROR_FAIL; + else + { + CloseHandle(pi.hThread); + hProcess = pi.hProcess; + } + } + + if (hProcess != 0) + { + WaitForSingleObject(hProcess, INFINITE); + CloseHandle(hProcess); + } + + #ifndef UNDER_CE + SetCurrentDirectory(oldCurDir); + #endif + } + + path[pathLen] = L'\0'; + RemoveDirWithSubItems(path); + + if (res == SZ_OK) + return 0; + + { + if (res == SZ_ERROR_UNSUPPORTED) + errorMessage = "Decoder doesn't support this archive"; + else if (res == SZ_ERROR_MEM) + errorMessage = "Can't allocate required memory"; + else if (res == SZ_ERROR_CRC) + errorMessage = "CRC error"; + else + { + if (!errorMessage) + errorMessage = "ERROR"; + } + if (errorMessage) + PrintErrorMessage(errorMessage); + } + return 1; +} diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsp b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsp new file mode 100644 index 00000000..1d5fdd8a --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsp @@ -0,0 +1,211 @@ +# Microsoft Developer Studio Project File - Name="SfxSetup" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SfxSetup - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SfxSetup.mak" CFG="SfxSetup - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SfxSetup - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SfxSetup - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SfxSetup - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W4 /WX /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "SfxSetup - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W4 /WX /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Yu"Precomp.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SfxSetup - Win32 Release" +# Name "SfxSetup - Win32 Debug" +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\7z.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zArcIn.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zBuf.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zCrcOpt.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zFile.h +# End Source File +# Begin Source File + +SOURCE=..\..\7zStream.c +# End Source File +# Begin Source File + +SOURCE=..\..\7zTypes.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bcj2.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.c +# End Source File +# Begin Source File + +SOURCE=..\..\Bra.h +# End Source File +# Begin Source File + +SOURCE=..\..\Bra86.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.c +# End Source File +# Begin Source File + +SOURCE=..\..\CpuArch.h +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.c +# End Source File +# Begin Source File + +SOURCE=..\..\Lzma2Dec.h +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.c +# End Source File +# Begin Source File + +SOURCE=..\..\LzmaDec.h +# End Source File +# End Group +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Precomp.c +# ADD CPP /Yc"Precomp.h" +# End Source File +# Begin Source File + +SOURCE=.\Precomp.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SfxSetup.c +# End Source File +# End Target +# End Project diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsw b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsw new file mode 100644 index 00000000..128fcdd3 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/SfxSetup.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SfxSetup"=.\SfxSetup.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/makefile b/mp/src/utils/lzma/C/Util/SfxSetup/makefile new file mode 100644 index 00000000..cc9878af --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/makefile @@ -0,0 +1,33 @@ +PROG = 7zS2.sfx + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/makefile_con b/mp/src/utils/lzma/C/Util/SfxSetup/makefile_con new file mode 100644 index 00000000..f8bbb1fd --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/makefile_con @@ -0,0 +1,34 @@ +PROG = 7zS2con.sfx +CFLAGS = $(CFLAGS) -D_CONSOLE + +C_OBJS = \ + $O\7zAlloc.obj \ + $O\7zArcIn.obj \ + $O\7zBuf.obj \ + $O\7zBuf2.obj \ + $O\7zCrc.obj \ + $O\7zCrcOpt.obj \ + $O\7zFile.obj \ + $O\7zDec.obj \ + $O\7zStream.obj \ + $O\Bcj2.obj \ + $O\Bra.obj \ + $O\Bra86.obj \ + $O\CpuArch.obj \ + $O\Lzma2Dec.obj \ + $O\LzmaDec.obj \ + +7Z_OBJS = \ + $O\SfxSetup.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $(C_OBJS) \ + $O\resource.res + +!include "../../../CPP/Build.mak" + +$(7Z_OBJS): $(*B).c + $(COMPL_O1) +$(C_OBJS): ../../$(*B).c + $(COMPL_O1) diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/resource.rc b/mp/src/utils/lzma/C/Util/SfxSetup/resource.rc new file mode 100644 index 00000000..0c1637f2 --- /dev/null +++ b/mp/src/utils/lzma/C/Util/SfxSetup/resource.rc @@ -0,0 +1,5 @@ +#include "../../7zVersion.rc" + +MY_VERSION_INFO_APP("7z Setup SFX small", "7zS2.sfx") + +1 ICON "setup.ico" diff --git a/mp/src/utils/lzma/C/Util/SfxSetup/setup.ico b/mp/src/utils/lzma/C/Util/SfxSetup/setup.ico new file mode 100644 index 00000000..dbb6ca8b Binary files /dev/null and b/mp/src/utils/lzma/C/Util/SfxSetup/setup.ico differ diff --git a/mp/src/utils/lzma/C/Xz.c b/mp/src/utils/lzma/C/Xz.c new file mode 100644 index 00000000..fbc732a8 --- /dev/null +++ b/mp/src/utils/lzma/C/Xz.c @@ -0,0 +1,90 @@ +/* Xz.c - Xz +2009-04-15 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" +#include "XzCrc64.h" + +Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 }; +Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' }; + +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v) +{ + unsigned i = 0; + do + { + buf[i++] = (Byte)((v & 0x7F) | 0x80); + v >>= 7; + } + while (v != 0); + buf[i - 1] &= 0x7F; + return i; +} + +void Xz_Construct(CXzStream *p) +{ + p->numBlocks = p->numBlocksAllocated = 0; + p->blocks = 0; + p->flags = 0; +} + +void Xz_Free(CXzStream *p, ISzAlloc *alloc) +{ + alloc->Free(alloc, p->blocks); + p->numBlocks = p->numBlocksAllocated = 0; + p->blocks = 0; +} + +unsigned XzFlags_GetCheckSize(CXzStreamFlags f) +{ + int t = XzFlags_GetCheckType(f); + return (t == 0) ? 0 : (4 << ((t - 1) / 3)); +} + +void XzCheck_Init(CXzCheck *p, int mode) +{ + p->mode = mode; + switch (mode) + { + case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break; + case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break; + case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break; + } +} + +void XzCheck_Update(CXzCheck *p, const void *data, size_t size) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break; + case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break; + case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break; + } +} + +int XzCheck_Final(CXzCheck *p, Byte *digest) +{ + switch (p->mode) + { + case XZ_CHECK_CRC32: + SetUi32(digest, CRC_GET_DIGEST(p->crc)); + break; + case XZ_CHECK_CRC64: + { + int i; + UInt64 v = CRC64_GET_DIGEST(p->crc64); + for (i = 0; i < 8; i++, v >>= 8) + digest[i] = (Byte)(v & 0xFF); + break; + } + case XZ_CHECK_SHA256: + Sha256_Final(&p->sha, digest); + break; + default: + return 0; + } + return 1; +} diff --git a/mp/src/utils/lzma/C/Xz.h b/mp/src/utils/lzma/C/Xz.h new file mode 100644 index 00000000..7e6fc564 --- /dev/null +++ b/mp/src/utils/lzma/C/Xz.h @@ -0,0 +1,275 @@ +/* Xz.h - Xz interface +2014-12-30 : Igor Pavlov : Public domain */ + +#ifndef __XZ_H +#define __XZ_H + +#include "Sha256.h" + +EXTERN_C_BEGIN + +#define XZ_ID_Subblock 1 +#define XZ_ID_Delta 3 +#define XZ_ID_X86 4 +#define XZ_ID_PPC 5 +#define XZ_ID_IA64 6 +#define XZ_ID_ARM 7 +#define XZ_ID_ARMT 8 +#define XZ_ID_SPARC 9 +#define XZ_ID_LZMA2 0x21 + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value); +unsigned Xz_WriteVarInt(Byte *buf, UInt64 v); + +/* ---------- xz block ---------- */ + +#define XZ_BLOCK_HEADER_SIZE_MAX 1024 + +#define XZ_NUM_FILTERS_MAX 4 +#define XZ_BF_NUM_FILTERS_MASK 3 +#define XZ_BF_PACK_SIZE (1 << 6) +#define XZ_BF_UNPACK_SIZE (1 << 7) + +#define XZ_FILTER_PROPS_SIZE_MAX 20 + +typedef struct +{ + UInt64 id; + UInt32 propsSize; + Byte props[XZ_FILTER_PROPS_SIZE_MAX]; +} CXzFilter; + +typedef struct +{ + UInt64 packSize; + UInt64 unpackSize; + Byte flags; + CXzFilter filters[XZ_NUM_FILTERS_MAX]; +} CXzBlock; + +#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1) +#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0) +#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0) + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header); +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes); + +/* ---------- xz stream ---------- */ + +#define XZ_SIG_SIZE 6 +#define XZ_FOOTER_SIG_SIZE 2 + +extern Byte XZ_SIG[XZ_SIG_SIZE]; +extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE]; + +#define XZ_STREAM_FLAGS_SIZE 2 +#define XZ_STREAM_CRC_SIZE 4 + +#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE) +#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4) + +#define XZ_CHECK_MASK 0xF +#define XZ_CHECK_NO 0 +#define XZ_CHECK_CRC32 1 +#define XZ_CHECK_CRC64 4 +#define XZ_CHECK_SHA256 10 + +typedef struct +{ + int mode; + UInt32 crc; + UInt64 crc64; + CSha256 sha; +} CXzCheck; + +void XzCheck_Init(CXzCheck *p, int mode); +void XzCheck_Update(CXzCheck *p, const void *data, size_t size); +int XzCheck_Final(CXzCheck *p, Byte *digest); + +typedef UInt16 CXzStreamFlags; + +#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK) +#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK) +#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32) +unsigned XzFlags_GetCheckSize(CXzStreamFlags f); + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf); +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream); + +typedef struct +{ + UInt64 unpackSize; + UInt64 totalSize; +} CXzBlockSizes; + +typedef struct +{ + CXzStreamFlags flags; + size_t numBlocks; + size_t numBlocksAllocated; + CXzBlockSizes *blocks; + UInt64 startOffset; +} CXzStream; + +void Xz_Construct(CXzStream *p); +void Xz_Free(CXzStream *p, ISzAlloc *alloc); + +#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1) + +UInt64 Xz_GetUnpackSize(const CXzStream *p); +UInt64 Xz_GetPackSize(const CXzStream *p); + +typedef struct +{ + size_t num; + size_t numAllocated; + CXzStream *streams; +} CXzs; + +void Xzs_Construct(CXzs *p); +void Xzs_Free(CXzs *p, ISzAlloc *alloc); +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc); + +UInt64 Xzs_GetNumBlocks(const CXzs *p); +UInt64 Xzs_GetUnpackSize(const CXzs *p); + +typedef enum +{ + CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */ + CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + CODER_STATUS_NOT_FINISHED, /* stream was not finished */ + CODER_STATUS_NEEDS_MORE_INPUT /* you must provide more input bytes */ +} ECoderStatus; + +typedef enum +{ + CODER_FINISH_ANY, /* finish at any point */ + CODER_FINISH_END /* block must be finished at the end */ +} ECoderFinishMode; + +typedef struct _IStateCoder +{ + void *p; + void (*Free)(void *p, ISzAlloc *alloc); + SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc); + void (*Init)(void *p); + SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished); +} IStateCoder; + +#define MIXCODER_NUM_FILTERS_MAX 4 + +typedef struct +{ + ISzAlloc *alloc; + Byte *buf; + int numCoders; + int finished[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t pos[MIXCODER_NUM_FILTERS_MAX - 1]; + size_t size[MIXCODER_NUM_FILTERS_MAX - 1]; + UInt64 ids[MIXCODER_NUM_FILTERS_MAX]; + IStateCoder coders[MIXCODER_NUM_FILTERS_MAX]; +} CMixCoder; + +void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc); +void MixCoder_Free(CMixCoder *p); +void MixCoder_Init(CMixCoder *p); +SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId); +SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, ECoderStatus *status); + +typedef enum +{ + XZ_STATE_STREAM_HEADER, + XZ_STATE_STREAM_INDEX, + XZ_STATE_STREAM_INDEX_CRC, + XZ_STATE_STREAM_FOOTER, + XZ_STATE_STREAM_PADDING, + XZ_STATE_BLOCK_HEADER, + XZ_STATE_BLOCK, + XZ_STATE_BLOCK_FOOTER +} EXzState; + +typedef struct +{ + EXzState state; + UInt32 pos; + unsigned alignPos; + unsigned indexPreSize; + + CXzStreamFlags streamFlags; + + UInt32 blockHeaderSize; + UInt64 packSize; + UInt64 unpackSize; + + UInt64 numBlocks; + UInt64 indexSize; + UInt64 indexPos; + UInt64 padSize; + + UInt64 numStartedStreams; + UInt64 numFinishedStreams; + UInt64 numTotalBlocks; + + UInt32 crc; + CMixCoder decoder; + CXzBlock block; + CXzCheck check; + CSha256 sha; + Byte shaDigest[SHA256_DIGEST_SIZE]; + Byte buf[XZ_BLOCK_HEADER_SIZE_MAX]; +} CXzUnpacker; + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc); +void XzUnpacker_Init(CXzUnpacker *p); +void XzUnpacker_Free(CXzUnpacker *p); + +/* +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + CODER_FINISH_ANY - use smallest number of input bytes + CODER_FINISH_END - read EndOfStream marker after decoding + +Returns: + SZ_OK + status: + CODER_STATUS_NOT_FINISHED, + CODER_STATUS_NEEDS_MORE_INPUT - maybe there are more xz streams, + call XzUnpacker_IsStreamWasFinished to check that current stream was finished + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_DATA - Data error + SZ_ERROR_UNSUPPORTED - Unsupported method or method properties + SZ_ERROR_CRC - CRC error + // SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). + + SZ_ERROR_NO_ARCHIVE - the error with xz Stream Header with one of the following reasons: + - xz Stream Signature failure + - CRC32 of xz Stream Header is failed + - The size of Stream padding is not multiple of four bytes. + It's possible to get that error, if xz stream was finished and the stream + contains some another data. In that case you can call XzUnpacker_GetExtraSize() + function to get real size of xz stream. +*/ + + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, + ECoderStatus *status); + +Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p); + +/* +Call XzUnpacker_GetExtraSize after XzUnpacker_Code function to detect real size of +xz stream in two cases: +XzUnpacker_Code() returns: + res == SZ_OK && status == CODER_STATUS_NEEDS_MORE_INPUT + res == SZ_ERROR_NO_ARCHIVE +*/ + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/XzCrc64.c b/mp/src/utils/lzma/C/XzCrc64.c new file mode 100644 index 00000000..aa812548 --- /dev/null +++ b/mp/src/utils/lzma/C/XzCrc64.c @@ -0,0 +1,90 @@ +/* XzCrc64.c -- CRC64 calculation +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "XzCrc64.h" +#include "CpuArch.h" + +#define kCrc64Poly UINT64_CONST(0xC96C5795D7870F42) + +#ifdef MY_CPU_LE + #define CRC_NUM_TABLES 4 +#else + #define CRC_NUM_TABLES 5 + #define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +#ifndef MY_CPU_BE + UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table); +#endif + +typedef UInt64 (MY_FAST_CALL *CRC_FUNC)(UInt64 v, const void *data, size_t size, const UInt64 *table); + +static CRC_FUNC g_Crc64Update; +UInt64 g_Crc64Table[256 * CRC_NUM_TABLES]; + +UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size) +{ + return g_Crc64Update(v, data, size, g_Crc64Table); +} + +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size) +{ + return g_Crc64Update(CRC64_INIT_VAL, data, size, g_Crc64Table) ^ CRC64_INIT_VAL; +} + +void MY_FAST_CALL Crc64GenerateTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt64 r = i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrc64Poly & ~((r & 1) - 1)); + g_Crc64Table[i] = r; + } + for (; i < 256 * CRC_NUM_TABLES; i++) + { + UInt64 r = g_Crc64Table[i - 256]; + g_Crc64Table[i] = g_Crc64Table[r & 0xFF] ^ (r >> 8); + } + + #ifdef MY_CPU_LE + + g_Crc64Update = XzCrc64UpdateT4; + + + + + + + #else + { + #ifndef MY_CPU_BE + UInt32 k = 1; + if (*(const Byte *)&k == 1) + g_Crc64Update = XzCrc64UpdateT4; + else + #endif + { + for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--) + { + UInt64 x = g_Crc64Table[i - 256]; + g_Crc64Table[i] = CRC_UINT64_SWAP(x); + } + g_Crc64Update = XzCrc64UpdateT1_BeT4; + } + } + #endif +} diff --git a/mp/src/utils/lzma/C/XzCrc64.h b/mp/src/utils/lzma/C/XzCrc64.h new file mode 100644 index 00000000..08dbc330 --- /dev/null +++ b/mp/src/utils/lzma/C/XzCrc64.h @@ -0,0 +1,26 @@ +/* XzCrc64.h -- CRC64 calculation +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __XZ_CRC64_H +#define __XZ_CRC64_H + +#include + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +extern UInt64 g_Crc64Table[]; + +void MY_FAST_CALL Crc64GenerateTable(void); + +#define CRC64_INIT_VAL UINT64_CONST(0xFFFFFFFFFFFFFFFF) +#define CRC64_GET_DIGEST(crc) ((crc) ^ CRC64_INIT_VAL) +#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size); +UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/XzCrc64Opt.c b/mp/src/utils/lzma/C/XzCrc64Opt.c new file mode 100644 index 00000000..dccae1c1 --- /dev/null +++ b/mp/src/utils/lzma/C/XzCrc64Opt.c @@ -0,0 +1,69 @@ +/* XzCrc64Opt.c -- CRC64 calculation +2011-06-28 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "CpuArch.h" + +#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) + +#ifndef MY_CPU_BE + +UInt64 MY_FAST_CALL XzCrc64UpdateT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)v ^ *(const UInt32 *)p; + v = (v >> 32) ^ + table[0x300 + ((d ) & 0xFF)] ^ + table[0x200 + ((d >> 8) & 0xFF)] ^ + table[0x100 + ((d >> 16) & 0xFF)] ^ + table[0x000 + ((d >> 24))]; + } + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif + + +#ifndef MY_CPU_LE + +#define CRC_UINT64_SWAP(v) \ + ((v >> 56) | \ + ((v >> 40) & ((UInt64)0xFF << 8)) | \ + ((v >> 24) & ((UInt64)0xFF << 16)) | \ + ((v >> 8) & ((UInt64)0xFF << 24)) | \ + ((v << 8) & ((UInt64)0xFF << 32)) | \ + ((v << 24) & ((UInt64)0xFF << 40)) | \ + ((v << 40) & ((UInt64)0xFF << 48)) | \ + (v << 56)) + +UInt64 MY_FAST_CALL XzCrc64UpdateT1_BeT4(UInt64 v, const void *data, size_t size, const UInt64 *table) +{ + const Byte *p = (const Byte *)data; + for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + v = CRC_UINT64_SWAP(v); + table += 0x100; + for (; size >= 4; size -= 4, p += 4) + { + UInt32 d = (UInt32)(v >> 32) ^ *(const UInt32 *)p; + v = (v << 32) ^ + table[0x000 + ((d ) & 0xFF)] ^ + table[0x100 + ((d >> 8) & 0xFF)] ^ + table[0x200 + ((d >> 16) & 0xFF)] ^ + table[0x300 + ((d >> 24))]; + } + table -= 0x100; + v = CRC_UINT64_SWAP(v); + for (; size > 0; size--, p++) + v = CRC_UPDATE_BYTE_2(v, *p); + return v; +} + +#endif diff --git a/mp/src/utils/lzma/C/XzDec.c b/mp/src/utils/lzma/C/XzDec.c new file mode 100644 index 00000000..a5698e86 --- /dev/null +++ b/mp/src/utils/lzma/C/XzDec.c @@ -0,0 +1,909 @@ +/* XzDec.c -- Xz Decode +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +/* #define XZ_DUMP */ + +#ifdef XZ_DUMP +#include +#endif + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#include "Delta.h" +#include "Lzma2Dec.h" + +#ifdef USE_SUBBLOCK +#include "Bcj3Dec.c" +#include "SbDec.c" +#endif + +#include "Xz.h" + +#define XZ_CHECK_SIZE_MAX 64 + +#define CODER_BUF_SIZE (1 << 17) + +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) +{ + int i, limit; + *value = 0; + limit = (maxSize > 9) ? 9 : (int)maxSize; + + for (i = 0; i < limit;) + { + Byte b = p[i]; + *value |= (UInt64)(b & 0x7F) << (7 * i++); + if ((b & 0x80) == 0) + return (b == 0 && i != 1) ? 0 : i; + } + return 0; +} + +/* ---------- BraState ---------- */ + +#define BRA_BUF_SIZE (1 << 14) + +typedef struct +{ + size_t bufPos; + size_t bufConv; + size_t bufTotal; + + UInt32 methodId; + int encodeMode; + UInt32 delta; + UInt32 ip; + UInt32 x86State; + Byte deltaState[DELTA_STATE_SIZE]; + + Byte buf[BRA_BUF_SIZE]; +} CBraState; + +void BraState_Free(void *pp, ISzAlloc *alloc) +{ + alloc->Free(alloc, pp); +} + +SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + CBraState *p = ((CBraState *)pp); + alloc = alloc; + p->ip = 0; + if (p->methodId == XZ_ID_Delta) + { + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + p->delta = (unsigned)props[0] + 1; + } + else + { + if (propSize == 4) + { + UInt32 v = GetUi32(props); + switch(p->methodId) + { + case XZ_ID_PPC: + case XZ_ID_ARM: + case XZ_ID_SPARC: + if ((v & 3) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_ARMT: + if ((v & 1) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + case XZ_ID_IA64: + if ((v & 0xF) != 0) + return SZ_ERROR_UNSUPPORTED; + break; + } + p->ip = v; + } + else if (propSize != 0) + return SZ_ERROR_UNSUPPORTED; + } + return SZ_OK; +} + +void BraState_Init(void *pp) +{ + CBraState *p = ((CBraState *)pp); + p->bufPos = p->bufConv = p->bufTotal = 0; + x86_Convert_Init(p->x86State); + if (p->methodId == XZ_ID_Delta) + Delta_Init(p->deltaState); +} + +#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break; + +static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + CBraState *p = ((CBraState *)pp); + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + finishMode = finishMode; + *wasFinished = 0; + while (destLenOrig > 0) + { + if (p->bufPos != p->bufConv) + { + size_t curSize = p->bufConv - p->bufPos; + if (curSize > destLenOrig) + curSize = destLenOrig; + memcpy(dest, p->buf + p->bufPos, curSize); + p->bufPos += curSize; + *destLen += curSize; + dest += curSize; + destLenOrig -= curSize; + continue; + } + p->bufTotal -= p->bufPos; + memmove(p->buf, p->buf + p->bufPos, p->bufTotal); + p->bufPos = 0; + p->bufConv = 0; + { + size_t curSize = BRA_BUF_SIZE - p->bufTotal; + if (curSize > srcLenOrig) + curSize = srcLenOrig; + memcpy(p->buf + p->bufTotal, src, curSize); + *srcLen += curSize; + src += curSize; + srcLenOrig -= curSize; + p->bufTotal += curSize; + } + if (p->bufTotal == 0) + break; + switch(p->methodId) + { + case XZ_ID_Delta: + if (p->encodeMode) + Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal); + else + Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal); + p->bufConv = p->bufTotal; + break; + case XZ_ID_X86: + p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode); + break; + CASE_BRA_CONV(PPC) + CASE_BRA_CONV(IA64) + CASE_BRA_CONV(ARM) + CASE_BRA_CONV(ARMT) + CASE_BRA_CONV(SPARC) + default: + return SZ_ERROR_UNSUPPORTED; + } + p->ip += (UInt32)p->bufConv; + + if (p->bufConv == 0) + { + if (!srcWasFinished) + break; + p->bufConv = p->bufTotal; + } + } + if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished) + *wasFinished = 1; + return SZ_OK; +} + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc) +{ + CBraState *decoder; + if (id != XZ_ID_Delta && + id != XZ_ID_X86 && + id != XZ_ID_PPC && + id != XZ_ID_IA64 && + id != XZ_ID_ARM && + id != XZ_ID_ARMT && + id != XZ_ID_SPARC) + return SZ_ERROR_UNSUPPORTED; + p->p = 0; + decoder = (CBraState *)alloc->Alloc(alloc, sizeof(CBraState)); + if (decoder == 0) + return SZ_ERROR_MEM; + decoder->methodId = (UInt32)id; + decoder->encodeMode = encodeMode; + p->p = decoder; + p->Free = BraState_Free; + p->SetProps = BraState_SetProps; + p->Init = BraState_Init; + p->Code = BraState_Code; + return SZ_OK; +} + +/* ---------- SbState ---------- */ + +#ifdef USE_SUBBLOCK + +static void SbState_Free(void *pp, ISzAlloc *alloc) +{ + CSbDec *p = (CSbDec *)pp; + SbDec_Free(p); + alloc->Free(alloc, pp); +} + +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + pp = pp; + props = props; + alloc = alloc; + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static void SbState_Init(void *pp) +{ + SbDec_Init((CSbDec *)pp); +} + +static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + CSbDec *p = (CSbDec *)pp; + SRes res; + srcWasFinished = srcWasFinished; + p->dest = dest; + p->destLen = *destLen; + p->src = src; + p->srcLen = *srcLen; + p->finish = finishMode; /* change it */ + res = SbDec_Decode((CSbDec *)pp); + *destLen -= p->destLen; + *srcLen -= p->srcLen; + *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ + return res; +} + +SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) +{ + CSbDec *decoder; + p->p = 0; + decoder = alloc->Alloc(alloc, sizeof(CSbDec)); + if (decoder == 0) + return SZ_ERROR_MEM; + p->p = decoder; + p->Free = SbState_Free; + p->SetProps = SbState_SetProps; + p->Init = SbState_Init; + p->Code = SbState_Code; + SbDec_Construct(decoder); + SbDec_SetAlloc(decoder, alloc); + return SZ_OK; +} +#endif + +/* ---------- Lzma2State ---------- */ + +static void Lzma2State_Free(void *pp, ISzAlloc *alloc) +{ + Lzma2Dec_Free((CLzma2Dec *)pp, alloc); + alloc->Free(alloc, pp); +} + +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc) +{ + if (propSize != 1) + return SZ_ERROR_UNSUPPORTED; + return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc); +} + +static void Lzma2State_Init(void *pp) +{ + Lzma2Dec_Init((CLzma2Dec *)pp); +} + +static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished) +{ + ELzmaStatus status; + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ + SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status); + srcWasFinished = srcWasFinished; + *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK); + return res; +} + +static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc) +{ + CLzma2Dec *decoder = (CLzma2Dec *)alloc->Alloc(alloc, sizeof(CLzma2Dec)); + p->p = decoder; + if (decoder == 0) + return SZ_ERROR_MEM; + p->Free = Lzma2State_Free; + p->SetProps = Lzma2State_SetProps; + p->Init = Lzma2State_Init; + p->Code = Lzma2State_Code; + Lzma2Dec_Construct(decoder); + return SZ_OK; +} + + +void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc) +{ + int i; + p->alloc = alloc; + p->buf = 0; + p->numCoders = 0; + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) + p->coders[i].p = NULL; +} + +void MixCoder_Free(CMixCoder *p) +{ + int i; + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *sc = &p->coders[i]; + if (p->alloc && sc->p) + sc->Free(sc->p, p->alloc); + } + p->numCoders = 0; + if (p->buf) + { + p->alloc->Free(p->alloc, p->buf); + p->buf = 0; /* 9.31: the BUG was fixed */ + } +} + +void MixCoder_Init(CMixCoder *p) +{ + int i; + for (i = 0; i < p->numCoders - 1; i++) + { + p->size[i] = 0; + p->pos[i] = 0; + p->finished[i] = 0; + } + for (i = 0; i < p->numCoders; i++) + { + IStateCoder *coder = &p->coders[i]; + coder->Init(coder->p); + } +} + +SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId) +{ + IStateCoder *sc = &p->coders[coderIndex]; + p->ids[coderIndex] = methodId; + switch(methodId) + { + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc); + #ifdef USE_SUBBLOCK + case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); + #endif + } + if (coderIndex == 0) + return SZ_ERROR_UNSUPPORTED; + return BraState_SetFromMethod(sc, methodId, 0, p->alloc); +} + +SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, int srcWasFinished, + ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + Bool allFinished = True; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_FINISHED; + + if (p->buf == 0) + { + p->buf = (Byte *)p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); + if (p->buf == 0) + return SZ_ERROR_MEM; + } + + if (p->numCoders != 1) + finishMode = CODER_FINISH_ANY; + + for (;;) + { + Bool processed = False; + int i; + /* + if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) + break; + */ + + for (i = 0; i < p->numCoders; i++) + { + SRes res; + IStateCoder *coder = &p->coders[i]; + Byte *destCur; + SizeT destLenCur, srcLenCur; + const Byte *srcCur; + int srcFinishedCur; + int encodingWasFinished; + + if (i == 0) + { + srcCur = src; + srcLenCur = srcLenOrig - *srcLen; + srcFinishedCur = srcWasFinished; + } + else + { + srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1]; + srcLenCur = p->size[i - 1] - p->pos[i - 1]; + srcFinishedCur = p->finished[i - 1]; + } + + if (i == p->numCoders - 1) + { + destCur = dest; + destLenCur = destLenOrig - *destLen; + } + else + { + if (p->pos[i] != p->size[i]) + continue; + destCur = p->buf + (CODER_BUF_SIZE * i); + destLenCur = CODER_BUF_SIZE; + } + + res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished); + + if (!encodingWasFinished) + allFinished = False; + + if (i == 0) + { + *srcLen += srcLenCur; + src += srcLenCur; + } + else + { + p->pos[i - 1] += srcLenCur; + } + + if (i == p->numCoders - 1) + { + *destLen += destLenCur; + dest += destLenCur; + } + else + { + p->size[i] = destLenCur; + p->pos[i] = 0; + p->finished[i] = encodingWasFinished; + } + + if (res != SZ_OK) + return res; + + if (destLenCur != 0 || srcLenCur != 0) + processed = True; + } + if (!processed) + break; + } + if (allFinished) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + +SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) +{ + *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); + if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != + GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) + return SZ_ERROR_NO_ARCHIVE; + return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; +} + +static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) +{ + return + indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) && + (GetUi32(buf) == CrcCalc(buf + 4, 6) && + flags == GetBe16(buf + 8) && + memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0); +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + + +SRes XzBlock_Parse(CXzBlock *p, const Byte *header) +{ + unsigned pos; + int numFilters, i; + UInt32 headerSize = (UInt32)header[0] << 2; + + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) + return SZ_ERROR_ARCHIVE; + + pos = 1; + if (pos == headerSize) + return SZ_ERROR_ARCHIVE; + p->flags = header[pos++]; + + if (XzBlock_HasPackSize(p)) + { + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize); + if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) + return SZ_ERROR_ARCHIVE; + } + + if (XzBlock_HasUnpackSize(p)) + READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize); + + numFilters = XzBlock_GetNumFilters(p); + for (i = 0; i < numFilters; i++) + { + CXzFilter *filter = p->filters + i; + UInt64 size; + READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id); + READ_VARINT_AND_CHECK(header, pos, headerSize, &size); + if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) + return SZ_ERROR_ARCHIVE; + filter->propsSize = (UInt32)size; + memcpy(filter->props, header + pos, (size_t)size); + pos += (unsigned)size; + + #ifdef XZ_DUMP + printf("\nf[%d] = %2X: ", i, filter->id); + { + int i; + for (i = 0; i < size; i++) + printf(" %2X", filter->props[i]); + } + #endif + } + + while (pos < headerSize) + if (header[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return SZ_OK; +} + +SRes XzDec_Init(CMixCoder *p, const CXzBlock *block) +{ + int i; + Bool needReInit = True; + int numFilters = XzBlock_GetNumFilters(block); + if (numFilters == p->numCoders) + { + for (i = 0; i < numFilters; i++) + if (p->ids[i] != block->filters[numFilters - 1 - i].id) + break; + needReInit = (i != numFilters); + } + if (needReInit) + { + MixCoder_Free(p); + p->numCoders = numFilters; + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + RINOK(MixCoder_SetFromMethod(p, i, f->id)); + } + } + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &block->filters[numFilters - 1 - i]; + IStateCoder *sc = &p->coders[i]; + RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); + } + MixCoder_Init(p); + return SZ_OK; +} + +void XzUnpacker_Init(CXzUnpacker *p) +{ + p->state = XZ_STATE_STREAM_HEADER; + p->pos = 0; + p->numStartedStreams = 0; + p->numFinishedStreams = 0; + p->numTotalBlocks = 0; + p->padSize = 0; +} + +void XzUnpacker_Construct(CXzUnpacker *p, ISzAlloc *alloc) +{ + MixCoder_Construct(&p->decoder, alloc); + XzUnpacker_Init(p); +} + +void XzUnpacker_Free(CXzUnpacker *p) +{ + MixCoder_Free(&p->decoder); +} + +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ECoderFinishMode finishMode, ECoderStatus *status) +{ + SizeT destLenOrig = *destLen; + SizeT srcLenOrig = *srcLen; + *destLen = 0; + *srcLen = 0; + *status = CODER_STATUS_NOT_SPECIFIED; + for (;;) + { + SizeT srcRem = srcLenOrig - *srcLen; + + if (p->state == XZ_STATE_BLOCK) + { + SizeT destLen2 = destLenOrig - *destLen; + SizeT srcLen2 = srcLenOrig - *srcLen; + SRes res; + if (srcLen2 == 0 && destLen2 == 0) + { + *status = CODER_STATUS_NOT_FINISHED; + return SZ_OK; + } + + res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status); + XzCheck_Update(&p->check, dest, destLen2); + + (*srcLen) += srcLen2; + src += srcLen2; + p->packSize += srcLen2; + + (*destLen) += destLen2; + dest += destLen2; + p->unpackSize += destLen2; + + RINOK(res); + + if (*status == CODER_STATUS_FINISHED_WITH_MARK) + { + Byte temp[32]; + unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags)); + num += Xz_WriteVarInt(temp + num, p->unpackSize); + Sha256_Update(&p->sha, temp, num); + p->indexSize += num; + p->numBlocks++; + + p->state = XZ_STATE_BLOCK_FOOTER; + p->pos = 0; + p->alignPos = 0; + } + else if (srcLen2 == 0 && destLen2 == 0) + return SZ_OK; + + continue; + } + + if (srcRem == 0) + { + *status = CODER_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + + switch (p->state) + { + case XZ_STATE_STREAM_HEADER: + { + if (p->pos < XZ_STREAM_HEADER_SIZE) + { + if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) + return SZ_ERROR_NO_ARCHIVE; + p->buf[p->pos++] = *src++; + (*srcLen)++; + } + else + { + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); + p->numStartedStreams++; + p->state = XZ_STATE_BLOCK_HEADER; + Sha256_Init(&p->sha); + p->indexSize = 0; + p->numBlocks = 0; + p->pos = 0; + } + break; + } + + case XZ_STATE_BLOCK_HEADER: + { + if (p->pos == 0) + { + p->buf[p->pos++] = *src++; + (*srcLen)++; + if (p->buf[0] == 0) + { + p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); + p->indexPos = p->indexPreSize; + p->indexSize += p->indexPreSize; + Sha256_Final(&p->sha, p->shaDigest); + Sha256_Init(&p->sha); + p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); + p->state = XZ_STATE_STREAM_INDEX; + } + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; + } + else if (p->pos != p->blockHeaderSize) + { + UInt32 cur = p->blockHeaderSize - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + RINOK(XzBlock_Parse(&p->block, p->buf)); + p->numTotalBlocks++; + p->state = XZ_STATE_BLOCK; + p->packSize = 0; + p->unpackSize = 0; + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); + RINOK(XzDec_Init(&p->decoder, &p->block)); + } + break; + } + + case XZ_STATE_BLOCK_FOOTER: + { + if (((p->packSize + p->alignPos) & 3) != 0) + { + (*srcLen)++; + p->alignPos++; + if (*src++ != 0) + return SZ_ERROR_CRC; + } + else + { + UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); + UInt32 cur = checkSize - p->pos; + if (cur != 0) + { + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + } + else + { + Byte digest[XZ_CHECK_SIZE_MAX]; + p->state = XZ_STATE_BLOCK_HEADER; + p->pos = 0; + if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) + return SZ_ERROR_CRC; + } + } + break; + } + + case XZ_STATE_STREAM_INDEX: + { + if (p->pos < p->indexPreSize) + { + (*srcLen)++; + if (*src++ != p->buf[p->pos++]) + return SZ_ERROR_CRC; + } + else + { + if (p->indexPos < p->indexSize) + { + UInt64 cur = p->indexSize - p->indexPos; + if (srcRem > cur) + srcRem = (SizeT)cur; + p->crc = CrcUpdate(p->crc, src, srcRem); + Sha256_Update(&p->sha, src, srcRem); + (*srcLen) += srcRem; + src += srcRem; + p->indexPos += srcRem; + } + else if ((p->indexPos & 3) != 0) + { + Byte b = *src++; + p->crc = CRC_UPDATE_BYTE(p->crc, b); + (*srcLen)++; + p->indexPos++; + p->indexSize++; + if (b != 0) + return SZ_ERROR_CRC; + } + else + { + Byte digest[SHA256_DIGEST_SIZE]; + p->state = XZ_STATE_STREAM_INDEX_CRC; + p->indexSize += 4; + p->pos = 0; + Sha256_Final(&p->sha, digest); + if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) + return SZ_ERROR_CRC; + } + } + break; + } + + case XZ_STATE_STREAM_INDEX_CRC: + { + if (p->pos < 4) + { + (*srcLen)++; + p->buf[p->pos++] = *src++; + } + else + { + p->state = XZ_STATE_STREAM_FOOTER; + p->pos = 0; + if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_FOOTER: + { + UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; + if (cur > srcRem) + cur = (UInt32)srcRem; + memcpy(p->buf + p->pos, src, cur); + p->pos += cur; + (*srcLen) += cur; + src += cur; + if (p->pos == XZ_STREAM_FOOTER_SIZE) + { + p->state = XZ_STATE_STREAM_PADDING; + p->numFinishedStreams++; + p->padSize = 0; + if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) + return SZ_ERROR_CRC; + } + break; + } + + case XZ_STATE_STREAM_PADDING: + { + if (*src != 0) + { + if (((UInt32)p->padSize & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + p->pos = 0; + p->state = XZ_STATE_STREAM_HEADER; + } + else + { + (*srcLen)++; + src++; + p->padSize++; + } + break; + } + + case XZ_STATE_BLOCK: break; /* to disable GCC warning */ + } + } + /* + if (p->state == XZ_STATE_FINISHED) + *status = CODER_STATUS_FINISHED_WITH_MARK; + return SZ_OK; + */ +} + +Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p) +{ + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); +} + +UInt64 XzUnpacker_GetExtraSize(CXzUnpacker *p) +{ + UInt64 num = 0; + if (p->state == XZ_STATE_STREAM_PADDING) + num += p->padSize; + else if (p->state == XZ_STATE_STREAM_HEADER) + num += p->padSize + p->pos; + return num; +} diff --git a/mp/src/utils/lzma/C/XzEnc.c b/mp/src/utils/lzma/C/XzEnc.c new file mode 100644 index 00000000..ed6e1ba6 --- /dev/null +++ b/mp/src/utils/lzma/C/XzEnc.c @@ -0,0 +1,522 @@ +/* XzEnc.c -- Xz Encode +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include +#include + +#include "7zCrc.h" +#include "Alloc.h" +#include "Bra.h" +#include "CpuArch.h" +#ifdef USE_SUBBLOCK +#include "Bcj3Enc.c" +#include "SbFind.c" +#include "SbEnc.c" +#endif + +#include "XzEnc.h" + +static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); } +static void SzBigFree(void *p, void *address) { p = p; BigFree(address); } +static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + +static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } +static void SzFree(void *p, void *address) { p = p; MyFree(address); } +static ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +#define XzBlock_ClearFlags(p) (p)->flags = 0; +#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1); +#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE; +#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE; + +static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size) +{ + return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE; +} + +static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc) +{ + *crc = CrcUpdate(*crc, buf, size); + return WriteBytes(s, buf, size); +} + +SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s) +{ + UInt32 crc; + Byte header[XZ_STREAM_HEADER_SIZE]; + memcpy(header, XZ_SIG, XZ_SIG_SIZE); + header[XZ_SIG_SIZE] = (Byte)(f >> 8); + header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF); + crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE); + SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc); + return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE); +} + +SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + + unsigned pos = 1; + int numFilters, i; + header[pos++] = p->flags; + + if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize); + if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize); + numFilters = XzBlock_GetNumFilters(p); + for (i = 0; i < numFilters; i++) + { + const CXzFilter *f = &p->filters[i]; + pos += Xz_WriteVarInt(header + pos, f->id); + pos += Xz_WriteVarInt(header + pos, f->propsSize); + memcpy(header + pos, f->props, f->propsSize); + pos += f->propsSize; + } + while((pos & 3) != 0) + header[pos++] = 0; + header[0] = (Byte)(pos >> 2); + SetUi32(header + pos, CrcCalc(header, pos)); + return WriteBytes(s, header, pos + 4); +} + +SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s) +{ + Byte buf[32]; + UInt64 globalPos; + { + UInt32 crc = CRC_INIT_VAL; + unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks); + size_t i; + + globalPos = pos; + buf[0] = 0; + RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); + for (i = 0; i < p->numBlocks; i++) + { + const CXzBlockSizes *block = &p->blocks[i]; + pos = Xz_WriteVarInt(buf, block->totalSize); + pos += Xz_WriteVarInt(buf + pos, block->unpackSize); + globalPos += pos; + RINOK(WriteBytesAndCrc(s, buf, pos, &crc)); + } + pos = ((unsigned)globalPos & 3); + if (pos != 0) + { + buf[0] = buf[1] = buf[2] = 0; + RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc)); + globalPos += 4 - pos; + } + { + SetUi32(buf, CRC_GET_DIGEST(crc)); + RINOK(WriteBytes(s, buf, 4)); + globalPos += 4; + } + } + + { + UInt32 indexSize = (UInt32)((globalPos >> 2) - 1); + SetUi32(buf + 4, indexSize); + buf[8] = (Byte)(p->flags >> 8); + buf[9] = (Byte)(p->flags & 0xFF); + SetUi32(buf, CrcCalc(buf + 4, 6)); + memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE); + return WriteBytes(s, buf, 12); + } +} + +SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc) +{ + if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks) + { + size_t num = (p->numBlocks + 1) * 2; + size_t newSize = sizeof(CXzBlockSizes) * num; + CXzBlockSizes *blocks; + if (newSize / sizeof(CXzBlockSizes) != num) + return SZ_ERROR_MEM; + blocks = (CXzBlockSizes *)alloc->Alloc(alloc, newSize); + if (blocks == 0) + return SZ_ERROR_MEM; + if (p->numBlocks != 0) + { + memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes)); + Xz_Free(p, alloc); + } + p->blocks = blocks; + p->numBlocksAllocated = num; + } + { + CXzBlockSizes *block = &p->blocks[p->numBlocks++]; + block->totalSize = totalSize; + block->unpackSize = unpackSize; + } + return SZ_OK; +} + +/* ---------- CSeqCheckInStream ---------- */ + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + UInt64 processed; + CXzCheck check; +} CSeqCheckInStream; + +void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode) +{ + p->processed = 0; + XzCheck_Init(&p->check, mode); +} + +void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest) +{ + XzCheck_Final(&p->check, digest); +} + +static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size) +{ + CSeqCheckInStream *p = (CSeqCheckInStream *)pp; + SRes res = p->realStream->Read(p->realStream, data, size); + XzCheck_Update(&p->check, data, *size); + p->processed += *size; + return res; +} + +/* ---------- CSeqSizeOutStream ---------- */ + +typedef struct +{ + ISeqOutStream p; + ISeqOutStream *realStream; + UInt64 processed; +} CSeqSizeOutStream; + +static size_t MyWrite(void *pp, const void *data, size_t size) +{ + CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp; + size = p->realStream->Write(p->realStream, data, size); + p->processed += size; + return size; +} + +/* ---------- CSeqInFilter ---------- */ + +#define FILTER_BUF_SIZE (1 << 20) + +typedef struct +{ + ISeqInStream p; + ISeqInStream *realStream; + IStateCoder StateCoder; + Byte *buf; + size_t curPos; + size_t endPos; + int srcWasFinished; +} CSeqInFilter; + +static SRes SeqInFilter_Read(void *pp, void *data, size_t *size) +{ + CSeqInFilter *p = (CSeqInFilter *)pp; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return SZ_OK; + *size = 0; + for (;;) + { + if (!p->srcWasFinished && p->curPos == p->endPos) + { + p->curPos = 0; + p->endPos = FILTER_BUF_SIZE; + RINOK(p->realStream->Read(p->realStream, p->buf, &p->endPos)); + if (p->endPos == 0) + p->srcWasFinished = 1; + } + { + SizeT srcLen = p->endPos - p->curPos; + int wasFinished; + SRes res; + *size = sizeOriginal; + res = p->StateCoder.Code(p->StateCoder.p, data, size, p->buf + p->curPos, &srcLen, + p->srcWasFinished, CODER_FINISH_ANY, &wasFinished); + p->curPos += srcLen; + if (*size != 0 || srcLen == 0 || res != 0) + return res; + } + } +} + +static void SeqInFilter_Construct(CSeqInFilter *p) +{ + p->buf = NULL; + p->p.Read = SeqInFilter_Read; +} + +static void SeqInFilter_Free(CSeqInFilter *p) +{ + if (p->buf) + { + g_Alloc.Free(&g_Alloc, p->buf); + p->buf = NULL; + } +} + +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAlloc *alloc); + +static SRes SeqInFilter_Init(CSeqInFilter *p, const CXzFilter *props) +{ + if (!p->buf) + { + p->buf = g_Alloc.Alloc(&g_Alloc, FILTER_BUF_SIZE); + if (!p->buf) + return SZ_ERROR_MEM; + } + p->curPos = p->endPos = 0; + p->srcWasFinished = 0; + RINOK(BraState_SetFromMethod(&p->StateCoder, props->id, 1, &g_Alloc)); + RINOK(p->StateCoder.SetProps(p->StateCoder.p, props->props, props->propsSize, &g_Alloc)); + p->StateCoder.Init(p->StateCoder.p); + return SZ_OK; +} + +/* ---------- CSbEncInStream ---------- */ + +#ifdef USE_SUBBLOCK + +typedef struct +{ + ISeqInStream p; + ISeqInStream *inStream; + CSbEnc enc; +} CSbEncInStream; + +static SRes SbEncInStream_Read(void *pp, void *data, size_t *size) +{ + CSbEncInStream *p = (CSbEncInStream *)pp; + size_t sizeOriginal = *size; + if (sizeOriginal == 0) + return S_OK; + for (;;) + { + if (p->enc.needRead && !p->enc.readWasFinished) + { + size_t processed = p->enc.needReadSizeMax; + RINOK(p->inStream->Read(p->inStream, p->enc.buf + p->enc.readPos, &processed)); + p->enc.readPos += processed; + if (processed == 0) + { + p->enc.readWasFinished = True; + p->enc.isFinalFinished = True; + } + p->enc.needRead = False; + } + *size = sizeOriginal; + RINOK(SbEnc_Read(&p->enc, data, size)); + if (*size != 0 || !p->enc.needRead) + return S_OK; + } +} + +void SbEncInStream_Construct(CSbEncInStream *p, ISzAlloc *alloc) +{ + SbEnc_Construct(&p->enc, alloc); + p->p.Read = SbEncInStream_Read; +} + +SRes SbEncInStream_Init(CSbEncInStream *p) +{ + return SbEnc_Init(&p->enc); +} + +void SbEncInStream_Free(CSbEncInStream *p) +{ + SbEnc_Free(&p->enc); +} + +#endif + + +typedef struct +{ + CLzma2EncHandle lzma2; + #ifdef USE_SUBBLOCK + CSbEncInStream sb; + #endif + CSeqInFilter filter; + ISzAlloc *alloc; + ISzAlloc *bigAlloc; +} CLzma2WithFilters; + + +static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc) +{ + p->alloc = alloc; + p->bigAlloc = bigAlloc; + p->lzma2 = NULL; + #ifdef USE_SUBBLOCK + SbEncInStream_Construct(&p->sb, alloc); + #endif + SeqInFilter_Construct(&p->filter); +} + +static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p) +{ + p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc); + if (p->lzma2 == 0) + return SZ_ERROR_MEM; + return SZ_OK; +} + +static void Lzma2WithFilters_Free(CLzma2WithFilters *p) +{ + SeqInFilter_Free(&p->filter); + #ifdef USE_SUBBLOCK + SbEncInStream_Free(&p->sb); + #endif + if (p->lzma2) + { + Lzma2Enc_Destroy(p->lzma2); + p->lzma2 = NULL; + } +} + +void XzProps_Init(CXzProps *p) +{ + p->lzma2Props = 0; + p->filterProps = 0; + p->checkId = XZ_CHECK_CRC32; +} + +void XzFilterProps_Init(CXzFilterProps *p) +{ + p->id = 0; + p->delta = 0; + p->ip= 0; + p->ipDefined = False; +} + +static SRes Xz_Compress(CXzStream *xz, CLzma2WithFilters *lzmaf, + ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + xz->flags = (Byte)props->checkId; + + RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, props->lzma2Props)); + RINOK(Xz_WriteHeader(xz->flags, outStream)); + + { + CSeqCheckInStream checkInStream; + CSeqSizeOutStream seqSizeOutStream; + CXzBlock block; + int filterIndex = 0; + CXzFilter *filter = NULL; + const CXzFilterProps *fp = props->filterProps; + + XzBlock_ClearFlags(&block); + XzBlock_SetNumFilters(&block, 1 + (fp ? 1 : 0)); + + if (fp) + { + filter = &block.filters[filterIndex++]; + filter->id = fp->id; + filter->propsSize = 0; + if (fp->id == XZ_ID_Delta) + { + filter->props[0] = (Byte)(fp->delta - 1); + filter->propsSize = 1; + } + else if (fp->ipDefined) + { + SetUi32(filter->props, fp->ip); + filter->propsSize = 4; + } + } + + { + CXzFilter *f = &block.filters[filterIndex++]; + f->id = XZ_ID_LZMA2; + f->propsSize = 1; + f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2); + } + + seqSizeOutStream.p.Write = MyWrite; + seqSizeOutStream.realStream = outStream; + seqSizeOutStream.processed = 0; + + RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p)); + + checkInStream.p.Read = SeqCheckInStream_Read; + checkInStream.realStream = inStream; + SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags)); + + if (fp) + { + #ifdef USE_SUBBLOCK + if (fp->id == XZ_ID_Subblock) + { + lzmaf->sb.inStream = &checkInStream.p; + RINOK(SbEncInStream_Init(&lzmaf->sb)); + } + else + #endif + { + lzmaf->filter.realStream = &checkInStream.p; + RINOK(SeqInFilter_Init(&lzmaf->filter, filter)); + } + } + + { + UInt64 packPos = seqSizeOutStream.processed; + SRes res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p, + fp ? + #ifdef USE_SUBBLOCK + (fp->id == XZ_ID_Subblock) ? &lzmaf->sb.p: + #endif + &lzmaf->filter.p: + &checkInStream.p, + progress); + RINOK(res); + block.unpackSize = checkInStream.processed; + block.packSize = seqSizeOutStream.processed - packPos; + } + + { + unsigned padSize = 0; + Byte buf[128]; + while((((unsigned)block.packSize + padSize) & 3) != 0) + buf[padSize++] = 0; + SeqCheckInStream_GetDigest(&checkInStream, buf + padSize); + RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags))); + RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc)); + } + } + return Xz_WriteFooter(xz, outStream); +} + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress) +{ + SRes res; + CXzStream xz; + CLzma2WithFilters lzmaf; + Xz_Construct(&xz); + Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc); + res = Lzma2WithFilters_Create(&lzmaf); + if (res == SZ_OK) + res = Xz_Compress(&xz, &lzmaf, outStream, inStream, props, progress); + Lzma2WithFilters_Free(&lzmaf); + Xz_Free(&xz, &g_Alloc); + return res; +} + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream) +{ + SRes res; + CXzStream xz; + Xz_Construct(&xz); + res = Xz_WriteHeader(xz.flags, outStream); + if (res == SZ_OK) + res = Xz_WriteFooter(&xz, outStream); + Xz_Free(&xz, &g_Alloc); + return res; +} diff --git a/mp/src/utils/lzma/C/XzEnc.h b/mp/src/utils/lzma/C/XzEnc.h new file mode 100644 index 00000000..c3c19eca --- /dev/null +++ b/mp/src/utils/lzma/C/XzEnc.h @@ -0,0 +1,39 @@ +/* XzEnc.h -- Xz Encode +2011-02-07 : Igor Pavlov : Public domain */ + +#ifndef __XZ_ENC_H +#define __XZ_ENC_H + +#include "Lzma2Enc.h" + +#include "Xz.h" + +EXTERN_C_BEGIN + +typedef struct +{ + UInt32 id; + UInt32 delta; + UInt32 ip; + int ipDefined; +} CXzFilterProps; + +void XzFilterProps_Init(CXzFilterProps *p); + +typedef struct +{ + const CLzma2EncProps *lzma2Props; + const CXzFilterProps *filterProps; + unsigned checkId; +} CXzProps; + +void XzProps_Init(CXzProps *p); + +SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream, + const CXzProps *props, ICompressProgress *progress); + +SRes Xz_EncodeEmpty(ISeqOutStream *outStream); + +EXTERN_C_END + +#endif diff --git a/mp/src/utils/lzma/C/XzIn.c b/mp/src/utils/lzma/C/XzIn.c new file mode 100644 index 00000000..05b4a5f0 --- /dev/null +++ b/mp/src/utils/lzma/C/XzIn.c @@ -0,0 +1,307 @@ +/* XzIn.c - Xz input +2014-12-30 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zCrc.h" +#include "CpuArch.h" +#include "Xz.h" + +SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream) +{ + Byte sig[XZ_STREAM_HEADER_SIZE]; + RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + return Xz_ParseHeader(p, sig); +} + +#define READ_VARINT_AND_CHECK(buf, pos, size, res) \ + { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ + if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; } + +SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes) +{ + Byte header[XZ_BLOCK_HEADER_SIZE_MAX]; + unsigned headerSize; + *headerSizeRes = 0; + RINOK(SeqInStream_ReadByte(inStream, &header[0])); + headerSize = ((unsigned)header[0] << 2) + 4; + if (headerSize == 0) + { + *headerSizeRes = 1; + *isIndex = True; + return SZ_OK; + } + + *isIndex = False; + *headerSizeRes = headerSize; + RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1)); + return XzBlock_Parse(p, header); +} + +#define ADD_SIZE_CHECH(size, val) \ + { UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; } + +UInt64 Xz_GetUnpackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECH(size, p->blocks[i].unpackSize); + return size; +} + +UInt64 Xz_GetPackSize(const CXzStream *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->numBlocks; i++) + ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3); + return size; +} + +/* +SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream) +{ + return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f)); +} +*/ + +static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc) +{ + size_t i, numBlocks, pos = 1; + UInt32 crc; + + if (size < 5 || buf[0] != 0) + return SZ_ERROR_ARCHIVE; + + size -= 4; + crc = CrcCalc(buf, size); + if (crc != GetUi32(buf + size)) + return SZ_ERROR_ARCHIVE; + + { + UInt64 numBlocks64; + READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64); + numBlocks = (size_t)numBlocks64; + if (numBlocks != numBlocks64 || numBlocks * 2 > size) + return SZ_ERROR_ARCHIVE; + } + + Xz_Free(p, alloc); + if (numBlocks != 0) + { + p->numBlocks = numBlocks; + p->numBlocksAllocated = numBlocks; + p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks); + if (p->blocks == 0) + return SZ_ERROR_MEM; + for (i = 0; i < numBlocks; i++) + { + CXzBlockSizes *block = &p->blocks[i]; + READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize); + READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize); + if (block->totalSize == 0) + return SZ_ERROR_ARCHIVE; + } + } + while ((pos & 3) != 0) + if (buf[pos++] != 0) + return SZ_ERROR_ARCHIVE; + return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; +} + +static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc) +{ + SRes res; + size_t size; + Byte *buf; + if (indexSize > ((UInt32)1 << 31)) + return SZ_ERROR_UNSUPPORTED; + size = (size_t)indexSize; + if (size != indexSize) + return SZ_ERROR_UNSUPPORTED; + buf = alloc->Alloc(alloc, size); + if (buf == 0) + return SZ_ERROR_MEM; + res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED); + if (res == SZ_OK) + res = Xz_ReadIndex2(p, buf, size, alloc); + alloc->Free(alloc, buf); + return res; +} + +static SRes SeekFromCur(ILookInStream *inStream, Int64 *res) +{ + return inStream->Seek(inStream, res, SZ_SEEK_CUR); +} + +static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc) +{ + UInt64 indexSize; + Byte buf[XZ_STREAM_FOOTER_SIZE]; + + if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset = -XZ_STREAM_FOOTER_SIZE; + RINOK(SeekFromCur(stream, startOffset)); + + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + { + UInt32 total = 0; + *startOffset += XZ_STREAM_FOOTER_SIZE; + for (;;) + { + size_t i; + #define TEMP_BUF_SIZE (1 << 10) + Byte tempBuf[TEMP_BUF_SIZE]; + if (*startOffset < XZ_STREAM_FOOTER_SIZE || total > (1 << 16)) + return SZ_ERROR_NO_ARCHIVE; + i = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset; + total += (UInt32)i; + *startOffset = -(Int64)i; + RINOK(SeekFromCur(stream, startOffset)); + RINOK(LookInStream_Read2(stream, tempBuf, i, SZ_ERROR_NO_ARCHIVE)); + for (; i != 0; i--) + if (tempBuf[i - 1] != 0) + break; + if (i != 0) + { + if ((i & 3) != 0) + return SZ_ERROR_NO_ARCHIVE; + *startOffset += i; + break; + } + } + if (*startOffset < XZ_STREAM_FOOTER_SIZE) + return SZ_ERROR_NO_ARCHIVE; + *startOffset -= XZ_STREAM_FOOTER_SIZE; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE)); + if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0) + return SZ_ERROR_NO_ARCHIVE; + } + + p->flags = (CXzStreamFlags)GetBe16(buf + 8); + + if (!XzFlags_IsSupported(p->flags)) + return SZ_ERROR_UNSUPPORTED; + + if (GetUi32(buf) != CrcCalc(buf + 4, 6)) + return SZ_ERROR_ARCHIVE; + + indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2; + + *startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE); + RINOK(SeekFromCur(stream, startOffset)); + + RINOK(Xz_ReadIndex(p, stream, indexSize, alloc)); + + { + UInt64 totalSize = Xz_GetPackSize(p); + UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize; + if (totalSize == XZ_SIZE_OVERFLOW || + sum >= ((UInt64)1 << 63) || + totalSize >= ((UInt64)1 << 63)) + return SZ_ERROR_ARCHIVE; + *startOffset = -(Int64)sum; + RINOK(SeekFromCur(stream, startOffset)); + } + { + CXzStreamFlags headerFlags; + CSecToRead secToRead; + SecToRead_CreateVTable(&secToRead); + secToRead.realStream = stream; + + RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s)); + return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE; + } +} + + +/* ---------- Xz Streams ---------- */ + +void Xzs_Construct(CXzs *p) +{ + p->num = p->numAllocated = 0; + p->streams = 0; +} + +void Xzs_Free(CXzs *p, ISzAlloc *alloc) +{ + size_t i; + for (i = 0; i < p->num; i++) + Xz_Free(&p->streams[i], alloc); + alloc->Free(alloc, p->streams); + p->num = p->numAllocated = 0; + p->streams = 0; +} + +UInt64 Xzs_GetNumBlocks(const CXzs *p) +{ + UInt64 num = 0; + size_t i; + for (i = 0; i < p->num; i++) + num += p->streams[i].numBlocks; + return num; +} + +UInt64 Xzs_GetUnpackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i])); + return size; +} + +/* +UInt64 Xzs_GetPackSize(const CXzs *p) +{ + UInt64 size = 0; + size_t i; + for (i = 0; i < p->num; i++) + ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i])); + return size; +} +*/ + +SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc) +{ + Int64 endOffset = 0; + RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END)); + *startOffset = endOffset; + for (;;) + { + CXzStream st; + SRes res; + Xz_Construct(&st); + res = Xz_ReadBackward(&st, stream, startOffset, alloc); + st.startOffset = *startOffset; + RINOK(res); + if (p->num == p->numAllocated) + { + size_t newNum = p->num + p->num / 4 + 1; + Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream)); + if (data == 0) + return SZ_ERROR_MEM; + p->numAllocated = newNum; + if (p->num != 0) + memcpy(data, p->streams, p->num * sizeof(CXzStream)); + alloc->Free(alloc, p->streams); + p->streams = (CXzStream *)data; + } + p->streams[p->num++] = st; + if (*startOffset == 0) + break; + RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET)); + if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK) + return SZ_ERROR_PROGRESS; + } + return SZ_OK; +} diff --git a/mp/src/utils/vbsp/vbsp.cpp b/mp/src/utils/vbsp/vbsp.cpp index 97a4df4c..7b8c0593 100644 --- a/mp/src/utils/vbsp/vbsp.cpp +++ b/mp/src/utils/vbsp/vbsp.cpp @@ -66,6 +66,8 @@ int g_nDXLevel = 0; // default dxlevel if you don't specify it on the command- CUtlVector g_SkyAreas; char outbase[32]; +char g_szEmbedDir[MAX_PATH] = { 0 }; + // HLTOOLS: Introduce these calcs to make the block algorithm proportional to the proper // world coordinate extents. Assumes square spatial constraints. #define BLOCKS_SIZE 1024 @@ -896,6 +898,12 @@ int RunVBSP( int argc, char **argv ) Q_FileBase( source, mapbase, sizeof( mapbase ) ); strlwr( mapbase ); + // Maintaining legacy behavior here to avoid breaking tools: regardless of the extension we are passed, we strip it + // to get the "source" name, and append extensions as desired... + char mapFile[1024]; + V_strncpy( mapFile, source, sizeof( mapFile ) ); + V_strncat( mapFile, ".bsp", sizeof( mapFile ) ); + LoadCmdLineFromFile( argc, argv, mapbase, "vbsp" ); Msg( "Valve Software - vbsp.exe (%s)\n", __DATE__ ); @@ -1095,7 +1103,7 @@ int RunVBSP( int argc, char **argv ) { // nothing to do here, but don't bail on this option } - else if ( !Q_stricmp( argv[i], "-vproject" ) || !Q_stricmp( argv[i], "-game" ) ) + else if ( !Q_stricmp( argv[i], "-vproject" ) || !Q_stricmp( argv[i], "-game" ) || !Q_stricmp( argv[i], "-insert_search_path" ) ) { ++i; } @@ -1129,6 +1137,19 @@ int RunVBSP( int argc, char **argv ) { EnableFullMinidumps( true ); } + else if ( !Q_stricmp( argv[i], "-embed" ) && i < argc - 1 ) + { + V_MakeAbsolutePath( g_szEmbedDir, sizeof( g_szEmbedDir ), argv[++i], "." ); + V_FixSlashes( g_szEmbedDir ); + if ( !V_RemoveDotSlashes( g_szEmbedDir ) ) + { + Error( "Bad -embed - Can't resolve pathname for '%s'", g_szEmbedDir ); + break; + } + V_StripTrailingSlash( g_szEmbedDir ); + g_pFullFileSystem->AddSearchPath( g_szEmbedDir, "GAME", PATH_ADD_TO_TAIL ); + g_pFullFileSystem->AddSearchPath( g_szEmbedDir, "MOD", PATH_ADD_TO_TAIL ); + } else if (argv[i][0] == '-') { Warning("VBSP: Unknown option \"%s\"\n\n", argv[i]); @@ -1162,6 +1183,9 @@ int RunVBSP( int argc, char **argv ) " what affects visibility.\n" " -nowater : Get rid of water brushes.\n" " -low : Run as an idle-priority process.\n" + " -embed : Use as an additional search path for assets\n" + " and embed all assets in this directory into the compiled\n" + " map\n" "\n" " -vproject : Override the VPROJECT environment variable.\n" " -game : Same as -vproject.\n" @@ -1220,6 +1244,17 @@ int RunVBSP( int argc, char **argv ) CmdLib_Exit( 1 ); } + // Sanity check + if ( *g_szEmbedDir && ( onlyents || onlyprops ) ) + { + Warning( "-embed only makes sense alongside full BSP compiles.\n" + "\n" + "Use the bspzip utility to update embedded files.\n" ); + DeleteCmdLine( argc, argv ); + CmdLib_Cleanup(); + CmdLib_Exit( 1 ); + } + start = Plat_FloatTime(); // Run in the background? @@ -1261,7 +1296,7 @@ int RunVBSP( int argc, char **argv ) sprintf( materialPath, "%smaterials", gamedir ); InitMaterialSystem( materialPath, CmdLib_GetFileSystemFactory() ); Msg( "materialPath: %s\n", materialPath ); - + // delete portal and line files sprintf (path, "%s.prt", source); remove (path); @@ -1280,9 +1315,6 @@ int RunVBSP( int argc, char **argv ) } } - char platformBSPFileName[1024]; - GetPlatformMapPath( source, platformBSPFileName, g_nDXLevel, 1024 ); - // if we're combining materials, load the script file if ( g_ReplaceMaterials ) { @@ -1294,7 +1326,7 @@ int RunVBSP( int argc, char **argv ) // if (onlyents) { - LoadBSPFile (platformBSPFileName); + LoadBSPFile (mapFile); num_entities = 0; // Clear out the cubemap samples since they will be reparsed even with -onlyents g_nCubemapSamples = 0; @@ -1326,12 +1358,12 @@ int RunVBSP( int argc, char **argv ) // Doing this here because stuff abov may filter out entities UnparseEntities (); - WriteBSPFile (platformBSPFileName); + WriteBSPFile (mapFile); } else if (onlyprops) { // In the only props case, deal with static + detail props only - LoadBSPFile (platformBSPFileName); + LoadBSPFile (mapFile); LoadMapFile(name); SetModelNumbers(); @@ -1344,7 +1376,7 @@ int RunVBSP( int argc, char **argv ) LoadEmitDetailObjectDictionary( gamedir ); EmitDetailObjects(); - WriteBSPFile (platformBSPFileName); + WriteBSPFile (mapFile); } else { @@ -1353,9 +1385,9 @@ int RunVBSP( int argc, char **argv ) // // Load just the file system from the bsp - if( g_bKeepStaleZip && FileExists( platformBSPFileName ) ) + if( g_bKeepStaleZip && FileExists( mapFile ) ) { - LoadBSPFile_FileSystemOnly (platformBSPFileName); + LoadBSPFile_FileSystemOnly (mapFile); // Mark as stale since the lighting could be screwed with new ents. AddBufferToPak( GetPakFile(), "stale.txt", "stale", strlen( "stale" ) + 1, false ); } @@ -1372,6 +1404,13 @@ int RunVBSP( int argc, char **argv ) SetLightStyles (); LoadEmitDetailObjectDictionary( gamedir ); ProcessModels (); + + // Add embed dir if provided + if ( *g_szEmbedDir ) + { + AddDirToPak( GetPakFile(), g_szEmbedDir ); + WriteBSPFile( mapFile ); + } } end = Plat_FloatTime(); diff --git a/mp/src/utils/vbsp/vbsp.vpc b/mp/src/utils/vbsp/vbsp.vpc index 7065f0a5..e55762f2 100644 --- a/mp/src/utils/vbsp/vbsp.vpc +++ b/mp/src/utils/vbsp/vbsp.vpc @@ -178,6 +178,7 @@ $Project "Vbsp" $Lib mathlib $Lib tier2 $Lib vtf + $Lib "$LIBCOMMON/lzma" } $File "notes.txt" diff --git a/mp/src/utils/vbsp/writebsp.cpp b/mp/src/utils/vbsp/writebsp.cpp index 60d05980..005990d6 100644 --- a/mp/src/utils/vbsp/writebsp.cpp +++ b/mp/src/utils/vbsp/writebsp.cpp @@ -1271,23 +1271,24 @@ void EndBSPFile (void) // Compute bounds after creating disp info because we need to reference it ComputeBoundsNoSkybox(); - + // Make sure that we have a water lod control eneity if we have water in the map. EnsurePresenceOfWaterLODControlEntity(); // Doing this here because stuff about may filter out entities UnparseEntities (); - + // remove unused texinfos CompactTexinfos(); // Figure out which faces want macro textures. DiscoverMacroTextures(); - - char targetPath[1024]; - GetPlatformMapPath( source, targetPath, g_nDXLevel, 1024 ); - Msg ("Writing %s\n", targetPath); - WriteBSPFile (targetPath); + + char fileName[1024]; + V_strncpy( fileName, source, sizeof( fileName ) ); + V_DefaultExtension( fileName, ".bsp", sizeof( fileName ) ); + Msg ("Writing %s\n", fileName); + WriteBSPFile (fileName); } diff --git a/mp/src/utils/vrad/vrad.cpp b/mp/src/utils/vrad/vrad.cpp index 61a52095..1e880090 100644 --- a/mp/src/utils/vrad/vrad.cpp +++ b/mp/src/utils/vrad/vrad.cpp @@ -71,7 +71,6 @@ float lightscale = 1.0; float dlight_threshold = 0.1; // was DIRECT_LIGHT constant char source[MAX_PATH] = ""; -char platformPath[MAX_PATH] = ""; char level_name[MAX_PATH] = ""; // map filename, without extension or path info @@ -2121,6 +2120,7 @@ void InitDumpPatchesFiles() } } +extern IFileSystem *g_pOriginalPassThruFileSystem; void VRAD_LoadBSP( char const *pFilename ) { @@ -2180,12 +2180,24 @@ void VRAD_LoadBSP( char const *pFilename ) Q_DefaultExtension(incrementfile, ".r0", sizeof(incrementfile)); Q_DefaultExtension(source, ".bsp", sizeof( source )); - GetPlatformMapPath( source, platformPath, 0, MAX_PATH ); - - Msg( "Loading %s\n", platformPath ); + Msg( "Loading %s\n", source ); VMPI_SetCurrentStage( "LoadBSPFile" ); - LoadBSPFile (platformPath); - + LoadBSPFile (source); + + // Add this bsp to our search path so embedded resources can be found + if ( g_bUseMPI && g_bMPIMaster ) + { + // MPI Master, MPI workers don't need to do anything + g_pOriginalPassThruFileSystem->AddSearchPath(source, "GAME", PATH_ADD_TO_HEAD); + g_pOriginalPassThruFileSystem->AddSearchPath(source, "MOD", PATH_ADD_TO_HEAD); + } + else if ( !g_bUseMPI ) + { + // Non-MPI + g_pFullFileSystem->AddSearchPath(source, "GAME", PATH_ADD_TO_HEAD); + g_pFullFileSystem->AddSearchPath(source, "MOD", PATH_ADD_TO_HEAD); + } + // now, set whether or not static prop lighting is present if (g_bStaticPropLighting) g_LevelFlags |= g_bHDR? LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_HDR : LVLFLAGS_BAKED_STATIC_PROP_LIGHTING_NONHDR; @@ -2310,9 +2322,9 @@ void VRAD_Finish() PrintBSPFileSizes(); } - Msg( "Writing %s\n", platformPath ); + Msg( "Writing %s\n", source ); VMPI_SetCurrentStage( "WriteBSPFile" ); - WriteBSPFile(platformPath); + WriteBSPFile(source); if ( g_bDumpPatches ) { @@ -2353,6 +2365,8 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) { *onlydetail = false; + int mapArg = -1; + // default to LDR SetHDRMode( false ); int i; @@ -2418,14 +2432,14 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( bounceParam < 0 ) { Warning("Error: expected non-negative value after '-bounce'\n" ); - return 1; + return -1; } numbounce = (unsigned)bounceParam; } else { Warning("Error: expected a value after '-bounce'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-verbose") || !Q_stricmp(argv[i],"-v")) @@ -2440,13 +2454,13 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( numthreads <= 0 ) { Warning("Error: expected positive value after '-threads'\n" ); - return 1; + return -1; } } else { Warning("Error: expected a value after '-threads'\n" ); - return 1; + return -1; } } else if ( !Q_stricmp(argv[i], "-lights" ) ) @@ -2458,7 +2472,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a filepath after '-lights'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-noextra")) @@ -2494,7 +2508,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a scale factor after '-extrasky'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-centersamples")) @@ -2510,7 +2524,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected an angle after '-smooth'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-dlightmap")) @@ -2528,7 +2542,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a value after '-luxeldensity'\n" ); - return 1; + return -1; } } else if( !Q_stricmp( argv[i], "-low" ) ) @@ -2554,7 +2568,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected an angular extent value (0..180) '-softsun'\n" ); - return 1; + return -1; } } else if ( !Q_stricmp( argv[i], "-maxdispsamplesize" ) ) @@ -2566,7 +2580,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning( "Error: expected a sample size after '-maxdispsamplesize'\n" ); - return 1; + return -1; } } else if ( stricmp( argv[i], "-StopOnExit" ) == 0 ) @@ -2583,7 +2597,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else if ( !Q_stricmp( argv[i], CMDLINEOPTION_NOVCONFIG ) ) { } - else if ( !Q_stricmp( argv[i], "-vproject" ) || !Q_stricmp( argv[i], "-game" ) ) + else if ( !Q_stricmp( argv[i], "-vproject" ) || !Q_stricmp( argv[i], "-game" ) || !Q_stricmp( argv[i], "-insert_search_path" ) ) { ++i; } @@ -2607,13 +2621,13 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( maxchop < 1 ) { Warning("Error: expected positive value after '-maxchop'\n" ); - return 1; + return -1; } } else { Warning("Error: expected a value after '-maxchop'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-chop")) @@ -2624,14 +2638,14 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( minchop < 1 ) { Warning("Error: expected positive value after '-chop'\n" ); - return 1; + return -1; } minchop = min( minchop, maxchop ); } else { Warning("Error: expected a value after '-chop'\n" ); - return 1; + return -1; } } else if ( !Q_stricmp( argv[i], "-dispchop" ) ) @@ -2642,13 +2656,13 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( dispchop < 1.0f ) { Warning( "Error: expected positive value after '-dipschop'\n" ); - return 1; + return -1; } } else { Warning( "Error: expected a value after '-dispchop'\n" ); - return 1; + return -1; } } else if ( !Q_stricmp( argv[i], "-disppatchradius" ) ) @@ -2659,13 +2673,13 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( g_MaxDispPatchRadius < 10.0f ) { Warning( "Error: g_MaxDispPatchRadius < 10.0\n" ); - return 1; + return -1; } } else { Warning( "Error: expected a value after '-disppatchradius'\n" ); - return 1; + return -1; } } @@ -2679,7 +2693,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a value after '-scale'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-ambient")) @@ -2693,7 +2707,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected three color values after '-ambient'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-dlight")) @@ -2705,7 +2719,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a value after '-dlight'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-sky")) @@ -2717,7 +2731,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a value after '-sky'\n" ); - return 1; + return -1; } } else if (!Q_stricmp(argv[i],"-notexscale")) @@ -2733,7 +2747,7 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) else { Warning("Error: expected a light threshold after '-coring'\n" ); - return 1; + return -1; } } #endif @@ -2749,13 +2763,17 @@ int ParseCommandLine( int argc, char **argv, bool *onlydetail ) if ( i == argc - 1 && V_stricmp( argv[i], "-mpi_ListParams" ) != 0 ) break; } + else if ( mapArg == -1 ) + { + mapArg = i; + } else { - break; + return -1; } } - return i; + return mapArg; } @@ -2867,7 +2885,6 @@ void PrintUsage( int argc, char **argv ) #endif } - int RunVRAD( int argc, char **argv ) { #if defined(_MSC_VER) && ( _MSC_VER >= 1310 ) @@ -2882,13 +2899,18 @@ int RunVRAD( int argc, char **argv ) bool onlydetail; int i = ParseCommandLine( argc, argv, &onlydetail ); - if (i != argc - 1) + if (i == -1) { PrintUsage( argc, argv ); DeleteCmdLine( argc, argv ); CmdLib_Exit( 1 ); } + // Initialize the filesystem, so additional commandline options can be loaded + Q_StripExtension( argv[ i ], source, sizeof( source ) ); + CmdLib_InitFileSystem( argv[ i ] ); + Q_FileBase( source, source, sizeof( source ) ); + VRAD_LoadBSP( argv[i] ); if ( (! onlydetail) && (! g_bOnlyStaticProps ) ) @@ -2917,11 +2939,6 @@ int VRAD_Main(int argc, char **argv) // This must come first. VRAD_SetupMPI( argc, argv ); - // Initialize the filesystem, so additional commandline options can be loaded - Q_StripExtension( argv[ argc - 1 ], source, sizeof( source ) ); - CmdLib_InitFileSystem( argv[ argc - 1 ] ); - Q_FileBase( source, source, sizeof( source ) ); - #if !defined( _DEBUG ) if ( g_bUseMPI && !g_bMPIMaster ) { diff --git a/mp/src/utils/vrad/vrad_dll.vpc b/mp/src/utils/vrad/vrad_dll.vpc index a1ae67b4..7ebef01d 100644 --- a/mp/src/utils/vrad/vrad_dll.vpc +++ b/mp/src/utils/vrad/vrad_dll.vpc @@ -219,6 +219,7 @@ $Project "Vrad_dll" $Lib tier2 $Lib vmpi $Lib vtf + $Lib "$LIBCOMMON/lzma" } $File "notes.txt" diff --git a/mp/src/utils/vrad_launcher/vrad_launcher.vpc b/mp/src/utils/vrad_launcher/vrad_launcher.vpc index 426647c5..6c1e7b2d 100644 --- a/mp/src/utils/vrad_launcher/vrad_launcher.vpc +++ b/mp/src/utils/vrad_launcher/vrad_launcher.vpc @@ -17,6 +17,11 @@ $Configuration $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" $PrecompiledHeaderFile "$(IntDir)/vrad_launcher.pch" } + + $Linker [$WIN32] + { + $EnableLargeAddresses "Support Addresses Larger Than 2 Gigabytes (/LARGEADDRESSAWARE)" + } } $Project "Vrad_launcher" diff --git a/mp/src/utils/vtf2tga/vtf2tga.cpp b/mp/src/utils/vtf2tga/vtf2tga.cpp index c06999b0..926473c7 100644 --- a/mp/src/utils/vtf2tga/vtf2tga.cpp +++ b/mp/src/utils/vtf2tga/vtf2tga.cpp @@ -187,7 +187,7 @@ int main( int argc, char **argv ) for ( int z = 0; z < iDepth; ++z ) { // Construct output filename - char *pTempNameBuf = (char *)stackalloc( iTGANameLen + 13 ); + char *pTempNameBuf = new char[iTGANameLen + 13];//(char *)stackalloc( iTGANameLen + 13 ); Q_strncpy( pTempNameBuf, pOutFileNameBase, iTGANameLen + 1 ); char *pExt = Q_strrchr( pTempNameBuf, '.' ); if ( pExt ) @@ -306,6 +306,8 @@ int main( int argc, char **argv ) { PFMWrite( ( float * )pDstImage, pTempNameBuf, iWidth, iHeight ); } + + delete[] pTempNameBuf; } } } diff --git a/mp/src/utils/vtfdiff/vtfdiff.cpp b/mp/src/utils/vtfdiff/vtfdiff.cpp index 068cb319..765fb405 100644 --- a/mp/src/utils/vtfdiff/vtfdiff.cpp +++ b/mp/src/utils/vtfdiff/vtfdiff.cpp @@ -102,9 +102,9 @@ void PrintFlags( int flags ) PRNFLAG( TEXTUREFLAGS_DEPTHRENDERTARGET ) PRNFLAG( TEXTUREFLAGS_NODEBUGOVERRIDE ) PRNFLAG( TEXTUREFLAGS_SINGLECOPY ) - PRNFLAG( TEXTUREFLAGS_UNUSED_00080000 ) - PRNFLAG( TEXTUREFLAGS_UNUSED_00100000 ) - PRNFLAG( TEXTUREFLAGS_UNUSED_00200000 ) + PRNFLAG( TEXTUREFLAGS_STAGING_MEMORY ) + PRNFLAG( TEXTUREFLAGS_IMMEDIATE_CLEANUP ) + PRNFLAG( TEXTUREFLAGS_IGNORE_PICMIP ) PRNFLAG( TEXTUREFLAGS_UNUSED_00400000 ) PRNFLAG( TEXTUREFLAGS_NODEPTHBUFFER ) PRNFLAG( TEXTUREFLAGS_UNUSED_01000000 ) diff --git a/mp/src/utils/vvis/vvis.cpp b/mp/src/utils/vvis/vvis.cpp index 0fb61388..42edd0bf 100644 --- a/mp/src/utils/vvis/vvis.cpp +++ b/mp/src/utils/vvis/vvis.cpp @@ -1072,6 +1072,7 @@ int RunVVis( int argc, char **argv ) { char portalfile[1024]; char source[1024]; + char mapFile[1024]; double start, end; @@ -1079,17 +1080,25 @@ int RunVVis( int argc, char **argv ) verbose = false; - Q_StripExtension( argv[ argc - 1 ], source, sizeof( source ) ); - CmdLib_InitFileSystem( argv[ argc - 1 ] ); - - Q_FileBase( source, source, sizeof( source ) ); - LoadCmdLineFromFile( argc, argv, source, "vvis" ); int i = ParseCommandLine( argc, argv ); - // This part is just for VMPI. VMPI's file system needs the basedir in front of all filenames, + CmdLib_InitFileSystem( argv[ argc - 1 ] ); + + // The ExpandPath is just for VMPI. VMPI's file system needs the basedir in front of all filenames, // so we prepend qdir here. - strcpy( source, ExpandPath( source ) ); + + // XXX(johns): Somewhat preserving legacy behavior here to avoid changing tool behavior, there's no specific rhyme + // or reason to this. We get just the base name we were passed, discarding any directory or extension + // information. We then ExpandPath() it (see VMPI comment above), and tack on .bsp for the file access + // parts. + V_FileBase( argv[ argc - 1 ], mapFile, sizeof( mapFile ) ); + V_strncpy( mapFile, ExpandPath( mapFile ), sizeof( mapFile ) ); + V_strncat( mapFile, ".bsp", sizeof( mapFile ) ); + + // Source is just the mapfile without an extension at this point... + V_strncpy( source, mapFile, sizeof( mapFile ) ); + V_StripExtension( source, source, sizeof( source ) ); if (i != argc - 1) { @@ -1114,13 +1123,11 @@ int RunVVis( int argc, char **argv ) { SetLowPriority(); } - + ThreadSetDefault (); - char targetPath[1024]; - GetPlatformMapPath( source, targetPath, 0, 1024 ); - Msg ("reading %s\n", targetPath); - LoadBSPFile (targetPath); + Msg ("reading %s\n", mapFile); + LoadBSPFile (mapFile); if (numnodes == 0 || numfaces == 0) Error ("Empty map"); ParseEntities (); @@ -1151,7 +1158,7 @@ int RunVVis( int argc, char **argv ) Q_StripExtension( portalfile, portalfile, sizeof( portalfile ) ); } strcat (portalfile, ".prt"); - + Msg ("reading %s\n", portalfile); LoadPortals (portalfile); @@ -1162,17 +1169,17 @@ int RunVVis( int argc, char **argv ) CalcPAS (); // We need a mapping from cluster to leaves, since the PVS - // deals with clusters for both CalcVisibleFogVolumes and + // deals with clusters for both CalcVisibleFogVolumes and BuildClusterTable(); CalcVisibleFogVolumes(); CalcDistanceFromLeavesToWater(); - visdatasize = vismap_p - dvisdata; + visdatasize = vismap_p - dvisdata; Msg ("visdatasize:%i compressed from %i\n", visdatasize, originalvismapsize*2); - Msg ("writing %s\n", targetPath); - WriteBSPFile (targetPath); + Msg ("writing %s\n", mapFile); + WriteBSPFile (mapFile); } else { @@ -1187,9 +1194,9 @@ int RunVVis( int argc, char **argv ) CalcVisTrace (); WritePortalTrace(source); } - + end = Plat_FloatTime(); - + char str[512]; GetHourMinuteSecondsString( (int)( end - start ), str, sizeof( str ) ); Msg( "%s elapsed\n", str ); diff --git a/mp/src/utils/vvis/vvis_dll.vpc b/mp/src/utils/vvis/vvis_dll.vpc index 43001443..211719ff 100644 --- a/mp/src/utils/vvis/vvis_dll.vpc +++ b/mp/src/utils/vvis/vvis_dll.vpc @@ -97,5 +97,6 @@ $Project "Vvis_dll" $Lib mathlib $Lib tier2 $Lib vmpi + $Lib "$LIBCOMMON/lzma" } } diff --git a/mp/src/utils/vvis_launcher/vvis_launcher.vpc b/mp/src/utils/vvis_launcher/vvis_launcher.vpc index f3c5e958..71713400 100644 --- a/mp/src/utils/vvis_launcher/vvis_launcher.vpc +++ b/mp/src/utils/vvis_launcher/vvis_launcher.vpc @@ -18,6 +18,11 @@ $Configuration $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" $PrecompiledHeaderFile "Debug/vvis_launcher.pch" } + + $Linker [$WIN32] + { + $EnableLargeAddresses "Support Addresses Larger Than 2 Gigabytes (/LARGEADDRESSAWARE)" + } } $Project "Vvis_launcher" diff --git a/mp/src/vgui2/vgui_controls/AnimationController.cpp b/mp/src/vgui2/vgui_controls/AnimationController.cpp index 6da33a38..b8780a89 100644 --- a/mp/src/vgui2/vgui_controls/AnimationController.cpp +++ b/mp/src/vgui2/vgui_controls/AnimationController.cpp @@ -68,6 +68,8 @@ AnimationController::AnimationController(Panel *parent) : BaseClass(parent, NULL m_sWide = g_ScriptSymbols.AddString("wide"); m_sTall = g_ScriptSymbols.AddString("tall"); + m_sModelPos = g_ScriptSymbols.AddString( "model_pos" ); + m_flCurrentTime = 0.0f; } @@ -508,6 +510,34 @@ bool AnimationController::ParseScriptFile(char *pMem, int length) pMem = ParseFile(pMem, token, NULL); animCmd.cmdData.runEvent.timeDelay = (float)atof(token); } + else if (!stricmp(token, "runeventchild")) + { + animCmd.commandType = CMD_RUNEVENTCHILD; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.event = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } + else if (!stricmp(token, "firecommand")) + { + animCmd.commandType = CMD_FIRECOMMAND; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + } + else if (!stricmp(token, "setvisible")) + { + animCmd.commandType = CMD_SETVISIBLE; + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable = g_ScriptSymbols.AddString(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.variable2 = atoi(token); + pMem = ParseFile(pMem, token, NULL); + animCmd.cmdData.runEvent.timeDelay = (float)atof(token); + } else if (!stricmp(token, "stopevent")) { animCmd.commandType = CMD_STOPEVENT; @@ -659,9 +689,11 @@ void AnimationController::UpdatePostedMessages(bool bRunToCompletion) case CMD_RUNEVENT: { RanEvent_t curEvent; + curEvent.pParent = NULL; curEvent.event = msg.event; - curEvent.pParent = msg.parent.Get(); + curEvent.pParent = msg.parent.Get(); + // run the event, but only if we haven't already run it this frame, for this parent if (!eventsRanThisFrame.HasElement(curEvent)) { @@ -670,6 +702,37 @@ void AnimationController::UpdatePostedMessages(bool bRunToCompletion) } } break; + case CMD_RUNEVENTCHILD: + { + RanEvent_t curEvent; + curEvent.pParent = NULL; + curEvent.event = msg.event; + + curEvent.pParent = msg.parent.Get()->FindChildByName( g_ScriptSymbols.String(msg.variable) ); + msg.parent = curEvent.pParent; + + // run the event, but only if we haven't already run it this frame, for this parent + if (!eventsRanThisFrame.HasElement(curEvent)) + { + eventsRanThisFrame.AddToTail(curEvent); + RunCmd_RunEvent(msg); + } + } + break; + case CMD_FIRECOMMAND: + { + msg.parent->OnCommand( g_ScriptSymbols.String(msg.variable) ); + } + break; + case CMD_SETVISIBLE: + { + Panel* pPanel = msg.parent.Get()->FindChildByName( g_ScriptSymbols.String(msg.variable) ); + if ( pPanel ) + { + pPanel->SetVisible( msg.variable2 == 1 ); + } + } + break; case CMD_STOPEVENT: RunCmd_StopEvent(msg); break; @@ -946,6 +1009,63 @@ bool AnimationController::StartAnimationSequence(Panel *pWithinParent, const cha return true; } +//----------------------------------------------------------------------------- +// Purpose: stops an animation sequence script +//----------------------------------------------------------------------------- +bool AnimationController::StopAnimationSequence( Panel *pWithinParent, const char *sequenceName ) +{ + Assert( pWithinParent ); + + // lookup the symbol for the name + UtlSymId_t seqName = g_ScriptSymbols.Find( sequenceName ); + if (seqName == UTL_INVAL_SYMBOL) + return false; + + // remove the existing command from the queue + RemoveQueuedAnimationCommands( seqName, pWithinParent ); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Runs a custom command from code, not from a script file +//----------------------------------------------------------------------------- +void AnimationController::CancelAnimationsForPanel( Panel *pWithinParent ) +{ + // Msg("Removing queued anims for sequence %s\n", g_ScriptSymbols.String(seqName)); + + // remove messages posted by this sequence + // if pWithinParent is specified, remove only messages under that parent + { + for (int i = 0; i < m_PostedMessages.Count(); i++) + { + if ( m_PostedMessages[i].parent == pWithinParent ) + { + m_PostedMessages.Remove(i); + --i; + } + } + } + + // remove all animations + // if pWithinParent is specified, remove only animations under that parent + for (int i = 0; i < m_ActiveAnimations.Count(); i++) + { + Panel *animPanel = m_ActiveAnimations[i].panel; + + if ( !animPanel ) + continue; + + Panel *foundPanel = pWithinParent->FindChildByName(animPanel->GetName(),true); + + if ( foundPanel != animPanel ) + continue; + + m_ActiveAnimations.Remove(i); + --i; + } +} + //----------------------------------------------------------------------------- // Purpose: Runs a custom command from code, not from a script file //----------------------------------------------------------------------------- diff --git a/mp/src/vgui2/vgui_controls/ComboBox.cpp b/mp/src/vgui2/vgui_controls/ComboBox.cpp index f8be274b..e7d0f86f 100644 --- a/mp/src/vgui2/vgui_controls/ComboBox.cpp +++ b/mp/src/vgui2/vgui_controls/ComboBox.cpp @@ -234,7 +234,7 @@ void ComboBox::RemoveAll() //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- -int ComboBox::GetItemCount() +int ComboBox::GetItemCount() const { return m_pDropDown->GetItemCount(); } diff --git a/mp/src/vgui2/vgui_controls/HTML.cpp b/mp/src/vgui2/vgui_controls/HTML.cpp index a35ef1b7..1a1ca440 100644 --- a/mp/src/vgui2/vgui_controls/HTML.cpp +++ b/mp/src/vgui2/vgui_controls/HTML.cpp @@ -26,9 +26,6 @@ using namespace vgui; - -const int k_nMaxCustomCursors = 2; // the max number of custom cursors we keep cached PER html control - //----------------------------------------------------------------------------- // Purpose: A simple passthrough panel to render the border onto the HTML widget //----------------------------------------------------------------------------- @@ -48,54 +45,6 @@ private: HTML *m_pHTML; }; - -//----------------------------------------------------------------------------- -// Purpose: a vgui container for popup menus displayed by a control, only 1 menu for any control can be visible at a time -//----------------------------------------------------------------------------- -class HTMLComboBoxHost : public vgui::EditablePanel -{ - DECLARE_CLASS_SIMPLE( HTMLComboBoxHost, EditablePanel ); -public: - HTMLComboBoxHost( HTML *parent, const char *panelName ) : EditablePanel( parent, panelName ) - { - m_pParent = parent; - MakePopup(false); - } - ~HTMLComboBoxHost() {} - - virtual void PaintBackground(); - - virtual void OnMousePressed(MouseCode code); - virtual void OnMouseReleased(MouseCode code); - virtual void OnCursorMoved(int x,int y); - virtual void OnMouseDoublePressed(MouseCode code); - virtual void OnKeyTyped(wchar_t unichar); - virtual void OnKeyCodeTyped(KeyCode code); - virtual void OnKeyCodeReleased(KeyCode code); - virtual void OnMouseWheeled(int delta); - - virtual void OnKillFocus() - { - if ( vgui::input()->GetFocus() != m_pParent->GetVPanel() ) // if its not our parent trying to steal focus - { - BaseClass::OnKillFocus(); - if ( m_pParent ) - m_pParent->HidePopup(); - } - } - - virtual void PerformLayout() - { - // no op the perform layout as we just render the html controls popup texture into it - // we don't want the menu logic trying to play with its size - } - - -private: - HTML *m_pParent; -}; - - //----------------------------------------------------------------------------- // Purpose: container class for any external popup windows the browser requests //----------------------------------------------------------------------------- @@ -163,15 +112,12 @@ private: //----------------------------------------------------------------------------- HTML::HTML(Panel *parent, const char *name, bool allowJavaScript, bool bPopupWindow) : Panel(parent, name), m_NeedsPaint( this, &HTML::BrowserNeedsPaint ), -m_ComboNeedsPaint( this, &HTML::BrowserComboNeedsPaint ), m_StartRequest( this, &HTML::BrowserStartRequest ), m_URLChanged( this, &HTML::BrowserURLChanged ), m_FinishedRequest( this, &HTML::BrowserFinishedRequest ), -m_ShowPopup( this, &HTML::BrowserShowPopup ), -m_HidePopup( this, &HTML::BrowserHidePopup ), -m_SizePopup( this, &HTML::BrowserSizePopup ), m_LinkInNewTab( this, &HTML::BrowserOpenNewTab ), m_ChangeTitle( this, &HTML::BrowserSetHTMLTitle ), +m_NewWindow( this, &HTML::BrowserPopupHTMLWindow ), m_FileLoadDialog( this, &HTML::BrowserFileLoadDialog ), m_SearchResults( this, &HTML::BrowserSearchResults ), m_CloseBrowser( this, &HTML::BrowserClose ), @@ -181,7 +127,6 @@ m_LinkAtPosResp( this, &HTML::BrowserLinkAtPositionResponse ), m_JSAlert( this, &HTML::BrowserJSAlert ), m_JSConfirm( this, &HTML::BrowserJSConfirm ), m_CanGoBackForward( this, &HTML::BrowserCanGoBackandForward ), -m_NewWindow( this, &HTML::BrowserPopupHTMLWindow ), m_SetCursor( this, &HTML::BrowserSetCursor ), m_StatusText( this, &HTML::BrowserStatusText ), m_ShowTooltip( this, &HTML::BrowserShowToolTip ), @@ -189,7 +134,6 @@ m_UpdateTooltip( this, &HTML::BrowserUpdateToolTip ), m_HideTooltip( this, &HTML::BrowserHideToolTip ) { m_iHTMLTextureID = 0; - m_iComboBoxTextureID = 0; m_bCanGoBack = false; m_bCanGoForward = false; m_bInFind = false; @@ -201,7 +145,7 @@ m_HideTooltip( this, &HTML::BrowserHideToolTip ) m_pInteriorPanel = new HTMLInterior( this ); SetPostChildPaintEnabled( true ); - m_unBrowserHandle = INVALID_HTTMLBROWSER; + m_unBrowserHandle = INVALID_HTMLBROWSER; m_SteamAPIContext.Init(); if ( m_SteamAPIContext.SteamHTMLSurface() ) { @@ -233,10 +177,6 @@ m_HideTooltip( this, &HTML::BrowserHideToolTip ) m_pFindBar = new HTML::CHTMLFindBar( this ); m_pFindBar->SetZPos( 2 ); m_pFindBar->SetVisible( false ); - - m_pComboBoxHost = new HTMLComboBoxHost( this, "ComboBoxHost" ); - m_pComboBoxHost->SetPaintBackgroundEnabled( true ); - m_pComboBoxHost->SetVisible( false ); m_pContextMenu = new Menu( this, "contextmenu" ); m_pContextMenu->AddMenuItem( "#vgui_HTMLBack", new KeyValues( "Command", "command", "back" ), this ); @@ -349,36 +289,6 @@ void HTML::Paint() } } - -//----------------------------------------------------------------------------- -// Purpose: paint the combo box texture if we have one -//----------------------------------------------------------------------------- -void HTML::PaintComboBox() -{ - BaseClass::Paint(); - if ( m_iComboBoxTextureID != 0 ) - { - surface()->DrawSetTexture( m_iComboBoxTextureID ); - surface()->DrawSetColor( Color( 255, 255, 255, 255 ) ); - int tw = m_allocedComboBoxWidth; - int tt = m_allocedComboBoxHeight; - surface()->DrawTexturedRect( 0, 0, tw, tt ); - } - -} - - -//----------------------------------------------------------------------------- -// Purpose: overrides panel class, paints a texture of the HTML window as a background -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::PaintBackground() -{ - BaseClass::PaintBackground(); - - m_pParent->PaintComboBox(); -} - - //----------------------------------------------------------------------------- // Purpose: causes a repaint when the layout changes //----------------------------------------------------------------------------- @@ -431,11 +341,6 @@ void HTML::OnMove() // tell cef where we are on the screen so plugins can correctly render int nPanelAbsX, nPanelAbsY; ipanel()->GetAbsPos( GetVPanel(), nPanelAbsX, nPanelAbsY ); - - if ( m_pComboBoxHost && m_pComboBoxHost->IsVisible() ) - { - m_pComboBoxHost->SetVisible( false ); - } } @@ -452,7 +357,7 @@ void HTML::OpenURL(const char *URL, const char *postData, bool force) //----------------------------------------------------------------------------- void HTML::PostURL(const char *URL, const char *pchPostData, bool force) { - if ( m_unBrowserHandle == INVALID_HTTMLBROWSER ) + if ( m_unBrowserHandle == INVALID_HTMLBROWSER ) { m_sPendingURLLoad = URL; m_sPendingPostData = pchPostData; @@ -674,7 +579,7 @@ void HTML::OnMouseReleased(MouseCode code) input()->SetMouseCapture( NULL ); input()->SetCursorOveride( 0 ); - if ( !m_sDragURL.IsEmpty() && input()->GetMouseOver() != GetVPanel() && input()->GetMouseOver() != NULL ) + if ( !m_sDragURL.IsEmpty() && input()->GetMouseOver() != GetVPanel() && input()->GetMouseOver() ) { // post the text as a drag drop to the target panel KeyValuesAD kv( "DragDrop" ); @@ -709,7 +614,7 @@ void HTML::OnCursorMoved(int x,int y) } else if ( !m_sDragURL.IsEmpty() ) { - if ( input()->GetMouseOver() == NULL ) + if ( !input()->GetMouseOver() ) { // we're not over any vgui window, switch to the OS implementation of drag/drop // BR FIXME @@ -749,18 +654,18 @@ int GetKeyModifiers() // Any time a key is pressed reset modifier list as well int nModifierCodes = 0; if (vgui::input()->IsKeyDown( KEY_LCONTROL ) || vgui::input()->IsKeyDown( KEY_RCONTROL )) - nModifierCodes |= ISteamHTMLSurface::eHTMLKeyModifier_CrtlDown; + nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_CtrlDown; if (vgui::input()->IsKeyDown( KEY_LALT ) || vgui::input()->IsKeyDown( KEY_RALT )) - nModifierCodes |= ISteamHTMLSurface::eHTMLKeyModifier_AltDown; + nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_AltDown; if (vgui::input()->IsKeyDown( KEY_LSHIFT ) || vgui::input()->IsKeyDown( KEY_RSHIFT )) - nModifierCodes |= ISteamHTMLSurface::eHTMLKeyModifier_ShiftDown; + nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_ShiftDown; #ifdef OSX // for now pipe through the cmd-key to be like the control key so we get copy/paste if (vgui::input()->IsKeyDown( KEY_LWIN ) || vgui::input()->IsKeyDown( KEY_RWIN )) - nModifierCodes |= ISteamHTMLSurface::eHTMLKeyModifier_CrtlDown; + nModifierCodes |= ISteamHTMLSurface::k_eHTMLKeyModifier_CtrlDown; #endif return nModifierCodes; @@ -925,8 +830,8 @@ void HTML::OnKeyCodeReleased(KeyCode code) // Purpose: scrolls the vertical scroll bar on a web page //----------------------------------------------------------------------------- void HTML::OnMouseWheeled(int delta) -{ - if (_vbar && ( ( m_pComboBoxHost && !m_pComboBoxHost->IsVisible() ) ) ) +{ + if (_vbar ) { int val = _vbar->GetValue(); val -= (delta * 100.0/3.0 ); // 100 for every 3 lines matches chromes code @@ -954,7 +859,7 @@ void HTML::AddCustomURLHandler(const char *customProtocolName, vgui::Panel *targ //----------------------------------------------------------------------------- void HTML::BrowserResize() { - if (m_unBrowserHandle == INVALID_HTTMLBROWSER) + if (m_unBrowserHandle == INVALID_HTMLBROWSER) return; int w,h; @@ -1120,16 +1025,12 @@ void HTML::OnSetFocus() //----------------------------------------------------------------------------- void HTML::OnKillFocus() { - if ( vgui::input()->GetFocus() != m_pComboBoxHost->GetVPanel() ) // if its not the menu stealing our focus - BaseClass::OnKillFocus(); + BaseClass::OnKillFocus(); // Don't clear the actual html focus if a context menu is what took focus if ( m_pContextMenu->HasFocus() ) return; - if ( m_pComboBoxHost->HasFocus() ) - return; - if (m_SteamAPIContext.SteamHTMLSurface()) m_SteamAPIContext.SteamHTMLSurface()->SetKeyFocus( m_unBrowserHandle, false ); } @@ -1279,83 +1180,6 @@ void HTML::OnTextChanged( Panel *pPanel ) Find( rgchText ); } - -//----------------------------------------------------------------------------- -// Purpose: passes mouse clicks to the control -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnMousePressed(MouseCode code) -{ - m_pParent->OnMousePressed(code); -} - - -//----------------------------------------------------------------------------- -// Purpose: passes mouse up events -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnMouseReleased(MouseCode code) -{ - m_pParent->OnMouseReleased(code); -} - - -//----------------------------------------------------------------------------- -// Purpose: keeps track of where the cursor is -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnCursorMoved(int x,int y) -{ - // Only do this when we are over the current panel - if ( vgui::input()->GetMouseOver() == GetVPanel() ) - { - m_pParent->OnHTMLMouseMoved( x, y ); - } -} - - -//----------------------------------------------------------------------------- -// Purpose: passes double click events to the browser -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnMouseDoublePressed(MouseCode code) -{ - m_pParent->OnMouseDoublePressed(code); -} - - -//----------------------------------------------------------------------------- -// Purpose: passes key presses to the browser (we don't current do this) -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnKeyTyped(wchar_t unichar) -{ - m_pParent->OnKeyTyped(unichar); -} - - -//----------------------------------------------------------------------------- -// Purpose: passes key presses to the browser -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnKeyCodeTyped(KeyCode code) -{ - m_pParent->OnKeyCodeTyped(code); -} - - -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnKeyCodeReleased(KeyCode code) -{ - m_pParent->OnKeyCodeReleased(code); -} - - -//----------------------------------------------------------------------------- -// Purpose: scrolls the vertical scroll bar on a web page -//----------------------------------------------------------------------------- -void HTMLComboBoxHost::OnMouseWheeled(int delta) -{ - m_pParent->OnMouseWheeled( delta ); -} - - //----------------------------------------------------------------------------- // Purpose: helper class for the find bar //----------------------------------------------------------------------------- @@ -1441,43 +1265,6 @@ void HTML::BrowserNeedsPaint( HTML_NeedsPaint_t *pCallback ) Repaint(); } - -//----------------------------------------------------------------------------- -// Purpose: we have a new texture to update -//----------------------------------------------------------------------------- -void HTML::BrowserComboNeedsPaint( HTML_ComboNeedsPaint_t *pCallback ) -{ - if ( m_pComboBoxHost->IsVisible() ) - { - int tw = 0, tt = 0; - // update the combo box texture also - if ( m_iComboBoxTextureID != 0 ) - { - tw = m_allocedComboBoxWidth; - tt = m_allocedComboBoxHeight; - } - - if ( m_iComboBoxTextureID == 0 || tw != (int)pCallback->unWide || tt != (int)pCallback->unTall ) - { - if ( m_iComboBoxTextureID != 0 ) - surface()->DeleteTextureByID( m_iComboBoxTextureID ); - - // if the dimensions changed we also need to re-create the texture ID to support the overlay properly (it won't resize a texture on the fly, this is the only control that needs - // to so lets have a tiny bit more code here to support that) - m_iComboBoxTextureID = surface()->CreateNewTextureID( true ); - surface()->DrawSetTextureRGBAEx( m_iComboBoxTextureID, (const unsigned char *)pCallback->pBGRA, pCallback->unWide, pCallback->unTall, IMAGE_FORMAT_BGRA8888 ); - m_allocedComboBoxWidth = (int)pCallback->unWide; - m_allocedComboBoxHeight = (int)pCallback->unTall; - } - else - { - // same size texture, just bits changing in it, lets twiddle - surface()->DrawUpdateRegionTextureRGBA( m_iComboBoxTextureID, 0, 0, (const unsigned char *)pCallback->pBGRA, pCallback->unWide, pCallback->unTall, IMAGE_FORMAT_BGRA8888 ); - } - } -} - - //----------------------------------------------------------------------------- // Purpose: browser wants to start loading this url, do we let it? //----------------------------------------------------------------------------- @@ -1579,45 +1366,6 @@ void HTML::BrowserFinishedRequest( HTML_FinishedRequest_t *pCmd ) OnFinishRequest( pCmd->pchURL, pCmd->pchPageTitle, mapHeaders ); } - -//----------------------------------------------------------------------------- -// Purpose: show a popup dialog -//----------------------------------------------------------------------------- -void HTML::BrowserShowPopup( HTML_ShowPopup_t *pCmd ) -{ - m_pComboBoxHost->SetVisible( true ); -} - - -//----------------------------------------------------------------------------- -// Purpose: hide the popup -//----------------------------------------------------------------------------- -void HTML::HidePopup() -{ - m_pComboBoxHost->SetVisible( false ); -} - - -//----------------------------------------------------------------------------- -// Purpose: browser wants us to hide a popup -//----------------------------------------------------------------------------- -void HTML::BrowserHidePopup( HTML_HidePopup_t *pCmd ) -{ - HidePopup(); -} - - -//----------------------------------------------------------------------------- -// Purpose: browser wants us to position a popup -//----------------------------------------------------------------------------- -void HTML::BrowserSizePopup( HTML_SizePopup_t *pCmd ) -{ - int nAbsX, nAbsY; - ipanel()->GetAbsPos( GetVPanel(), nAbsX, nAbsY ); - m_pComboBoxHost->SetBounds( pCmd->unX + 1 + nAbsX, pCmd->unY+ nAbsY, pCmd->unWide, pCmd->unTall ); -} - - //----------------------------------------------------------------------------- // Purpose: browser wants to open a new tab //----------------------------------------------------------------------------- @@ -1627,9 +1375,8 @@ void HTML::BrowserOpenNewTab( HTML_OpenLinkInNewTab_t *pCmd ) // Not suppored by default, if a child class overrides us and knows how to handle tabs, then it can do this. } - //----------------------------------------------------------------------------- -// Purpose: display a new html window +// Purpose: display a new html window //----------------------------------------------------------------------------- void HTML::BrowserPopupHTMLWindow( HTML_NewWindow_t *pCmd ) { diff --git a/mp/src/vgui2/vgui_controls/Label.cpp b/mp/src/vgui2/vgui_controls/Label.cpp index 776c8c6e..2178f390 100644 --- a/mp/src/vgui2/vgui_controls/Label.cpp +++ b/mp/src/vgui2/vgui_controls/Label.cpp @@ -361,8 +361,14 @@ void Label::SetTextInset(int xInset, int yInset) //----------------------------------------------------------------------------- void Label::GetTextInset(int *xInset, int *yInset ) { - *xInset = _textInset[0]; - *yInset = _textInset[1]; + if ( xInset ) + { + *xInset = _textInset[0]; + } + if ( yInset ) + { + *yInset = _textInset[1]; + } } //----------------------------------------------------------------------------- diff --git a/mp/src/vgui2/vgui_controls/Menu.cpp b/mp/src/vgui2/vgui_controls/Menu.cpp index 695d3523..9978824e 100644 --- a/mp/src/vgui2/vgui_controls/Menu.cpp +++ b/mp/src/vgui2/vgui_controls/Menu.cpp @@ -2107,7 +2107,7 @@ void Menu::ActivateItemByRow(int row) //----------------------------------------------------------------------------- // Purpose: Return the number of items currently in the menu list //----------------------------------------------------------------------------- -int Menu::GetItemCount() +int Menu::GetItemCount() const { return m_MenuItems.Count(); } @@ -2701,3 +2701,33 @@ void Menu::Validate( CValidator &validator, char *pchName ) validator.Pop(); } #endif // DBGFLAG_VALIDATE + + +MenuBuilder::MenuBuilder( Menu *pMenu, Panel *pActionTarget ) + : m_pMenu( pMenu ) + , m_pActionTarget( pActionTarget ) + , m_pszLastCategory( NULL ) +{} + +MenuItem* MenuBuilder::AddMenuItem( const char *pszButtonText, const char *pszCommand, const char *pszCategoryName ) +{ + AddSepratorIfNeeded( pszCategoryName ); + return m_pMenu->GetMenuItem( m_pMenu->AddMenuItem( pszButtonText, new KeyValues( pszCommand ), m_pActionTarget ) ); +} + +MenuItem* MenuBuilder::AddCascadingMenuItem( const char *pszButtonText, Menu *pSubMenu, const char *pszCategoryName ) +{ + AddSepratorIfNeeded( pszCategoryName ); + return m_pMenu->GetMenuItem( m_pMenu->AddCascadingMenuItem( pszButtonText, m_pActionTarget, pSubMenu ) ); +} + +void MenuBuilder::AddSepratorIfNeeded( const char *pszCategoryName ) +{ + // Add a separator if the categories are different + if ( m_pszLastCategory && V_stricmp( pszCategoryName, m_pszLastCategory ) != 0 ) + { + m_pMenu->AddSeparator(); + } + + m_pszLastCategory = pszCategoryName; +} diff --git a/mp/src/vgui2/vgui_controls/Panel.cpp b/mp/src/vgui2/vgui_controls/Panel.cpp index 499296d9..5291c437 100644 --- a/mp/src/vgui2/vgui_controls/Panel.cpp +++ b/mp/src/vgui2/vgui_controls/Panel.cpp @@ -40,6 +40,7 @@ #include "mempool.h" #include "filesystem.h" #include "tier0/icommandline.h" +#include "tier0/minidump.h" #include "tier0/vprof.h" @@ -50,7 +51,38 @@ using namespace vgui; #define TRIPLE_PRESS_MSEC 300 +const char *g_PinCornerStrings [] = +{ + "PIN_TOPLEFT", + "PIN_TOPRIGHT", + "PIN_BOTTOMLEFT", + "PIN_BOTTOMRIGHT", + "PIN_CENTER_TOP", + "PIN_CENTER_RIGHT", + "PIN_CENTER_BOTTOM", + "PIN_CENTER_LEFT", +}; + +COMPILE_TIME_ASSERT( Panel::PIN_LAST == ARRAYSIZE( g_PinCornerStrings ) ); + +static const char *COM_GetModDirectory() +{ + static char modDir[MAX_PATH]; + if ( Q_strlen( modDir ) == 0 ) + { + const char *gamedir = CommandLine()->ParmValue("-game", CommandLine()->ParmValue( "-defaultgamedir", "hl2" ) ); + Q_strncpy( modDir, gamedir, sizeof(modDir) ); + if ( strchr( modDir, '/' ) || strchr( modDir, '\\' ) ) + { + Q_StripLastDir( modDir, sizeof(modDir) ); + int dirlen = Q_strlen( modDir ); + Q_strncpy( modDir, gamedir + dirlen, sizeof(modDir) - dirlen ); + } + } + + return modDir; +} extern int GetBuildModeDialogCount(); static char *CopyString( const char *in ) @@ -64,6 +96,13 @@ static char *CopyString( const char *in ) return n; } +#ifdef STAGING_ONLY +ConVar tf_strict_mouse_up_events( "tf_strict_mouse_up_events", "0", FCVAR_ARCHIVE, "Only allow Mouse-Release events to happens on panels we also Mouse-Downed in" ); +#endif + +// Temporary convar to help debug why the MvMVictoryMannUpPanel TabContainer is sometimes way off to the left. +ConVar tf_debug_tabcontainer( "tf_debug_tabcontainer", "0", FCVAR_HIDDEN, "Spew TabContainer dimensions." ); + #if defined( VGUI_USEDRAGDROP ) //----------------------------------------------------------------------------- // Purpose: @@ -370,6 +409,8 @@ KeyBindingContextHandle_t Panel::CreateKeyBindingsContext( char const *filename, return g_KBMgr.CreateContext( filename, pathID ); } +COMPILE_TIME_ASSERT( ( MOUSE_MIDDLE - MOUSE_LEFT ) == 2 ); +Panel* Panel::m_sMousePressedPanels[] = { NULL, NULL, NULL }; //----------------------------------------------------------------------------- // Purpose: static method @@ -722,7 +763,6 @@ void Panel::Init( int x, int y, int wide, int tall ) m_bForceStereoRenderToFrameBuffer = false; } - //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- @@ -732,7 +772,7 @@ Panel::~Panel() if ( !m_bToolTipOverridden ) { if ( m_pTooltips ) - { + { delete m_pTooltips; } } @@ -785,6 +825,13 @@ Panel::~Panel() #if defined( VGUI_USEDRAGDROP ) delete m_pDragDrop; #endif // VGUI_USEDRAGDROP + +#if defined( VGUI_PANEL_VERIFY_DELETES ) + // Zero out our vtbl pointer. This should hopefully help us catch bad guys using + // this panel after it has been deleted. + uintp *panel_vtbl = (uintp *)this; + *panel_vtbl = NULL; +#endif } //----------------------------------------------------------------------------- @@ -864,7 +911,7 @@ const char *Panel::GetClassName() //----------------------------------------------------------------------------- void Panel::SetPos(int x, int y) { - if (!CommandLine()->FindParm("-hushasserts")) + if ( !HushAsserts() ) { Assert( abs(x) < 32768 && abs(y) < 32768 ); } @@ -879,6 +926,26 @@ void Panel::GetPos(int &x, int &y) ipanel()->GetPos(GetVPanel(), x, y); } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int Panel::GetXPos() +{ + int x,y; + GetPos( x, y ); + return x; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int Panel::GetYPos() +{ + int x,y; + GetPos( x, y ); + return y; +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -1063,6 +1130,15 @@ void Panel::Think() OnThink(); } +void Panel::OnChildSettingsApplied( KeyValues *pInResourceData, Panel *pChild ) +{ + Panel* pParent = GetParent(); + if( pParent ) + { + pParent->OnChildSettingsApplied( pInResourceData, pChild ); + } +} + //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -1577,7 +1653,6 @@ void Panel::CallParentFunction(KeyValues *message) } } - //----------------------------------------------------------------------------- // Purpose: if set to true, panel automatically frees itself when parent is deleted //----------------------------------------------------------------------------- @@ -1867,6 +1942,17 @@ void Panel::InternalMousePressed(int code) } #endif +#ifdef STAGING_ONLY + const char *pGameDir = COM_GetModDirectory(); + if ( Q_stristr( pGameDir, "tf" ) ) + { + if ( code >= MOUSE_LEFT && code <= MOUSE_MIDDLE ) + { + m_sMousePressedPanels[ code - MOUSE_LEFT ] = this; + } + } +#endif + Panel *pMouseHandler = m_hMouseEventHandler.Get(); if ( pMouseHandler ) { @@ -2001,6 +2087,26 @@ void Panel::InternalMouseReleased(int code) } } +#ifdef STAGING_ONLY + const char *pGameDir = COM_GetModDirectory(); + if ( Q_stristr( pGameDir, "tf" ) && tf_strict_mouse_up_events.GetBool() ) + { + // Only allow mouse release events to go to panels that we also + // first clicked into + if ( code >= MOUSE_LEFT && code <= MOUSE_MIDDLE ) + { + const int nIndex = code - MOUSE_LEFT; + Panel* pPressedPanel = m_sMousePressedPanels[ nIndex ]; + m_sMousePressedPanels[ nIndex ] = NULL; // Clear out pressed panel + if ( pPressedPanel != this ) + { + OnMouseMismatchedRelease( (MouseCode)code, pPressedPanel ); + return; + } + } + } +#endif + OnMouseReleased((MouseCode)code); } @@ -2951,6 +3057,10 @@ void Panel::OnMouseReleased(MouseCode code) { } +void Panel::OnMouseMismatchedRelease( MouseCode code, Panel* pPressedPanel ) +{ +} + void Panel::OnMouseWheeled(int delta) { CallParentFunction(new KeyValues("MouseWheeled", "delta", delta)); @@ -4281,6 +4391,7 @@ int Panel::ComputePos( const char *pszInput, int &nPos, const int& nSize, const const int nFlagProportionalParent = bX ? BUILDMODE_SAVE_XPOS_PROPORTIONAL_PARENT : BUILDMODE_SAVE_YPOS_PROPORTIONAL_PARENT; int nFlags = 0; + int nPosDelta = 0; if ( pszInput ) { // look for alignment flags @@ -4319,7 +4430,6 @@ int Panel::ComputePos( const char *pszInput, int &nPos, const int& nSize, const flProportion = (float)nPos / (float)nOldPos; } - int nPosDelta = 0; if ( nFlags & nFlagProportionalSlef ) { nPosDelta = nSize * flPos; @@ -4348,9 +4458,40 @@ int Panel::ComputePos( const char *pszInput, int &nPos, const int& nSize, const } } + if ( tf_debug_tabcontainer.GetBool() && !Q_stricmp( "TabContainer", GetName() ) ) + { + Msg( "TabContainer nFlags:%x nPos:%d nParentSize:%d nPosDelta:%d nSize:%d GetParent:%p (%s) pszInput:'%s'\n", + nFlags, nPos, nParentSize, nPosDelta, nSize, GetParent(), GetParent() ? GetParent()->GetName() : "??", + pszInput ? pszInput : "??" ); + } + return nFlags; } +Panel::PinCorner_e GetPinCornerFromString( const char* pszCornerName ) +{ + if ( pszCornerName == NULL ) + { + return Panel::PIN_TOPLEFT; + } + + // Optimize for all the old entries of a single digit + if ( strlen( pszCornerName ) == 1 ) + { + return (Panel::PinCorner_e)atoi( pszCornerName ); + } + + for( int i=0; iGetInt( "actionsignallevel", -1 ); + if ( nActionSignalLevel != -1 ) + { + Panel *pActionSignalTarget = this; + while( nActionSignalLevel-- ) + { + pActionSignalTarget = pActionSignalTarget->GetParent(); + } + AddActionSignalTarget( pActionSignalTarget ); + } + // check to see if we need to render to the frame buffer even if // stereo mode is trying to render all of the ui to a render target m_bForceStereoRenderToFrameBuffer = inResourceData->GetBool( "ForceStereoRenderToFrameBuffer", false ); @@ -4640,8 +4794,8 @@ void Panel::ApplySettings(KeyValues *inResourceData) //============================================================================= const char *pszSiblingName = inResourceData->GetString("pin_to_sibling", NULL); - PinCorner_e pinOurCornerToSibling = (PinCorner_e)inResourceData->GetInt( "pin_corner_to_sibling", PIN_TOPLEFT ); - PinCorner_e pinSiblingCorner = (PinCorner_e)inResourceData->GetInt( "pin_to_sibling_corner", PIN_TOPLEFT ); + PinCorner_e pinOurCornerToSibling = GetPinCornerFromString( inResourceData->GetString( "pin_corner_to_sibling", NULL ) ); + PinCorner_e pinSiblingCorner = GetPinCornerFromString( inResourceData->GetString( "pin_to_sibling_corner", NULL ) ); PinToSibling( pszSiblingName, pinOurCornerToSibling, pinSiblingCorner ); @@ -4680,6 +4834,8 @@ void Panel::ApplySettings(KeyValues *inResourceData) { SetKeyBoardInputEnabled( atoi( pKeyboardInputEnabled ) ); } + + OnChildSettingsApplied( inResourceData, this ); } //----------------------------------------------------------------------------- diff --git a/mp/src/vgui2/vgui_controls/PanelListPanel.cpp b/mp/src/vgui2/vgui_controls/PanelListPanel.cpp index 355ac08f..995ce460 100644 --- a/mp/src/vgui2/vgui_controls/PanelListPanel.cpp +++ b/mp/src/vgui2/vgui_controls/PanelListPanel.cpp @@ -248,7 +248,8 @@ void PanelListPanel::DeleteAllItems() { if ( m_DataItems[i].panel ) { - delete m_DataItems[i].panel; + m_DataItems[i].panel->MarkForDeletion(); + m_DataItems[i].panel = NULL; } } diff --git a/mp/src/vgui2/vgui_controls/ScrollBar.cpp b/mp/src/vgui2/vgui_controls/ScrollBar.cpp index d4e8a9b4..94d76088 100644 --- a/mp/src/vgui2/vgui_controls/ScrollBar.cpp +++ b/mp/src/vgui2/vgui_controls/ScrollBar.cpp @@ -625,7 +625,7 @@ void ScrollBar::UseImages( const char *pszUpArrow, const char *pszDownArrow, con } else if ( m_pUpArrow ) { - m_pUpArrow->DeletePanel(); + m_pUpArrow->MarkForDeletion(); m_pUpArrow = NULL; } @@ -648,7 +648,7 @@ void ScrollBar::UseImages( const char *pszUpArrow, const char *pszDownArrow, con } else if ( m_pDownArrow ) { - m_pDownArrow->DeletePanel(); + m_pDownArrow->MarkForDeletion(); m_pDownArrow = NULL; } @@ -669,7 +669,7 @@ void ScrollBar::UseImages( const char *pszUpArrow, const char *pszDownArrow, con } else if ( m_pLine ) { - m_pLine->DeletePanel(); + m_pLine->MarkForDeletion(); m_pLine = NULL; } @@ -690,7 +690,7 @@ void ScrollBar::UseImages( const char *pszUpArrow, const char *pszDownArrow, con } else if ( m_pBox ) { - m_pBox->DeletePanel(); + m_pBox->MarkForDeletion(); m_pBox = NULL; } diff --git a/mp/src/vpc_scripts/source_posix_base.vpc b/mp/src/vpc_scripts/source_posix_base.vpc index 0aeef1a9..907a008c 100644 --- a/mp/src/vpc_scripts/source_posix_base.vpc +++ b/mp/src/vpc_scripts/source_posix_base.vpc @@ -45,6 +45,7 @@ $Configuration $PreprocessorDefinitions "$BASE;_OSX;OSX;_DARWIN_UNLIMITED_SELECT;FD_SETSIZE=10240;" [$OSXALL] $PreprocessorDefinitions "$BASE;OVERRIDE_V_DEFINES" [$OSXALL] $PreprocessorDefinitions "$BASE;_LINUX;LINUX;" [$LINUXALL] + $PreprocessorDefinitions "$BASE;PLATFORM_64BITS" [$LINUX64] $SymbolVisibility "hidden" [$POSIX] $PreprocessorDefinitions "$BASE;POSIX;_POSIX" [$POSIX] diff --git a/sp/src/devtools/bin/vpc_linux b/sp/src/devtools/bin/vpc_linux index 39a40f56..dfdf10bd 100755 Binary files a/sp/src/devtools/bin/vpc_linux and b/sp/src/devtools/bin/vpc_linux differ diff --git a/sp/src/devtools/bin/vpc_osx b/sp/src/devtools/bin/vpc_osx index c06acd46..19f2b842 100755 Binary files a/sp/src/devtools/bin/vpc_osx and b/sp/src/devtools/bin/vpc_osx differ diff --git a/sp/src/lib/common/ubuntu12_32/libcrypto.a b/sp/src/lib/common/ubuntu12_32/libcrypto.a new file mode 100644 index 00000000..274849e0 Binary files /dev/null and b/sp/src/lib/common/ubuntu12_32/libcrypto.a differ diff --git a/sp/src/lib/public/fgdlib.lib b/sp/src/lib/public/fgdlib.lib index 903c5a0c..cc4b4d6f 100644 Binary files a/sp/src/lib/public/fgdlib.lib and b/sp/src/lib/public/fgdlib.lib differ diff --git a/sp/src/lib/public/linux32/bitmap.a b/sp/src/lib/public/linux32/bitmap.a index a73c2a09..cc942c70 100644 Binary files a/sp/src/lib/public/linux32/bitmap.a and b/sp/src/lib/public/linux32/bitmap.a differ diff --git a/sp/src/lib/public/linux32/choreoobjects.a b/sp/src/lib/public/linux32/choreoobjects.a index cf3c6541..6c27bc5c 100644 Binary files a/sp/src/lib/public/linux32/choreoobjects.a and b/sp/src/lib/public/linux32/choreoobjects.a differ diff --git a/sp/src/lib/public/linux32/dmxloader.a b/sp/src/lib/public/linux32/dmxloader.a index de7b9f44..553ea325 100644 Binary files a/sp/src/lib/public/linux32/dmxloader.a and b/sp/src/lib/public/linux32/dmxloader.a differ diff --git a/sp/src/lib/public/linux32/libtier0.so b/sp/src/lib/public/linux32/libtier0.so index aac57b02..6cfc8341 100644 Binary files a/sp/src/lib/public/linux32/libtier0.so and b/sp/src/lib/public/linux32/libtier0.so differ diff --git a/sp/src/lib/public/linux32/libvstdlib.so b/sp/src/lib/public/linux32/libvstdlib.so index fb23a367..4a4af170 100644 Binary files a/sp/src/lib/public/linux32/libvstdlib.so and b/sp/src/lib/public/linux32/libvstdlib.so differ diff --git a/sp/src/lib/public/linux32/mathlib.a b/sp/src/lib/public/linux32/mathlib.a index d4e55884..225b51a7 100644 Binary files a/sp/src/lib/public/linux32/mathlib.a and b/sp/src/lib/public/linux32/mathlib.a differ diff --git a/sp/src/lib/public/linux32/matsys_controls.a b/sp/src/lib/public/linux32/matsys_controls.a index 1642750a..c389ddf7 100644 Binary files a/sp/src/lib/public/linux32/matsys_controls.a and b/sp/src/lib/public/linux32/matsys_controls.a differ diff --git a/sp/src/lib/public/linux32/particles.a b/sp/src/lib/public/linux32/particles.a index 5ff1a966..9c20f024 100644 Binary files a/sp/src/lib/public/linux32/particles.a and b/sp/src/lib/public/linux32/particles.a differ diff --git a/sp/src/lib/public/linux32/raytrace.a b/sp/src/lib/public/linux32/raytrace.a index 0c080b3d..881256ad 100644 Binary files a/sp/src/lib/public/linux32/raytrace.a and b/sp/src/lib/public/linux32/raytrace.a differ diff --git a/sp/src/lib/public/linux32/shaderlib.a b/sp/src/lib/public/linux32/shaderlib.a index 061df5c9..062e7b66 100644 Binary files a/sp/src/lib/public/linux32/shaderlib.a and b/sp/src/lib/public/linux32/shaderlib.a differ diff --git a/sp/src/lib/public/linux32/tier1.a b/sp/src/lib/public/linux32/tier1.a index 5ba32663..9fe363f1 100644 Binary files a/sp/src/lib/public/linux32/tier1.a and b/sp/src/lib/public/linux32/tier1.a differ diff --git a/sp/src/lib/public/linux32/tier2.a b/sp/src/lib/public/linux32/tier2.a index a1b1b277..d54e8639 100644 Binary files a/sp/src/lib/public/linux32/tier2.a and b/sp/src/lib/public/linux32/tier2.a differ diff --git a/sp/src/lib/public/linux32/tier3.a b/sp/src/lib/public/linux32/tier3.a index 8b868aa6..637239e7 100644 Binary files a/sp/src/lib/public/linux32/tier3.a and b/sp/src/lib/public/linux32/tier3.a differ diff --git a/sp/src/lib/public/linux32/vgui_controls.a b/sp/src/lib/public/linux32/vgui_controls.a index 929a7529..84aa3533 100644 Binary files a/sp/src/lib/public/linux32/vgui_controls.a and b/sp/src/lib/public/linux32/vgui_controls.a differ diff --git a/sp/src/lib/public/linux32/vtf.a b/sp/src/lib/public/linux32/vtf.a index a5a3551e..e0fed546 100644 Binary files a/sp/src/lib/public/linux32/vtf.a and b/sp/src/lib/public/linux32/vtf.a differ diff --git a/sp/src/lib/public/mathlib.lib b/sp/src/lib/public/mathlib.lib index 4f525a99..e78a6df8 100644 Binary files a/sp/src/lib/public/mathlib.lib and b/sp/src/lib/public/mathlib.lib differ diff --git a/sp/src/lib/public/osx32/bitmap.a b/sp/src/lib/public/osx32/bitmap.a index 08256a31..3a98ecb5 100644 Binary files a/sp/src/lib/public/osx32/bitmap.a and b/sp/src/lib/public/osx32/bitmap.a differ diff --git a/sp/src/lib/public/osx32/choreoobjects.a b/sp/src/lib/public/osx32/choreoobjects.a index 9f24ec53..399df923 100644 Binary files a/sp/src/lib/public/osx32/choreoobjects.a and b/sp/src/lib/public/osx32/choreoobjects.a differ diff --git a/sp/src/lib/public/osx32/dmxloader.a b/sp/src/lib/public/osx32/dmxloader.a index f2fdb648..fb4719ed 100644 Binary files a/sp/src/lib/public/osx32/dmxloader.a and b/sp/src/lib/public/osx32/dmxloader.a differ diff --git a/sp/src/lib/public/osx32/matsys_controls.a b/sp/src/lib/public/osx32/matsys_controls.a index 3aff10b9..786bcf02 100644 Binary files a/sp/src/lib/public/osx32/matsys_controls.a and b/sp/src/lib/public/osx32/matsys_controls.a differ diff --git a/sp/src/lib/public/osx32/particles.a b/sp/src/lib/public/osx32/particles.a index 9cafa21d..2633980c 100644 Binary files a/sp/src/lib/public/osx32/particles.a and b/sp/src/lib/public/osx32/particles.a differ diff --git a/sp/src/lib/public/osx32/shaderlib.a b/sp/src/lib/public/osx32/shaderlib.a index 7d3300a6..dbdc3e70 100644 Binary files a/sp/src/lib/public/osx32/shaderlib.a and b/sp/src/lib/public/osx32/shaderlib.a differ diff --git a/sp/src/lib/public/osx32/tier2.a b/sp/src/lib/public/osx32/tier2.a index de7c9b5a..e24448c0 100644 Binary files a/sp/src/lib/public/osx32/tier2.a and b/sp/src/lib/public/osx32/tier2.a differ diff --git a/sp/src/lib/public/osx32/tier3.a b/sp/src/lib/public/osx32/tier3.a index 0956e01b..f6cd2330 100644 Binary files a/sp/src/lib/public/osx32/tier3.a and b/sp/src/lib/public/osx32/tier3.a differ diff --git a/sp/src/lib/public/osx32/vtf.a b/sp/src/lib/public/osx32/vtf.a index a0d193cd..ca0c3b05 100644 Binary files a/sp/src/lib/public/osx32/vtf.a and b/sp/src/lib/public/osx32/vtf.a differ diff --git a/sp/src/lib/public/raytrace.lib b/sp/src/lib/public/raytrace.lib index 860ad2f2..c080d044 100644 Binary files a/sp/src/lib/public/raytrace.lib and b/sp/src/lib/public/raytrace.lib differ diff --git a/sp/src/lib/public/tier1.lib b/sp/src/lib/public/tier1.lib index 23ae78b3..8b5b14bf 100644 Binary files a/sp/src/lib/public/tier1.lib and b/sp/src/lib/public/tier1.lib differ diff --git a/sp/src/lib/public/vgui_controls.lib b/sp/src/lib/public/vgui_controls.lib index 7d0033ff..893264a5 100644 Binary files a/sp/src/lib/public/vgui_controls.lib and b/sp/src/lib/public/vgui_controls.lib differ diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.c new file mode 100644 index 00000000..21bb30c7 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.c @@ -0,0 +1,70 @@ +/* 7zAlloc.c */ + +#include +#include "7zAlloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ + +#ifdef _SZ_ALLOC_DEBUG + +#ifdef _WIN32 +#include +#endif +#include +int g_allocCount = 0; +int g_allocCountTemp = 0; +#endif + +void *SzAlloc(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); + g_allocCount++; + #endif + return malloc(size); +} + +void SzFree(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCount--; + fprintf(stderr, "\nFree; count = %10d", g_allocCount); + } + #endif + free(address); +} + +void *SzAllocTemp(size_t size) +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); + g_allocCountTemp++; + #ifdef _WIN32 + return HeapAlloc(GetProcessHeap(), 0, size); + #endif + #endif + return malloc(size); +} + +void SzFreeTemp(void *address) +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + { + g_allocCountTemp--; + fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); + } + #ifdef _WIN32 + HeapFree(GetProcessHeap(), 0, address); + return; + #endif + #endif + free(address); +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.h new file mode 100644 index 00000000..4ca4170c --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zAlloc.h @@ -0,0 +1,20 @@ +/* 7zAlloc.h */ + +#ifndef __7Z_ALLOC_H +#define __7Z_ALLOC_H + +#include + +typedef struct _ISzAlloc +{ + void *(*Alloc)(size_t size); + void (*Free)(void *address); /* address can be 0 */ +} ISzAlloc; + +void *SzAlloc(size_t size); +void SzFree(void *address); + +void *SzAllocTemp(size_t size); +void SzFreeTemp(void *address); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.c new file mode 100644 index 00000000..3c4b71e8 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.c @@ -0,0 +1,29 @@ +/* 7zBuffer.c */ + +#include "7zBuffer.h" +#include "7zAlloc.h" + +void SzByteBufferInit(CSzByteBuffer *buffer) +{ + buffer->Capacity = 0; + buffer->Items = 0; +} + +int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)) +{ + buffer->Capacity = newCapacity; + if (newCapacity == 0) + { + buffer->Items = 0; + return 1; + } + buffer->Items = (Byte *)allocFunc(newCapacity); + return (buffer->Items != 0); +} + +void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)) +{ + freeFunc(buffer->Items); + buffer->Items = 0; + buffer->Capacity = 0; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.h new file mode 100644 index 00000000..17e59060 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zBuffer.h @@ -0,0 +1,19 @@ +/* 7zBuffer.h */ + +#ifndef __7Z_BUFFER_H +#define __7Z_BUFFER_H + +#include +#include "7zTypes.h" + +typedef struct _CSzByteBuffer +{ + size_t Capacity; + Byte *Items; +}CSzByteBuffer; + +void SzByteBufferInit(CSzByteBuffer *buffer); +int SzByteBufferCreate(CSzByteBuffer *buffer, size_t newCapacity, void * (*allocFunc)(size_t size)); +void SzByteBufferFree(CSzByteBuffer *buffer, void (*freeFunc)(void *)); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.c new file mode 100644 index 00000000..97738404 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.c @@ -0,0 +1,76 @@ +/* 7zCrc.c */ + +#include "7zCrc.h" + +#define kCrcPoly 0xEDB88320 + +UInt32 g_CrcTable[256]; + +void InitCrcTable() +{ + UInt32 i; + for (i = 0; i < 256; i++) + { + UInt32 r = i; + int j; + for (j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCrcPoly; + else + r >>= 1; + g_CrcTable[i] = r; + } +} + +void CrcInit(UInt32 *crc) { *crc = 0xFFFFFFFF; } +UInt32 CrcGetDigest(UInt32 *crc) { return *crc ^ 0xFFFFFFFF; } + +void CrcUpdateByte(UInt32 *crc, Byte b) +{ + *crc = g_CrcTable[((Byte)(*crc)) ^ b] ^ (*crc >> 8); +} + +void CrcUpdateUInt16(UInt32 *crc, UInt16 v) +{ + CrcUpdateByte(crc, (Byte)v); + CrcUpdateByte(crc, (Byte)(v >> 8)); +} + +void CrcUpdateUInt32(UInt32 *crc, UInt32 v) +{ + int i; + for (i = 0; i < 4; i++) + CrcUpdateByte(crc, (Byte)(v >> (8 * i))); +} + +void CrcUpdateUInt64(UInt32 *crc, UInt64 v) +{ + int i; + for (i = 0; i < 8; i++) + { + CrcUpdateByte(crc, (Byte)(v)); + v >>= 8; + } +} + +void CrcUpdate(UInt32 *crc, const void *data, size_t size) +{ + UInt32 v = *crc; + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = g_CrcTable[((Byte)(v)) ^ *p] ^ (v >> 8); + *crc = v; +} + +UInt32 CrcCalculateDigest(const void *data, size_t size) +{ + UInt32 crc; + CrcInit(&crc); + CrcUpdate(&crc, data, size); + return CrcGetDigest(&crc); +} + +int CrcVerifyDigest(UInt32 digest, const void *data, size_t size) +{ + return (CrcCalculateDigest(data, size) == digest); +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.h new file mode 100644 index 00000000..adcc563a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zCrc.h @@ -0,0 +1,24 @@ +/* 7zCrc.h */ + +#ifndef __7Z_CRC_H +#define __7Z_CRC_H + +#include + +#include "7zTypes.h" + +extern UInt32 g_CrcTable[256]; +void InitCrcTable(); + +void CrcInit(UInt32 *crc); +UInt32 CrcGetDigest(UInt32 *crc); +void CrcUpdateByte(UInt32 *crc, Byte v); +void CrcUpdateUInt16(UInt32 *crc, UInt16 v); +void CrcUpdateUInt32(UInt32 *crc, UInt32 v); +void CrcUpdateUInt64(UInt32 *crc, UInt64 v); +void CrcUpdate(UInt32 *crc, const void *data, size_t size); + +UInt32 CrcCalculateDigest(const void *data, size_t size); +int CrcVerifyDigest(UInt32 digest, const void *data, size_t size); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.c new file mode 100644 index 00000000..b42ff927 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.c @@ -0,0 +1,150 @@ +/* 7zDecode.c */ + +#include "7zDecode.h" +#ifdef _SZ_ONE_DIRECTORY +#include "LzmaDecode.h" +#else +#include "../../Compress/LZMA_C/LzmaDecode.h" +#endif + +CMethodID k_Copy = { { 0x0 }, 1 }; +CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 }; + +#ifdef _LZMA_IN_CB + +typedef struct _CLzmaInCallbackImp +{ + ILzmaInCallback InCallback; + ISzInStream *InStream; + size_t Size; +} CLzmaInCallbackImp; + +int LzmaReadImp(void *object, const unsigned char **buffer, SizeT *size) +{ + CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object; + size_t processedSize; + SZ_RESULT res; + *size = 0; + res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize); + *size = (SizeT)processedSize; + if (processedSize > cb->Size) + return (int)SZE_FAIL; + cb->Size -= processedSize; + if (res == SZ_OK) + return 0; + return (int)res; +} + +#endif + +SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, + #ifdef _LZMA_IN_CB + ISzInStream *inStream, + #else + const Byte *inBuffer, + #endif + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain) +{ + UInt32 si; + size_t inSize = 0; + CCoderInfo *coder; + if (folder->NumPackStreams != 1) + return SZE_NOTIMPL; + if (folder->NumCoders != 1) + return SZE_NOTIMPL; + coder = folder->Coders; + *outSizeProcessed = 0; + + for (si = 0; si < folder->NumPackStreams; si++) + inSize += (size_t)packSizes[si]; + + if (AreMethodsEqual(&coder->MethodID, &k_Copy)) + { + size_t i; + if (inSize != outSize) + return SZE_DATA_ERROR; + #ifdef _LZMA_IN_CB + for (i = 0; i < inSize;) + { + size_t j; + Byte *inBuffer; + size_t bufferSize; + RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize)); + if (bufferSize == 0) + return SZE_DATA_ERROR; + if (bufferSize > inSize - i) + return SZE_FAIL; + *outSizeProcessed += bufferSize; + for (j = 0; j < bufferSize && i < inSize; j++, i++) + outBuffer[i] = inBuffer[j]; + } + #else + for (i = 0; i < inSize; i++) + outBuffer[i] = inBuffer[i]; + *outSizeProcessed = inSize; + #endif + return SZ_OK; + } + + if (AreMethodsEqual(&coder->MethodID, &k_LZMA)) + { + #ifdef _LZMA_IN_CB + CLzmaInCallbackImp lzmaCallback; + #else + SizeT inProcessed; + #endif + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + int result; + SizeT outSizeProcessedLoc; + + #ifdef _LZMA_IN_CB + lzmaCallback.Size = inSize; + lzmaCallback.InStream = inStream; + lzmaCallback.InCallback.Read = LzmaReadImp; + #endif + + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + coder->Properties.Capacity) != LZMA_RESULT_OK) + return SZE_FAIL; + + state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (state.Probs == 0) + return SZE_OUTOFMEMORY; + + #ifdef _LZMA_OUT_READ + if (state.Properties.DictionarySize == 0) + state.Dictionary = 0; + else + { + state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize); + if (state.Dictionary == 0) + { + allocMain->Free(state.Probs); + return SZE_OUTOFMEMORY; + } + } + LzmaDecoderInit(&state); + #endif + + result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + inBuffer, (SizeT)inSize, &inProcessed, + #endif + outBuffer, (SizeT)outSize, &outSizeProcessedLoc); + *outSizeProcessed = (size_t)outSizeProcessedLoc; + allocMain->Free(state.Probs); + #ifdef _LZMA_OUT_READ + allocMain->Free(state.Dictionary); + #endif + if (result == LZMA_RESULT_DATA_ERROR) + return SZE_DATA_ERROR; + if (result != LZMA_RESULT_OK) + return SZE_FAIL; + return SZ_OK; + } + return SZE_NOTIMPL; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.h new file mode 100644 index 00000000..74bb180f --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zDecode.h @@ -0,0 +1,21 @@ +/* 7zDecode.h */ + +#ifndef __7Z_DECODE_H +#define __7Z_DECODE_H + +#include "7zItem.h" +#include "7zAlloc.h" +#ifdef _LZMA_IN_CB +#include "7zIn.h" +#endif + +SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, + #ifdef _LZMA_IN_CB + ISzInStream *stream, + #else + const Byte *inBuffer, + #endif + Byte *outBuffer, size_t outSize, + size_t *outSizeProcessed, ISzAlloc *allocMain); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.c new file mode 100644 index 00000000..6ef872c3 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.c @@ -0,0 +1,116 @@ +/* 7zExtract.c */ + +#include "7zExtract.h" +#include "7zDecode.h" +#include "7zCrc.h" + +SZ_RESULT SzExtract( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, + UInt32 *blockIndex, + Byte **outBuffer, + size_t *outBufferSize, + size_t *offset, + size_t *outSizeProcessed, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt32 folderIndex = db->FileIndexToFolderIndexMap[fileIndex]; + SZ_RESULT res = SZ_OK; + *offset = 0; + *outSizeProcessed = 0; + if (folderIndex == (UInt32)-1) + { + allocMain->Free(*outBuffer); + *blockIndex = folderIndex; + *outBuffer = 0; + *outBufferSize = 0; + return SZ_OK; + } + + if (*outBuffer == 0 || *blockIndex != folderIndex) + { + CFolder *folder = db->Database.Folders + folderIndex; + CFileSize unPackSize = SzFolderGetUnPackSize(folder); + #ifndef _LZMA_IN_CB + CFileSize packSize = SzArDbGetFolderFullPackSize(db, folderIndex); + Byte *inBuffer = 0; + size_t processedSize; + #endif + *blockIndex = folderIndex; + allocMain->Free(*outBuffer); + *outBuffer = 0; + + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); + + #ifndef _LZMA_IN_CB + if (packSize != 0) + { + inBuffer = (Byte *)allocTemp->Alloc((size_t)packSize); + if (inBuffer == 0) + return SZE_OUTOFMEMORY; + } + res = inStream->Read(inStream, inBuffer, (size_t)packSize, &processedSize); + if (res == SZ_OK && processedSize != (size_t)packSize) + res = SZE_FAIL; + #endif + if (res == SZ_OK) + { + *outBufferSize = (size_t)unPackSize; + if (unPackSize != 0) + { + *outBuffer = (Byte *)allocMain->Alloc((size_t)unPackSize); + if (*outBuffer == 0) + res = SZE_OUTOFMEMORY; + } + if (res == SZ_OK) + { + size_t outRealSize; + res = SzDecode(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, + #ifdef _LZMA_IN_CB + inStream, + #else + inBuffer, + #endif + *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); + if (res == SZ_OK) + { + if (outRealSize == (size_t)unPackSize) + { + if (folder->UnPackCRCDefined) + { + if (!CrcVerifyDigest(folder->UnPackCRC, *outBuffer, (size_t)unPackSize)) + res = SZE_FAIL; + } + } + else + res = SZE_FAIL; + } + } + } + #ifndef _LZMA_IN_CB + allocTemp->Free(inBuffer); + #endif + } + if (res == SZ_OK) + { + UInt32 i; + CFileItem *fileItem = db->Database.Files + fileIndex; + *offset = 0; + for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) + *offset += (UInt32)db->Database.Files[i].Size; + *outSizeProcessed = (size_t)fileItem->Size; + if (*offset + *outSizeProcessed > *outBufferSize) + return SZE_FAIL; + { + if (fileItem->IsFileCRCDefined) + { + if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer + *offset, *outSizeProcessed)) + res = SZE_FAIL; + } + } + } + return res; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.h new file mode 100644 index 00000000..e9a4fb4e --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zExtract.h @@ -0,0 +1,40 @@ +/* 7zExtract.h */ + +#ifndef __7Z_EXTRACT_H +#define __7Z_EXTRACT_H + +#include "7zIn.h" + +/* + SzExtract extracts file from archive + + *outBuffer must be 0 before first call for each new archive. + + Extracting cache: + If you need to decompress more than one file, you can send + these values from previous call: + *blockIndex, + *outBuffer, + *outBufferSize + You can consider "*outBuffer" as cache of solid block. If your archive is solid, + it will increase decompression speed. + + If you use external function, you can declare these 3 cache variables + (blockIndex, outBuffer, outBufferSize) as static in that external function. + + Free *outBuffer and set *outBuffer to 0, if you want to flush cache. +*/ + +SZ_RESULT SzExtract( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + UInt32 fileIndex, /* index of file */ + UInt32 *blockIndex, /* index of solid block */ + Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ + size_t *outBufferSize, /* buffer size for output buffer */ + size_t *offset, /* offset of stream for required file in *outBuffer */ + size_t *outSizeProcessed, /* size of file in *outBuffer */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.c new file mode 100644 index 00000000..3be4bc27 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.c @@ -0,0 +1,5 @@ +/* 7zHeader.c */ + +#include "7zHeader.h" + +Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.h new file mode 100644 index 00000000..0356aaa6 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zHeader.h @@ -0,0 +1,55 @@ +/* 7zHeader.h */ + +#ifndef __7Z_HEADER_H +#define __7Z_HEADER_H + +#include "7zTypes.h" + +#define k7zSignatureSize 6 +extern Byte k7zSignature[k7zSignatureSize]; + +#define k7zMajorVersion 0 + +#define k7zStartHeaderSize 0x20 + +enum EIdEnum +{ + k7zIdEnd, + + k7zIdHeader, + + k7zIdArchiveProperties, + + k7zIdAdditionalStreamsInfo, + k7zIdMainStreamsInfo, + k7zIdFilesInfo, + + k7zIdPackInfo, + k7zIdUnPackInfo, + k7zIdSubStreamsInfo, + + k7zIdSize, + k7zIdCRC, + + k7zIdFolder, + + k7zIdCodersUnPackSize, + k7zIdNumUnPackStream, + + k7zIdEmptyStream, + k7zIdEmptyFile, + k7zIdAnti, + + k7zIdName, + k7zIdCreationTime, + k7zIdLastAccessTime, + k7zIdLastWriteTime, + k7zIdWinAttributes, + k7zIdComment, + + k7zIdEncodedHeader, + + k7zIdStartPos +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.c new file mode 100644 index 00000000..8ff1e62d --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.c @@ -0,0 +1,1281 @@ +/* 7zIn.c */ + +#include "7zIn.h" +#include "7zCrc.h" +#include "7zDecode.h" + +#define RINOM(x) { if((x) == 0) return SZE_OUTOFMEMORY; } + +void SzArDbExInit(CArchiveDatabaseEx *db) +{ + SzArchiveDatabaseInit(&db->Database); + db->FolderStartPackStreamIndex = 0; + db->PackStreamStartPositions = 0; + db->FolderStartFileIndex = 0; + db->FileIndexToFolderIndexMap = 0; +} + +void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)) +{ + freeFunc(db->FolderStartPackStreamIndex); + freeFunc(db->PackStreamStartPositions); + freeFunc(db->FolderStartFileIndex); + freeFunc(db->FileIndexToFolderIndexMap); + SzArchiveDatabaseFree(&db->Database, freeFunc); + SzArDbExInit(db); +} + +/* +CFileSize GetFolderPackStreamSize(int folderIndex, int streamIndex) const +{ + return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; +} + +CFileSize GetFilePackSize(int fileIndex) const +{ + int folderIndex = FileIndexToFolderIndexMap[fileIndex]; + if (folderIndex >= 0) + { + const CFolder &folderInfo = Folders[folderIndex]; + if (FolderStartFileIndex[folderIndex] == fileIndex) + return GetFolderFullPackSize(folderIndex); + } + return 0; +} +*/ + +#define MY_ALLOC(T, p, size, allocFunc) { if ((size) == 0) p = 0; else \ + if ((p = (T *)allocFunc((size) * sizeof(T))) == 0) return SZE_OUTOFMEMORY; } + +SZ_RESULT SzArDbExFill(CArchiveDatabaseEx *db, void * (*allocFunc)(size_t size)) +{ + UInt32 startPos = 0; + CFileSize startPosSize = 0; + UInt32 i; + UInt32 folderIndex = 0; + UInt32 indexInFolder = 0; + MY_ALLOC(UInt32, db->FolderStartPackStreamIndex, db->Database.NumFolders, allocFunc); + for(i = 0; i < db->Database.NumFolders; i++) + { + db->FolderStartPackStreamIndex[i] = startPos; + startPos += db->Database.Folders[i].NumPackStreams; + } + + MY_ALLOC(CFileSize, db->PackStreamStartPositions, db->Database.NumPackStreams, allocFunc); + + for(i = 0; i < db->Database.NumPackStreams; i++) + { + db->PackStreamStartPositions[i] = startPosSize; + startPosSize += db->Database.PackSizes[i]; + } + + MY_ALLOC(UInt32, db->FolderStartFileIndex, db->Database.NumFolders, allocFunc); + MY_ALLOC(UInt32, db->FileIndexToFolderIndexMap, db->Database.NumFiles, allocFunc); + + for (i = 0; i < db->Database.NumFiles; i++) + { + CFileItem *file = db->Database.Files + i; + int emptyStream = !file->HasStream; + if (emptyStream && indexInFolder == 0) + { + db->FileIndexToFolderIndexMap[i] = (UInt32)-1; + continue; + } + if (indexInFolder == 0) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: Loop for skipping empty folders + */ + while(1) + { + if (folderIndex >= db->Database.NumFolders) + return SZE_ARCHIVE_ERROR; + db->FolderStartFileIndex[folderIndex] = i; + if (db->Database.Folders[folderIndex].NumUnPackStreams != 0) + break; + folderIndex++; + } + } + db->FileIndexToFolderIndexMap[i] = folderIndex; + if (emptyStream) + continue; + indexInFolder++; + if (indexInFolder >= db->Database.Folders[folderIndex].NumUnPackStreams) + { + folderIndex++; + indexInFolder = 0; + } + } + return SZ_OK; +} + + +CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder) +{ + return db->ArchiveInfo.DataStartPosition + + db->PackStreamStartPositions[db->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; +} + +CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex) +{ + UInt32 packStreamIndex = db->FolderStartPackStreamIndex[folderIndex]; + CFolder *folder = db->Database.Folders + folderIndex; + CFileSize size = 0; + UInt32 i; + for (i = 0; i < folder->NumPackStreams; i++) + size += db->Database.PackSizes[packStreamIndex + i]; + return size; +} + + +/* +SZ_RESULT SzReadTime(const CObjectVector &dataVector, + CObjectVector &files, UInt64 type) +{ + CBoolVector boolVector; + RINOK(ReadBoolVector2(files.Size(), boolVector)) + + CStreamSwitch streamSwitch; + RINOK(streamSwitch.Set(this, &dataVector)); + + for(int i = 0; i < files.Size(); i++) + { + CFileItem &file = files[i]; + CArchiveFileTime fileTime; + bool defined = boolVector[i]; + if (defined) + { + UInt32 low, high; + RINOK(SzReadUInt32(low)); + RINOK(SzReadUInt32(high)); + fileTime.dwLowDateTime = low; + fileTime.dwHighDateTime = high; + } + switch(type) + { + case k7zIdCreationTime: + file.IsCreationTimeDefined = defined; + if (defined) + file.CreationTime = fileTime; + break; + case k7zIdLastWriteTime: + file.IsLastWriteTimeDefined = defined; + if (defined) + file.LastWriteTime = fileTime; + break; + case k7zIdLastAccessTime: + file.IsLastAccessTimeDefined = defined; + if (defined) + file.LastAccessTime = fileTime; + break; + } + } + return SZ_OK; +} +*/ + +SZ_RESULT SafeReadDirect(ISzInStream *inStream, Byte *data, size_t size) +{ + #ifdef _LZMA_IN_CB + while (size > 0) + { + Byte *inBuffer; + size_t processedSize; + RINOK(inStream->Read(inStream, (void **)&inBuffer, size, &processedSize)); + if (processedSize == 0 || processedSize > size) + return SZE_FAIL; + size -= processedSize; + do + { + *data++ = *inBuffer++; + } + while (--processedSize != 0); + } + #else + size_t processedSize; + RINOK(inStream->Read(inStream, data, size, &processedSize)); + if (processedSize != size) + return SZE_FAIL; + #endif + return SZ_OK; +} + +SZ_RESULT SafeReadDirectByte(ISzInStream *inStream, Byte *data) +{ + return SafeReadDirect(inStream, data, 1); +} + +SZ_RESULT SafeReadDirectUInt32(ISzInStream *inStream, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SafeReadDirectByte(inStream, &b)); + *value |= ((UInt32)b << (8 * i)); + } + return SZ_OK; +} + +SZ_RESULT SafeReadDirectUInt64(ISzInStream *inStream, UInt64 *value) +{ + int i; + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + RINOK(SafeReadDirectByte(inStream, &b)); + *value |= ((UInt32)b << (8 * i)); + } + return SZ_OK; +} + +int TestSignatureCandidate(Byte *testBytes) +{ + size_t i; + for (i = 0; i < k7zSignatureSize; i++) + if (testBytes[i] != k7zSignature[i]) + return 0; + return 1; +} + +typedef struct _CSzState +{ + Byte *Data; + size_t Size; +}CSzData; + +SZ_RESULT SzReadByte(CSzData *sd, Byte *b) +{ + if (sd->Size == 0) + return SZE_ARCHIVE_ERROR; + sd->Size--; + *b = *sd->Data++; + return SZ_OK; +} + +SZ_RESULT SzReadBytes(CSzData *sd, Byte *data, size_t size) +{ + size_t i; + for (i = 0; i < size; i++) + { + RINOK(SzReadByte(sd, data + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadUInt32(CSzData *sd, UInt32 *value) +{ + int i; + *value = 0; + for (i = 0; i < 4; i++) + { + Byte b; + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt32)(b) << (8 * i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadNumber(CSzData *sd, UInt64 *value) +{ + Byte firstByte; + Byte mask = 0x80; + int i; + RINOK(SzReadByte(sd, &firstByte)); + *value = 0; + for (i = 0; i < 8; i++) + { + Byte b; + if ((firstByte & mask) == 0) + { + UInt64 highPart = firstByte & (mask - 1); + *value += (highPart << (8 * i)); + return SZ_OK; + } + RINOK(SzReadByte(sd, &b)); + *value |= ((UInt64)b << (8 * i)); + mask >>= 1; + } + return SZ_OK; +} + +SZ_RESULT SzReadSize(CSzData *sd, CFileSize *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + *value = (CFileSize)value64; + return SZ_OK; +} + +SZ_RESULT SzReadNumber32(CSzData *sd, UInt32 *value) +{ + UInt64 value64; + RINOK(SzReadNumber(sd, &value64)); + if (value64 >= 0x80000000) + return SZE_NOTIMPL; + if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) + return SZE_NOTIMPL; + *value = (UInt32)value64; + return SZ_OK; +} + +SZ_RESULT SzReadID(CSzData *sd, UInt64 *value) +{ + return SzReadNumber(sd, value); +} + +SZ_RESULT SzSkeepDataSize(CSzData *sd, UInt64 size) +{ + if (size > sd->Size) + return SZE_ARCHIVE_ERROR; + sd->Size -= (size_t)size; + sd->Data += (size_t)size; + return SZ_OK; +} + +SZ_RESULT SzSkeepData(CSzData *sd) +{ + UInt64 size; + RINOK(SzReadNumber(sd, &size)); + return SzSkeepDataSize(sd, size); +} + +SZ_RESULT SzReadArchiveProperties(CSzData *sd) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + SzSkeepData(sd); + } + return SZ_OK; +} + +SZ_RESULT SzWaitAttribute(CSzData *sd, UInt64 attribute) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == attribute) + return SZ_OK; + if (type == k7zIdEnd) + return SZE_ARCHIVE_ERROR; + RINOK(SzSkeepData(sd)); + } +} + +SZ_RESULT SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) +{ + Byte b = 0; + Byte mask = 0; + size_t i; + MY_ALLOC(Byte, *v, numItems, allocFunc); + for(i = 0; i < numItems; i++) + { + if (mask == 0) + { + RINOK(SzReadByte(sd, &b)); + mask = 0x80; + } + (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); + mask >>= 1; + } + return SZ_OK; +} + +SZ_RESULT SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, void * (*allocFunc)(size_t size)) +{ + Byte allAreDefined; + size_t i; + RINOK(SzReadByte(sd, &allAreDefined)); + if (allAreDefined == 0) + return SzReadBoolVector(sd, numItems, v, allocFunc); + MY_ALLOC(Byte, *v, numItems, allocFunc); + for(i = 0; i < numItems; i++) + (*v)[i] = 1; + return SZ_OK; +} + +SZ_RESULT SzReadHashDigests( + CSzData *sd, + size_t numItems, + Byte **digestsDefined, + UInt32 **digests, + void * (*allocFunc)(size_t size)) +{ + size_t i; + RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, allocFunc)); + MY_ALLOC(UInt32, *digests, numItems, allocFunc); + for(i = 0; i < numItems; i++) + if ((*digestsDefined)[i]) + { + RINOK(SzReadUInt32(sd, (*digests) + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadPackInfo( + CSzData *sd, + CFileSize *dataOffset, + UInt32 *numPackStreams, + CFileSize **packSizes, + Byte **packCRCsDefined, + UInt32 **packCRCs, + void * (*allocFunc)(size_t size)) +{ + UInt32 i; + RINOK(SzReadSize(sd, dataOffset)); + RINOK(SzReadNumber32(sd, numPackStreams)); + + RINOK(SzWaitAttribute(sd, k7zIdSize)); + + MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc); + + for(i = 0; i < *numPackStreams; i++) + { + RINOK(SzReadSize(sd, (*packSizes) + i)); + } + + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + if (type == k7zIdCRC) + { + RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc)); + continue; + } + RINOK(SzSkeepData(sd)); + } + if (*packCRCsDefined == 0) + { + MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc); + MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc); + for(i = 0; i < *numPackStreams; i++) + { + (*packCRCsDefined)[i] = 0; + (*packCRCs)[i] = 0; + } + } + return SZ_OK; +} + +SZ_RESULT SzReadSwitch(CSzData *sd) +{ + Byte external; + RINOK(SzReadByte(sd, &external)); + return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR; +} + +SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size)) +{ + UInt32 numCoders; + UInt32 numBindPairs; + UInt32 numPackedStreams; + UInt32 i; + UInt32 numInStreams = 0; + UInt32 numOutStreams = 0; + RINOK(SzReadNumber32(sd, &numCoders)); + folder->NumCoders = numCoders; + + MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc); + + for (i = 0; i < numCoders; i++) + SzCoderInfoInit(folder->Coders + i); + + for (i = 0; i < numCoders; i++) + { + Byte mainByte; + CCoderInfo *coder = folder->Coders + i; + { + RINOK(SzReadByte(sd, &mainByte)); + coder->MethodID.IDSize = (Byte)(mainByte & 0xF); + RINOK(SzReadBytes(sd, coder->MethodID.ID, coder->MethodID.IDSize)); + if ((mainByte & 0x10) != 0) + { + RINOK(SzReadNumber32(sd, &coder->NumInStreams)); + RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); + } + else + { + coder->NumInStreams = 1; + coder->NumOutStreams = 1; + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc)) + return SZE_OUTOFMEMORY; + RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize)); + } + } + while ((mainByte & 0x80) != 0) + { + RINOK(SzReadByte(sd, &mainByte)); + RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); + if ((mainByte & 0x10) != 0) + { + UInt32 n; + RINOK(SzReadNumber32(sd, &n)); + RINOK(SzReadNumber32(sd, &n)); + } + if ((mainByte & 0x20) != 0) + { + UInt64 propertiesSize = 0; + RINOK(SzReadNumber(sd, &propertiesSize)); + RINOK(SzSkeepDataSize(sd, propertiesSize)); + } + } + numInStreams += (UInt32)coder->NumInStreams; + numOutStreams += (UInt32)coder->NumOutStreams; + } + + numBindPairs = numOutStreams - 1; + folder->NumBindPairs = numBindPairs; + + + MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc); + + for (i = 0; i < numBindPairs; i++) + { + CBindPair *bindPair = folder->BindPairs + i;; + RINOK(SzReadNumber32(sd, &bindPair->InIndex)); + RINOK(SzReadNumber32(sd, &bindPair->OutIndex)); + } + + numPackedStreams = numInStreams - (UInt32)numBindPairs; + + folder->NumPackStreams = numPackedStreams; + MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc); + + if (numPackedStreams == 1) + { + UInt32 j; + UInt32 pi = 0; + for (j = 0; j < numInStreams; j++) + if (SzFolderFindBindPairForInStream(folder, j) < 0) + { + folder->PackStreams[pi++] = j; + break; + } + } + else + for(i = 0; i < numPackedStreams; i++) + { + RINOK(SzReadNumber32(sd, folder->PackStreams + i)); + } + return SZ_OK; +} + +SZ_RESULT SzReadUnPackInfo( + CSzData *sd, + UInt32 *numFolders, + CFolder **folders, /* for allocFunc */ + void * (*allocFunc)(size_t size), + ISzAlloc *allocTemp) +{ + UInt32 i; + RINOK(SzWaitAttribute(sd, k7zIdFolder)); + RINOK(SzReadNumber32(sd, numFolders)); + { + RINOK(SzReadSwitch(sd)); + + MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc); + + for(i = 0; i < *numFolders; i++) + SzFolderInit((*folders) + i); + + for(i = 0; i < *numFolders; i++) + { + RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc)); + } + } + + RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize)); + + for(i = 0; i < *numFolders; i++) + { + UInt32 j; + CFolder *folder = (*folders) + i; + UInt32 numOutStreams = SzFolderGetNumOutStreams(folder); + + MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc); + + for(j = 0; j < numOutStreams; j++) + { + RINOK(SzReadSize(sd, folder->UnPackSizes + j)); + } + } + + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + return SZ_OK; + if (type == k7zIdCRC) + { + SZ_RESULT res; + Byte *crcsDefined = 0; + UInt32 *crcs = 0; + res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc); + if (res == SZ_OK) + { + for(i = 0; i < *numFolders; i++) + { + CFolder *folder = (*folders) + i; + folder->UnPackCRCDefined = crcsDefined[i]; + folder->UnPackCRC = crcs[i]; + } + } + allocTemp->Free(crcs); + allocTemp->Free(crcsDefined); + RINOK(res); + continue; + } + RINOK(SzSkeepData(sd)); + } +} + +SZ_RESULT SzReadSubStreamsInfo( + CSzData *sd, + UInt32 numFolders, + CFolder *folders, + UInt32 *numUnPackStreams, + CFileSize **unPackSizes, + Byte **digestsDefined, + UInt32 **digests, + ISzAlloc *allocTemp) +{ + UInt64 type = 0; + UInt32 i; + UInt32 si = 0; + UInt32 numDigests = 0; + + for(i = 0; i < numFolders; i++) + folders[i].NumUnPackStreams = 1; + *numUnPackStreams = numFolders; + + while(1) + { + RINOK(SzReadID(sd, &type)); + if (type == k7zIdNumUnPackStream) + { + *numUnPackStreams = 0; + for(i = 0; i < numFolders; i++) + { + UInt32 numStreams; + RINOK(SzReadNumber32(sd, &numStreams)); + folders[i].NumUnPackStreams = numStreams; + *numUnPackStreams += numStreams; + } + continue; + } + if (type == k7zIdCRC || type == k7zIdSize) + break; + if (type == k7zIdEnd) + break; + RINOK(SzSkeepData(sd)); + } + + if (*numUnPackStreams == 0) + { + *unPackSizes = 0; + *digestsDefined = 0; + *digests = 0; + } + else + { + *unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize)); + RINOM(*unPackSizes); + *digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte)); + RINOM(*digestsDefined); + *digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32)); + RINOM(*digests); + } + + for(i = 0; i < numFolders; i++) + { + /* + v3.13 incorrectly worked with empty folders + v4.07: we check that folder is empty + */ + CFileSize sum = 0; + UInt32 j; + UInt32 numSubstreams = folders[i].NumUnPackStreams; + if (numSubstreams == 0) + continue; + if (type == k7zIdSize) + for (j = 1; j < numSubstreams; j++) + { + CFileSize size; + RINOK(SzReadSize(sd, &size)); + (*unPackSizes)[si++] = size; + sum += size; + } + (*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum; + } + if (type == k7zIdSize) + { + RINOK(SzReadID(sd, &type)); + } + + for(i = 0; i < *numUnPackStreams; i++) + { + (*digestsDefined)[i] = 0; + (*digests)[i] = 0; + } + + + for(i = 0; i < numFolders; i++) + { + UInt32 numSubstreams = folders[i].NumUnPackStreams; + if (numSubstreams != 1 || !folders[i].UnPackCRCDefined) + numDigests += numSubstreams; + } + + + si = 0; + while(1) + { + if (type == k7zIdCRC) + { + int digestIndex = 0; + Byte *digestsDefined2 = 0; + UInt32 *digests2 = 0; + SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc); + if (res == SZ_OK) + { + for (i = 0; i < numFolders; i++) + { + CFolder *folder = folders + i; + UInt32 numSubstreams = folder->NumUnPackStreams; + if (numSubstreams == 1 && folder->UnPackCRCDefined) + { + (*digestsDefined)[si] = 1; + (*digests)[si] = folder->UnPackCRC; + si++; + } + else + { + UInt32 j; + for (j = 0; j < numSubstreams; j++, digestIndex++) + { + (*digestsDefined)[si] = digestsDefined2[digestIndex]; + (*digests)[si] = digests2[digestIndex]; + si++; + } + } + } + } + allocTemp->Free(digestsDefined2); + allocTemp->Free(digests2); + RINOK(res); + } + else if (type == k7zIdEnd) + return SZ_OK; + else + { + RINOK(SzSkeepData(sd)); + } + RINOK(SzReadID(sd, &type)); + } +} + + +SZ_RESULT SzReadStreamsInfo( + CSzData *sd, + CFileSize *dataOffset, + CArchiveDatabase *db, + UInt32 *numUnPackStreams, + CFileSize **unPackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + void * (*allocFunc)(size_t size), + ISzAlloc *allocTemp) +{ + while(1) + { + UInt64 type; + RINOK(SzReadID(sd, &type)); + if ((UInt64)(int)type != type) + return SZE_FAIL; + switch((int)type) + { + case k7zIdEnd: + return SZ_OK; + case k7zIdPackInfo: + { + RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams, + &db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc)); + break; + } + case k7zIdUnPackInfo: + { + RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp)); + break; + } + case k7zIdSubStreamsInfo: + { + RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders, + numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp)); + break; + } + default: + return SZE_FAIL; + } + } +} + +Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + +SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files, + void * (*allocFunc)(size_t size)) +{ + UInt32 i; + for(i = 0; i < numFiles; i++) + { + UInt32 len = 0; + UInt32 pos = 0; + CFileItem *file = files + i; + while(pos + 2 <= sd->Size) + { + int numAdds; + UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); + pos += 2; + len++; + if (value == 0) + break; + if (value < 0x80) + continue; + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2; + if (value >= 0xDC00) + return SZE_ARCHIVE_ERROR; + if (pos + 2 > sd->Size) + return SZE_ARCHIVE_ERROR; + c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); + pos += 2; + if (c2 < 0xDC00 || c2 >= 0xE000) + return SZE_ARCHIVE_ERROR; + value = ((value - 0xD800) << 10) | (c2 - 0xDC00); + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + len += numAdds; + } + + MY_ALLOC(char, file->Name, (size_t)len, allocFunc); + + len = 0; + while(2 <= sd->Size) + { + int numAdds; + UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); + SzSkeepDataSize(sd, 2); + if (value < 0x80) + { + file->Name[len++] = (char)value; + if (value == 0) + break; + continue; + } + if (value >= 0xD800 && value < 0xE000) + { + UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); + SzSkeepDataSize(sd, 2); + value = ((value - 0xD800) << 10) | (c2 - 0xDC00); + } + for (numAdds = 1; numAdds < 5; numAdds++) + if (value < (((UInt32)1) << (numAdds * 5 + 6))) + break; + file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); + do + { + numAdds--; + file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); + } + while(numAdds > 0); + + len += numAdds; + } + } + return SZ_OK; +} + +SZ_RESULT SzReadHeader2( + CSzData *sd, + CArchiveDatabaseEx *db, /* allocMain */ + CFileSize **unPackSizes, /* allocTemp */ + Byte **digestsDefined, /* allocTemp */ + UInt32 **digests, /* allocTemp */ + Byte **emptyStreamVector, /* allocTemp */ + Byte **emptyFileVector, /* allocTemp */ + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + UInt64 type; + UInt32 numUnPackStreams = 0; + UInt32 numFiles = 0; + CFileItem *files = 0; + UInt32 numEmptyStreams = 0; + UInt32 i; + + RINOK(SzReadID(sd, &type)); + + if (type == k7zIdArchiveProperties) + { + RINOK(SzReadArchiveProperties(sd)); + RINOK(SzReadID(sd, &type)); + } + + + if (type == k7zIdMainStreamsInfo) + { + RINOK(SzReadStreamsInfo(sd, + &db->ArchiveInfo.DataStartPosition, + &db->Database, + &numUnPackStreams, + unPackSizes, + digestsDefined, + digests, allocMain->Alloc, allocTemp)); + db->ArchiveInfo.DataStartPosition += db->ArchiveInfo.StartPositionAfterHeader; + RINOK(SzReadID(sd, &type)); + } + + if (type == k7zIdEnd) + return SZ_OK; + if (type != k7zIdFilesInfo) + return SZE_ARCHIVE_ERROR; + + RINOK(SzReadNumber32(sd, &numFiles)); + db->Database.NumFiles = numFiles; + + MY_ALLOC(CFileItem, files, (size_t)numFiles, allocMain->Alloc); + + db->Database.Files = files; + for(i = 0; i < numFiles; i++) + SzFileInit(files + i); + + while(1) + { + UInt64 type; + UInt64 size; + RINOK(SzReadID(sd, &type)); + if (type == k7zIdEnd) + break; + RINOK(SzReadNumber(sd, &size)); + + if ((UInt64)(int)type != type) + { + RINOK(SzSkeepDataSize(sd, size)); + } + else + switch((int)type) + { + case k7zIdName: + { + RINOK(SzReadSwitch(sd)); + RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) + break; + } + case k7zIdEmptyStream: + { + RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); + numEmptyStreams = 0; + for (i = 0; i < numFiles; i++) + if ((*emptyStreamVector)[i]) + numEmptyStreams++; + break; + } + case k7zIdEmptyFile: + { + RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); + break; + } + default: + { + RINOK(SzSkeepDataSize(sd, size)); + } + } + } + + { + UInt32 emptyFileIndex = 0; + UInt32 sizeIndex = 0; + for(i = 0; i < numFiles; i++) + { + CFileItem *file = files + i; + file->IsAnti = 0; + if (*emptyStreamVector == 0) + file->HasStream = 1; + else + file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); + if(file->HasStream) + { + file->IsDirectory = 0; + file->Size = (*unPackSizes)[sizeIndex]; + file->FileCRC = (*digests)[sizeIndex]; + file->IsFileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; + sizeIndex++; + } + else + { + if (*emptyFileVector == 0) + file->IsDirectory = 1; + else + file->IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); + emptyFileIndex++; + file->Size = 0; + file->IsFileCRCDefined = 0; + } + } + } + return SzArDbExFill(db, allocMain->Alloc); +} + +SZ_RESULT SzReadHeader( + CSzData *sd, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + CFileSize *unPackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + Byte *emptyStreamVector = 0; + Byte *emptyFileVector = 0; + SZ_RESULT res = SzReadHeader2(sd, db, + &unPackSizes, &digestsDefined, &digests, + &emptyStreamVector, &emptyFileVector, + allocMain, allocTemp); + allocTemp->Free(unPackSizes); + allocTemp->Free(digestsDefined); + allocTemp->Free(digests); + allocTemp->Free(emptyStreamVector); + allocTemp->Free(emptyFileVector); + return res; +} + +SZ_RESULT SzReadAndDecodePackedStreams2( + ISzInStream *inStream, + CSzData *sd, + CSzByteBuffer *outBuffer, + CFileSize baseOffset, + CArchiveDatabase *db, + CFileSize **unPackSizes, + Byte **digestsDefined, + UInt32 **digests, + #ifndef _LZMA_IN_CB + Byte **inBuffer, + #endif + ISzAlloc *allocTemp) +{ + + UInt32 numUnPackStreams = 0; + CFileSize dataStartPos; + CFolder *folder; + #ifndef _LZMA_IN_CB + CFileSize packSize = 0; + UInt32 i = 0; + #endif + CFileSize unPackSize; + size_t outRealSize; + SZ_RESULT res; + + RINOK(SzReadStreamsInfo(sd, &dataStartPos, db, + &numUnPackStreams, unPackSizes, digestsDefined, digests, + allocTemp->Alloc, allocTemp)); + + dataStartPos += baseOffset; + if (db->NumFolders != 1) + return SZE_ARCHIVE_ERROR; + + folder = db->Folders; + unPackSize = SzFolderGetUnPackSize(folder); + + RINOK(inStream->Seek(inStream, dataStartPos)); + + #ifndef _LZMA_IN_CB + for (i = 0; i < db->NumPackStreams; i++) + packSize += db->PackSizes[i]; + + MY_ALLOC(Byte, *inBuffer, (size_t)packSize, allocTemp->Alloc); + + RINOK(SafeReadDirect(inStream, *inBuffer, (size_t)packSize)); + #endif + + if (!SzByteBufferCreate(outBuffer, (size_t)unPackSize, allocTemp->Alloc)) + return SZE_OUTOFMEMORY; + + res = SzDecode(db->PackSizes, folder, + #ifdef _LZMA_IN_CB + inStream, + #else + *inBuffer, + #endif + outBuffer->Items, (size_t)unPackSize, + &outRealSize, allocTemp); + RINOK(res) + if (outRealSize != (UInt32)unPackSize) + return SZE_FAIL; + if (folder->UnPackCRCDefined) + if (!CrcVerifyDigest(folder->UnPackCRC, outBuffer->Items, (size_t)unPackSize)) + return SZE_FAIL; + return SZ_OK; +} + +SZ_RESULT SzReadAndDecodePackedStreams( + ISzInStream *inStream, + CSzData *sd, + CSzByteBuffer *outBuffer, + CFileSize baseOffset, + ISzAlloc *allocTemp) +{ + CArchiveDatabase db; + CFileSize *unPackSizes = 0; + Byte *digestsDefined = 0; + UInt32 *digests = 0; + #ifndef _LZMA_IN_CB + Byte *inBuffer = 0; + #endif + SZ_RESULT res; + SzArchiveDatabaseInit(&db); + res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, + &db, &unPackSizes, &digestsDefined, &digests, + #ifndef _LZMA_IN_CB + &inBuffer, + #endif + allocTemp); + SzArchiveDatabaseFree(&db, allocTemp->Free); + allocTemp->Free(unPackSizes); + allocTemp->Free(digestsDefined); + allocTemp->Free(digests); + #ifndef _LZMA_IN_CB + allocTemp->Free(inBuffer); + #endif + return res; +} + +SZ_RESULT SzArchiveOpen2( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + Byte signature[k7zSignatureSize]; + Byte version; + UInt32 crcFromArchive; + UInt64 nextHeaderOffset; + UInt64 nextHeaderSize; + UInt32 nextHeaderCRC; + UInt32 crc; + CFileSize pos = 0; + CSzByteBuffer buffer; + CSzData sd; + SZ_RESULT res; + + RINOK(SafeReadDirect(inStream, signature, k7zSignatureSize)); + + if (!TestSignatureCandidate(signature)) + return SZE_ARCHIVE_ERROR; + + /* + db.Clear(); + db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition; + */ + RINOK(SafeReadDirectByte(inStream, &version)); + if (version != k7zMajorVersion) + return SZE_ARCHIVE_ERROR; + RINOK(SafeReadDirectByte(inStream, &version)); + + RINOK(SafeReadDirectUInt32(inStream, &crcFromArchive)); + + CrcInit(&crc); + RINOK(SafeReadDirectUInt64(inStream, &nextHeaderOffset)); + CrcUpdateUInt64(&crc, nextHeaderOffset); + RINOK(SafeReadDirectUInt64(inStream, &nextHeaderSize)); + CrcUpdateUInt64(&crc, nextHeaderSize); + RINOK(SafeReadDirectUInt32(inStream, &nextHeaderCRC)); + CrcUpdateUInt32(&crc, nextHeaderCRC); + + pos = k7zStartHeaderSize; + db->ArchiveInfo.StartPositionAfterHeader = pos; + + if (CrcGetDigest(&crc) != crcFromArchive) + return SZE_ARCHIVE_ERROR; + + if (nextHeaderSize == 0) + return SZ_OK; + + RINOK(inStream->Seek(inStream, (CFileSize)(pos + nextHeaderOffset))); + + if (!SzByteBufferCreate(&buffer, (size_t)nextHeaderSize, allocTemp->Alloc)) + return SZE_OUTOFMEMORY; + + res = SafeReadDirect(inStream, buffer.Items, (size_t)nextHeaderSize); + if (res == SZ_OK) + { + if (CrcVerifyDigest(nextHeaderCRC, buffer.Items, (UInt32)nextHeaderSize)) + { + while (1) + { + UInt64 type; + sd.Data = buffer.Items; + sd.Size = buffer.Capacity; + res = SzReadID(&sd, &type); + if (res != SZ_OK) + break; + if (type == k7zIdHeader) + { + res = SzReadHeader(&sd, db, allocMain, allocTemp); + break; + } + if (type != k7zIdEncodedHeader) + { + res = SZE_ARCHIVE_ERROR; + break; + } + { + CSzByteBuffer outBuffer; + res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, + db->ArchiveInfo.StartPositionAfterHeader, + allocTemp); + if (res != SZ_OK) + { + SzByteBufferFree(&outBuffer, allocTemp->Free); + break; + } + SzByteBufferFree(&buffer, allocTemp->Free); + buffer.Items = outBuffer.Items; + buffer.Capacity = outBuffer.Capacity; + } + } + } + } + SzByteBufferFree(&buffer, allocTemp->Free); + return res; +} + +SZ_RESULT SzArchiveOpen( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp) +{ + SZ_RESULT res = SzArchiveOpen2(inStream, db, allocMain, allocTemp); + if (res != SZ_OK) + SzArDbExFree(db, allocMain->Free); + return res; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.h new file mode 100644 index 00000000..6bfa2a70 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zIn.h @@ -0,0 +1,55 @@ +/* 7zIn.h */ + +#ifndef __7Z_IN_H +#define __7Z_IN_H + +#include "7zHeader.h" +#include "7zItem.h" +#include "7zAlloc.h" + +typedef struct _CInArchiveInfo +{ + CFileSize StartPositionAfterHeader; + CFileSize DataStartPosition; +}CInArchiveInfo; + +typedef struct _CArchiveDatabaseEx +{ + CArchiveDatabase Database; + CInArchiveInfo ArchiveInfo; + UInt32 *FolderStartPackStreamIndex; + CFileSize *PackStreamStartPositions; + UInt32 *FolderStartFileIndex; + UInt32 *FileIndexToFolderIndexMap; +}CArchiveDatabaseEx; + +void SzArDbExInit(CArchiveDatabaseEx *db); +void SzArDbExFree(CArchiveDatabaseEx *db, void (*freeFunc)(void *)); +CFileSize SzArDbGetFolderStreamPos(CArchiveDatabaseEx *db, UInt32 folderIndex, UInt32 indexInFolder); +CFileSize SzArDbGetFolderFullPackSize(CArchiveDatabaseEx *db, UInt32 folderIndex); + +typedef struct _ISzInStream +{ + #ifdef _LZMA_IN_CB + SZ_RESULT (*Read)( + void *object, /* pointer to ISzInStream itself */ + void **buffer, /* out: pointer to buffer with data */ + size_t maxRequiredSize, /* max required size to read */ + size_t *processedSize); /* real processed size. + processedSize can be less than maxRequiredSize. + If processedSize == 0, then there are no more + bytes in stream. */ + #else + SZ_RESULT (*Read)(void *object, void *buffer, size_t size, size_t *processedSize); + #endif + SZ_RESULT (*Seek)(void *object, CFileSize pos); +} ISzInStream; + + +int SzArchiveOpen( + ISzInStream *inStream, + CArchiveDatabaseEx *db, + ISzAlloc *allocMain, + ISzAlloc *allocTemp); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.c new file mode 100644 index 00000000..2a408050 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.c @@ -0,0 +1,133 @@ +/* 7zItem.c */ + +#include "7zItem.h" +#include "7zAlloc.h" + +void SzCoderInfoInit(CCoderInfo *coder) +{ + SzByteBufferInit(&coder->Properties); +} + +void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)) +{ + SzByteBufferFree(&coder->Properties, freeFunc); + SzCoderInfoInit(coder); +} + +void SzFolderInit(CFolder *folder) +{ + folder->NumCoders = 0; + folder->Coders = 0; + folder->NumBindPairs = 0; + folder->BindPairs = 0; + folder->NumPackStreams = 0; + folder->PackStreams = 0; + folder->UnPackSizes = 0; + folder->UnPackCRCDefined = 0; + folder->UnPackCRC = 0; + folder->NumUnPackStreams = 0; +} + +void SzFolderFree(CFolder *folder, void (*freeFunc)(void *p)) +{ + UInt32 i; + for (i = 0; i < folder->NumCoders; i++) + SzCoderInfoFree(&folder->Coders[i], freeFunc); + freeFunc(folder->Coders); + freeFunc(folder->BindPairs); + freeFunc(folder->PackStreams); + freeFunc(folder->UnPackSizes); + SzFolderInit(folder); +} + +UInt32 SzFolderGetNumOutStreams(CFolder *folder) +{ + UInt32 result = 0; + UInt32 i; + for (i = 0; i < folder->NumCoders; i++) + result += folder->Coders[i].NumOutStreams; + return result; +} + +int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex) +{ + UInt32 i; + for(i = 0; i < folder->NumBindPairs; i++) + if (folder->BindPairs[i].InIndex == inStreamIndex) + return i; + return -1; +} + + +int SzFolderFindBindPairForOutStream(CFolder *folder, UInt32 outStreamIndex) +{ + UInt32 i; + for(i = 0; i < folder->NumBindPairs; i++) + if (folder->BindPairs[i].OutIndex == outStreamIndex) + return i; + return -1; +} + +CFileSize SzFolderGetUnPackSize(CFolder *folder) +{ + int i = (int)SzFolderGetNumOutStreams(folder); + if (i == 0) + return 0; + for (i--; i >= 0; i--) + if (SzFolderFindBindPairForOutStream(folder, i) < 0) + return folder->UnPackSizes[i]; + /* throw 1; */ + return 0; +} + +/* +int FindPackStreamArrayIndex(int inStreamIndex) const +{ + for(int i = 0; i < PackStreams.Size(); i++) + if (PackStreams[i] == inStreamIndex) + return i; + return -1; +} +*/ + +void SzFileInit(CFileItem *fileItem) +{ + fileItem->IsFileCRCDefined = 0; + fileItem->HasStream = 1; + fileItem->IsDirectory = 0; + fileItem->IsAnti = 0; + fileItem->Name = 0; +} + +void SzFileFree(CFileItem *fileItem, void (*freeFunc)(void *p)) +{ + freeFunc(fileItem->Name); + SzFileInit(fileItem); +} + +void SzArchiveDatabaseInit(CArchiveDatabase *db) +{ + db->NumPackStreams = 0; + db->PackSizes = 0; + db->PackCRCsDefined = 0; + db->PackCRCs = 0; + db->NumFolders = 0; + db->Folders = 0; + db->NumFiles = 0; + db->Files = 0; +} + +void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)) +{ + UInt32 i; + for (i = 0; i < db->NumFolders; i++) + SzFolderFree(&db->Folders[i], freeFunc); + for (i = 0; i < db->NumFiles; i++) + SzFileFree(&db->Files[i], freeFunc); + freeFunc(db->PackSizes); + freeFunc(db->PackCRCsDefined); + freeFunc(db->PackCRCs); + freeFunc(db->Folders); + freeFunc(db->Files); + SzArchiveDatabaseInit(db); +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.h new file mode 100644 index 00000000..876539a9 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zItem.h @@ -0,0 +1,90 @@ +/* 7zItem.h */ + +#ifndef __7Z_ITEM_H +#define __7Z_ITEM_H + +#include "7zMethodID.h" +#include "7zHeader.h" +#include "7zBuffer.h" + +typedef struct _CCoderInfo +{ + UInt32 NumInStreams; + UInt32 NumOutStreams; + CMethodID MethodID; + CSzByteBuffer Properties; +}CCoderInfo; + +void SzCoderInfoInit(CCoderInfo *coder); +void SzCoderInfoFree(CCoderInfo *coder, void (*freeFunc)(void *p)); + +typedef struct _CBindPair +{ + UInt32 InIndex; + UInt32 OutIndex; +}CBindPair; + +typedef struct _CFolder +{ + UInt32 NumCoders; + CCoderInfo *Coders; + UInt32 NumBindPairs; + CBindPair *BindPairs; + UInt32 NumPackStreams; + UInt32 *PackStreams; + CFileSize *UnPackSizes; + int UnPackCRCDefined; + UInt32 UnPackCRC; + + UInt32 NumUnPackStreams; +}CFolder; + +void SzFolderInit(CFolder *folder); +CFileSize SzFolderGetUnPackSize(CFolder *folder); +int SzFolderFindBindPairForInStream(CFolder *folder, UInt32 inStreamIndex); +UInt32 SzFolderGetNumOutStreams(CFolder *folder); +CFileSize SzFolderGetUnPackSize(CFolder *folder); + +/* #define CArchiveFileTime UInt64 */ + +typedef struct _CFileItem +{ + /* + CArchiveFileTime LastWriteTime; + CFileSize StartPos; + UInt32 Attributes; + */ + CFileSize Size; + UInt32 FileCRC; + char *Name; + + Byte IsFileCRCDefined; + Byte HasStream; + Byte IsDirectory; + Byte IsAnti; + /* + int AreAttributesDefined; + int IsLastWriteTimeDefined; + int IsStartPosDefined; + */ +}CFileItem; + +void SzFileInit(CFileItem *fileItem); + +typedef struct _CArchiveDatabase +{ + UInt32 NumPackStreams; + CFileSize *PackSizes; + Byte *PackCRCsDefined; + UInt32 *PackCRCs; + UInt32 NumFolders; + CFolder *Folders; + UInt32 NumFiles; + CFileItem *Files; +}CArchiveDatabase; + +void SzArchiveDatabaseInit(CArchiveDatabase *db); +void SzArchiveDatabaseFree(CArchiveDatabase *db, void (*freeFunc)(void *)); + + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMain.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMain.c new file mode 100644 index 00000000..73bf36bb --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMain.c @@ -0,0 +1,225 @@ +/* +7zMain.c +Test application for 7z Decoder +LZMA SDK 4.43 Copyright (c) 1999-2006 Igor Pavlov (2006-06-04) +*/ + +#include +#include +#include + +#include "7zCrc.h" +#include "7zIn.h" +#include "7zExtract.h" + +typedef struct _CFileInStream +{ + ISzInStream InStream; + FILE *File; +} CFileInStream; + +#ifdef _LZMA_IN_CB + +#define kBufferSize (1 << 12) +Byte g_Buffer[kBufferSize]; + +SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) +{ + CFileInStream *s = (CFileInStream *)object; + size_t processedSizeLoc; + if (maxRequiredSize > kBufferSize) + maxRequiredSize = kBufferSize; + processedSizeLoc = fread(g_Buffer, 1, maxRequiredSize, s->File); + *buffer = g_Buffer; + if (processedSize != 0) + *processedSize = processedSizeLoc; + return SZ_OK; +} + +#else + +SZ_RESULT SzFileReadImp(void *object, void *buffer, size_t size, size_t *processedSize) +{ + CFileInStream *s = (CFileInStream *)object; + size_t processedSizeLoc = fread(buffer, 1, size, s->File); + if (processedSize != 0) + *processedSize = processedSizeLoc; + return SZ_OK; +} + +#endif + +SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) +{ + CFileInStream *s = (CFileInStream *)object; + int res = fseek(s->File, (long)pos, SEEK_SET); + if (res == 0) + return SZ_OK; + return SZE_FAIL; +} + +void PrintError(char *sz) +{ + printf("\nERROR: %s\n", sz); +} + +int main(int numargs, char *args[]) +{ + CFileInStream archiveStream; + CArchiveDatabaseEx db; + SZ_RESULT res; + ISzAlloc allocImp; + ISzAlloc allocTempImp; + + printf("\n7z ANSI-C Decoder 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04\n"); + if (numargs == 1) + { + printf( + "\nUsage: 7zDec \n\n" + "\n" + " e: Extract files from archive\n" + " l: List contents of archive\n" + " t: Test integrity of archive\n"); + return 0; + } + if (numargs < 3) + { + PrintError("incorrect command"); + return 1; + } + + archiveStream.File = fopen(args[2], "rb"); + if (archiveStream.File == 0) + { + PrintError("can not open input file"); + return 1; + } + + archiveStream.InStream.Read = SzFileReadImp; + archiveStream.InStream.Seek = SzFileSeekImp; + + allocImp.Alloc = SzAlloc; + allocImp.Free = SzFree; + + allocTempImp.Alloc = SzAllocTemp; + allocTempImp.Free = SzFreeTemp; + + InitCrcTable(); + SzArDbExInit(&db); + res = SzArchiveOpen(&archiveStream.InStream, &db, &allocImp, &allocTempImp); + if (res == SZ_OK) + { + char *command = args[1]; + int listCommand = 0; + int testCommand = 0; + int extractCommand = 0; + if (strcmp(command, "l") == 0) + listCommand = 1; + if (strcmp(command, "t") == 0) + testCommand = 1; + else if (strcmp(command, "e") == 0) + extractCommand = 1; + + if (listCommand) + { + UInt32 i; + for (i = 0; i < db.Database.NumFiles; i++) + { + CFileItem *f = db.Database.Files + i; + printf("%10d %s\n", (int)f->Size, f->Name); + } + } + else if (testCommand || extractCommand) + { + UInt32 i; + + /* + if you need cache, use these 3 variables. + if you use external function, you can make these variable as static. + */ + UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */ + Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */ + size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */ + + printf("\n"); + for (i = 0; i < db.Database.NumFiles; i++) + { + size_t offset; + size_t outSizeProcessed; + CFileItem *f = db.Database.Files + i; + if (f->IsDirectory) + printf("Directory "); + else + printf(testCommand ? + "Testing ": + "Extracting"); + printf(" %s", f->Name); + if (f->IsDirectory) + { + printf("\n"); + continue; + } + res = SzExtract(&archiveStream.InStream, &db, i, + &blockIndex, &outBuffer, &outBufferSize, + &offset, &outSizeProcessed, + &allocImp, &allocTempImp); + if (res != SZ_OK) + break; + if (!testCommand) + { + FILE *outputHandle; + UInt32 processedSize; + char *fileName = f->Name; + size_t nameLen = strlen(f->Name); + for (; nameLen > 0; nameLen--) + if (f->Name[nameLen - 1] == '/') + { + fileName = f->Name + nameLen; + break; + } + + outputHandle = fopen(fileName, "wb+"); + if (outputHandle == 0) + { + PrintError("can not open output file"); + res = SZE_FAIL; + break; + } + processedSize = fwrite(outBuffer + offset, 1, outSizeProcessed, outputHandle); + if (processedSize != outSizeProcessed) + { + PrintError("can not write output file"); + res = SZE_FAIL; + break; + } + if (fclose(outputHandle)) + { + PrintError("can not close output file"); + res = SZE_FAIL; + break; + } + } + printf("\n"); + } + allocImp.Free(outBuffer); + } + else + { + PrintError("incorrect command"); + res = SZE_FAIL; + } + } + SzArDbExFree(&db, allocImp.Free); + + fclose(archiveStream.File); + if (res == SZ_OK) + { + printf("\nEverything is Ok\n"); + return 0; + } + if (res == SZE_OUTOFMEMORY) + PrintError("can not allocate memory"); + else + printf("\nERROR #%d\n", res); + return 1; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.c b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.c new file mode 100644 index 00000000..5047359f --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.c @@ -0,0 +1,14 @@ +/* 7zMethodID.c */ + +#include "7zMethodID.h" + +int AreMethodsEqual(CMethodID *a1, CMethodID *a2) +{ + int i; + if (a1->IDSize != a2->IDSize) + return 0; + for (i = 0; i < a1->IDSize; i++) + if (a1->ID[i] != a2->ID[i]) + return 0; + return 1; +} diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.h new file mode 100644 index 00000000..162fcd15 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zMethodID.h @@ -0,0 +1,18 @@ +/* 7zMethodID.h */ + +#ifndef __7Z_METHOD_ID_H +#define __7Z_METHOD_ID_H + +#include "7zTypes.h" + +#define kMethodIDSize 15 + +typedef struct _CMethodID +{ + Byte ID[kMethodIDSize]; + Byte IDSize; +} CMethodID; + +int AreMethodsEqual(CMethodID *a1, CMethodID *a2); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zTypes.h b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zTypes.h new file mode 100644 index 00000000..60dd68c3 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7zTypes.h @@ -0,0 +1,67 @@ +/* 7zTypes.h */ + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _SZ_NO_INT_64 */ +/* define it your compiler doesn't support long long int */ + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +#ifdef _SZ_NO_INT_64 +typedef unsigned long UInt64; +#else +#ifdef _MSC_VER +typedef unsigned __int64 UInt64; +#else +typedef unsigned long long int UInt64; +#endif +#endif +#endif + + +/* #define _SZ_FILE_SIZE_64 */ +/* Use _SZ_FILE_SIZE_64 if you need support for files larger than 4 GB*/ + +#ifndef CFileSize +#ifdef _SZ_FILE_SIZE_64 +typedef UInt64 CFileSize; +#else +typedef UInt32 CFileSize; +#endif +#endif + +#define SZ_RESULT int + +#define SZ_OK (0) +#define SZE_DATA_ERROR (1) +#define SZE_OUTOFMEMORY (2) +#define SZE_CRC_ERROR (3) + +#define SZE_NOTIMPL (4) +#define SZE_FAIL (5) + +#define SZE_ARCHIVE_ERROR (6) + +#define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsp b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsp new file mode 100644 index 00000000..cf45463e --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsp @@ -0,0 +1,182 @@ +# Microsoft Developer Studio Project File - Name="7z_C" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=7z_C - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "7z_C.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "7z_C.mak" CFG="7z_C - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "7z_C - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "7z_C - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "7z_C - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W4 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/7zDec.exe" + +!ELSEIF "$(CFG)" == "7z_C - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "_LZMA_PROB32" /D "_LZMA_IN_CB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/7zDec.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "7z_C - Win32 Release" +# Name "7z_C - Win32 Debug" +# Begin Group "LZMA" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\LZMA_C\LzmaDecode.c +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LZMA_C\LzmaDecode.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LZMA_C\LzmaTypes.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\7zAlloc.c +# End Source File +# Begin Source File + +SOURCE=.\7zAlloc.h +# End Source File +# Begin Source File + +SOURCE=.\7zBuffer.c +# End Source File +# Begin Source File + +SOURCE=.\7zBuffer.h +# End Source File +# Begin Source File + +SOURCE=.\7zCrc.c +# End Source File +# Begin Source File + +SOURCE=.\7zCrc.h +# End Source File +# Begin Source File + +SOURCE=.\7zDecode.c +# End Source File +# Begin Source File + +SOURCE=.\7zDecode.h +# End Source File +# Begin Source File + +SOURCE=.\7zExtract.c +# End Source File +# Begin Source File + +SOURCE=.\7zExtract.h +# End Source File +# Begin Source File + +SOURCE=.\7zHeader.c +# End Source File +# Begin Source File + +SOURCE=.\7zHeader.h +# End Source File +# Begin Source File + +SOURCE=.\7zIn.c +# End Source File +# Begin Source File + +SOURCE=.\7zIn.h +# End Source File +# Begin Source File + +SOURCE=.\7zItem.c +# End Source File +# Begin Source File + +SOURCE=.\7zItem.h +# End Source File +# Begin Source File + +SOURCE=.\7zMain.c +# End Source File +# Begin Source File + +SOURCE=.\7zMethodID.c +# End Source File +# Begin Source File + +SOURCE=.\7zMethodID.h +# End Source File +# Begin Source File + +SOURCE=.\7zTypes.h +# End Source File +# End Target +# End Project diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsw b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsw new file mode 100644 index 00000000..6fd39621 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/7z_C.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "7z_C"=.\7z_C.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile b/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile new file mode 100644 index 00000000..9ce2c346 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile @@ -0,0 +1,55 @@ +PROG = 7zDec.exe + +!IFNDEF O +!IFDEF CPU +O=$(CPU) +!ELSE +O=O +!ENDIF +!ENDIF + +CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- +CFLAGS_O1 = $(CFLAGS) -O1 +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 + +PROGPATH = $O\$(PROG) + +COMPL_O1 = $(CPP) $(CFLAGS_O1) $** +COMPL_O2 = $(CPP) $(CFLAGS_O2) $** +COMPL = $(CPP) $(CFLAGS_O1) $** + + +7Z_OBJS = \ + $O\7zAlloc.obj \ + $O\7zBuffer.obj \ + $O\7zCrc.obj \ + $O\7zDecode.obj \ + $O\7zExtract.obj \ + $O\7zHeader.obj \ + $O\7zIn.obj \ + $O\7zItem.obj \ + $O\7zMain.obj \ + $O\7zMethodID.obj \ + +OBJS = \ + $(7Z_OBJS) \ + $O\LzmaDecode.obj \ + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch + +$O: + if not exist "$O" mkdir "$O" + +$(PROGPATH): $O $(OBJS) + link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) + + +$(7Z_OBJS): $(*B).c + $(COMPL) +$O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c + $(COMPL_O2) diff --git a/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile.gcc b/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile.gcc new file mode 100644 index 00000000..21b7df47 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Archive/7z_C/makefile.gcc @@ -0,0 +1,50 @@ +PROG = 7zDec +CXX = g++ +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall + +OBJS = 7zAlloc.o 7zBuffer.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o 7zMethodID.o LzmaDecode.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +7zAlloc.o: 7zAlloc.c + $(CXX) $(CFLAGS) 7zAlloc.c + +7zBuffer.o: 7zBuffer.c + $(CXX) $(CFLAGS) 7zBuffer.c + +7zCrc.o: 7zCrc.c + $(CXX) $(CFLAGS) 7zCrc.c + +7zDecode.o: 7zDecode.c + $(CXX) $(CFLAGS) 7zDecode.c + +7zExtract.o: 7zExtract.c + $(CXX) $(CFLAGS) 7zExtract.c + +7zHeader.o: 7zHeader.c + $(CXX) $(CFLAGS) 7zHeader.c + +7zIn.o: 7zIn.c + $(CXX) $(CFLAGS) 7zIn.c + +7zItem.o: 7zItem.c + $(CXX) $(CFLAGS) 7zItem.c + +7zMain.o: 7zMain.c + $(CXX) $(CFLAGS) 7zMain.c + +7zMethodID.o: 7zMethodID.c + $(CXX) $(CFLAGS) 7zMethodID.c + +LzmaDecode.o: ../../Compress/LZMA_C/LzmaDecode.c + $(CXX) $(CFLAGS) ../../Compress/LZMA_C/LzmaDecode.c + + +clean: + -$(RM) $(PROG) $(OBJS) + diff --git a/sp/src/utils/lzma/C/7zip/Common/FileStreams.cpp b/sp/src/utils/lzma/C/7zip/Common/FileStreams.cpp new file mode 100644 index 00000000..8a000e4e --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/FileStreams.cpp @@ -0,0 +1,251 @@ +// FileStreams.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 +#include +#include +#include +#endif + +#include "FileStreams.h" + +static inline HRESULT ConvertBoolToHRESULT(bool result) +{ + // return result ? S_OK: E_FAIL; + #ifdef _WIN32 + return result ? S_OK: (::GetLastError()); + #else + return result ? S_OK: E_FAIL; + #endif +} + +bool CInFileStream::Open(LPCTSTR fileName) +{ + return File.Open(fileName); +} + +#ifdef _WIN32 +#ifndef _UNICODE +bool CInFileStream::Open(LPCWSTR fileName) +{ + return File.Open(fileName); +} +#endif +#endif + +STDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef _WIN32 + + UInt32 realProcessedSize; + bool result = File.ReadPart(data, size, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return ConvertBoolToHRESULT(result); + + #else + + if(processedSize != NULL) + *processedSize = 0; + ssize_t res = File.Read(data, (size_t)size); + if (res == -1) + return E_FAIL; + if(processedSize != NULL) + *processedSize = (UInt32)res; + return S_OK; + + #endif +} + +#ifndef _WIN32_WCE +STDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef _WIN32 + UInt32 realProcessedSize; + BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), + data, size, (DWORD *)&realProcessedSize, NULL); + if(processedSize != NULL) + *processedSize = realProcessedSize; + if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE) + return S_OK; + return ConvertBoolToHRESULT(res != FALSE); + + #else + + if(processedSize != NULL) + *processedSize = 0; + ssize_t res; + do + { + res = read(0, data, (size_t)size); + } + while (res < 0 && (errno == EINTR)); + if (res == -1) + return E_FAIL; + if(processedSize != NULL) + *processedSize = (UInt32)res; + return S_OK; + + #endif +} + +#endif + +STDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, + UInt64 *newPosition) +{ + if(seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + + #ifdef _WIN32 + + UInt64 realNewPosition; + bool result = File.Seek(offset, seekOrigin, realNewPosition); + if(newPosition != NULL) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.Seek(offset, seekOrigin); + if (res == -1) + return E_FAIL; + if(newPosition != NULL) + *newPosition = (UInt64)res; + return S_OK; + + #endif +} + +STDMETHODIMP CInFileStream::GetSize(UInt64 *size) +{ + return ConvertBoolToHRESULT(File.GetLength(*size)); +} + + +////////////////////////// +// COutFileStream + +bool COutFileStream::Create(LPCTSTR fileName, bool createAlways) +{ + return File.Create(fileName, createAlways); +} + +#ifdef _WIN32 +#ifndef _UNICODE +bool COutFileStream::Create(LPCWSTR fileName, bool createAlways) +{ + return File.Create(fileName, createAlways); +} +#endif +#endif + +STDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + #ifdef _WIN32 + + UInt32 realProcessedSize; + bool result = File.WritePart(data, size, realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + return ConvertBoolToHRESULT(result); + + #else + + if(processedSize != NULL) + *processedSize = 0; + ssize_t res = File.Write(data, (size_t)size); + if (res == -1) + return E_FAIL; + if(processedSize != NULL) + *processedSize = (UInt32)res; + return S_OK; + + #endif +} + +STDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, + UInt64 *newPosition) +{ + if(seekOrigin >= 3) + return STG_E_INVALIDFUNCTION; + #ifdef _WIN32 + + UInt64 realNewPosition; + bool result = File.Seek(offset, seekOrigin, realNewPosition); + if(newPosition != NULL) + *newPosition = realNewPosition; + return ConvertBoolToHRESULT(result); + + #else + + off_t res = File.Seek(offset, seekOrigin); + if (res == -1) + return E_FAIL; + if(newPosition != NULL) + *newPosition = (UInt64)res; + return S_OK; + + #endif +} + +STDMETHODIMP COutFileStream::SetSize(Int64 newSize) +{ + #ifdef _WIN32 + UInt64 currentPos; + if(!File.Seek(0, FILE_CURRENT, currentPos)) + return E_FAIL; + bool result = File.SetLength(newSize); + UInt64 currentPos2; + result = result && File.Seek(currentPos, currentPos2); + return result ? S_OK : E_FAIL; + #else + return E_FAIL; + #endif +} + +#ifndef _WIN32_WCE +STDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + if(processedSize != NULL) + *processedSize = 0; + + #ifdef _WIN32 + UInt32 realProcessedSize; + BOOL res = TRUE; + if (size > 0) + { + // Seems that Windows doesn't like big amounts writing to stdout. + // So we limit portions by 32KB. + UInt32 sizeTemp = (1 << 15); + if (sizeTemp > size) + sizeTemp = size; + res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), + data, sizeTemp, (DWORD *)&realProcessedSize, NULL); + size -= realProcessedSize; + data = (const void *)((const Byte *)data + realProcessedSize); + if(processedSize != NULL) + *processedSize += realProcessedSize; + } + return ConvertBoolToHRESULT(res != FALSE); + + #else + + ssize_t res; + do + { + res = write(1, data, (size_t)size); + } + while (res < 0 && (errno == EINTR)); + if (res == -1) + return E_FAIL; + if(processedSize != NULL) + *processedSize = (UInt32)res; + return S_OK; + + return S_OK; + #endif +} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Common/FileStreams.h b/sp/src/utils/lzma/C/7zip/Common/FileStreams.h new file mode 100644 index 00000000..9326372a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/FileStreams.h @@ -0,0 +1,98 @@ +// FileStreams.h + +#ifndef __FILESTREAMS_H +#define __FILESTREAMS_H + +#ifdef _WIN32 +#include "../../Windows/FileIO.h" +#else +#include "../../Common/C_FileIO.h" +#endif + +#include "../IStream.h" +#include "../../Common/MyCom.h" + +class CInFileStream: + public IInStream, + public IStreamGetSize, + public CMyUnknownImp +{ +public: + #ifdef _WIN32 + NWindows::NFile::NIO::CInFile File; + #else + NC::NFile::NIO::CInFile File; + #endif + CInFileStream() {} + virtual ~CInFileStream() {} + + bool Open(LPCTSTR fileName); + #ifdef _WIN32 + #ifndef _UNICODE + bool Open(LPCWSTR fileName); + #endif + #endif + + MY_UNKNOWN_IMP2(IInStream, IStreamGetSize) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + + STDMETHOD(GetSize)(UInt64 *size); +}; + +#ifndef _WIN32_WCE +class CStdInFileStream: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + // HANDLE File; + // CStdInFileStream() File(INVALID_HANDLE_VALUE): {} + // void Open() { File = GetStdHandle(STD_INPUT_HANDLE); }; + MY_UNKNOWN_IMP + + virtual ~CStdInFileStream() {} + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; +#endif + +class COutFileStream: + public IOutStream, + public CMyUnknownImp +{ +public: + #ifdef _WIN32 + NWindows::NFile::NIO::COutFile File; + #else + NC::NFile::NIO::COutFile File; + #endif + virtual ~COutFileStream() {} + bool Create(LPCTSTR fileName, bool createAlways); + #ifdef _WIN32 + #ifndef _UNICODE + bool Create(LPCWSTR fileName, bool createAlways); + #endif + #endif + + MY_UNKNOWN_IMP1(IOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition); + STDMETHOD(SetSize)(Int64 newSize); +}; + +#ifndef _WIN32_WCE +class CStdOutFileStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP + + virtual ~CStdOutFileStream() {} + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; +#endif + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Common/InBuffer.cpp b/sp/src/utils/lzma/C/7zip/Common/InBuffer.cpp new file mode 100644 index 00000000..02f2adfa --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/InBuffer.cpp @@ -0,0 +1,80 @@ +// InBuffer.cpp + +#include "StdAfx.h" + +#include "InBuffer.h" + +#include "../../Common/Alloc.h" + +CInBuffer::CInBuffer(): + _buffer(0), + _bufferLimit(0), + _bufferBase(0), + _stream(0), + _bufferSize(0) +{} + +bool CInBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_bufferBase != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _bufferBase = (Byte *)::MidAlloc(bufferSize); + return (_bufferBase != 0); +} + +void CInBuffer::Free() +{ + ::MidFree(_bufferBase); + _bufferBase = 0; +} + +void CInBuffer::SetStream(ISequentialInStream *stream) +{ + _stream = stream; +} + +void CInBuffer::Init() +{ + _processedSize = 0; + _buffer = _bufferBase; + _bufferLimit = _buffer; + _wasFinished = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +bool CInBuffer::ReadBlock() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return false; + #endif + if (_wasFinished) + return false; + _processedSize += (_buffer - _bufferBase); + UInt32 numProcessedBytes; + HRESULT result = _stream->Read(_bufferBase, _bufferSize, &numProcessedBytes); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw CInBufferException(result); + #endif + _buffer = _bufferBase; + _bufferLimit = _buffer + numProcessedBytes; + _wasFinished = (numProcessedBytes == 0); + return (!_wasFinished); +} + +Byte CInBuffer::ReadBlock2() +{ + if(!ReadBlock()) + return 0xFF; + return *_buffer++; +} diff --git a/sp/src/utils/lzma/C/7zip/Common/InBuffer.h b/sp/src/utils/lzma/C/7zip/Common/InBuffer.h new file mode 100644 index 00000000..057caa16 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/InBuffer.h @@ -0,0 +1,76 @@ +// InBuffer.h + +#ifndef __INBUFFER_H +#define __INBUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" + +#ifndef _NO_EXCEPTIONS +class CInBufferException +{ +public: + HRESULT ErrorCode; + CInBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; +#endif + +class CInBuffer +{ + Byte *_buffer; + Byte *_bufferLimit; + Byte *_bufferBase; + CMyComPtr _stream; + UInt64 _processedSize; + UInt32 _bufferSize; + bool _wasFinished; + + bool ReadBlock(); + Byte ReadBlock2(); + +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + CInBuffer(); + ~CInBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetStream(ISequentialInStream *stream); + void Init(); + void ReleaseStream() { _stream.Release(); } + + bool ReadByte(Byte &b) + { + if(_buffer >= _bufferLimit) + if(!ReadBlock()) + return false; + b = *_buffer++; + return true; + } + Byte ReadByte() + { + if(_buffer >= _bufferLimit) + return ReadBlock2(); + return *_buffer++; + } + void ReadBytes(void *data, UInt32 size, UInt32 &processedSize) + { + for(processedSize = 0; processedSize < size; processedSize++) + if (!ReadByte(((Byte *)data)[processedSize])) + return; + } + bool ReadBytes(void *data, UInt32 size) + { + UInt32 processedSize; + ReadBytes(data, size, processedSize); + return (processedSize == size); + } + UInt64 GetProcessedSize() const { return _processedSize + (_buffer - _bufferBase); } + bool WasFinished() const { return _wasFinished; } +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Common/OutBuffer.cpp b/sp/src/utils/lzma/C/7zip/Common/OutBuffer.cpp new file mode 100644 index 00000000..a73fa7c5 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/OutBuffer.cpp @@ -0,0 +1,116 @@ +// OutByte.cpp + +#include "StdAfx.h" + +#include "OutBuffer.h" + +#include "../../Common/Alloc.h" + +bool COutBuffer::Create(UInt32 bufferSize) +{ + const UInt32 kMinBlockSize = 1; + if (bufferSize < kMinBlockSize) + bufferSize = kMinBlockSize; + if (_buffer != 0 && _bufferSize == bufferSize) + return true; + Free(); + _bufferSize = bufferSize; + _buffer = (Byte *)::MidAlloc(bufferSize); + return (_buffer != 0); +} + +void COutBuffer::Free() +{ + ::MidFree(_buffer); + _buffer = 0; +} + +void COutBuffer::SetStream(ISequentialOutStream *stream) +{ + _stream = stream; +} + +void COutBuffer::Init() +{ + _streamPos = 0; + _limitPos = _bufferSize; + _pos = 0; + _processedSize = 0; + _overDict = false; + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + +UInt64 COutBuffer::GetProcessedSize() const +{ + UInt64 res = _processedSize + _pos - _streamPos; + if (_streamPos > _pos) + res += _bufferSize; + return res; +} + + +HRESULT COutBuffer::FlushPart() +{ + // _streamPos < _bufferSize + UInt32 size = (_streamPos >= _pos) ? (_bufferSize - _streamPos) : (_pos - _streamPos); + HRESULT result = S_OK; + #ifdef _NO_EXCEPTIONS + result = ErrorCode; + #endif + if (_buffer2 != 0) + { + memmove(_buffer2, _buffer + _streamPos, size); + _buffer2 += size; + } + + if (_stream != 0 + #ifdef _NO_EXCEPTIONS + && (ErrorCode == S_OK) + #endif + ) + { + UInt32 processedSize = 0; + result = _stream->Write(_buffer + _streamPos, size, &processedSize); + size = processedSize; + } + _streamPos += size; + if (_streamPos == _bufferSize) + _streamPos = 0; + if (_pos == _bufferSize) + { + _overDict = true; + _pos = 0; + } + _limitPos = (_streamPos > _pos) ? _streamPos : _bufferSize; + _processedSize += size; + return result; +} + +HRESULT COutBuffer::Flush() +{ + #ifdef _NO_EXCEPTIONS + if (ErrorCode != S_OK) + return ErrorCode; + #endif + + while(_streamPos != _pos) + { + HRESULT result = FlushPart(); + if (result != S_OK) + return result; + } + return S_OK; +} + +void COutBuffer::FlushWithCheck() +{ + HRESULT result = FlushPart(); + #ifdef _NO_EXCEPTIONS + ErrorCode = result; + #else + if (result != S_OK) + throw COutBufferException(result); + #endif +} diff --git a/sp/src/utils/lzma/C/7zip/Common/OutBuffer.h b/sp/src/utils/lzma/C/7zip/Common/OutBuffer.h new file mode 100644 index 00000000..0ce54e21 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/OutBuffer.h @@ -0,0 +1,64 @@ +// OutBuffer.h + +#ifndef __OUTBUFFER_H +#define __OUTBUFFER_H + +#include "../IStream.h" +#include "../../Common/MyCom.h" + +#ifndef _NO_EXCEPTIONS +struct COutBufferException +{ + HRESULT ErrorCode; + COutBufferException(HRESULT errorCode): ErrorCode(errorCode) {} +}; +#endif + +class COutBuffer +{ +protected: + Byte *_buffer; + UInt32 _pos; + UInt32 _limitPos; + UInt32 _streamPos; + UInt32 _bufferSize; + CMyComPtr _stream; + UInt64 _processedSize; + Byte *_buffer2; + bool _overDict; + + HRESULT FlushPart(); + void FlushWithCheck(); +public: + #ifdef _NO_EXCEPTIONS + HRESULT ErrorCode; + #endif + + COutBuffer(): _buffer(0), _pos(0), _stream(0), _buffer2(0) {} + ~COutBuffer() { Free(); } + + bool Create(UInt32 bufferSize); + void Free(); + + void SetMemStream(Byte *buffer) { _buffer2 = buffer; } + void SetStream(ISequentialOutStream *stream); + void Init(); + HRESULT Flush(); + void ReleaseStream() { _stream.Release(); } + + void WriteByte(Byte b) + { + _buffer[_pos++] = b; + if(_pos == _limitPos) + FlushWithCheck(); + } + void WriteBytes(const void *data, size_t size) + { + for (size_t i = 0; i < size; i++) + WriteByte(((const Byte *)data)[i]); + } + + UInt64 GetProcessedSize() const; +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Common/StdAfx.h b/sp/src/utils/lzma/C/7zip/Common/StdAfx.h new file mode 100644 index 00000000..27a77b10 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../Common/MyWindows.h" +#include "../../Common/NewHandler.h" + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Common/StreamUtils.cpp b/sp/src/utils/lzma/C/7zip/Common/StreamUtils.cpp new file mode 100644 index 00000000..a5d9ac0e --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/StreamUtils.cpp @@ -0,0 +1,44 @@ +// StreamUtils.cpp + +#include "StdAfx.h" + +#include "../../Common/MyCom.h" +#include "StreamUtils.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Read(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (Byte *)((Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + return S_OK; + } + return S_OK; +} + +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize) +{ + if (processedSize != 0) + *processedSize = 0; + while(size != 0) + { + UInt32 processedSizeLoc; + HRESULT res = stream->Write(data, size, &processedSizeLoc); + if (processedSize != 0) + *processedSize += processedSizeLoc; + data = (const void *)((const Byte *)data + processedSizeLoc); + size -= processedSizeLoc; + RINOK(res); + if (processedSizeLoc == 0) + break; + } + return S_OK; +} diff --git a/sp/src/utils/lzma/C/7zip/Common/StreamUtils.h b/sp/src/utils/lzma/C/7zip/Common/StreamUtils.h new file mode 100644 index 00000000..59f88733 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Common/StreamUtils.h @@ -0,0 +1,11 @@ +// StreamUtils.h + +#ifndef __STREAMUTILS_H +#define __STREAMUTILS_H + +#include "../IStream.h" + +HRESULT ReadStream(ISequentialInStream *stream, void *data, UInt32 size, UInt32 *processedSize); +HRESULT WriteStream(ISequentialOutStream *stream, const void *data, UInt32 size, UInt32 *processedSize); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.cpp new file mode 100644 index 00000000..4bd5e183 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.cpp @@ -0,0 +1,16 @@ +// ARM.cpp + +#include "StdAfx.h" +#include "ARM.h" + +#include "BranchARM.c" + +UInt32 CBC_ARM_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::ARM_Convert(data, size, _bufferPos, 1); +} + +UInt32 CBC_ARM_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::ARM_Convert(data, size, _bufferPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.h new file mode 100644 index 00000000..5561299b --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARM.h @@ -0,0 +1,10 @@ +// ARM.h + +#ifndef __ARM_H +#define __ARM_H + +#include "BranchCoder.h" + +MyClassA(BC_ARM, 0x05, 1) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.cpp new file mode 100644 index 00000000..fbd25701 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.cpp @@ -0,0 +1,16 @@ +// ARMThumb.cpp + +#include "StdAfx.h" +#include "ARMThumb.h" + +#include "BranchARMThumb.c" + +UInt32 CBC_ARMThumb_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::ARMThumb_Convert(data, size, _bufferPos, 1); +} + +UInt32 CBC_ARMThumb_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::ARMThumb_Convert(data, size, _bufferPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.h new file mode 100644 index 00000000..601e40bf --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/ARMThumb.h @@ -0,0 +1,10 @@ +// ARMThumb.h + +#ifndef __ARMTHUMB_H +#define __ARMTHUMB_H + +#include "BranchCoder.h" + +MyClassA(BC_ARMThumb, 0x07, 1) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.c new file mode 100644 index 00000000..04bd81e0 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.c @@ -0,0 +1,26 @@ +/* BranchARM.c */ + +#include "BranchARM.h" + +UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) +{ + UInt32 i; + for (i = 0; i + 4 <= size; i += 4) + { + if (data[i + 3] == 0xEB) + { + UInt32 src = (data[i + 2] << 16) | (data[i + 1] << 8) | (data[i + 0]); + src <<= 2; + UInt32 dest; + if (encoding) + dest = nowPos + i + 8 + src; + else + dest = src - (nowPos + i + 8); + dest >>= 2; + data[i + 2] = (dest >> 16); + data[i + 1] = (dest >> 8); + data[i + 0] = dest; + } + } + return i; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.h new file mode 100644 index 00000000..02eb1b47 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARM.h @@ -0,0 +1,10 @@ +// BranchARM.h + +#ifndef __BRANCH_ARM_H +#define __BRANCH_ARM_H + +#include "BranchTypes.h" + +UInt32 ARM_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.c new file mode 100644 index 00000000..4e4b04b0 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.c @@ -0,0 +1,35 @@ +/* BranchARMThumb.c */ + +#include "BranchARMThumb.h" + +UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) +{ + UInt32 i; + for (i = 0; i + 4 <= size; i += 2) + { + if ((data[i + 1] & 0xF8) == 0xF0 && + (data[i + 3] & 0xF8) == 0xF8) + { + UInt32 src = + ((data[i + 1] & 0x7) << 19) | + (data[i + 0] << 11) | + ((data[i + 3] & 0x7) << 8) | + (data[i + 2]); + + src <<= 1; + UInt32 dest; + if (encoding) + dest = nowPos + i + 4 + src; + else + dest = src - (nowPos + i + 4); + dest >>= 1; + + data[i + 1] = 0xF0 | ((dest >> 19) & 0x7); + data[i + 0] = (dest >> 11); + data[i + 3] = 0xF8 | ((dest >> 8) & 0x7); + data[i + 2] = (dest); + i += 2; + } + } + return i; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.h new file mode 100644 index 00000000..d67e6e5a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchARMThumb.h @@ -0,0 +1,10 @@ +// BranchARMThumb.h + +#ifndef __BRANCH_ARM_THUMB_H +#define __BRANCH_ARM_THUMB_H + +#include "BranchTypes.h" + +UInt32 ARMThumb_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.cpp new file mode 100644 index 00000000..8d25f0d5 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.cpp @@ -0,0 +1,18 @@ +// BranchCoder.cpp + +#include "StdAfx.h" +#include "BranchCoder.h" + +STDMETHODIMP CBranchConverter::Init() +{ + _bufferPos = 0; + SubInit(); + return S_OK; +} + +STDMETHODIMP_(UInt32) CBranchConverter::Filter(Byte *data, UInt32 size) +{ + UInt32 processedSize = SubFilter(data, size); + _bufferPos += processedSize; + return processedSize; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.h new file mode 100644 index 00000000..4b53b6cb --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchCoder.h @@ -0,0 +1,54 @@ +// BranchCoder.h + +#ifndef __BRANCH_CODER_H +#define __BRANCH_CODER_H + +#include "Common/MyCom.h" +#include "Common/Types.h" +#include "Common/Alloc.h" + +#include "../../ICoder.h" + +class CBranchConverter: + public ICompressFilter, + public CMyUnknownImp +{ +protected: + UInt32 _bufferPos; + virtual void SubInit() {} + virtual UInt32 SubFilter(Byte *data, UInt32 size) = 0; +public: + MY_UNKNOWN_IMP; + STDMETHOD(Init)(); + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size); +}; + +#define MyClassEncoderA(Name) class C ## Name: public CBranchConverter \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); }; + +#define MyClassDecoderA(Name) class C ## Name: public CBranchConverter \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); }; + +#define MyClassEncoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; + +#define MyClassDecoderB(Name, ADD_ITEMS, ADD_INIT) class C ## Name: public CBranchConverter, public ADD_ITEMS \ + { public: UInt32 SubFilter(Byte *data, UInt32 size); ADD_INIT}; + +#define MyClass2b(Name, id, subId, encodingId) \ +DEFINE_GUID(CLSID_CCompressConvert ## Name, \ +0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); + +#define MyClassA(Name, id, subId) \ +MyClass2b(Name ## _Encoder, id, subId, 0x01) \ +MyClassEncoderA(Name ## _Encoder) \ +MyClass2b(Name ## _Decoder, id, subId, 0x00) \ +MyClassDecoderA(Name ## _Decoder) + +#define MyClassB(Name, id, subId, ADD_ITEMS, ADD_INIT) \ +MyClass2b(Name ## _Encoder, id, subId, 0x01) \ +MyClassEncoderB(Name ## _Encoder, ADD_ITEMS, ADD_INIT) \ +MyClass2b(Name ## _Decoder, id, subId, 0x00) \ +MyClassDecoderB(Name ## _Decoder, ADD_ITEMS, ADD_INIT) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.c new file mode 100644 index 00000000..e7775564 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.c @@ -0,0 +1,63 @@ +/* BranchIA64.c */ + +#include "BranchIA64.h" + +const Byte kBranchTable[32] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 4, 4, 6, 6, 0, 0, 7, 7, + 4, 4, 0, 0, 4, 4, 0, 0 +}; + +UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) +{ + UInt32 i; + for (i = 0; i + 16 <= size; i += 16) + { + UInt32 instrTemplate = data[i] & 0x1F; + UInt32 mask = kBranchTable[instrTemplate]; + UInt32 bitPos = 5; + for (int slot = 0; slot < 3; slot++, bitPos += 41) + { + if (((mask >> slot) & 1) == 0) + continue; + UInt32 bytePos = (bitPos >> 3); + UInt32 bitRes = bitPos & 0x7; + UInt64 instruction = 0; + int j; + for (j = 0; j < 6; j++) + instruction += (UInt64)(data[i + j + bytePos]) << (8 * j); + + UInt64 instNorm = instruction >> bitRes; + if (((instNorm >> 37) & 0xF) == 0x5 + && ((instNorm >> 9) & 0x7) == 0 + /* && (instNorm & 0x3F)== 0 */ + ) + { + UInt32 src = UInt32((instNorm >> 13) & 0xFFFFF); + src |= ((instNorm >> 36) & 1) << 20; + + src <<= 4; + + UInt32 dest; + if (encoding) + dest = nowPos + i + src; + else + dest = src - (nowPos + i); + + dest >>= 4; + + instNorm &= ~(UInt64(0x8FFFFF) << 13); + instNorm |= (UInt64(dest & 0xFFFFF) << 13); + instNorm |= (UInt64(dest & 0x100000) << (36 - 20)); + + instruction &= (1 << bitRes) - 1; + instruction |= (instNorm << bitRes); + for (j = 0; j < 6; j++) + data[i + j + bytePos] = Byte(instruction >> (8 * j)); + } + } + } + return i; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.h new file mode 100644 index 00000000..b7757fe9 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchIA64.h @@ -0,0 +1,10 @@ +// BranchIA64.h + +#ifndef __BRANCH_IA64_H +#define __BRANCH_IA64_H + +#include "BranchTypes.h" + +UInt32 IA64_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.c new file mode 100644 index 00000000..a173eb15 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.c @@ -0,0 +1,36 @@ +/* BranchPPC.c */ + +#include "BranchPPC.h" + +UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) +{ + UInt32 i; + for (i = 0; i + 4 <= size; i += 4) + { + /* PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link) */ + if ((data[i] >> 2) == 0x12 && + ( + (data[i + 3] & 3) == 1 + /* || (data[i+3] & 3) == 3 */ + ) + ) + { + UInt32 src = ((data[i + 0] & 3) << 24) | + (data[i + 1] << 16) | + (data[i + 2] << 8) | + (data[i + 3] & (~3)); + + UInt32 dest; + if (encoding) + dest = nowPos + i + src; + else + dest = src - (nowPos + i); + data[i + 0] = 0x48 | ((dest >> 24) & 0x3); + data[i + 1] = (dest >> 16); + data[i + 2] = (dest >> 8); + data[i + 3] &= 0x3; + data[i + 3] |= dest; + } + } + return i; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.h new file mode 100644 index 00000000..c02bba19 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchPPC.h @@ -0,0 +1,10 @@ +// BranchPPC.h + +#ifndef __BRANCH_PPC_H +#define __BRANCH_PPC_H + +#include "BranchTypes.h" + +UInt32 PPC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.c new file mode 100644 index 00000000..c175875b --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.c @@ -0,0 +1,36 @@ +/* BranchSPARC.c */ + +#include "BranchSPARC.h" + +UInt32 SPARC_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding) +{ + UInt32 i; + for (i = 0; i + 4 <= size; i += 4) + { + if (data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00 || + data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0) + { + UInt32 src = + ((UInt32)data[i + 0] << 24) | + ((UInt32)data[i + 1] << 16) | + ((UInt32)data[i + 2] << 8) | + ((UInt32)data[i + 3]); + + src <<= 2; + UInt32 dest; + if (encoding) + dest = nowPos + i + src; + else + dest = src - (nowPos + i); + dest >>= 2; + + dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000; + + data[i + 0] = (Byte)(dest >> 24); + data[i + 1] = (Byte)(dest >> 16); + data[i + 2] = (Byte)(dest >> 8); + data[i + 3] = (Byte)dest; + } + } + return i; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.h new file mode 100644 index 00000000..fbe9e673 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchSPARC.h @@ -0,0 +1,10 @@ +// BranchSPARC.h + +#ifndef __BRANCH_SPARC_H +#define __BRANCH_SPARC_H + +#include "BranchTypes.h" + +UInt32 SPARC_B_Convert(Byte *data, UInt32 size, UInt32 nowPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchTypes.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchTypes.h new file mode 100644 index 00000000..f7ad3abc --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchTypes.h @@ -0,0 +1,25 @@ +/* BranchTypes.h */ + +#ifndef __BRANCHTYPES_H +#define __BRANCHTYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.c b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.c new file mode 100644 index 00000000..2c6f69a5 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.c @@ -0,0 +1,101 @@ +/* BranchX86.c */ + +#include "BranchX86.h" + +/* +static int inline Test86MSByte(Byte b) +{ + return (b == 0 || b == 0xFF); +} +*/ +#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) + +const int kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; +const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; + +/* +void x86_Convert_Init(UInt32 *prevMask, UInt32 *prevPos) +{ + *prevMask = 0; + *prevPos = (UInt32)(-5); +} +*/ + +UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, + UInt32 *prevMask, UInt32 *prevPos, int encoding) +{ + UInt32 bufferPos = 0; + UInt32 limit; + + if (endPos < 5) + return 0; + + if (nowPos - *prevPos > 5) + *prevPos = nowPos - 5; + + limit = endPos - 5; + while(bufferPos <= limit) + { + Byte b = buffer[bufferPos]; + UInt32 offset; + if (b != 0xE8 && b != 0xE9) + { + bufferPos++; + continue; + } + offset = (nowPos + bufferPos - *prevPos); + *prevPos = (nowPos + bufferPos); + if (offset > 5) + *prevMask = 0; + else + { + UInt32 i; + for (i = 0; i < offset; i++) + { + *prevMask &= 0x77; + *prevMask <<= 1; + } + } + b = buffer[bufferPos + 4]; + if (Test86MSByte(b) && kMaskToAllowedStatus[(*prevMask >> 1) & 0x7] && + (*prevMask >> 1) < 0x10) + { + UInt32 src = + ((UInt32)(b) << 24) | + ((UInt32)(buffer[bufferPos + 3]) << 16) | + ((UInt32)(buffer[bufferPos + 2]) << 8) | + (buffer[bufferPos + 1]); + + UInt32 dest; + while(1) + { + UInt32 index; + if (encoding) + dest = (nowPos + bufferPos + 5) + src; + else + dest = src - (nowPos + bufferPos + 5); + if (*prevMask == 0) + break; + index = kMaskToBitNumber[*prevMask >> 1]; + b = (Byte)(dest >> (24 - index * 8)); + if (!Test86MSByte(b)) + break; + src = dest ^ ((1 << (32 - index * 8)) - 1); + } + buffer[bufferPos + 4] = (Byte)(~(((dest >> 24) & 1) - 1)); + buffer[bufferPos + 3] = (Byte)(dest >> 16); + buffer[bufferPos + 2] = (Byte)(dest >> 8); + buffer[bufferPos + 1] = (Byte)dest; + bufferPos += 5; + *prevMask = 0; + } + else + { + bufferPos++; + *prevMask |= 1; + if (Test86MSByte(b)) + *prevMask |= 0x10; + } + } + return bufferPos; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.h new file mode 100644 index 00000000..25c1ae51 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/BranchX86.h @@ -0,0 +1,13 @@ +/* BranchX86.h */ + +#ifndef __BRANCHX86_H +#define __BRANCHX86_H + +#include "BranchTypes.h" + +#define x86_Convert_Init(prevMask, prevPos) { prevMask = 0; prevPos = (UInt32)(-5); } + +UInt32 x86_Convert(Byte *buffer, UInt32 endPos, UInt32 nowPos, + UInt32 *prevMask, UInt32 *prevPos, int encoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.cpp new file mode 100644 index 00000000..75dfdcba --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.cpp @@ -0,0 +1,16 @@ +// IA64.cpp + +#include "StdAfx.h" +#include "IA64.h" + +#include "BranchIA64.c" + +UInt32 CBC_IA64_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::IA64_Convert(data, size, _bufferPos, 1); +} + +UInt32 CBC_IA64_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::IA64_Convert(data, size, _bufferPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.h new file mode 100644 index 00000000..7fe715ed --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/IA64.h @@ -0,0 +1,10 @@ +// IA64.h + +#ifndef __IA64_H +#define __IA64_H + +#include "BranchCoder.h" + +MyClassA(BC_IA64, 0x04, 1) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.cpp new file mode 100644 index 00000000..197a8e58 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.cpp @@ -0,0 +1,17 @@ +// PPC.cpp + +#include "StdAfx.h" +#include "PPC.h" + +#include "Windows/Defs.h" +#include "BranchPPC.c" + +UInt32 CBC_PPC_B_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::PPC_B_Convert(data, size, _bufferPos, 1); +} + +UInt32 CBC_PPC_B_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::PPC_B_Convert(data, size, _bufferPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.h new file mode 100644 index 00000000..a0e33444 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/PPC.h @@ -0,0 +1,10 @@ +// PPC.h + +#ifndef __PPC_H +#define __PPC_H + +#include "BranchCoder.h" + +MyClassA(BC_PPC_B, 0x02, 5) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.cpp new file mode 100644 index 00000000..d054eaaf --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.cpp @@ -0,0 +1,17 @@ +// SPARC.cpp + +#include "StdAfx.h" +#include "SPARC.h" + +#include "Windows/Defs.h" +#include "BranchSPARC.c" + +UInt32 CBC_SPARC_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::SPARC_Convert(data, size, _bufferPos, 1); +} + +UInt32 CBC_SPARC_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::SPARC_Convert(data, size, _bufferPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.h new file mode 100644 index 00000000..e0a682ef --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/SPARC.h @@ -0,0 +1,10 @@ +// SPARC.h + +#ifndef __SPARC_H +#define __SPARC_H + +#include "BranchCoder.h" + +MyClassA(BC_SPARC, 0x08, 5) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/StdAfx.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/StdAfx.h new file mode 100644 index 00000000..e7fb6986 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.cpp new file mode 100644 index 00000000..013e42b6 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.cpp @@ -0,0 +1,18 @@ +// x86.cpp + +#include "StdAfx.h" +#include "x86.h" + +#include "Windows/Defs.h" + +#include "BranchX86.c" + +UInt32 CBCJ_x86_Encoder::SubFilter(Byte *data, UInt32 size) +{ + return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 1); +} + +UInt32 CBCJ_x86_Decoder::SubFilter(Byte *data, UInt32 size) +{ + return ::x86_Convert(data, size, _bufferPos, &_prevMask, &_prevPos, 0); +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.h new file mode 100644 index 00000000..10d03982 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86.h @@ -0,0 +1,19 @@ +// x86.h + +#ifndef __X86_H +#define __X86_H + +#include "BranchCoder.h" +#include "BranchX86.h" + +struct CBranch86 +{ + UInt32 _prevMask; + UInt32 _prevPos; + void x86Init() { x86_Convert_Init(_prevMask, _prevPos); } +}; + +MyClassB(BCJ_x86, 0x01, 3, CBranch86 , + virtual void SubInit() { x86Init(); }) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.cpp b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.cpp new file mode 100644 index 00000000..8f7bff21 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.cpp @@ -0,0 +1,412 @@ +// x86_2.cpp + +#include "StdAfx.h" +#include "x86_2.h" + +#include "../../../Common/Alloc.h" + +static const int kBufferSize = 1 << 17; + +inline bool IsJcc(Byte b0, Byte b1) +{ + return (b0 == 0x0F && (b1 & 0xF0) == 0x80); +} + +#ifndef EXTRACT_ONLY + +static bool inline Test86MSByte(Byte b) +{ + return (b == 0 || b == 0xFF); +} + +bool CBCJ2_x86_Encoder::Create() +{ + if (!_mainStream.Create(1 << 16)) + return false; + if (!_callStream.Create(1 << 20)) + return false; + if (!_jumpStream.Create(1 << 20)) + return false; + if (!_rangeEncoder.Create(1 << 20)) + return false; + if (_buffer == 0) + { + _buffer = (Byte *)MidAlloc(kBufferSize); + if (_buffer == 0) + return false; + } + return true; +} + +CBCJ2_x86_Encoder::~CBCJ2_x86_Encoder() +{ + ::MidFree(_buffer); +} + +HRESULT CBCJ2_x86_Encoder::Flush() +{ + RINOK(_mainStream.Flush()); + RINOK(_callStream.Flush()); + RINOK(_jumpStream.Flush()); + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); +} + +const UInt32 kDefaultLimit = (1 << 24); + +HRESULT CBCJ2_x86_Encoder::CodeReal(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != 1 || numOutStreams != 4) + return E_INVALIDARG; + + if (!Create()) + return E_OUTOFMEMORY; + + bool sizeIsDefined = false; + UInt64 inSize; + if (inSizes != NULL) + if (inSizes[0] != NULL) + { + inSize = *inSizes[0]; + if (inSize <= kDefaultLimit) + sizeIsDefined = true; + } + + ISequentialInStream *inStream = inStreams[0]; + + _mainStream.SetStream(outStreams[0]); + _mainStream.Init(); + _callStream.SetStream(outStreams[1]); + _callStream.Init(); + _jumpStream.SetStream(outStreams[2]); + _jumpStream.Init(); + _rangeEncoder.SetStream(outStreams[3]); + _rangeEncoder.Init(); + for (int i = 0; i < 256; i++) + _statusE8Encoder[i].Init(); + _statusE9Encoder.Init(); + _statusJccEncoder.Init(); + CCoderReleaser releaser(this); + + CMyComPtr getSubStreamSize; + { + inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize); + } + + UInt32 nowPos = 0; + UInt64 nowPos64 = 0; + UInt32 bufferPos = 0; + + Byte prevByte = 0; + + UInt64 subStreamIndex = 0; + UInt64 subStreamStartPos = 0; + UInt64 subStreamEndPos = 0; + + while(true) + { + UInt32 processedSize = 0; + while(true) + { + UInt32 size = kBufferSize - (bufferPos + processedSize); + UInt32 processedSizeLoc; + if (size == 0) + break; + RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc)); + if (processedSizeLoc == 0) + break; + processedSize += processedSizeLoc; + } + UInt32 endPos = bufferPos + processedSize; + + if (endPos < 5) + { + // change it + for (bufferPos = 0; bufferPos < endPos; bufferPos++) + { + Byte b = _buffer[bufferPos]; + _mainStream.WriteByte(b); + if (b == 0xE8) + _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); + else if (b == 0xE9) + _statusE9Encoder.Encode(&_rangeEncoder, 0); + else if (IsJcc(prevByte, b)) + _statusJccEncoder.Encode(&_rangeEncoder, 0); + prevByte = b; + } + return Flush(); + } + + bufferPos = 0; + + UInt32 limit = endPos - 5; + while(bufferPos <= limit) + { + Byte b = _buffer[bufferPos]; + _mainStream.WriteByte(b); + if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) + { + bufferPos++; + prevByte = b; + continue; + } + Byte nextByte = _buffer[bufferPos + 4]; + UInt32 src = + (UInt32(nextByte) << 24) | + (UInt32(_buffer[bufferPos + 3]) << 16) | + (UInt32(_buffer[bufferPos + 2]) << 8) | + (_buffer[bufferPos + 1]); + UInt32 dest = (nowPos + bufferPos + 5) + src; + // if (Test86MSByte(nextByte)) + bool convert; + if (getSubStreamSize != NULL) + { + UInt64 currentPos = (nowPos64 + bufferPos); + while (subStreamEndPos < currentPos) + { + UInt64 subStreamSize; + HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize); + if (result == S_OK) + { + subStreamStartPos = subStreamEndPos; + subStreamEndPos += subStreamSize; + subStreamIndex++; + } + else if (result == S_FALSE || result == E_NOTIMPL) + { + getSubStreamSize.Release(); + subStreamStartPos = 0; + subStreamEndPos = subStreamStartPos - 1; + } + else + return result; + } + if (getSubStreamSize == NULL) + { + if (sizeIsDefined) + convert = (dest < inSize); + else + convert = Test86MSByte(nextByte); + } + else if (subStreamEndPos - subStreamStartPos > kDefaultLimit) + convert = Test86MSByte(nextByte); + else + { + UInt64 dest64 = (currentPos + 5) + Int64(Int32(src)); + convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos); + } + } + else if (sizeIsDefined) + convert = (dest < inSize); + else + convert = Test86MSByte(nextByte); + if (convert) + { + if (b == 0xE8) + _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 1); + else if (b == 0xE9) + _statusE9Encoder.Encode(&_rangeEncoder, 1); + else + _statusJccEncoder.Encode(&_rangeEncoder, 1); + + bufferPos += 5; + if (b == 0xE8) + { + _callStream.WriteByte((Byte)(dest >> 24)); + _callStream.WriteByte((Byte)(dest >> 16)); + _callStream.WriteByte((Byte)(dest >> 8)); + _callStream.WriteByte((Byte)(dest)); + } + else + { + _jumpStream.WriteByte((Byte)(dest >> 24)); + _jumpStream.WriteByte((Byte)(dest >> 16)); + _jumpStream.WriteByte((Byte)(dest >> 8)); + _jumpStream.WriteByte((Byte)(dest)); + } + prevByte = nextByte; + } + else + { + if (b == 0xE8) + _statusE8Encoder[prevByte].Encode(&_rangeEncoder, 0); + else if (b == 0xE9) + _statusE9Encoder.Encode(&_rangeEncoder, 0); + else + _statusJccEncoder.Encode(&_rangeEncoder, 0); + bufferPos++; + prevByte = b; + } + } + nowPos += bufferPos; + nowPos64 += bufferPos; + + if (progress != NULL) + { + RINOK(progress->SetRatioInfo(&nowPos64, NULL)); + } + + UInt32 i = 0; + while(bufferPos < endPos) + _buffer[i++] = _buffer[bufferPos++]; + bufferPos = i; + } +} + +STDMETHODIMP CBCJ2_x86_Encoder::Code(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + try + { + return CodeReal(inStreams, inSizes, numInStreams, + outStreams, outSizes,numOutStreams, progress); + } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} + +#endif + +HRESULT CBCJ2_x86_Decoder::CodeReal(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + if (numInStreams != 4 || numOutStreams != 1) + return E_INVALIDARG; + + if (!_mainInStream.Create(1 << 16)) + return E_OUTOFMEMORY; + if (!_callStream.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_jumpStream.Create(1 << 16)) + return E_OUTOFMEMORY; + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_outStream.Create(1 << 16)) + return E_OUTOFMEMORY; + + _mainInStream.SetStream(inStreams[0]); + _callStream.SetStream(inStreams[1]); + _jumpStream.SetStream(inStreams[2]); + _rangeDecoder.SetStream(inStreams[3]); + _outStream.SetStream(outStreams[0]); + + _mainInStream.Init(); + _callStream.Init(); + _jumpStream.Init(); + _rangeDecoder.Init(); + _outStream.Init(); + + for (int i = 0; i < 256; i++) + _statusE8Decoder[i].Init(); + _statusE9Decoder.Init(); + _statusJccDecoder.Init(); + + CCoderReleaser releaser(this); + + Byte prevByte = 0; + UInt32 processedBytes = 0; + while(true) + { + if (processedBytes > (1 << 20) && progress != NULL) + { + UInt64 nowPos64 = _outStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(NULL, &nowPos64)); + processedBytes = 0; + } + processedBytes++; + Byte b; + if (!_mainInStream.ReadByte(b)) + return Flush(); + _outStream.WriteByte(b); + if (b != 0xE8 && b != 0xE9 && !IsJcc(prevByte, b)) + { + prevByte = b; + continue; + } + bool status; + if (b == 0xE8) + status = (_statusE8Decoder[prevByte].Decode(&_rangeDecoder) == 1); + else if (b == 0xE9) + status = (_statusE9Decoder.Decode(&_rangeDecoder) == 1); + else + status = (_statusJccDecoder.Decode(&_rangeDecoder) == 1); + if (status) + { + UInt32 src; + if (b == 0xE8) + { + Byte b0; + if(!_callStream.ReadByte(b0)) + return S_FALSE; + src = ((UInt32)b0) << 24; + if(!_callStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0) << 16; + if(!_callStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0) << 8; + if(!_callStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0); + } + else + { + Byte b0; + if(!_jumpStream.ReadByte(b0)) + return S_FALSE; + src = ((UInt32)b0) << 24; + if(!_jumpStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0) << 16; + if(!_jumpStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0) << 8; + if(!_jumpStream.ReadByte(b0)) + return S_FALSE; + src |= ((UInt32)b0); + } + UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ; + _outStream.WriteByte((Byte)(dest)); + _outStream.WriteByte((Byte)(dest >> 8)); + _outStream.WriteByte((Byte)(dest >> 16)); + _outStream.WriteByte((Byte)(dest >> 24)); + prevByte = (dest >> 24); + processedBytes += 4; + } + else + prevByte = b; + } +} + +STDMETHODIMP CBCJ2_x86_Decoder::Code(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) +{ + try + { + return CodeReal(inStreams, inSizes, numInStreams, + outStreams, outSizes,numOutStreams, progress); + } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return S_FALSE; } +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.h b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.h new file mode 100644 index 00000000..3d34eb8d --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/Branch/x86_2.h @@ -0,0 +1,133 @@ +// x86_2.h + +#ifndef __BRANCH_X86_2_H +#define __BRANCH_X86_2_H + +#include "../../../Common/MyCom.h" +#include "../RangeCoder/RangeCoderBit.h" +#include "../../ICoder.h" + +// {23170F69-40C1-278B-0303-010100000100} +#define MyClass2_a(Name, id, subId, encodingId) \ +DEFINE_GUID(CLSID_CCompressConvert ## Name, \ +0x23170F69, 0x40C1, 0x278B, 0x03, 0x03, id, subId, 0x00, 0x00, encodingId, 0x00); + +#define MyClass_a(Name, id, subId) \ +MyClass2_a(Name ## _Encoder, id, subId, 0x01) \ +MyClass2_a(Name ## _Decoder, id, subId, 0x00) + +MyClass_a(BCJ2_x86, 0x01, 0x1B) + +const int kNumMoveBits = 5; + +#ifndef EXTRACT_ONLY + +class CBCJ2_x86_Encoder: + public ICompressCoder2, + public CMyUnknownImp +{ + Byte *_buffer; +public: + CBCJ2_x86_Encoder(): _buffer(0) {}; + ~CBCJ2_x86_Encoder(); + bool Create(); + + COutBuffer _mainStream; + COutBuffer _callStream; + COutBuffer _jumpStream; + NCompress::NRangeCoder::CEncoder _rangeEncoder; + NCompress::NRangeCoder::CBitEncoder _statusE8Encoder[256]; + NCompress::NRangeCoder::CBitEncoder _statusE9Encoder; + NCompress::NRangeCoder::CBitEncoder _statusJccEncoder; + + HRESULT Flush(); + void ReleaseStreams() + { + _mainStream.ReleaseStream(); + _callStream.ReleaseStream(); + _jumpStream.ReleaseStream(); + _rangeEncoder.ReleaseStream(); + } + + class CCoderReleaser + { + CBCJ2_x86_Encoder *_coder; + public: + CCoderReleaser(CBCJ2_x86_Encoder *coder): _coder(coder) {} + ~CCoderReleaser() { _coder->ReleaseStreams(); } + }; + +public: + + MY_UNKNOWN_IMP + + HRESULT CodeReal(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); +}; + +#endif + +class CBCJ2_x86_Decoder: + public ICompressCoder2, + public CMyUnknownImp +{ +public: + CInBuffer _mainInStream; + CInBuffer _callStream; + CInBuffer _jumpStream; + NCompress::NRangeCoder::CDecoder _rangeDecoder; + NCompress::NRangeCoder::CBitDecoder _statusE8Decoder[256]; + NCompress::NRangeCoder::CBitDecoder _statusE9Decoder; + NCompress::NRangeCoder::CBitDecoder _statusJccDecoder; + + COutBuffer _outStream; + + void ReleaseStreams() + { + _mainInStream.ReleaseStream(); + _callStream.ReleaseStream(); + _jumpStream.ReleaseStream(); + _rangeDecoder.ReleaseStream(); + _outStream.ReleaseStream(); + } + + HRESULT Flush() { return _outStream.Flush(); } + class CCoderReleaser + { + CBCJ2_x86_Decoder *_coder; + public: + CCoderReleaser(CBCJ2_x86_Decoder *coder): _coder(coder) {} + ~CCoderReleaser() { _coder->ReleaseStreams(); } + }; + +public: + MY_UNKNOWN_IMP + HRESULT CodeReal(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress); +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h new file mode 100644 index 00000000..b3b3f13a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree.h @@ -0,0 +1,54 @@ +// BinTree.h + +#include "../LZInWindow.h" +#include "../IMatchFinder.h" + +namespace BT_NAMESPACE { + +typedef UInt32 CIndex; +const UInt32 kMaxValForNormalize = (UInt32(1) << 31) - 1; + +class CMatchFinder: + public IMatchFinder, + public CLZInWindow, + public CMyUnknownImp, + public IMatchFinderSetNumPasses +{ + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize; // it must be historySize + 1 + UInt32 _matchMaxLen; + CIndex *_hash; + CIndex *_son; + UInt32 _hashMask; + UInt32 _cutValue; + UInt32 _hashSizeSum; + + void Normalize(); + void FreeThisClassMemory(); + void FreeMemory(); + + MY_UNKNOWN_IMP + + STDMETHOD(SetStream)(ISequentialInStream *inStream); + STDMETHOD_(void, ReleaseStream)(); + STDMETHOD(Init)(); + HRESULT MovePos(); + STDMETHOD_(Byte, GetIndexByte)(Int32 index); + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 back, UInt32 limit); + STDMETHOD_(UInt32, GetNumAvailableBytes)(); + STDMETHOD_(const Byte *, GetPointerToCurrentPos)(); + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes); + STDMETHOD_(void, ChangeBufferPos)(); + + STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + STDMETHOD(GetMatches)(UInt32 *distances); + STDMETHOD(Skip)(UInt32 num); + +public: + CMatchFinder(); + virtual ~CMatchFinder(); + virtual void SetNumPasses(UInt32 numPasses) { _cutValue = numPasses; } +}; + +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h new file mode 100644 index 00000000..74ca8d9d --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree2.h @@ -0,0 +1,12 @@ +// BinTree2.h + +#ifndef __BINTREE2_H +#define __BINTREE2_H + +#define BT_NAMESPACE NBT2 + +#include "BinTreeMain.h" + +#undef BT_NAMESPACE + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h new file mode 100644 index 00000000..76bd9ddd --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3.h @@ -0,0 +1,16 @@ +// BinTree3.h + +#ifndef __BINTREE3_H +#define __BINTREE3_H + +#define BT_NAMESPACE NBT3 + +#define HASH_ARRAY_2 + +#include "BinTreeMain.h" + +#undef HASH_ARRAY_2 + +#undef BT_NAMESPACE + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h new file mode 100644 index 00000000..d2c092b4 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree3Z.h @@ -0,0 +1,16 @@ +// BinTree3Z.h + +#ifndef __BINTREE3Z_H +#define __BINTREE3Z_H + +#define BT_NAMESPACE NBT3Z + +#define HASH_ZIP + +#include "BinTreeMain.h" + +#undef HASH_ZIP + +#undef BT_NAMESPACE + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h new file mode 100644 index 00000000..08e2d1ce --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTree4.h @@ -0,0 +1,18 @@ +// BinTree4.h + +#ifndef __BINTREE4_H +#define __BINTREE4_H + +#define BT_NAMESPACE NBT4 + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 + +#include "BinTreeMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 + +#undef BT_NAMESPACE + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h new file mode 100644 index 00000000..7a6f621a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/BinTree/BinTreeMain.h @@ -0,0 +1,531 @@ +// BinTreeMain.h + +#include "../../../../Common/Defs.h" +#include "../../../../Common/CRC.h" +#include "../../../../Common/Alloc.h" + +#include "BinTree.h" + +// #include +// It's for prefetch +// But prefetch doesn't give big gain in K8. + +namespace BT_NAMESPACE { + +#ifdef HASH_ARRAY_2 + static const UInt32 kHash2Size = 1 << 10; + #define kNumHashDirectBytes 0 + #ifdef HASH_ARRAY_3 + static const UInt32 kNumHashBytes = 4; + static const UInt32 kHash3Size = 1 << 16; + #else + static const UInt32 kNumHashBytes = 3; + #endif + static const UInt32 kHashSize = 0; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; +#else + #ifdef HASH_ZIP + #define kNumHashDirectBytes 0 + static const UInt32 kNumHashBytes = 3; + static const UInt32 kHashSize = 1 << 16; + static const UInt32 kMinMatchCheck = kNumHashBytes; + static const UInt32 kStartMaxLen = 1; + #else + #define kNumHashDirectBytes 2 + static const UInt32 kNumHashBytes = 2; + static const UInt32 kHashSize = 1 << (8 * kNumHashBytes); + static const UInt32 kMinMatchCheck = kNumHashBytes + 1; + static const UInt32 kStartMaxLen = 1; + #endif +#endif + +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 +static const UInt32 kHash3Offset = kHash2Size; +#endif +#endif + +static const UInt32 kFixHashSize = 0 + #ifdef HASH_ARRAY_2 + + kHash2Size + #ifdef HASH_ARRAY_3 + + kHash3Size + #endif + #endif + ; + +CMatchFinder::CMatchFinder(): + _hash(0) +{ +} + +void CMatchFinder::FreeThisClassMemory() +{ + BigFree(_hash); + _hash = 0; +} + +void CMatchFinder::FreeMemory() +{ + FreeThisClassMemory(); + CLZInWindow::Free(); +} + +CMatchFinder::~CMatchFinder() +{ + FreeMemory(); +} + +STDMETHODIMP CMatchFinder::Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) +{ + if (historySize > kMaxValForNormalize - 256) + { + FreeMemory(); + return E_INVALIDARG; + } + _cutValue = + #ifdef _HASH_CHAIN + 8 + (matchMaxLen >> 2); + #else + 16 + (matchMaxLen >> 1); + #endif + UInt32 sizeReserv = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + if (CLZInWindow::Create(historySize + keepAddBufferBefore, + matchMaxLen + keepAddBufferAfter, sizeReserv)) + { + _matchMaxLen = matchMaxLen; + UInt32 newCyclicBufferSize = historySize + 1; + if (_hash != 0 && newCyclicBufferSize == _cyclicBufferSize) + return S_OK; + FreeThisClassMemory(); + _cyclicBufferSize = newCyclicBufferSize; // don't change it + + UInt32 hs = kHashSize; + + #ifdef HASH_ARRAY_2 + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + { + #ifdef HASH_ARRAY_3 + hs >>= 1; + #else + hs = (1 << 24) - 1; + #endif + } + _hashMask = hs; + hs++; + #endif + _hashSizeSum = hs + kFixHashSize; + UInt32 numItems = _hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ; + size_t sizeInBytes = (size_t)numItems * sizeof(CIndex); + if (sizeInBytes / sizeof(CIndex) != numItems) + return E_OUTOFMEMORY; + _hash = (CIndex *)BigAlloc(sizeInBytes); + _son = _hash + _hashSizeSum; + if (_hash != 0) + return S_OK; + } + FreeMemory(); + return E_OUTOFMEMORY; +} + +static const UInt32 kEmptyHashValue = 0; + +STDMETHODIMP CMatchFinder::SetStream(ISequentialInStream *stream) +{ + CLZInWindow::SetStream(stream); + return S_OK; +} + +STDMETHODIMP CMatchFinder::Init() +{ + RINOK(CLZInWindow::Init()); + for(UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + return S_OK; +} + +STDMETHODIMP_(void) CMatchFinder::ReleaseStream() +{ + // ReleaseStream(); +} + +#ifdef HASH_ARRAY_2 +#ifdef HASH_ARRAY_3 + +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hash3Value = (temp ^ (UInt32(cur[2]) << 8)) & (kHash3Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8) ^ (CCRC::Table[cur[3]] << 5)) & _hashMask; } + +#else // no HASH_ARRAY_3 +#define HASH_CALC { \ + UInt32 temp = CCRC::Table[cur[0]] ^ cur[1]; \ + hash2Value = temp & (kHash2Size - 1); \ + hashValue = (temp ^ (UInt32(cur[2]) << 8)) & _hashMask; } +#endif // HASH_ARRAY_3 +#else // no HASH_ARRAY_2 +#ifdef HASH_ZIP +inline UInt32 Hash(const Byte *pointer) +{ + return ((UInt32(pointer[0]) << 8) ^ CCRC::Table[pointer[1]] ^ pointer[2]) & (kHashSize - 1); +} +#else // no HASH_ZIP +inline UInt32 Hash(const Byte *pointer) +{ + return pointer[0] ^ (UInt32(pointer[1]) << 8); +} +#endif // HASH_ZIP +#endif // HASH_ARRAY_2 + +STDMETHODIMP CMatchFinder::GetMatches(UInt32 *distances) +{ + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if(lenLimit < kMinMatchCheck) + { + distances[0] = 0; + return MovePos(); + } + } + + int offset = 1; + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + const Byte *cur = _buffer + _pos; + + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + + #ifdef HASH_ARRAY_2 + UInt32 hash2Value; + #ifdef HASH_ARRAY_3 + UInt32 hash3Value; + #endif + UInt32 hashValue; + HASH_CALC; + #else + UInt32 hashValue = Hash(cur); + #endif + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + #ifdef HASH_ARRAY_2 + UInt32 curMatch2 = _hash[hash2Value]; + #ifdef HASH_ARRAY_3 + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + #endif + _hash[hash2Value] = _pos; + if(curMatch2 > matchMinPos) + if (_buffer[curMatch2] == cur[0]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + + #ifdef HASH_ARRAY_3 + _hash[kHash3Offset + hash3Value] = _pos; + if(curMatch3 > matchMinPos) + if (_buffer[curMatch3] == cur[0]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + #endif + if (offset != 1 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + #endif + + _hash[kFixHashSize + hashValue] = _pos; + + CIndex *son = _son; + + #ifdef _HASH_CHAIN + son[_cyclicBufferPos] = curMatch; + #else + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + #endif + + #if kNumHashDirectBytes != 0 + if(curMatch > matchMinPos) + { + if (_buffer[curMatch + kNumHashDirectBytes] != cur[kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + #endif + UInt32 count = _cutValue; + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + #ifndef _HASH_CHAIN + *ptr0 = *ptr1 = kEmptyHashValue; + #endif + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + + #ifdef _HASH_CHAIN + cyclicPos; + #else + (cyclicPos << 1); + #endif + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = + #ifdef _HASH_CHAIN + kNumHashDirectBytes; + if (pb[maxLen] == cur[maxLen]) + #else + MyMin(len0, len1); + #endif + if (pb[len] == cur[len]) + { + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + #ifndef _HASH_CHAIN + *ptr1 = pair[0]; + *ptr0 = pair[1]; + #endif + break; + } + } + } + #ifdef _HASH_CHAIN + curMatch = *pair; + #else + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + #endif + } + distances[0] = offset - 1; + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; +} + +STDMETHODIMP CMatchFinder::Skip(UInt32 num) +{ + do + { + #ifdef _HASH_CHAIN + if (_streamPos - _pos < kNumHashBytes) + { + RINOK(MovePos()); + continue; + } + #else + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if(lenLimit < kMinMatchCheck) + { + RINOK(MovePos()); + continue; + } + } + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + #endif + const Byte *cur = _buffer + _pos; + + #ifdef HASH_ARRAY_2 + UInt32 hash2Value; + #ifdef HASH_ARRAY_3 + UInt32 hash3Value; + UInt32 hashValue; + HASH_CALC; + _hash[kHash3Offset + hash3Value] = _pos; + #else + UInt32 hashValue; + HASH_CALC; + #endif + _hash[hash2Value] = _pos; + #else + UInt32 hashValue = Hash(cur); + #endif + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + #ifdef _HASH_CHAIN + _son[_cyclicBufferPos] = curMatch; + #else + CIndex *son = _son; + CIndex *ptr0 = son + (_cyclicBufferPos << 1) + 1; + CIndex *ptr1 = son + (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + UInt32 count = _cutValue; + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = (delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta): + (_cyclicBufferPos - delta + _cyclicBufferSize); + CIndex *pair = son + (cyclicPos << 1); + + // _mm_prefetch((const char *)pair, _MM_HINT_T0); + + const Byte *pb = _buffer + curMatch; + UInt32 len = MyMin(len0, len1); + + if (pb[len] == cur[len]) + { + while(++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + break; + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + #endif + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + } + while(--num != 0); + return S_OK; +} + +void CMatchFinder::Normalize() +{ + UInt32 subValue = _pos - _cyclicBufferSize; + CIndex *items = _hash; + UInt32 numItems = (_hashSizeSum + _cyclicBufferSize + #ifndef _HASH_CHAIN + * 2 + #endif + ); + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + ReduceOffsets(subValue); +} + +HRESULT CMatchFinder::MovePos() +{ + if (++_cyclicBufferPos == _cyclicBufferSize) + _cyclicBufferPos = 0; + RINOK(CLZInWindow::MovePos()); + if (_pos == kMaxValForNormalize) + Normalize(); + return S_OK; +} + +STDMETHODIMP_(Byte) CMatchFinder::GetIndexByte(Int32 index) + { return CLZInWindow::GetIndexByte(index); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetMatchLen(Int32 index, + UInt32 back, UInt32 limit) + { return CLZInWindow::GetMatchLen(index, back, limit); } + +STDMETHODIMP_(UInt32) CMatchFinder::GetNumAvailableBytes() + { return CLZInWindow::GetNumAvailableBytes(); } + +STDMETHODIMP_(const Byte *) CMatchFinder::GetPointerToCurrentPos() + { return CLZInWindow::GetPointerToCurrentPos(); } + +STDMETHODIMP_(Int32) CMatchFinder::NeedChangeBufferPos(UInt32 numCheckBytes) + { return CLZInWindow::NeedMove(numCheckBytes) ? 1: 0; } + +STDMETHODIMP_(void) CMatchFinder::ChangeBufferPos() + { CLZInWindow::MoveBlock();} + +#undef HASH_CALC +#undef kNumHashDirectBytes + +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC2.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC2.h new file mode 100644 index 00000000..d8e61a74 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC2.h @@ -0,0 +1,13 @@ +// HC2.h + +#ifndef __HC2_H +#define __HC2_H + +#define BT_NAMESPACE NHC2 + +#include "HCMain.h" + +#undef BT_NAMESPACE + +#endif + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC3.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC3.h new file mode 100644 index 00000000..263690af --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC3.h @@ -0,0 +1,16 @@ +// HC3.h + +#ifndef __HC3_H +#define __HC3_H + +#define BT_NAMESPACE NHC3 + +#define HASH_ARRAY_2 + +#include "HCMain.h" + +#undef HASH_ARRAY_2 +#undef BT_NAMESPACE + +#endif + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC4.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC4.h new file mode 100644 index 00000000..1fda4ac6 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HC4.h @@ -0,0 +1,19 @@ +// HC4.h + +#ifndef __HC4_H +#define __HC4_H + +#define BT_NAMESPACE NHC4 + +#define HASH_ARRAY_2 +#define HASH_ARRAY_3 + +#include "HCMain.h" + +#undef HASH_ARRAY_2 +#undef HASH_ARRAY_3 + +#undef BT_NAMESPACE + +#endif + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h new file mode 100644 index 00000000..d509befe --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/HashChain/HCMain.h @@ -0,0 +1,6 @@ +// HCMain.h + +#define _HASH_CHAIN +#include "../BinTree/BinTreeMain.h" +#undef _HASH_CHAIN + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/IMatchFinder.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/IMatchFinder.h new file mode 100644 index 00000000..528b7b1c --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/IMatchFinder.h @@ -0,0 +1,32 @@ +// MatchFinders/IMatchFinder.h + +#ifndef __IMATCHFINDER_H +#define __IMATCHFINDER_H + +struct IInWindowStream: public IUnknown +{ + STDMETHOD(SetStream)(ISequentialInStream *inStream) PURE; + STDMETHOD_(void, ReleaseStream)() PURE; + STDMETHOD(Init)() PURE; + STDMETHOD_(Byte, GetIndexByte)(Int32 index) PURE; + STDMETHOD_(UInt32, GetMatchLen)(Int32 index, UInt32 distance, UInt32 limit) PURE; + STDMETHOD_(UInt32, GetNumAvailableBytes)() PURE; + STDMETHOD_(const Byte *, GetPointerToCurrentPos)() PURE; + STDMETHOD_(Int32, NeedChangeBufferPos)(UInt32 numCheckBytes) PURE; + STDMETHOD_(void, ChangeBufferPos)() PURE; +}; + +struct IMatchFinder: public IInWindowStream +{ + STDMETHOD(Create)(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) PURE; + STDMETHOD(GetMatches)(UInt32 *distances) PURE; + STDMETHOD(Skip)(UInt32 num) PURE; +}; + +struct IMatchFinderSetNumPasses +{ + virtual void SetNumPasses(UInt32 numPasses) PURE; +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.cpp new file mode 100644 index 00000000..0e65c425 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.cpp @@ -0,0 +1,105 @@ +// LZInWindow.cpp + +#include "StdAfx.h" + +#include "LZInWindow.h" +#include "../../../Common/MyCom.h" +#include "../../../Common/Alloc.h" + +void CLZInWindow::Free() +{ + ::BigFree(_bufferBase); + _bufferBase = 0; +} + +bool CLZInWindow::Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) +{ + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == 0 || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + if (_blockSize != 0) + _bufferBase = (Byte *)::BigAlloc(_blockSize); + } + _pointerToLastSafePosition = _bufferBase + _blockSize - keepSizeAfter; + if (_blockSize == 0) + return true; + return (_bufferBase != 0); +} + +void CLZInWindow::SetStream(ISequentialInStream *stream) +{ + _stream = stream; +} + +HRESULT CLZInWindow::Init() +{ + _buffer = _bufferBase; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + return ReadBlock(); +} + +/* +void CLZInWindow::ReleaseStream() +{ + _stream.Release(); +} +*/ + +/////////////////////////////////////////// +// ReadBlock + +// In State: +// (_buffer + _streamPos) <= (_bufferBase + _blockSize) +// Out State: +// _posLimit <= _blockSize - _keepSizeAfter; +// if(_streamEndWasReached == false): +// _streamPos >= _pos + _keepSizeAfter +// _posLimit = _streamPos - _keepSizeAfter; +// else +// + +HRESULT CLZInWindow::ReadBlock() +{ + if(_streamEndWasReached) + return S_OK; + while(true) + { + UInt32 size = (UInt32)(_bufferBase - _buffer) + _blockSize - _streamPos; + if(size == 0) + return S_OK; + UInt32 numReadBytes; + RINOK(_stream->Read(_buffer + _streamPos, size, &numReadBytes)); + if(numReadBytes == 0) + { + _posLimit = _streamPos; + const Byte *pointerToPostion = _buffer + _posLimit; + if(pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _buffer); + _streamEndWasReached = true; + return S_OK; + } + _streamPos += numReadBytes; + if(_streamPos >= _pos + _keepSizeAfter) + { + _posLimit = _streamPos - _keepSizeAfter; + return S_OK; + } + } +} + +void CLZInWindow::MoveBlock() +{ + UInt32 offset = (UInt32)(_buffer - _bufferBase) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + UInt32 numBytes = (UInt32)(_buffer - _bufferBase) + _streamPos - offset; + memmove(_bufferBase, _bufferBase + offset, numBytes); + _buffer -= offset; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.h new file mode 100644 index 00000000..54f2cb7b --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZInWindow.h @@ -0,0 +1,87 @@ +// LZInWindow.h + +#ifndef __LZ_IN_WINDOW_H +#define __LZ_IN_WINDOW_H + +#include "../../IStream.h" + +class CLZInWindow +{ + Byte *_bufferBase; // pointer to buffer with data + ISequentialInStream *_stream; + UInt32 _posLimit; // offset (from _buffer) when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + const Byte *_pointerToLastSafePosition; +protected: + Byte *_buffer; // Pointer to virtual Buffer begin + UInt32 _blockSize; // Size of Allocated memory block + UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + void MoveBlock(); + HRESULT ReadBlock(); + void Free(); +public: + CLZInWindow(): _bufferBase(0) {} + virtual ~CLZInWindow() { Free(); } + + // keepSizeBefore + keepSizeAfter + keepSizeReserv < 4G) + bool Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv = (1<<17)); + + void SetStream(ISequentialInStream *stream); + HRESULT Init(); + // void ReleaseStream(); + + Byte *GetBuffer() const { return _buffer; } + + const Byte *GetPointerToCurrentPos() const { return _buffer + _pos; } + + HRESULT MovePos() + { + _pos++; + if (_pos > _posLimit) + { + const Byte *pointerToPostion = _buffer + _pos; + if(pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + return ReadBlock(); + } + else + return S_OK; + } + Byte GetIndexByte(Int32 index) const { return _buffer[(size_t)_pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + // -2G <= index < 2G + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) const + { + if(_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (_pos + index); + distance++; + const Byte *pby = _buffer + (size_t)_pos + index; + UInt32 i; + for(i = 0; i < limit && pby[i] == pby[(size_t)i - distance]; i++); + return i; + } + + UInt32 GetNumAvailableBytes() const { return _streamPos - _pos; } + + void ReduceOffsets(Int32 subValue) + { + _buffer += subValue; + _posLimit -= subValue; + _pos -= subValue; + _streamPos -= subValue; + } + + bool NeedMove(UInt32 numCheckBytes) + { + UInt32 reserv = _pointerToLastSafePosition - (_buffer + _pos); + return (reserv <= numCheckBytes); + } +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp new file mode 100644 index 00000000..e2d6aba1 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.cpp @@ -0,0 +1,17 @@ +// LZOutWindow.cpp + +#include "StdAfx.h" + +#include "../../../Common/Alloc.h" +#include "LZOutWindow.h" + +void CLZOutWindow::Init(bool solid) +{ + if(!solid) + COutBuffer::Init(); + #ifdef _NO_EXCEPTIONS + ErrorCode = S_OK; + #endif +} + + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.h new file mode 100644 index 00000000..3c50c6e7 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/LZOutWindow.h @@ -0,0 +1,56 @@ +// LZOutWindow.h + +#ifndef __LZ_OUT_WINDOW_H +#define __LZ_OUT_WINDOW_H + +#include "../../IStream.h" +#include "../../Common/OutBuffer.h" + +#ifndef _NO_EXCEPTIONS +typedef COutBufferException CLZOutWindowException; +#endif + +class CLZOutWindow: public COutBuffer +{ +public: + void Init(bool solid = false); + + // distance >= 0, len > 0, + bool CopyBlock(UInt32 distance, UInt32 len) + { + UInt32 pos = _pos - distance - 1; + if (distance >= _pos) + { + if (!_overDict || distance >= _bufferSize) + return false; + pos += _bufferSize; + } + do + { + if (pos == _bufferSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos == _limitPos) + FlushWithCheck(); + } + while(--len != 0); + return true; + } + + void PutByte(Byte b) + { + _buffer[_pos++] = b; + if (_pos == _limitPos) + FlushWithCheck(); + } + + Byte GetByte(UInt32 distance) const + { + UInt32 pos = _pos - distance - 1; + if (pos >= _bufferSize) + pos += _bufferSize; + return _buffer[pos]; + } +}; + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZ/StdAfx.h b/sp/src/utils/lzma/C/7zip/Compress/LZ/StdAfx.h new file mode 100644 index 00000000..3ff6d8a2 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZ/StdAfx.h @@ -0,0 +1,6 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMA.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMA.h new file mode 100644 index 00000000..7bc4c438 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMA.h @@ -0,0 +1,82 @@ +// LZMA.h + +#ifndef __LZMA_H +#define __LZMA_H + +namespace NCompress { +namespace NLZMA { + +const UInt32 kNumRepDistances = 4; + +const int kNumStates = 12; + +const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +class CState +{ +public: + Byte Index; + void Init() { Index = 0; } + void UpdateChar() { Index = kLiteralNextStates[Index]; } + void UpdateMatch() { Index = kMatchNextStates[Index]; } + void UpdateRep() { Index = kRepNextStates[Index]; } + void UpdateShortRep() { Index = kShortRepNextStates[Index]; } + bool IsCharState() const { return Index < 7; } +}; + +const int kNumPosSlotBits = 6; +const int kDicLogSizeMin = 0; +const int kDicLogSizeMax = 32; +const int kDistTableSizeMax = kDicLogSizeMax * 2; + +const UInt32 kNumLenToPosStates = 4; + +inline UInt32 GetLenToPosState(UInt32 len) +{ + len -= 2; + if (len < kNumLenToPosStates) + return len; + return kNumLenToPosStates - 1; +} + +namespace NLength { + +const int kNumPosStatesBitsMax = 4; +const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + +const int kNumPosStatesBitsEncodingMax = 4; +const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + +const int kNumLowBits = 3; +const int kNumMidBits = 3; +const int kNumHighBits = 8; +const UInt32 kNumLowSymbols = 1 << kNumLowBits; +const UInt32 kNumMidSymbols = 1 << kNumMidBits; +const UInt32 kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); + +} + +const UInt32 kMatchMinLen = 2; +const UInt32 kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; + +const int kNumAlignBits = 4; +const UInt32 kAlignTableSize = 1 << kNumAlignBits; +const UInt32 kAlignMask = (kAlignTableSize - 1); + +const UInt32 kStartPosModelIndex = 4; +const UInt32 kEndPosModelIndex = 14; +const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + +const UInt32 kNumFullDistances = 1 << (kEndPosModelIndex / 2); + +const int kNumLitPosStatesBitsEncodingMax = 4; +const int kNumLitContextBitsMax = 8; + +const int kNumMoveBits = 5; + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp new file mode 100644 index 00000000..af984c4a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.cpp @@ -0,0 +1,337 @@ +// LZMADecoder.cpp + +#include "StdAfx.h" + +#include "LZMADecoder.h" +#include "../../../Common/Defs.h" + +namespace NCompress { +namespace NLZMA { + +const int kLenIdFinished = -1; +const int kLenIdNeedInit = -2; + +void CDecoder::Init() +{ + { + for(int i = 0; i < kNumStates; i++) + { + for (UInt32 j = 0; j <= _posStateMask; j++) + { + _isMatch[i][j].Init(); + _isRep0Long[i][j].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + } + { + for (UInt32 i = 0; i < kNumLenToPosStates; i++) + _posSlotDecoder[i].Init(); + } + { + for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + _posDecoders[i].Init(); + } + _posAlignDecoder.Init(); + _lenDecoder.Init(_posStateMask + 1); + _repMatchLenDecoder.Init(_posStateMask + 1); + _literalDecoder.Init(); + + _state.Init(); + _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; +} + +HRESULT CDecoder::CodeSpec(UInt32 curSize) +{ + if (_outSizeDefined) + { + const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); + if (curSize > rem) + curSize = (UInt32)rem; + } + + if (_remainLen == kLenIdFinished) + return S_OK; + if (_remainLen == kLenIdNeedInit) + { + _rangeDecoder.Init(); + Init(); + _remainLen = 0; + } + if (curSize == 0) + return S_OK; + + UInt32 rep0 = _reps[0]; + UInt32 rep1 = _reps[1]; + UInt32 rep2 = _reps[2]; + UInt32 rep3 = _reps[3]; + CState state = _state; + Byte previousByte; + + while(_remainLen > 0 && curSize > 0) + { + previousByte = _outWindowStream.GetByte(rep0); + _outWindowStream.PutByte(previousByte); + _remainLen--; + curSize--; + } + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); + if (nowPos64 == 0) + previousByte = 0; + else + previousByte = _outWindowStream.GetByte(0); + + while(curSize > 0) + { + { + #ifdef _NO_EXCEPTIONS + if (_rangeDecoder.Stream.ErrorCode != S_OK) + return _rangeDecoder.Stream.ErrorCode; + #endif + if (_rangeDecoder.Stream.WasFinished()) + return S_FALSE; + UInt32 posState = UInt32(nowPos64) & _posStateMask; + if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) + { + if(!state.IsCharState()) + previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, + (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); + else + previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, + (UInt32)nowPos64, previousByte); + _outWindowStream.PutByte(previousByte); + state.UpdateChar(); + curSize--; + nowPos64++; + } + else + { + UInt32 len; + if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) + { + len = 0; + if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) + { + if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) + { + state.UpdateShortRep(); + len = 1; + } + } + else + { + UInt32 distance; + if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) + distance = rep1; + else + { + if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + if (len == 0) + { + len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; + state.UpdateRep(); + } + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); + state.UpdateMatch(); + UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); + if (posSlot >= kStartPosModelIndex) + { + UInt32 numDirectBits = (posSlot >> 1) - 1; + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + + if (posSlot < kEndPosModelIndex) + rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); + else + { + rep0 += (_rangeDecoder.DecodeDirectBits( + numDirectBits - kNumAlignBits) << kNumAlignBits); + rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); + if (rep0 == 0xFFFFFFFF) + { + _remainLen = kLenIdFinished; + return S_OK; + } + } + } + else + rep0 = posSlot; + } + UInt32 locLen = len; + if (len > curSize) + locLen = (UInt32)curSize; + if (!_outWindowStream.CopyBlock(rep0, locLen)) + return S_FALSE; + previousByte = _outWindowStream.GetByte(0); + curSize -= locLen; + nowPos64 += locLen; + len -= locLen; + if (len != 0) + { + _remainLen = (Int32)len; + break; + } + + #ifdef _NO_EXCEPTIONS + if (_outWindowStream.ErrorCode != S_OK) + return _outWindowStream.ErrorCode; + #endif + } + } + } + if (_rangeDecoder.Stream.WasFinished()) + return S_FALSE; + _reps[0] = rep0; + _reps[1] = rep1; + _reps[2] = rep2; + _reps[3] = rep3; + _state = state; + + return S_OK; +} + +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + SetInStream(inStream); + _outWindowStream.SetStream(outStream); + SetOutStreamSize(outSize); + CDecoderFlusher flusher(this); + + while (true) + { + UInt32 curSize = 1 << 18; + RINOK(CodeSpec(curSize)); + if (_remainLen == kLenIdFinished) + break; + if (progress != NULL) + { + UInt64 inSize = _rangeDecoder.GetProcessedSize(); + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); + } + if (_outSizeDefined) + if (_outWindowStream.GetProcessedSize() >= _outSize) + break; + } + flusher.NeedFlush = false; + return Flush(); +} + + +#ifdef _NO_EXCEPTIONS + +#define LZMA_TRY_BEGIN +#define LZMA_TRY_END + +#else + +#define LZMA_TRY_BEGIN try { +#define LZMA_TRY_END } \ + catch(const CInBufferException &e) { return e.ErrorCode; } \ + catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ + catch(...) { return S_FALSE; } + +#endif + + +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + LZMA_TRY_BEGIN + return CodeReal(inStream, outStream, inSize, outSize, progress); + LZMA_TRY_END +} + +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) +{ + if (size < 5) + return E_INVALIDARG; + int lc = properties[0] % 9; + Byte remainder = (Byte)(properties[0] / 9); + int lp = remainder % 5; + int pb = remainder / 5; + if (pb > NLength::kNumPosStatesBitsMax) + return E_INVALIDARG; + _posStateMask = (1 << pb) - 1; + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); + if (!_outWindowStream.Create(dictionarySize)) + return E_OUTOFMEMORY; + if (!_literalDecoder.Create(lp, lc)) + return E_OUTOFMEMORY; + if (!_rangeDecoder.Create(1 << 20)) + return E_OUTOFMEMORY; + return S_OK; +} + +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) +{ + *value = _rangeDecoder.GetProcessedSize(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + _rangeDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + _rangeDecoder.ReleaseStream(); + return S_OK; +} + +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) +{ + if ((_outSizeDefined = (outSize != NULL))) + _outSize = *outSize; + _remainLen = kLenIdNeedInit; + _outWindowStream.Init(); + return S_OK; +} + +#ifdef _ST_MODE + +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + LZMA_TRY_BEGIN + if (processedSize) + *processedSize = 0; + const UInt64 startPos = _outWindowStream.GetProcessedSize(); + _outWindowStream.SetMemStream((Byte *)data); + RINOK(CodeSpec(size)); + if (processedSize) + *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); + return Flush(); + LZMA_TRY_END +} + +#endif + +}} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.h new file mode 100644 index 00000000..1c10409f --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMADecoder.h @@ -0,0 +1,251 @@ +// LZMA/Decoder.h + +#ifndef __LZMA_DECODER_H +#define __LZMA_DECODER_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/Alloc.h" +#include "../../ICoder.h" +#include "../LZ/LZOutWindow.h" +#include "../RangeCoder/RangeCoderBitTree.h" + +#include "LZMA.h" + +namespace NCompress { +namespace NLZMA { + +typedef NRangeCoder::CBitDecoder CMyBitDecoder; + +class CLiteralDecoder2 +{ + CMyBitDecoder _decoders[0x300]; +public: + void Init() + { + for (int i = 0; i < 0x300; i++) + _decoders[i].Init(); + } + Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder) + { + UInt32 symbol = 1; + RC_INIT_VAR + do + { + // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); + RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) + } + while (symbol < 0x100); + RC_FLUSH_VAR + return (Byte)symbol; + } + Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, Byte matchByte) + { + UInt32 symbol = 1; + RC_INIT_VAR + do + { + UInt32 matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + // UInt32 bit = _decoders[1 + matchBit][symbol].Decode(rangeDecoder); + // symbol = (symbol << 1) | bit; + UInt32 bit; + RC_GETBIT2(kNumMoveBits, _decoders[0x100 + (matchBit << 8) + symbol].Prob, symbol, + bit = 0, bit = 1) + if (matchBit != bit) + { + while (symbol < 0x100) + { + // symbol = (symbol << 1) | _decoders[0][symbol].Decode(rangeDecoder); + RC_GETBIT(kNumMoveBits, _decoders[symbol].Prob, symbol) + } + break; + } + } + while (symbol < 0x100); + RC_FLUSH_VAR + return (Byte)symbol; + } +}; + +class CLiteralDecoder +{ + CLiteralDecoder2 *_coders; + int _numPrevBits; + int _numPosBits; + UInt32 _posMask; +public: + CLiteralDecoder(): _coders(0) {} + ~CLiteralDecoder() { Free(); } + void Free() + { + MyFree(_coders); + _coders = 0; + } + bool Create(int numPosBits, int numPrevBits) + { + if (_coders == 0 || (numPosBits + numPrevBits) != + (_numPrevBits + _numPosBits) ) + { + Free(); + UInt32 numStates = 1 << (numPosBits + numPrevBits); + _coders = (CLiteralDecoder2 *)MyAlloc(numStates * sizeof(CLiteralDecoder2)); + } + _numPosBits = numPosBits; + _posMask = (1 << numPosBits) - 1; + _numPrevBits = numPrevBits; + return (_coders != 0); + } + void Init() + { + UInt32 numStates = 1 << (_numPrevBits + _numPosBits); + for (UInt32 i = 0; i < numStates; i++) + _coders[i].Init(); + } + UInt32 GetState(UInt32 pos, Byte prevByte) const + { return ((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits)); } + Byte DecodeNormal(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte) + { return _coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + Byte DecodeWithMatchByte(NRangeCoder::CDecoder *rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) + { return _coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } +}; + +namespace NLength { + +class CDecoder +{ + CMyBitDecoder _choice; + CMyBitDecoder _choice2; + NRangeCoder::CBitTreeDecoder _lowCoder[kNumPosStatesMax]; + NRangeCoder::CBitTreeDecoder _midCoder[kNumPosStatesMax]; + NRangeCoder::CBitTreeDecoder _highCoder; +public: + void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + UInt32 Decode(NRangeCoder::CDecoder *rangeDecoder, UInt32 posState) + { + if(_choice.Decode(rangeDecoder) == 0) + return _lowCoder[posState].Decode(rangeDecoder); + if(_choice2.Decode(rangeDecoder) == 0) + return kNumLowSymbols + _midCoder[posState].Decode(rangeDecoder); + return kNumLowSymbols + kNumMidSymbols + _highCoder.Decode(rangeDecoder); + } +}; + +} + +class CDecoder: + public ICompressCoder, + public ICompressSetDecoderProperties2, + public ICompressGetInStreamProcessedSize, + #ifdef _ST_MODE + public ICompressSetInStream, + public ICompressSetOutStreamSize, + public ISequentialInStream, + #endif + public CMyUnknownImp +{ + CLZOutWindow _outWindowStream; + NRangeCoder::CDecoder _rangeDecoder; + + CMyBitDecoder _isMatch[kNumStates][NLength::kNumPosStatesMax]; + CMyBitDecoder _isRep[kNumStates]; + CMyBitDecoder _isRepG0[kNumStates]; + CMyBitDecoder _isRepG1[kNumStates]; + CMyBitDecoder _isRepG2[kNumStates]; + CMyBitDecoder _isRep0Long[kNumStates][NLength::kNumPosStatesMax]; + + NRangeCoder::CBitTreeDecoder _posSlotDecoder[kNumLenToPosStates]; + + CMyBitDecoder _posDecoders[kNumFullDistances - kEndPosModelIndex]; + NRangeCoder::CBitTreeDecoder _posAlignDecoder; + + NLength::CDecoder _lenDecoder; + NLength::CDecoder _repMatchLenDecoder; + + CLiteralDecoder _literalDecoder; + + UInt32 _posStateMask; + + /////////////////// + // State + UInt32 _reps[4]; + CState _state; + Int32 _remainLen; // -1 means end of stream. // -2 means need Init + UInt64 _outSize; + bool _outSizeDefined; + + void Init(); + HRESULT CodeSpec(UInt32 size); +public: + + #ifdef _ST_MODE + MY_UNKNOWN_IMP5( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize, + ICompressSetInStream, + ICompressSetOutStreamSize, + ISequentialInStream) + #else + MY_UNKNOWN_IMP2( + ICompressSetDecoderProperties2, + ICompressGetInStreamProcessedSize) + #endif + + void ReleaseStreams() + { + _outWindowStream.ReleaseStream(); + ReleaseInStream(); + } + + class CDecoderFlusher + { + CDecoder *_decoder; + public: + bool NeedFlush; + CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {} + ~CDecoderFlusher() + { + if (NeedFlush) + _decoder->Flush(); + _decoder->ReleaseStreams(); + } + }; + + HRESULT Flush() { return _outWindowStream.Flush(); } + + STDMETHOD(CodeReal)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size); + + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); + + STDMETHOD(SetInStream)(ISequentialInStream *inStream); + STDMETHOD(ReleaseInStream)(); + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); + + #ifdef _ST_MODE + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); + #endif + + CDecoder(): _outSizeDefined(false) {} + virtual ~CDecoder() {} +}; + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp new file mode 100644 index 00000000..30aa4524 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.cpp @@ -0,0 +1,1564 @@ +// LZMA/Encoder.cpp + +#include "StdAfx.h" + +#include "../../../Common/Defs.h" +#include "../../Common/StreamUtils.h" + +#include "LZMAEncoder.h" + +// for minimal compressing code size define these: +// #define COMPRESS_MF_BT +// #define COMPRESS_MF_BT4 + +#if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_HC) +#define COMPRESS_MF_BT +#define COMPRESS_MF_HC +#endif + +#ifdef COMPRESS_MF_BT +#if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) +#define COMPRESS_MF_BT2 +#define COMPRESS_MF_BT3 +#define COMPRESS_MF_BT4 +#endif +#ifdef COMPRESS_MF_BT2 +#include "../LZ/BinTree/BinTree2.h" +#endif +#ifdef COMPRESS_MF_BT3 +#include "../LZ/BinTree/BinTree3.h" +#endif +#ifdef COMPRESS_MF_BT4 +#include "../LZ/BinTree/BinTree4.h" +#endif +#endif + +#ifdef COMPRESS_MF_HC +#include "../LZ/HashChain/HC4.h" +#endif + +#ifdef COMPRESS_MF_MT +#include "../LZ/MT/MT.h" +#endif + +namespace NCompress { +namespace NLZMA { + +const int kDefaultDictionaryLogSize = 22; +const UInt32 kNumFastBytesDefault = 0x20; + +enum +{ + kBT2, + kBT3, + kBT4, + kHC4 +}; + +static const wchar_t *kMatchFinderIDs[] = +{ + L"BT2", + L"BT3", + L"BT4", + L"HC4" +}; + +Byte g_FastPos[1 << 11]; + +class CFastPosInit +{ +public: + CFastPosInit() { Init(); } + void Init() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = (1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } +} g_FastPosInit; + + +void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol) +{ + UInt32 context = 1; + int i = 8; + do + { + i--; + UInt32 bit = (symbol >> i) & 1; + _encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + while(i != 0); +} + +void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, + Byte matchByte, Byte symbol) +{ + UInt32 context = 1; + int i = 8; + do + { + i--; + UInt32 bit = (symbol >> i) & 1; + UInt32 matchBit = (matchByte >> i) & 1; + _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + while(i != 0) + { + i--; + UInt32 bit = (symbol >> i) & 1; + _encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + break; + } + } + while(i != 0); +} + +UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const +{ + UInt32 price = 0; + UInt32 context = 1; + int i = 8; + if (matchMode) + { + do + { + i--; + UInt32 matchBit = (matchByte >> i) & 1; + UInt32 bit = (symbol >> i) & 1; + price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + break; + } + while (i != 0); + } + while(i != 0) + { + i--; + UInt32 bit = (symbol >> i) & 1; + price += _encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; +}; + + +namespace NLength { + +void CEncoder::Init(UInt32 numPosStates) +{ + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); +} + +void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState) +{ + if(symbol < kNumLowSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice.Encode(rangeEncoder, 1); + if(symbol < kNumLowSymbols + kNumMidSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols); + } + } +} + +void CEncoder::SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const +{ + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < kNumLowSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < kNumLowSymbols + kNumMidSymbols; i++) + { + if (i >= numSymbols) + return; + prices[i] = b0 + _midCoder[posState].GetPrice(i - kNumLowSymbols); + } + for (; i < numSymbols; i++) + prices[i] = b1 + _highCoder.GetPrice(i - kNumLowSymbols - kNumMidSymbols); +} + +} +CEncoder::CEncoder(): + _numFastBytes(kNumFastBytesDefault), + _distTableSize(kDefaultDictionaryLogSize * 2), + _posStateBits(2), + _posStateMask(4 - 1), + _numLiteralPosStateBits(0), + _numLiteralContextBits(3), + _dictionarySize(1 << kDefaultDictionaryLogSize), + _dictionarySizePrev(UInt32(-1)), + _numFastBytesPrev(UInt32(-1)), + _matchFinderCycles(0), + _matchFinderIndex(kBT4), + #ifdef COMPRESS_MF_MT + _multiThread(false), + #endif + _writeEndMark(false), + setMfPasses(0) +{ + // _maxMode = false; + _fastMode = false; +} + +HRESULT CEncoder::Create() +{ + if (!_rangeEncoder.Create(1 << 20)) + return E_OUTOFMEMORY; + if (!_matchFinder) + { + switch(_matchFinderIndex) + { + #ifdef COMPRESS_MF_BT + #ifdef COMPRESS_MF_BT2 + case kBT2: + { + NBT2::CMatchFinder *mfSpec = new NBT2::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #ifdef COMPRESS_MF_BT3 + case kBT3: + { + NBT3::CMatchFinder *mfSpec = new NBT3::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #ifdef COMPRESS_MF_BT4 + case kBT4: + { + NBT4::CMatchFinder *mfSpec = new NBT4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + #endif + + #ifdef COMPRESS_MF_HC + case kHC4: + { + NHC4::CMatchFinder *mfSpec = new NHC4::CMatchFinder; + setMfPasses = mfSpec; + _matchFinder = mfSpec; + break; + } + #endif + } + if (_matchFinder == 0) + return E_OUTOFMEMORY; + + #ifdef COMPRESS_MF_MT + if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC4))) + { + CMatchFinderMT *mfSpec = new CMatchFinderMT; + if (mfSpec == 0) + return E_OUTOFMEMORY; + CMyComPtr mf = mfSpec; + RINOK(mfSpec->SetMatchFinder(_matchFinder)); + _matchFinder.Release(); + _matchFinder = mf; + } + #endif + } + + if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits)) + return E_OUTOFMEMORY; + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return S_OK; + RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes, kMatchMaxLen + 1)); // actually it's + _numFastBytes - _numFastBytes + if (_matchFinderCycles != 0 && setMfPasses != 0) + setMfPasses->SetNumPasses(_matchFinderCycles); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + return S_OK; +} + +static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString) +{ + while (true) + { + wchar_t c = *testString; + if (c >= 'a' && c <= 'z') + c -= 0x20; + if (*base != c) + return false; + if (c == 0) + return true; + base++; + testString++; + } +} + +static int FindMatchFinder(const wchar_t *s) +{ + for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++) + if (AreStringsEqual(kMatchFinderIDs[m], s)) + return m; + return -1; +} + +STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) +{ + for (UInt32 i = 0; i < numProperties; i++) + { + const PROPVARIANT &prop = properties[i]; + switch(propIDs[i]) + { + case NCoderPropID::kNumFastBytes: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 numFastBytes = prop.ulVal; + if(numFastBytes < 5 || numFastBytes > kMatchMaxLen) + return E_INVALIDARG; + _numFastBytes = numFastBytes; + break; + } + case NCoderPropID::kMatchFinderCycles: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + _matchFinderCycles = prop.ulVal; + break; + } + case NCoderPropID::kAlgorithm: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 maximize = prop.ulVal; + _fastMode = (maximize == 0); + // _maxMode = (maximize >= 2); + break; + } + case NCoderPropID::kMatchFinder: + { + if (prop.vt != VT_BSTR) + return E_INVALIDARG; + int matchFinderIndexPrev = _matchFinderIndex; + int m = FindMatchFinder(prop.bstrVal); + if (m < 0) + return E_INVALIDARG; + _matchFinderIndex = m; + if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + } + break; + } + #ifdef COMPRESS_MF_MT + case NCoderPropID::kMultiThread: + { + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + bool newMultiThread = (prop.boolVal == VARIANT_TRUE); + if (newMultiThread != _multiThread) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + break; + } + case NCoderPropID::kNumThreads: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + bool newMultiThread = (prop.ulVal > 1); + if (newMultiThread != _multiThread) + { + _dictionarySizePrev = (UInt32)-1; + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + break; + } + #endif + case NCoderPropID::kDictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 dictionarySize = prop.ulVal; + if (dictionarySize < UInt32(1 << kDicLogSizeMin) || + dictionarySize > UInt32(1 << kDicLogSizeMaxCompress)) + return E_INVALIDARG; + _dictionarySize = dictionarySize; + UInt32 dicLogSize; + for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= (UInt32(1) << dicLogSize)) + break; + _distTableSize = dicLogSize * 2; + break; + } + case NCoderPropID::kPosStateBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax) + return E_INVALIDARG; + _posStateBits = value; + _posStateMask = (1 << _posStateBits) - 1; + break; + } + case NCoderPropID::kLitPosBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)kNumLitPosStatesBitsEncodingMax) + return E_INVALIDARG; + _numLiteralPosStateBits = value; + break; + } + case NCoderPropID::kLitContextBits: + { + if (prop.vt != VT_UI4) + return E_INVALIDARG; + UInt32 value = prop.ulVal; + if (value > (UInt32)kNumLitContextBitsMax) + return E_INVALIDARG; + _numLiteralContextBits = value; + break; + } + case NCoderPropID::kEndMarker: + { + if (prop.vt != VT_BOOL) + return E_INVALIDARG; + SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE); + break; + } + default: + return E_INVALIDARG; + } + } + return S_OK; +} + +STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream) +{ + const UInt32 kPropSize = 5; + Byte properties[kPropSize]; + properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits; + for (int i = 0; i < 4; i++) + properties[1 + i] = Byte(_dictionarySize >> (8 * i)); + return WriteStream(outStream, properties, kPropSize, NULL); +} + +STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream) +{ + _rangeEncoder.SetStream(outStream); + return S_OK; +} + +STDMETHODIMP CEncoder::ReleaseOutStream() +{ + _rangeEncoder.ReleaseStream(); + return S_OK; +} + +HRESULT CEncoder::Init() +{ + CBaseState::Init(); + + // RINOK(_matchFinder->Init(inStream)); + _rangeEncoder.Init(); + + for(int i = 0; i < kNumStates; i++) + { + for (UInt32 j = 0; j <= _posStateMask; j++) + { + _isMatch[i][j].Init(); + _isRep0Long[i][j].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + + _literalEncoder.Init(); + + { + for(UInt32 i = 0; i < kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + } + { + for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) + _posEncoders[i].Init(); + } + + _lenEncoder.Init(1 << _posStateBits); + _repMatchLenEncoder.Init(1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + + return S_OK; +} + +HRESULT CEncoder::MovePos(UInt32 num) +{ + if (num == 0) + return S_OK; + _additionalOffset += num; + return _matchFinder->Skip(num); +} + +UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur) +{ + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while(cur != 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; +} + +/* +Out: + (lenRes == 1) && (backRes == 0xFFFFFFFF) means Literal +*/ + +HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes) +{ + if(_optimumEndIndex != _optimumCurrentIndex) + { + const COptimal &optimum = _optimum[_optimumCurrentIndex]; + lenRes = optimum.PosPrev - _optimumCurrentIndex; + backRes = optimum.BackPrev; + _optimumCurrentIndex = optimum.PosPrev; + return S_OK; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; + + UInt32 reps[kNumRepDistances]; + UInt32 repLens[kNumRepDistances]; + UInt32 repMaxIndex = 0; + UInt32 i; + for(i = 0; i < kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + UInt32 backOffset = reps[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 lenTest; + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + repLens[i] = lenTest; + if (lenTest > repLens[repMaxIndex]) + repMaxIndex = i; + } + if(repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + return MovePos(lenRes - 1); + } + + UInt32 *matchDistances = _matchDistances + 1; + if(lenMain >= _numFastBytes) + { + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 1); + } + Byte currentByte = *data; + Byte matchByte = data[(size_t)0 - reps[0] - 1]; + + if(lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)-1; + lenRes = 1; + return S_OK; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte)->GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if(matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if(shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + lenRes = 1; + return S_OK; + } + + _optimum[1].PosPrev = 0; + for (i = 0; i < kNumRepDistances; i++) + _optimum[0].Backs[i] = reps[i]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for(i = 0; i < kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + COptimal &optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while(--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > matchDistances[offs]) + offs += 2; + for(; ; len++) + { + UInt32 distance = matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + COptimal &optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while(true) + { + cur++; + if(cur == lenEnd) + { + lenRes = Backward(backRes, cur); + return S_OK; + } + UInt32 newLen, numDistancePairs; + RINOK(ReadMatchDistances(newLen, numDistancePairs)); + if(newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + lenRes = Backward(backRes, cur); + return S_OK; + } + position++; + COptimal &curOptimum = _optimum[cur]; + UInt32 posPrev = curOptimum.PosPrev; + CState state; + if (curOptimum.Prev1IsChar) + { + posPrev--; + if (curOptimum.Prev2) + { + state = _optimum[curOptimum.PosPrev2].State; + if (curOptimum.BackPrev2 < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (curOptimum.IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (curOptimum.Prev1IsChar && curOptimum.Prev2) + { + posPrev = curOptimum.PosPrev2; + pos = curOptimum.BackPrev2; + state.UpdateRep(); + } + else + { + pos = curOptimum.BackPrev; + if (pos < kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + const COptimal &prevOptimum = _optimum[posPrev]; + if (pos < kNumRepDistances) + { + reps[0] = prevOptimum.Backs[pos]; + UInt32 i; + for(i = 1; i <= pos; i++) + reps[i] = prevOptimum.Backs[i - 1]; + for(; i < kNumRepDistances; i++) + reps[i] = prevOptimum.Backs[i]; + } + else + { + reps[0] = (pos - kNumRepDistances); + for(UInt32 i = 1; i < kNumRepDistances; i++) + reps[i] = prevOptimum.Backs[i - 1]; + } + } + curOptimum.State = state; + for(UInt32 i = 0; i < kNumRepDistances; i++) + curOptimum.Backs[i] = reps[i]; + UInt32 curPrice = curOptimum.Price; + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + const Byte currentByte = *data; + const Byte matchByte = data[(size_t)0 - reps[0] - 1]; + + UInt32 posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[state.Index][posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, data[(size_t)0 - 1])->GetPrice(!state.IsCharState(), matchByte, currentByte); + + COptimal &nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if(matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if(shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + /* + if(newLen == 2 && matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? + continue; + */ + + UInt32 numAvailableBytesFull = _matchFinder->GetNumAvailableBytes() + 1; + numAvailableBytesFull = MyMin(kNumOpts - 1 - cur, numAvailableBytesFull); + UInt32 numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) // speed optimization + { + // try Literal + rep0 + UInt32 backOffset = reps[0] + 1; + UInt32 limit = MyMin(numAvailableBytesFull, _numFastBytes + 1); + UInt32 temp; + for (temp = 1; temp < limit && + data[temp] == data[(size_t)temp - backOffset]; temp++); + UInt32 lenTest2 = temp - 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + // for (; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) + { + // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; + UInt32 backOffset = reps[repIndex] + 1; + if (data[0] != data[(size_t)0 - backOffset] || + data[1] != data[(size_t)1 - backOffset]) + continue; + UInt32 lenTest; + for (lenTest = 2; lenTest < numAvailableBytes && + data[lenTest] == data[(size_t)lenTest - backOffset]; lenTest++); + while(lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 lenTestTemp = lenTest; + UInt32 price = repMatchPrice + GetPureRepPrice(repIndex, state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState); + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + { + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + price + _repMatchLenEncoder.GetPrice(lenTest - 2, posState) + + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( + true, data[(size_t)lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2); + matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while(lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while(startLen > matchDistances[offs]) + offs += 2; + UInt32 curBack = matchDistances[offs + 1]; + UInt32 posSlot = GetPosSlot2(curBack); + for(UInt32 lenTest = /*2*/ startLen; ; lenTest++) + { + UInt32 curAndLenPrice = normalMatchPrice; + UInt32 lenToPosState = GetLenToPosState(lenTest); + if (curBack < kNumFullDistances) + curAndLenPrice += _distancesPrices[lenToPosState][curBack]; + else + curAndLenPrice += _posSlotPrices[lenToPosState][posSlot] + _alignPrices[curBack & kAlignMask]; + + curAndLenPrice += _lenEncoder.GetPrice(lenTest - kMatchMinLen, posState); + + COptimal &optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (/*_maxMode && */lenTest == matchDistances[offs]) + { + // Try Match + Literal + Rep0 + UInt32 backOffset = curBack + 1; + UInt32 lenTest2 = lenTest + 1; + UInt32 limit = MyMin(numAvailableBytesFull, lenTest2 + _numFastBytes); + for (; lenTest2 < limit && + data[lenTest2] == data[(size_t)lenTest2 - backOffset]; lenTest2++); + lenTest2 -= lenTest + 1; + if (lenTest2 >= 2) + { + CState state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[state2.Index][posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, data[(size_t)lenTest - 1])->GetPrice( + true, data[(size_t)lenTest - backOffset], data[lenTest]); + state2.UpdateChar(); + posStateNext = (posStateNext + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAndLenCharPrice + + _isMatch[state2.Index][posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = cur + lenTest + 1 + lenTest2; + while(lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + COptimal &optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + curBack = matchDistances[offs + 1]; + if (curBack >= kNumFullDistances) + posSlot = GetPosSlot2(curBack); + } + } + } + } +} + +static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist) +{ + return ((bigDist >> 7) > smallDist); +} + + +HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes, UInt32 &numDistancePairs) +{ + lenRes = 0; + RINOK(_matchFinder->GetMatches(_matchDistances)); + numDistancePairs = _matchDistances[0]; + if (numDistancePairs > 0) + { + lenRes = _matchDistances[1 + numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder->GetMatchLen(lenRes - 1, _matchDistances[1 + numDistancePairs - 1], + kMatchMaxLen - lenRes); + } + _additionalOffset++; + return S_OK; +} + +HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes) +{ + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + RINOK(ReadMatchDistances(lenMain, numDistancePairs)); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; + UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; + if (numAvailableBytes > kMatchMaxLen) + numAvailableBytes = kMatchMaxLen; + if (numAvailableBytes < 2) + { + backRes = (UInt32)(-1); + lenRes = 1; + return S_OK; + } + + UInt32 repLens[kNumRepDistances]; + UInt32 repMaxIndex = 0; + + for(UInt32 i = 0; i < kNumRepDistances; i++) + { + UInt32 backOffset = _repDistances[i] + 1; + if (data[0] != data[(size_t)0 - backOffset] || data[1] != data[(size_t)1 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if(len >= _numFastBytes) + { + backRes = i; + lenRes = len; + return MovePos(lenRes - 1); + } + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + } + UInt32 *matchDistances = _matchDistances + 1; + if(lenMain >= _numFastBytes) + { + backRes = matchDistances[numDistancePairs - 1] + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 1); + } + + UInt32 backMain = 0; // for GCC + if (lenMain >= 2) + { + backMain = matchDistances[numDistancePairs - 1]; + while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1) + { + if (!ChangePair(matchDistances[numDistancePairs - 3], backMain)) + break; + numDistancePairs -= 2; + lenMain = matchDistances[numDistancePairs - 2]; + backMain = matchDistances[numDistancePairs - 1]; + } + if (lenMain == 2 && backMain >= 0x80) + lenMain = 1; + } + + if (repLens[repMaxIndex] >= 2) + { + if (repLens[repMaxIndex] + 1 >= lenMain || + ( repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9)) ) || + ( repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15)) ) ) + { + backRes = repMaxIndex; + lenRes = repLens[repMaxIndex]; + return MovePos(lenRes - 1); + } + } + + if (lenMain >= 2 && numAvailableBytes > 2) + { + RINOK(ReadMatchDistances(_longestMatchLength, _numDistancePairs)); + if (_longestMatchLength >= 2) + { + UInt32 newDistance = matchDistances[_numDistancePairs - 1]; + if (( _longestMatchLength >= lenMain && newDistance < backMain ) || + ( _longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance) ) || + ( _longestMatchLength > lenMain + 1 ) || + ( _longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain) ) ) + { + _longestMatchWasFound = true; + backRes = UInt32(-1); + lenRes = 1; + return S_OK; + } + } + data++; + numAvailableBytes--; + for(UInt32 i = 0; i < kNumRepDistances; i++) + { + UInt32 backOffset = _repDistances[i] + 1; + if (data[1] != data[(size_t)1 - backOffset] || data[2] != data[(size_t)2 - backOffset]) + { + repLens[i] = 0; + continue; + } + UInt32 len; + for (len = 2; len < numAvailableBytes && data[len] == data[(size_t)len - backOffset]; len++); + if (len + 1 >= lenMain) + { + _longestMatchWasFound = true; + backRes = UInt32(-1); + lenRes = 1; + return S_OK; + } + } + backRes = backMain + kNumRepDistances; + lenRes = lenMain; + return MovePos(lenMain - 2); + } + backRes = UInt32(-1); + lenRes = 1; + return S_OK; +} + +HRESULT CEncoder::Flush(UInt32 nowPos) +{ + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + return _rangeEncoder.FlushStream(); +} + +void CEncoder::WriteEndMarker(UInt32 posState) +{ + // This function for writing End Mark for stream version of LZMA. + // In current version this feature is not used. + if (!_writeEndMark) + return; + + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); + _isRep[_state.Index].Encode(&_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = kMatchMinLen; // kMatchMaxLen; + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + UInt32 posSlot = (1 << kNumPosSlotBits) - 1; + UInt32 lenToPosState = GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot); + UInt32 footerBits = 30; + UInt32 posReduced = (UInt32(1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); +} + +HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + _needReleaseMFStream = false; + CCoderReleaser coderReleaser(this); + RINOK(SetStreams(inStream, outStream, inSize, outSize)); + while(true) + { + UInt64 processedInSize; + UInt64 processedOutSize; + Int32 finished; + RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished)); + if (finished != 0) + return S_OK; + if (progress != 0) + { + RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize)); + } + } +} + +HRESULT CEncoder::SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize) +{ + _inStream = inStream; + _finished = false; + RINOK(Create()); + RINOK(SetOutStream(outStream)); + RINOK(Init()); + + // CCoderReleaser releaser(this); + + /* + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(); + */ + + if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); + _lenEncoder.UpdateTables(1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - kMatchMinLen); + _repMatchLenEncoder.UpdateTables(1 << _posStateBits); + + nowPos64 = 0; + return S_OK; +} + +HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished) +{ + if (_inStream != 0) + { + RINOK(_matchFinder->SetStream(_inStream)); + RINOK(_matchFinder->Init()); + _needReleaseMFStream = true; + _inStream = 0; + } + + + *finished = 1; + if (_finished) + return S_OK; + _finished = true; + + if (nowPos64 == 0) + { + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(UInt32(nowPos64)); + UInt32 len, numDistancePairs; + RINOK(ReadMatchDistances(len, numDistancePairs)); + UInt32 posState = UInt32(nowPos64) & _posStateMask; + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + + UInt32 nowPos32 = (UInt32)nowPos64; + UInt32 progressPosValuePrev = nowPos32; + + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(nowPos32); + + while(true) + { + #ifdef _NO_EXCEPTIONS + if (_rangeEncoder.Stream.ErrorCode != S_OK) + return _rangeEncoder.Stream.ErrorCode; + #endif + UInt32 pos, len; + HRESULT result; + if (_fastMode) + result = GetOptimumFast(nowPos32, pos, len); + else + result = GetOptimum(nowPos32, pos, len); + RINOK(result); + + UInt32 posState = nowPos32 & _posStateMask; + if(len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0); + Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset); + CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(nowPos32, _previousByte); + if(_state.IsCharState()) + subCoder->Encode(&_rangeEncoder, curByte); + else + { + Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset); + subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte); + } + _state.UpdateChar(); + _previousByte = curByte; + } + else + { + _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1); + if(pos < kNumRepDistances) + { + _isRep[_state.Index].Encode(&_rangeEncoder, 1); + if(pos == 0) + { + _isRepG0[_state.Index].Encode(&_rangeEncoder, 0); + _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, ((len == 1) ? 0 : 1)); + } + else + { + UInt32 distance = _repDistances[pos]; + _isRepG0[_state.Index].Encode(&_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(&_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(&_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2); + if (pos == 3) + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; + } + _repDistances[1] = _repDistances[0]; + _repDistances[0] = distance; + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + _state.UpdateRep(); + } + } + else + { + _isRep[_state.Index].Encode(&_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState, !_fastMode); + pos -= kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + _posSlotEncoder[GetLenToPosState(len)].Encode(&_rangeEncoder, posSlot); + + if (posSlot >= kStartPosModelIndex) + { + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - base; + + if (posSlot < kEndPosModelIndex) + NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1, + &_rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask); + _alignPriceCount++; + } + } + _repDistances[3] = _repDistances[2]; + _repDistances[2] = _repDistances[1]; + _repDistances[1] = _repDistances[0]; + _repDistances[0] = pos; + _matchPriceCount++; + } + _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset); + } + _additionalOffset -= len; + nowPos32 += len; + if (_additionalOffset == 0) + { + if (!_fastMode) + { + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= kAlignTableSize) + FillAlignPrices(); + } + if (_matchFinder->GetNumAvailableBytes() == 0) + return Flush(nowPos32); + if (nowPos32 - progressPosValuePrev >= (1 << 14)) + { + nowPos64 += nowPos32 - progressPosValuePrev; + *inSize = nowPos64; + *outSize = _rangeEncoder.GetProcessedSize(); + _finished = false; + *finished = 0; + return S_OK; + } + } + } +} + +STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) +{ + #ifndef _NO_EXCEPTIONS + try + { + #endif + return CodeReal(inStream, outStream, inSize, outSize, progress); + #ifndef _NO_EXCEPTIONS + } + catch(const COutBufferException &e) { return e.ErrorCode; } + catch(...) { return E_FAIL; } + #endif +} + +void CEncoder::FillDistancesPrices() +{ + UInt32 tempPrices[kNumFullDistances]; + for (UInt32 i = kStartPosModelIndex; i < kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + UInt32 footerBits = ((posSlot >> 1) - 1); + UInt32 base = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = NRangeCoder::ReverseBitTreeGetPrice(_posEncoders + + base - posSlot - 1, footerBits, i - base); + } + + for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + NRangeCoder::CBitTreeEncoder &encoder = _posSlotEncoder[lenToPosState]; + UInt32 *posSlotPrices = _posSlotPrices[lenToPosState]; + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] = encoder.GetPrice(posSlot); + for (posSlot = kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits); + + UInt32 *distancesPrices = _distancesPrices[lenToPosState]; + UInt32 i; + for (i = 0; i < kStartPosModelIndex; i++) + distancesPrices[i] = posSlotPrices[i]; + for (; i < kNumFullDistances; i++) + distancesPrices[i] = posSlotPrices[GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; +} + +void CEncoder::FillAlignPrices() +{ + for (UInt32 i = 0; i < kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; +} + +}} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h new file mode 100644 index 00000000..f4c2c151 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/LZMAEncoder.h @@ -0,0 +1,411 @@ +// LZMA/Encoder.h + +#ifndef __LZMA_ENCODER_H +#define __LZMA_ENCODER_H + +#include "../../../Common/MyCom.h" +#include "../../../Common/Alloc.h" +#include "../../ICoder.h" +#include "../LZ/IMatchFinder.h" +#include "../RangeCoder/RangeCoderBitTree.h" + +#include "LZMA.h" + +namespace NCompress { +namespace NLZMA { + +typedef NRangeCoder::CBitEncoder CMyBitEncoder; + +class CBaseState +{ +protected: + CState _state; + Byte _previousByte; + UInt32 _repDistances[kNumRepDistances]; + void Init() + { + _state.Init(); + _previousByte = 0; + for(UInt32 i = 0 ; i < kNumRepDistances; i++) + _repDistances[i] = 0; + } +}; + +struct COptimal +{ + CState State; + + bool Prev1IsChar; + bool Prev2; + + UInt32 PosPrev2; + UInt32 BackPrev2; + + UInt32 Price; + UInt32 PosPrev; // posNext; + UInt32 BackPrev; + UInt32 Backs[kNumRepDistances]; + void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; } + void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + bool IsShortRep() { return (BackPrev == 0); } +}; + + +extern Byte g_FastPos[1 << 11]; +inline UInt32 GetPosSlot(UInt32 pos) +{ + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return g_FastPos[pos >> 10] + 20; + return g_FastPos[pos >> 20] + 40; +} + +inline UInt32 GetPosSlot2(UInt32 pos) +{ + if (pos < (1 << 17)) + return g_FastPos[pos >> 6] + 12; + if (pos < (1 << 27)) + return g_FastPos[pos >> 16] + 32; + return g_FastPos[pos >> 26] + 52; +} + +const UInt32 kIfinityPrice = 0xFFFFFFF; + +const UInt32 kNumOpts = 1 << 12; + + +class CLiteralEncoder2 +{ + CMyBitEncoder _encoders[0x300]; +public: + void Init() + { + for (int i = 0; i < 0x300; i++) + _encoders[i].Init(); + } + void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol); + void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol); + UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const; +}; + +class CLiteralEncoder +{ + CLiteralEncoder2 *_coders; + int _numPrevBits; + int _numPosBits; + UInt32 _posMask; +public: + CLiteralEncoder(): _coders(0) {} + ~CLiteralEncoder() { Free(); } + void Free() + { + MyFree(_coders); + _coders = 0; + } + bool Create(int numPosBits, int numPrevBits) + { + if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits)) + { + Free(); + UInt32 numStates = 1 << (numPosBits + numPrevBits); + _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2)); + } + _numPosBits = numPosBits; + _posMask = (1 << numPosBits) - 1; + _numPrevBits = numPrevBits; + return (_coders != 0); + } + void Init() + { + UInt32 numStates = 1 << (_numPrevBits + _numPosBits); + for (UInt32 i = 0; i < numStates; i++) + _coders[i].Init(); + } + CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte) + { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; } +}; + +namespace NLength { + +class CEncoder +{ + CMyBitEncoder _choice; + CMyBitEncoder _choice2; + NRangeCoder::CBitTreeEncoder _lowCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder _midCoder[kNumPosStatesEncodingMax]; + NRangeCoder::CBitTreeEncoder _highCoder; +public: + void Init(UInt32 numPosStates); + void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState); + void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const; +}; + +const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; + +class CPriceTableEncoder: public CEncoder +{ + UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal]; + UInt32 _tableSize; + UInt32 _counters[kNumPosStatesEncodingMax]; +public: + void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; } + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices[posState]); + _counters[posState] = _tableSize; + } + void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice) + { + CEncoder::Encode(rangeEncoder, symbol, posState); + if (updatePrice) + if (--_counters[posState] == 0) + UpdateTable(posState); + } +}; + +} + +class CEncoder : + public ICompressCoder, + public ICompressSetOutStream, + public ICompressSetCoderProperties, + public ICompressWriteCoderProperties, + public CBaseState, + public CMyUnknownImp +{ + COptimal _optimum[kNumOpts]; + CMyComPtr _matchFinder; // test it + NRangeCoder::CEncoder _rangeEncoder; + + CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax]; + CMyBitEncoder _isRep[kNumStates]; + CMyBitEncoder _isRepG0[kNumStates]; + CMyBitEncoder _isRepG1[kNumStates]; + CMyBitEncoder _isRepG2[kNumStates]; + CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax]; + + NRangeCoder::CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates]; + + CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex]; + NRangeCoder::CBitTreeEncoder _posAlignEncoder; + + NLength::CPriceTableEncoder _lenEncoder; + NLength::CPriceTableEncoder _repMatchLenEncoder; + + CLiteralEncoder _literalEncoder; + + UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1]; + + bool _fastMode; + // bool _maxMode; + UInt32 _numFastBytes; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + + UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + UInt32 _alignPrices[kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize; + + UInt32 _posStateBits; + UInt32 _posStateMask; + UInt32 _numLiteralPosStateBits; + UInt32 _numLiteralContextBits; + + UInt32 _dictionarySize; + + UInt32 _dictionarySizePrev; + UInt32 _numFastBytesPrev; + + UInt32 _matchPriceCount; + UInt64 nowPos64; + bool _finished; + ISequentialInStream *_inStream; + + UInt32 _matchFinderCycles; + int _matchFinderIndex; + #ifdef COMPRESS_MF_MT + bool _multiThread; + #endif + + bool _writeEndMark; + + bool _needReleaseMFStream; + + IMatchFinderSetNumPasses *setMfPasses; + + void ReleaseMatchFinder() + { + setMfPasses = 0; + _matchFinder.Release(); + } + + HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs); + + HRESULT MovePos(UInt32 num); + UInt32 GetRepLen1Price(CState state, UInt32 posState) const + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[state.Index][posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const + { + UInt32 price; + if(repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[state.Index][posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const + { + return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) + + GetPureRepPrice(repIndex, state, posState); + } + /* + UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const + { + if (pos >= kNumFullDistances) + return kIfinityPrice; + return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState); + } + UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const + { + UInt32 price; + UInt32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + */ + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const + { + UInt32 price; + UInt32 lenToPosState = GetLenToPosState(len); + if (pos < kNumFullDistances) + price = _distancesPrices[lenToPosState][pos]; + else + price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + + _alignPrices[pos & kAlignMask]; + return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState); + } + + UInt32 Backward(UInt32 &backRes, UInt32 cur); + HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes); + HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes); + + void FillDistancesPrices(); + void FillAlignPrices(); + + void ReleaseMFStream() + { + if (_matchFinder && _needReleaseMFStream) + { + _matchFinder->ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + HRESULT Flush(UInt32 nowPos); + class CCoderReleaser + { + CEncoder *_coder; + public: + CCoderReleaser(CEncoder *coder): _coder(coder) {} + ~CCoderReleaser() + { + _coder->ReleaseStreams(); + } + }; + friend class CCoderReleaser; + + void WriteEndMarker(UInt32 posState); + +public: + CEncoder(); + void SetWriteEndMarkerMode(bool writeEndMarker) + { _writeEndMark= writeEndMarker; } + + HRESULT Create(); + + MY_UNKNOWN_IMP3( + ICompressSetOutStream, + ICompressSetCoderProperties, + ICompressWriteCoderProperties + ) + + HRESULT Init(); + + // ICompressCoder interface + HRESULT SetStreams(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize); + HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished); + + HRESULT CodeReal(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + // ICompressCoder interface + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress); + + // ICompressSetCoderProperties2 + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties); + + // ICompressWriteCoderProperties + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream); + + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream); + STDMETHOD(ReleaseOutStream)(); + + virtual ~CEncoder() {} +}; + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA/StdAfx.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA/StdAfx.h new file mode 100644 index 00000000..e7fb6986 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp new file mode 100644 index 00000000..dace1476 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsp @@ -0,0 +1,475 @@ +# Microsoft Developer Studio Project File - Name="AloneLZMA" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=AloneLZMA - Win32 DebugU +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "AloneLZMA.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "AloneLZMA.mak" CFG="AloneLZMA - Win32 DebugU" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "AloneLZMA - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "AloneLZMA - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE "AloneLZMA - Win32 ReleaseU" (based on "Win32 (x86) Console Application") +!MESSAGE "AloneLZMA - Win32 DebugU" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "AloneLZMA - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "AloneLZMA - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_MBCS" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept + +!ELSEIF "$(CFG)" == "AloneLZMA - Win32 ReleaseU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseU" +# PROP BASE Intermediate_Dir "ReleaseU" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseU" +# PROP Intermediate_Dir "ReleaseU" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /Yu"StdAfx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\..\\" /D "NDEBUG" /D "UNICODE" /D "_UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /c +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x419 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\7za2.exe" /opt:NOWIN98 +# SUBTRACT BASE LINK32 /pdb:none +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"c:\UTIL\lzma.exe" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "AloneLZMA - Win32 DebugU" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugU" +# PROP BASE Intermediate_Dir "DebugU" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugU" +# PROP Intermediate_Dir "DebugU" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "EXCLUDE_COM" /D "NO_REGISTRY" /D "FORMAT_7Z" /D "FORMAT_BZIP2" /D "FORMAT_ZIP" /D "FORMAT_TAR" /D "FORMAT_GZIP" /D "COMPRESS_LZMA" /D "COMPRESS_BCJ_X86" /D "COMPRESS_BCJ2" /D "COMPRESS_COPY" /D "COMPRESS_MF_PAT" /D "COMPRESS_MF_BT" /D "COMPRESS_PPMD" /D "COMPRESS_DEFLATE" /D "COMPRESS_IMPLODE" /D "COMPRESS_BZIP2" /D "CRYPTO_ZIP" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D "_CONSOLE" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x419 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\7za2.exe" /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"c:\UTIL\lzma.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "AloneLZMA - Win32 Release" +# Name "AloneLZMA - Win32 Debug" +# Name "AloneLZMA - Win32 ReleaseU" +# Name "AloneLZMA - Win32 DebugU" +# Begin Group "Spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"StdAfx.h" +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Group "LZMA" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\LZMA\LZMA.h +# End Source File +# Begin Source File + +SOURCE=..\LZMA\LZMADecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\LZMA\LZMADecoder.h +# End Source File +# Begin Source File + +SOURCE=..\LZMA\LZMAEncoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\LZMA\LZMAEncoder.h +# End Source File +# End Group +# Begin Group "RangeCoder" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoder.h +# End Source File +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoderBit.cpp +# End Source File +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoderBit.h +# End Source File +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoderBitTree.h +# End Source File +# Begin Source File + +SOURCE=..\RangeCoder\RangeCoderOpt.h +# End Source File +# End Group +# Begin Group "LZ" + +# PROP Default_Filter "" +# Begin Group "BT" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTree.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTree2.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTree3.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTree3Z.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTree4.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\BinTree\BinTreeMain.h +# End Source File +# End Group +# Begin Group "HC" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\LZ\HashChain\HC4.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\HashChain\HCMain.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\LZ\IMatchFinder.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\LZInWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\LZ\LZInWindow.h +# End Source File +# Begin Source File + +SOURCE=..\LZ\LZOutWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\LZ\LZOutWindow.h +# End Source File +# End Group +# Begin Group "Branch" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Branch\BranchTypes.h +# End Source File +# Begin Source File + +SOURCE=..\Branch\BranchX86.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\Branch\BranchX86.h +# End Source File +# End Group +# Begin Group "LZMA_C" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\LZMA_C\LzmaDecode.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=..\LZMA_C\LzmaDecode.h +# End Source File +# Begin Source File + +SOURCE=..\LZMA_C\LzmaTypes.h +# End Source File +# End Group +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileIO.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CommandLineParser.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Defs.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyCom.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\MyWindows.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Types.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.h +# End Source File +# End Group +# Begin Group "7zip Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\FileStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\FileStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\ICoder.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaAlone.cpp +# End Source File +# Begin Source File + +SOURCE=.\LzmaBench.cpp +# End Source File +# Begin Source File + +SOURCE=.\LzmaBench.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaRam.cpp +# End Source File +# Begin Source File + +SOURCE=.\LzmaRam.h +# End Source File +# Begin Source File + +SOURCE=.\LzmaRamDecode.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# Begin Source File + +SOURCE=.\LzmaRamDecode.h +# End Source File +# End Target +# End Project diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw new file mode 100644 index 00000000..d7482d8a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/AloneLZMA.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "AloneLZMA"=.\AloneLZMA.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp new file mode 100644 index 00000000..cce01eb2 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaAlone.cpp @@ -0,0 +1,524 @@ +// LzmaAlone.cpp + +#include "StdAfx.h" + +#include "../../../Common/MyWindows.h" +#include "../../../Common/MyInitGuid.h" + +#include + +#if defined(_WIN32) || defined(OS2) || defined(MSDOS) +#include +#include +#define MY_SET_BINARY_MODE(file) setmode(fileno(file),O_BINARY) +#else +#define MY_SET_BINARY_MODE(file) +#endif + +#include "../../../Common/CommandLineParser.h" +#include "../../../Common/StringConvert.h" +#include "../../../Common/StringToInt.h" + +#include "../../Common/FileStreams.h" +#include "../../Common/StreamUtils.h" + +#include "../LZMA/LZMADecoder.h" +#include "../LZMA/LZMAEncoder.h" + +#include "LzmaBench.h" +#include "LzmaRam.h" + +extern "C" +{ +#include "LzmaRamDecode.h" +} + +using namespace NCommandLineParser; + +#ifdef _WIN32 +bool g_IsNT = false; +static inline bool IsItWindowsNT() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif + +static const char *kCantAllocate = "Can not allocate memory"; +static const char *kReadError = "Read error"; +static const char *kWriteError = "Write error"; + +namespace NKey { +enum Enum +{ + kHelp1 = 0, + kHelp2, + kMode, + kDictionary, + kFastBytes, + kMatchFinderCycles, + kLitContext, + kLitPos, + kPosBits, + kMatchFinder, + kEOS, + kStdIn, + kStdOut, + kFilter86 +}; +} + +static const CSwitchForm kSwitchForms[] = +{ + { L"?", NSwitchType::kSimple, false }, + { L"H", NSwitchType::kSimple, false }, + { L"A", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"D", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"FB", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"MC", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"LC", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"LP", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"PB", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"MF", NSwitchType::kUnLimitedPostString, false, 1 }, + { L"EOS", NSwitchType::kSimple, false }, + { L"SI", NSwitchType::kSimple, false }, + { L"SO", NSwitchType::kSimple, false }, + { L"F86", NSwitchType::kSimple, false } +}; + +static const int kNumSwitches = sizeof(kSwitchForms) / sizeof(kSwitchForms[0]); + +static void PrintHelp() +{ + fprintf(stderr, "\nUsage: LZMA inputFile outputFile [...]\n" + " e: encode file\n" + " d: decode file\n" + " b: Benchmark\n" + "\n" + " -a{N}: set compression mode - [0, 1], default: 1 (max)\n" + " -d{N}: set dictionary - [0,30], default: 23 (8MB)\n" + " -fb{N}: set number of fast bytes - [5, 273], default: 128\n" + " -mc{N}: set number of cycles for match finder\n" + " -lc{N}: set number of literal context bits - [0, 8], default: 3\n" + " -lp{N}: set number of literal pos bits - [0, 4], default: 0\n" + " -pb{N}: set number of pos bits - [0, 4], default: 2\n" + " -mf{MF_ID}: set Match Finder: [bt2, bt3, bt4, hc4], default: bt4\n" + " -eos: write End Of Stream marker\n" + " -si: read data from stdin\n" + " -so: write data to stdout\n" + ); +} + +static void PrintHelpAndExit(const char *s) +{ + fprintf(stderr, "\nError: %s\n\n", s); + PrintHelp(); + throw -1; +} + +static void IncorrectCommand() +{ + PrintHelpAndExit("Incorrect command"); +} + +static void WriteArgumentsToStringList(int numArguments, const char *arguments[], + UStringVector &strings) +{ + for(int i = 1; i < numArguments; i++) + strings.Add(MultiByteToUnicodeString(arguments[i])); +} + +static bool GetNumber(const wchar_t *s, UInt32 &value) +{ + value = 0; + if (MyStringLen(s) == 0) + return false; + const wchar_t *end; + UInt64 res = ConvertStringToUInt64(s, &end); + if (*end != L'\0') + return false; + if (res > 0xFFFFFFFF) + return false; + value = UInt32(res); + return true; +} + +int main2(int n, const char *args[]) +{ + #ifdef _WIN32 + g_IsNT = IsItWindowsNT(); + #endif + + fprintf(stderr, "\nLZMA 4.43 Copyright (c) 1999-2006 Igor Pavlov 2006-06-04\n"); + + if (n == 1) + { + PrintHelp(); + return 0; + } + + if (sizeof(Byte) != 1 || sizeof(UInt32) < 4 || sizeof(UInt64) < 4) + { + fprintf(stderr, "Unsupported base types. Edit Common/Types.h and recompile"); + return 1; + } + + UStringVector commandStrings; + WriteArgumentsToStringList(n, args, commandStrings); + CParser parser(kNumSwitches); + try + { + parser.ParseStrings(kSwitchForms, commandStrings); + } + catch(...) + { + IncorrectCommand(); + } + + if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) + { + PrintHelp(); + return 0; + } + const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; + + int paramIndex = 0; + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &command = nonSwitchStrings[paramIndex++]; + + bool dictionaryIsDefined = false; + UInt32 dictionary = 1 << 21; + if(parser[NKey::kDictionary].ThereIs) + { + UInt32 dicLog; + if (!GetNumber(parser[NKey::kDictionary].PostStrings[0], dicLog)) + IncorrectCommand(); + dictionary = 1 << dicLog; + dictionaryIsDefined = true; + } + UString mf = L"BT4"; + if (parser[NKey::kMatchFinder].ThereIs) + mf = parser[NKey::kMatchFinder].PostStrings[0]; + + if (command.CompareNoCase(L"b") == 0) + { + const UInt32 kNumDefaultItereations = 10; + UInt32 numIterations = kNumDefaultItereations; + { + if (paramIndex < nonSwitchStrings.Size()) + if (!GetNumber(nonSwitchStrings[paramIndex++], numIterations)) + numIterations = kNumDefaultItereations; + } + return LzmaBenchmark(stderr, numIterations, dictionary); + } + + bool encodeMode = false; + if (command.CompareNoCase(L"e") == 0) + encodeMode = true; + else if (command.CompareNoCase(L"d") == 0) + encodeMode = false; + else + IncorrectCommand(); + + bool stdInMode = parser[NKey::kStdIn].ThereIs; + bool stdOutMode = parser[NKey::kStdOut].ThereIs; + + CMyComPtr inStream; + CInFileStream *inStreamSpec = 0; + if (stdInMode) + { + inStream = new CStdInFileStream; + MY_SET_BINARY_MODE(stdin); + } + else + { + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &inputName = nonSwitchStrings[paramIndex++]; + inStreamSpec = new CInFileStream; + inStream = inStreamSpec; + if (!inStreamSpec->Open(GetSystemString(inputName))) + { + fprintf(stderr, "\nError: can not open input file %s\n", + (const char *)GetOemString(inputName)); + return 1; + } + } + + CMyComPtr outStream; + if (stdOutMode) + { + outStream = new CStdOutFileStream; + MY_SET_BINARY_MODE(stdout); + } + else + { + if (paramIndex >= nonSwitchStrings.Size()) + IncorrectCommand(); + const UString &outputName = nonSwitchStrings[paramIndex++]; + COutFileStream *outStreamSpec = new COutFileStream; + outStream = outStreamSpec; + if (!outStreamSpec->Create(GetSystemString(outputName), true)) + { + fprintf(stderr, "\nError: can not open output file %s\n", + (const char *)GetOemString(outputName)); + return 1; + } + } + + if (parser[NKey::kFilter86].ThereIs) + { + // -f86 switch is for x86 filtered mode: BCJ + LZMA. + if (parser[NKey::kEOS].ThereIs || stdInMode) + throw "Can not use stdin in this mode"; + UInt64 fileSize; + inStreamSpec->File.GetLength(fileSize); + if (fileSize > 0xF0000000) + throw "File is too big"; + UInt32 inSize = (UInt32)fileSize; + Byte *inBuffer = 0; + if (inSize != 0) + { + inBuffer = (Byte *)MyAlloc((size_t)inSize); + if (inBuffer == 0) + throw kCantAllocate; + } + + UInt32 processedSize; + if (ReadStream(inStream, inBuffer, (UInt32)inSize, &processedSize) != S_OK) + throw "Can not read"; + if ((UInt32)inSize != processedSize) + throw "Read size error"; + + Byte *outBuffer = 0; + size_t outSizeProcessed; + if (encodeMode) + { + // we allocate 105% of original size for output buffer + size_t outSize = (size_t)fileSize / 20 * 21 + (1 << 16); + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc((size_t)outSize); + if (outBuffer == 0) + throw kCantAllocate; + } + if (!dictionaryIsDefined) + dictionary = 1 << 23; + int res = LzmaRamEncode(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, + dictionary, SZ_FILTER_AUTO); + if (res != 0) + { + fprintf(stderr, "\nEncoder error = %d\n", (int)res); + return 1; + } + } + else + { + size_t outSize; + if (LzmaRamGetUncompressedSize(inBuffer, inSize, &outSize) != 0) + throw "data error"; + if (outSize != 0) + { + outBuffer = (Byte *)MyAlloc(outSize); + if (outBuffer == 0) + throw kCantAllocate; + } + int res = LzmaRamDecompress(inBuffer, inSize, outBuffer, outSize, &outSizeProcessed, malloc, free); + if (res != 0) + throw "LzmaDecoder error"; + } + if (WriteStream(outStream, outBuffer, (UInt32)outSizeProcessed, &processedSize) != S_OK) + throw kWriteError; + MyFree(outBuffer); + MyFree(inBuffer); + return 0; + } + + + UInt64 fileSize; + if (encodeMode) + { + NCompress::NLZMA::CEncoder *encoderSpec = + new NCompress::NLZMA::CEncoder; + CMyComPtr encoder = encoderSpec; + + if (!dictionaryIsDefined) + dictionary = 1 << 23; + + UInt32 posStateBits = 2; + UInt32 litContextBits = 3; // for normal files + // UInt32 litContextBits = 0; // for 32-bit data + UInt32 litPosBits = 0; + // UInt32 litPosBits = 2; // for 32-bit data + UInt32 algorithm = 2; + UInt32 numFastBytes = 128; + UInt32 matchFinderCycles = 16 + numFastBytes / 2; + bool matchFinderCyclesDefined = false; + + bool eos = parser[NKey::kEOS].ThereIs || stdInMode; + + if(parser[NKey::kMode].ThereIs) + if (!GetNumber(parser[NKey::kMode].PostStrings[0], algorithm)) + IncorrectCommand(); + + if(parser[NKey::kFastBytes].ThereIs) + if (!GetNumber(parser[NKey::kFastBytes].PostStrings[0], numFastBytes)) + IncorrectCommand(); + if (matchFinderCyclesDefined = parser[NKey::kMatchFinderCycles].ThereIs) + if (!GetNumber(parser[NKey::kMatchFinderCycles].PostStrings[0], matchFinderCycles)) + IncorrectCommand(); + if(parser[NKey::kLitContext].ThereIs) + if (!GetNumber(parser[NKey::kLitContext].PostStrings[0], litContextBits)) + IncorrectCommand(); + if(parser[NKey::kLitPos].ThereIs) + if (!GetNumber(parser[NKey::kLitPos].PostStrings[0], litPosBits)) + IncorrectCommand(); + if(parser[NKey::kPosBits].ThereIs) + if (!GetNumber(parser[NKey::kPosBits].PostStrings[0], posStateBits)) + IncorrectCommand(); + + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kPosStateBits, + NCoderPropID::kLitContextBits, + NCoderPropID::kLitPosBits, + NCoderPropID::kAlgorithm, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinder, + NCoderPropID::kEndMarker, + NCoderPropID::kMatchFinderCycles + }; + const int kNumPropsMax = sizeof(propIDs) / sizeof(propIDs[0]); + /* + NWindows::NCOM::CPropVariant properties[kNumProps]; + properties[0] = UInt32(dictionary); + properties[1] = UInt32(posStateBits); + properties[2] = UInt32(litContextBits); + + properties[3] = UInt32(litPosBits); + properties[4] = UInt32(algorithm); + properties[5] = UInt32(numFastBytes); + properties[6] = mf; + properties[7] = eos; + */ + PROPVARIANT properties[kNumPropsMax]; + for (int p = 0; p < 6; p++) + properties[p].vt = VT_UI4; + + properties[0].ulVal = UInt32(dictionary); + properties[1].ulVal = UInt32(posStateBits); + properties[2].ulVal = UInt32(litContextBits); + properties[3].ulVal = UInt32(litPosBits); + properties[4].ulVal = UInt32(algorithm); + properties[5].ulVal = UInt32(numFastBytes); + + properties[8].vt = VT_UI4; + properties[8].ulVal = UInt32(matchFinderCycles); + + properties[6].vt = VT_BSTR; + properties[6].bstrVal = (BSTR)(const wchar_t *)mf; + + properties[7].vt = VT_BOOL; + properties[7].boolVal = eos ? VARIANT_TRUE : VARIANT_FALSE; + + int numProps = kNumPropsMax; + if (!matchFinderCyclesDefined) + numProps--; + + if (encoderSpec->SetCoderProperties(propIDs, properties, numProps) != S_OK) + IncorrectCommand(); + encoderSpec->WriteCoderProperties(outStream); + + if (eos || stdInMode) + fileSize = (UInt64)(Int64)-1; + else + inStreamSpec->File.GetLength(fileSize); + + for (int i = 0; i < 8; i++) + { + Byte b = Byte(fileSize >> (8 * i)); + if (outStream->Write(&b, 1, 0) != S_OK) + { + fprintf(stderr, kWriteError); + return 1; + } + } + HRESULT result = encoder->Code(inStream, outStream, 0, 0, 0); + if (result == E_OUTOFMEMORY) + { + fprintf(stderr, "\nError: Can not allocate memory\n"); + return 1; + } + else if (result != S_OK) + { + fprintf(stderr, "\nEncoder error = %X\n", (unsigned int)result); + return 1; + } + } + else + { + NCompress::NLZMA::CDecoder *decoderSpec = + new NCompress::NLZMA::CDecoder; + CMyComPtr decoder = decoderSpec; + const UInt32 kPropertiesSize = 5; + Byte properties[kPropertiesSize]; + UInt32 processedSize; + if (ReadStream(inStream, properties, kPropertiesSize, &processedSize) != S_OK) + { + fprintf(stderr, kReadError); + return 1; + } + if (processedSize != kPropertiesSize) + { + fprintf(stderr, kReadError); + return 1; + } + if (decoderSpec->SetDecoderProperties2(properties, kPropertiesSize) != S_OK) + { + fprintf(stderr, "SetDecoderProperties error"); + return 1; + } + fileSize = 0; + for (int i = 0; i < 8; i++) + { + Byte b; + if (inStream->Read(&b, 1, &processedSize) != S_OK) + { + fprintf(stderr, kReadError); + return 1; + } + if (processedSize != 1) + { + fprintf(stderr, kReadError); + return 1; + } + fileSize |= ((UInt64)b) << (8 * i); + } + if (decoder->Code(inStream, outStream, 0, &fileSize, 0) != S_OK) + { + fprintf(stderr, "Decoder error"); + return 1; + } + } + return 0; +} + +int main(int n, const char *args[]) +{ + try { return main2(n, args); } + catch(const char *s) + { + fprintf(stderr, "\nError: %s\n", s); + return 1; + } + catch(...) + { + fprintf(stderr, "\nError\n"); + return 1; + } +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp new file mode 100644 index 00000000..7b54b26c --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.cpp @@ -0,0 +1,506 @@ +// LzmaBench.cpp + +#include "StdAfx.h" + +#include "LzmaBench.h" + +#ifndef _WIN32 +#include +#endif + +#include "../../../Common/CRC.h" +#include "../LZMA/LZMADecoder.h" +#include "../LZMA/LZMAEncoder.h" + +static const UInt32 kAdditionalSize = +#ifdef _WIN32_WCE +(1 << 20); +#else +(6 << 20); +#endif + +static const UInt32 kCompressedAdditionalSize = (1 << 10); +static const UInt32 kMaxLzmaPropSize = 10; + +class CRandomGenerator +{ + UInt32 A1; + UInt32 A2; +public: + CRandomGenerator() { Init(); } + void Init() { A1 = 362436069; A2 = 521288629;} + UInt32 GetRnd() + { + return + ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ + ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) ); + } +}; + +class CBitRandomGenerator +{ + CRandomGenerator RG; + UInt32 Value; + int NumBits; +public: + void Init() + { + Value = 0; + NumBits = 0; + } + UInt32 GetRnd(int numBits) + { + if (NumBits > numBits) + { + UInt32 result = Value & ((1 << numBits) - 1); + Value >>= numBits; + NumBits -= numBits; + return result; + } + numBits -= NumBits; + UInt32 result = (Value << numBits); + Value = RG.GetRnd(); + result |= Value & ((1 << numBits) - 1); + Value >>= numBits; + NumBits = 32 - numBits; + return result; + } +}; + +class CBenchRandomGenerator +{ + CBitRandomGenerator RG; + UInt32 Pos; + UInt32 Rep0; +public: + UInt32 BufferSize; + Byte *Buffer; + CBenchRandomGenerator(): Buffer(0) {} + ~CBenchRandomGenerator() { Free(); } + void Free() + { + ::MidFree(Buffer); + Buffer = 0; + } + bool Alloc(UInt32 bufferSize) + { + if (Buffer != 0 && BufferSize == bufferSize) + return true; + Free(); + Buffer = (Byte *)::MidAlloc(bufferSize); + Pos = 0; + BufferSize = bufferSize; + return (Buffer != 0); + } + UInt32 GetRndBit() { return RG.GetRnd(1); } + /* + UInt32 GetLogRand(int maxLen) + { + UInt32 len = GetRnd() % (maxLen + 1); + return GetRnd() & ((1 << len) - 1); + } + */ + UInt32 GetLogRandBits(int numBits) + { + UInt32 len = RG.GetRnd(numBits); + return RG.GetRnd(len); + } + UInt32 GetOffset() + { + if (GetRndBit() == 0) + return GetLogRandBits(4); + return (GetLogRandBits(4) << 10) | RG.GetRnd(10); + } + UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } + UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } + void Generate() + { + RG.Init(); + Rep0 = 1; + while(Pos < BufferSize) + { + if (GetRndBit() == 0 || Pos < 1) + Buffer[Pos++] = (Byte)RG.GetRnd(8); + else + { + UInt32 len; + if (RG.GetRnd(3) == 0) + len = 1 + GetLen1(); + else + { + do + Rep0 = GetOffset(); + while (Rep0 >= Pos); + Rep0++; + len = 2 + GetLen2(); + } + for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) + Buffer[Pos] = Buffer[Pos - Rep0]; + } + } + } +}; + +class CBenchmarkInStream: + public ISequentialInStream, + public CMyUnknownImp +{ + const Byte *Data; + UInt32 Pos; + UInt32 Size; +public: + MY_UNKNOWN_IMP + void Init(const Byte *data, UInt32 size) + { + Data = data; + Size = size; + Pos = 0; + } + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 remain = Size - Pos; + if (size > remain) + size = remain; + for (UInt32 i = 0; i < size; i++) + ((Byte *)data)[i] = Data[Pos + i]; + Pos += size; + if(processedSize != NULL) + *processedSize = size; + return S_OK; +} + +class CBenchmarkOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ + UInt32 BufferSize; + FILE *_f; +public: + UInt32 Pos; + Byte *Buffer; + CBenchmarkOutStream(): _f(0), Buffer(0) {} + virtual ~CBenchmarkOutStream() { delete []Buffer; } + void Init(FILE *f, UInt32 bufferSize) + { + delete []Buffer; + Buffer = 0; + Buffer = new Byte[bufferSize]; + Pos = 0; + BufferSize = bufferSize; + _f = f; + } + MY_UNKNOWN_IMP + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 i; + for (i = 0; i < size && Pos < BufferSize; i++) + Buffer[Pos++] = ((const Byte *)data)[i]; + if(processedSize != NULL) + *processedSize = i; + if (i != size) + { + fprintf(_f, "\nERROR: Buffer is full\n"); + return E_FAIL; + } + return S_OK; +} + +class CCrcOutStream: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CCRC CRC; + MY_UNKNOWN_IMP + void Init() { CRC.Init(); } + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + CRC.Update(data, size); + if(processedSize != NULL) + *processedSize = size; + return S_OK; +} + +static UInt64 GetTimeCount() +{ + #ifdef _WIN32 + LARGE_INTEGER value; + if (::QueryPerformanceCounter(&value)) + return value.QuadPart; + return GetTickCount(); + #else + return clock(); + #endif +} + +static UInt64 GetFreq() +{ + #ifdef _WIN32 + LARGE_INTEGER value; + if (::QueryPerformanceFrequency(&value)) + return value.QuadPart; + return 1000; + #else + return CLOCKS_PER_SEC; + #endif +} + +struct CProgressInfo: + public ICompressProgressInfo, + public CMyUnknownImp +{ + UInt64 ApprovedStart; + UInt64 InSize; + UInt64 Time; + void Init() + { + InSize = 0; + Time = 0; + } + MY_UNKNOWN_IMP + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); +}; + +STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize) +{ + if (*inSize >= ApprovedStart && InSize == 0) + { + Time = ::GetTimeCount(); + InSize = *inSize; + } + return S_OK; +} + +static const int kSubBits = 8; + +static UInt32 GetLogSize(UInt32 size) +{ + for (int i = kSubBits; i < 32; i++) + for (UInt32 j = 0; j < (1 << kSubBits); j++) + if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) + return (i << kSubBits) + j; + return (32 << kSubBits); +} + +static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) +{ + UInt64 freq = GetFreq(); + UInt64 elTime = elapsedTime; + while(freq > 1000000) + { + freq >>= 1; + elTime >>= 1; + } + if (elTime == 0) + elTime = 1; + return value * freq / elTime; +} + +static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) +{ + UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); + UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); + UInt64 numCommands = (UInt64)(size) * numCommandsForOne; + return MyMultDiv64(numCommands, elapsedTime); +} + +static UInt64 GetDecompressRating(UInt64 elapsedTime, + UInt64 outSize, UInt64 inSize) +{ + UInt64 numCommands = inSize * 220 + outSize * 20; + return MyMultDiv64(numCommands, elapsedTime); +} + +/* +static UInt64 GetTotalRating( + UInt32 dictionarySize, + bool isBT4, + UInt64 elapsedTimeEn, UInt64 sizeEn, + UInt64 elapsedTimeDe, + UInt64 inSizeDe, UInt64 outSizeDe) +{ + return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + + GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; +} +*/ + +static void PrintRating(FILE *f, UInt64 rating) +{ + fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000)); +} + +static void PrintResults( + FILE *f, + UInt32 dictionarySize, + UInt64 elapsedTime, + UInt64 size, + bool decompressMode, UInt64 secondSize) +{ + UInt64 speed = MyMultDiv64(size, elapsedTime); + fprintf(f, "%6d KB/s ", (unsigned int)(speed / 1024)); + UInt64 rating; + if (decompressMode) + rating = GetDecompressRating(elapsedTime, size, secondSize); + else + rating = GetCompressRating(dictionarySize, elapsedTime, size); + PrintRating(f, rating); +} + +static void ThrowError(FILE *f, HRESULT result, const char *s) +{ + fprintf(f, "\nError: "); + if (result == E_ABORT) + fprintf(f, "User break"); + if (result == E_OUTOFMEMORY) + fprintf(f, "Can not allocate memory"); + else + fprintf(f, s); + fprintf(f, "\n"); +} + +const wchar_t *bt2 = L"BT2"; +const wchar_t *bt4 = L"BT4"; + +int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize) +{ + if (numIterations == 0) + return 0; + if (dictionarySize < (1 << 18)) + { + fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n"); + return 1; + } + fprintf(f, "\n Compressing Decompressing\n\n"); + NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; + CMyComPtr encoder = encoderSpec; + + NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder; + CMyComPtr decoder = decoderSpec; + + CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream; + CMyComPtr propStream = propStreamSpec; + propStreamSpec->Init(f, kMaxLzmaPropSize); + + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize + }; + const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT properties[kNumProps]; + properties[0].vt = VT_UI4; + properties[0].ulVal = UInt32(dictionarySize); + + const UInt32 kBufferSize = dictionarySize + kAdditionalSize; + const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; + + if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) + { + fprintf(f, "\nError: Incorrect command\n"); + return 1; + } + encoderSpec->WriteCoderProperties(propStream); + + CBenchRandomGenerator rg; + if (!rg.Alloc(kBufferSize)) + { + fprintf(f, "\nError: Can't allocate memory\n"); + return 1; + } + + rg.Generate(); + CCRC crc; + crc.Update(rg.Buffer, rg.BufferSize); + + CProgressInfo *progressInfoSpec = new CProgressInfo; + CMyComPtr progressInfo = progressInfoSpec; + + progressInfoSpec->ApprovedStart = dictionarySize; + + UInt64 totalBenchSize = 0; + UInt64 totalEncodeTime = 0; + UInt64 totalDecodeTime = 0; + UInt64 totalCompressedSize = 0; + + for (UInt32 i = 0; i < numIterations; i++) + { + progressInfoSpec->Init(); + CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream; + inStreamSpec->Init(rg.Buffer, rg.BufferSize); + CMyComPtr inStream = inStreamSpec; + CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream; + outStreamSpec->Init(f, kCompressedBufferSize); + CMyComPtr outStream = outStreamSpec; + HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo); + UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time; + UInt32 compressedSize = outStreamSpec->Pos; + if(result != S_OK) + { + ThrowError(f, result, "Encoder Error"); + return 1; + } + if (progressInfoSpec->InSize == 0) + { + fprintf(f, "\nError: Internal ERROR 1282\n"); + return 1; + } + + /////////////////////// + // Decompressing + + CCrcOutStream *crcOutStreamSpec = new CCrcOutStream; + CMyComPtr crcOutStream = crcOutStreamSpec; + + UInt64 decodeTime; + for (int j = 0; j < 2; j++) + { + inStreamSpec->Init(outStreamSpec->Buffer, compressedSize); + crcOutStreamSpec->Init(); + + if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK) + { + fprintf(f, "\nError: Set Decoder Properties Error\n"); + return 1; + } + UInt64 outSize = kBufferSize; + UInt64 startTime = ::GetTimeCount(); + result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0); + decodeTime = ::GetTimeCount() - startTime; + if(result != S_OK) + { + ThrowError(f, result, "Decode Error"); + return 1; + } + if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest()) + { + fprintf(f, "\nError: CRC Error\n"); + return 1; + } + } + UInt64 benchSize = kBufferSize - progressInfoSpec->InSize; + PrintResults(f, dictionarySize, encodeTime, benchSize, false, 0); + fprintf(f, " "); + PrintResults(f, dictionarySize, decodeTime, kBufferSize, true, compressedSize); + fprintf(f, "\n"); + + totalBenchSize += benchSize; + totalEncodeTime += encodeTime; + totalDecodeTime += decodeTime; + totalCompressedSize += compressedSize; + } + fprintf(f, "---------------------------------------------------\n"); + PrintResults(f, dictionarySize, totalEncodeTime, totalBenchSize, false, 0); + fprintf(f, " "); + PrintResults(f, dictionarySize, totalDecodeTime, + kBufferSize * numIterations, true, totalCompressedSize); + fprintf(f, " Average\n"); + return 0; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h new file mode 100644 index 00000000..a6a0e82e --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaBench.h @@ -0,0 +1,11 @@ +// LzmaBench.h + +#ifndef __LzmaBench_h +#define __LzmaBench_h + +#include +#include "../../../Common/Types.h" + +int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp new file mode 100644 index 00000000..090d73d8 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.cpp @@ -0,0 +1,228 @@ +// LzmaRam.cpp + +#include "StdAfx.h" +#include "../../../Common/Types.h" +#include "../LZMA/LZMADecoder.h" +#include "../LZMA/LZMAEncoder.h" +#include "LzmaRam.h" + +extern "C" +{ +#include "../Branch/BranchX86.h" +} + +class CInStreamRam: + public ISequentialInStream, + public CMyUnknownImp +{ + const Byte *Data; + size_t Size; + size_t Pos; +public: + MY_UNKNOWN_IMP + void Init(const Byte *data, size_t size) + { + Data = data; + Size = size; + Pos = 0; + } + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 remain = Size - Pos; + if (size > remain) + size = remain; + for (UInt32 i = 0; i < size; i++) + ((Byte *)data)[i] = Data[Pos + i]; + Pos += size; + if(processedSize != NULL) + *processedSize = size; + return S_OK; +} + +class COutStreamRam: + public ISequentialOutStream, + public CMyUnknownImp +{ + size_t Size; +public: + Byte *Data; + size_t Pos; + bool Overflow; + void Init(Byte *data, size_t size) + { + Data = data; + Size = size; + Pos = 0; + Overflow = false; + } + void SetPos(size_t pos) + { + Overflow = false; + Pos = pos; + } + MY_UNKNOWN_IMP + HRESULT WriteByte(Byte b) + { + if (Pos >= Size) + { + Overflow = true; + return E_FAIL; + } + Data[Pos++] = b; + return S_OK; + } + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 i; + for (i = 0; i < size && Pos < Size; i++) + Data[Pos++] = ((const Byte *)data)[i]; + if(processedSize != NULL) + *processedSize = i; + if (i != size) + { + Overflow = true; + return E_FAIL; + } + return S_OK; +} + +#define SZE_FAIL (1) +#define SZE_OUTOFMEMORY (2) +#define SZE_OUT_OVERFLOW (3) + +int LzmaRamEncode( + const Byte *inBuffer, size_t inSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, + UInt32 dictionarySize, ESzFilterMode filterMode) +{ + #ifndef _NO_EXCEPTIONS + try { + #endif + + *outSizeProcessed = 0; + const size_t kIdSize = 1; + const size_t kLzmaPropsSize = 5; + const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8; + if (outSize < kMinDestSize) + return SZE_OUT_OVERFLOW; + NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder; + CMyComPtr encoder = encoderSpec; + + PROPID propIDs[] = + { + NCoderPropID::kAlgorithm, + NCoderPropID::kDictionarySize, + NCoderPropID::kNumFastBytes, + }; + const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]); + PROPVARIANT properties[kNumProps]; + properties[0].vt = VT_UI4; + properties[1].vt = VT_UI4; + properties[2].vt = VT_UI4; + properties[0].ulVal = (UInt32)2; + properties[1].ulVal = (UInt32)dictionarySize; + properties[2].ulVal = (UInt32)64; + + if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK) + return 1; + + COutStreamRam *outStreamSpec = new COutStreamRam; + if (outStreamSpec == 0) + return SZE_OUTOFMEMORY; + CMyComPtr outStream = outStreamSpec; + CInStreamRam *inStreamSpec = new CInStreamRam; + if (inStreamSpec == 0) + return SZE_OUTOFMEMORY; + CMyComPtr inStream = inStreamSpec; + + outStreamSpec->Init(outBuffer, outSize); + if (outStreamSpec->WriteByte(0) != S_OK) + return SZE_OUT_OVERFLOW; + + if (encoderSpec->WriteCoderProperties(outStream) != S_OK) + return SZE_OUT_OVERFLOW; + if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize) + return 1; + + int i; + for (i = 0; i < 8; i++) + { + UInt64 t = (UInt64)(inSize); + if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK) + return SZE_OUT_OVERFLOW; + } + + Byte *filteredStream = 0; + + bool useFilter = (filterMode != SZ_FILTER_NO); + if (useFilter) + { + if (inSize != 0) + { + filteredStream = (Byte *)MyAlloc(inSize); + if (filteredStream == 0) + return SZE_OUTOFMEMORY; + memmove(filteredStream, inBuffer, inSize); + } + UInt32 _prevMask; + UInt32 _prevPos; + x86_Convert_Init(_prevMask, _prevPos); + x86_Convert(filteredStream, (UInt32)inSize, 0, &_prevMask, &_prevPos, 1); + } + + UInt32 minSize = 0; + int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1; + bool bestIsFiltered = false; + int mainResult = 0; + size_t startPos = outStreamSpec->Pos; + for (i = 0; i < numPasses; i++) + { + if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered) + break; + outStreamSpec->SetPos(startPos); + bool curModeIsFiltered = false; + if (useFilter && i == 0) + curModeIsFiltered = true; + if (numPasses > 1 && i == numPasses - 1) + curModeIsFiltered = true; + + inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize); + + HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0); + + mainResult = 0; + if (lzmaResult == E_OUTOFMEMORY) + { + mainResult = SZE_OUTOFMEMORY; + break; + } + if (i == 0 || outStreamSpec->Pos <= minSize) + { + minSize = outStreamSpec->Pos; + bestIsFiltered = curModeIsFiltered; + } + if (outStreamSpec->Overflow) + mainResult = SZE_OUT_OVERFLOW; + else if (lzmaResult != S_OK) + { + mainResult = SZE_FAIL; + break; + } + } + *outSizeProcessed = outStreamSpec->Pos; + if (bestIsFiltered) + outBuffer[0] = 1; + if (useFilter) + MyFree(filteredStream); + return mainResult; + + #ifndef _NO_EXCEPTIONS + } catch(...) { return SZE_OUTOFMEMORY; } + #endif +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h new file mode 100644 index 00000000..1244dc86 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRam.h @@ -0,0 +1,46 @@ +// LzmaRam.h + +#ifndef __LzmaRam_h +#define __LzmaRam_h + +#include +#include "../../../Common/Types.h" + +/* +LzmaRamEncode: BCJ + LZMA RAM->RAM compressing. +It uses .lzma format, but it writes one additional byte to .lzma file: + 0: - no filter + 1: - x86(BCJ) filter. + +To provide best compression ratio dictionarySize mustbe >= inSize + +LzmaRamEncode allocates Data with MyAlloc/BigAlloc functions. +RAM Requirements: + RamSize = dictionarySize * 9.5 + 6MB + FilterBlockSize + FilterBlockSize = 0, if useFilter == false + FilterBlockSize = inSize, if useFilter == true + + Return code: + 0 - OK + 1 - Unspecified Error + 2 - Memory allocating error + 3 - Output buffer OVERFLOW + +If you use SZ_FILTER_AUTO mode, then encoder will use 2 or 3 passes: + 2 passes when FILTER_NO provides better compression. + 3 passes when FILTER_YES provides better compression. +*/ + +enum ESzFilterMode +{ + SZ_FILTER_NO, + SZ_FILTER_YES, + SZ_FILTER_AUTO +}; + +int LzmaRamEncode( + const Byte *inBuffer, size_t inSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, + UInt32 dictionarySize, ESzFilterMode filterMode); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c new file mode 100644 index 00000000..11ff7f69 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.c @@ -0,0 +1,79 @@ +/* LzmaRamDecode.c */ + +#include "LzmaRamDecode.h" +#ifdef _SZ_ONE_DIRECTORY +#include "LzmaDecode.h" +#include "BranchX86.h" +#else +#include "../LZMA_C/LzmaDecode.h" +#include "../Branch/BranchX86.h" +#endif + +#define LZMA_PROPS_SIZE 14 +#define LZMA_SIZE_OFFSET 6 + +int LzmaRamGetUncompressedSize( + const unsigned char *inBuffer, + size_t inSize, + size_t *outSize) +{ + unsigned int i; + if (inSize < LZMA_PROPS_SIZE) + return 1; + *outSize = 0; + for(i = 0; i < sizeof(size_t); i++) + *outSize += ((size_t)inBuffer[LZMA_SIZE_OFFSET + i]) << (8 * i); + for(; i < 8; i++) + if (inBuffer[LZMA_SIZE_OFFSET + i] != 0) + return 1; + return 0; +} + +#define SZE_DATA_ERROR (1) +#define SZE_OUTOFMEMORY (2) + +int LzmaRamDecompress( + const unsigned char *inBuffer, + size_t inSize, + unsigned char *outBuffer, + size_t outSize, + size_t *outSizeProcessed, + void * (*allocFunc)(size_t size), + void (*freeFunc)(void *)) +{ + CLzmaDecoderState state; /* it's about 24 bytes structure, if int is 32-bit */ + int result; + SizeT outSizeProcessedLoc; + SizeT inProcessed; + int useFilter; + + if (inSize < LZMA_PROPS_SIZE) + return 1; + useFilter = inBuffer[0]; + + *outSizeProcessed = 0; + if (useFilter > 1) + return 1; + + if (LzmaDecodeProperties(&state.Properties, inBuffer + 1, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + return 1; + state.Probs = (CProb *)allocFunc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (state.Probs == 0) + return SZE_OUTOFMEMORY; + + result = LzmaDecode(&state, + inBuffer + LZMA_PROPS_SIZE, (SizeT)inSize - LZMA_PROPS_SIZE, &inProcessed, + outBuffer, (SizeT)outSize, &outSizeProcessedLoc); + freeFunc(state.Probs); + if (result != LZMA_RESULT_OK) + return 1; + *outSizeProcessed = (size_t)outSizeProcessedLoc; + if (useFilter == 1) + { + UInt32 _prevMask; + UInt32 _prevPos; + x86_Convert_Init(_prevMask, _prevPos); + x86_Convert(outBuffer, (UInt32)outSizeProcessedLoc, 0, &_prevMask, &_prevPos, 0); + } + return 0; +} \ No newline at end of file diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h new file mode 100644 index 00000000..7e641c55 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/LzmaRamDecode.h @@ -0,0 +1,55 @@ +/* LzmaRamDecode.h */ + +#ifndef __LzmaRamDecode_h +#define __LzmaRamDecode_h + +#include + +/* +LzmaRamGetUncompressedSize: + In: + inBuffer - input data + inSize - input data size + Out: + outSize - uncompressed size + Return code: + 0 - OK + 1 - Error in headers +*/ + +int LzmaRamGetUncompressedSize( + const unsigned char *inBuffer, + size_t inSize, + size_t *outSize); + + +/* +LzmaRamDecompress: + In: + inBuffer - input data + inSize - input data size + outBuffer - output data + outSize - output size + allocFunc - alloc function (can be malloc) + freeFunc - free function (can be free) + Out: + outSizeProcessed - processed size + Return code: + 0 - OK + 1 - Error in headers / data stream + 2 - Memory allocating error + +Memory requirements depend from properties of LZMA stream. +With default lzma settings it's about 16 KB. +*/ + +int LzmaRamDecompress( + const unsigned char *inBuffer, + size_t inSize, + unsigned char *outBuffer, + size_t outSize, + size_t *outSizeProcessed, + void * (*allocFunc)(size_t size), + void (*freeFunc)(void *)); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp new file mode 100644 index 00000000..d0feea85 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h new file mode 100644 index 00000000..e7fb6986 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile new file mode 100644 index 00000000..63a63ae4 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile @@ -0,0 +1,100 @@ +PROG = lzma.exe +CFLAGS = $(CFLAGS) -I ../../../ +LIBS = $(LIBS) oleaut32.lib user32.lib + +!IFNDEF O +!IFDEF CPU +O=$(CPU) +!ELSE +O=O +!ENDIF +!ENDIF + +CFLAGS = $(CFLAGS) -nologo -EHsc -c -Fo$O/ -GS- +CFLAGS_O1 = $(CFLAGS) -O1 +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 + +PROGPATH = $O\$(PROG) + +COMPL_O1 = $(CPP) $(CFLAGS_O1) $** +COMPL_O2 = $(CPP) $(CFLAGS_O2) $** +COMPL = $(CPP) $(CFLAGS_O1) $** + + +LZMA_OBJS = \ + $O\LzmaAlone.obj \ + $O\LzmaBench.obj \ + $O\LzmaRam.obj \ + +LZMA_OPT_OBJS = \ + $O\LZMADecoder.obj \ + $O\LZMAEncoder.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + $O\CRC.obj \ + $O\CommandLineParser.obj \ + $O\String.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\Vector.obj + +7ZIP_COMMON_OBJS = \ + $O\InBuffer.obj \ + $O\OutBuffer.obj \ + $O\StreamUtils.obj \ + +LZ_OBJS = \ + $O\LZInWindow.obj \ + $O\LZOutWindow.obj \ + + +OBJS = \ + $(LZMA_OBJS) \ + $(LZMA_OPT_OBJS) \ + $(COMMON_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(LZ_OBJS) \ + $O\LzmaRamDecode.obj \ + $O\LzmaDecode.obj \ + $O\FileStreams.obj \ + $O\FileIO.obj \ + $O\RangeCoderBit.obj \ + $O\BranchX86.obj \ + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch + +$O: + if not exist "$O" mkdir "$O" + +$(PROGPATH): $O $(OBJS) + link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) + + +$(LZMA_OBJS): $(*B).cpp + $(COMPL) +$(LZMA_OPT_OBJS): ../LZMA/$(*B).cpp + $(COMPL_O2) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(LZ_OBJS): ../LZ/$(*B).cpp + $(COMPL) +$O\RangeCoderBit.obj: ../RangeCoder/$(*B).cpp + $(COMPL) +$O\LzmaRamDecode.obj: LzmaRamDecode.c + $(COMPL_O1) +$O\LzmaDecode.obj: ../LZMA_C/LzmaDecode.c + $(COMPL_O2) +$O\BranchX86.obj: ../Branch/BranchX86.c + $(COMPL_O2) +$O\FileStreams.obj: ../../Common/FileStreams.cpp + $(COMPL) +$O\FileIO.obj: ../../../Windows/FileIO.cpp + $(COMPL) diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc new file mode 100644 index 00000000..1e180742 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_Alone/makefile.gcc @@ -0,0 +1,113 @@ +PROG = lzma +CXX = g++ -O2 -Wall +CXX_C = gcc -O2 -Wall +LIB = -lm +RM = rm -f +CFLAGS = -c -I ../../../ + +OBJS = \ + LzmaAlone.o \ + LzmaBench.o \ + LzmaRam.o \ + LzmaRamDecode.o \ + LzmaDecode.o \ + BranchX86.o \ + LZMADecoder.o \ + LZMAEncoder.o \ + LZInWindow.o \ + LZOutWindow.o \ + RangeCoderBit.o \ + InBuffer.o \ + OutBuffer.o \ + FileStreams.o \ + StreamUtils.o \ + Alloc.o \ + C_FileIO.o \ + CommandLineParser.o \ + CRC.o \ + String.o \ + StringConvert.o \ + StringToInt.o \ + Vector.o \ + + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +LzmaAlone.o: LzmaAlone.cpp + $(CXX) $(CFLAGS) LzmaAlone.cpp + +LzmaBench.o: LzmaBench.cpp + $(CXX) $(CFLAGS) LzmaBench.cpp + +LzmaRam.o: LzmaRam.cpp + $(CXX) $(CFLAGS) LzmaRam.cpp + +LzmaRamDecode.o: LzmaRamDecode.c + $(CXX_C) $(CFLAGS) LzmaRamDecode.c + +LzmaDecode.o: ../LZMA_C/LzmaDecode.c + $(CXX_C) $(CFLAGS) ../LZMA_C/LzmaDecode.c + +BranchX86.o: ../Branch/BranchX86.c + $(CXX_C) $(CFLAGS) ../Branch/BranchX86.c + +LZMADecoder.o: ../LZMA/LZMADecoder.cpp + $(CXX) $(CFLAGS) ../LZMA/LZMADecoder.cpp + +LZMAEncoder.o: ../LZMA/LZMAEncoder.cpp + $(CXX) $(CFLAGS) ../LZMA/LZMAEncoder.cpp + +LZInWindow.o: ../LZ/LZInWindow.cpp + $(CXX) $(CFLAGS) ../LZ/LZInWindow.cpp + +LZOutWindow.o: ../LZ/LZOutWindow.cpp + $(CXX) $(CFLAGS) ../LZ/LZOutWindow.cpp + +RangeCoderBit.o: ../RangeCoder/RangeCoderBit.cpp + $(CXX) $(CFLAGS) ../RangeCoder/RangeCoderBit.cpp + +InBuffer.o: ../../Common/InBuffer.cpp + $(CXX) $(CFLAGS) ../../Common/InBuffer.cpp + +OutBuffer.o: ../../Common/OutBuffer.cpp + $(CXX) $(CFLAGS) ../../Common/OutBuffer.cpp + +FileStreams.o: ../../Common/FileStreams.cpp + $(CXX) $(CFLAGS) ../../Common/FileStreams.cpp + +StreamUtils.o: ../../Common/StreamUtils.cpp + $(CXX) $(CFLAGS) ../../Common/StreamUtils.cpp + +Alloc.o: ../../../Common/Alloc.cpp + $(CXX) $(CFLAGS) ../../../Common/Alloc.cpp + +C_FileIO.o: ../../../Common/C_FileIO.cpp + $(CXX) $(CFLAGS) ../../../Common/C_FileIO.cpp + +CommandLineParser.o: ../../../Common/CommandLineParser.cpp + $(CXX) $(CFLAGS) ../../../Common/CommandLineParser.cpp + +CRC.o: ../../../Common/CRC.cpp + $(CXX) $(CFLAGS) ../../../Common/CRC.cpp + +MyWindows.o: ../../../Common/MyWindows.cpp + $(CXX) $(CFLAGS) ../../../Common/MyWindows.cpp + +String.o: ../../../Common/String.cpp + $(CXX) $(CFLAGS) ../../../Common/String.cpp + +StringConvert.o: ../../../Common/StringConvert.cpp + $(CXX) $(CFLAGS) ../../../Common/StringConvert.cpp + +StringToInt.o: ../../../Common/StringToInt.cpp + $(CXX) $(CFLAGS) ../../../Common/StringToInt.cpp + +Vector.o: ../../../Common/Vector.cpp + $(CXX) $(CFLAGS) ../../../Common/Vector.cpp + +clean: + -$(RM) $(PROG) $(OBJS) + diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c new file mode 100644 index 00000000..cb834537 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.c @@ -0,0 +1,584 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \ + BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + return LZMA_RESULT_DATA_ERROR; + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + return LZMA_RESULT_DATA_ERROR; + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h new file mode 100644 index 00000000..2870eeb9 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecode.h @@ -0,0 +1,113 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c new file mode 100644 index 00000000..a3a5eb9d --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaDecodeSize.c @@ -0,0 +1,712 @@ +/* + LzmaDecodeSize.c + LZMA Decoder (optimized for Size version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +typedef struct _CRangeDecoder +{ + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback; + int Result; + #endif + int ExtraBytes; +} CRangeDecoder; + +Byte RangeDecoderReadByte(CRangeDecoder *rd) +{ + if (rd->Buffer == rd->BufferLim) + { + #ifdef _LZMA_IN_CB + SizeT size; + rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); + rd->BufferLim = rd->Buffer + size; + if (size == 0) + #endif + { + rd->ExtraBytes = 1; + return 0xFF; + } + } + return (*rd->Buffer++); +} + +/* #define ReadByte (*rd->Buffer++) */ +#define ReadByte (RangeDecoderReadByte(rd)) + +void RangeDecoderInit(CRangeDecoder *rd + #ifndef _LZMA_IN_CB + , const Byte *stream, SizeT bufferSize + #endif + ) +{ + int i; + #ifdef _LZMA_IN_CB + rd->Buffer = rd->BufferLim = 0; + #else + rd->Buffer = stream; + rd->BufferLim = stream + bufferSize; + #endif + rd->ExtraBytes = 0; + rd->Code = 0; + rd->Range = (0xFFFFFFFF); + for(i = 0; i < 5; i++) + rd->Code = (rd->Code << 8) | ReadByte; +} + +#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; +#define RC_FLUSH_VAR rd->Range = range; rd->Code = code; +#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } + +UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) +{ + RC_INIT_VAR + UInt32 result = 0; + int i; + for (i = numTotalBits; i != 0; i--) + { + /* UInt32 t; */ + range >>= 1; + + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + /* + t = (code - range) >> 31; + t &= 1; + code -= range & (t - 1); + result = (result + result) | (1 - t); + */ + RC_NORMALIZE + } + RC_FLUSH_VAR + return result; +} + +int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) +{ + UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; + if (rd->Code < bound) + { + rd->Range = bound; + *prob += (kBitModelTotal - *prob) >> kNumMoveBits; + if (rd->Range < kTopValue) + { + rd->Code = (rd->Code << 8) | ReadByte; + rd->Range <<= 8; + } + return 0; + } + else + { + rd->Range -= bound; + rd->Code -= bound; + *prob -= (*prob) >> kNumMoveBits; + if (rd->Range < kTopValue) + { + rd->Code = (rd->Code << 8) | ReadByte; + rd->Range <<= 8; + } + return 1; + } +} + +#define RC_GET_BIT2(prob, mi, A0, A1) \ + UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ + if (code < bound) \ + { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ + else \ + { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ + RC_NORMALIZE + +#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) + +int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +{ + int mi = 1; + int i; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + for(i = numLevels; i != 0; i--) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + mi; + RC_GET_BIT(prob, mi) + #else + mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); + #endif + } + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return mi - (1 << numLevels); +} + +int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) +{ + int mi = 1; + int i; + int symbol = 0; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + for(i = 0; i < numLevels; i++) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + mi; + RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) + #else + int bit = RangeDecoderBitDecode(probs + mi, rd); + mi = mi + mi + bit; + symbol |= (bit << i); + #endif + } + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) +{ + int symbol = 1; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + do + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + symbol; + RC_GET_BIT(prob, symbol) + #else + symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); + #endif + } + while (symbol < 0x100); + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) +{ + int symbol = 1; + #ifdef _LZMA_LOC_OPT + RC_INIT_VAR + #endif + do + { + int bit; + int matchBit = (matchByte >> 7) & 1; + matchByte <<= 1; + #ifdef _LZMA_LOC_OPT + { + CProb *prob = probs + 0x100 + (matchBit << 8) + symbol; + RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) + } + #else + bit = RangeDecoderBitDecode(probs + 0x100 + (matchBit << 8) + symbol, rd); + symbol = (symbol << 1) | bit; + #endif + if (matchBit != bit) + { + while (symbol < 0x100) + { + #ifdef _LZMA_LOC_OPT + CProb *prob = probs + symbol; + RC_GET_BIT(prob, symbol) + #else + symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); + #endif + } + break; + } + } + while (symbol < 0x100); + #ifdef _LZMA_LOC_OPT + RC_FLUSH_VAR + #endif + return symbol; +} + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) +{ + if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) + return RangeDecoderBitTreeDecode(p + LenLow + + (posState << kLenNumLowBits), kLenNumLowBits, rd); + if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) + return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + + (posState << kLenNumMidBits), kLenNumMidBits, rd); + return kLenNumLowSymbols + kLenNumMidSymbols + + RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); +} + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + CRangeDecoder rd; + + #ifdef _LZMA_OUT_READ + + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + rd.Range = vs->Range; + rd.Code = vs->Code; + #ifdef _LZMA_IN_CB + rd.InCallback = InCallback; + rd.Buffer = vs->Buffer; + rd.BufferLim = vs->BufferLim; + #else + rd.Buffer = inStream; + rd.BufferLim = inStream + inSize; + #endif + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + RangeDecoderInit(&rd + #ifndef _LZMA_IN_CB + , inStream, inSize + #endif + ); + #ifdef _LZMA_IN_CB + if (rd.Result != LZMA_RESULT_OK) + return rd.Result; + #endif + if (rd.ExtraBytes != 0) + return LZMA_RESULT_DATA_ERROR; + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #ifdef _LZMA_IN_CB + rd.Result = LZMA_RESULT_OK; + #endif + rd.ExtraBytes = 0; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + rd.InCallback = InCallback; + #endif + RangeDecoderInit(&rd + #ifndef _LZMA_IN_CB + , inStream, inSize + #endif + ); + + #ifdef _LZMA_IN_CB + if (rd.Result != LZMA_RESULT_OK) + return rd.Result; + #endif + if (rd.ExtraBytes != 0) + return LZMA_RESULT_DATA_ERROR; + + #endif /* _LZMA_OUT_READ */ + + + while(nowPos < outSize) + { + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + #ifdef _LZMA_IN_CB + if (rd.Result != LZMA_RESULT_OK) + return rd.Result; + #endif + if (rd.ExtraBytes != 0) + return LZMA_RESULT_DATA_ERROR; + if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) + { + CProb *probs = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + Byte matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); + } + else + previousByte = LzmaLiteralDecode(probs, &rd); + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) + { + if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) + { + if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + return LZMA_RESULT_DATA_ERROR; + + state = state < 7 ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + continue; + } + } + else + { + UInt32 distance; + if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) + distance = rep1; + else + { + if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = LzmaLenDecode(p + RepLenCoder, &rd, posState); + state = state < 7 ? 8 : 11; + } + else + { + int posSlot; + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < 7 ? 7 : 10; + len = LzmaLenDecode(p + LenCoder, &rd, posState); + posSlot = RangeDecoderBitTreeDecode(p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits), kNumPosSlotBits, &rd); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); + if (posSlot < kEndPosModelIndex) + { + rep0 += RangeDecoderReverseBitTreeDecode( + p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); + } + else + { + rep0 += RangeDecoderDecodeDirectBits(&rd, + numDirectBits - kNumAlignBits) << kNumAlignBits; + rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + return LZMA_RESULT_DATA_ERROR; + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + + + #ifdef _LZMA_OUT_READ + vs->Range = rd.Range; + vs->Code = rd.Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = rd.Buffer; + vs->BufferLim = rd.BufferLim; + #else + *inSizeProcessed = (SizeT)(rd.Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c new file mode 100644 index 00000000..e50f88b5 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.c @@ -0,0 +1,521 @@ +/* + LzmaStateDecode.c + LZMA Decoder (State version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#include "LzmaStateDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { Code = (Code << 8) | RC_READ_BYTE; }} + +#define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +/* kRequiredInBufferSize = number of required input bytes for worst case: + longest match with longest distance. + kLzmaInBufferSize must be larger than kRequiredInBufferSize + 23 bits = 2 (match select) + 10 (len) + 6 (distance) + 4(align) + 1 (RC_NORMALIZE) +*/ + +#define kRequiredInBufferSize ((23 * (kNumBitModelTotalBits - kNumMoveBits + 1) + 26 + 9) / 8) + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + return LZMA_RESULT_DATA_ERROR; + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + return LZMA_RESULT_DATA_ERROR; + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + return LZMA_RESULT_OK; + } +} + +int LzmaDecode( + CLzmaDecoderState *vs, + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, + int finishDecoding) +{ + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + + unsigned char *Buffer = vs->Buffer; + int BufferSize = vs->BufferSize; /* don't change it to unsigned int */ + CProb *p = vs->Probs; + + int state = vs->State; + unsigned char previousByte; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + SizeT nowPos = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + unsigned char *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + unsigned char tempDictionary[4]; + + (*inSizeProcessed) = 0; + (*outSizeProcessed) = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + while (inSize > 0 && BufferSize < kLzmaInBufferSize) + { + Buffer[BufferSize++] = *inStream++; + (*inSizeProcessed)++; + inSize--; + } + if (BufferSize < 5) + { + vs->BufferSize = BufferSize; + return finishDecoding ? LZMA_RESULT_DATA_ERROR : LZMA_RESULT_OK; + } + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + RC_INIT; + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + while(1) + { + int bufferPos = (int)(Buffer - vs->Buffer); + if (BufferSize - bufferPos < kRequiredInBufferSize) + { + int i; + BufferSize -= bufferPos; + if (BufferSize < 0) + return LZMA_RESULT_DATA_ERROR; + for (i = 0; i < BufferSize; i++) + vs->Buffer[i] = Buffer[i]; + Buffer = vs->Buffer; + while (inSize > 0 && BufferSize < kLzmaInBufferSize) + { + Buffer[BufferSize++] = *inStream++; + (*inSizeProcessed)++; + inSize--; + } + if (BufferSize < kRequiredInBufferSize && !finishDecoding) + break; + } + if (nowPos >= outSize) + break; + { + CProb *prob; + UInt32 bound; + int posState = (int)((nowPos + globalPos) & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((((nowPos + globalPos)& literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (unsigned char)symbol; + + outStream[nowPos++] = previousByte; + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + UInt32 pos; + UpdateBit0(prob); + if (distanceLimit == 0) + return LZMA_RESULT_DATA_ERROR; + if (distanceLimit < dictionarySize) + distanceLimit++; + state = state < kNumLitStates ? 9 : 11; + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + outStream[nowPos++] = previousByte; + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + if (rep0 > distanceLimit) + return LZMA_RESULT_DATA_ERROR; + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + + do + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + } + RC_NORMALIZE; + + BufferSize -= (int)(Buffer - vs->Buffer); + if (BufferSize < 0) + return LZMA_RESULT_DATA_ERROR; + { + int i; + for (i = 0; i < BufferSize; i++) + vs->Buffer[i] = Buffer[i]; + } + vs->BufferSize = BufferSize; + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = (UInt32)(globalPos + nowPos); + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + + (*outSizeProcessed) = nowPos; + return LZMA_RESULT_OK; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h new file mode 100644 index 00000000..26490d61 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateDecode.h @@ -0,0 +1,96 @@ +/* + LzmaStateDecode.h + LZMA Decoder interface (State version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMASTATEDECODE_H +#define __LZMASTATEDECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + UInt32 DictionarySize; +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(lzmaProps) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((lzmaProps)->lc + (lzmaProps)->lp))) + +#define kLzmaInBufferSize 64 /* don't change it. it must be larger than kRequiredInBufferSize */ + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + unsigned char *Dictionary; + + unsigned char Buffer[kLzmaInBufferSize]; + int BufferSize; + + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; /* -2: decoder needs internal initialization + -1: stream was finished, + 0: ok + > 0: need to write RemainLen bytes as match Reps[0], + */ + unsigned char TempDictionary[4]; /* it's required when DictionarySize = 0 */ +} CLzmaDecoderState; + +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; (vs)->BufferSize = 0; } + +/* LzmaDecode: decoding from input stream to output stream. + If finishDecoding != 0, then there are no more bytes in input stream + after inStream[inSize - 1]. */ + +int LzmaDecode(CLzmaDecoderState *vs, + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed, + int finishDecoding); + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c new file mode 100644 index 00000000..5df4e438 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaStateTest.c @@ -0,0 +1,195 @@ +/* +LzmaStateTest.c +Test application for LZMA Decoder (State version) + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.26 (2005-08-02) +*/ + +#include +#include +#include + +#include "LzmaStateDecode.h" + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; + +#define kInBufferSize (1 << 15) +#define kOutBufferSize (1 << 15) + +unsigned char g_InBuffer[kInBufferSize]; +unsigned char g_OutBuffer[kOutBufferSize]; + +size_t MyReadFile(FILE *file, void *data, size_t size) + { return fread(data, 1, size, file); } + +int MyReadFileAndCheck(FILE *file, void *data, size_t size) + { return (MyReadFile(file, data, size) == size); } + +int PrintError(char *buffer, const char *message) +{ + sprintf(buffer + strlen(buffer), "\nError: "); + sprintf(buffer + strlen(buffer), message); + return 1; +} + +int main3(FILE *inFile, FILE *outFile, char *rs) +{ + /* We use two 32-bit integers to construct 64-bit integer for file size. + You can remove outSizeHigh, if you don't need >= 4GB supporting, + or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ + UInt32 outSize = 0; + UInt32 outSizeHigh = 0; + + int waitEOS = 1; + /* waitEOS = 1, if there is no uncompressed size in headers, + so decoder will wait EOS (End of Stream Marker) in compressed stream */ + + int i; + int res = 0; + CLzmaDecoderState state; /* it's about 140 bytes structure, if int is 32-bit */ + unsigned char properties[LZMA_PROPERTIES_SIZE]; + SizeT inAvail = 0; + unsigned char *inBuffer = 0; + + if (sizeof(UInt32) < 4) + return PrintError(rs, "LZMA decoder needs correct UInt32"); + + /* Read LZMA properties for compressed stream */ + + if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) + return PrintError(rs, kCantReadMessage); + + /* Read uncompressed size */ + + for (i = 0; i < 8; i++) + { + unsigned char b; + if (!MyReadFileAndCheck(inFile, &b, 1)) + return PrintError(rs, kCantReadMessage); + if (b != 0xFF) + waitEOS = 0; + if (i < 4) + outSize += (UInt32)(b) << (i * 8); + else + outSizeHigh += (UInt32)(b) << ((i - 4) * 8); + } + + /* Decode LZMA properties and allocate memory */ + + if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + return PrintError(rs, "Incorrect stream properties"); + state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + if (state.Probs == 0) + return PrintError(rs, kCantAllocateMessage); + + if (state.Properties.DictionarySize == 0) + state.Dictionary = 0; + else + { + state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); + if (state.Dictionary == 0) + { + free(state.Probs); + return PrintError(rs, kCantAllocateMessage); + } + } + + /* Decompress */ + + LzmaDecoderInit(&state); + + do + { + SizeT inProcessed, outProcessed; + int finishDecoding; + UInt32 outAvail = kOutBufferSize; + if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) + outAvail = outSize; + if (inAvail == 0) + { + inAvail = (SizeT)MyReadFile(inFile, g_InBuffer, kInBufferSize); + inBuffer = g_InBuffer; + } + finishDecoding = (inAvail == 0); + res = LzmaDecode(&state, + inBuffer, inAvail, &inProcessed, + g_OutBuffer, outAvail, &outProcessed, + finishDecoding); + if (res != 0) + { + sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); + res = 1; + break; + } + inAvail -= inProcessed; + inBuffer += inProcessed; + + if (outFile != 0) + if (fwrite(g_OutBuffer, 1, outProcessed, outFile) != outProcessed) + { + PrintError(rs, kCantWriteMessage); + res = 1; + break; + } + + if (outSize < outProcessed) + outSizeHigh--; + outSize -= (UInt32)outProcessed; + outSize &= 0xFFFFFFFF; + + if (outProcessed == 0 && finishDecoding) + { + if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) + res = 1; + break; + } + } + while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); + + free(state.Dictionary); + free(state.Probs); + return res; +} + +int main2(int numArgs, const char *args[], char *rs) +{ + FILE *inFile = 0; + FILE *outFile = 0; + int res; + + sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-02\n"); + if (numArgs < 2 || numArgs > 3) + { + sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); + return 1; + } + + inFile = fopen(args[1], "rb"); + if (inFile == 0) + return PrintError(rs, "Can not open input file"); + + if (numArgs > 2) + { + outFile = fopen(args[2], "wb+"); + if (outFile == 0) + return PrintError(rs, "Can not open output file"); + } + + res = main3(inFile, outFile, rs); + + if (outFile != 0) + fclose(outFile); + fclose(inFile); + return res; +} + +int main(int numArgs, const char *args[]) +{ + char rs[800] = { 0 }; + int res = main2(numArgs, args, rs); + printf(rs); + return res; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c new file mode 100644 index 00000000..f95a753b --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTest.c @@ -0,0 +1,342 @@ +/* +LzmaTest.c +Test application for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.26 (2005-08-05) +*/ + +#include +#include +#include + +#include "LzmaDecode.h" + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; + +size_t MyReadFile(FILE *file, void *data, size_t size) +{ + if (size == 0) + return 0; + return fread(data, 1, size, file); +} + +int MyReadFileAndCheck(FILE *file, void *data, size_t size) + { return (MyReadFile(file, data, size) == size);} + +size_t MyWriteFile(FILE *file, const void *data, size_t size) +{ + if (size == 0) + return 0; + return fwrite(data, 1, size, file); +} + +int MyWriteFileAndCheck(FILE *file, const void *data, size_t size) + { return (MyWriteFile(file, data, size) == size); } + +#ifdef _LZMA_IN_CB +#define kInBufferSize (1 << 15) +typedef struct _CBuffer +{ + ILzmaInCallback InCallback; + FILE *File; + unsigned char Buffer[kInBufferSize]; +} CBuffer; + +int LzmaReadCompressed(void *object, const unsigned char **buffer, SizeT *size) +{ + CBuffer *b = (CBuffer *)object; + *buffer = b->Buffer; + *size = (SizeT)MyReadFile(b->File, b->Buffer, kInBufferSize); + return LZMA_RESULT_OK; +} +CBuffer g_InBuffer; + +#endif + +#ifdef _LZMA_OUT_READ +#define kOutBufferSize (1 << 15) +unsigned char g_OutBuffer[kOutBufferSize]; +#endif + +int PrintError(char *buffer, const char *message) +{ + sprintf(buffer + strlen(buffer), "\nError: "); + sprintf(buffer + strlen(buffer), message); + return 1; +} + +int main3(FILE *inFile, FILE *outFile, char *rs) +{ + /* We use two 32-bit integers to construct 64-bit integer for file size. + You can remove outSizeHigh, if you don't need >= 4GB supporting, + or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ + UInt32 outSize = 0; + UInt32 outSizeHigh = 0; + #ifndef _LZMA_OUT_READ + SizeT outSizeFull; + unsigned char *outStream; + #endif + + int waitEOS = 1; + /* waitEOS = 1, if there is no uncompressed size in headers, + so decoder will wait EOS (End of Stream Marker) in compressed stream */ + + #ifndef _LZMA_IN_CB + SizeT compressedSize; + unsigned char *inStream; + #endif + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + unsigned char properties[LZMA_PROPERTIES_SIZE]; + + int res; + + #ifdef _LZMA_IN_CB + g_InBuffer.File = inFile; + #endif + + if (sizeof(UInt32) < 4) + return PrintError(rs, "LZMA decoder needs correct UInt32"); + + #ifndef _LZMA_IN_CB + { + long length; + fseek(inFile, 0, SEEK_END); + length = ftell(inFile); + fseek(inFile, 0, SEEK_SET); + if ((long)(SizeT)length != length) + return PrintError(rs, "Too big compressed stream"); + compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); + } + #endif + + /* Read LZMA properties for compressed stream */ + + if (!MyReadFileAndCheck(inFile, properties, sizeof(properties))) + return PrintError(rs, kCantReadMessage); + + /* Read uncompressed size */ + + { + int i; + for (i = 0; i < 8; i++) + { + unsigned char b; + if (!MyReadFileAndCheck(inFile, &b, 1)) + return PrintError(rs, kCantReadMessage); + if (b != 0xFF) + waitEOS = 0; + if (i < 4) + outSize += (UInt32)(b) << (i * 8); + else + outSizeHigh += (UInt32)(b) << ((i - 4) * 8); + } + + #ifndef _LZMA_OUT_READ + if (waitEOS) + return PrintError(rs, "Stream with EOS marker is not supported"); + outSizeFull = (SizeT)outSize; + if (sizeof(SizeT) >= 8) + outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); + else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) + return PrintError(rs, "Too big uncompressed stream"); + #endif + } + + /* Decode LZMA properties and allocate memory */ + + if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + return PrintError(rs, "Incorrect stream properties"); + state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + + #ifdef _LZMA_OUT_READ + if (state.Properties.DictionarySize == 0) + state.Dictionary = 0; + else + state.Dictionary = (unsigned char *)malloc(state.Properties.DictionarySize); + #else + if (outSizeFull == 0) + outStream = 0; + else + outStream = (unsigned char *)malloc(outSizeFull); + #endif + + #ifndef _LZMA_IN_CB + if (compressedSize == 0) + inStream = 0; + else + inStream = (unsigned char *)malloc(compressedSize); + #endif + + if (state.Probs == 0 + #ifdef _LZMA_OUT_READ + || (state.Dictionary == 0 && state.Properties.DictionarySize != 0) + #else + || (outStream == 0 && outSizeFull != 0) + #endif + #ifndef _LZMA_IN_CB + || (inStream == 0 && compressedSize != 0) + #endif + ) + { + free(state.Probs); + #ifdef _LZMA_OUT_READ + free(state.Dictionary); + #else + free(outStream); + #endif + #ifndef _LZMA_IN_CB + free(inStream); + #endif + return PrintError(rs, kCantAllocateMessage); + } + + /* Decompress */ + + #ifdef _LZMA_IN_CB + g_InBuffer.InCallback.Read = LzmaReadCompressed; + #else + if (!MyReadFileAndCheck(inFile, inStream, compressedSize)) + return PrintError(rs, kCantReadMessage); + #endif + + #ifdef _LZMA_OUT_READ + { + #ifndef _LZMA_IN_CB + SizeT inAvail = compressedSize; + const unsigned char *inBuffer = inStream; + #endif + LzmaDecoderInit(&state); + do + { + #ifndef _LZMA_IN_CB + SizeT inProcessed; + #endif + SizeT outProcessed; + SizeT outAvail = kOutBufferSize; + if (!waitEOS && outSizeHigh == 0 && outAvail > outSize) + outAvail = (SizeT)outSize; + res = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &g_InBuffer.InCallback, + #else + inBuffer, inAvail, &inProcessed, + #endif + g_OutBuffer, outAvail, &outProcessed); + if (res != 0) + { + sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); + res = 1; + break; + } + #ifndef _LZMA_IN_CB + inAvail -= inProcessed; + inBuffer += inProcessed; + #endif + + if (outFile != 0) + if (!MyWriteFileAndCheck(outFile, g_OutBuffer, (size_t)outProcessed)) + { + PrintError(rs, kCantWriteMessage); + res = 1; + break; + } + + if (outSize < outProcessed) + outSizeHigh--; + outSize -= (UInt32)outProcessed; + outSize &= 0xFFFFFFFF; + + if (outProcessed == 0) + { + if (!waitEOS && (outSize != 0 || outSizeHigh != 0)) + res = 1; + break; + } + } + while ((outSize != 0 && outSizeHigh == 0) || outSizeHigh != 0 || waitEOS); + } + + #else + { + #ifndef _LZMA_IN_CB + SizeT inProcessed; + #endif + SizeT outProcessed; + res = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &g_InBuffer.InCallback, + #else + inStream, compressedSize, &inProcessed, + #endif + outStream, outSizeFull, &outProcessed); + if (res != 0) + { + sprintf(rs + strlen(rs), "\nDecoding error = %d\n", res); + res = 1; + } + else if (outFile != 0) + { + if (!MyWriteFileAndCheck(outFile, outStream, (size_t)outProcessed)) + { + PrintError(rs, kCantWriteMessage); + res = 1; + } + } + } + #endif + + free(state.Probs); + #ifdef _LZMA_OUT_READ + free(state.Dictionary); + #else + free(outStream); + #endif + #ifndef _LZMA_IN_CB + free(inStream); + #endif + return res; +} + +int main2(int numArgs, const char *args[], char *rs) +{ + FILE *inFile = 0; + FILE *outFile = 0; + int res; + + sprintf(rs + strlen(rs), "\nLZMA Decoder 4.26 Copyright (c) 1999-2005 Igor Pavlov 2005-08-05\n"); + if (numArgs < 2 || numArgs > 3) + { + sprintf(rs + strlen(rs), "\nUsage: lzmadec file.lzma [outFile]\n"); + return 1; + } + + inFile = fopen(args[1], "rb"); + if (inFile == 0) + return PrintError(rs, "Can not open input file"); + + if (numArgs > 2) + { + outFile = fopen(args[2], "wb+"); + if (outFile == 0) + return PrintError(rs, "Can not open output file"); + } + + res = main3(inFile, outFile, rs); + + if (outFile != 0) + fclose(outFile); + fclose(inFile); + return res; +} + +int main(int numArgs, const char *args[]) +{ + char rs[800] = { 0 }; + int res = main2(numArgs, args, rs); + printf(rs); + return res; +} diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTypes.h b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTypes.h new file mode 100644 index 00000000..288c5e45 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/LzmaTypes.h @@ -0,0 +1,45 @@ +/* +LzmaTypes.h + +Types for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.40 (2006-05-01) +*/ + +#ifndef __LZMATYPES_H +#define __LZMATYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile new file mode 100644 index 00000000..7d6a93be --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile @@ -0,0 +1,43 @@ +PROG = lzmaDec.exe + +!IFNDEF O +!IFDEF CPU +O=$(CPU) +!ELSE +O=O +!ENDIF +!ENDIF + +CFLAGS = $(CFLAGS) -nologo -c -Fo$O/ -GS- +CFLAGS_O1 = $(CFLAGS) -O1 +CFLAGS_O2 = $(CFLAGS) -O2 + +LFLAGS = $(LFLAGS) -nologo -OPT:NOWIN98 + +PROGPATH = $O\$(PROG) + +COMPL_O1 = $(CPP) $(CFLAGS_O1) $** +COMPL_O2 = $(CPP) $(CFLAGS_O2) $** +COMPL = $(CPP) $(CFLAGS_O1) $** + + +OBJS = \ + $O\LzmaTest.obj \ + $O\LzmaDecode.obj \ + +all: $(PROGPATH) + +clean: + -del /Q $(PROGPATH) $O\*.exe $O\*.dll $O\*.obj $O\*.lib $O\*.exp $O\*.res $O\*.pch + +$O: + if not exist "$O" mkdir "$O" + +$(PROGPATH): $O $(OBJS) + link $(LFLAGS) -out:$(PROGPATH) $(OBJS) $(LIBS) + + +$O\LzmaTest.obj: $(*B).c + $(COMPL) +$O\LzmaDecode.obj: ../../Compress/LZMA_C/$(*B).c + $(COMPL_O2) diff --git a/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile.gcc b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile.gcc new file mode 100644 index 00000000..9b9c1a33 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/LZMA_C/makefile.gcc @@ -0,0 +1,23 @@ +PROG = lzmadec +CXX = gcc +LIB = +RM = rm -f +CFLAGS = -c -O2 -Wall -pedantic -D _LZMA_PROB32 + +OBJS = LzmaTest.o LzmaDecode.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CXX) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIB) + +LzmaTest.o: LzmaTest.c + $(CXX) $(CFLAGS) LzmaTest.c + +LzmaDecode.o: LzmaDecode.c + $(CXX) $(CFLAGS) LzmaDecode.c + + +clean: + -$(RM) $(PROG) $(OBJS) + diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h new file mode 100644 index 00000000..bbb2ba82 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoder.h @@ -0,0 +1,205 @@ +// Compress/RangeCoder/RangeCoder.h + +#ifndef __COMPRESS_RANGECODER_H +#define __COMPRESS_RANGECODER_H + +#include "../../Common/InBuffer.h" +#include "../../Common/OutBuffer.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumTopBits = 24; +const UInt32 kTopValue = (1 << kNumTopBits); + +class CEncoder +{ + UInt32 _cacheSize; + Byte _cache; +public: + UInt64 Low; + UInt32 Range; + COutBuffer Stream; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + void FlushData() + { + // Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() { return Stream.Flush(); } + + void ReleaseStream() { Stream.ReleaseStream(); } + + void Encode(UInt32 start, UInt32 size, UInt32 total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + void ShiftLow() + { + if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0) + { + Byte temp = _cache; + do + { + Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32))); + temp = 0xFF; + } + while(--_cacheSize != 0); + _cache = (Byte)((UInt32)Low >> 24); + } + _cacheSize++; + Low = (UInt32)Low << 8; + } + + void EncodeDirectBits(UInt32 value, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((value >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; } +}; + +class CDecoder +{ +public: + CInBuffer Stream; + UInt32 Range; + UInt32 Code; + bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); } + + void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | Stream.ReadByte(); + Range <<= 8; + } + } + + void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); } + void Init() + { + Stream.Init(); + Code = 0; + Range = 0xFFFFFFFF; + for(int i = 0; i < 5; i++) + Code = (Code << 8) | Stream.ReadByte(); + } + + void ReleaseStream() { Stream.ReleaseStream(); } + + UInt32 GetThreshold(UInt32 total) + { + return (Code) / ( Range /= total); + } + + void Decode(UInt32 start, UInt32 size) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + UInt32 DecodeDirectBits(int numTotalBits) + { + UInt32 range = Range; + UInt32 code = Code; + UInt32 result = 0; + for (int i = numTotalBits; i != 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + UInt32 t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits) + { + UInt32 newBound = (Range >> numTotalBits) * size0; + UInt32 symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); } +}; + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp new file mode 100644 index 00000000..8e4c4d3a --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.cpp @@ -0,0 +1,80 @@ +// Compress/RangeCoder/RangeCoderBit.cpp + +#include "StdAfx.h" + +#include "RangeCoderBit.h" + +namespace NCompress { +namespace NRangeCoder { + +UInt32 CPriceTables::ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; +static CPriceTables g_PriceTables; + +CPriceTables::CPriceTables() { Init(); } + +void CPriceTables::Init() +{ + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for(int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = 1 << (kNumBits - i - 1); + UInt32 end = 1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = (i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + + /* + // simplest: bad solution + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + ProbPrices[i] = kBitPrice; + */ + + /* + const double kDummyMultMid = (1.0 / kBitPrice) / 2; + const double kDummyMultMid = 0; + // float solution + double ln2 = log(double(2)); + double lnAll = log(double(kBitModelTotal >> kNumMoveReducingBits)); + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + ProbPrices[i] = UInt32((fabs(lnAll - log(double(i))) / ln2 + kDummyMultMid) * kBitPrice); + */ + + /* + // experimental, slow, solution: + for(UInt32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + { + const int kCyclesBits = 5; + const UInt32 kCycles = (1 << kCyclesBits); + + UInt32 range = UInt32(-1); + UInt32 bitCount = 0; + for (UInt32 j = 0; j < kCycles; j++) + { + range >>= (kNumBitModelTotalBits - kNumMoveReducingBits); + range *= i; + while(range < (1 << 31)) + { + range <<= 1; + bitCount++; + } + } + bitCount <<= kNumBitPriceShiftBits; + range -= (1 << 31); + for (int k = kNumBitPriceShiftBits - 1; k >= 0; k--) + { + range <<= 1; + if (range > (1 << 31)) + { + bitCount += (1 << k); + range -= (1 << 31); + } + } + ProbPrices[i] = (bitCount + // + (1 << (kCyclesBits - 1)) + ) >> kCyclesBits; + } + */ +} + +}} diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h new file mode 100644 index 00000000..624f887c --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBit.h @@ -0,0 +1,120 @@ +// Compress/RangeCoder/RangeCoderBit.h + +#ifndef __COMPRESS_RANGECODER_BIT_H +#define __COMPRESS_RANGECODER_BIT_H + +#include "RangeCoder.h" + +namespace NCompress { +namespace NRangeCoder { + +const int kNumBitModelTotalBits = 11; +const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); + +const int kNumMoveReducingBits = 2; + +const int kNumBitPriceShiftBits = 6; +const UInt32 kBitPrice = 1 << kNumBitPriceShiftBits; + +class CPriceTables +{ +public: + static UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + static void Init(); + CPriceTables(); +}; + +template +class CBitModel +{ +public: + UInt32 Prob; + void UpdateModel(UInt32 symbol) + { + /* + Prob -= (Prob + ((symbol - 1) & ((1 << numMoveBits) - 1))) >> numMoveBits; + Prob += (1 - symbol) << (kNumBitModelTotalBits - numMoveBits); + */ + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } +public: + void Init() { Prob = kBitModelTotal / 2; } +}; + +template +class CBitEncoder: public CBitModel +{ +public: + void Encode(CEncoder *encoder, UInt32 symbol) + { + /* + encoder->EncodeBit(this->Prob, kNumBitModelTotalBits, symbol); + this->UpdateModel(symbol); + */ + UInt32 newBound = (encoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (symbol == 0) + { + encoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + } + else + { + encoder->Low += newBound; + encoder->Range -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + } + if (encoder->Range < kTopValue) + { + encoder->Range <<= 8; + encoder->ShiftLow(); + } + } + UInt32 GetPrice(UInt32 symbol) const + { + return CPriceTables::ProbPrices[ + (((this->Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + UInt32 GetPrice0() const { return CPriceTables::ProbPrices[this->Prob >> kNumMoveReducingBits]; } + UInt32 GetPrice1() const { return CPriceTables::ProbPrices[(kBitModelTotal - this->Prob) >> kNumMoveReducingBits]; } +}; + + +template +class CBitDecoder: public CBitModel +{ +public: + UInt32 Decode(CDecoder *decoder) + { + UInt32 newBound = (decoder->Range >> kNumBitModelTotalBits) * this->Prob; + if (decoder->Code < newBound) + { + decoder->Range = newBound; + this->Prob += (kBitModelTotal - this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 0; + } + else + { + decoder->Range -= newBound; + decoder->Code -= newBound; + this->Prob -= (this->Prob) >> numMoveBits; + if (decoder->Range < kTopValue) + { + decoder->Code = (decoder->Code << 8) | decoder->Stream.ReadByte(); + decoder->Range <<= 8; + } + return 1; + } + } +}; + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h new file mode 100644 index 00000000..4f0c78b4 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderBitTree.h @@ -0,0 +1,161 @@ +// Compress/RangeCoder/RangeCoderBitTree.h + +#ifndef __COMPRESS_RANGECODER_BIT_TREE_H +#define __COMPRESS_RANGECODER_BIT_TREE_H + +#include "RangeCoderBit.h" +#include "RangeCoderOpt.h" + +namespace NCompress { +namespace NRangeCoder { + +template +class CBitTreeEncoder +{ + CBitEncoder Models[1 << NumBitLevels]; +public: + void Init() + { + for(UInt32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + void Encode(CEncoder *rangeEncoder, UInt32 symbol) + { + UInt32 modelIndex = 1; + for (int bitIndex = NumBitLevels; bitIndex != 0 ;) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + } + }; + void ReverseEncode(CEncoder *rangeEncoder, UInt32 symbol) + { + UInt32 modelIndex = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } + } + UInt32 GetPrice(UInt32 symbol) const + { + symbol |= (1 << NumBitLevels); + UInt32 price = 0; + while (symbol != 1) + { + price += Models[symbol >> 1].GetPrice(symbol & 1); + symbol >>= 1; + } + return price; + } + UInt32 ReverseGetPrice(UInt32 symbol) const + { + UInt32 price = 0; + UInt32 modelIndex = 1; + for (int i = NumBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) | bit; + } + return price; + } +}; + +template +class CBitTreeDecoder +{ + CBitDecoder Models[1 << NumBitLevels]; +public: + void Init() + { + for(UInt32 i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + UInt32 Decode(CDecoder *rangeDecoder) + { + UInt32 modelIndex = 1; + RC_INIT_VAR + for(int bitIndex = NumBitLevels; bitIndex != 0; bitIndex--) + { + // modelIndex = (modelIndex << 1) + Models[modelIndex].Decode(rangeDecoder); + RC_GETBIT(numMoveBits, Models[modelIndex].Prob, modelIndex) + } + RC_FLUSH_VAR + return modelIndex - (1 << NumBitLevels); + }; + UInt32 ReverseDecode(CDecoder *rangeDecoder) + { + UInt32 modelIndex = 1; + UInt32 symbol = 0; + RC_INIT_VAR + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; + } +}; + +template +void ReverseBitTreeEncode(CBitEncoder *Models, + CEncoder *rangeEncoder, int NumBitLevels, UInt32 symbol) +{ + UInt32 modelIndex = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[modelIndex].Encode(rangeEncoder, bit); + modelIndex = (modelIndex << 1) | bit; + symbol >>= 1; + } +} + +template +UInt32 ReverseBitTreeGetPrice(CBitEncoder *Models, + UInt32 NumBitLevels, UInt32 symbol) +{ + UInt32 price = 0; + UInt32 modelIndex = 1; + for (int i = NumBitLevels; i != 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[modelIndex].GetPrice(bit); + modelIndex = (modelIndex << 1) | bit; + } + return price; +} + +template +UInt32 ReverseBitTreeDecode(CBitDecoder *Models, + CDecoder *rangeDecoder, int NumBitLevels) +{ + UInt32 modelIndex = 1; + UInt32 symbol = 0; + RC_INIT_VAR + for(int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + // UInt32 bit = Models[modelIndex].Decode(rangeDecoder); + // modelIndex <<= 1; + // modelIndex += bit; + // symbol |= (bit << bitIndex); + RC_GETBIT2(numMoveBits, Models[modelIndex].Prob, modelIndex, ; , symbol |= (1 << bitIndex)) + } + RC_FLUSH_VAR + return symbol; +} + +}} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h new file mode 100644 index 00000000..668b9a5b --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/RangeCoderOpt.h @@ -0,0 +1,31 @@ +// Compress/RangeCoder/RangeCoderOpt.h + +#ifndef __COMPRESS_RANGECODER_OPT_H +#define __COMPRESS_RANGECODER_OPT_H + +#define RC_INIT_VAR \ + UInt32 range = rangeDecoder->Range; \ + UInt32 code = rangeDecoder->Code; + +#define RC_FLUSH_VAR \ + rangeDecoder->Range = range; \ + rangeDecoder->Code = code; + +#define RC_NORMALIZE \ + if (range < NCompress::NRangeCoder::kTopValue) \ + { code = (code << 8) | rangeDecoder->Stream.ReadByte(); range <<= 8; } + +#define RC_GETBIT2(numMoveBits, prob, mi, A0, A1) \ + { UInt32 bound = (range >> NCompress::NRangeCoder::kNumBitModelTotalBits) * prob; \ + if (code < bound) \ + { A0; range = bound; \ + prob += (NCompress::NRangeCoder::kBitModelTotal - prob) >> numMoveBits; \ + mi <<= 1; } \ + else \ + { A1; range -= bound; code -= bound; prob -= (prob) >> numMoveBits; \ + mi = (mi + mi) + 1; }} \ + RC_NORMALIZE + +#define RC_GETBIT(numMoveBits, prob, mi) RC_GETBIT2(numMoveBits, prob, mi, ; , ;) + +#endif diff --git a/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/StdAfx.h b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/StdAfx.h new file mode 100644 index 00000000..b637fd40 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/Compress/RangeCoder/StdAfx.h @@ -0,0 +1,6 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#endif diff --git a/sp/src/utils/lzma/C/7zip/ICoder.h b/sp/src/utils/lzma/C/7zip/ICoder.h new file mode 100644 index 00000000..d84575dc --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/ICoder.h @@ -0,0 +1,163 @@ +// ICoder.h + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +// "23170F69-40C1-278A-0000-000400xx0000" +#define CODER_INTERFACE(i, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x04, 0x00, x, 0x00, 0x00); \ +struct i: public IUnknown + +CODER_INTERFACE(ICompressProgressInfo, 0x04) +{ + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressCoder, 0x05) +{ + STDMETHOD(Code)(ISequentialInStream *inStream, + ISequentialOutStream *outStream, + const UInt64 *inSize, + const UInt64 *outSize, + ICompressProgressInfo *progress) PURE; +}; + +CODER_INTERFACE(ICompressCoder2, 0x18) +{ + STDMETHOD(Code)(ISequentialInStream **inStreams, + const UInt64 **inSizes, + UInt32 numInStreams, + ISequentialOutStream **outStreams, + const UInt64 **outSizes, + UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +namespace NCoderPropID +{ + enum EEnum + { + kDictionarySize = 0x400, + kUsedMemorySize, + kOrder, + kPosStateBits = 0x440, + kLitContextBits, + kLitPosBits, + kNumFastBytes = 0x450, + kMatchFinder, + kMatchFinderCycles, + kNumPasses = 0x460, + kAlgorithm = 0x470, + kMultiThread = 0x480, + kNumThreads, + kEndMarker = 0x490 + }; +} + +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, + const PROPVARIANT *properties, UInt32 numProperties) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStreams) PURE; +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) +{ + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetInStream, 0x31) +{ + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetOutStream, 0x32) +{ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + STDMETHOD(Init)() PURE; + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; + // Filter return outSize (UInt32) + // if (outSize <= size): Filter have converted outSize bytes + // if (outSize > size): Filter have not converted anything. + // and it needs at least outSize bytes to convert one block + // (it's for crypto block algorithms). +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + +////////////////////// +// It's for DLL file +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kInStreams, + kOutStreams, + kDescription + }; +} + +#endif diff --git a/sp/src/utils/lzma/C/7zip/IStream.h b/sp/src/utils/lzma/C/7zip/IStream.h new file mode 100644 index 00000000..bba21a31 --- /dev/null +++ b/sp/src/utils/lzma/C/7zip/IStream.h @@ -0,0 +1,62 @@ +// IStream.h + +#ifndef __ISTREAM_H +#define __ISTREAM_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.h" + +// "23170F69-40C1-278A-0000-000300xx0000" + +#define STREAM_INTERFACE_SUB(i, b, x) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x03, 0x00, x, 0x00, 0x00); \ +struct i: public b + +#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) + +STREAM_INTERFACE(ISequentialInStream, 0x01) +{ + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + Out: if size != 0, return_value = S_OK and (*processedSize == 0), + then there are no more bytes in stream. + if (size > 0) && there are bytes in stream, + this function must read at least 1 byte. + This function is allowed to read less than number of remaining bytes in stream. + You must call Read function in loop, if you need exact amount of data + */ +}; + +STREAM_INTERFACE(ISequentialOutStream, 0x02) +{ + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + if (size > 0) this function must write at least 1 byte. + This function is allowed to write less than "size". + You must call Write function in loop, if you need to write exact amount of data + */ +}; + +STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; +}; + +STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; + STDMETHOD(SetSize)(Int64 newSize) PURE; +}; + +STREAM_INTERFACE(IStreamGetSize, 0x06) +{ + STDMETHOD(GetSize)(UInt64 *size) PURE; +}; + +STREAM_INTERFACE(IOutStreamFlush, 0x07) +{ + STDMETHOD(Flush)() PURE; +}; + +#endif diff --git a/sp/src/utils/lzma/C/Common/Alloc.cpp b/sp/src/utils/lzma/C/Common/Alloc.cpp new file mode 100644 index 00000000..e2b8c3d2 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Alloc.cpp @@ -0,0 +1,118 @@ +// Common/Alloc.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include "MyWindows.h" +#else +#include +#endif + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; +#endif + +void *MyAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount++); + #endif + return ::malloc(size); +} + +void MyFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree; count = %10d", --g_allocCount); + #endif + + ::free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Mid %10d bytes; count = %10d", size, g_allocCountMid++); + #endif + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Mid; count = %10d", --g_allocCountMid); + #endif + if (address == 0) + return; + ::VirtualFree(address, 0, MEM_RELEASE); +} + +static SIZE_T g_LargePageSize = + #ifdef _WIN64 + (1 << 21); + #else + (1 << 22); + #endif + +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); + +bool SetLargePageSize() +{ + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + ::GetProcAddress(::GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (largePageMinimum == 0) + return false; + SIZE_T size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return false; + g_LargePageSize = size; + return true; +} + + +void *BigAlloc(size_t size) throw() +{ + if (size == 0) + return 0; + #ifdef _SZ_ALLOC_DEBUG + fprintf(stderr, "\nAlloc_Big %10d bytes; count = %10d", size, g_allocCountBig++); + #endif + + if (size >= (1 << 18)) + { + void *res = ::VirtualAlloc(0, (size + g_LargePageSize - 1) & (~(g_LargePageSize - 1)), + MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res != 0) + return res; + } + return ::VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) throw() +{ + #ifdef _SZ_ALLOC_DEBUG + if (address != 0) + fprintf(stderr, "\nFree_Big; count = %10d", --g_allocCountBig); + #endif + + if (address == 0) + return; + ::VirtualFree(address, 0, MEM_RELEASE); +} + +#endif diff --git a/sp/src/utils/lzma/C/Common/Alloc.h b/sp/src/utils/lzma/C/Common/Alloc.h new file mode 100644 index 00000000..d444f631 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Alloc.h @@ -0,0 +1,29 @@ +// Common/Alloc.h + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include + +void *MyAlloc(size_t size) throw(); +void MyFree(void *address) throw(); + +#ifdef _WIN32 + +bool SetLargePageSize(); + +void *MidAlloc(size_t size) throw(); +void MidFree(void *address) throw(); +void *BigAlloc(size_t size) throw(); +void BigFree(void *address) throw(); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/CRC.cpp b/sp/src/utils/lzma/C/Common/CRC.cpp new file mode 100644 index 00000000..35e1a187 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/CRC.cpp @@ -0,0 +1,61 @@ +// Common/CRC.cpp + +#include "StdAfx.h" + +#include "CRC.h" + +static const UInt32 kCRCPoly = 0xEDB88320; + +UInt32 CCRC::Table[256]; + +void CCRC::InitTable() +{ + for (UInt32 i = 0; i < 256; i++) + { + UInt32 r = i; + for (int j = 0; j < 8; j++) + if (r & 1) + r = (r >> 1) ^ kCRCPoly; + else + r >>= 1; + CCRC::Table[i] = r; + } +} + +class CCRCTableInit +{ +public: + CCRCTableInit() { CCRC::InitTable(); } +} g_CRCTableInit; + +void CCRC::UpdateByte(Byte b) +{ + _value = Table[((Byte)(_value)) ^ b] ^ (_value >> 8); +} + +void CCRC::UpdateUInt16(UInt16 v) +{ + UpdateByte(Byte(v)); + UpdateByte(Byte(v >> 8)); +} + +void CCRC::UpdateUInt32(UInt32 v) +{ + for (int i = 0; i < 4; i++) + UpdateByte((Byte)(v >> (8 * i))); +} + +void CCRC::UpdateUInt64(UInt64 v) +{ + for (int i = 0; i < 8; i++) + UpdateByte((Byte)(v >> (8 * i))); +} + +void CCRC::Update(const void *data, size_t size) +{ + UInt32 v = _value; + const Byte *p = (const Byte *)data; + for (; size > 0 ; size--, p++) + v = Table[((Byte)(v)) ^ *p] ^ (v >> 8); + _value = v; +} diff --git a/sp/src/utils/lzma/C/Common/CRC.h b/sp/src/utils/lzma/C/Common/CRC.h new file mode 100644 index 00000000..6b4f1b79 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/CRC.h @@ -0,0 +1,36 @@ +// Common/CRC.h + +#ifndef __COMMON_CRC_H +#define __COMMON_CRC_H + +#include +#include "Types.h" + +class CCRC +{ + UInt32 _value; +public: + static UInt32 Table[256]; + static void InitTable(); + + CCRC(): _value(0xFFFFFFFF){}; + void Init() { _value = 0xFFFFFFFF; } + void UpdateByte(Byte v); + void UpdateUInt16(UInt16 v); + void UpdateUInt32(UInt32 v); + void UpdateUInt64(UInt64 v); + void Update(const void *data, size_t size); + UInt32 GetDigest() const { return _value ^ 0xFFFFFFFF; } + static UInt32 CalculateDigest(const void *data, size_t size) + { + CCRC crc; + crc.Update(data, size); + return crc.GetDigest(); + } + static bool VerifyDigest(UInt32 digest, const void *data, size_t size) + { + return (CalculateDigest(data, size) == digest); + } +}; + +#endif diff --git a/sp/src/utils/lzma/C/Common/C_FileIO.cpp b/sp/src/utils/lzma/C/Common/C_FileIO.cpp new file mode 100644 index 00000000..7d9e00d0 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/C_FileIO.cpp @@ -0,0 +1,78 @@ +// Common/C_FileIO.h + +#include "C_FileIO.h" + +#include +#include + +namespace NC { +namespace NFile { +namespace NIO { + +bool CFileBase::OpenBinary(const char *name, int flags) +{ + #ifdef O_BINARY + flags |= O_BINARY; + #endif + Close(); + _handle = ::open(name, flags, 0666); + return _handle != -1; +} + +bool CFileBase::Close() +{ + if(_handle == -1) + return true; + if (close(_handle) != 0) + return false; + _handle = -1; + return true; +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + off_t curPos = Seek(0, SEEK_CUR); + off_t lengthTemp = Seek(0, SEEK_END); + Seek(curPos, SEEK_SET); + length = (UInt64)lengthTemp; + return true; +} + +off_t CFileBase::Seek(off_t distanceToMove, int moveMethod) const +{ + return ::lseek(_handle, distanceToMove, moveMethod); +} + +///////////////////////// +// CInFile + +bool CInFile::Open(const char *name) +{ + return CFileBase::OpenBinary(name, O_RDONLY); +} + +ssize_t CInFile::Read(void *data, size_t size) +{ + return read(_handle, data, size); +} + +///////////////////////// +// COutFile + +bool COutFile::Create(const char *name, bool createAlways) +{ + if (createAlways) + { + Close(); + _handle = ::creat(name, 0666); + return _handle != -1; + } + return OpenBinary(name, O_CREAT | O_EXCL | O_WRONLY); +} + +ssize_t COutFile::Write(const void *data, size_t size) +{ + return write(_handle, data, size); +} + +}}} diff --git a/sp/src/utils/lzma/C/Common/C_FileIO.h b/sp/src/utils/lzma/C/Common/C_FileIO.h new file mode 100644 index 00000000..2ad07167 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/C_FileIO.h @@ -0,0 +1,45 @@ +// Common/C_FileIO.h + +#ifndef __COMMON_C_FILEIO_H +#define __COMMON_C_FILEIO_H + +#include +#include + +#include "Types.h" +#include "MyWindows.h" + +namespace NC { +namespace NFile { +namespace NIO { + +class CFileBase +{ +protected: + int _handle; + bool OpenBinary(const char *name, int flags); +public: + CFileBase(): _handle(-1) {}; + ~CFileBase() { Close(); } + bool Close(); + bool GetLength(UInt64 &length) const; + off_t Seek(off_t distanceToMove, int moveMethod) const; +}; + +class CInFile: public CFileBase +{ +public: + bool Open(const char *name); + ssize_t Read(void *data, size_t size); +}; + +class COutFile: public CFileBase +{ +public: + bool Create(const char *name, bool createAlways); + ssize_t Write(const void *data, size_t size); +}; + +}}} + +#endif diff --git a/sp/src/utils/lzma/C/Common/ComTry.h b/sp/src/utils/lzma/C/Common/ComTry.h new file mode 100644 index 00000000..5153362f --- /dev/null +++ b/sp/src/utils/lzma/C/Common/ComTry.h @@ -0,0 +1,17 @@ +// ComTry.h + +#ifndef __COM_TRY_H +#define __COM_TRY_H + +#include "MyWindows.h" +// #include "Exception.h" +// #include "NewHandler.h" + +#define COM_TRY_BEGIN try { +#define COM_TRY_END } catch(...) { return E_OUTOFMEMORY; } + + // catch(const CNewException &) { return E_OUTOFMEMORY; }\ + // catch(const CSystemException &e) { return e.ErrorCode; }\ + // catch(...) { return E_FAIL; } + +#endif diff --git a/sp/src/utils/lzma/C/Common/CommandLineParser.cpp b/sp/src/utils/lzma/C/Common/CommandLineParser.cpp new file mode 100644 index 00000000..69c41841 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/CommandLineParser.cpp @@ -0,0 +1,232 @@ +// CommandLineParser.cpp + +#include "StdAfx.h" + +#include "CommandLineParser.h" + +namespace NCommandLineParser { + +void SplitCommandLine(const UString &src, UString &dest1, UString &dest2) +{ + dest1.Empty(); + dest2.Empty(); + bool quoteMode = false; + int i; + for (i = 0; i < src.Length(); i++) + { + wchar_t c = src[i]; + if (c == L'\"') + quoteMode = !quoteMode; + else if (c == L' ' && !quoteMode) + { + i++; + break; + } + else + dest1 += c; + } + dest2 = src.Mid(i); +} + +void SplitCommandLine(const UString &s, UStringVector &parts) +{ + UString sTemp = s; + sTemp.Trim(); + parts.Clear(); + while (true) + { + UString s1, s2; + SplitCommandLine(sTemp, s1, s2); + // s1.Trim(); + // s2.Trim(); + if (!s1.IsEmpty()) + parts.Add(s1); + if (s2.IsEmpty()) + return; + sTemp = s2; + } +} + + +static const wchar_t kSwitchID1 = '-'; +// static const wchar_t kSwitchID2 = '/'; + +static const wchar_t kSwitchMinus = '-'; +static const wchar_t *kStopSwitchParsing = L"--"; + +static bool IsItSwitchChar(wchar_t c) +{ + return (c == kSwitchID1 /*|| c == kSwitchID2 */); +} + +CParser::CParser(int numSwitches): + _numSwitches(numSwitches) +{ + _switches = new CSwitchResult[_numSwitches]; +} + +CParser::~CParser() +{ + delete []_switches; +} + +void CParser::ParseStrings(const CSwitchForm *switchForms, + const UStringVector &commandStrings) +{ + int numCommandStrings = commandStrings.Size(); + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + const UString &s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } +} + +// if string contains switch then function updates switch structures +// out: (string is a switch) +bool CParser::ParseString(const UString &s, const CSwitchForm *switchForms) +{ + int len = s.Length(); + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(s[pos])) + return false; + while(pos < len) + { + if (IsItSwitchChar(s[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; // GCC Warning + int maxLen = kNoLen; + for(int switchIndex = 0; switchIndex < _numSwitches; switchIndex++) + { + int switchLen = MyStringLen(switchForms[switchIndex].IDString); + if (switchLen <= maxLen || pos + switchLen > len) + continue; + + UString temp = s + pos; + temp = temp.Left(switchLen); + if(temp.CompareNoCase(switchForms[switchIndex].IDString) == 0) + // if(_strnicmp(switchForms[switchIndex].IDString, LPCSTR(s) + pos, switchLen) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw "maxLen == kNoLen"; + CSwitchResult &matchedSwitch = _switches[matchedSwitchIndex]; + const CSwitchForm &switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw "switch must be single"; + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + NSwitchType::EEnum type = switchForm.Type; + switch(type) + { + case NSwitchType::kPostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (s[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case NSwitchType::kPostChar: + { + if (tailSize < switchForm.MinLen) + throw "switch is not full"; + UString set = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = set.Find(s[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case NSwitchType::kLimitedPostString: + case NSwitchType::kUnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw "switch is not full"; + if (type == NSwitchType::kUnLimitedPostString) + { + matchedSwitch.PostStrings.Add(s.Mid(pos)); + return true; + } + int maxLen = switchForm.MaxLen; + UString stringSwitch = s.Mid(pos, minLen); + pos += minLen; + for(int i = minLen; i < maxLen && pos < len; i++, pos++) + { + wchar_t c = s[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + case NSwitchType::kSimple: + break; + } + } + return true; +} + +const CSwitchResult& CParser::operator[](size_t index) const +{ + return _switches[index]; +} + +///////////////////////////////// +// Command parsing procedures + +int ParseCommand(int numCommandForms, const CCommandForm *commandForms, + const UString &commandString, UString &postString) +{ + for(int i = 0; i < numCommandForms; i++) + { + const UString id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if(commandString.Find(id) == 0) + { + postString = commandString.Mid(id.Length()); + return i; + } + } + else + if (commandString == id) + { + postString.Empty(); + return i; + } + } + return -1; +} + +} diff --git a/sp/src/utils/lzma/C/Common/CommandLineParser.h b/sp/src/utils/lzma/C/Common/CommandLineParser.h new file mode 100644 index 00000000..af698db8 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/CommandLineParser.h @@ -0,0 +1,72 @@ +// Common/CommandLineParser.h + +#ifndef __COMMON_COMMANDLINEPARSER_H +#define __COMMON_COMMANDLINEPARSER_H + +#include "Common/String.h" + +namespace NCommandLineParser { + +void SplitCommandLine(const UString &src, UString &dest1, UString &dest2); +void SplitCommandLine(const UString &s, UStringVector &parts); + +namespace NSwitchType { + enum EEnum + { + kSimple, + kPostMinus, + kLimitedPostString, + kUnLimitedPostString, + kPostChar + }; +} + +struct CSwitchForm +{ + const wchar_t *IDString; + NSwitchType::EEnum Type; + bool Multi; + int MinLen; + int MaxLen; + const wchar_t *PostCharSet; +}; + +struct CSwitchResult +{ + bool ThereIs; + bool WithMinus; + UStringVector PostStrings; + int PostCharIndex; + CSwitchResult(): ThereIs(false) {}; +}; + +class CParser +{ + int _numSwitches; + CSwitchResult *_switches; + bool ParseString(const UString &s, const CSwitchForm *switchForms); +public: + UStringVector NonSwitchStrings; + CParser(int numSwitches); + ~CParser(); + void ParseStrings(const CSwitchForm *switchForms, + const UStringVector &commandStrings); + const CSwitchResult& operator[](size_t index) const; +}; + +///////////////////////////////// +// Command parsing procedures + +struct CCommandForm +{ + wchar_t *IDString; + bool PostStringMode; +}; + +// Returns: Index of form and postString; -1, if there is no match +int ParseCommand(int numCommandForms, const CCommandForm *commandForms, + const UString &commandString, UString &postString); + +} + +#endif diff --git a/sp/src/utils/lzma/C/Common/Defs.h b/sp/src/utils/lzma/C/Common/Defs.h new file mode 100644 index 00000000..dad3ae8f --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Defs.h @@ -0,0 +1,20 @@ +// Common/Defs.h + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template inline T MyMin(T a, T b) + { return a < b ? a : b; } +template inline T MyMax(T a, T b) + { return a > b ? a : b; } + +template inline int MyCompare(T a, T b) + { return a < b ? -1 : (a == b ? 0 : 1); } + +inline int BoolToInt(bool value) + { return (value ? 1: 0); } + +inline bool IntToBool(int value) + { return (value != 0); } + +#endif diff --git a/sp/src/utils/lzma/C/Common/MyCom.h b/sp/src/utils/lzma/C/Common/MyCom.h new file mode 100644 index 00000000..e9034930 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/MyCom.h @@ -0,0 +1,203 @@ +// MyCom.h + +#ifndef __MYCOM_H +#define __MYCOM_H + +#include "MyWindows.h" + +#define RINOK(x) { HRESULT __result_ = (x); if(__result_ != S_OK) return __result_; } + +template +class CMyComPtr +{ + T* _p; +public: + // typedef T _PtrClass; + CMyComPtr() { _p = NULL;} + CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) + { + if ((_p = lp._p) != NULL) + _p->AddRef(); + } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p != 0) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + // Compare two objects for equivalence + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + #ifdef _WIN32 + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + #endif + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template + HRESULT QueryInterface(REFGUID iid, Q** pp) const + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +class CMyComBSTR +{ +public: + BSTR m_str; + CMyComBSTR() { m_str = NULL; } + CMyComBSTR(LPCOLESTR pSrc) { m_str = ::SysAllocString(pSrc); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + ~CMyComBSTR() { ::SysFreeString(m_str); } + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + CMyComBSTR& operator=(LPCOLESTR pSrc) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(pSrc); + return *this; + } + unsigned int Length() const { return ::SysStringLen(m_str); } + operator BSTR() const { return m_str; } + BSTR* operator&() { return &m_str; } + BSTR MyCopy() const + { + int byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + memmove(res, m_str, byteLen); + return res; + } + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } + bool operator!() const { return (m_str == NULL); } +}; + + +////////////////////////////////////////////////////////// + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} +}; + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ + (REFGUID iid, void **outObject) { + +#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP STDMETHOD(QueryInterface)(REFGUID, void **) { \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) + +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) + +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + ) + +#endif diff --git a/sp/src/utils/lzma/C/Common/MyGuidDef.h b/sp/src/utils/lzma/C/Common/MyGuidDef.h new file mode 100644 index 00000000..2c954f81 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/MyGuidDef.h @@ -0,0 +1,54 @@ +// Common/MyGuidDef.h + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +#include "Types.h" + +typedef struct { + UInt32 Data1; + UInt16 Data2; + UInt16 Data3; + unsigned char Data4[8]; +} GUID; + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +#define REFCLSID REFGUID +#define REFIID REFGUID + +#ifdef __cplusplus +inline bool operator==(REFGUID g1, REFGUID g2) +{ + for (int i = 0; i < (int)sizeof(g1); i++) + if (((unsigned char *)&g1)[i] != ((unsigned char *)&g2)[i]) + return false; + return true; +} +inline bool operator!=(REFGUID g1, REFGUID g2) { return !(g1 == g2); } +#endif + +#ifdef __cplusplus + #define MY_EXTERN_C extern "C" +#else + #define MY_EXTERN_C extern +#endif + +#endif // GUID_DEFINED + + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else + #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + MY_EXTERN_C const GUID name +#endif diff --git a/sp/src/utils/lzma/C/Common/MyInitGuid.h b/sp/src/utils/lzma/C/Common/MyInitGuid.h new file mode 100644 index 00000000..5bdfeed5 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/MyInitGuid.h @@ -0,0 +1,13 @@ +// Common/MyInitGuid.h + +#ifndef __COMMON_MYINITGUID_H +#define __COMMON_MYINITGUID_H + +#ifdef _WIN32 +#include +#else +#define INITGUID +#include "MyGuidDef.h" +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/MyUnknown.h b/sp/src/utils/lzma/C/Common/MyUnknown.h new file mode 100644 index 00000000..d28d8542 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/MyUnknown.h @@ -0,0 +1,24 @@ +// MyUnknown.h + +#ifndef __MYUNKNOWN_H +#define __MYUNKNOWN_H + +#ifdef _WIN32 + +#ifdef _WIN32_WCE +#if (_WIN32_WCE > 300) +#include +#else +#define MIDL_INTERFACE(x) struct +#endif +#else +#include +#endif + +#include + +#else +#include "MyWindows.h" +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/MyWindows.h b/sp/src/utils/lzma/C/Common/MyWindows.h new file mode 100644 index 00000000..e1ea41fb --- /dev/null +++ b/sp/src/utils/lzma/C/Common/MyWindows.h @@ -0,0 +1,200 @@ +// MyWindows.h + +#ifndef __MYWINDOWS_H +#define __MYWINDOWS_H + +#ifdef _WIN32 + +#include + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#include // for wchar_t +#include + +#include "MyGuidDef.h" + +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; +typedef short VARIANT_BOOL; + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; +typedef OLECHAR *BSTR; +typedef const OLECHAR *LPCOLESTR; +typedef OLECHAR *LPOLESTR; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +}FILETIME; + +#define HRESULT LONG +#define FAILED(Status) ((HRESULT)(Status)<0) +typedef ULONG PROPID; +typedef LONG SCODE; + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOINTERFACE ((HRESULT)0x80004002L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) + +#ifdef _MSC_VER +#define STDMETHODCALLTYPE __stdcall +#else +#define STDMETHODCALLTYPE +#endif + +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0 + +#define MIDL_INTERFACE(x) struct + +struct IUnknown +{ + STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; +}; + +typedef IUnknown *LPUNKNOWN; + +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +enum VARENUM +{ + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_FILETIME = 64 +}; + +typedef unsigned short VARTYPE; +typedef WORD PROPVAR_PAD1; +typedef WORD PROPVAR_PAD2; +typedef WORD PROPVAR_PAD3; + +typedef struct tagPROPVARIANT +{ + VARTYPE vt; + PROPVAR_PAD1 wReserved1; + PROPVAR_PAD2 wReserved2; + PROPVAR_PAD3 wReserved3; + union + { + CHAR cVal; + UCHAR bVal; + SHORT iVal; + USHORT uiVal; + LONG lVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + SCODE scode; + FILETIME filetime; + BSTR bstrVal; + }; +} PROPVARIANT; + +typedef PROPVARIANT tagVARIANT; +typedef tagVARIANT VARIANT; +typedef VARIANT VARIANTARG; + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); + +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); + +#define CP_ACP 0 +#define CP_OEMCP 1 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + +#endif +#endif diff --git a/sp/src/utils/lzma/C/Common/NewHandler.cpp b/sp/src/utils/lzma/C/Common/NewHandler.cpp new file mode 100644 index 00000000..094eb642 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/NewHandler.cpp @@ -0,0 +1,116 @@ +// NewHandler.cpp + +#include "StdAfx.h" + +#include + +#include "NewHandler.h" + +// #define DEBUG_MEMORY_LEAK + +#ifndef DEBUG_MEMORY_LEAK + +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw() +{ + /* + if (p == 0) + return; + ::HeapFree(::GetProcessHeap(), 0, p); + */ + ::free(p); +} +#endif + +#else + +#pragma init_seg(lib) +const int kDebugSize = 1000000; +static void *a[kDebugSize]; +static int index = 0; + +static int numAllocs = 0; +void * __cdecl operator new(size_t size) +{ + numAllocs++; + void *p = HeapAlloc(GetProcessHeap(), 0, size); + if (index == 40) + { + int t = 1; + } + if (index < kDebugSize) + { + a[index] = p; + index++; + } + if (p == 0) + throw CNewException(); + printf("Alloc %6d, size = %8d\n", numAllocs, size); + return p; +} + +class CC +{ +public: + CC() + { + for (int i = 0; i < kDebugSize; i++) + a[i] = 0; + } + ~CC() + { + for (int i = 0; i < kDebugSize; i++) + if (a[i] != 0) + return; + } +} g_CC; + + +void __cdecl operator delete(void *p) +{ + if (p == 0) + return; + /* + for (int i = 0; i < index; i++) + if (a[i] == p) + a[i] = 0; + */ + HeapFree(GetProcessHeap(), 0, p); + numAllocs--; + printf("Free %d\n", numAllocs); +} + +#endif + +/* +int MemErrorVC(size_t) +{ + throw CNewException(); + // return 1; +} +CNewHandlerSetter::CNewHandlerSetter() +{ + // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); +} +CNewHandlerSetter::~CNewHandlerSetter() +{ + // _set_new_handler(MemErrorOldVCFunction); +} +*/ diff --git a/sp/src/utils/lzma/C/Common/NewHandler.h b/sp/src/utils/lzma/C/Common/NewHandler.h new file mode 100644 index 00000000..0619fc69 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/NewHandler.h @@ -0,0 +1,16 @@ +// Common/NewHandler.h + +#ifndef __COMMON_NEWHANDLER_H +#define __COMMON_NEWHANDLER_H + +class CNewException {}; + +#ifdef _WIN32 +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw(); +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/StdAfx.h b/sp/src/utils/lzma/C/Common/StdAfx.h new file mode 100644 index 00000000..681ee935 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +// #include "MyWindows.h" +#include "NewHandler.h" + +#endif diff --git a/sp/src/utils/lzma/C/Common/String.cpp b/sp/src/utils/lzma/C/Common/String.cpp new file mode 100644 index 00000000..7921fe41 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/String.cpp @@ -0,0 +1,198 @@ +// Common/String.cpp + +#include "StdAfx.h" + +#ifdef _WIN32 +#include "StringConvert.h" +#else +#include +#endif + +#include "Common/String.h" + + +#ifdef _WIN32 + +#ifndef _UNICODE + +wchar_t MyCharUpper(wchar_t c) +{ + if (c == 0) + return 0; + wchar_t *res = CharUpperW((LPWSTR)(unsigned int)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned int)res; + const int kBufferSize = 4; + char s[kBufferSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); + if (numChars == 0 || numChars > kBufferSize) + return c; + s[numChars] = 0; + ::CharUpperA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} + +wchar_t MyCharLower(wchar_t c) +{ + if (c == 0) + return 0; + wchar_t *res = CharLowerW((LPWSTR)(unsigned int)c); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return (wchar_t)(unsigned int)res; + const int kBufferSize = 4; + char s[kBufferSize + 1]; + int numChars = ::WideCharToMultiByte(CP_ACP, 0, &c, 1, s, kBufferSize, 0, 0); + if (numChars == 0 || numChars > kBufferSize) + return c; + s[numChars] = 0; + ::CharLowerA(s); + ::MultiByteToWideChar(CP_ACP, 0, s, numChars, &c, 1); + return c; +} + +wchar_t * MyStringUpper(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharUpperW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeUpper(); + return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); +} + +wchar_t * MyStringLower(wchar_t *s) +{ + if (s == 0) + return 0; + wchar_t *res = CharLowerW(s); + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return res; + AString a = UnicodeStringToMultiByte(s); + a.MakeLower(); + return MyStringCopy(s, (const wchar_t *)MultiByteToUnicodeString(a)); +} + +#endif + +/* +inline int ConvertCompareResult(int r) { return r - 2; } + +int MyStringCollate(const wchar_t *s1, const wchar_t *s2) +{ + int res = CompareStringW( + LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1); + #ifdef _UNICODE + return ConvertCompareResult(res); + #else + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return ConvertCompareResult(res); + return MyStringCollate(UnicodeStringToMultiByte(s1), + UnicodeStringToMultiByte(s2)); + #endif +} + +#ifndef _WIN32_WCE +int MyStringCollate(const char *s1, const char *s2) +{ + return ConvertCompareResult(CompareStringA( + LOCALE_USER_DEFAULT, SORT_STRINGSORT, s1, -1, s2, -1)); +} + +int MyStringCollateNoCase(const char *s1, const char *s2) +{ + return ConvertCompareResult(CompareStringA( + LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1)); +} +#endif + +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +{ + int res = CompareStringW( + LOCALE_USER_DEFAULT, NORM_IGNORECASE | SORT_STRINGSORT, s1, -1, s2, -1); + #ifdef _UNICODE + return ConvertCompareResult(res); + #else + if (res != 0 || ::GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) + return ConvertCompareResult(res); + return MyStringCollateNoCase(UnicodeStringToMultiByte(s1), + UnicodeStringToMultiByte(s2)); + #endif +} +*/ + +#else + +wchar_t MyCharUpper(wchar_t c) +{ + return toupper(c); +} + +/* +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2) +{ + while (true) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + + if (u1 < u2) return -1; + if (u1 > u2) return 1; + if (u1 == 0) return 0; + } +} +*/ + +#endif + +int MyStringCompare(const char *s1, const char *s2) +{ + while (true) + { + unsigned char c1 = (unsigned char)*s1++; + unsigned char c2 = (unsigned char)*s2++; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + if (c1 == 0) return 0; + } +} + +int MyStringCompare(const wchar_t *s1, const wchar_t *s2) +{ + while (true) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + if (c1 == 0) return 0; + } +} + +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2) +{ + while (true) + { + wchar_t c1 = *s1++; + wchar_t c2 = *s2++; + if (c1 != c2) + { + wchar_t u1 = MyCharUpper(c1); + wchar_t u2 = MyCharUpper(c2); + if (u1 < u2) return -1; + if (u1 > u2) return 1; + } + if (c1 == 0) return 0; + } +} + +#ifdef _WIN32 +int MyStringCompareNoCase(const char *s1, const char *s2) +{ + return MyStringCompareNoCase(MultiByteToUnicodeString(s1), MultiByteToUnicodeString(s2)); +} +#endif diff --git a/sp/src/utils/lzma/C/Common/String.h b/sp/src/utils/lzma/C/Common/String.h new file mode 100644 index 00000000..c4277c1c --- /dev/null +++ b/sp/src/utils/lzma/C/Common/String.h @@ -0,0 +1,631 @@ +// Common/String.h + +#ifndef __COMMON_STRING_H +#define __COMMON_STRING_H + +#include +// #include + +#include "Vector.h" + +#ifdef _WIN32 +#include "MyWindows.h" +#endif + +static const char *kTrimDefaultCharSet = " \n\t"; + +template +inline int MyStringLen(const T *s) +{ + int i; + for (i = 0; s[i] != '\0'; i++); + return i; +} + +template +inline T * MyStringCopy(T *dest, const T *src) +{ + T *destStart = dest; + while((*dest++ = *src++) != 0); + return destStart; +} + +inline wchar_t* MyStringGetNextCharPointer(wchar_t *p) + { return (p + 1); } +inline const wchar_t* MyStringGetNextCharPointer(const wchar_t *p) + { return (p + 1); } +inline wchar_t* MyStringGetPrevCharPointer(const wchar_t *, wchar_t *p) + { return (p - 1); } +inline const wchar_t* MyStringGetPrevCharPointer(const wchar_t *, const wchar_t *p) + { return (p - 1); } + +#ifdef _WIN32 + +inline char* MyStringGetNextCharPointer(char *p) + { return CharNextA(p); } +inline const char* MyStringGetNextCharPointer(const char *p) + { return CharNextA(p); } + +inline char* MyStringGetPrevCharPointer(char *base, char *p) + { return CharPrevA(base, p); } +inline const char* MyStringGetPrevCharPointer(const char *base, const char *p) + { return CharPrevA(base, p); } + +inline char MyCharUpper(char c) + { return (char)(unsigned int)CharUpperA((LPSTR)(unsigned int)(unsigned char)c); } +#ifdef _UNICODE +inline wchar_t MyCharUpper(wchar_t c) + { return (wchar_t)CharUpperW((LPWSTR)c); } +#else +wchar_t MyCharUpper(wchar_t c); +#endif + +inline char MyCharLower(char c) + { return (char)(unsigned int)CharLowerA((LPSTR)(unsigned int)(unsigned char)c); } +#ifdef _UNICODE +inline wchar_t MyCharLower(wchar_t c) + { return (wchar_t)CharLowerW((LPWSTR)c); } +#else +wchar_t MyCharLower(wchar_t c); +#endif + +inline char * MyStringUpper(char *s) { return CharUpperA(s); } +#ifdef _UNICODE +inline wchar_t * MyStringUpper(wchar_t *s) { return CharUpperW(s); } +#else +wchar_t * MyStringUpper(wchar_t *s); +#endif + +inline char * MyStringLower(char *s) { return CharLowerA(s); } +#ifdef _UNICODE +inline wchar_t * MyStringLower(wchar_t *s) { return CharLowerW(s); } +#else +wchar_t * MyStringLower(wchar_t *s); +#endif + +#else // Standard-C +wchar_t MyCharUpper(wchar_t c); +#endif + +////////////////////////////////////// +// Compare + +/* +#ifndef _WIN32_WCE +int MyStringCollate(const char *s1, const char *s2); +int MyStringCollateNoCase(const char *s1, const char *s2); +#endif +int MyStringCollate(const wchar_t *s1, const wchar_t *s2); +int MyStringCollateNoCase(const wchar_t *s1, const wchar_t *s2); +*/ + +int MyStringCompare(const char *s1, const char *s2); +int MyStringCompare(const wchar_t *s1, const wchar_t *s2); + +#ifdef _WIN32 +int MyStringCompareNoCase(const char *s1, const char *s2); +#endif + +int MyStringCompareNoCase(const wchar_t *s1, const wchar_t *s2); + +template +class CStringBase +{ + void TrimLeftWithCharSet(const CStringBase &charSet) + { + const T *p = _chars; + while (charSet.Find(*p) >= 0 && (*p != 0)) + p = GetNextCharPointer(p); + Delete(0, (int)(p - _chars)); + } + void TrimRightWithCharSet(const CStringBase &charSet) + { + const T *p = _chars; + const T *pLast = NULL; + while (*p != 0) + { + if (charSet.Find(*p) >= 0) + { + if (pLast == NULL) + pLast = p; + } + else + pLast = NULL; + p = GetNextCharPointer(p); + } + if(pLast != NULL) + { + int i = (int)(pLast - _chars); + Delete(i, _length - i); + } + + } + void MoveItems(int destIndex, int srcIndex) + { + memmove(_chars + destIndex, _chars + srcIndex, + sizeof(T) * (_length - srcIndex + 1)); + } + + void InsertSpace(int &index, int size) + { + CorrectIndex(index); + GrowLength(size); + MoveItems(index + size, index); + } + + static T *GetNextCharPointer(T *p) + { return MyStringGetNextCharPointer(p); } + static const T *GetNextCharPointer(const T *p) + { return MyStringGetNextCharPointer(p); } + static T *GetPrevCharPointer(T *base, T *p) + { return MyStringGetPrevCharPointer(base, p); } + static const T *GetPrevCharPointer(const T *base, const T *p) + { return MyStringGetPrevCharPointer(base, p); } +protected: + T *_chars; + int _length; + int _capacity; + + void SetCapacity(int newCapacity) + { + int realCapacity = newCapacity + 1; + if(realCapacity == _capacity) + return; + /* + const int kMaxStringSize = 0x20000000; + #ifndef _WIN32_WCE + if(newCapacity > kMaxStringSize || newCapacity < _length) + throw 1052337; + #endif + */ + T *newBuffer = new T[realCapacity]; + if(_capacity > 0) + { + for (int i = 0; i < (_length + 1); i++) + newBuffer[i] = _chars[i]; + delete []_chars; + _chars = newBuffer; + } + else + { + _chars = newBuffer; + _chars[0] = 0; + } + _capacity = realCapacity; + } + + void GrowLength(int n) + { + int freeSize = _capacity - _length - 1; + if (n <= freeSize) + return; + int delta; + if (_capacity > 64) + delta = _capacity / 2; + else if (_capacity > 8) + delta = 16; + else + delta = 4; + if (freeSize + delta < n) + delta = n - freeSize; + SetCapacity(_capacity + delta); + } + + void CorrectIndex(int &index) const + { + if (index > _length) + index = _length; + } + +public: + CStringBase(): _chars(0), _length(0), _capacity(0) + { SetCapacity(16 - 1); } + CStringBase(T c): _chars(0), _length(0), _capacity(0) + { + SetCapacity(1); + _chars[0] = c; + _chars[1] = 0; + _length = 1; + } + CStringBase(const T *chars): _chars(0), _length(0), _capacity(0) + { + int length = MyStringLen(chars); + SetCapacity(length); + MyStringCopy(_chars, chars); // can be optimized by memove() + _length = length; + } + CStringBase(const CStringBase &s): _chars(0), _length(0), _capacity(0) + { + SetCapacity(s._length); + MyStringCopy(_chars, s._chars); + _length = s._length; + } + ~CStringBase() { delete []_chars; } + + operator const T*() const { return _chars;} + + // The minimum size of the character buffer in characters. + // This value does not include space for a null terminator. + T* GetBuffer(int minBufLength) + { + if(minBufLength >= _capacity) + SetCapacity(minBufLength + 1); + return _chars; + } + void ReleaseBuffer() { ReleaseBuffer(MyStringLen(_chars)); } + void ReleaseBuffer(int newLength) + { + /* + #ifndef _WIN32_WCE + if(newLength >= _capacity) + throw 282217; + #endif + */ + _chars[newLength] = 0; + _length = newLength; + } + + CStringBase& operator=(T c) + { + Empty(); + SetCapacity(1); + _chars[0] = c; + _chars[1] = 0; + _length = 1; + return *this; + } + CStringBase& operator=(const T *chars) + { + Empty(); + int length = MyStringLen(chars); + SetCapacity(length); + MyStringCopy(_chars, chars); + _length = length; + return *this; + } + CStringBase& operator=(const CStringBase& s) + { + if(&s == this) + return *this; + Empty(); + SetCapacity(s._length); + MyStringCopy(_chars, s._chars); + _length = s._length; + return *this; + } + + CStringBase& operator+=(T c) + { + GrowLength(1); + _chars[_length] = c; + _chars[++_length] = 0; + return *this; + } + CStringBase& operator+=(const T *s) + { + int len = MyStringLen(s); + GrowLength(len); + MyStringCopy(_chars + _length, s); + _length += len; + return *this; + } + CStringBase& operator+=(const CStringBase &s) + { + GrowLength(s._length); + MyStringCopy(_chars + _length, s._chars); + _length += s._length; + return *this; + } + void Empty() + { + _length = 0; + _chars[0] = 0; + } + int Length() const { return _length; } + bool IsEmpty() const { return (_length == 0); } + + CStringBase Mid(int startIndex) const + { return Mid(startIndex, _length - startIndex); } + CStringBase Mid(int startIndex, int count ) const + { + if (startIndex + count > _length) + count = _length - startIndex; + + if (startIndex == 0 && startIndex + count == _length) + return *this; + + CStringBase result; + result.SetCapacity(count); + // MyStringNCopy(result._chars, _chars + startIndex, count); + for (int i = 0; i < count; i++) + result._chars[i] = _chars[startIndex + i]; + result._chars[count] = 0; + result._length = count; + return result; + } + CStringBase Left(int count) const + { return Mid(0, count); } + CStringBase Right(int count) const + { + if (count > _length) + count = _length; + return Mid(_length - count, count); + } + + void MakeUpper() + { MyStringUpper(_chars); } + void MakeLower() + { MyStringLower(_chars); } + + int Compare(const CStringBase& s) const + { return MyStringCompare(_chars, s._chars); } + + int CompareNoCase(const CStringBase& s) const + { return MyStringCompareNoCase(_chars, s._chars); } + /* + int Collate(const CStringBase& s) const + { return MyStringCollate(_chars, s._chars); } + int CollateNoCase(const CStringBase& s) const + { return MyStringCollateNoCase(_chars, s._chars); } + */ + + int Find(T c) const { return Find(c, 0); } + int Find(T c, int startIndex) const + { + T *p = _chars + startIndex; + while (true) + { + if (*p == c) + return (int)(p - _chars); + if (*p == 0) + return -1; + p = GetNextCharPointer(p); + } + } + int Find(const CStringBase &s) const { return Find(s, 0); } + int Find(const CStringBase &s, int startIndex) const + { + if (s.IsEmpty()) + return startIndex; + for (; startIndex < _length; startIndex++) + { + int j; + for (j = 0; j < s._length && startIndex + j < _length; j++) + if (_chars[startIndex+j] != s._chars[j]) + break; + if (j == s._length) + return startIndex; + } + return -1; + } + int ReverseFind(T c) const + { + if (_length == 0) + return -1; + T *p = _chars + _length - 1; + while (true) + { + if (*p == c) + return (int)(p - _chars); + if (p == _chars) + return -1; + p = GetPrevCharPointer(_chars, p); + } + } + int FindOneOf(const CStringBase &s) const + { + for(int i = 0; i < _length; i++) + if (s.Find(_chars[i]) >= 0) + return i; + return -1; + } + + void TrimLeft(T c) + { + const T *p = _chars; + while (c == *p) + p = GetNextCharPointer(p); + Delete(0, p - _chars); + } + private: + CStringBase GetTrimDefaultCharSet() + { + CStringBase charSet; + for(int i = 0; i < (int)(sizeof(kTrimDefaultCharSet) / + sizeof(kTrimDefaultCharSet[0])); i++) + charSet += (T)kTrimDefaultCharSet[i]; + return charSet; + } + public: + + void TrimLeft() + { + TrimLeftWithCharSet(GetTrimDefaultCharSet()); + } + void TrimRight() + { + TrimRightWithCharSet(GetTrimDefaultCharSet()); + } + void TrimRight(T c) + { + const T *p = _chars; + const T *pLast = NULL; + while (*p != 0) + { + if (*p == c) + { + if (pLast == NULL) + pLast = p; + } + else + pLast = NULL; + p = GetNextCharPointer(p); + } + if(pLast != NULL) + { + int i = pLast - _chars; + Delete(i, _length - i); + } + } + void Trim() + { + TrimRight(); + TrimLeft(); + } + + int Insert(int index, T c) + { + InsertSpace(index, 1); + _chars[index] = c; + _length++; + return _length; + } + int Insert(int index, const CStringBase &s) + { + CorrectIndex(index); + if (s.IsEmpty()) + return _length; + int numInsertChars = s.Length(); + InsertSpace(index, numInsertChars); + for(int i = 0; i < numInsertChars; i++) + _chars[index + i] = s[i]; + _length += numInsertChars; + return _length; + } + + // !!!!!!!!!!!!!!! test it if newChar = '\0' + int Replace(T oldChar, T newChar) + { + if (oldChar == newChar) + return 0; + int number = 0; + int pos = 0; + while (pos < Length()) + { + pos = Find(oldChar, pos); + if (pos < 0) + break; + _chars[pos] = newChar; + pos++; + number++; + } + return number; + } + int Replace(const CStringBase &oldString, const CStringBase &newString) + { + if (oldString.IsEmpty()) + return 0; + if (oldString == newString) + return 0; + int oldStringLength = oldString.Length(); + int newStringLength = newString.Length(); + int number = 0; + int pos = 0; + while (pos < _length) + { + pos = Find(oldString, pos); + if (pos < 0) + break; + Delete(pos, oldStringLength); + Insert(pos, newString); + pos += newStringLength; + number++; + } + return number; + } + int Delete(int index, int count = 1 ) + { + if (index + count > _length) + count = _length - index; + if (count > 0) + { + MoveItems(index, index + count); + _length -= count; + } + return _length; + } +}; + +template +CStringBase operator+(const CStringBase& s1, const CStringBase& s2) +{ + CStringBase result(s1); + result += s2; + return result; +} + +template +CStringBase operator+(const CStringBase& s, T c) +{ + CStringBase result(s); + result += c; + return result; +} + +template +CStringBase operator+(T c, const CStringBase& s) +{ + CStringBase result(c); + result += s; + return result; +} + +template +CStringBase operator+(const CStringBase& s, const T * chars) +{ + CStringBase result(s); + result += chars; + return result; +} + +template +CStringBase operator+(const T * chars, const CStringBase& s) +{ + CStringBase result(chars); + result += s; + return result; +} + +template +bool operator==(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) == 0); } + +template +bool operator<(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) < 0); } + +template +bool operator==(const T *s1, const CStringBase& s2) + { return (s2.Compare(s1) == 0); } + +template +bool operator==(const CStringBase& s1, const T *s2) + { return (s1.Compare(s2) == 0); } + +template +bool operator!=(const CStringBase& s1, const CStringBase& s2) + { return (s1.Compare(s2) != 0); } + +template +bool operator!=(const T *s1, const CStringBase& s2) + { return (s2.Compare(s1) != 0); } + +template +bool operator!=(const CStringBase& s1, const T *s2) + { return (s1.Compare(s2) != 0); } + +typedef CStringBase AString; +typedef CStringBase UString; + +typedef CObjectVector AStringVector; +typedef CObjectVector UStringVector; + +#ifdef _UNICODE + typedef UString CSysString; +#else + typedef AString CSysString; +#endif + +typedef CObjectVector CSysStringVector; + +#endif diff --git a/sp/src/utils/lzma/C/Common/StringConvert.cpp b/sp/src/utils/lzma/C/Common/StringConvert.cpp new file mode 100644 index 00000000..d6d05d6c --- /dev/null +++ b/sp/src/utils/lzma/C/Common/StringConvert.cpp @@ -0,0 +1,93 @@ +// Common/StringConvert.cpp + +#include "StdAfx.h" + +#include "StringConvert.h" + +#ifndef _WIN32 +#include +#endif + +#ifdef _WIN32 +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) +{ + UString resultString; + if(!srcString.IsEmpty()) + { + int numChars = MultiByteToWideChar(codePage, 0, srcString, + srcString.Length(), resultString.GetBuffer(srcString.Length()), + srcString.Length() + 1); + #ifndef _WIN32_WCE + if(numChars == 0) + throw 282228; + #endif + resultString.ReleaseBuffer(numChars); + } + return resultString; +} + +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) +{ + AString resultString; + if(!srcString.IsEmpty()) + { + int numRequiredBytes = srcString.Length() * 2; + int numChars = WideCharToMultiByte(codePage, 0, srcString, + srcString.Length(), resultString.GetBuffer(numRequiredBytes), + numRequiredBytes + 1, NULL, NULL); + #ifndef _WIN32_WCE + if(numChars == 0) + throw 282229; + #endif + resultString.ReleaseBuffer(numChars); + } + return resultString; +} + +#ifndef _WIN32_WCE +AString SystemStringToOemString(const CSysString &srcString) +{ + AString result; + CharToOem(srcString, result.GetBuffer(srcString.Length() * 2)); + result.ReleaseBuffer(); + return result; +} +#endif + +#else + +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage) +{ + UString resultString; + for (int i = 0; i < srcString.Length(); i++) + resultString += wchar_t(srcString[i]); + /* + if(!srcString.IsEmpty()) + { + int numChars = mbstowcs(resultString.GetBuffer(srcString.Length()), srcString, srcString.Length() + 1); + if (numChars < 0) throw "Your environment does not support UNICODE"; + resultString.ReleaseBuffer(numChars); + } + */ + return resultString; +} + +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage) +{ + AString resultString; + for (int i = 0; i < srcString.Length(); i++) + resultString += char(srcString[i]); + /* + if(!srcString.IsEmpty()) + { + int numRequiredBytes = srcString.Length() * 6 + 1; + int numChars = wcstombs(resultString.GetBuffer(numRequiredBytes), srcString, numRequiredBytes); + if (numChars < 0) throw "Your environment does not support UNICODE"; + resultString.ReleaseBuffer(numChars); + } + */ + return resultString; +} + +#endif + diff --git a/sp/src/utils/lzma/C/Common/StringConvert.h b/sp/src/utils/lzma/C/Common/StringConvert.h new file mode 100644 index 00000000..648ca028 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/StringConvert.h @@ -0,0 +1,71 @@ +// Common/StringConvert.h + +#ifndef __COMMON_STRINGCONVERT_H +#define __COMMON_STRINGCONVERT_H + +#include "MyWindows.h" +#include "Common/String.h" +#include "Types.h" + +UString MultiByteToUnicodeString(const AString &srcString, UINT codePage = CP_ACP); +AString UnicodeStringToMultiByte(const UString &srcString, UINT codePage = CP_ACP); + +inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString) + { return unicodeString; } +inline const UString& GetUnicodeString(const UString &unicodeString) + { return unicodeString; } +inline UString GetUnicodeString(const AString &ansiString) + { return MultiByteToUnicodeString(ansiString); } +inline UString GetUnicodeString(const AString &multiByteString, UINT codePage) + { return MultiByteToUnicodeString(multiByteString, codePage); } +inline const wchar_t* GetUnicodeString(const wchar_t* unicodeString, UINT) + { return unicodeString; } +inline const UString& GetUnicodeString(const UString &unicodeString, UINT) + { return unicodeString; } + +inline const char* GetAnsiString(const char* ansiString) + { return ansiString; } +inline const AString& GetAnsiString(const AString &ansiString) + { return ansiString; } +inline AString GetAnsiString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString); } + +inline const char* GetOemString(const char* oemString) + { return oemString; } +inline const AString& GetOemString(const AString &oemString) + { return oemString; } +inline AString GetOemString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString, CP_OEMCP); } + + +#ifdef _UNICODE + inline const wchar_t* GetSystemString(const wchar_t* unicodeString) + { return unicodeString;} + inline const UString& GetSystemString(const UString &unicodeString) + { return unicodeString;} + inline const wchar_t* GetSystemString(const wchar_t* unicodeString, UINT codePage) + { return unicodeString;} + inline const UString& GetSystemString(const UString &unicodeString, UINT codePage) + { return unicodeString;} + inline UString GetSystemString(const AString &multiByteString, UINT codePage) + { return MultiByteToUnicodeString(multiByteString, codePage);} + inline UString GetSystemString(const AString &multiByteString) + { return MultiByteToUnicodeString(multiByteString);} +#else + inline const char* GetSystemString(const char *ansiString) + { return ansiString; } + inline const AString& GetSystemString(const AString &multiByteString, UINT) + { return multiByteString; } + inline const char * GetSystemString(const char *multiByteString, UINT) + { return multiByteString; } + inline AString GetSystemString(const UString &unicodeString) + { return UnicodeStringToMultiByte(unicodeString); } + inline AString GetSystemString(const UString &unicodeString, UINT codePage) + { return UnicodeStringToMultiByte(unicodeString, codePage); } +#endif + +#ifndef _WIN32_WCE +AString SystemStringToOemString(const CSysString &srcString); +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/StringToInt.cpp b/sp/src/utils/lzma/C/Common/StringToInt.cpp new file mode 100644 index 00000000..1fa8ef21 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/StringToInt.cpp @@ -0,0 +1,68 @@ +// Common/StringToInt.cpp + +#include "StdAfx.h" + +#include "StringToInt.h" + +UInt64 ConvertStringToUInt64(const char *s, const char **end) +{ + UInt64 result = 0; + while(true) + { + char c = *s; + if (c < '0' || c > '9') + { + if (end != NULL) + *end = s; + return result; + } + result *= 10; + result += (c - '0'); + s++; + } +} + +UInt64 ConvertOctStringToUInt64(const char *s, const char **end) +{ + UInt64 result = 0; + while(true) + { + char c = *s; + if (c < '0' || c > '7') + { + if (end != NULL) + *end = s; + return result; + } + result <<= 3; + result += (c - '0'); + s++; + } +} + + +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end) +{ + UInt64 result = 0; + while(true) + { + wchar_t c = *s; + if (c < '0' || c > '9') + { + if (end != NULL) + *end = s; + return result; + } + result *= 10; + result += (c - '0'); + s++; + } +} + + +Int64 ConvertStringToInt64(const char *s, const char **end) +{ + if (*s == '-') + return -(Int64)ConvertStringToUInt64(s + 1, end); + return ConvertStringToUInt64(s, end); +} diff --git a/sp/src/utils/lzma/C/Common/StringToInt.h b/sp/src/utils/lzma/C/Common/StringToInt.h new file mode 100644 index 00000000..bb971f62 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/StringToInt.h @@ -0,0 +1,17 @@ +// Common/StringToInt.h + +#ifndef __COMMON_STRINGTOINT_H +#define __COMMON_STRINGTOINT_H + +#include +#include "Types.h" + +UInt64 ConvertStringToUInt64(const char *s, const char **end); +UInt64 ConvertOctStringToUInt64(const char *s, const char **end); +UInt64 ConvertStringToUInt64(const wchar_t *s, const wchar_t **end); + +Int64 ConvertStringToInt64(const char *s, const char **end); + +#endif + + diff --git a/sp/src/utils/lzma/C/Common/Types.h b/sp/src/utils/lzma/C/Common/Types.h new file mode 100644 index 00000000..b5befd3b --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Types.h @@ -0,0 +1,66 @@ +// Common/Types.h + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // warning C4127: conditional expression is constant +#pragma warning(disable : 4706) // warning C4706: assignment within conditional expression +#pragma warning(disable : 4100) // warning C4100: unreferenced formal parameter +//#pragma warning(disable : 4312) // warning C4312: conversion from 'unsigned int' to 'LPSTR' of greater size +#pragma warning(disable : 4244) // warning C4244: 'initializing' : conversion from '__w64 int' to 'UInt32', possible loss of data +#pragma warning(disable : 4267) // warning C4267: 'conversion from 'size_t' to 'UInt32', possible loss of data +#endif + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_INT16_DEFINED +#define _7ZIP_INT16_DEFINED +typedef short Int16; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_INT32_DEFINED +#define _7ZIP_INT32_DEFINED +typedef int Int32; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +typedef unsigned int UInt32; +#endif + +#ifdef _MSC_VER + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED +typedef __int64 Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +typedef unsigned __int64 UInt64; +#endif + +#else + +#ifndef _7ZIP_INT64_DEFINED +#define _7ZIP_INT64_DEFINED +typedef long long int Int64; +#endif + +#ifndef _7ZIP_UINT64_DEFINED +#define _7ZIP_UINT64_DEFINED +typedef unsigned long long int UInt64; +#endif + +#endif + +#endif diff --git a/sp/src/utils/lzma/C/Common/Vector.cpp b/sp/src/utils/lzma/C/Common/Vector.cpp new file mode 100644 index 00000000..cb3d8752 --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Vector.cpp @@ -0,0 +1,74 @@ +// Common/Vector.cpp + +#include "StdAfx.h" + +#include + +#include "Vector.h" + +CBaseRecordVector::~CBaseRecordVector() + { delete []((unsigned char *)_items); } +void CBaseRecordVector::Clear() + { DeleteFrom(0); } +void CBaseRecordVector::DeleteBack() + { Delete(_size - 1); } +void CBaseRecordVector::DeleteFrom(int index) + { Delete(index, _size - index); } + +void CBaseRecordVector::ReserveOnePosition() +{ + if(_size != _capacity) + return; + int delta; + if (_capacity > 64) + delta = _capacity / 2; + else if (_capacity > 8) + delta = 8; + else + delta = 4; + Reserve(_capacity + delta); +} + +void CBaseRecordVector::Reserve(int newCapacity) +{ + if(newCapacity <= _capacity) + return; + /* + #ifndef _DEBUG + static const unsigned int kMaxVectorSize = 0xF0000000; + if(newCapacity < _size || + ((unsigned int )newCapacity * (unsigned int )_itemSize) > kMaxVectorSize) + throw 1052354; + #endif + */ + unsigned char *p = new unsigned char[newCapacity * _itemSize]; + int numRecordsToMove = _capacity; + memmove(p, _items, _itemSize * numRecordsToMove); + delete [](unsigned char *)_items; + _items = p; + _capacity = newCapacity; +} + +void CBaseRecordVector::MoveItems(int destIndex, int srcIndex) +{ + memmove(((unsigned char *)_items) + destIndex * _itemSize, + ((unsigned char *)_items) + srcIndex * _itemSize, + _itemSize * (_size - srcIndex)); +} + +void CBaseRecordVector::InsertOneItem(int index) +{ + ReserveOnePosition(); + MoveItems(index + 1, index); + _size++; +} + +void CBaseRecordVector::Delete(int index, int num) +{ + TestIndexAndCorrectNum(index, num); + if (num > 0) + { + MoveItems(index, index + num); + _size -= num; + } +} diff --git a/sp/src/utils/lzma/C/Common/Vector.h b/sp/src/utils/lzma/C/Common/Vector.h new file mode 100644 index 00000000..210c385e --- /dev/null +++ b/sp/src/utils/lzma/C/Common/Vector.h @@ -0,0 +1,228 @@ +// Common/Vector.h + +#ifndef __COMMON_VECTOR_H +#define __COMMON_VECTOR_H + +#include "Defs.h" + +class CBaseRecordVector +{ + void MoveItems(int destIndex, int srcIndex); +protected: + int _capacity; + int _size; + void *_items; + size_t _itemSize; + + void ReserveOnePosition(); + void InsertOneItem(int index); + void TestIndexAndCorrectNum(int index, int &num) const + { if (index + num > _size) num = _size - index; } +public: + CBaseRecordVector(size_t itemSize): + _capacity(0), _size(0), _items(0), _itemSize(itemSize) {} + virtual ~CBaseRecordVector(); + int Size() const { return _size; } + bool IsEmpty() const { return (_size == 0); } + void Reserve(int newCapacity); + virtual void Delete(int index, int num = 1); + void Clear(); + void DeleteFrom(int index); + void DeleteBack(); +}; + +template +class CRecordVector: public CBaseRecordVector +{ +public: + CRecordVector():CBaseRecordVector(sizeof(T)){}; + CRecordVector(const CRecordVector &v): + CBaseRecordVector(sizeof(T)) { *this = v;} + CRecordVector& operator=(const CRecordVector &v) + { + Clear(); + return (*this += v); + } + CRecordVector& operator+=(const CRecordVector &v) + { + int size = v.Size(); + Reserve(Size() + size); + for(int i = 0; i < size; i++) + Add(v[i]); + return *this; + } + int Add(T item) + { + ReserveOnePosition(); + ((T *)_items)[_size] = item; + return _size++; + } + void Insert(int index, T item) + { + InsertOneItem(index); + ((T *)_items)[index] = item; + } + // T* GetPointer() const { return (T*)_items; } + // operator const T *() const { return _items; }; + const T& operator[](int index) const { return ((T *)_items)[index]; } + T& operator[](int index) { return ((T *)_items)[index]; } + const T& Front() const { return operator[](0); } + T& Front() { return operator[](0); } + const T& Back() const { return operator[](_size - 1); } + T& Back() { return operator[](_size - 1); } + + void Swap(int i, int j) + { + T temp = operator[](i); + operator[](i) = operator[](j); + operator[](j) = temp; + } + + int FindInSorted(const T& item) const + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + + void Sort(int left, int right) + { + if (right - left < 2) + return; + Swap(left, (left + right) / 2); + int last = left; + for (int i = left; i < right; i++) + if (operator[](i) < operator[](left)) + Swap(++last, i); + Swap(left, last); + Sort(left, last); + Sort(last + 1, right); + } + void Sort() { Sort(0, Size()); } + void Sort(int left, int right, int (*compare)(const T*, const T*, void *), void *param) + { + if (right - left < 2) + return; + Swap(left, (left + right) / 2); + int last = left; + for (int i = left; i < right; i++) + if (compare(&operator[](i), &operator[](left), param) < 0) + Swap(++last, i); + Swap(left, last); + Sort(left, last, compare, param); + Sort(last + 1, right, compare, param); + } + + void Sort(int (*compare)(const T*, const T*, void *), void *param) + { + Sort(0, Size(), compare, param); + } +}; + +typedef CRecordVector CIntVector; +typedef CRecordVector CUIntVector; +typedef CRecordVector CBoolVector; +typedef CRecordVector CByteVector; +typedef CRecordVector CPointerVector; + +template +class CObjectVector: public CPointerVector +{ +public: + CObjectVector(){}; + ~CObjectVector() { Clear(); } + CObjectVector(const CObjectVector &objectVector) + { *this = objectVector; } + CObjectVector& operator=(const CObjectVector &objectVector) + { + Clear(); + return (*this += objectVector); + } + CObjectVector& operator+=(const CObjectVector &objectVector) + { + int size = objectVector.Size(); + Reserve(Size() + size); + for(int i = 0; i < size; i++) + Add(objectVector[i]); + return *this; + } + const T& operator[](int index) const { return *((T *)CPointerVector::operator[](index)); } + T& operator[](int index) { return *((T *)CPointerVector::operator[](index)); } + T& Front() { return operator[](0); } + const T& Front() const { return operator[](0); } + T& Back() { return operator[](_size - 1); } + const T& Back() const { return operator[](_size - 1); } + int Add(const T& item) + { return CPointerVector::Add(new T(item)); } + void Insert(int index, const T& item) + { CPointerVector::Insert(index, new T(item)); } + virtual void Delete(int index, int num = 1) + { + TestIndexAndCorrectNum(index, num); + for(int i = 0; i < num; i++) + delete (T *)(((void **)_items)[index + i]); + CPointerVector::Delete(index, num); + } + int Find(const T& item) const + { + for(int i = 0; i < Size(); i++) + if (item == (*this)[i]) + return i; + return -1; + } + int FindInSorted(const T& item) const + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + return mid; + if (item < midValue) + right = mid; + else + left = mid + 1; + } + return -1; + } + int AddToSorted(const T& item) + { + int left = 0, right = Size(); + while (left != right) + { + int mid = (left + right) / 2; + const T& midValue = (*this)[mid]; + if (item == midValue) + { + right = mid + 1; + break; + } + if (item < midValue) + right = mid; + else + left = mid + 1; + } + Insert(right, item); + return right; + } + + void Sort(int (*compare)(void *const *, void *const *, void *), void *param) + { CPointerVector::Sort(compare, param); } + + static int CompareObjectItems(void *const *a1, void *const *a2, void *param) + { return MyCompare(*(*((const T **)a1)), *(*((const T **)a2))); } + void Sort() { CPointerVector::Sort(CompareObjectItems, 0); } +}; + +#endif diff --git a/sp/src/utils/lzma/C/Windows/Defs.h b/sp/src/utils/lzma/C/Windows/Defs.h new file mode 100644 index 00000000..c0038d61 --- /dev/null +++ b/sp/src/utils/lzma/C/Windows/Defs.h @@ -0,0 +1,18 @@ +// Windows/Defs.h + +#ifndef __WINDOWS_DEFS_H +#define __WINDOWS_DEFS_H + +inline bool BOOLToBool(BOOL value) + { return (value != FALSE); } + +inline BOOL BoolToBOOL(bool value) + { return (value ? TRUE: FALSE); } + +inline VARIANT_BOOL BoolToVARIANT_BOOL(bool value) + { return (value ? VARIANT_TRUE: VARIANT_FALSE); } + +inline bool VARIANT_BOOLToBool(VARIANT_BOOL value) + { return (value != VARIANT_FALSE); } + +#endif diff --git a/sp/src/utils/lzma/C/Windows/FileIO.cpp b/sp/src/utils/lzma/C/Windows/FileIO.cpp new file mode 100644 index 00000000..203de843 --- /dev/null +++ b/sp/src/utils/lzma/C/Windows/FileIO.cpp @@ -0,0 +1,245 @@ +// Windows/FileIO.cpp + +#include "StdAfx.h" + +#include "FileIO.h" +#include "Defs.h" +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + +#ifndef _UNICODE +extern bool g_IsNT; +#endif + +namespace NWindows { +namespace NFile { +namespace NIO { + +CFileBase::~CFileBase() { Close(); } + +bool CFileBase::Create(LPCTSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + Close(); + _handle = ::CreateFile(fileName, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE) NULL); + return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); +} + +#ifndef _UNICODE +bool CFileBase::Create(LPCWSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) +{ + if (g_IsNT) + { + Close(); + _handle = ::CreateFileW(fileName, desiredAccess, shareMode, + (LPSECURITY_ATTRIBUTES)NULL, creationDisposition, + flagsAndAttributes, (HANDLE) NULL); + return (_fileIsOpen = (_handle != INVALID_HANDLE_VALUE)); + } + return Create(UnicodeStringToMultiByte(fileName, ::AreFileApisANSI() ? CP_ACP : CP_OEMCP), + desiredAccess, shareMode, creationDisposition, flagsAndAttributes); +} +#endif + +bool CFileBase::Close() +{ + if(!_fileIsOpen) + return true; + bool result = BOOLToBool(::CloseHandle(_handle)); + _fileIsOpen = !result; + return result; +} + +bool CFileBase::GetPosition(UInt64 &position) const +{ + return Seek(0, FILE_CURRENT, position); +} + +bool CFileBase::GetLength(UInt64 &length) const +{ + DWORD sizeHigh; + DWORD sizeLow = ::GetFileSize(_handle, &sizeHigh); + if(sizeLow == 0xFFFFFFFF) + if(::GetLastError() != NO_ERROR) + return false; + length = (((UInt64)sizeHigh) << 32) + sizeLow; + return true; +} + +bool CFileBase::Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const +{ + LARGE_INTEGER value; + value.QuadPart = distanceToMove; + value.LowPart = ::SetFilePointer(_handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + if(::GetLastError() != NO_ERROR) + return false; + newPosition = value.QuadPart; + return true; +} + +bool CFileBase::Seek(UInt64 position, UInt64 &newPosition) +{ + return Seek(position, FILE_BEGIN, newPosition); +} + +bool CFileBase::SeekToBegin() +{ + UInt64 newPosition; + return Seek(0, newPosition); +} + +bool CFileBase::SeekToEnd(UInt64 &newPosition) +{ + return Seek(0, FILE_END, newPosition); +} + +bool CFileBase::GetFileInformation(CByHandleFileInfo &fileInfo) const +{ + BY_HANDLE_FILE_INFORMATION winFileInfo; + if(!::GetFileInformationByHandle(_handle, &winFileInfo)) + return false; + fileInfo.Attributes = winFileInfo.dwFileAttributes; + fileInfo.CreationTime = winFileInfo.ftCreationTime; + fileInfo.LastAccessTime = winFileInfo.ftLastAccessTime; + fileInfo.LastWriteTime = winFileInfo.ftLastWriteTime; + fileInfo.VolumeSerialNumber = winFileInfo.dwFileAttributes; + fileInfo.Size = (((UInt64)winFileInfo.nFileSizeHigh) << 32) + winFileInfo.nFileSizeLow; + fileInfo.NumberOfLinks = winFileInfo.nNumberOfLinks; + fileInfo.FileIndex = (((UInt64)winFileInfo.nFileIndexHigh) << 32) + winFileInfo.nFileIndexLow; + return true; +} + +///////////////////////// +// CInFile + +bool CInFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } + +bool CInFile::Open(LPCTSTR fileName) + { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } + +#ifndef _UNICODE +bool CInFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return Create(fileName, GENERIC_READ, shareMode, creationDisposition, flagsAndAttributes); } + +bool CInFile::Open(LPCWSTR fileName) + { return Open(fileName, FILE_SHARE_READ, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL); } +#endif + +// ReadFile and WriteFile functions in Windows have BUG: +// If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) +// from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES +// (Insufficient system resources exist to complete the requested service). + +static UInt32 kChunkSizeMax = (1 << 24); + +bool CInFile::ReadPart(void *data, UInt32 size, UInt32 &processedSize) +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + DWORD processedLoc = 0; + bool res = BOOLToBool(::ReadFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool CInFile::Read(void *data, UInt32 size, UInt32 &processedSize) +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = ReadPart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (void *)((unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +///////////////////////// +// COutFile + +bool COutFile::Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +static inline DWORD GetCreationDisposition(bool createAlways) + { return createAlways? CREATE_ALWAYS: CREATE_NEW; } + +bool COutFile::Open(LPCTSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(LPCTSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +#ifndef _UNICODE + +bool COutFile::Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes) + { return CFileBase::Create(fileName, GENERIC_WRITE, shareMode, creationDisposition, flagsAndAttributes); } + +bool COutFile::Open(LPCWSTR fileName, DWORD creationDisposition) + { return Open(fileName, FILE_SHARE_READ, creationDisposition, FILE_ATTRIBUTE_NORMAL); } + +bool COutFile::Create(LPCWSTR fileName, bool createAlways) + { return Open(fileName, GetCreationDisposition(createAlways)); } + +#endif + +bool COutFile::SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime) + { return BOOLToBool(::SetFileTime(_handle, creationTime, lastAccessTime, lastWriteTime)); } + +bool COutFile::SetLastWriteTime(const FILETIME *lastWriteTime) + { return SetTime(NULL, NULL, lastWriteTime); } + +bool COutFile::WritePart(const void *data, UInt32 size, UInt32 &processedSize) +{ + if (size > kChunkSizeMax) + size = kChunkSizeMax; + DWORD processedLoc = 0; + bool res = BOOLToBool(::WriteFile(_handle, data, size, &processedLoc, NULL)); + processedSize = (UInt32)processedLoc; + return res; +} + +bool COutFile::Write(const void *data, UInt32 size, UInt32 &processedSize) +{ + processedSize = 0; + do + { + UInt32 processedLoc = 0; + bool res = WritePart(data, size, processedLoc); + processedSize += processedLoc; + if (!res) + return false; + if (processedLoc == 0) + return true; + data = (const void *)((const unsigned char *)data + processedLoc); + size -= processedLoc; + } + while (size > 0); + return true; +} + +bool COutFile::SetEndOfFile() { return BOOLToBool(::SetEndOfFile(_handle)); } + +bool COutFile::SetLength(UInt64 length) +{ + UInt64 newPosition; + if(!Seek(length, newPosition)) + return false; + if(newPosition != length) + return false; + return SetEndOfFile(); +} + +}}} diff --git a/sp/src/utils/lzma/C/Windows/FileIO.h b/sp/src/utils/lzma/C/Windows/FileIO.h new file mode 100644 index 00000000..18014844 --- /dev/null +++ b/sp/src/utils/lzma/C/Windows/FileIO.h @@ -0,0 +1,98 @@ +// Windows/FileIO.h + +#ifndef __WINDOWS_FILEIO_H +#define __WINDOWS_FILEIO_H + +#include "../Common/Types.h" + +namespace NWindows { +namespace NFile { +namespace NIO { + +struct CByHandleFileInfo +{ + DWORD Attributes; + FILETIME CreationTime; + FILETIME LastAccessTime; + FILETIME LastWriteTime; + DWORD VolumeSerialNumber; + UInt64 Size; + DWORD NumberOfLinks; + UInt64 FileIndex; +}; + +class CFileBase +{ +protected: + bool _fileIsOpen; + HANDLE _handle; + bool Create(LPCTSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + #ifndef _UNICODE + bool Create(LPCWSTR fileName, DWORD desiredAccess, + DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + #endif + +public: + CFileBase(): _fileIsOpen(false){}; + virtual ~CFileBase(); + + virtual bool Close(); + + bool GetPosition(UInt64 &position) const; + bool GetLength(UInt64 &length) const; + + bool Seek(Int64 distanceToMove, DWORD moveMethod, UInt64 &newPosition) const; + bool Seek(UInt64 position, UInt64 &newPosition); + bool SeekToBegin(); + bool SeekToEnd(UInt64 &newPosition); + + bool GetFileInformation(CByHandleFileInfo &fileInfo) const; +}; + +class CInFile: public CFileBase +{ +public: + bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCTSTR fileName); + #ifndef _UNICODE + bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCWSTR fileName); + #endif + bool ReadPart(void *data, UInt32 size, UInt32 &processedSize); + bool Read(void *data, UInt32 size, UInt32 &processedSize); +}; + +class COutFile: public CFileBase +{ + // DWORD m_CreationDisposition; +public: + // COutFile(): m_CreationDisposition(CREATE_NEW){}; + bool Open(LPCTSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCTSTR fileName, DWORD creationDisposition); + bool Create(LPCTSTR fileName, bool createAlways); + + #ifndef _UNICODE + bool Open(LPCWSTR fileName, DWORD shareMode, DWORD creationDisposition, DWORD flagsAndAttributes); + bool Open(LPCWSTR fileName, DWORD creationDisposition); + bool Create(LPCWSTR fileName, bool createAlways); + #endif + + /* + void SetOpenCreationDisposition(DWORD creationDisposition) + { m_CreationDisposition = creationDisposition; } + void SetOpenCreationDispositionCreateAlways() + { m_CreationDisposition = CREATE_ALWAYS; } + */ + + bool SetTime(const FILETIME *creationTime, const FILETIME *lastAccessTime, const FILETIME *lastWriteTime); + bool SetLastWriteTime(const FILETIME *lastWriteTime); + bool WritePart(const void *data, UInt32 size, UInt32 &processedSize); + bool Write(const void *data, UInt32 size, UInt32 &processedSize); + bool SetEndOfFile(); + bool SetLength(UInt64 length); +}; + +}}} + +#endif diff --git a/sp/src/utils/lzma/C/Windows/StdAfx.h b/sp/src/utils/lzma/C/Windows/StdAfx.h new file mode 100644 index 00000000..e7924c8f --- /dev/null +++ b/sp/src/utils/lzma/C/Windows/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../Common/MyWindows.h" +#include "../Common/NewHandler.h" + +#endif