mirror of
https://github.com/ZDoom/ZDRay.git
synced 2024-11-27 14:12:38 +00:00
Initial import
This commit is contained in:
parent
ddd769c695
commit
e9356ea255
49 changed files with 21219 additions and 0 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
/Debug
|
||||
/*.ncb
|
||||
/*.suo
|
||||
/debug_vs2005
|
||||
/Release_vs2005
|
||||
/build
|
235
CMakeLists.txt
Normal file
235
CMakeLists.txt
Normal file
|
@ -0,0 +1,235 @@
|
|||
cmake_minimum_required( VERSION 2.4 )
|
||||
if( COMMAND cmake_policy )
|
||||
cmake_policy( SET CMP0003 NEW )
|
||||
endif( COMMAND cmake_policy )
|
||||
|
||||
include( CheckFunctionExists )
|
||||
include( CheckCXXCompilerFlag )
|
||||
|
||||
project( ZDRay )
|
||||
|
||||
IF( NOT CMAKE_BUILD_TYPE )
|
||||
SET( CMAKE_BUILD_TYPE Debug CACHE STRING
|
||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE )
|
||||
ENDIF( NOT CMAKE_BUILD_TYPE )
|
||||
|
||||
set( SSE_MATTERS NO )
|
||||
|
||||
# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it.
|
||||
if( CMAKE_SIZEOF_VOID_P MATCHES "4" )
|
||||
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
|
||||
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
|
||||
if( CAN_DO_MFPMATH )
|
||||
set( SSE1_ENABLE "-msse -mfpmath=sse" )
|
||||
set( SSE2_ENABLE "-msse2 -mfpmath=sse" )
|
||||
set( SSE_MATTERS YES )
|
||||
elseif( CAN_DO_ARCHSSE2 )
|
||||
set( SSE1_ENABLE -arch:SSE )
|
||||
set( SSE2_ENABLE -arch:SSE2 )
|
||||
set( SSE_MATTERS YES )
|
||||
endif( CAN_DO_MFPMATH )
|
||||
endif( CMAKE_SIZEOF_VOID_P MATCHES "4" )
|
||||
|
||||
if( SSE_MATTERS )
|
||||
if( WIN32 )
|
||||
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
|
||||
else( WIN32 )
|
||||
CHECK_FUNCTION_EXISTS(mprotect HAVE_MPROTECT)
|
||||
if( HAVE_MPROTECT )
|
||||
set( BACKPATCH 1 CACHE BOOL "Enable backpatching." )
|
||||
else( HAVE_MPROTECT )
|
||||
set( BACKPATCH 0 )
|
||||
endif( HAVE_MPROTECT )
|
||||
endif( WIN32 )
|
||||
set( FULL_SSE2 0 CACHE BOOL "Use SSE2 math everywhere." )
|
||||
set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." )
|
||||
else( SSE_MATTERS )
|
||||
set( BACKPATCH 0 )
|
||||
endif( SSE_MATTERS )
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
set( GPROF 0 CACHE BOOL "Enable profiling with gprof for Debug and RelWithDebInfo build types." )
|
||||
set( PROFILE 0 CACHE INT "1=Generate profile coverage info, 2=Use it" )
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
find_package( ZLIB )
|
||||
|
||||
if( MSVC )
|
||||
# Eliminate unreferenced functions and data
|
||||
# Perform identical COMDAT folding
|
||||
set( REL_LINKER_FLAGS "/opt:ref /opt:icf /nodefaultlib:msvcrt" )
|
||||
|
||||
# String pooling
|
||||
# Function-level linking
|
||||
# Disable run-time type information
|
||||
set( ALL_C_FLAGS "/GF /Gy /GR-" )
|
||||
|
||||
# Avoid CRT DLL dependancies in release builds
|
||||
set( REL_C_FLAGS "/MT" )
|
||||
|
||||
# Disable warnings for unsecure CRT functions from VC8+
|
||||
if( MSVC_VERSION GREATER 1399 )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} /wd4996" )
|
||||
endif( MSVC_VERSION GREATER 1399 )
|
||||
|
||||
# The CMake configurations set /GR and /MD by default, which conflict with our settings.
|
||||
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} )
|
||||
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL} )
|
||||
string(REPLACE "/MD " " " CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} )
|
||||
string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} )
|
||||
string(REPLACE "/MD " " " CMAKE_C_FLAGS_MINSIZEREL ${CMAKE_C_FLAGS_MINSIZEREL} )
|
||||
string(REPLACE "/MD " " " CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO} )
|
||||
string(REPLACE " /GR" " " CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} )
|
||||
endif( MSVC )
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -ffast-math -pipe" )
|
||||
if( GPROF )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -pg -g" )
|
||||
else( GPROF )
|
||||
set( REL_C_FLAGS "${REL_C_FLAGS} -fomit-frame-pointer" )
|
||||
endif( GPROF )
|
||||
if( PROFILE EQUAL 1 )
|
||||
message( STATUS "Generating profile coverage information" )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-generate" )
|
||||
set( PROF_LIB "gcov" )
|
||||
elseif( PROFILE EQUAL 2 )
|
||||
message( STATUS "Using profile coverage information" )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -fprofile-use" )
|
||||
endif( PROFILE EQUAL 1 )
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
#if( WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||
# set( ALL_C_FLAGS "${ALL_C_FLAGS} -Wno-deprecated-declarations -Wno-format" )
|
||||
#endif( WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
|
||||
|
||||
if( ZLIB_FOUND )
|
||||
message( STATUS "Using system zlib" )
|
||||
else( ZLIB_FOUND )
|
||||
message( STATUS "Using internal zlib" )
|
||||
add_subdirectory( zlib )
|
||||
set( ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib )
|
||||
set( ZLIB_LIBRARIES z )
|
||||
set( ZLIB_LIBRARY z )
|
||||
endif( ZLIB_FOUND )
|
||||
|
||||
if( BACKPATCH )
|
||||
add_definitions( -DBACKPATCH )
|
||||
endif( BACKPATCH )
|
||||
|
||||
CHECK_FUNCTION_EXISTS( stricmp STRICMP_EXISTS )
|
||||
if( NOT STRICMP_EXISTS )
|
||||
add_definitions( -Dstricmp=strcasecmp )
|
||||
endif( NOT STRICMP_EXISTS )
|
||||
|
||||
CHECK_FUNCTION_EXISTS( strnicmp STRNICMP_EXISTS )
|
||||
if( NOT STRNICMP_EXISTS )
|
||||
add_definitions( -Dstrnicmp=strncasecmp )
|
||||
endif( NOT STRNICMP_EXISTS )
|
||||
|
||||
set( ZDRAY_LIBS "${ZLIB_LIBRARIES}" )
|
||||
set( SOURCES
|
||||
src/commandline/main.cpp
|
||||
src/commandline/getopt.c
|
||||
src/commandline/getopt1.c
|
||||
src/blockmapbuilder/blockmapbuilder.cpp
|
||||
src/level/level.cpp
|
||||
src/level/level_udmf.cpp
|
||||
src/parse/sc_man.cpp
|
||||
src/wad/wad.cpp
|
||||
src/nodebuilder/nodebuild.cpp
|
||||
src/nodebuilder/nodebuild_events.cpp
|
||||
src/nodebuilder/nodebuild_extract.cpp
|
||||
src/nodebuilder/nodebuild_gl.cpp
|
||||
src/nodebuilder/nodebuild_utility.cpp
|
||||
src/nodebuilder/nodebuild_classify_nosse2.cpp
|
||||
)
|
||||
if( WIN32 )
|
||||
set( SOURCES "${SOURCES}" src/viewer/view.cpp )
|
||||
else( WIN32 )
|
||||
add_definitions( -DNO_MAP_VIEWER )
|
||||
endif( WIN32 )
|
||||
|
||||
set( HEADERS
|
||||
src/commandline/getopt.h
|
||||
src/blockmapbuilder/blockmapbuilder.h
|
||||
src/nodebuilder/nodebuild.h
|
||||
src/level/doomdata.h
|
||||
src/level/level.h
|
||||
src/level/workdata.h
|
||||
src/parse/sc_man.h
|
||||
src/wad/wad.h
|
||||
src/platform/windows/resource.h
|
||||
src/framework/tarray.h
|
||||
src/framework/templates.h
|
||||
src/framework/zdray.h
|
||||
src/framework/xs_Float.h )
|
||||
|
||||
if( SSE_MATTERS )
|
||||
if( FULL_SSE2 )
|
||||
message( STATUS "Using SSE2 math everywhere." )
|
||||
# Building everything with SSE2 is much like disabling it, in that we
|
||||
# need not check for its existance while running.
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE ${SSE2_ENABLE}" )
|
||||
else( FULL_SSE2 )
|
||||
if( SSE )
|
||||
message( STATUS "Using SSE math for ClassifyLine only." )
|
||||
set( SOURCES ${SOURCES} src/nodebuilder/nodebuild_classify_sse1.cpp src/nodebuilder/nodebuild_classify_sse2.cpp )
|
||||
set_source_files_properties( src/nodebuilder/nodebuild_classify_sse1.cpp PROPERTIES COMPILE_FLAGS "${SSE1_ENABLE}" )
|
||||
set_source_files_properties( src/nodebuilder/nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "${SSE2_ENABLE}" )
|
||||
else( SSE )
|
||||
message( STATUS "SSE math is completely disabled." )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" )
|
||||
endif( SSE )
|
||||
endif( FULL_SSE2 )
|
||||
else( SSE_MATTERS )
|
||||
set( ALL_C_FLAGS "${ALL_C_FLAGS} -DDISABLE_SSE" )
|
||||
endif( SSE_MATTERS )
|
||||
|
||||
if( WIN32 )
|
||||
set( ZDRAY_LIBS ${ZDRAY_LIBS} user32 gdi32 )
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
# CMake is not set up to compile and link rc files with GCC. :(
|
||||
add_custom_command( OUTPUT zdray-rc.o
|
||||
COMMAND windres -o zdray-rc.o -i ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/resource.rc
|
||||
DEPENDS resource.rc )
|
||||
set( SOURCES ${SOURCES} zdray-rc.o )
|
||||
else( CMAKE_COMPILER_IS_GNUCXX )
|
||||
set( SOURCES ${SOURCES} src/platform/windows/resource.rc )
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
||||
endif( WIN32 )
|
||||
|
||||
|
||||
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${REL_LINKER_FLAGS}" )
|
||||
set( CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} ${REL_LINKER_FLAGS}" )
|
||||
set( CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${REL_LINKER_FLAGS}" )
|
||||
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ALL_C_FLAGS}" )
|
||||
set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
|
||||
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALL_C_FLAGS}" )
|
||||
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_C_FLAGS}" )
|
||||
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEB_C_FLAGS} -D_DEBUG" )
|
||||
|
||||
add_executable( zdray ${SOURCES} ${HEADERS} )
|
||||
target_link_libraries( zdray ${ZDRAY_LIBS} ${PROF_LIB} )
|
||||
include_directories( src "${ZLIB_INCLUDE_DIR}" )
|
||||
|
||||
source_group("Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/.+")
|
||||
source_group("Sources\\BlockmapBuilder" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/blockmapbuilder/.+")
|
||||
source_group("Sources\\Commandline" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/commandline/.+")
|
||||
source_group("Sources\\Framework" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/framework/.+")
|
||||
source_group("Sources\\Level" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/level/.+")
|
||||
source_group("Sources\\NodeBuilder" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/nodebuilder/.+")
|
||||
source_group("Sources\\Parse" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/parse/.+")
|
||||
source_group("Sources\\Platform" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/platform/.+")
|
||||
source_group("Sources\\Platform\\Windows" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/.+")
|
||||
source_group("Sources\\Viewer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/viewer/.+")
|
||||
source_group("Sources\\Wad" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/src/wad/.+")
|
340
COPYING
Normal file
340
COPYING
Normal file
|
@ -0,0 +1,340 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
442
src/blockmapbuilder/blockmapbuilder.cpp
Normal file
442
src/blockmapbuilder/blockmapbuilder.cpp
Normal file
|
@ -0,0 +1,442 @@
|
|||
/*
|
||||
Routines for building a Doom map's BLOCKMAP lump.
|
||||
Copyright (C) 2002 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "framework/templates.h"
|
||||
#include "framework/tarray.h"
|
||||
#include "blockmapbuilder/blockmapbuilder.h"
|
||||
|
||||
#undef BLOCK_TEST
|
||||
|
||||
FBlockmapBuilder::FBlockmapBuilder (FLevel &level)
|
||||
: Level (level)
|
||||
{
|
||||
BuildBlockmap ();
|
||||
}
|
||||
|
||||
#ifdef BLOCK_TEST
|
||||
inline int PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
|
||||
{
|
||||
int foo = DMulScale32 ((y-y1) << 16, dx<<16, (x1-x)<<16, (dy)<<16);
|
||||
//return abs(foo) < 4 ? 0 : foo;
|
||||
return foo > 0;
|
||||
}
|
||||
|
||||
int BoxOnSide (int bx1, int by1, int bx2, int by2,
|
||||
int lx1, int ly1, int lx2, int ly2)
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
|
||||
if (ly1 == ly2)
|
||||
{
|
||||
p1 = by1 > ly1;
|
||||
p2 = by2 > ly1;
|
||||
}
|
||||
else if (lx1 == lx2)
|
||||
{
|
||||
p1 = bx2 < lx1;
|
||||
p2 = bx1 < lx1;
|
||||
}
|
||||
else if (((ly2-ly1) ^ (lx2-lx1)) >= 0)
|
||||
{
|
||||
p1 = PointOnSide (bx1, by1, lx1, ly1, lx2-lx1, ly2-ly1);
|
||||
p2 = PointOnSide (bx2, by2, lx1, ly1, lx2-lx1, ly2-ly1);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = PointOnSide (bx2, by1, lx1, ly1, lx2-lx1, ly2-ly1);
|
||||
p2 = PointOnSide (bx1, by2, lx1, ly1, lx2-lx1, ly2-ly1);
|
||||
}
|
||||
|
||||
return (p1 == p2) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
WORD *FBlockmapBuilder::GetBlockmap (int &size)
|
||||
{
|
||||
#ifdef BLOCK_TEST
|
||||
FILE *f = fopen ("blockmap.lmp", "rb");
|
||||
if (f)
|
||||
{
|
||||
size_t fsize;
|
||||
fseek (f, 0, SEEK_END);
|
||||
fsize = ftell (f);
|
||||
fseek (f, 0, SEEK_SET);
|
||||
short *stuff = (short *)alloca (fsize);
|
||||
fread (stuff, 2, fsize/2, f);
|
||||
fclose (f);
|
||||
|
||||
if ((WORD)stuff[0] != BlockMap[0] ||
|
||||
(WORD)stuff[1] != BlockMap[1] ||
|
||||
(WORD)stuff[2] != BlockMap[2] ||
|
||||
(WORD)stuff[3] != BlockMap[3])
|
||||
{
|
||||
printf ("different blockmap sizes\n");
|
||||
goto notest;
|
||||
}
|
||||
int i, x, y;
|
||||
|
||||
for (i = 0; i < stuff[2] * stuff[3]; ++i)
|
||||
{
|
||||
WORD i1, i2;
|
||||
i1 = stuff[4+i] + 1;
|
||||
while (stuff[i1] != -1)
|
||||
{
|
||||
i2 = BlockMap[4+i] + 1;
|
||||
while (BlockMap[i2] != 0xffff)
|
||||
{
|
||||
if (BlockMap[i2] == stuff[i1])
|
||||
break;
|
||||
i2++;
|
||||
}
|
||||
if (BlockMap[i2] == 0xffff)
|
||||
{
|
||||
y = i / stuff[2];
|
||||
x = i - y * stuff[2];
|
||||
int l = stuff[i1];
|
||||
// If a diagonal line passed near a block (within 2 or 4 units, I think),
|
||||
// it could be considered in the block even if it's really outside it,
|
||||
// so if things differ, see if DoomBSP was at fault.
|
||||
if (BoxOnSide (
|
||||
stuff[0] + 128*x, stuff[1] + 128*y,
|
||||
stuff[0] + 128*x + 127, stuff[1] + 128*y + 127,
|
||||
Vertices[Lines[l].v1].x, Vertices[Lines[l].v1].y,
|
||||
Vertices[Lines[l].v2].x, Vertices[Lines[l].v2].y))
|
||||
{
|
||||
printf ("not in cell %4d: line %4d [%2d,%2d] : (%5d,%5d)-(%5d,%5d)\n", i, stuff[i1],
|
||||
x, y,
|
||||
stuff[0] + 128*x, stuff[1] + 128*y,
|
||||
stuff[0] + 128*x + 127, stuff[1] + 128*y + 127
|
||||
);
|
||||
}
|
||||
}
|
||||
i1 ++;
|
||||
}
|
||||
i1 = BlockMap[4+i] + 1;
|
||||
while (BlockMap[i1] != 0xffff)
|
||||
{
|
||||
i2 = stuff[4+i] + 1;
|
||||
while (stuff[i2] != -1)
|
||||
{
|
||||
if ((WORD)stuff[i2] == BlockMap[i1])
|
||||
break;
|
||||
i2++;
|
||||
}
|
||||
if (stuff[i2] == -1)
|
||||
{
|
||||
y = i / BlockMap[2];
|
||||
x = i - y * BlockMap[2];
|
||||
int l = BlockMap[i1];
|
||||
if (!BoxOnSide (
|
||||
(short)BlockMap[0] + 128*x, (short)BlockMap[1] + 128*y,
|
||||
(short)BlockMap[0] + 128*x + 127, (short)BlockMap[1] + 128*y + 127,
|
||||
Vertices[Lines[l].v1].x, Vertices[Lines[l].v1].y,
|
||||
Vertices[Lines[l].v2].x, Vertices[Lines[l].v2].y))
|
||||
{
|
||||
printf ("EXT in cell %4d: line %4d [%2d,%2d] : (%5d,%5d)-(%5d,%5d)\n", i, (short)BlockMap[i1],
|
||||
x, y,
|
||||
(short)BlockMap[0] + 128*x, (short)BlockMap[1] + 128*y,
|
||||
(short)BlockMap[0] + 128*x + 127, (short)BlockMap[1] + 128*y + 127
|
||||
);
|
||||
}
|
||||
}
|
||||
i1 ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
notest:
|
||||
#endif
|
||||
size = BlockMap.Size();
|
||||
return &BlockMap[0];
|
||||
}
|
||||
|
||||
void FBlockmapBuilder::BuildBlockmap ()
|
||||
{
|
||||
TArray<WORD> *BlockLists, *block, *endblock;
|
||||
WORD adder;
|
||||
int bmapwidth, bmapheight;
|
||||
int minx, maxx, miny, maxy;
|
||||
WORD line;
|
||||
|
||||
if (Level.NumVertices <= 0)
|
||||
return;
|
||||
|
||||
// Get map extents for the blockmap
|
||||
minx = Level.MinX >> FRACBITS;
|
||||
miny = Level.MinY >> FRACBITS;
|
||||
maxx = Level.MaxX >> FRACBITS;
|
||||
maxy = Level.MaxY >> FRACBITS;
|
||||
|
||||
/*
|
||||
// DoomBSP did this to give the map a margin when drawing it
|
||||
// in a window on NeXT machines. It's not necessary, but
|
||||
// it lets me verify my output against DoomBSP's for correctness.
|
||||
minx -= 8;
|
||||
miny -= 8;
|
||||
maxx += 8;
|
||||
maxy += 8;
|
||||
|
||||
// And DeepBSP seems to do this.
|
||||
minx &= ~7;
|
||||
miny &= ~7;
|
||||
*/
|
||||
bmapwidth = ((maxx - minx) >> BLOCKBITS) + 1;
|
||||
bmapheight = ((maxy - miny) >> BLOCKBITS) + 1;
|
||||
|
||||
adder = WORD(minx); BlockMap.Push (adder);
|
||||
adder = WORD(miny); BlockMap.Push (adder);
|
||||
adder = WORD(bmapwidth); BlockMap.Push (adder);
|
||||
adder = WORD(bmapheight); BlockMap.Push (adder);
|
||||
|
||||
BlockLists = new TArray<WORD>[bmapwidth * bmapheight];
|
||||
|
||||
for (line = 0; line < Level.NumLines(); ++line)
|
||||
{
|
||||
int x1 = Level.Vertices[Level.Lines[line].v1].x >> FRACBITS;
|
||||
int y1 = Level.Vertices[Level.Lines[line].v1].y >> FRACBITS;
|
||||
int x2 = Level.Vertices[Level.Lines[line].v2].x >> FRACBITS;
|
||||
int y2 = Level.Vertices[Level.Lines[line].v2].y >> FRACBITS;
|
||||
int dx = x2 - x1;
|
||||
int dy = y2 - y1;
|
||||
int bx = (x1 - minx) >> BLOCKBITS;
|
||||
int by = (y1 - miny) >> BLOCKBITS;
|
||||
int bx2 = (x2 - minx) >> BLOCKBITS;
|
||||
int by2 = (y2 - miny) >> BLOCKBITS;
|
||||
|
||||
block = &BlockLists[bx + by * bmapwidth];
|
||||
endblock = &BlockLists[bx2 + by2 * bmapwidth];
|
||||
|
||||
if (block == endblock) // Single block
|
||||
{
|
||||
block->Push (line);
|
||||
}
|
||||
else if (by == by2) // Horizontal line
|
||||
{
|
||||
if (bx > bx2)
|
||||
{
|
||||
swap (block, endblock);
|
||||
}
|
||||
do
|
||||
{
|
||||
block->Push (line);
|
||||
block += 1;
|
||||
} while (block <= endblock);
|
||||
}
|
||||
else if (bx == bx2) // Vertical line
|
||||
{
|
||||
if (by > by2)
|
||||
{
|
||||
swap (block, endblock);
|
||||
}
|
||||
do
|
||||
{
|
||||
block->Push (line);
|
||||
block += bmapwidth;
|
||||
} while (block <= endblock);
|
||||
}
|
||||
else // Diagonal line
|
||||
{
|
||||
int xchange = (dx < 0) ? -1 : 1;
|
||||
int ychange = (dy < 0) ? -1 : 1;
|
||||
int ymove = ychange * bmapwidth;
|
||||
int adx = abs (dx);
|
||||
int ady = abs (dy);
|
||||
|
||||
if (adx == ady) // 45 degrees
|
||||
{
|
||||
int xb = (x1 - minx) & (BLOCKSIZE-1);
|
||||
int yb = (y1 - miny) & (BLOCKSIZE-1);
|
||||
if (dx < 0)
|
||||
{
|
||||
xb = BLOCKSIZE-xb;
|
||||
}
|
||||
if (dy < 0)
|
||||
{
|
||||
yb = BLOCKSIZE-yb;
|
||||
}
|
||||
if (xb < yb)
|
||||
adx--;
|
||||
}
|
||||
if (adx >= ady) // X-major
|
||||
{
|
||||
int yadd = dy < 0 ? -1 : BLOCKSIZE;
|
||||
do
|
||||
{
|
||||
int stop = (Scale ((by << BLOCKBITS) + yadd - (y1 - miny), dx, dy) + (x1 - minx)) >> BLOCKBITS;
|
||||
while (bx != stop)
|
||||
{
|
||||
block->Push (line);
|
||||
block += xchange;
|
||||
bx += xchange;
|
||||
}
|
||||
block->Push (line);
|
||||
block += ymove;
|
||||
by += ychange;
|
||||
} while (by != by2);
|
||||
while (block != endblock)
|
||||
{
|
||||
block->Push (line);
|
||||
block += xchange;
|
||||
}
|
||||
block->Push (line);
|
||||
}
|
||||
else // Y-major
|
||||
{
|
||||
int xadd = dx < 0 ? -1 : BLOCKSIZE;
|
||||
do
|
||||
{
|
||||
int stop = (Scale ((bx << BLOCKBITS) + xadd - (x1 - minx), dy, dx) + (y1 - miny)) >> BLOCKBITS;
|
||||
while (by != stop)
|
||||
{
|
||||
block->Push (line);
|
||||
block += ymove;
|
||||
by += ychange;
|
||||
}
|
||||
block->Push (line);
|
||||
block += xchange;
|
||||
bx += xchange;
|
||||
} while (bx != bx2);
|
||||
while (block != endblock)
|
||||
{
|
||||
block->Push (line);
|
||||
block += ymove;
|
||||
}
|
||||
block->Push (line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlockMap.Reserve (bmapwidth * bmapheight);
|
||||
CreatePackedBlockmap (BlockLists, bmapwidth, bmapheight);
|
||||
delete[] BlockLists;
|
||||
}
|
||||
|
||||
void FBlockmapBuilder::CreateUnpackedBlockmap (TArray<WORD> *blocks, int bmapwidth, int bmapheight)
|
||||
{
|
||||
TArray<WORD> *block;
|
||||
WORD zero = 0;
|
||||
WORD terminator = 0xffff;
|
||||
|
||||
for (int i = 0; i < bmapwidth * bmapheight; ++i)
|
||||
{
|
||||
BlockMap[4+i] = WORD(BlockMap.Size());
|
||||
BlockMap.Push (zero);
|
||||
block = &blocks[i];
|
||||
for (unsigned int j = 0; j < block->Size(); ++j)
|
||||
{
|
||||
BlockMap.Push ((*block)[j]);
|
||||
}
|
||||
BlockMap.Push (terminator);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int BlockHash (TArray<WORD> *block)
|
||||
{
|
||||
int hash = 0;
|
||||
WORD *ar = &(*block)[0];
|
||||
for (size_t i = 0; i < block->Size(); ++i)
|
||||
{
|
||||
hash = hash * 12235 + ar[i];
|
||||
}
|
||||
return hash & 0x7fffffff;
|
||||
}
|
||||
|
||||
static bool BlockCompare (TArray<WORD> *block1, TArray<WORD> *block2)
|
||||
{
|
||||
size_t size = block1->Size();
|
||||
|
||||
if (size != block2->Size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (size == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
WORD *ar1 = &(*block1)[0];
|
||||
WORD *ar2 = &(*block2)[0];
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (ar1[i] != ar2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FBlockmapBuilder::CreatePackedBlockmap (TArray<WORD> *blocks, int bmapwidth, int bmapheight)
|
||||
{
|
||||
WORD buckets[4096];
|
||||
WORD *hashes, hashblock;
|
||||
TArray<WORD> *block;
|
||||
WORD zero = 0;
|
||||
WORD terminator = 0xffff;
|
||||
WORD *array;
|
||||
int i, hash;
|
||||
int hashed = 0, nothashed = 0;
|
||||
|
||||
hashes = new WORD[bmapwidth * bmapheight];
|
||||
|
||||
memset (hashes, 0xff, sizeof(WORD)*bmapwidth*bmapheight);
|
||||
memset (buckets, 0xff, sizeof(buckets));
|
||||
|
||||
for (i = 0; i < bmapwidth * bmapheight; ++i)
|
||||
{
|
||||
block = &blocks[i];
|
||||
hash = BlockHash (block) % 4096;
|
||||
hashblock = buckets[hash];
|
||||
while (hashblock != 0xffff)
|
||||
{
|
||||
if (BlockCompare (block, &blocks[hashblock]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
hashblock = hashes[hashblock];
|
||||
}
|
||||
if (hashblock != 0xffff)
|
||||
{
|
||||
BlockMap[4+i] = BlockMap[4+hashblock];
|
||||
hashed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hashes[i] = buckets[hash];
|
||||
buckets[hash] = WORD(i);
|
||||
BlockMap[4+i] = WORD(BlockMap.Size());
|
||||
BlockMap.Push (zero);
|
||||
array = &(*block)[0];
|
||||
for (size_t j = 0; j < block->Size(); ++j)
|
||||
{
|
||||
BlockMap.Push (array[j]);
|
||||
}
|
||||
BlockMap.Push (terminator);
|
||||
nothashed++;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] hashes;
|
||||
|
||||
// printf ("%d blocks written, %d blocks saved\n", nothashed, hashed);
|
||||
}
|
||||
|
21
src/blockmapbuilder/blockmapbuilder.h
Normal file
21
src/blockmapbuilder/blockmapbuilder.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "level/doomdata.h"
|
||||
#include "level/workdata.h"
|
||||
#include "framework/tarray.h"
|
||||
|
||||
class FBlockmapBuilder
|
||||
{
|
||||
public:
|
||||
FBlockmapBuilder (FLevel &level);
|
||||
WORD *GetBlockmap (int &size);
|
||||
|
||||
private:
|
||||
FLevel &Level;
|
||||
TArray<WORD> BlockMap;
|
||||
|
||||
void BuildBlockmap ();
|
||||
void CreateUnpackedBlockmap (TArray<WORD> *blocks, int bmapwidth, int bmapheight);
|
||||
void CreatePackedBlockmap (TArray<WORD> *blocks, int bmapwidth, int bmapheight);
|
||||
};
|
1064
src/commandline/getopt.c
Normal file
1064
src/commandline/getopt.c
Normal file
File diff suppressed because it is too large
Load diff
131
src/commandline/getopt.h
Normal file
131
src/commandline/getopt.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
/* Declarations for getopt.
|
||||
Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
#ifndef _GETOPT_H
|
||||
#define _GETOPT_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
extern char *optarg;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns -1, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
extern int optind;
|
||||
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints
|
||||
for unrecognized options. */
|
||||
|
||||
extern int opterr;
|
||||
|
||||
/* Set to an option character which was unrecognized. */
|
||||
|
||||
extern int optopt;
|
||||
|
||||
/* Describe the long-named options requested by the application.
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
|
||||
of `struct option' terminated by an element containing a name which is
|
||||
zero.
|
||||
|
||||
The field `has_arg' is:
|
||||
no_argument (or 0) if the option does not take an argument,
|
||||
required_argument (or 1) if the option requires an argument,
|
||||
optional_argument (or 2) if the option takes an optional argument.
|
||||
|
||||
If the field `flag' is not NULL, it points to a variable that is set
|
||||
to the value given in the field `val' when the option is found, but
|
||||
left unchanged if the option is not found.
|
||||
|
||||
To have a long-named option do something other than set an `int' to
|
||||
a compiled-in constant, such as set a value from `optarg', set the
|
||||
option's `flag' field to zero and its `val' field to a nonzero
|
||||
value (the equivalent single-letter option character, if there is
|
||||
one). For long options that have a zero `flag' field, `getopt'
|
||||
returns the contents of the `val' field. */
|
||||
|
||||
struct option
|
||||
{
|
||||
const char *name;
|
||||
/* has_arg can't be an enum because some compilers complain about
|
||||
type mismatches in all the code that assumes it is an int. */
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#if (defined (__STDC__) && __STDC__) || (defined (__cplusplus))
|
||||
#ifndef __APPLE__
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Many other libraries have conflicting prototypes for getopt, with
|
||||
differences in the consts, in stdlib.h. To avoid compilation
|
||||
errors, only prototype getopt for the GNU C library. */
|
||||
extern int getopt (int argc, char *const *argv, const char *shortopts);
|
||||
#else /* not __GNU_LIBRARY__ */
|
||||
extern int getopt ();
|
||||
#endif /* __GNU_LIBRARY__ */
|
||||
#endif
|
||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
extern int getopt_long_only (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind);
|
||||
|
||||
/* Internal only. Users should not call this directly. */
|
||||
extern int _getopt_internal (int argc, char *const *argv,
|
||||
const char *shortopts,
|
||||
const struct option *longopts, int *longind,
|
||||
int long_only);
|
||||
#else /* not __STDC__ */
|
||||
extern int getopt ();
|
||||
extern int getopt_long ();
|
||||
extern int getopt_long_only ();
|
||||
|
||||
extern int _getopt_internal ();
|
||||
#endif /* __STDC__ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GETOPT_H */
|
189
src/commandline/getopt1.c
Normal file
189
src/commandline/getopt1.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
|
||||
|
||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#if !defined (__STDC__) || !__STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
|
||||
#define GETOPT_INTERFACE_VERSION 2
|
||||
#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
|
||||
#include <gnu-versions.h>
|
||||
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
|
||||
#define ELIDE_CODE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ELIDE_CODE
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* Not ELIDE_CODE. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
713
src/commandline/main.cpp
Normal file
713
src/commandline/main.cpp
Normal file
|
@ -0,0 +1,713 @@
|
|||
/*
|
||||
The main glue for ZDRay.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Need windows.h for QueryPerformanceCounter
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define HAVE_TIMING 1
|
||||
#define START_COUNTER(s,e,f) \
|
||||
LARGE_INTEGER s, e, f; QueryPerformanceCounter (&s);
|
||||
#define END_COUNTER(s,e,f,l) \
|
||||
QueryPerformanceCounter (&e); QueryPerformanceFrequency (&f); \
|
||||
if (!NoTiming) printf (l, double(e.QuadPart - s.QuadPart) / double(f.QuadPart));
|
||||
|
||||
#else
|
||||
|
||||
#include <time.h>
|
||||
#define HAVE_TIMING 1
|
||||
#define START_COUNTER(s,e,f) \
|
||||
clock_t s, e; s = clock();
|
||||
#define END_COUNTER(s,e,f,l) \
|
||||
e = clock(); \
|
||||
if (!NoTiming) printf (l, double(e - s) / CLOCKS_PER_SEC);
|
||||
|
||||
// Need these to check if input/output are the same file
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "wad/wad.h"
|
||||
#include "level/level.h"
|
||||
#include "commandline/getopt.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static void ParseArgs (int argc, char **argv);
|
||||
static void ShowUsage ();
|
||||
static void ShowVersion ();
|
||||
static bool CheckInOutNames ();
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
static void CheckSSE ();
|
||||
#endif
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern "C" int optind;
|
||||
extern "C" char *optarg;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
const char *Map = NULL;
|
||||
const char *InName;
|
||||
const char *OutName = "tmp.wad";
|
||||
bool BuildNodes = true;
|
||||
bool BuildGLNodes = false;
|
||||
bool ConformNodes = false;
|
||||
bool NoPrune = false;
|
||||
EBlockmapMode BlockmapMode = EBM_Rebuild;
|
||||
ERejectMode RejectMode = ERM_DontTouch;
|
||||
bool WriteComments = false;
|
||||
int MaxSegs = 64;
|
||||
int SplitCost = 8;
|
||||
int AAPreference = 16;
|
||||
bool CheckPolyobjs = true;
|
||||
bool ShowMap = false;
|
||||
bool ShowWarnings = false;
|
||||
bool NoTiming = false;
|
||||
bool CompressNodes = false;
|
||||
bool CompressGLNodes = false;
|
||||
bool ForceCompression = false;
|
||||
bool GLOnly = false;
|
||||
bool V5GLNodes = false;
|
||||
bool HaveSSE1, HaveSSE2;
|
||||
int SSELevel;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static option long_opts[] =
|
||||
{
|
||||
{"help", no_argument, 0, 1000},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"view", no_argument, 0, 'v'},
|
||||
{"warn", no_argument, 0, 'w'},
|
||||
{"map", required_argument, 0, 'm'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"output-file", required_argument, 0, 'o'},
|
||||
{"file", required_argument, 0, 'f'},
|
||||
{"no-nodes", no_argument, 0, 'N'},
|
||||
{"gl", no_argument, 0, 'g'},
|
||||
{"gl-matching", no_argument, 0, 'G'},
|
||||
{"empty-blockmap", no_argument, 0, 'b'},
|
||||
{"empty-reject", no_argument, 0, 'r'},
|
||||
{"zero-reject", no_argument, 0, 'R'},
|
||||
{"full-reject", no_argument, 0, 'e'},
|
||||
{"no-reject", no_argument, 0, 'E'},
|
||||
{"partition", required_argument, 0, 'p'},
|
||||
{"split-cost", required_argument, 0, 's'},
|
||||
{"diagonal-cost", required_argument, 0, 'd'},
|
||||
{"no-polyobjs", no_argument, 0, 'P'},
|
||||
{"no-prune", no_argument, 0, 'q'},
|
||||
{"no-timing", no_argument, 0, 't'},
|
||||
{"compress", no_argument, 0, 'z'},
|
||||
{"compress-normal", no_argument, 0, 'Z'},
|
||||
{"extended", no_argument, 0, 'X'},
|
||||
{"gl-only", no_argument, 0, 'x'},
|
||||
{"gl-v5", no_argument, 0, '5'},
|
||||
{"no-sse", no_argument, 0, 1002},
|
||||
{"no-sse2", no_argument, 0, 1003},
|
||||
{"comments", no_argument, 0, 'c'},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZXx5c";
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
bool fixSame = false;
|
||||
|
||||
#ifdef DISABLE_SSE
|
||||
HaveSSE1 = HaveSSE2 = false;
|
||||
#else
|
||||
HaveSSE1 = HaveSSE2 = true;
|
||||
#endif
|
||||
|
||||
ParseArgs (argc, argv);
|
||||
|
||||
if (InName == NULL)
|
||||
{
|
||||
if (optind >= argc || optind < argc-1)
|
||||
{ // Source file is unspecified or followed by junk
|
||||
ShowUsage ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
InName = argv[optind];
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
CheckSSE ();
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
START_COUNTER(t1a, t1b, t1c)
|
||||
|
||||
if (CheckInOutNames ())
|
||||
{
|
||||
// When the input and output files are the same, output will go to
|
||||
// a temporary file. After everything is done, the input file is
|
||||
// deleted and the output file is renamed to match the input file.
|
||||
|
||||
char *out = new char[strlen(OutName)+3], *dot;
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
throw std::runtime_error("Could not create temporary file name.");
|
||||
}
|
||||
|
||||
strcpy (out, OutName);
|
||||
dot = strrchr (out, '.');
|
||||
if (dot && (dot[1] == 'w' || dot[1] == 'W')
|
||||
&& (dot[2] == 'a' || dot[2] == 'A')
|
||||
&& (dot[3] == 'd' || dot[3] == 'D')
|
||||
&& dot[4] == 0)
|
||||
{
|
||||
// *.wad becomes *.daw
|
||||
dot[1] = 'd';
|
||||
dot[3] = 'w';
|
||||
}
|
||||
else
|
||||
{
|
||||
// * becomes *.x
|
||||
strcat (out, ".x");
|
||||
}
|
||||
OutName = out;
|
||||
fixSame = true;
|
||||
}
|
||||
|
||||
{
|
||||
FWadReader inwad (InName);
|
||||
FWadWriter outwad (OutName, inwad.IsIWAD());
|
||||
|
||||
int lump = 0;
|
||||
int max = inwad.NumLumps ();
|
||||
|
||||
while (lump < max)
|
||||
{
|
||||
if (inwad.IsMap (lump) &&
|
||||
(!Map || stricmp (inwad.LumpName (lump), Map) == 0))
|
||||
{
|
||||
START_COUNTER(t2a, t2b, t2c)
|
||||
FProcessor builder (inwad, lump);
|
||||
builder.Write (outwad);
|
||||
END_COUNTER(t2a, t2b, t2c, " %.3f seconds.\n")
|
||||
|
||||
lump = inwad.LumpAfterMap (lump);
|
||||
}
|
||||
else if (inwad.IsGLNodes (lump))
|
||||
{
|
||||
// Ignore GL nodes from the input for any maps we process.
|
||||
if (BuildNodes && (Map == NULL || stricmp (inwad.LumpName (lump)+3, Map) == 0))
|
||||
{
|
||||
lump = inwad.SkipGLNodes (lump);
|
||||
}
|
||||
else
|
||||
{
|
||||
outwad.CopyLump (inwad, lump);
|
||||
++lump;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf ("copy %s\n", inwad.LumpName (lump));
|
||||
outwad.CopyLump (inwad, lump);
|
||||
++lump;
|
||||
}
|
||||
}
|
||||
|
||||
outwad.Close ();
|
||||
}
|
||||
|
||||
if (fixSame)
|
||||
{
|
||||
remove (InName);
|
||||
if (0 != rename (OutName, InName))
|
||||
{
|
||||
printf ("The output file could not be renamed to %s.\nYou can find it as %s.\n",
|
||||
InName, OutName);
|
||||
}
|
||||
}
|
||||
|
||||
END_COUNTER(t1a, t1b, t1c, "\nTotal time: %.3f seconds.\n")
|
||||
}
|
||||
catch (std::runtime_error msg)
|
||||
{
|
||||
printf ("%s\n", msg.what());
|
||||
return 20;
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
printf ("Out of memory\n");
|
||||
return 20;
|
||||
}
|
||||
catch (std::exception msg)
|
||||
{
|
||||
printf ("%s\n", msg.what());
|
||||
return 20;
|
||||
}
|
||||
#ifndef _DEBUG
|
||||
catch (...)
|
||||
{
|
||||
printf ("Unhandled exception. ZDRay cannot continue.\n");
|
||||
return 20;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ParseArgs
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ParseArgs (int argc, char **argv)
|
||||
{
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
ShowMap = true;
|
||||
break;
|
||||
case 'w':
|
||||
ShowWarnings = true;
|
||||
break;
|
||||
case 'm':
|
||||
Map = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
OutName = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
InName = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
BuildNodes = false;
|
||||
break;
|
||||
case 'b':
|
||||
BlockmapMode = EBM_Create0;
|
||||
break;
|
||||
case 'r':
|
||||
RejectMode = ERM_Create0;
|
||||
break;
|
||||
case 'R':
|
||||
RejectMode = ERM_CreateZeroes;
|
||||
break;
|
||||
case 'e':
|
||||
RejectMode = ERM_Rebuild;
|
||||
break;
|
||||
case 'E':
|
||||
RejectMode = ERM_DontTouch;
|
||||
break;
|
||||
case 'p':
|
||||
MaxSegs = atoi (optarg);
|
||||
if (MaxSegs < 3)
|
||||
{ // Don't be too unreasonable
|
||||
MaxSegs = 3;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
SplitCost = atoi (optarg);
|
||||
if (SplitCost < 1)
|
||||
{ // 1 means to add no extra weight at all
|
||||
SplitCost = 1;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
AAPreference = atoi (optarg);
|
||||
if (AAPreference < 1)
|
||||
{
|
||||
AAPreference = 1;
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
CheckPolyobjs = false;
|
||||
break;
|
||||
case 'g':
|
||||
BuildGLNodes = true;
|
||||
ConformNodes = false;
|
||||
break;
|
||||
case 'G':
|
||||
BuildGLNodes = true;
|
||||
ConformNodes = true;
|
||||
break;
|
||||
case 'X':
|
||||
CompressNodes = true;
|
||||
CompressGLNodes = true;
|
||||
ForceCompression = false;
|
||||
break;
|
||||
case 'z':
|
||||
CompressNodes = true;
|
||||
CompressGLNodes = true;
|
||||
ForceCompression = true;
|
||||
break;
|
||||
case 'Z':
|
||||
CompressNodes = true;
|
||||
CompressGLNodes = false;
|
||||
ForceCompression = true;
|
||||
break;
|
||||
case 'x':
|
||||
GLOnly = true;
|
||||
BuildGLNodes = true;
|
||||
ConformNodes = false;
|
||||
break;
|
||||
case '5':
|
||||
V5GLNodes = true;
|
||||
break;
|
||||
case 'q':
|
||||
NoPrune = true;
|
||||
break;
|
||||
case 't':
|
||||
NoTiming = true;
|
||||
break;
|
||||
case 'c':
|
||||
WriteComments = true;
|
||||
break;
|
||||
case 'V':
|
||||
ShowVersion ();
|
||||
exit (0);
|
||||
break;
|
||||
case 1002: // Disable SSE/SSE2 ClassifyLine routine
|
||||
HaveSSE1 = false;
|
||||
HaveSSE2 = false;
|
||||
break;
|
||||
case 1003: // Disable only SSE2 ClassifyLine routine
|
||||
HaveSSE2 = false;
|
||||
break;
|
||||
case 1000:
|
||||
ShowUsage ();
|
||||
exit (0);
|
||||
default:
|
||||
printf ("Try `zdray --help' for more information.\n");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ShowUsage
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ShowUsage ()
|
||||
{
|
||||
printf (
|
||||
"Usage: zdray [options] sourcefile.wad\n"
|
||||
" -m, --map=MAP Only affect the specified map\n"
|
||||
" -o, --output=FILE Write output to FILE instead of tmp.wad\n"
|
||||
" -q, --no-prune Keep unused sidedefs and sectors\n"
|
||||
" -N, --no-nodes Do not rebuild nodes\n"
|
||||
" -g, --gl Build GL-friendly nodes\n"
|
||||
" -G, --gl-matching Build GL-friendly nodes that match normal nodes\n"
|
||||
" -x, --gl-only Only build GL-friendly nodes\n"
|
||||
" -5, --gl-v5 Create v5 GL-friendly nodes (overriden by -z and -X)\n"
|
||||
" -X, --extended Create extended nodes (including GL nodes, if built)\n"
|
||||
" -z, --compress Compress the nodes (including GL nodes, if built)\n"
|
||||
" -Z, --compress-normal Compress normal nodes but not GL nodes\n"
|
||||
" -b, --empty-blockmap Create an empty blockmap\n"
|
||||
" -r, --empty-reject Create an empty reject table\n"
|
||||
" -R, --zero-reject Create a reject table of all zeroes\n"
|
||||
//" -e, --full-reject Rebuild reject table (unsupported)\n"
|
||||
" -E, --no-reject Leave reject table untouched\n"
|
||||
" -p, --partition=NNN Maximum segs to consider at each node (default %d)\n"
|
||||
" -s, --split-cost=NNN Cost for splitting segs (default %d)\n"
|
||||
" -d, --diagonal-cost=NNN Cost for avoiding diagonal splitters (default %d)\n"
|
||||
" -P, --no-polyobjs Do not check for polyobject subsector splits\n"
|
||||
#ifdef _WIN32
|
||||
" -v, --view View the nodes\n"
|
||||
#endif
|
||||
" -w, --warn Show warning messages\n"
|
||||
#if HAVE_TIMING
|
||||
" -t, --no-timing Suppress timing information\n"
|
||||
#endif
|
||||
" -V, --version Display version information\n"
|
||||
" --help Display this usage information"
|
||||
#ifndef _WIN32
|
||||
"\n"
|
||||
#endif
|
||||
, MaxSegs /* Partition size */
|
||||
, SplitCost
|
||||
, AAPreference
|
||||
);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ShowVersion
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ShowVersion ()
|
||||
{
|
||||
printf ("ZDRay " ZDRAY_VERSION " ("
|
||||
#if defined(__GNUC__)
|
||||
|
||||
"GCC"
|
||||
#if defined(__i386__)
|
||||
"-x86"
|
||||
#elif defined(__amd64__)
|
||||
"-amd64"
|
||||
#elif defined(__ppc__)
|
||||
"-ppc"
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
"VC"
|
||||
#if defined(_M_IX86)
|
||||
"-x86"
|
||||
#if _M_IX86_FP > 1
|
||||
"-SSE2"
|
||||
#endif
|
||||
#elif defined(_M_X64)
|
||||
"-x64"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
" : " __DATE__ ")\n");
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckInOutNames
|
||||
//
|
||||
// Returns true if InName and OutName refer to the same file. This needs
|
||||
// to be implemented different under Windows than Unix because the inode
|
||||
// information returned by stat is always 0, so it cannot be used to
|
||||
// determine duplicate files.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool CheckInOutNames ()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct stat info;
|
||||
dev_t outdev;
|
||||
ino_t outinode;
|
||||
|
||||
if (0 != stat (OutName, &info))
|
||||
{ // If out doesn't exist, it can't be duplicated
|
||||
return false;
|
||||
}
|
||||
outdev = info.st_dev;
|
||||
outinode = info.st_ino;
|
||||
if (0 != stat (InName, &info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return outinode == info.st_ino && outdev == info.st_dev;
|
||||
#else
|
||||
HANDLE inFile, outFile;
|
||||
|
||||
outFile = CreateFile (OutName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (outFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
inFile = CreateFile (InName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (inFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle (outFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION inInfo, outInfo;
|
||||
bool same = false;
|
||||
|
||||
if (GetFileInformationByHandle (inFile, &inInfo) &&
|
||||
GetFileInformationByHandle (outFile, &outInfo))
|
||||
{
|
||||
same = inInfo.dwVolumeSerialNumber == outInfo.dwVolumeSerialNumber &&
|
||||
inInfo.nFileIndexLow == outInfo.nFileIndexLow &&
|
||||
inInfo.nFileIndexHigh == outInfo.nFileIndexHigh;
|
||||
}
|
||||
|
||||
CloseHandle (inFile);
|
||||
CloseHandle (outFile);
|
||||
|
||||
return same;
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckSSE
|
||||
//
|
||||
// Checks if the processor supports SSE or SSE2.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
static void CheckSSE ()
|
||||
{
|
||||
#ifdef __SSE2__
|
||||
// If we compiled with SSE2 support enabled for everything, then
|
||||
// obviously it's available, or the program won't get very far.
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!HaveSSE2 && !HaveSSE1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool forcenosse1 = !HaveSSE1;
|
||||
bool forcenosse2 = !HaveSSE2;
|
||||
|
||||
HaveSSE1 = false;
|
||||
HaveSSE2 = false;
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#ifdef _M_X64
|
||||
// Processors implementing AMD64 are required to support SSE2.
|
||||
return;
|
||||
#else
|
||||
__asm
|
||||
{
|
||||
pushfd // save EFLAGS
|
||||
pop eax // store EFLAGS in EAX
|
||||
mov edx,eax // save in EDX for later testing
|
||||
xor eax,0x00200000 // toggle bit 21
|
||||
push eax // put to stack
|
||||
popfd // save changed EAX to EFLAGS
|
||||
pushfd // push EFLAGS to TOS
|
||||
pop eax // store EFLAGS in EAX
|
||||
cmp eax,edx // see if bit 21 has changed
|
||||
jz noid // if no change, then no CPUID
|
||||
|
||||
// Check the feature flag for SSE/SSE2
|
||||
mov eax,1
|
||||
cpuid
|
||||
test edx,(1<<25) // Check for SSE
|
||||
setnz HaveSSE1
|
||||
test edx,(1<<26) // Check for SSE2
|
||||
setnz HaveSSE2
|
||||
noid:
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
|
||||
// Same as above, but for GCC
|
||||
asm volatile
|
||||
("pushfl\n\t"
|
||||
"popl %%eax\n\t"
|
||||
"movl %%eax,%%edx\n\t"
|
||||
"xorl $0x200000,%%eax\n\t"
|
||||
"pushl %%eax\n\t"
|
||||
"popfl\n\t"
|
||||
"pushfl\n\t"
|
||||
"popl %%eax\n\t"
|
||||
"cmp %%edx,%%eax\n\t"
|
||||
"jz noid\n\t"
|
||||
"mov $1,%%eax\n\t"
|
||||
"cpuid\n\t"
|
||||
"test $(1<<25),%%edx\n\t"
|
||||
"setneb %0\n"
|
||||
"test $(1<<26),%%edx\n\t"
|
||||
"setneb %1\n"
|
||||
"noid:"
|
||||
:"=m" (HaveSSE1),"=m" (HaveSSE2)::"eax","ebx","ecx","edx");
|
||||
|
||||
#endif
|
||||
|
||||
if (forcenosse1)
|
||||
{
|
||||
HaveSSE1 = false;
|
||||
}
|
||||
if (forcenosse2)
|
||||
{
|
||||
HaveSSE2 = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PointToAngle
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
angle_t PointToAngle (fixed_t x, fixed_t y)
|
||||
{
|
||||
double ang = atan2 (double(y), double(x));
|
||||
const double rad2bam = double(1<<30) / M_PI;
|
||||
double dbam = ang * rad2bam;
|
||||
// Convert to signed first since negative double to unsigned is undefined.
|
||||
return angle_t(int(dbam)) << 1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Warn
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Warn (const char *format, ...)
|
||||
{
|
||||
va_list marker;
|
||||
|
||||
if (!ShowWarnings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_start (marker, format);
|
||||
vprintf (format, marker);
|
||||
va_end (marker);
|
||||
}
|
333
src/framework/tarray.h
Normal file
333
src/framework/tarray.h
Normal file
|
@ -0,0 +1,333 @@
|
|||
/*
|
||||
** tarray.h
|
||||
** Templated, automatically resizing array
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2007 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#ifndef __APPLE__
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include <new>
|
||||
|
||||
// TArray -------------------------------------------------------------------
|
||||
|
||||
// T is the type stored in the array.
|
||||
// TT is the type returned by operator().
|
||||
template <class T, class TT=T>
|
||||
class TArray
|
||||
{
|
||||
public:
|
||||
////////
|
||||
// This is a dummy constructor that does nothing. The purpose of this
|
||||
// is so you can create a global TArray in the data segment that gets
|
||||
// used by code before startup without worrying about the constructor
|
||||
// resetting it after it's already been used. You MUST NOT use it for
|
||||
// heap- or stack-allocated TArrays.
|
||||
enum ENoInit
|
||||
{
|
||||
NoInit
|
||||
};
|
||||
TArray (ENoInit dummy)
|
||||
{
|
||||
}
|
||||
////////
|
||||
TArray ()
|
||||
{
|
||||
Most = 0;
|
||||
Count = 0;
|
||||
Array = NULL;
|
||||
}
|
||||
TArray (int max)
|
||||
{
|
||||
Most = max;
|
||||
Count = 0;
|
||||
Array = (T *)malloc (sizeof(T)*max);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
TArray (const TArray<T> &other)
|
||||
{
|
||||
DoCopy (other);
|
||||
}
|
||||
TArray<T> &operator= (const TArray<T> &other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
if (Array != NULL)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
}
|
||||
free (Array);
|
||||
}
|
||||
DoCopy (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~TArray ()
|
||||
{
|
||||
if (Array)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
}
|
||||
free (Array);
|
||||
Array = NULL;
|
||||
Count = 0;
|
||||
Most = 0;
|
||||
}
|
||||
}
|
||||
// Return a reference to an element
|
||||
T &operator[] (unsigned int index) const
|
||||
{
|
||||
return Array[index];
|
||||
}
|
||||
// Returns the value of an element
|
||||
TT operator() (unsigned int index) const
|
||||
{
|
||||
return Array[index];
|
||||
}
|
||||
unsigned int Push (const T &item)
|
||||
{
|
||||
Grow (1);
|
||||
::new((void*)&Array[Count]) T(item);
|
||||
return Count++;
|
||||
}
|
||||
bool Pop (T &item)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
item = Array[--Count];
|
||||
Array[Count].~T();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Delete (unsigned int index)
|
||||
{
|
||||
if (index < Count)
|
||||
{
|
||||
Array[index].~T();
|
||||
if (index < --Count)
|
||||
{
|
||||
memmove (&Array[index], &Array[index+1], sizeof(T)*(Count - index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Delete (unsigned int index, int deletecount)
|
||||
{
|
||||
if (index + deletecount > Count) deletecount = Count - index;
|
||||
if (deletecount > 0)
|
||||
{
|
||||
for(int i = 0; i < deletecount; i++)
|
||||
{
|
||||
Array[index + i].~T();
|
||||
}
|
||||
Count -= deletecount;
|
||||
if (index < Count)
|
||||
{
|
||||
memmove (&Array[index], &Array[index+deletecount], sizeof(T)*(Count - index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts an item into the array, shifting elements as needed
|
||||
void Insert (unsigned int index, const T &item)
|
||||
{
|
||||
if (index >= Count)
|
||||
{
|
||||
// Inserting somewhere past the end of the array, so we can
|
||||
// just add it without moving things.
|
||||
Resize (index + 1);
|
||||
::new ((void *)&Array[index]) T(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Inserting somewhere in the middle of the array,
|
||||
// so make room for it
|
||||
Resize (Count + 1);
|
||||
|
||||
// Now move items from the index and onward out of the way
|
||||
memmove (&Array[index+1], &Array[index], sizeof(T)*(Count - index - 1));
|
||||
|
||||
// And put the new element in
|
||||
::new ((void *)&Array[index]) T(item);
|
||||
}
|
||||
}
|
||||
void ShrinkToFit ()
|
||||
{
|
||||
if (Most > Count)
|
||||
{
|
||||
Most = Count;
|
||||
if (Most == 0)
|
||||
{
|
||||
if (Array != NULL)
|
||||
{
|
||||
free (Array);
|
||||
Array = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DoResize ();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow Array to be large enough to hold amount more entries without
|
||||
// further growing.
|
||||
void Grow (unsigned int amount)
|
||||
{
|
||||
if (Count + amount > Most)
|
||||
{
|
||||
const unsigned int choicea = Count + amount;
|
||||
const unsigned int choiceb = Most = (Most >= 16) ? Most + Most / 2 : 16;
|
||||
Most = (choicea > choiceb ? choicea : choiceb);
|
||||
DoResize ();
|
||||
}
|
||||
}
|
||||
// Resize Array so that it has exactly amount entries in use.
|
||||
void Resize (unsigned int amount)
|
||||
{
|
||||
if (Count < amount)
|
||||
{
|
||||
// Adding new entries
|
||||
Grow (amount - Count);
|
||||
for (unsigned int i = Count; i < amount; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
}
|
||||
else if (Count != amount)
|
||||
{
|
||||
// Deleting old entries
|
||||
DoDelete (amount, Count - 1);
|
||||
}
|
||||
Count = amount;
|
||||
}
|
||||
// Reserves amount entries at the end of the array, but does nothing
|
||||
// with them.
|
||||
unsigned int Reserve (unsigned int amount)
|
||||
{
|
||||
Grow (amount);
|
||||
unsigned int place = Count;
|
||||
Count += amount;
|
||||
for (unsigned int i = place; i < Count; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
return place;
|
||||
}
|
||||
unsigned int Size () const
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
unsigned int Max () const
|
||||
{
|
||||
return Most;
|
||||
}
|
||||
void Clear ()
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
DoDelete (0, Count-1);
|
||||
Count = 0;
|
||||
}
|
||||
}
|
||||
private:
|
||||
T *Array;
|
||||
unsigned int Most;
|
||||
unsigned int Count;
|
||||
|
||||
void DoCopy (const TArray<T> &other)
|
||||
{
|
||||
Most = Count = other.Count;
|
||||
if (Count != 0)
|
||||
{
|
||||
Array = (T *)malloc (sizeof(T)*Most);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
for (unsigned int i = 0; i < Count; ++i)
|
||||
{
|
||||
::new(&Array[i]) T(other.Array[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void DoResize ()
|
||||
{
|
||||
size_t allocsize = sizeof(T)*Most;
|
||||
Array = (T *)realloc (Array, allocsize);
|
||||
if (Array == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
void DoDelete (unsigned int first, unsigned int last)
|
||||
{
|
||||
assert (last != ~0u);
|
||||
for (unsigned int i = first; i <= last; ++i)
|
||||
{
|
||||
Array[i].~T();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TDeletingArray -----------------------------------------------------------
|
||||
// An array that deletes its elements when it gets deleted.
|
||||
template<class T, class TT=T>
|
||||
class TDeletingArray : public TArray<T, TT>
|
||||
{
|
||||
public:
|
||||
~TDeletingArray<T, TT> ()
|
||||
{
|
||||
for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i)
|
||||
{
|
||||
if ((*this)[i] != NULL)
|
||||
delete (*this)[i];
|
||||
}
|
||||
}
|
||||
};
|
195
src/framework/templates.h
Normal file
195
src/framework/templates.h
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
** templates.h
|
||||
** Some useful template functions
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2006 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// BinarySearch
|
||||
//
|
||||
// Searches an array sorted in ascending order for an element matching
|
||||
// the desired key.
|
||||
//
|
||||
// Template parameters:
|
||||
// ClassType - The class to be searched
|
||||
// KeyType - The type of the key contained in the class
|
||||
//
|
||||
// Function parameters:
|
||||
// first - Pointer to the first element in the array
|
||||
// max - The number of elements in the array
|
||||
// keyptr - Pointer to the key member of ClassType
|
||||
// key - The key value to look for
|
||||
//
|
||||
// Returns:
|
||||
// A pointer to the element with a matching key or NULL if none found.
|
||||
//==========================================================================
|
||||
|
||||
template<class ClassType, class KeyType>
|
||||
inline
|
||||
const ClassType *BinarySearch (const ClassType *first, int max,
|
||||
const KeyType ClassType::*keyptr, const KeyType key)
|
||||
{
|
||||
int min = 0;
|
||||
--max;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
const ClassType *probe = &first[mid];
|
||||
const KeyType &seekey = probe->*keyptr;
|
||||
if (seekey == key)
|
||||
{
|
||||
return probe;
|
||||
}
|
||||
else if (seekey < key)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// BinarySearchFlexible
|
||||
//
|
||||
// THIS DOES NOT WORK RIGHT WITH VISUAL C++
|
||||
// ONLY ONE COMPTYPE SEEMS TO BE USED FOR ANY INSTANCE OF THIS FUNCTION
|
||||
// IN A DEBUG BUILD. RELEASE MIGHT BE DIFFERENT--I DIDN'T BOTHER TRYING.
|
||||
//
|
||||
// Similar to BinarySearch, except another function is used to copmare
|
||||
// items in the array.
|
||||
//
|
||||
// Template parameters:
|
||||
// IndexType - The type used to index the array (int, size_t, etc.)
|
||||
// KeyType - The type of the key
|
||||
// CompType - A class with a static DoCompare(IndexType, KeyType) method.
|
||||
//
|
||||
// Function parameters:
|
||||
// max - The number of elements in the array
|
||||
// key - The key value to look for
|
||||
// noIndex - The value to return if no matching element is found.
|
||||
//
|
||||
// Returns:
|
||||
// The index of the matching element or noIndex.
|
||||
//==========================================================================
|
||||
|
||||
template<class IndexType, class KeyType, class CompType>
|
||||
inline
|
||||
IndexType BinarySearchFlexible (IndexType max, const KeyType key, IndexType noIndex)
|
||||
{
|
||||
IndexType min = 0;
|
||||
--max;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
IndexType mid = (min + max) / 2;
|
||||
int lexx = CompType::DoCompare (mid, key);
|
||||
if (lexx == 0)
|
||||
{
|
||||
return mid;
|
||||
}
|
||||
else if (lexx < 0)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return noIndex;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIN
|
||||
//
|
||||
// Returns the minimum of a and b.
|
||||
//==========================================================================
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
const T MIN (const T a, const T b)
|
||||
{
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// MAX
|
||||
//
|
||||
// Returns the maximum of a and b.
|
||||
//==========================================================================
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
const T MAX (const T a, const T b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// clamp
|
||||
//
|
||||
// Clamps in to the range [min,max].
|
||||
//==========================================================================
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
T clamp (const T in, const T min, const T max)
|
||||
{
|
||||
return in <= min ? min : in >= max ? max : in;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// swap
|
||||
//
|
||||
// Swaps the values of a and b.
|
||||
//==========================================================================
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
void swap (T &a, T &b)
|
||||
{
|
||||
T temp = a; a = b; b = temp;
|
||||
}
|
218
src/framework/xs_Float.h
Normal file
218
src/framework/xs_Float.h
Normal file
|
@ -0,0 +1,218 @@
|
|||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// xs_Float.h
|
||||
//
|
||||
// Source: "Know Your FPU: Fixing Floating Fast"
|
||||
// http://www.stereopsis.com/sree/fpu2006.html
|
||||
//
|
||||
// xs_CRoundToInt: Round toward nearest, but ties round toward even (just like FISTP)
|
||||
// xs_ToInt: Round toward zero, just like the C (int) cast
|
||||
// xs_FloorToInt: Round down
|
||||
// xs_CeilToInt: Round up
|
||||
// xs_RoundToInt: Round toward nearest, but ties round up
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
|
||||
#pragma once
|
||||
|
||||
// ====================================================================================================================
|
||||
// Defines
|
||||
// ====================================================================================================================
|
||||
#ifndef _xs_DEFAULT_CONVERSION
|
||||
#define _xs_DEFAULT_CONVERSION 0
|
||||
#endif //_xs_DEFAULT_CONVERSION
|
||||
|
||||
|
||||
#if __BIG_ENDIAN__
|
||||
#define _xs_iexp_ 0
|
||||
#define _xs_iman_ 1
|
||||
#else
|
||||
#define _xs_iexp_ 1 //intel is little endian
|
||||
#define _xs_iman_ 0
|
||||
#endif //BigEndian_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define finline inline
|
||||
#else
|
||||
#define finline __forceinline
|
||||
#endif
|
||||
|
||||
union _xs_doubleints
|
||||
{
|
||||
real64 val;
|
||||
uint32 ival[2];
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define _xs_doublecopysgn(a,b) ((int32*)&a)[_xs_iexp_]&=~(((int32*)&b)[_xs_iexp_]&0x80000000)
|
||||
#define _xs_doubleisnegative(a) ((((int32*)&a)[_xs_iexp_])|0x80000000)
|
||||
#endif
|
||||
|
||||
// ====================================================================================================================
|
||||
// Constants
|
||||
// ====================================================================================================================
|
||||
const real64 _xs_doublemagic = real64 (6755399441055744.0); //2^52 * 1.5, uses limited precisicion to floor
|
||||
const real64 _xs_doublemagicdelta = (1.5e-8); //almost .5f = .5f + 1e^(number of exp bit)
|
||||
const real64 _xs_doublemagicroundeps = (.5f-_xs_doublemagicdelta); //almost .5f = .5f - 1e^(number of exp bit)
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// Prototypes
|
||||
// ====================================================================================================================
|
||||
static int32 xs_CRoundToInt (real64 val, real64 dmr = _xs_doublemagic);
|
||||
static int32 xs_ToInt (real64 val, real64 dme = -_xs_doublemagicroundeps);
|
||||
static int32 xs_FloorToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||
static int32 xs_CeilToInt (real64 val, real64 dme = _xs_doublemagicroundeps);
|
||||
static int32 xs_RoundToInt (real64 val);
|
||||
|
||||
//int32 versions
|
||||
finline static int32 xs_CRoundToInt (int32 val) {return val;}
|
||||
finline static int32 xs_ToInt (int32 val) {return val;}
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// Fix Class
|
||||
// ====================================================================================================================
|
||||
template <int32 N> class xs_Fix
|
||||
{
|
||||
public:
|
||||
typedef int32 Fix;
|
||||
|
||||
// ====================================================================================================================
|
||||
// Basic Conversion from Numbers
|
||||
// ====================================================================================================================
|
||||
finline static Fix ToFix (int32 val) {return val<<N;}
|
||||
finline static Fix ToFix (real64 val) {return xs_ConvertToFixed(val);}
|
||||
|
||||
// ====================================================================================================================
|
||||
// Basic Conversion to Numbers
|
||||
// ====================================================================================================================
|
||||
finline static real64 ToReal (Fix f) {return real64(f)/real64(1<<N);}
|
||||
finline static int32 ToInt (Fix f) {return f>>N;}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
// ====================================================================================================================
|
||||
// Helper function - mainly to preserve _xs_DEFAULT_CONVERSION
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_ConvertToFixed (real64 val)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt(val, _xs_doublemagic/(1<<N));
|
||||
#else
|
||||
return (long)((val)*(1<<N));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// Inline implementation
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_CRoundToInt(real64 val, real64 dmr)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
_xs_doubleints uval;
|
||||
uval.val = val + dmr;
|
||||
return uval.ival[_xs_iman_];
|
||||
#else
|
||||
return int32(floor(val+.5));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_ToInt(real64 val, real64 dme)
|
||||
{
|
||||
/* unused - something else I tried...
|
||||
_xs_doublecopysgn(dme,val);
|
||||
return xs_CRoundToInt(val+dme);
|
||||
return 0;
|
||||
*/
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
// VC++ 2005's standard cast is a little bit faster than this
|
||||
// magic number code. (Which is pretty amazing!) SSE has the
|
||||
// fastest C-style float->int conversion, but unfortunately,
|
||||
// checking for SSE support every time you need to do a
|
||||
// conversion completely negates its performance advantage.
|
||||
return int32(val);
|
||||
#else
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return (val<0) ? xs_CRoundToInt(val-dme) :
|
||||
xs_CRoundToInt(val+dme);
|
||||
#else
|
||||
return int32(val);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_FloorToInt(real64 val, real64 dme)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt (val - dme);
|
||||
#else
|
||||
return floor(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_CeilToInt(real64 val, real64 dme)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
return xs_CRoundToInt (val + dme);
|
||||
#else
|
||||
return ceil(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
finline static int32 xs_RoundToInt(real64 val)
|
||||
{
|
||||
#if _xs_DEFAULT_CONVERSION==0
|
||||
// Yes, it is important that two fadds be generated, so you cannot override the dmr
|
||||
// passed to xs_CRoundToInt with _xs_doublemagic + _xs_doublemagicdelta. If you do,
|
||||
// you'll end up with Banker's Rounding again.
|
||||
return xs_CRoundToInt (val + _xs_doublemagicdelta);
|
||||
#else
|
||||
return floor(val+.5);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
// Unsigned variants
|
||||
// ====================================================================================================================
|
||||
// ====================================================================================================================
|
||||
finline static uint32 xs_CRoundToUInt(real64 val)
|
||||
{
|
||||
return (uint32)xs_CRoundToInt(val);
|
||||
}
|
||||
|
||||
finline static uint32 xs_FloorToUInt(real64 val)
|
||||
{
|
||||
return (uint32)xs_FloorToInt(val);
|
||||
}
|
||||
|
||||
finline static uint32 xs_CeilToUInt(real64 val)
|
||||
{
|
||||
return (uint32)xs_CeilToUInt(val);
|
||||
}
|
||||
|
||||
finline static uint32 xs_RoundToUInt(real64 val)
|
||||
{
|
||||
return (uint32)xs_RoundToInt(val);
|
||||
}
|
269
src/framework/zdray.h
Normal file
269
src/framework/zdray.h
Normal file
|
@ -0,0 +1,269 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <limits.h>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ZDRAY_VERSION "1.0"
|
||||
|
||||
enum EBlockmapMode
|
||||
{
|
||||
EBM_Rebuild,
|
||||
EBM_Create0
|
||||
};
|
||||
|
||||
enum ERejectMode
|
||||
{
|
||||
ERM_DontTouch,
|
||||
ERM_CreateZeroes,
|
||||
ERM_Create0,
|
||||
ERM_Rebuild
|
||||
};
|
||||
|
||||
extern const char *Map;
|
||||
extern const char *InName;
|
||||
extern const char *OutName;
|
||||
extern bool BuildNodes, BuildGLNodes, ConformNodes, GLOnly, WriteComments;
|
||||
extern bool NoPrune;
|
||||
extern EBlockmapMode BlockmapMode;
|
||||
extern ERejectMode RejectMode;
|
||||
extern int MaxSegs;
|
||||
extern int SplitCost;
|
||||
extern int AAPreference;
|
||||
extern bool CheckPolyobjs;
|
||||
extern bool ShowMap;
|
||||
extern bool CompressNodes, CompressGLNodes, ForceCompression, V5GLNodes;
|
||||
extern bool HaveSSE1, HaveSSE2;
|
||||
extern int SSELevel;
|
||||
|
||||
|
||||
#define FIXED_MAX INT_MAX
|
||||
#define FIXED_MIN INT_MIN
|
||||
|
||||
#define FRACBITS 16
|
||||
|
||||
typedef int fixed_t;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef signed short SWORD;
|
||||
#ifdef _WIN32
|
||||
typedef unsigned long DWORD;
|
||||
#else
|
||||
typedef uint32_t DWORD;
|
||||
#endif
|
||||
typedef uint32_t angle_t;
|
||||
|
||||
angle_t PointToAngle (fixed_t x, fixed_t y);
|
||||
|
||||
static const WORD NO_MAP_INDEX = 0xffff;
|
||||
static const DWORD NO_INDEX = 0xffffffff;
|
||||
static const angle_t ANGLE_MAX = 0xffffffff;
|
||||
static const DWORD DWORD_MAX = 0xffffffff;
|
||||
static const angle_t ANGLE_180 = (1u<<31);
|
||||
static const angle_t ANGLE_EPSILON = 5000;
|
||||
|
||||
void Warn (const char *format, ...);
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_IX86)
|
||||
|
||||
#pragma warning (disable: 4035)
|
||||
|
||||
inline fixed_t Scale (fixed_t a, fixed_t b, fixed_t c)
|
||||
{
|
||||
__asm mov eax,a
|
||||
__asm mov ecx,c
|
||||
__asm imul b
|
||||
__asm idiv ecx
|
||||
}
|
||||
|
||||
inline fixed_t DivScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
__asm mov edx,a
|
||||
__asm sar edx,2
|
||||
__asm mov eax,a
|
||||
__asm shl eax,30
|
||||
__asm idiv b
|
||||
}
|
||||
|
||||
inline fixed_t MulScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
__asm mov eax,a
|
||||
__asm imul b
|
||||
__asm shrd eax,edx,30
|
||||
}
|
||||
|
||||
inline fixed_t DMulScale32 (fixed_t a, fixed_t b, fixed_t c, fixed_t d)
|
||||
{
|
||||
__asm mov eax,a
|
||||
__asm imul b
|
||||
__asm mov ebx,eax
|
||||
__asm mov eax,c
|
||||
__asm mov esi,edx
|
||||
__asm imul d
|
||||
__asm add eax,ebx
|
||||
__asm adc edx,esi
|
||||
__asm mov eax,edx
|
||||
}
|
||||
|
||||
#pragma warning (default: 4035)
|
||||
|
||||
#elif defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
#ifdef __clang__
|
||||
inline fixed_t Scale (fixed_t a, fixed_t b, fixed_t c)
|
||||
{
|
||||
fixed_t result, dummy;
|
||||
|
||||
asm volatile
|
||||
("imull %3\n\t"
|
||||
"idivl %4"
|
||||
: "=a" (result),
|
||||
"=&d" (dummy)
|
||||
: "a" (a),
|
||||
"r" (b),
|
||||
"r" (c)
|
||||
: "%cc"
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline fixed_t DivScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
fixed_t result, dummy;
|
||||
asm volatile
|
||||
("idivl %4"
|
||||
: "=a" (result),
|
||||
"=d" (dummy)
|
||||
: "a" (a<<30),
|
||||
"d" (a>>2),
|
||||
"r" (b) \
|
||||
: "%cc");
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
inline fixed_t Scale (fixed_t a, fixed_t b, fixed_t c)
|
||||
{
|
||||
fixed_t result, dummy;
|
||||
|
||||
asm volatile
|
||||
("imull %3\n\t"
|
||||
"idivl %4"
|
||||
: "=a,a,a,a,a,a" (result),
|
||||
"=&d,&d,&d,&d,d,d" (dummy)
|
||||
: "a,a,a,a,a,a" (a),
|
||||
"m,r,m,r,d,d" (b),
|
||||
"r,r,m,m,r,m" (c)
|
||||
: "%cc"
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline fixed_t DivScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
fixed_t result, dummy;
|
||||
asm volatile
|
||||
("idivl %4"
|
||||
: "=a,a" (result),
|
||||
"=d,d" (dummy)
|
||||
: "a,a" (a<<30),
|
||||
"d,d" (a>>2),
|
||||
"r,m" (b) \
|
||||
: "%cc");
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline fixed_t MulScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
return ((int64_t)a * b) >> 30;
|
||||
}
|
||||
|
||||
inline fixed_t DMulScale30 (fixed_t a, fixed_t b, fixed_t c, fixed_t d)
|
||||
{
|
||||
return (((int64_t)a * b) + ((int64_t)c * d)) >> 30;
|
||||
}
|
||||
|
||||
inline fixed_t DMulScale32 (fixed_t a, fixed_t b, fixed_t c, fixed_t d)
|
||||
{
|
||||
return (((int64_t)a * b) + ((int64_t)c * d)) >> 32;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline fixed_t Scale (fixed_t a, fixed_t b, fixed_t c)
|
||||
{
|
||||
return (fixed_t)(double(a)*double(b)/double(c));
|
||||
}
|
||||
|
||||
inline fixed_t DivScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
return (fixed_t)(double(a)/double(b)*double(1<<30));
|
||||
}
|
||||
|
||||
inline fixed_t MulScale30 (fixed_t a, fixed_t b)
|
||||
{
|
||||
return (fixed_t)(double(a)*double(b)/double(1<<30));
|
||||
}
|
||||
|
||||
inline fixed_t DMulScale30 (fixed_t a, fixed_t b, fixed_t c, fixed_t d)
|
||||
{
|
||||
return (fixed_t)((double(a)*double(b)+double(c)*double(d))/double(1<<30));
|
||||
}
|
||||
|
||||
inline fixed_t DMulScale32 (fixed_t a, fixed_t b, fixed_t c, fixed_t d)
|
||||
{
|
||||
return (fixed_t)((double(a)*double(b)+double(c)*double(d))/4294967296.0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#define LittleShort(x) CFSwapInt16LittleToHost(x)
|
||||
#define LittleLong(x) CFSwapInt32LittleToHost(x)
|
||||
#else
|
||||
#ifdef __BIG_ENDIAN__
|
||||
|
||||
// Swap 16bit, that is, MSB and LSB byte.
|
||||
// No masking with 0xFF should be necessary.
|
||||
inline short LittleShort (short x)
|
||||
{
|
||||
return (short)((((unsigned short)x)>>8) | (((unsigned short)x)<<8));
|
||||
}
|
||||
|
||||
inline unsigned short LittleShort (unsigned short x)
|
||||
{
|
||||
return (unsigned short)((x>>8) | (x<<8));
|
||||
}
|
||||
|
||||
// Swapping 32bit.
|
||||
inline unsigned int LittleLong (unsigned int x)
|
||||
{
|
||||
return (unsigned int)(
|
||||
(x>>24)
|
||||
| ((x>>8) & 0xff00)
|
||||
| ((x<<8) & 0xff0000)
|
||||
| (x<<24));
|
||||
}
|
||||
|
||||
inline int LittleLong (int x)
|
||||
{
|
||||
return (int)(
|
||||
(((unsigned int)x)>>24)
|
||||
| ((((unsigned int)x)>>8) & 0xff00)
|
||||
| ((((unsigned int)x)<<8) & 0xff0000)
|
||||
| (((unsigned int)x)<<24));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define LittleShort(x) (x)
|
||||
#define LittleLong(x) (x)
|
||||
|
||||
#endif // __BIG_ENDIAN__
|
||||
#endif // __APPLE__
|
268
src/level/doomdata.h
Normal file
268
src/level/doomdata.h
Normal file
|
@ -0,0 +1,268 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "framework/tarray.h"
|
||||
|
||||
enum
|
||||
{
|
||||
BOXTOP, BOXBOTTOM, BOXLEFT, BOXRIGHT
|
||||
};
|
||||
|
||||
struct UDMFKey
|
||||
{
|
||||
const char *key;
|
||||
const char *value;
|
||||
};
|
||||
|
||||
struct MapVertex
|
||||
{
|
||||
short x, y;
|
||||
};
|
||||
|
||||
struct WideVertex
|
||||
{
|
||||
fixed_t x, y;
|
||||
int index;
|
||||
};
|
||||
|
||||
struct MapSideDef
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
WORD sector;
|
||||
};
|
||||
|
||||
struct IntSideDef
|
||||
{
|
||||
// the first 5 values are only used for binary format maps
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
|
||||
int sector;
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
||||
struct MapLineDef
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
short flags;
|
||||
short special;
|
||||
short tag;
|
||||
WORD sidenum[2];
|
||||
};
|
||||
|
||||
struct MapLineDef2
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
short flags;
|
||||
unsigned char special;
|
||||
unsigned char args[5];
|
||||
WORD sidenum[2];
|
||||
};
|
||||
|
||||
struct IntLineDef
|
||||
{
|
||||
DWORD v1;
|
||||
DWORD v2;
|
||||
int flags;
|
||||
int special;
|
||||
int args[5];
|
||||
DWORD sidenum[2];
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
||||
struct MapSector
|
||||
{
|
||||
short floorheight;
|
||||
short ceilingheight;
|
||||
char floorpic[8];
|
||||
char ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special;
|
||||
short tag;
|
||||
};
|
||||
|
||||
struct IntSector
|
||||
{
|
||||
// none of the sector properties are used by the node builder
|
||||
// so there's no need to store them in their expanded form for
|
||||
// UDMF. Just storing the UDMF keys and leaving the binary fields
|
||||
// empty is enough
|
||||
MapSector data;
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
||||
struct MapSubsector
|
||||
{
|
||||
WORD numlines;
|
||||
WORD firstline;
|
||||
};
|
||||
|
||||
struct MapSubsectorEx
|
||||
{
|
||||
DWORD numlines;
|
||||
DWORD firstline;
|
||||
};
|
||||
|
||||
struct MapSeg
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
WORD angle;
|
||||
WORD linedef;
|
||||
short side;
|
||||
short offset;
|
||||
};
|
||||
|
||||
struct MapSegEx
|
||||
{
|
||||
DWORD v1;
|
||||
DWORD v2;
|
||||
WORD angle;
|
||||
WORD linedef;
|
||||
short side;
|
||||
short offset;
|
||||
};
|
||||
|
||||
struct MapSegGL
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
WORD linedef;
|
||||
WORD side;
|
||||
WORD partner;
|
||||
};
|
||||
|
||||
struct MapSegGLEx
|
||||
{
|
||||
DWORD v1;
|
||||
DWORD v2;
|
||||
DWORD linedef;
|
||||
WORD side;
|
||||
DWORD partner;
|
||||
};
|
||||
|
||||
#define NF_SUBSECTOR 0x8000
|
||||
#define NFX_SUBSECTOR 0x80000000
|
||||
|
||||
struct MapNode
|
||||
{
|
||||
short x,y,dx,dy;
|
||||
short bbox[2][4];
|
||||
WORD children[2];
|
||||
};
|
||||
|
||||
struct MapNodeExO
|
||||
{
|
||||
short x,y,dx,dy;
|
||||
short bbox[2][4];
|
||||
DWORD children[2];
|
||||
};
|
||||
|
||||
struct MapNodeEx
|
||||
{
|
||||
int x,y,dx,dy;
|
||||
short bbox[2][4];
|
||||
DWORD children[2];
|
||||
};
|
||||
|
||||
struct MapThing
|
||||
{
|
||||
short x;
|
||||
short y;
|
||||
short angle;
|
||||
short type;
|
||||
short flags;
|
||||
};
|
||||
|
||||
struct MapThing2
|
||||
{
|
||||
unsigned short thingid;
|
||||
short x;
|
||||
short y;
|
||||
short z;
|
||||
short angle;
|
||||
short type;
|
||||
short flags;
|
||||
char special;
|
||||
char args[5];
|
||||
};
|
||||
|
||||
struct IntThing
|
||||
{
|
||||
unsigned short thingid;
|
||||
fixed_t x; // full precision coordinates for UDMF support
|
||||
fixed_t y;
|
||||
// everything else is not needed or has no extended form in UDMF
|
||||
short z;
|
||||
short angle;
|
||||
short type;
|
||||
short flags;
|
||||
char special;
|
||||
char args[5];
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
||||
struct IntVertex
|
||||
{
|
||||
TArray<UDMFKey> props;
|
||||
};
|
||||
|
||||
struct FLevel
|
||||
{
|
||||
FLevel ();
|
||||
~FLevel ();
|
||||
|
||||
WideVertex *Vertices; int NumVertices;
|
||||
TArray<IntVertex> VertexProps;
|
||||
TArray<IntSideDef> Sides;
|
||||
TArray<IntLineDef> Lines;
|
||||
TArray<IntSector> Sectors;
|
||||
TArray<IntThing> Things;
|
||||
MapSubsectorEx *Subsectors; int NumSubsectors;
|
||||
MapSegEx *Segs; int NumSegs;
|
||||
MapNodeEx *Nodes; int NumNodes;
|
||||
WORD *Blockmap; int BlockmapSize;
|
||||
BYTE *Reject; int RejectSize;
|
||||
|
||||
MapSubsectorEx *GLSubsectors; int NumGLSubsectors;
|
||||
MapSegGLEx *GLSegs; int NumGLSegs;
|
||||
MapNodeEx *GLNodes; int NumGLNodes;
|
||||
WideVertex *GLVertices; int NumGLVertices;
|
||||
BYTE *GLPVS; int GLPVSSize;
|
||||
|
||||
int NumOrgVerts;
|
||||
|
||||
DWORD *OrgSectorMap; int NumOrgSectors;
|
||||
|
||||
fixed_t MinX, MinY, MaxX, MaxY;
|
||||
|
||||
TArray<UDMFKey> props;
|
||||
|
||||
void FindMapBounds ();
|
||||
void RemoveExtraLines ();
|
||||
void RemoveExtraSides ();
|
||||
void RemoveExtraSectors ();
|
||||
|
||||
int NumSides() const { return Sides.Size(); }
|
||||
int NumLines() const { return Lines.Size(); }
|
||||
int NumSectors() const { return Sectors.Size(); }
|
||||
int NumThings() const { return Things.Size(); }
|
||||
};
|
||||
|
||||
const int BLOCKSIZE = 128;
|
||||
const int BLOCKFRACSIZE = BLOCKSIZE<<FRACBITS;
|
||||
const int BLOCKBITS = 7;
|
||||
const int BLOCKFRACBITS = FRACBITS+7;
|
1762
src/level/level.cpp
Normal file
1762
src/level/level.cpp
Normal file
File diff suppressed because it is too large
Load diff
126
src/level/level.h
Normal file
126
src/level/level.h
Normal file
|
@ -0,0 +1,126 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "wad/wad.h"
|
||||
#include "level/doomdata.h"
|
||||
#include "level/workdata.h"
|
||||
#include "framework/tarray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
#include "blockmapbuilder/blockmapbuilder.h"
|
||||
#include <zlib.h>
|
||||
|
||||
class ZLibOut
|
||||
{
|
||||
public:
|
||||
ZLibOut (FWadWriter &out);
|
||||
~ZLibOut ();
|
||||
|
||||
ZLibOut &operator << (BYTE);
|
||||
ZLibOut &operator << (WORD);
|
||||
ZLibOut &operator << (SWORD);
|
||||
ZLibOut &operator << (DWORD);
|
||||
ZLibOut &operator << (fixed_t);
|
||||
void Write (BYTE *data, int len);
|
||||
|
||||
private:
|
||||
enum { BUFFER_SIZE = 8192 };
|
||||
|
||||
z_stream Stream;
|
||||
BYTE Buffer[BUFFER_SIZE];
|
||||
|
||||
FWadWriter &Out;
|
||||
};
|
||||
|
||||
class FProcessor
|
||||
{
|
||||
public:
|
||||
FProcessor (FWadReader &inwad, int lump);
|
||||
|
||||
void Write (FWadWriter &out);
|
||||
|
||||
private:
|
||||
void LoadUDMF();
|
||||
void LoadThings ();
|
||||
void LoadLines ();
|
||||
void LoadVertices ();
|
||||
void LoadSides ();
|
||||
void LoadSectors ();
|
||||
void GetPolySpots ();
|
||||
|
||||
MapNodeEx *NodesToEx (const MapNode *nodes, int count);
|
||||
MapSubsectorEx *SubsectorsToEx (const MapSubsector *ssec, int count);
|
||||
MapSegGLEx *SegGLsToEx (const MapSegGL *segs, int count);
|
||||
|
||||
BYTE *FixReject (const BYTE *oldreject);
|
||||
bool CheckForFracSplitters(const MapNodeEx *nodes, int count);
|
||||
|
||||
void WriteLines (FWadWriter &out);
|
||||
void WriteVertices (FWadWriter &out, int count);
|
||||
void WriteSectors (FWadWriter &out);
|
||||
void WriteSides (FWadWriter &out);
|
||||
void WriteSegs (FWadWriter &out);
|
||||
void WriteSSectors (FWadWriter &out) const;
|
||||
void WriteNodes (FWadWriter &out) const;
|
||||
void WriteBlockmap (FWadWriter &out);
|
||||
void WriteReject (FWadWriter &out);
|
||||
|
||||
void WriteGLVertices (FWadWriter &out, bool v5);
|
||||
void WriteGLSegs (FWadWriter &out, bool v5);
|
||||
void WriteGLSegs5 (FWadWriter &out);
|
||||
void WriteGLSSect (FWadWriter &out, bool v5);
|
||||
void WriteGLNodes (FWadWriter &out, bool v5);
|
||||
|
||||
void WriteBSPZ (FWadWriter &out, const char *label);
|
||||
void WriteGLBSPZ (FWadWriter &out, const char *label);
|
||||
|
||||
void WriteVerticesZ (ZLibOut &out, const WideVertex *verts, int orgverts, int newverts);
|
||||
void WriteSubsectorsZ (ZLibOut &out, const MapSubsectorEx *subs, int numsubs);
|
||||
void WriteSegsZ (ZLibOut &out, const MapSegEx *segs, int numsegs);
|
||||
void WriteGLSegsZ (ZLibOut &out, const MapSegGLEx *segs, int numsegs, int nodever);
|
||||
void WriteNodesZ (ZLibOut &out, const MapNodeEx *nodes, int numnodes, int nodever);
|
||||
|
||||
void WriteBSPX (FWadWriter &out, const char *label);
|
||||
void WriteGLBSPX (FWadWriter &out, const char *label);
|
||||
|
||||
void WriteVerticesX (FWadWriter &out, const WideVertex *verts, int orgverts, int newverts);
|
||||
void WriteSubsectorsX (FWadWriter &out, const MapSubsectorEx *subs, int numsubs);
|
||||
void WriteSegsX (FWadWriter &out, const MapSegEx *segs, int numsegs);
|
||||
void WriteGLSegsX (FWadWriter &out, const MapSegGLEx *segs, int numsegs, int nodever);
|
||||
void WriteNodesX (FWadWriter &out, const MapNodeEx *nodes, int numnodes, int nodever);
|
||||
|
||||
void WriteNodes2 (FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const;
|
||||
void WriteSSectors2 (FWadWriter &out, const char *name, const MapSubsectorEx *zaSubs, int count) const;
|
||||
void WriteNodes5 (FWadWriter &out, const char *name, const MapNodeEx *zaNodes, int count) const;
|
||||
void WriteSSectors5 (FWadWriter &out, const char *name, const MapSubsectorEx *zaSubs, int count) const;
|
||||
|
||||
const char *ParseKey(const char *&value);
|
||||
bool CheckKey(const char *&key, const char *&value);
|
||||
void ParseThing(IntThing *th);
|
||||
void ParseLinedef(IntLineDef *ld);
|
||||
void ParseSidedef(IntSideDef *sd);
|
||||
void ParseSector(IntSector *sec);
|
||||
void ParseVertex(WideVertex *vt, IntVertex *vtp);
|
||||
void ParseMapProperties();
|
||||
void ParseTextMap(int lump);
|
||||
|
||||
void WriteProps(FWadWriter &out, TArray<UDMFKey> &props);
|
||||
void WriteIntProp(FWadWriter &out, const char *key, int value);
|
||||
void WriteThingUDMF(FWadWriter &out, IntThing *th, int num);
|
||||
void WriteLinedefUDMF(FWadWriter &out, IntLineDef *ld, int num);
|
||||
void WriteSidedefUDMF(FWadWriter &out, IntSideDef *sd, int num);
|
||||
void WriteSectorUDMF(FWadWriter &out, IntSector *sec, int num);
|
||||
void WriteVertexUDMF(FWadWriter &out, IntVertex *vt, int num);
|
||||
void WriteTextMap(FWadWriter &out);
|
||||
void WriteUDMF(FWadWriter &out);
|
||||
|
||||
FLevel Level;
|
||||
|
||||
TArray<FNodeBuilder::FPolyStart> PolyStarts;
|
||||
TArray<FNodeBuilder::FPolyStart> PolyAnchors;
|
||||
|
||||
bool Extended;
|
||||
bool isUDMF;
|
||||
|
||||
FWadReader &Wad;
|
||||
int Lump;
|
||||
};
|
606
src/level/level_udmf.cpp
Normal file
606
src/level/level_udmf.cpp
Normal file
|
@ -0,0 +1,606 @@
|
|||
/*
|
||||
Reads and writes UDMF maps
|
||||
Copyright (C) 2009 Christoph Oelckers
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <float.h>
|
||||
#include "level/level.h"
|
||||
#include "parse/sc_man.h"
|
||||
|
||||
typedef double real64;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
#include "framework/xs_Float.h"
|
||||
|
||||
|
||||
class StringBuffer
|
||||
{
|
||||
const static size_t BLOCK_SIZE = 100000;
|
||||
const static size_t BLOCK_ALIGN = sizeof(size_t);
|
||||
|
||||
TDeletingArray<char *> blocks;
|
||||
size_t currentindex;
|
||||
|
||||
char *Alloc(size_t size)
|
||||
{
|
||||
if (currentindex + size >= BLOCK_SIZE)
|
||||
{
|
||||
// Block is full - get a new one!
|
||||
char *newblock = new char[BLOCK_SIZE];
|
||||
blocks.Push(newblock);
|
||||
currentindex = 0;
|
||||
}
|
||||
size = (size + BLOCK_ALIGN-1) &~ (BLOCK_ALIGN-1);
|
||||
char *p = blocks[blocks.Size()-1] + currentindex;
|
||||
currentindex += size;
|
||||
return p;
|
||||
}
|
||||
public:
|
||||
|
||||
StringBuffer()
|
||||
{
|
||||
currentindex = BLOCK_SIZE;
|
||||
}
|
||||
|
||||
char * Copy(const char * p)
|
||||
{
|
||||
return p != NULL? strcpy(Alloc(strlen(p)+1) , p) : NULL;
|
||||
}
|
||||
};
|
||||
|
||||
StringBuffer stbuf;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parses a 'key = value;' line of the map
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
const char *FProcessor::ParseKey(const char *&value)
|
||||
{
|
||||
SC_MustGetString();
|
||||
const char *key = stbuf.Copy(sc_String);
|
||||
SC_MustGetStringName("=");
|
||||
|
||||
sc_Number = INT_MIN;
|
||||
sc_Float = DBL_MIN;
|
||||
if (!SC_CheckFloat())
|
||||
{
|
||||
SC_MustGetString();
|
||||
}
|
||||
value = stbuf.Copy(sc_String);
|
||||
SC_MustGetStringName(";");
|
||||
return key;
|
||||
}
|
||||
|
||||
bool FProcessor::CheckKey(const char *&key, const char *&value)
|
||||
{
|
||||
SC_SavePos();
|
||||
SC_MustGetString();
|
||||
if (SC_CheckString("="))
|
||||
{
|
||||
SC_RestorePos();
|
||||
key = ParseKey(value);
|
||||
return true;
|
||||
}
|
||||
SC_RestorePos();
|
||||
return false;
|
||||
}
|
||||
|
||||
int CheckInt(const char *key)
|
||||
{
|
||||
if (sc_Number == INT_MIN)
|
||||
{
|
||||
SC_ScriptError("Integer value expected for key '%s'", key);
|
||||
}
|
||||
return sc_Number;
|
||||
}
|
||||
|
||||
double CheckFloat(const char *key)
|
||||
{
|
||||
if (sc_Float == DBL_MIN)
|
||||
{
|
||||
SC_ScriptError("Floating point value expected for key '%s'", key);
|
||||
}
|
||||
return sc_Float;
|
||||
}
|
||||
|
||||
fixed_t CheckFixed(const char *key)
|
||||
{
|
||||
double val = CheckFloat(key);
|
||||
if (val < -32768 || val > 32767)
|
||||
{
|
||||
SC_ScriptError("Fixed point value is out of range for key '%s'\n\t%.2f should be within [-32768,32767]", key, val / 65536);
|
||||
}
|
||||
return xs_Fix<16>::ToFix(val);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a thing block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseThing(IntThing *th)
|
||||
{
|
||||
SC_MustGetStringName("{");
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
const char *value;
|
||||
const char *key = ParseKey(value);
|
||||
|
||||
// The only properties we need from a thing are
|
||||
// x, y, angle and type.
|
||||
|
||||
if (!stricmp(key, "x"))
|
||||
{
|
||||
th->x = CheckFixed(key);
|
||||
}
|
||||
else if (!stricmp(key, "y"))
|
||||
{
|
||||
th->y = CheckFixed(key);
|
||||
}
|
||||
if (!stricmp(key, "angle"))
|
||||
{
|
||||
th->angle = (short)CheckInt(key);
|
||||
}
|
||||
if (!stricmp(key, "type"))
|
||||
{
|
||||
th->type = (short)CheckInt(key);
|
||||
}
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
th->props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a linedef block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseLinedef(IntLineDef *ld)
|
||||
{
|
||||
SC_MustGetStringName("{");
|
||||
ld->v1 = ld->v2 = ld->sidenum[0] = ld->sidenum[1] = NO_INDEX;
|
||||
ld->special = 0;
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
const char *value;
|
||||
const char *key = ParseKey(value);
|
||||
|
||||
if (!stricmp(key, "v1"))
|
||||
{
|
||||
ld->v1 = CheckInt(key);
|
||||
continue; // do not store in props
|
||||
}
|
||||
else if (!stricmp(key, "v2"))
|
||||
{
|
||||
ld->v2 = CheckInt(key);
|
||||
continue; // do not store in props
|
||||
}
|
||||
else if (Extended && !stricmp(key, "special"))
|
||||
{
|
||||
ld->special = CheckInt(key);
|
||||
}
|
||||
else if (Extended && !stricmp(key, "arg0"))
|
||||
{
|
||||
ld->args[0] = CheckInt(key);
|
||||
}
|
||||
if (!stricmp(key, "sidefront"))
|
||||
{
|
||||
ld->sidenum[0] = CheckInt(key);
|
||||
continue; // do not store in props
|
||||
}
|
||||
else if (!stricmp(key, "sideback"))
|
||||
{
|
||||
ld->sidenum[1] = CheckInt(key);
|
||||
continue; // do not store in props
|
||||
}
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
ld->props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a sidedef block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseSidedef(IntSideDef *sd)
|
||||
{
|
||||
SC_MustGetStringName("{");
|
||||
sd->sector = NO_INDEX;
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
const char *value;
|
||||
const char *key = ParseKey(value);
|
||||
|
||||
if (!stricmp(key, "sector"))
|
||||
{
|
||||
sd->sector = CheckInt(key);
|
||||
continue; // do not store in props
|
||||
}
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
sd->props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a sidedef block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseSector(IntSector *sec)
|
||||
{
|
||||
SC_MustGetStringName("{");
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
const char *value;
|
||||
const char *key = ParseKey(value);
|
||||
|
||||
// No specific sector properties are ever used by the node builder
|
||||
// so everything can go directly to the props array.
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
sec->props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// parse a vertex block
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseVertex(WideVertex *vt, IntVertex *vtp)
|
||||
{
|
||||
vt->x = vt->y = 0;
|
||||
SC_MustGetStringName("{");
|
||||
while (!SC_CheckString("}"))
|
||||
{
|
||||
const char *value;
|
||||
const char *key = ParseKey(value);
|
||||
|
||||
if (!stricmp(key, "x"))
|
||||
{
|
||||
vt->x = CheckFixed(key);
|
||||
}
|
||||
else if (!stricmp(key, "y"))
|
||||
{
|
||||
vt->y = CheckFixed(key);
|
||||
}
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
vtp->props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// parses global map properties
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseMapProperties()
|
||||
{
|
||||
const char *key, *value;
|
||||
|
||||
// all global keys must come before the first map element.
|
||||
|
||||
while (CheckKey(key, value))
|
||||
{
|
||||
if (!stricmp(key, "namespace"))
|
||||
{
|
||||
// all unknown namespaces are assumed to be standard.
|
||||
Extended = !stricmp(value, "\"ZDoom\"") || !stricmp(value, "\"Hexen\"") || !stricmp(value, "\"Vavoom\"");
|
||||
}
|
||||
|
||||
// now store the key in its unprocessed form
|
||||
UDMFKey k = {key, value};
|
||||
Level.props.Push(k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Main parsing function
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::ParseTextMap(int lump)
|
||||
{
|
||||
char *buffer;
|
||||
int buffersize;
|
||||
TArray<WideVertex> Vertices;
|
||||
|
||||
ReadLump<char> (Wad, lump, buffer, buffersize);
|
||||
SC_OpenMem("TEXTMAP", buffer, buffersize);
|
||||
|
||||
SC_SetCMode(true);
|
||||
ParseMapProperties();
|
||||
|
||||
while (SC_GetString())
|
||||
{
|
||||
if (SC_Compare("thing"))
|
||||
{
|
||||
IntThing *th = &Level.Things[Level.Things.Reserve(1)];
|
||||
ParseThing(th);
|
||||
}
|
||||
else if (SC_Compare("linedef"))
|
||||
{
|
||||
IntLineDef *ld = &Level.Lines[Level.Lines.Reserve(1)];
|
||||
ParseLinedef(ld);
|
||||
}
|
||||
else if (SC_Compare("sidedef"))
|
||||
{
|
||||
IntSideDef *sd = &Level.Sides[Level.Sides.Reserve(1)];
|
||||
ParseSidedef(sd);
|
||||
}
|
||||
else if (SC_Compare("sector"))
|
||||
{
|
||||
IntSector *sec = &Level.Sectors[Level.Sectors.Reserve(1)];
|
||||
ParseSector(sec);
|
||||
}
|
||||
else if (SC_Compare("vertex"))
|
||||
{
|
||||
WideVertex *vt = &Vertices[Vertices.Reserve(1)];
|
||||
IntVertex *vtp = &Level.VertexProps[Level.VertexProps.Reserve(1)];
|
||||
vt->index = Vertices.Size();
|
||||
ParseVertex(vt, vtp);
|
||||
}
|
||||
}
|
||||
Level.Vertices = new WideVertex[Vertices.Size()];
|
||||
Level.NumVertices = Vertices.Size();
|
||||
memcpy(Level.Vertices, &Vertices[0], Vertices.Size() * sizeof(WideVertex));
|
||||
SC_Close();
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// parse an UDMF map
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::LoadUDMF()
|
||||
{
|
||||
ParseTextMap(Lump+1);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a property list
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteProps(FWadWriter &out, TArray<UDMFKey> &props)
|
||||
{
|
||||
for(unsigned i=0; i< props.Size(); i++)
|
||||
{
|
||||
out.AddToLump(props[i].key, (int)strlen(props[i].key));
|
||||
out.AddToLump(" = ", 3);
|
||||
out.AddToLump(props[i].value, (int)strlen(props[i].value));
|
||||
out.AddToLump(";\n", 2);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes an integer property
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteIntProp(FWadWriter &out, const char *key, int value)
|
||||
{
|
||||
char buffer[20];
|
||||
|
||||
out.AddToLump(key, (int)strlen(key));
|
||||
out.AddToLump(" = ", 3);
|
||||
sprintf(buffer, "%d;\n", value);
|
||||
out.AddToLump(buffer, (int)strlen(buffer));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF thing
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteThingUDMF(FWadWriter &out, IntThing *th, int num)
|
||||
{
|
||||
out.AddToLump("thing", 5);
|
||||
if (WriteComments)
|
||||
{
|
||||
char buffer[32];
|
||||
int len = sprintf(buffer, " // %d", num);
|
||||
out.AddToLump(buffer, len);
|
||||
}
|
||||
out.AddToLump("\n{\n", 3);
|
||||
WriteProps(out, th->props);
|
||||
out.AddToLump("}\n\n", 3);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF linedef
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteLinedefUDMF(FWadWriter &out, IntLineDef *ld, int num)
|
||||
{
|
||||
out.AddToLump("linedef", 7);
|
||||
if (WriteComments)
|
||||
{
|
||||
char buffer[32];
|
||||
int len = sprintf(buffer, " // %d", num);
|
||||
out.AddToLump(buffer, len);
|
||||
}
|
||||
out.AddToLump("\n{\n", 3);
|
||||
WriteIntProp(out, "v1", ld->v1);
|
||||
WriteIntProp(out, "v2", ld->v2);
|
||||
if (ld->sidenum[0] != NO_INDEX) WriteIntProp(out, "sidefront", ld->sidenum[0]);
|
||||
if (ld->sidenum[1] != NO_INDEX) WriteIntProp(out, "sideback", ld->sidenum[1]);
|
||||
WriteProps(out, ld->props);
|
||||
out.AddToLump("}\n\n", 3);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF sidedef
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteSidedefUDMF(FWadWriter &out, IntSideDef *sd, int num)
|
||||
{
|
||||
out.AddToLump("sidedef", 7);
|
||||
if (WriteComments)
|
||||
{
|
||||
char buffer[32];
|
||||
int len = sprintf(buffer, " // %d", num);
|
||||
out.AddToLump(buffer, len);
|
||||
}
|
||||
out.AddToLump("\n{\n", 3);
|
||||
WriteIntProp(out, "sector", sd->sector);
|
||||
WriteProps(out, sd->props);
|
||||
out.AddToLump("}\n\n", 3);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF sector
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteSectorUDMF(FWadWriter &out, IntSector *sec, int num)
|
||||
{
|
||||
out.AddToLump("sector", 6);
|
||||
if (WriteComments)
|
||||
{
|
||||
char buffer[32];
|
||||
int len = sprintf(buffer, " // %d", num);
|
||||
out.AddToLump(buffer, len);
|
||||
}
|
||||
out.AddToLump("\n{\n", 3);
|
||||
WriteProps(out, sec->props);
|
||||
out.AddToLump("}\n\n", 3);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF vertex
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteVertexUDMF(FWadWriter &out, IntVertex *vt, int num)
|
||||
{
|
||||
out.AddToLump("vertex", 6);
|
||||
if (WriteComments)
|
||||
{
|
||||
char buffer[32];
|
||||
int len = sprintf(buffer, " // %d", num);
|
||||
out.AddToLump(buffer, len);
|
||||
}
|
||||
out.AddToLump("\n{\n", 3);
|
||||
WriteProps(out, vt->props);
|
||||
out.AddToLump("}\n\n", 3);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes a UDMF text map
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteTextMap(FWadWriter &out)
|
||||
{
|
||||
out.StartWritingLump("TEXTMAP");
|
||||
WriteProps(out, Level.props);
|
||||
for(int i = 0; i < Level.NumThings(); i++)
|
||||
{
|
||||
WriteThingUDMF(out, &Level.Things[i], i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < Level.NumOrgVerts; i++)
|
||||
{
|
||||
WideVertex *vt = &Level.Vertices[i];
|
||||
if (vt->index <= 0)
|
||||
{
|
||||
// not valid!
|
||||
throw std::runtime_error("Invalid vertex data.");
|
||||
}
|
||||
WriteVertexUDMF(out, &Level.VertexProps[vt->index-1], i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < Level.NumLines(); i++)
|
||||
{
|
||||
WriteLinedefUDMF(out, &Level.Lines[i], i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < Level.NumSides(); i++)
|
||||
{
|
||||
WriteSidedefUDMF(out, &Level.Sides[i], i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < Level.NumSectors(); i++)
|
||||
{
|
||||
WriteSectorUDMF(out, &Level.Sectors[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// writes an UDMF map
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FProcessor::WriteUDMF(FWadWriter &out)
|
||||
{
|
||||
out.CopyLump (Wad, Lump);
|
||||
WriteTextMap(out);
|
||||
if (ForceCompression) WriteGLBSPZ (out, "ZNODES");
|
||||
else WriteGLBSPX (out, "ZNODES");
|
||||
|
||||
// copy everything except existing nodes, blockmap and reject
|
||||
for(int i=Lump+2; stricmp(Wad.LumpName(i), "ENDMAP") && i < Wad.NumLumps(); i++)
|
||||
{
|
||||
const char *lumpname = Wad.LumpName(i);
|
||||
if (stricmp(lumpname, "ZNODES") &&
|
||||
stricmp(lumpname, "BLOCKMAP") &&
|
||||
stricmp(lumpname, "REJECT"))
|
||||
{
|
||||
out.CopyLump(Wad, i);
|
||||
}
|
||||
}
|
||||
out.CreateLabel("ENDMAP");
|
||||
}
|
22
src/level/workdata.h
Normal file
22
src/level/workdata.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "framework/zdray.h"
|
||||
|
||||
struct vertex_t
|
||||
{
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
struct node_t
|
||||
{
|
||||
fixed_t x, y, dx, dy;
|
||||
fixed_t bbox[2][4];
|
||||
unsigned int intchildren[2];
|
||||
};
|
||||
|
||||
struct subsector_t
|
||||
{
|
||||
DWORD numlines;
|
||||
DWORD firstline;
|
||||
};
|
1148
src/nodebuilder/nodebuild.cpp
Normal file
1148
src/nodebuilder/nodebuild.cpp
Normal file
File diff suppressed because it is too large
Load diff
322
src/nodebuilder/nodebuild.h
Normal file
322
src/nodebuilder/nodebuild.h
Normal file
|
@ -0,0 +1,322 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include "level/doomdata.h"
|
||||
#include "level/workdata.h"
|
||||
#include "framework/tarray.h"
|
||||
|
||||
struct FEventInfo
|
||||
{
|
||||
int Vertex;
|
||||
DWORD FrontSeg;
|
||||
};
|
||||
|
||||
struct FEvent
|
||||
{
|
||||
FEvent *Parent, *Left, *Right;
|
||||
double Distance;
|
||||
FEventInfo Info;
|
||||
};
|
||||
|
||||
class FEventTree
|
||||
{
|
||||
public:
|
||||
FEventTree ();
|
||||
~FEventTree ();
|
||||
|
||||
FEvent *GetMinimum ();
|
||||
FEvent *GetSuccessor (FEvent *event) const { FEvent *node = Successor(event); return node == &Nil ? NULL : node; }
|
||||
FEvent *GetPredecessor (FEvent *event) const { FEvent *node = Predecessor(event); return node == &Nil ? NULL : node; }
|
||||
|
||||
FEvent *GetNewNode ();
|
||||
void Insert (FEvent *event);
|
||||
FEvent *FindEvent (double distance) const;
|
||||
void DeleteAll ();
|
||||
|
||||
void PrintTree () const { PrintTree (Root); }
|
||||
|
||||
private:
|
||||
FEvent Nil;
|
||||
FEvent *Root;
|
||||
FEvent *Spare;
|
||||
|
||||
void DeletionTraverser (FEvent *event);
|
||||
FEvent *Successor (FEvent *event) const;
|
||||
FEvent *Predecessor (FEvent *event) const;
|
||||
|
||||
void PrintTree (const FEvent *event) const;
|
||||
};
|
||||
|
||||
struct FSimpleVert
|
||||
{
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||
#ifndef DISABLE_SSE
|
||||
int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||
int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||
#ifdef BACKPATCH
|
||||
#ifdef __GNUC__
|
||||
int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) __attribute__((noinline));
|
||||
#else
|
||||
int __declspec(noinline) ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
class FNodeBuilder
|
||||
{
|
||||
struct FPrivSeg
|
||||
{
|
||||
int v1, v2;
|
||||
DWORD sidedef;
|
||||
int linedef;
|
||||
int frontsector;
|
||||
int backsector;
|
||||
DWORD next;
|
||||
DWORD nextforvert;
|
||||
DWORD nextforvert2;
|
||||
int loopnum; // loop number for split avoidance (0 means splitting is okay)
|
||||
DWORD partner; // seg on back side
|
||||
DWORD storedseg; // seg # in the GL_SEGS lump
|
||||
angle_t angle;
|
||||
fixed_t offset;
|
||||
|
||||
int planenum;
|
||||
bool planefront;
|
||||
FPrivSeg *hashnext;
|
||||
};
|
||||
struct FPrivVert : FSimpleVert
|
||||
{
|
||||
DWORD segs; // segs that use this vertex as v1
|
||||
DWORD segs2; // segs that use this vertex as v2
|
||||
int index;
|
||||
int pad; // This structure must be 8-byte aligned.
|
||||
|
||||
bool operator== (const FPrivVert &other)
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
struct FSimpleLine
|
||||
{
|
||||
fixed_t x, y, dx, dy;
|
||||
};
|
||||
union USegPtr
|
||||
{
|
||||
DWORD SegNum;
|
||||
FPrivSeg *SegPtr;
|
||||
};
|
||||
struct FSplitSharer
|
||||
{
|
||||
double Distance;
|
||||
DWORD Seg;
|
||||
bool Forward;
|
||||
};
|
||||
|
||||
// Like a blockmap, but for vertices instead of lines
|
||||
class FVertexMap
|
||||
{
|
||||
public:
|
||||
FVertexMap (FNodeBuilder &builder, fixed_t minx, fixed_t miny, fixed_t maxx, fixed_t maxy);
|
||||
~FVertexMap ();
|
||||
|
||||
int SelectVertexExact (FPrivVert &vert);
|
||||
int SelectVertexClose (FPrivVert &vert);
|
||||
|
||||
private:
|
||||
FNodeBuilder &MyBuilder;
|
||||
TArray<int> *VertexGrid;
|
||||
|
||||
fixed_t MinX, MinY, MaxX, MaxY;
|
||||
int BlocksWide, BlocksTall;
|
||||
|
||||
enum { BLOCK_SHIFT = 8 + FRACBITS };
|
||||
enum { BLOCK_SIZE = 1 << BLOCK_SHIFT };
|
||||
|
||||
int InsertVertex (FPrivVert &vert);
|
||||
inline int GetBlock (fixed_t x, fixed_t y)
|
||||
{
|
||||
assert (x >= MinX);
|
||||
assert (y >= MinY);
|
||||
assert (x <= MaxX);
|
||||
assert (y <= MaxY);
|
||||
return (unsigned(x - MinX) >> BLOCK_SHIFT) + (unsigned(y - MinY) >> BLOCK_SHIFT) * BlocksWide;
|
||||
}
|
||||
};
|
||||
|
||||
friend class FVertexMap;
|
||||
|
||||
|
||||
public:
|
||||
struct FPolyStart
|
||||
{
|
||||
int polynum;
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
FNodeBuilder (FLevel &level,
|
||||
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
||||
const char *name, bool makeGLnodes);
|
||||
~FNodeBuilder ();
|
||||
|
||||
void GetVertices (WideVertex *&verts, int &count);
|
||||
void GetNodes (MapNodeEx *&nodes, int &nodeCount,
|
||||
MapSegEx *&segs, int &segCount,
|
||||
MapSubsectorEx *&ssecs, int &subCount);
|
||||
|
||||
void GetGLNodes (MapNodeEx *&nodes, int &nodeCount,
|
||||
MapSegGLEx *&segs, int &segCount,
|
||||
MapSubsectorEx *&ssecs, int &subCount);
|
||||
|
||||
// < 0 : in front of line
|
||||
// == 0 : on line
|
||||
// > 0 : behind line
|
||||
|
||||
static inline int PointOnSide (int x, int y, int x1, int y1, int dx, int dy);
|
||||
|
||||
private:
|
||||
FVertexMap *VertexMap;
|
||||
|
||||
TArray<node_t> Nodes;
|
||||
TArray<subsector_t> Subsectors;
|
||||
TArray<DWORD> SubsectorSets;
|
||||
TArray<FPrivSeg> Segs;
|
||||
TArray<FPrivVert> Vertices;
|
||||
TArray<USegPtr> SegList;
|
||||
TArray<BYTE> PlaneChecked;
|
||||
TArray<FSimpleLine> Planes;
|
||||
size_t InitialVertices; // Number of vertices in a map that are connected to linedefs
|
||||
|
||||
TArray<int> Touched; // Loops a splitter touches on a vertex
|
||||
TArray<int> Colinear; // Loops with edges colinear to a splitter
|
||||
FEventTree Events; // Vertices intersected by the current splitter
|
||||
TArray<FSplitSharer> SplitSharers; // Segs collinear with the current splitter
|
||||
|
||||
DWORD HackSeg; // Seg to force to back of splitter
|
||||
DWORD HackMate; // Seg to use in front of hack seg
|
||||
FLevel &Level;
|
||||
bool GLNodes;
|
||||
|
||||
// Progress meter stuff
|
||||
int SegsStuffed;
|
||||
const char *MapName;
|
||||
|
||||
void FindUsedVertices (WideVertex *vertices, int max);
|
||||
void BuildTree ();
|
||||
void MakeSegsFromSides ();
|
||||
int CreateSeg (int linenum, int sidenum);
|
||||
void GroupSegPlanes ();
|
||||
void FindPolyContainers (TArray<FPolyStart> &spots, TArray<FPolyStart> &anchors);
|
||||
bool GetPolyExtents (int polynum, fixed_t bbox[4]);
|
||||
int MarkLoop (DWORD firstseg, int loopnum);
|
||||
void AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg);
|
||||
DWORD CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]);
|
||||
DWORD CreateSubsector (DWORD set, fixed_t bbox[4]);
|
||||
void CreateSubsectorsForReal ();
|
||||
bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg);
|
||||
bool CheckSubsectorOverlappingSegs (DWORD set, node_t &node, DWORD &splitseg);
|
||||
bool ShoveSegBehind (DWORD set, node_t &node, DWORD seg, DWORD mate);
|
||||
int SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int step, bool nosplit);
|
||||
void SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &outset0, DWORD &outset1, unsigned int &count0, unsigned int &count1);
|
||||
DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront);
|
||||
int Heuristic (node_t &node, DWORD set, bool honorNoSplit);
|
||||
|
||||
// Returns:
|
||||
// 0 = seg is in front
|
||||
// 1 = seg is in back
|
||||
// -1 = seg cuts the node
|
||||
|
||||
inline int ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]);
|
||||
|
||||
void FixSplitSharers ();
|
||||
double AddIntersection (const node_t &node, int vertex);
|
||||
void AddMinisegs (const node_t &node, DWORD splitseg, DWORD &fset, DWORD &rset);
|
||||
DWORD CheckLoopStart (fixed_t dx, fixed_t dy, int vertex1, int vertex2);
|
||||
DWORD CheckLoopEnd (fixed_t dx, fixed_t dy, int vertex2);
|
||||
void RemoveSegFromVert1 (DWORD segnum, int vertnum);
|
||||
void RemoveSegFromVert2 (DWORD segnum, int vertnum);
|
||||
DWORD AddMiniseg (int v1, int v2, DWORD partner, DWORD seg1, DWORD splitseg);
|
||||
void SetNodeFromSeg (node_t &node, const FPrivSeg *pseg) const;
|
||||
|
||||
int RemoveMinisegs (MapNodeEx *nodes, TArray<MapSegEx> &segs, MapSubsectorEx *subs, int node, short bbox[4]);
|
||||
int StripMinisegs (TArray<MapSegEx> &segs, int subsector, short bbox[4]);
|
||||
void AddSegToShortBBox (short bbox[4], const FPrivSeg *seg);
|
||||
int CloseSubsector (TArray<MapSegGLEx> &segs, int subsector);
|
||||
DWORD PushGLSeg (TArray<MapSegGLEx> &segs, const FPrivSeg *seg);
|
||||
void PushConnectingGLSeg (int subsector, TArray<MapSegGLEx> &segs, int v1, int v2);
|
||||
int OutputDegenerateSubsector (TArray<MapSegGLEx> &segs, int subsector, bool bForward, double lastdot, FPrivSeg *&prev);
|
||||
|
||||
static int SortSegs (const void *a, const void *b);
|
||||
|
||||
double InterceptVector (const node_t &splitter, const FPrivSeg &seg);
|
||||
|
||||
void PrintSet (int l, DWORD set);
|
||||
void DumpNodes(MapNodeEx *outNodes, int nodeCount);
|
||||
};
|
||||
|
||||
// Points within this distance of a line will be considered on the line.
|
||||
// Units are in fixed_ts.
|
||||
const double SIDE_EPSILON = 6.5536;
|
||||
|
||||
// Vertices within this distance of each other will be considered as the same vertex.
|
||||
#define VERTEX_EPSILON 6 // This is a fixed_t value
|
||||
|
||||
inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int dy)
|
||||
{
|
||||
// For most cases, a simple dot product is enough.
|
||||
double d_dx = double(dx);
|
||||
double d_dy = double(dy);
|
||||
double d_x = double(x);
|
||||
double d_y = double(y);
|
||||
double d_x1 = double(x1);
|
||||
double d_y1 = double(y1);
|
||||
|
||||
double s_num = (d_y1-d_y)*d_dx - (d_x1-d_x)*d_dy;
|
||||
|
||||
if (fabs(s_num) < 17179869184.f) // 4<<32
|
||||
{
|
||||
// Either the point is very near the line, or the segment defining
|
||||
// the line is very short: Do a more expensive test to determine
|
||||
// just how far from the line the point is.
|
||||
double l = d_dx*d_dx + d_dy*d_dy; // double l = sqrt(d_dx*d_dx+d_dy*d_dy);
|
||||
double dist = s_num * s_num / l; // double dist = fabs(s_num)/l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON) // if (dist < SIDE_EPSILON)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return s_num > 0.0 ? -1 : 1;
|
||||
}
|
||||
|
||||
inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2])
|
||||
{
|
||||
#ifdef DISABLE_SSE
|
||||
return ClassifyLine2 (node, v1, v2, sidev);
|
||||
#else
|
||||
#if defined(__SSE2__) || defined(_M_X64)
|
||||
// If compiling with SSE2 support everywhere, just use the SSE2 version.
|
||||
return ClassifyLineSSE2 (node, v1, v2, sidev);
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1300
|
||||
// VC 6 does not support SSE optimizations.
|
||||
return ClassifyLine2 (node, v1, v2, sidev);
|
||||
#else
|
||||
// Select the routine based on our flag.
|
||||
#ifdef BACKPATCH
|
||||
return ClassifyLineBackpatch (node, v1, v2, sidev);
|
||||
#else
|
||||
if (SSELevel == 2)
|
||||
return ClassifyLineSSE2 (node, v1, v2, sidev);
|
||||
else if (SSELevel == 1)
|
||||
return ClassifyLineSSE1 (node, v1, v2, sidev);
|
||||
else
|
||||
return ClassifyLine2 (node, v1, v2, sidev);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
156
src/nodebuilder/nodebuild_classify_nosse2.cpp
Normal file
156
src/nodebuilder/nodebuild_classify_nosse2.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
Determine what side of a splitter a seg lies on.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
|
||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||
|
||||
extern "C" int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||
{
|
||||
double d_x1 = double(node.x);
|
||||
double d_y1 = double(node.y);
|
||||
double d_dx = double(node.dx);
|
||||
double d_dy = double(node.dy);
|
||||
double d_xv1 = double(v1->x);
|
||||
double d_xv2 = double(v2->x);
|
||||
double d_yv1 = double(v1->y);
|
||||
double d_yv2 = double(v2->y);
|
||||
|
||||
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
|
||||
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
|
||||
|
||||
int nears = 0;
|
||||
|
||||
if (s_num1 <= -FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = 1;
|
||||
return 1;
|
||||
}
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = 1;
|
||||
sidev[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else if (s_num1 >= FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = -1;
|
||||
sidev[1] = 1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nears = 2 | int(fabs(s_num2) < FAR_ENOUGH);
|
||||
}
|
||||
|
||||
if (nears)
|
||||
{
|
||||
double l = 1.f / (d_dx*d_dx + d_dy*d_dy);
|
||||
if (nears & 2)
|
||||
{
|
||||
double dist = s_num1 * s_num1 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
if (nears & 1)
|
||||
{
|
||||
double dist = s_num2 * s_num2 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
|
||||
if ((sidev[0] | sidev[1]) == 0)
|
||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||
// which child it ends up in. If it faces the same direction as the splitter,
|
||||
// it goes in front. Otherwise, it goes in back.
|
||||
|
||||
if (node.dx != 0)
|
||||
{
|
||||
if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sidev[0] <= 0 && sidev[1] <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (sidev[0] >= 0 && sidev[1] >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
164
src/nodebuilder/nodebuild_classify_sse1.cpp
Normal file
164
src/nodebuilder/nodebuild_classify_sse1.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Determine what side of a splitter a seg lies on. (SSE2 version)
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
|
||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||
|
||||
// You may notice that this function is identical to ClassifyLine2.
|
||||
// The reason it is SSE is because this file is explicitly compiled
|
||||
// with SSE math enabled, but the other files are not.
|
||||
|
||||
extern "C" int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||
{
|
||||
double d_x1 = double(node.x);
|
||||
double d_y1 = double(node.y);
|
||||
double d_dx = double(node.dx);
|
||||
double d_dy = double(node.dy);
|
||||
double d_xv1 = double(v1->x);
|
||||
double d_xv2 = double(v2->x);
|
||||
double d_yv1 = double(v1->y);
|
||||
double d_yv2 = double(v2->y);
|
||||
|
||||
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
|
||||
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
|
||||
|
||||
int nears = 0;
|
||||
|
||||
if (s_num1 <= -FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = 1;
|
||||
return 1;
|
||||
}
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = 1;
|
||||
sidev[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else if (s_num1 >= FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = -1;
|
||||
sidev[1] = 1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nears = 2 | int(fabs(s_num2) < FAR_ENOUGH);
|
||||
}
|
||||
|
||||
if (nears)
|
||||
{
|
||||
double l = 1.f / (d_dx*d_dx + d_dy*d_dy);
|
||||
if (nears & 2)
|
||||
{
|
||||
double dist = s_num1 * s_num1 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
if (nears & 1)
|
||||
{
|
||||
double dist = s_num2 * s_num2 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
|
||||
if ((sidev[0] | sidev[1]) == 0)
|
||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||
// which child it ends up in. If it faces the same direction as the splitter,
|
||||
// it goes in front. Otherwise, it goes in back.
|
||||
|
||||
if (node.dx != 0)
|
||||
{
|
||||
if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sidev[0] <= 0 && sidev[1] <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (sidev[0] >= 0 && sidev[1] >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
164
src/nodebuilder/nodebuild_classify_sse2.cpp
Normal file
164
src/nodebuilder/nodebuild_classify_sse2.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
Determine what side of a splitter a seg lies on. (SSE2 version)
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
|
||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||
|
||||
// You may notice that this function is identical to ClassifyLine2.
|
||||
// The reason it is SSE2 is because this file is explicitly compiled
|
||||
// with SSE2 math enabled, but the other files are not.
|
||||
|
||||
extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||
{
|
||||
double d_x1 = double(node.x);
|
||||
double d_y1 = double(node.y);
|
||||
double d_dx = double(node.dx);
|
||||
double d_dy = double(node.dy);
|
||||
double d_xv1 = double(v1->x);
|
||||
double d_xv2 = double(v2->x);
|
||||
double d_yv1 = double(v1->y);
|
||||
double d_yv2 = double(v2->y);
|
||||
|
||||
double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy;
|
||||
double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy;
|
||||
|
||||
int nears = 0;
|
||||
|
||||
if (s_num1 <= -FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = 1;
|
||||
return 1;
|
||||
}
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = 1;
|
||||
sidev[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else if (s_num1 >= FAR_ENOUGH)
|
||||
{
|
||||
if (s_num2 >= FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = sidev[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if (s_num2 <= -FAR_ENOUGH)
|
||||
{
|
||||
sidev[0] = -1;
|
||||
sidev[1] = 1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nears = 2 | int(fabs(s_num2) < FAR_ENOUGH);
|
||||
}
|
||||
|
||||
if (nears)
|
||||
{
|
||||
double l = 1.f / (d_dx*d_dx + d_dy*d_dy);
|
||||
if (nears & 2)
|
||||
{
|
||||
double dist = s_num1 * s_num1 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
}
|
||||
if (nears & 1)
|
||||
{
|
||||
double dist = s_num2 * s_num2 * l;
|
||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||
{
|
||||
sidev[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||
}
|
||||
|
||||
if ((sidev[0] | sidev[1]) == 0)
|
||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||
// which child it ends up in. If it faces the same direction as the splitter,
|
||||
// it goes in front. Otherwise, it goes in back.
|
||||
|
||||
if (node.dx != 0)
|
||||
{
|
||||
if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sidev[0] <= 0 && sidev[1] <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (sidev[0] >= 0 && sidev[1] >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
187
src/nodebuilder/nodebuild_classify_sse2_vect.cpp
Normal file
187
src/nodebuilder/nodebuild_classify_sse2_vect.cpp
Normal file
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
Determine what side of a splitter a seg lies on. (SSE2 version)
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DISABLE_SSE
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include <emmintrin.h>
|
||||
|
||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||
|
||||
// You may notice that this function is identical to ClassifyLine2.
|
||||
// The reason it is SSE2 is because this file is explicitly compiled
|
||||
// with SSE2 math enabled, but the other files are not.
|
||||
|
||||
extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||
{
|
||||
__m128d xy, dxy, xyv1, xyv2;
|
||||
|
||||
// Why does this intrinsic go through an MMX register, when it can just go through memory?
|
||||
// That would let it work with x64, too. (This only applies to VC++. GCC
|
||||
// is smarter and can load directly from memory without touching the MMX registers.)
|
||||
xy = _mm_cvtpi32_pd(*(__m64*)&node.x); // d_y1 d_x1
|
||||
dxy = _mm_cvtpi32_pd(*(__m64*)&node.dx); // d_dy d_dx
|
||||
xyv1 = _mm_cvtpi32_pd(*(__m64*)&v1->x); // d_yv1 d_xv1
|
||||
xyv2 = _mm_cvtpi32_pd(*(__m64*)&v2->x); // d_yv2 d_xv2
|
||||
|
||||
__m128d num1, num2, dyx;
|
||||
|
||||
dyx = _mm_shuffle_pd(dxy, dxy, _MM_SHUFFLE2(0,1));
|
||||
num1 = _mm_mul_pd(_mm_sub_pd(xy, xyv1), dyx);
|
||||
num2 = _mm_mul_pd(_mm_sub_pd(xy, xyv2), dyx);
|
||||
|
||||
__m128d pnuma, pnumb, num;
|
||||
|
||||
pnuma = _mm_shuffle_pd(num1, num2, _MM_SHUFFLE2(1,1));
|
||||
pnumb = _mm_shuffle_pd(num1, num2, _MM_SHUFFLE2(0,0));
|
||||
num = _mm_sub_pd(pnuma, pnumb);
|
||||
// s_num1 is at num[0]; s_num2 is at num[1]
|
||||
|
||||
__m128d neg_enough, pos_enough;
|
||||
__m128d neg_check, pos_check;
|
||||
|
||||
neg_enough = _mm_set1_pd(-FAR_ENOUGH);
|
||||
pos_enough = _mm_set1_pd( FAR_ENOUGH);
|
||||
|
||||
// Why do the comparison instructions return __m128d and not __m128i?
|
||||
neg_check = _mm_cmple_pd(num, neg_enough);
|
||||
pos_check = _mm_cmpge_pd(num, pos_enough);
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
double n[2], p[2];
|
||||
};
|
||||
struct
|
||||
{
|
||||
int ni[4], pi[4];
|
||||
};
|
||||
} _;
|
||||
|
||||
_mm_storeu_pd(_.n, neg_check);
|
||||
_mm_storeu_pd(_.p, pos_check);
|
||||
|
||||
int nears = 0;
|
||||
|
||||
if (_.ni[0])
|
||||
{
|
||||
if (_.ni[2])
|
||||
{
|
||||
sidev[0] = sidev[1] = 1;
|
||||
return 1;
|
||||
}
|
||||
if (_.pi[2])
|
||||
{
|
||||
sidev[0] = 1;
|
||||
sidev[1] = -1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else if (_.pi[0])
|
||||
{
|
||||
if (_.pi[2])
|
||||
{
|
||||
sidev[0] = sidev[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if (_.ni[2])
|
||||
{
|
||||
sidev[0] = -1;
|
||||
sidev[1] = 1;
|
||||
return -1;
|
||||
}
|
||||
nears = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nears = 2 | (((_.ni[2] | _.pi[2]) & 1) ^ 1);
|
||||
}
|
||||
|
||||
__m128d zero = _mm_setzero_pd();
|
||||
__m128d posi = _mm_cmpgt_pd(num, zero);
|
||||
_mm_storeu_pd(_.p, posi);
|
||||
|
||||
int sv1 = _.pi[0] ? _.pi[0] : 1;
|
||||
int sv2 = _.pi[2] ? _.pi[2] : 1;
|
||||
if (nears)
|
||||
{
|
||||
__m128d sqnum = _mm_mul_pd(num, num);
|
||||
__m128d sqdyx = _mm_mul_pd(dyx, dyx);
|
||||
__m128d sqdxy = _mm_mul_pd(dxy, dxy);
|
||||
__m128d l = _mm_add_pd(sqdyx, sqdxy);
|
||||
__m128d dist = _mm_div_pd(sqnum, l);
|
||||
__m128d epsilon = _mm_set1_pd(SIDE_EPSILON);
|
||||
__m128d close = _mm_cmplt_pd(dist, epsilon);
|
||||
_mm_storeu_pd(_.n, close);
|
||||
if (nears & _.ni[0] & 2)
|
||||
{
|
||||
sv1 = 0;
|
||||
}
|
||||
if (nears & _.ni[2] & 1)
|
||||
{
|
||||
sv2 = 0;
|
||||
}
|
||||
}
|
||||
sidev[0] = sv1;
|
||||
sidev[1] = sv2;
|
||||
|
||||
if ((sv1 | sv2) == 0)
|
||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||
// which child it ends up in. If it faces the same direction as the splitter,
|
||||
// it goes in front. Otherwise, it goes in back.
|
||||
|
||||
if (node.dx != 0)
|
||||
{
|
||||
if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sv1 <= 0 && sv2 <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (sv1 >= 0 && sv2 >= 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
207
src/nodebuilder/nodebuild_events.cpp
Normal file
207
src/nodebuilder/nodebuild_events.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
A red-black tree implementation for building minisegs.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "framework/zdray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
|
||||
FEventTree::FEventTree ()
|
||||
: Root (&Nil), Spare (NULL)
|
||||
{
|
||||
memset (&Nil, 0, sizeof(Nil));
|
||||
}
|
||||
|
||||
FEventTree::~FEventTree ()
|
||||
{
|
||||
FEvent *probe;
|
||||
|
||||
DeleteAll ();
|
||||
probe = Spare;
|
||||
while (probe != NULL)
|
||||
{
|
||||
FEvent *next = probe->Left;
|
||||
delete probe;
|
||||
probe = next;
|
||||
}
|
||||
}
|
||||
|
||||
void FEventTree::DeleteAll ()
|
||||
{
|
||||
DeletionTraverser (Root);
|
||||
Root = &Nil;
|
||||
}
|
||||
|
||||
void FEventTree::DeletionTraverser (FEvent *node)
|
||||
{
|
||||
if (node != &Nil && node != NULL)
|
||||
{
|
||||
DeletionTraverser (node->Left);
|
||||
DeletionTraverser (node->Right);
|
||||
node->Left = Spare;
|
||||
Spare = node;
|
||||
}
|
||||
}
|
||||
|
||||
FEvent *FEventTree::GetNewNode ()
|
||||
{
|
||||
FEvent *node;
|
||||
|
||||
if (Spare != NULL)
|
||||
{
|
||||
node = Spare;
|
||||
Spare = node->Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = new FEvent;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void FEventTree::Insert (FEvent *z)
|
||||
{
|
||||
FEvent *y = &Nil;
|
||||
FEvent *x = Root;
|
||||
|
||||
while (x != &Nil)
|
||||
{
|
||||
y = x;
|
||||
if (z->Distance < x->Distance)
|
||||
{
|
||||
x = x->Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = x->Right;
|
||||
}
|
||||
}
|
||||
z->Parent = y;
|
||||
if (y == &Nil)
|
||||
{
|
||||
Root = z;
|
||||
}
|
||||
else if (z->Distance < y->Distance)
|
||||
{
|
||||
y->Left = z;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->Right = z;
|
||||
}
|
||||
z->Left = &Nil;
|
||||
z->Right = &Nil;
|
||||
}
|
||||
|
||||
FEvent *FEventTree::Successor (FEvent *event) const
|
||||
{
|
||||
if (event->Right != &Nil)
|
||||
{
|
||||
event = event->Right;
|
||||
while (event->Left != &Nil)
|
||||
{
|
||||
event = event->Left;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
else
|
||||
{
|
||||
FEvent *y = event->Parent;
|
||||
while (y != &Nil && event == y->Right)
|
||||
{
|
||||
event = y;
|
||||
y = y->Parent;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
FEvent *FEventTree::Predecessor (FEvent *event) const
|
||||
{
|
||||
if (event->Left != &Nil)
|
||||
{
|
||||
event = event->Left;
|
||||
while (event->Right != &Nil)
|
||||
{
|
||||
event = event->Right;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
else
|
||||
{
|
||||
FEvent *y = event->Parent;
|
||||
while (y != &Nil && event == y->Left)
|
||||
{
|
||||
event = y;
|
||||
y = y->Parent;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
FEvent *FEventTree::FindEvent (double key) const
|
||||
{
|
||||
FEvent *node = Root;
|
||||
|
||||
while (node != &Nil)
|
||||
{
|
||||
if (node->Distance == key)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
else if (node->Distance > key)
|
||||
{
|
||||
node = node->Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->Right;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FEvent *FEventTree::GetMinimum ()
|
||||
{
|
||||
FEvent *node = Root;
|
||||
|
||||
if (node == &Nil)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while (node->Left != &Nil)
|
||||
{
|
||||
node = node->Left;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
void FEventTree::PrintTree (const FEvent *event) const
|
||||
{
|
||||
if (event->Left != &Nil)
|
||||
{
|
||||
PrintTree (event->Left);
|
||||
}
|
||||
printf (" Distance %g, vertex %d, seg %u\n",
|
||||
sqrt(event->Distance/4294967296.0), event->Info.Vertex, (unsigned)event->Info.FrontSeg);
|
||||
if (event->Right != &Nil)
|
||||
{
|
||||
PrintTree (event->Right);
|
||||
}
|
||||
}
|
572
src/nodebuilder/nodebuild_extract.cpp
Normal file
572
src/nodebuilder/nodebuild_extract.cpp
Normal file
|
@ -0,0 +1,572 @@
|
|||
/*
|
||||
Routines for extracting usable data from the new BSP tree.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
#include "framework/templates.h"
|
||||
|
||||
#if 0
|
||||
#define D(x) x
|
||||
#define DD 1
|
||||
#else
|
||||
#define D(x) do{}while(0)
|
||||
#undef DD
|
||||
#endif
|
||||
|
||||
void FNodeBuilder::GetGLNodes (MapNodeEx *&outNodes, int &nodeCount,
|
||||
MapSegGLEx *&outSegs, int &segCount,
|
||||
MapSubsectorEx *&outSubs, int &subCount)
|
||||
{
|
||||
TArray<MapSegGLEx> segs (Segs.Size()*5/4);
|
||||
int i, j, k;
|
||||
|
||||
nodeCount = Nodes.Size ();
|
||||
outNodes = new MapNodeEx[nodeCount];
|
||||
for (i = 0; i < nodeCount; ++i)
|
||||
{
|
||||
const node_t *orgnode = &Nodes[i];
|
||||
MapNodeEx *newnode = &outNodes[i];
|
||||
|
||||
newnode->x = orgnode->x;
|
||||
newnode->y = orgnode->y;
|
||||
newnode->dx = orgnode->dx;
|
||||
newnode->dy = orgnode->dy;
|
||||
|
||||
for (j = 0; j < 2; ++j)
|
||||
{
|
||||
for (k = 0; k < 4; ++k)
|
||||
{
|
||||
newnode->bbox[j][k] = orgnode->bbox[j][k] >> FRACBITS;
|
||||
}
|
||||
newnode->children[j] = orgnode->intchildren[j];
|
||||
}
|
||||
}
|
||||
|
||||
subCount = Subsectors.Size();
|
||||
outSubs = new MapSubsectorEx[subCount];
|
||||
for (i = 0; i < subCount; ++i)
|
||||
{
|
||||
int numsegs = CloseSubsector (segs, i);
|
||||
outSubs[i].numlines = numsegs;
|
||||
outSubs[i].firstline = segs.Size() - numsegs;
|
||||
}
|
||||
|
||||
segCount = segs.Size ();
|
||||
outSegs = new MapSegGLEx[segCount];
|
||||
memcpy (outSegs, &segs[0], segCount*sizeof(MapSegGLEx));
|
||||
|
||||
for (i = 0; i < segCount; ++i)
|
||||
{
|
||||
if (outSegs[i].partner != DWORD_MAX)
|
||||
{
|
||||
outSegs[i].partner = Segs[outSegs[i].partner].storedseg;
|
||||
}
|
||||
}
|
||||
|
||||
D(DumpNodes(outNodes, nodeCount));
|
||||
}
|
||||
|
||||
int FNodeBuilder::CloseSubsector (TArray<MapSegGLEx> &segs, int subsector)
|
||||
{
|
||||
FPrivSeg *seg, *prev;
|
||||
angle_t prevAngle;
|
||||
double accumx, accumy;
|
||||
fixed_t midx, midy;
|
||||
int i, j, first, max, count, firstVert;
|
||||
bool diffplanes;
|
||||
int firstplane;
|
||||
|
||||
first = Subsectors[subsector].firstline;
|
||||
max = first + Subsectors[subsector].numlines;
|
||||
count = 0;
|
||||
|
||||
accumx = accumy = 0.0;
|
||||
diffplanes = false;
|
||||
firstplane = Segs[SegList[first].SegNum].planenum;
|
||||
|
||||
// Calculate the midpoint of the subsector and also check for degenerate subsectors.
|
||||
// A subsector is degenerate if it exists in only one dimension, which can be
|
||||
// detected when all the segs lie in the same plane. This can happen if you have
|
||||
// outward-facing lines in the void that don't point toward any sector. (Some of the
|
||||
// polyobjects in Hexen are constructed like this.)
|
||||
for (i = first; i < max; ++i)
|
||||
{
|
||||
seg = &Segs[SegList[i].SegNum];
|
||||
accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x);
|
||||
accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y);
|
||||
if (firstplane != seg->planenum)
|
||||
{
|
||||
diffplanes = true;
|
||||
}
|
||||
}
|
||||
|
||||
midx = fixed_t(accumx / (max - first) / 2);
|
||||
midy = fixed_t(accumy / (max - first) / 2);
|
||||
|
||||
seg = &Segs[SegList[first].SegNum];
|
||||
prevAngle = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
seg->storedseg = PushGLSeg (segs, seg);
|
||||
count = 1;
|
||||
prev = seg;
|
||||
firstVert = seg->v1;
|
||||
|
||||
#ifdef DD
|
||||
printf("--%d--\n", subsector);
|
||||
for (j = first; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
printf ("%d%c %5d(%5d,%5d)->%5d(%5d,%5d) - %3.5f %d,%d [%08x,%08x]-[%08x,%08x]\n", j,
|
||||
seg->linedef == -1 ? '+' : ':',
|
||||
seg->v1, Vertices[seg->v1].x>>16, Vertices[seg->v1].y>>16,
|
||||
seg->v2, Vertices[seg->v2].x>>16, Vertices[seg->v2].y>>16,
|
||||
double(ang/2)*180/(1<<30),
|
||||
seg->planenum, seg->planefront,
|
||||
Vertices[seg->v1].x, Vertices[seg->v1].y,
|
||||
Vertices[seg->v2].x, Vertices[seg->v2].y);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (diffplanes)
|
||||
{ // A well-behaved subsector. Output the segs sorted by the angle formed by connecting
|
||||
// the subsector's center to their first vertex.
|
||||
|
||||
D(printf("Well behaved subsector\n"));
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
angle_t bestdiff = ANGLE_MAX;
|
||||
FPrivSeg *bestseg = NULL;
|
||||
int bestj = -1;
|
||||
for (j = first; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy);
|
||||
angle_t diff = prevAngle - ang;
|
||||
if (seg->v1 == prev->v2)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
break;
|
||||
}
|
||||
if (diff < bestdiff && diff > 0)
|
||||
{
|
||||
bestdiff = diff;
|
||||
bestseg = seg;
|
||||
bestj = j;
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
seg = bestseg;
|
||||
}
|
||||
if (prev->v2 != seg->v1)
|
||||
{
|
||||
// Add a new miniseg to connect the two segs
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, seg->v1);
|
||||
count++;
|
||||
}
|
||||
#ifdef DD
|
||||
printf ("+%d\n", bestj);
|
||||
#endif
|
||||
prevAngle -= bestdiff;
|
||||
seg->storedseg = PushGLSeg (segs, seg);
|
||||
count++;
|
||||
prev = seg;
|
||||
if (seg->v2 == firstVert)
|
||||
{
|
||||
prev = seg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DD
|
||||
printf ("\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{ // A degenerate subsector. These are handled in three stages:
|
||||
// Stage 1. Proceed in the same direction as the start seg until we
|
||||
// hit the seg furthest from it.
|
||||
// Stage 2. Reverse direction and proceed until we hit the seg
|
||||
// furthest from the start seg.
|
||||
// Stage 3. Reverse direction again and insert segs until we get
|
||||
// to the start seg.
|
||||
// A dot product serves to determine distance from the start seg.
|
||||
|
||||
D(printf("degenerate subsector\n"));
|
||||
|
||||
// Stage 1. Go forward.
|
||||
count += OutputDegenerateSubsector (segs, subsector, true, 0, prev);
|
||||
|
||||
// Stage 2. Go backward.
|
||||
count += OutputDegenerateSubsector (segs, subsector, false, DBL_MAX, prev);
|
||||
|
||||
// Stage 3. Go forward again.
|
||||
count += OutputDegenerateSubsector (segs, subsector, true, -DBL_MAX, prev);
|
||||
}
|
||||
|
||||
if (prev->v2 != firstVert)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, firstVert);
|
||||
count++;
|
||||
}
|
||||
#ifdef DD
|
||||
printf ("Output GL subsector %d:\n", subsector);
|
||||
for (i = segs.Size() - count; i < (int)segs.Size(); ++i)
|
||||
{
|
||||
printf (" Seg %5d%c(%5d,%5d)-(%5d,%5d) [%08x,%08x]-[%08x,%08x]\n", i,
|
||||
segs[i].linedef == NO_INDEX ? '+' : ' ',
|
||||
Vertices[segs[i].v1].x>>16,
|
||||
Vertices[segs[i].v1].y>>16,
|
||||
Vertices[segs[i].v2].x>>16,
|
||||
Vertices[segs[i].v2].y>>16,
|
||||
Vertices[segs[i].v1].x,
|
||||
Vertices[segs[i].v1].y,
|
||||
Vertices[segs[i].v2].x,
|
||||
Vertices[segs[i].v2].y);
|
||||
}
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int FNodeBuilder::OutputDegenerateSubsector (TArray<MapSegGLEx> &segs, int subsector, bool bForward, double lastdot, FPrivSeg *&prev)
|
||||
{
|
||||
static const double bestinit[2] = { -DBL_MAX, DBL_MAX };
|
||||
FPrivSeg *seg;
|
||||
int i, j, first, max, count;
|
||||
double dot, x1, y1, dx, dy, dx2, dy2;
|
||||
bool wantside;
|
||||
|
||||
first = Subsectors[subsector].firstline;
|
||||
max = first + Subsectors[subsector].numlines;
|
||||
count = 0;
|
||||
|
||||
seg = &Segs[SegList[first].SegNum];
|
||||
x1 = Vertices[seg->v1].x;
|
||||
y1 = Vertices[seg->v1].y;
|
||||
dx = Vertices[seg->v2].x - x1;
|
||||
dy = Vertices[seg->v2].y - y1;
|
||||
wantside = seg->planefront ^ !bForward;
|
||||
|
||||
for (i = first + 1; i < max; ++i)
|
||||
{
|
||||
double bestdot = bestinit[bForward];
|
||||
FPrivSeg *bestseg = NULL;
|
||||
for (j = first + 1; j < max; ++j)
|
||||
{
|
||||
seg = &Segs[SegList[j].SegNum];
|
||||
if (seg->planefront != wantside)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
dx2 = Vertices[seg->v1].x - x1;
|
||||
dy2 = Vertices[seg->v1].y - y1;
|
||||
dot = dx*dx2 + dy*dy2;
|
||||
|
||||
if (bForward)
|
||||
{
|
||||
if (dot < bestdot && dot > lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dot > bestdot && dot < lastdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestseg = seg;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestseg != NULL)
|
||||
{
|
||||
if (prev->v2 != bestseg->v1)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, bestseg->v1);
|
||||
count++;
|
||||
}
|
||||
seg->storedseg = PushGLSeg (segs, bestseg);
|
||||
count++;
|
||||
prev = bestseg;
|
||||
lastdot = bestdot;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
DWORD FNodeBuilder::PushGLSeg (TArray<MapSegGLEx> &segs, const FPrivSeg *seg)
|
||||
{
|
||||
MapSegGLEx newseg;
|
||||
|
||||
newseg.v1 = seg->v1;
|
||||
newseg.v2 = seg->v2;
|
||||
newseg.linedef = seg->linedef;
|
||||
|
||||
// Just checking the sidedef to determine the side is insufficient.
|
||||
// When a level is sidedef compressed both sides may well have the same sidedef.
|
||||
|
||||
if (newseg.linedef != NO_INDEX)
|
||||
{
|
||||
IntLineDef *ld = &Level.Lines[newseg.linedef];
|
||||
|
||||
if (ld->sidenum[0] == ld->sidenum[1])
|
||||
{
|
||||
// When both sidedefs are the same a quick check doesn't work so this
|
||||
// has to be done by comparing the distances of the seg's end point to
|
||||
// the line's start.
|
||||
WideVertex *lv1 = &Level.Vertices[ld->v1];
|
||||
WideVertex *sv1 = &Level.Vertices[seg->v1];
|
||||
WideVertex *sv2 = &Level.Vertices[seg->v2];
|
||||
|
||||
double dist1sq = double(sv1->x-lv1->x)*(sv1->x-lv1->x) + double(sv1->y-lv1->y)*(sv1->y-lv1->y);
|
||||
double dist2sq = double(sv2->x-lv1->x)*(sv2->x-lv1->x) + double(sv2->y-lv1->y)*(sv2->y-lv1->y);
|
||||
|
||||
newseg.side = dist1sq < dist2sq ? 0 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
newseg.side = ld->sidenum[1] == seg->sidedef ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newseg.side = 0;
|
||||
}
|
||||
|
||||
newseg.partner = seg->partner;
|
||||
return segs.Push (newseg);
|
||||
}
|
||||
|
||||
void FNodeBuilder::PushConnectingGLSeg (int subsector, TArray<MapSegGLEx> &segs, int v1, int v2)
|
||||
{
|
||||
MapSegGLEx newseg;
|
||||
|
||||
Warn ("Unclosed subsector %d, from (%d,%d) to (%d,%d)\n", subsector,
|
||||
Vertices[v1].x >> FRACBITS, Vertices[v1].y >> FRACBITS,
|
||||
Vertices[v2].x >> FRACBITS, Vertices[v2].y >> FRACBITS);
|
||||
|
||||
newseg.v1 = v1;
|
||||
newseg.v2 = v2;
|
||||
newseg.linedef = NO_INDEX;
|
||||
newseg.side = 0;
|
||||
newseg.partner = DWORD_MAX;
|
||||
segs.Push (newseg);
|
||||
}
|
||||
|
||||
void FNodeBuilder::GetVertices (WideVertex *&verts, int &count)
|
||||
{
|
||||
count = Vertices.Size ();
|
||||
verts = new WideVertex[count];
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
verts[i].x = Vertices[i].x;
|
||||
verts[i].y = Vertices[i].y;
|
||||
verts[i].index = Vertices[i].index;
|
||||
}
|
||||
}
|
||||
|
||||
void FNodeBuilder::GetNodes (MapNodeEx *&outNodes, int &nodeCount,
|
||||
MapSegEx *&outSegs, int &segCount,
|
||||
MapSubsectorEx *&outSubs, int &subCount)
|
||||
{
|
||||
short bbox[4];
|
||||
TArray<MapSegEx> segs (Segs.Size());
|
||||
|
||||
// Walk the BSP and create a new BSP with only the information
|
||||
// suitable for a standard tree. At a minimum, this means removing
|
||||
// all minisegs. As an optional step, I also recompute all the
|
||||
// nodes' bounding boxes so that they only bound the real segs and
|
||||
// not the minisegs.
|
||||
|
||||
nodeCount = Nodes.Size ();
|
||||
outNodes = new MapNodeEx[nodeCount];
|
||||
|
||||
subCount = Subsectors.Size ();
|
||||
outSubs = new MapSubsectorEx[subCount];
|
||||
|
||||
RemoveMinisegs (outNodes, segs, outSubs, Nodes.Size() - 1, bbox);
|
||||
|
||||
segCount = segs.Size ();
|
||||
outSegs = new MapSegEx[segCount];
|
||||
memcpy (outSegs, &segs[0], segCount*sizeof(MapSegEx));
|
||||
|
||||
D(DumpNodes(outNodes, nodeCount));
|
||||
#ifdef DD
|
||||
for (int i = 0; i < segCount; ++i)
|
||||
{
|
||||
printf("Seg %d: v1(%d) -> v2(%d)\n", i, outSegs[i].v1, outSegs[i].v2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int FNodeBuilder::RemoveMinisegs (MapNodeEx *nodes,
|
||||
TArray<MapSegEx> &segs, MapSubsectorEx *subs, int node, short bbox[4])
|
||||
{
|
||||
if (node & NFX_SUBSECTOR)
|
||||
{
|
||||
int subnum = node == -1 ? 0 : node & ~NFX_SUBSECTOR;
|
||||
int numsegs = StripMinisegs (segs, subnum, bbox);
|
||||
subs[subnum].numlines = numsegs;
|
||||
subs[subnum].firstline = segs.Size() - numsegs;
|
||||
return NFX_SUBSECTOR | subnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
const node_t *orgnode = &Nodes[node];
|
||||
MapNodeEx *newnode = &nodes[node];
|
||||
|
||||
int child0 = RemoveMinisegs (nodes, segs, subs, orgnode->intchildren[0], newnode->bbox[0]);
|
||||
int child1 = RemoveMinisegs (nodes, segs, subs, orgnode->intchildren[1], newnode->bbox[1]);
|
||||
|
||||
|
||||
newnode->x = orgnode->x;
|
||||
newnode->y = orgnode->y;
|
||||
newnode->dx = orgnode->dx;
|
||||
newnode->dy = orgnode->dy;
|
||||
newnode->children[0] = child0;
|
||||
newnode->children[1] = child1;
|
||||
|
||||
bbox[BOXTOP] = MAX(newnode->bbox[0][BOXTOP], newnode->bbox[1][BOXTOP]);
|
||||
bbox[BOXBOTTOM] = MIN(newnode->bbox[0][BOXBOTTOM], newnode->bbox[1][BOXBOTTOM]);
|
||||
bbox[BOXLEFT] = MIN(newnode->bbox[0][BOXLEFT], newnode->bbox[1][BOXLEFT]);
|
||||
bbox[BOXRIGHT] = MAX(newnode->bbox[0][BOXRIGHT], newnode->bbox[1][BOXRIGHT]);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
int FNodeBuilder::StripMinisegs (TArray<MapSegEx> &segs, int subsector, short bbox[4])
|
||||
{
|
||||
int count, i, max;
|
||||
|
||||
// The bounding box is recomputed to only cover the real segs and not the
|
||||
// minisegs in the subsector.
|
||||
bbox[BOXTOP] = -32768;
|
||||
bbox[BOXBOTTOM] = 32767;
|
||||
bbox[BOXLEFT] = 32767;
|
||||
bbox[BOXRIGHT] = -32768;
|
||||
|
||||
i = Subsectors[subsector].firstline;
|
||||
max = Subsectors[subsector].numlines + i;
|
||||
|
||||
for (count = 0; i < max; ++i)
|
||||
{
|
||||
const FPrivSeg *org = &Segs[SegList[i].SegNum];
|
||||
|
||||
// Because of the ordering guaranteed by SortSegs(), all mini segs will
|
||||
// be at the end of the subsector, so once one is encountered, we can
|
||||
// stop right away.
|
||||
if (org->linedef == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
MapSegEx newseg;
|
||||
|
||||
AddSegToShortBBox (bbox, org);
|
||||
|
||||
newseg.v1 = org->v1;
|
||||
newseg.v2 = org->v2;
|
||||
newseg.angle = org->angle >> 16;
|
||||
newseg.offset = org->offset >> FRACBITS;
|
||||
newseg.linedef = org->linedef;
|
||||
|
||||
// Just checking the sidedef to determine the side is insufficient.
|
||||
// When a level is sidedef compressed both sides may well have the same sidedef.
|
||||
|
||||
IntLineDef * ld = &Level.Lines[newseg.linedef];
|
||||
|
||||
if (ld->sidenum[0]==ld->sidenum[1])
|
||||
{
|
||||
// When both sidedefs are the same a quick check doesn't work so this
|
||||
// has to be done by comparing the distances of the seg's end point to
|
||||
// the line's start.
|
||||
WideVertex * lv1 = &Level.Vertices[ld->v1];
|
||||
WideVertex * sv1 = &Level.Vertices[org->v1];
|
||||
WideVertex * sv2 = &Level.Vertices[org->v2];
|
||||
|
||||
double dist1sq = double(sv1->x-lv1->x)*(sv1->x-lv1->x) + double(sv1->y-lv1->y)*(sv1->y-lv1->y);
|
||||
double dist2sq = double(sv2->x-lv1->x)*(sv2->x-lv1->x) + double(sv2->y-lv1->y)*(sv2->y-lv1->y);
|
||||
|
||||
newseg.side = dist1sq<dist2sq? 0:1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
newseg.side = ld->sidenum[1] == org->sidedef ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
newseg.side = Level.Lines[org->linedef].sidenum[1] == org->sidedef ? 1 : 0;
|
||||
segs.Push (newseg);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void FNodeBuilder::AddSegToShortBBox (short bbox[4], const FPrivSeg *seg)
|
||||
{
|
||||
const FPrivVert *v1 = &Vertices[seg->v1];
|
||||
const FPrivVert *v2 = &Vertices[seg->v2];
|
||||
|
||||
short v1x = v1->x >> FRACBITS;
|
||||
short v1y = v1->y >> FRACBITS;
|
||||
short v2x = v2->x >> FRACBITS;
|
||||
short v2y = v2->y >> FRACBITS;
|
||||
|
||||
if (v1x < bbox[BOXLEFT]) bbox[BOXLEFT] = v1x;
|
||||
if (v1x > bbox[BOXRIGHT]) bbox[BOXRIGHT] = v1x;
|
||||
if (v1y < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = v1y;
|
||||
if (v1y > bbox[BOXTOP]) bbox[BOXTOP] = v1y;
|
||||
|
||||
if (v2x < bbox[BOXLEFT]) bbox[BOXLEFT] = v2x;
|
||||
if (v2x > bbox[BOXRIGHT]) bbox[BOXRIGHT] = v2x;
|
||||
if (v2y < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = v2y;
|
||||
if (v2y > bbox[BOXTOP]) bbox[BOXTOP] = v2y;
|
||||
}
|
||||
|
||||
void FNodeBuilder::DumpNodes(MapNodeEx *outNodes, int nodeCount)
|
||||
{
|
||||
for (unsigned int i = 0; i < Nodes.Size(); ++i)
|
||||
{
|
||||
printf("Node %d: Splitter[%08x,%08x] [%08x,%08x]\n", i,
|
||||
outNodes[i].x, outNodes[i].y, outNodes[i].dx, outNodes[i].dy);
|
||||
for (int j = 1; j >= 0; --j)
|
||||
{
|
||||
if (outNodes[i].children[j] & NFX_SUBSECTOR)
|
||||
{
|
||||
printf(" subsector %d\n", outNodes[i].children[j] & ~NFX_SUBSECTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" node %d\n", outNodes[i].children[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
394
src/nodebuilder/nodebuild_gl.cpp
Normal file
394
src/nodebuilder/nodebuild_gl.cpp
Normal file
|
@ -0,0 +1,394 @@
|
|||
/*
|
||||
Routines only necessary for building GL-friendly nodes.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include "framework/zdray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
|
||||
#define Printf printf
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
#define D(x) x
|
||||
#else
|
||||
#define D(x) do{}while(0)
|
||||
#endif
|
||||
|
||||
double FNodeBuilder::AddIntersection (const node_t &node, int vertex)
|
||||
{
|
||||
static const FEventInfo defaultInfo =
|
||||
{
|
||||
-1, DWORD_MAX
|
||||
};
|
||||
|
||||
// Calculate signed distance of intersection vertex from start of splitter.
|
||||
// Only ordering is important, so we don't need a sqrt.
|
||||
FPrivVert *v = &Vertices[vertex];
|
||||
double dist = (double(v->x) - node.x)*(node.dx) + (double(v->y) - node.y)*(node.dy);
|
||||
|
||||
FEvent *event = Events.FindEvent (dist);
|
||||
|
||||
if (event == NULL)
|
||||
{
|
||||
event = Events.GetNewNode ();
|
||||
event->Distance = dist;
|
||||
event->Info = defaultInfo;
|
||||
event->Info.Vertex = vertex;
|
||||
Events.Insert (event);
|
||||
}
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
// If there are any segs on the splitter that span more than two events, they
|
||||
// must be split. Alien Vendetta is one example wad that is quite bad about
|
||||
// having overlapping lines. If we skip this step, these segs will still be
|
||||
// split later, but minisegs will erroneously be added for them, and partner
|
||||
// seg information will be messed up in the generated tree.
|
||||
void FNodeBuilder::FixSplitSharers ()
|
||||
{
|
||||
D(printf("events:\n"));
|
||||
D(Events.PrintTree());
|
||||
for (unsigned int i = 0; i < SplitSharers.Size(); ++i)
|
||||
{
|
||||
DWORD seg = SplitSharers[i].Seg;
|
||||
int v2 = Segs[seg].v2;
|
||||
FEvent *event = Events.FindEvent (SplitSharers[i].Distance);
|
||||
FEvent *next;
|
||||
|
||||
if (event == NULL)
|
||||
{ // Should not happen
|
||||
continue;
|
||||
}
|
||||
|
||||
D(printf("Considering events on seg %d(%d[%d,%d]->%d[%d,%d]) [%g:%g]\n", seg,
|
||||
Segs[seg].v1,
|
||||
Vertices[Segs[seg].v1].x>>16,
|
||||
Vertices[Segs[seg].v1].y>>16,
|
||||
Segs[seg].v2,
|
||||
Vertices[Segs[seg].v2].x>>16,
|
||||
Vertices[Segs[seg].v2].y>>16,
|
||||
SplitSharers[i].Distance, event->Distance));
|
||||
|
||||
if (SplitSharers[i].Forward)
|
||||
{
|
||||
event = Events.GetSuccessor (event);
|
||||
if (event == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
next = Events.GetSuccessor (event);
|
||||
}
|
||||
else
|
||||
{
|
||||
event = Events.GetPredecessor (event);
|
||||
if (event == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
next = Events.GetPredecessor (event);
|
||||
}
|
||||
|
||||
while (event != NULL && next != NULL && event->Info.Vertex != v2)
|
||||
{
|
||||
D(printf("Forced split of seg %d(%d[%d,%d]->%d[%d,%d]) at %d(%d,%d):%g\n", seg,
|
||||
Segs[seg].v1,
|
||||
Vertices[Segs[seg].v1].x>>16,
|
||||
Vertices[Segs[seg].v1].y>>16,
|
||||
Segs[seg].v2,
|
||||
Vertices[Segs[seg].v2].x>>16,
|
||||
Vertices[Segs[seg].v2].y>>16,
|
||||
event->Info.Vertex,
|
||||
Vertices[event->Info.Vertex].x>>16,
|
||||
Vertices[event->Info.Vertex].y>>16,
|
||||
event->Distance));
|
||||
|
||||
DWORD newseg = SplitSeg (seg, event->Info.Vertex, 1);
|
||||
|
||||
Segs[newseg].next = Segs[seg].next;
|
||||
Segs[seg].next = newseg;
|
||||
|
||||
DWORD partner = Segs[seg].partner;
|
||||
if (partner != DWORD_MAX)
|
||||
{
|
||||
int endpartner = SplitSeg (partner, event->Info.Vertex, 1);
|
||||
|
||||
Segs[endpartner].next = Segs[partner].next;
|
||||
Segs[partner].next = endpartner;
|
||||
|
||||
Segs[seg].partner = endpartner;
|
||||
//Segs[endpartner].partner = seg;
|
||||
Segs[partner].partner = newseg;
|
||||
|
||||
assert (Segs[Segs[seg].partner].partner == seg);
|
||||
assert (Segs[Segs[newseg].partner].partner == newseg);
|
||||
assert (Segs[seg].v1 == Segs[endpartner].v2);
|
||||
assert (Segs[seg].v2 == Segs[endpartner].v1);
|
||||
assert (Segs[partner].v1 == Segs[newseg].v2);
|
||||
assert (Segs[partner].v2 == Segs[newseg].v1);
|
||||
}
|
||||
|
||||
seg = newseg;
|
||||
if (SplitSharers[i].Forward)
|
||||
{
|
||||
event = next;
|
||||
next = Events.GetSuccessor (next);
|
||||
}
|
||||
else
|
||||
{
|
||||
event = next;
|
||||
next = Events.GetPredecessor (next);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FNodeBuilder::AddMinisegs (const node_t &node, DWORD splitseg, DWORD &fset, DWORD &bset)
|
||||
{
|
||||
FEvent *event = Events.GetMinimum (), *prev = NULL;
|
||||
|
||||
while (event != NULL)
|
||||
{
|
||||
if (prev != NULL)
|
||||
{
|
||||
DWORD fseg1, bseg1, fseg2, bseg2;
|
||||
DWORD fnseg, bnseg;
|
||||
|
||||
// Minisegs should only be added when they can create valid loops on both the front and
|
||||
// back of the splitter. This means some subsectors could be unclosed if their sectors
|
||||
// are unclosed, but at least we won't be needlessly creating subsectors in void space.
|
||||
// Unclosed subsectors can be closed trivially once the BSP tree is complete.
|
||||
|
||||
if ((fseg1 = CheckLoopStart (node.dx, node.dy, prev->Info.Vertex, event->Info.Vertex)) != DWORD_MAX &&
|
||||
(bseg1 = CheckLoopStart (-node.dx, -node.dy, event->Info.Vertex, prev->Info.Vertex)) != DWORD_MAX &&
|
||||
(fseg2 = CheckLoopEnd (node.dx, node.dy, event->Info.Vertex)) != DWORD_MAX &&
|
||||
(bseg2 = CheckLoopEnd (-node.dx, -node.dy, prev->Info.Vertex)) != DWORD_MAX)
|
||||
{
|
||||
// Add miniseg on the front side
|
||||
fnseg = AddMiniseg (prev->Info.Vertex, event->Info.Vertex, DWORD_MAX, fseg1, splitseg);
|
||||
Segs[fnseg].next = fset;
|
||||
fset = fnseg;
|
||||
|
||||
// Add miniseg on the back side
|
||||
bnseg = AddMiniseg (event->Info.Vertex, prev->Info.Vertex, fnseg, bseg1, splitseg);
|
||||
Segs[bnseg].next = bset;
|
||||
bset = bnseg;
|
||||
|
||||
int fsector, bsector;
|
||||
|
||||
fsector = Segs[fseg1].frontsector;
|
||||
bsector = Segs[bseg1].frontsector;
|
||||
|
||||
Segs[fnseg].frontsector = fsector;
|
||||
Segs[fnseg].backsector = bsector;
|
||||
Segs[bnseg].frontsector = bsector;
|
||||
Segs[bnseg].backsector = fsector;
|
||||
|
||||
// Only print the warning if this might be bad.
|
||||
if (fsector != bsector &&
|
||||
fsector != Segs[fseg1].backsector &&
|
||||
bsector != Segs[bseg1].backsector)
|
||||
{
|
||||
Warn ("Sectors %d at (%d,%d) and %d at (%d,%d) don't match.\n",
|
||||
Segs[fseg1].frontsector,
|
||||
Vertices[prev->Info.Vertex].x>>FRACBITS, Vertices[prev->Info.Vertex].y>>FRACBITS,
|
||||
Segs[bseg1].frontsector,
|
||||
Vertices[event->Info.Vertex].x>>FRACBITS, Vertices[event->Info.Vertex].y>>FRACBITS
|
||||
);
|
||||
}
|
||||
|
||||
D(Printf ("**Minisegs** %d/%d added %d(%d,%d)->%d(%d,%d)\n", fnseg, bnseg,
|
||||
prev->Info.Vertex,
|
||||
Vertices[prev->Info.Vertex].x>>16, Vertices[prev->Info.Vertex].y>>16,
|
||||
event->Info.Vertex,
|
||||
Vertices[event->Info.Vertex].x>>16, Vertices[event->Info.Vertex].y>>16));
|
||||
}
|
||||
}
|
||||
prev = event;
|
||||
event = Events.GetSuccessor (event);
|
||||
}
|
||||
}
|
||||
|
||||
DWORD FNodeBuilder::AddMiniseg (int v1, int v2, DWORD partner, DWORD seg1, DWORD splitseg)
|
||||
{
|
||||
DWORD nseg;
|
||||
FPrivSeg *seg = &Segs[seg1];
|
||||
FPrivSeg newseg;
|
||||
|
||||
newseg.sidedef = NO_INDEX;
|
||||
newseg.linedef = NO_INDEX;
|
||||
newseg.loopnum = 0;
|
||||
newseg.next = DWORD_MAX;
|
||||
newseg.planefront = true;
|
||||
newseg.hashnext = NULL;
|
||||
newseg.storedseg = DWORD_MAX;
|
||||
newseg.frontsector = -1;
|
||||
newseg.backsector = -1;
|
||||
newseg.offset = 0;
|
||||
newseg.angle = 0;
|
||||
|
||||
if (splitseg != DWORD_MAX)
|
||||
{
|
||||
newseg.planenum = Segs[splitseg].planenum;
|
||||
}
|
||||
else
|
||||
{
|
||||
newseg.planenum = -1;
|
||||
}
|
||||
|
||||
newseg.v1 = v1;
|
||||
newseg.v2 = v2;
|
||||
newseg.nextforvert = Vertices[v1].segs;
|
||||
newseg.nextforvert2 = Vertices[v2].segs2;
|
||||
newseg.next = seg->next;
|
||||
if (partner != DWORD_MAX)
|
||||
{
|
||||
newseg.partner = partner;
|
||||
|
||||
assert (Segs[partner].v1 == newseg.v2);
|
||||
assert (Segs[partner].v2 == newseg.v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
newseg.partner = DWORD_MAX;
|
||||
}
|
||||
nseg = Segs.Push (newseg);
|
||||
if (newseg.partner != DWORD_MAX)
|
||||
{
|
||||
Segs[partner].partner = nseg;
|
||||
}
|
||||
Vertices[v1].segs = nseg;
|
||||
Vertices[v2].segs2 = nseg;
|
||||
//Printf ("Between %d and %d::::\n", seg1, seg2);
|
||||
return nseg;
|
||||
}
|
||||
|
||||
DWORD FNodeBuilder::CheckLoopStart (fixed_t dx, fixed_t dy, int vertex, int vertex2)
|
||||
{
|
||||
FPrivVert *v = &Vertices[vertex];
|
||||
angle_t splitAngle = PointToAngle (dx, dy);
|
||||
DWORD segnum;
|
||||
angle_t bestang;
|
||||
DWORD bestseg;
|
||||
|
||||
// Find the seg ending at this vertex that forms the smallest angle
|
||||
// to the splitter.
|
||||
segnum = v->segs2;
|
||||
bestang = ANGLE_MAX;
|
||||
bestseg = DWORD_MAX;
|
||||
while (segnum != DWORD_MAX)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[segnum];
|
||||
angle_t segAngle = PointToAngle (Vertices[seg->v1].x - v->x, Vertices[seg->v1].y - v->y);
|
||||
angle_t diff = splitAngle - segAngle;
|
||||
|
||||
if (diff < ANGLE_EPSILON &&
|
||||
PointOnSide (Vertices[seg->v1].x, Vertices[seg->v1].y, v->x, v->y, dx, dy) == 0)
|
||||
{
|
||||
// If a seg lies right on the splitter, don't count it
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff <= bestang)
|
||||
{
|
||||
bestang = diff;
|
||||
bestseg = segnum;
|
||||
}
|
||||
}
|
||||
segnum = seg->nextforvert2;
|
||||
}
|
||||
if (bestseg == DWORD_MAX)
|
||||
{
|
||||
return DWORD_MAX;
|
||||
}
|
||||
// Now make sure there are no segs starting at this vertex that form
|
||||
// an even smaller angle to the splitter.
|
||||
segnum = v->segs;
|
||||
while (segnum != DWORD_MAX)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[segnum];
|
||||
if (seg->v2 == vertex2)
|
||||
{
|
||||
return DWORD_MAX;
|
||||
}
|
||||
angle_t segAngle = PointToAngle (Vertices[seg->v2].x - v->x, Vertices[seg->v2].y - v->y);
|
||||
angle_t diff = splitAngle - segAngle;
|
||||
if (diff < bestang && seg->partner != bestseg)
|
||||
{
|
||||
return DWORD_MAX;
|
||||
}
|
||||
segnum = seg->nextforvert;
|
||||
}
|
||||
return bestseg;
|
||||
}
|
||||
|
||||
DWORD FNodeBuilder::CheckLoopEnd (fixed_t dx, fixed_t dy, int vertex)
|
||||
{
|
||||
FPrivVert *v = &Vertices[vertex];
|
||||
angle_t splitAngle = PointToAngle (dx, dy) + ANGLE_180;
|
||||
DWORD segnum;
|
||||
angle_t bestang;
|
||||
DWORD bestseg;
|
||||
|
||||
// Find the seg starting at this vertex that forms the smallest angle
|
||||
// to the splitter.
|
||||
segnum = v->segs;
|
||||
bestang = ANGLE_MAX;
|
||||
bestseg = DWORD_MAX;
|
||||
while (segnum != DWORD_MAX)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[segnum];
|
||||
angle_t segAngle = PointToAngle (Vertices[seg->v2].x - v->x, Vertices[seg->v2].y - v->y);
|
||||
angle_t diff = segAngle - splitAngle;
|
||||
|
||||
if (diff < ANGLE_EPSILON &&
|
||||
PointOnSide (Vertices[seg->v1].x, Vertices[seg->v1].y, v->x, v->y, dx, dy) == 0)
|
||||
{
|
||||
// If a seg lies right on the splitter, don't count it
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff <= bestang)
|
||||
{
|
||||
bestang = diff;
|
||||
bestseg = segnum;
|
||||
}
|
||||
}
|
||||
segnum = seg->nextforvert;
|
||||
}
|
||||
if (bestseg == DWORD_MAX)
|
||||
{
|
||||
return DWORD_MAX;
|
||||
}
|
||||
// Now make sure there are no segs ending at this vertex that form
|
||||
// an even smaller angle to the splitter.
|
||||
segnum = v->segs2;
|
||||
while (segnum != DWORD_MAX)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[segnum];
|
||||
angle_t segAngle = PointToAngle (Vertices[seg->v1].x - v->x, Vertices[seg->v1].y - v->y);
|
||||
angle_t diff = segAngle - splitAngle;
|
||||
if (diff < bestang && seg->partner != bestseg)
|
||||
{
|
||||
return DWORD_MAX;
|
||||
}
|
||||
segnum = seg->nextforvert2;
|
||||
}
|
||||
return bestseg;
|
||||
}
|
556
src/nodebuilder/nodebuild_utility.cpp
Normal file
556
src/nodebuilder/nodebuild_utility.cpp
Normal file
|
@ -0,0 +1,556 @@
|
|||
/*
|
||||
Various utility functions.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "nodebuilder/nodebuild.h"
|
||||
#include "framework/templates.h"
|
||||
|
||||
static const int PO_LINE_START = 1;
|
||||
static const int PO_LINE_EXPLICIT = 5;
|
||||
|
||||
#if 0
|
||||
#define D(x) x
|
||||
#else
|
||||
#define D(x) do{}while(0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define P(x) x
|
||||
#define Printf printf
|
||||
#else
|
||||
#define P(x) do{}while(0)
|
||||
#endif
|
||||
|
||||
void FNodeBuilder::FindUsedVertices (WideVertex *oldverts, int max)
|
||||
{
|
||||
int *map = new int[max];
|
||||
int i;
|
||||
FPrivVert newvert;
|
||||
|
||||
memset (&map[0], -1, sizeof(int)*max);
|
||||
|
||||
for (i = 0; i < Level.NumLines(); ++i)
|
||||
{
|
||||
int v1 = Level.Lines[i].v1;
|
||||
int v2 = Level.Lines[i].v2;
|
||||
|
||||
if (map[v1] == -1)
|
||||
{
|
||||
newvert.x = oldverts[v1].x;
|
||||
newvert.y = oldverts[v1].y;
|
||||
newvert.index = oldverts[v1].index;
|
||||
map[v1] = VertexMap->SelectVertexExact (newvert);
|
||||
}
|
||||
if (map[v2] == -1)
|
||||
{
|
||||
newvert.x = oldverts[v2].x;
|
||||
newvert.y = oldverts[v2].y;
|
||||
newvert.index = oldverts[v2].index;
|
||||
map[v2] = VertexMap->SelectVertexExact (newvert);
|
||||
}
|
||||
|
||||
Level.Lines[i].v1 = map[v1];
|
||||
Level.Lines[i].v2 = map[v2];
|
||||
}
|
||||
InitialVertices = Vertices.Size ();
|
||||
Level.NumOrgVerts = (int)InitialVertices;
|
||||
delete[] map;
|
||||
}
|
||||
|
||||
// For every sidedef in the map, create a corresponding seg.
|
||||
|
||||
void FNodeBuilder::MakeSegsFromSides ()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < Level.NumLines(); ++i)
|
||||
{
|
||||
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||
{
|
||||
CreateSeg (i, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Linedef %d does not have a front side.\n", i);
|
||||
}
|
||||
|
||||
if (Level.Lines[i].sidenum[1] != NO_INDEX)
|
||||
{
|
||||
j = CreateSeg (i, 1);
|
||||
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||
{
|
||||
Segs[j-1].partner = j;
|
||||
Segs[j].partner = j-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FNodeBuilder::CreateSeg (int linenum, int sidenum)
|
||||
{
|
||||
FPrivSeg seg;
|
||||
DWORD backside;
|
||||
int segnum;
|
||||
|
||||
seg.next = DWORD_MAX;
|
||||
seg.loopnum = 0;
|
||||
seg.offset = 0;
|
||||
seg.partner = DWORD_MAX;
|
||||
seg.hashnext = NULL;
|
||||
seg.planefront = false;
|
||||
seg.planenum = DWORD_MAX;
|
||||
seg.storedseg = DWORD_MAX;
|
||||
|
||||
if (sidenum == 0)
|
||||
{ // front
|
||||
seg.v1 = Level.Lines[linenum].v1;
|
||||
seg.v2 = Level.Lines[linenum].v2;
|
||||
}
|
||||
else
|
||||
{ // back
|
||||
seg.v2 = Level.Lines[linenum].v1;
|
||||
seg.v1 = Level.Lines[linenum].v2;
|
||||
}
|
||||
seg.linedef = linenum;
|
||||
seg.sidedef = Level.Lines[linenum].sidenum[sidenum];
|
||||
backside = Level.Lines[linenum].sidenum[!sidenum];
|
||||
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
||||
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
||||
seg.nextforvert = Vertices[seg.v1].segs;
|
||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||
seg.angle = PointToAngle (Vertices[seg.v2].x-Vertices[seg.v1].x,
|
||||
Vertices[seg.v2].y-Vertices[seg.v1].y);
|
||||
|
||||
segnum = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = segnum;
|
||||
Vertices[seg.v2].segs2 = segnum;
|
||||
D(printf("Seg %4d: From line %d, side %s (%5d,%5d)-(%5d,%5d) [%08x,%08x]-[%08x,%08x]\n", segnum, linenum, sidenum ? "back " : "front",
|
||||
Vertices[seg.v1].x>>16, Vertices[seg.v1].y>>16, Vertices[seg.v2].x>>16, Vertices[seg.v2].y>>16,
|
||||
Vertices[seg.v1].x, Vertices[seg.v1].y, Vertices[seg.v2].x, Vertices[seg.v2].y));
|
||||
|
||||
return segnum;
|
||||
}
|
||||
|
||||
// Group colinear segs together so that only one seg per line needs to be checked
|
||||
// by SelectSplitter().
|
||||
|
||||
void FNodeBuilder::GroupSegPlanes ()
|
||||
{
|
||||
const int bucketbits = 12;
|
||||
FPrivSeg *buckets[1<<bucketbits] = { 0 };
|
||||
int i, planenum;
|
||||
|
||||
for (i = 0; i < (int)Segs.Size(); ++i)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[i];
|
||||
seg->next = i+1;
|
||||
seg->hashnext = NULL;
|
||||
}
|
||||
|
||||
Segs[Segs.Size()-1].next = DWORD_MAX;
|
||||
|
||||
for (i = planenum = 0; i < (int)Segs.Size(); ++i)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[i];
|
||||
fixed_t x1 = Vertices[seg->v1].x;
|
||||
fixed_t y1 = Vertices[seg->v1].y;
|
||||
fixed_t x2 = Vertices[seg->v2].x;
|
||||
fixed_t y2 = Vertices[seg->v2].y;
|
||||
angle_t ang = PointToAngle (x2 - x1, y2 - y1);
|
||||
|
||||
if (ang >= 1u<<31)
|
||||
ang += 1u<<31;
|
||||
|
||||
FPrivSeg *check = buckets[ang >>= 31-bucketbits];
|
||||
|
||||
while (check != NULL)
|
||||
{
|
||||
fixed_t cx1 = Vertices[check->v1].x;
|
||||
fixed_t cy1 = Vertices[check->v1].y;
|
||||
fixed_t cdx = Vertices[check->v2].x - cx1;
|
||||
fixed_t cdy = Vertices[check->v2].y - cy1;
|
||||
if (PointOnSide (x1, y1, cx1, cy1, cdx, cdy) == 0 &&
|
||||
PointOnSide (x2, y2, cx1, cy1, cdx, cdy) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
check = check->hashnext;
|
||||
}
|
||||
if (check != NULL)
|
||||
{
|
||||
seg->planenum = check->planenum;
|
||||
const FSimpleLine *line = &Planes[seg->planenum];
|
||||
if (line->dx != 0)
|
||||
{
|
||||
if ((line->dx > 0 && x2 > x1) || (line->dx < 0 && x2 < x1))
|
||||
{
|
||||
seg->planefront = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
seg->planefront = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((line->dy > 0 && y2 > y1) || (line->dy < 0 && y2 < y1))
|
||||
{
|
||||
seg->planefront = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
seg->planefront = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
seg->hashnext = buckets[ang];
|
||||
buckets[ang] = seg;
|
||||
seg->planenum = planenum++;
|
||||
seg->planefront = true;
|
||||
|
||||
FSimpleLine pline = { Vertices[seg->v1].x,
|
||||
Vertices[seg->v1].y,
|
||||
Vertices[seg->v2].x - Vertices[seg->v1].x,
|
||||
Vertices[seg->v2].y - Vertices[seg->v1].y };
|
||||
Planes.Push (pline);
|
||||
}
|
||||
}
|
||||
|
||||
D(printf ("%d planes from %d segs\n", planenum, Segs.Size()));
|
||||
|
||||
PlaneChecked.Reserve ((planenum + 7) / 8);
|
||||
}
|
||||
|
||||
// Find "loops" of segs surrounding polyobject's origin. Note that a polyobject's origin
|
||||
// is not solely defined by the polyobject's anchor, but also by the polyobject itself.
|
||||
// For the split avoidance to work properly, you must have a convex, complete loop of
|
||||
// segs surrounding the polyobject origin. All the maps in hexen.wad have complete loops of
|
||||
// segs around their polyobjects, but they are not all convex: The doors at the start of MAP01
|
||||
// and some of the pillars in MAP02 that surround the entrance to MAP06 are not convex.
|
||||
// Heuristic() uses some special weighting to make these cases work properly.
|
||||
|
||||
void FNodeBuilder::FindPolyContainers (TArray<FPolyStart> &spots, TArray<FPolyStart> &anchors)
|
||||
{
|
||||
int loop = 1;
|
||||
|
||||
for (unsigned int i = 0; i < spots.Size(); ++i)
|
||||
{
|
||||
FPolyStart *spot = &spots[i];
|
||||
fixed_t bbox[4];
|
||||
|
||||
if (GetPolyExtents (spot->polynum, bbox))
|
||||
{
|
||||
FPolyStart *anchor;
|
||||
unsigned int j;
|
||||
|
||||
for (j = 0; j < anchors.Size(); ++j)
|
||||
{
|
||||
anchor = &anchors[j];
|
||||
if (anchor->polynum == spot->polynum)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j < anchors.Size())
|
||||
{
|
||||
vertex_t mid;
|
||||
vertex_t center;
|
||||
|
||||
mid.x = bbox[BOXLEFT] + (bbox[BOXRIGHT]-bbox[BOXLEFT])/2;
|
||||
mid.y = bbox[BOXBOTTOM] + (bbox[BOXTOP]-bbox[BOXBOTTOM])/2;
|
||||
|
||||
center.x = mid.x - anchor->x + spot->x;
|
||||
center.y = mid.y - anchor->y + spot->y;
|
||||
|
||||
// Scan right for the seg closest to the polyobject's center after it
|
||||
// gets moved to its start spot.
|
||||
fixed_t closestdist = FIXED_MAX;
|
||||
DWORD closestseg = 0;
|
||||
|
||||
P(Printf ("start %d,%d -- center %d, %d\n", spot->x>>16, spot->y>>16, center.x>>16, center.y>>16));
|
||||
|
||||
for (unsigned int j = 0; j < Segs.Size(); ++j)
|
||||
{
|
||||
FPrivSeg *seg = &Segs[j];
|
||||
FPrivVert *v1 = &Vertices[seg->v1];
|
||||
FPrivVert *v2 = &Vertices[seg->v2];
|
||||
fixed_t dy = v2->y - v1->y;
|
||||
|
||||
if (dy == 0)
|
||||
{ // Horizontal, so skip it
|
||||
continue;
|
||||
}
|
||||
if ((v1->y < center.y && v2->y < center.y) || (v1->y > center.y && v2->y > center.y))
|
||||
{ // Not crossed
|
||||
continue;
|
||||
}
|
||||
|
||||
fixed_t dx = v2->x - v1->x;
|
||||
|
||||
if (PointOnSide (center.x, center.y, v1->x, v1->y, dx, dy) <= 0)
|
||||
{
|
||||
fixed_t t = DivScale30 (center.y - v1->y, dy);
|
||||
fixed_t sx = v1->x + MulScale30 (dx, t);
|
||||
fixed_t dist = sx - spot->x;
|
||||
|
||||
if (dist < closestdist && dist >= 0)
|
||||
{
|
||||
closestdist = dist;
|
||||
closestseg = (long)j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closestdist != FIXED_MAX)
|
||||
{
|
||||
loop = MarkLoop (closestseg, loop);
|
||||
P(Printf ("Found polyobj in sector %d (loop %d)\n", Segs[closestseg].frontsector,
|
||||
Segs[closestseg].loopnum));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int FNodeBuilder::MarkLoop (DWORD firstseg, int loopnum)
|
||||
{
|
||||
int seg;
|
||||
int sec = Segs[firstseg].frontsector;
|
||||
|
||||
if (Segs[firstseg].loopnum != 0)
|
||||
{ // already marked
|
||||
return loopnum;
|
||||
}
|
||||
|
||||
seg = firstseg;
|
||||
|
||||
do
|
||||
{
|
||||
FPrivSeg *s1 = &Segs[seg];
|
||||
|
||||
s1->loopnum = loopnum;
|
||||
|
||||
P(Printf ("Mark seg %d (%d,%d)-(%d,%d)\n", seg,
|
||||
Vertices[s1->v1].x>>16, Vertices[s1->v1].y>>16,
|
||||
Vertices[s1->v2].x>>16, Vertices[s1->v2].y>>16));
|
||||
|
||||
DWORD bestseg = DWORD_MAX;
|
||||
DWORD tryseg = Vertices[s1->v2].segs;
|
||||
angle_t bestang = ANGLE_MAX;
|
||||
angle_t ang1 = s1->angle;
|
||||
|
||||
while (tryseg != DWORD_MAX)
|
||||
{
|
||||
FPrivSeg *s2 = &Segs[tryseg];
|
||||
|
||||
if (s2->frontsector == sec)
|
||||
{
|
||||
angle_t ang2 = s2->angle + ANGLE_180;
|
||||
angle_t angdiff = ang2 - ang1;
|
||||
|
||||
if (angdiff < bestang && angdiff > 0)
|
||||
{
|
||||
bestang = angdiff;
|
||||
bestseg = tryseg;
|
||||
}
|
||||
}
|
||||
tryseg = s2->nextforvert;
|
||||
}
|
||||
|
||||
seg = bestseg;
|
||||
} while (seg != (int)DWORD_MAX && Segs[seg].loopnum == 0);
|
||||
|
||||
return loopnum + 1;
|
||||
}
|
||||
|
||||
// Find the bounding box for a specific polyobject.
|
||||
|
||||
bool FNodeBuilder::GetPolyExtents (int polynum, fixed_t bbox[4])
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
bbox[BOXLEFT] = bbox[BOXBOTTOM] = FIXED_MAX;
|
||||
bbox[BOXRIGHT] = bbox[BOXTOP] = FIXED_MIN;
|
||||
|
||||
// Try to find a polyobj marked with a start line
|
||||
for (i = 0; i < Segs.Size(); ++i)
|
||||
{
|
||||
if (Level.Lines[Segs[i].linedef].special == PO_LINE_START &&
|
||||
Level.Lines[Segs[i].linedef].args[0] == polynum)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < Segs.Size())
|
||||
{
|
||||
vertex_t start;
|
||||
unsigned int vert;
|
||||
unsigned int count = Segs.Size(); // to prevent endless loops. Stop when this reaches the number of segs.
|
||||
|
||||
vert = Segs[i].v1;
|
||||
|
||||
start.x = Vertices[vert].x;
|
||||
start.y = Vertices[vert].y;
|
||||
|
||||
do
|
||||
{
|
||||
AddSegToBBox (bbox, &Segs[i]);
|
||||
vert = Segs[i].v2;
|
||||
i = Vertices[vert].segs;
|
||||
} while (--count && i != DWORD_MAX && (Vertices[vert].x != start.x || Vertices[vert].y != start.y));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to find a polyobj marked with explicit lines
|
||||
bool found = false;
|
||||
|
||||
for (i = 0; i < Segs.Size(); ++i)
|
||||
{
|
||||
if (Level.Lines[Segs[i].linedef].special == PO_LINE_EXPLICIT &&
|
||||
Level.Lines[Segs[i].linedef].args[0] == polynum)
|
||||
{
|
||||
AddSegToBBox (bbox, &Segs[i]);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void FNodeBuilder::AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg)
|
||||
{
|
||||
FPrivVert *v1 = &Vertices[seg->v1];
|
||||
FPrivVert *v2 = &Vertices[seg->v2];
|
||||
|
||||
if (v1->x < bbox[BOXLEFT]) bbox[BOXLEFT] = v1->x;
|
||||
if (v1->x > bbox[BOXRIGHT]) bbox[BOXRIGHT] = v1->x;
|
||||
if (v1->y < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = v1->y;
|
||||
if (v1->y > bbox[BOXTOP]) bbox[BOXTOP] = v1->y;
|
||||
|
||||
if (v2->x < bbox[BOXLEFT]) bbox[BOXLEFT] = v2->x;
|
||||
if (v2->x > bbox[BOXRIGHT]) bbox[BOXRIGHT] = v2->x;
|
||||
if (v2->y < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = v2->y;
|
||||
if (v2->y > bbox[BOXTOP]) bbox[BOXTOP] = v2->y;
|
||||
}
|
||||
|
||||
FNodeBuilder::FVertexMap::FVertexMap (FNodeBuilder &builder,
|
||||
fixed_t minx, fixed_t miny, fixed_t maxx, fixed_t maxy)
|
||||
: MyBuilder(builder)
|
||||
{
|
||||
MinX = minx;
|
||||
MinY = miny;
|
||||
BlocksWide = int(((double(maxx) - minx + 1) + (BLOCK_SIZE - 1)) / BLOCK_SIZE);
|
||||
BlocksTall = int(((double(maxy) - miny + 1) + (BLOCK_SIZE - 1)) / BLOCK_SIZE);
|
||||
MaxX = MinX + BlocksWide * BLOCK_SIZE - 1;
|
||||
MaxY = MinY + BlocksTall * BLOCK_SIZE - 1;
|
||||
VertexGrid = new TArray<int>[BlocksWide * BlocksTall];
|
||||
}
|
||||
|
||||
FNodeBuilder::FVertexMap::~FVertexMap ()
|
||||
{
|
||||
delete[] VertexGrid;
|
||||
}
|
||||
|
||||
int FNodeBuilder::FVertexMap::SelectVertexExact (FNodeBuilder::FPrivVert &vert)
|
||||
{
|
||||
TArray<int> &block = VertexGrid[GetBlock (vert.x, vert.y)];
|
||||
FPrivVert *vertices = &MyBuilder.Vertices[0];
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < block.Size(); ++i)
|
||||
{
|
||||
if (vertices[block[i]].x == vert.x && vertices[block[i]].y == vert.y)
|
||||
{
|
||||
return block[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Not present: add it!
|
||||
return InsertVertex (vert);
|
||||
}
|
||||
|
||||
int FNodeBuilder::FVertexMap::SelectVertexClose (FNodeBuilder::FPrivVert &vert)
|
||||
{
|
||||
TArray<int> &block = VertexGrid[GetBlock (vert.x, vert.y)];
|
||||
FPrivVert *vertices = &MyBuilder.Vertices[0];
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < block.Size(); ++i)
|
||||
{
|
||||
#if VERTEX_EPSILON <= 1
|
||||
if (vertices[block[i]].x == vert.x && vertices[block[i]].y == vert.y)
|
||||
#else
|
||||
if (abs(vertices[block[i]].x - vert.x) < VERTEX_EPSILON &&
|
||||
abs(vertices[block[i]].y - vert.y) < VERTEX_EPSILON)
|
||||
#endif
|
||||
{
|
||||
return block[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Not present: add it!
|
||||
return InsertVertex (vert);
|
||||
}
|
||||
|
||||
int FNodeBuilder::FVertexMap::InsertVertex (FNodeBuilder::FPrivVert &vert)
|
||||
{
|
||||
int vertnum;
|
||||
|
||||
vert.segs = DWORD_MAX;
|
||||
vert.segs2 = DWORD_MAX;
|
||||
vertnum = (int)MyBuilder.Vertices.Push (vert);
|
||||
|
||||
// If a vertex is near a block boundary, then it will be inserted on
|
||||
// both sides of the boundary so that SelectVertexClose can find
|
||||
// it by checking in only one block.
|
||||
fixed_t minx = MAX (MinX, vert.x - VERTEX_EPSILON);
|
||||
fixed_t maxx = MIN (MaxX, vert.x + VERTEX_EPSILON);
|
||||
fixed_t miny = MAX (MinY, vert.y - VERTEX_EPSILON);
|
||||
fixed_t maxy = MIN (MaxY, vert.y + VERTEX_EPSILON);
|
||||
|
||||
int blk[4] =
|
||||
{
|
||||
GetBlock (minx, miny),
|
||||
GetBlock (maxx, miny),
|
||||
GetBlock (minx, maxy),
|
||||
GetBlock (maxx, maxy)
|
||||
};
|
||||
unsigned int blkcount[4] =
|
||||
{
|
||||
VertexGrid[blk[0]].Size(),
|
||||
VertexGrid[blk[1]].Size(),
|
||||
VertexGrid[blk[2]].Size(),
|
||||
VertexGrid[blk[3]].Size()
|
||||
};
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (VertexGrid[blk[i]].Size() == blkcount[i])
|
||||
{
|
||||
VertexGrid[blk[i]].Push (vertnum);
|
||||
}
|
||||
}
|
||||
|
||||
return vertnum;
|
||||
}
|
714
src/parse/sc_man.cpp
Normal file
714
src/parse/sc_man.cpp
Normal file
|
@ -0,0 +1,714 @@
|
|||
/*
|
||||
Reads wad files, builds nodes, and saves new wad files.
|
||||
Copyright (C) 1996 Raven Software
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include "sc_man.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define MAX_STRING_SIZE 4096
|
||||
#define ASCII_COMMENT (';')
|
||||
#define CPP_COMMENT ('/')
|
||||
#define C_COMMENT ('*')
|
||||
#define ASCII_QUOTE (34)
|
||||
#define LUMP_SCRIPT 1
|
||||
#define FILE_ZONE_SCRIPT 2
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static void SC_PrepareScript (void);
|
||||
static void CheckOpen (void);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
char *sc_String;
|
||||
int sc_StringLen;
|
||||
int sc_Number;
|
||||
double sc_Float;
|
||||
int sc_Line;
|
||||
bool sc_End;
|
||||
bool sc_Crossed;
|
||||
bool sc_StringQuoted;
|
||||
bool sc_FileScripts = false;
|
||||
//FILE *sc_Out;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static char *ScriptBuffer;
|
||||
static char *ScriptPtr;
|
||||
static char *ScriptEndPtr;
|
||||
static char StringBuffer[MAX_STRING_SIZE];
|
||||
static bool ScriptOpen = false;
|
||||
static int ScriptSize;
|
||||
static bool AlreadyGot = false;
|
||||
static char *SavedScriptPtr;
|
||||
static int SavedScriptLine;
|
||||
static bool CMode;
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_OpenFile
|
||||
//
|
||||
// Loads a script
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_OpenMem (const char *name, char *buffer, int len)
|
||||
{
|
||||
SC_Close ();
|
||||
ScriptSize = len;
|
||||
ScriptBuffer = buffer;
|
||||
SC_PrepareScript ();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_PrepareScript
|
||||
//
|
||||
// Prepares a script for parsing.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void SC_PrepareScript (void)
|
||||
{
|
||||
ScriptPtr = ScriptBuffer;
|
||||
ScriptEndPtr = ScriptPtr + ScriptSize;
|
||||
sc_Line = 1;
|
||||
sc_End = false;
|
||||
ScriptOpen = true;
|
||||
sc_String = StringBuffer;
|
||||
AlreadyGot = false;
|
||||
SavedScriptPtr = NULL;
|
||||
CMode = false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_Close
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_Close (void)
|
||||
{
|
||||
if (ScriptOpen)
|
||||
{
|
||||
ScriptBuffer = NULL;
|
||||
ScriptOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_SavePos
|
||||
//
|
||||
// Saves the current script location for restoration later
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_SavePos (void)
|
||||
{
|
||||
CheckOpen ();
|
||||
if (sc_End)
|
||||
{
|
||||
SavedScriptPtr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
SavedScriptPtr = ScriptPtr;
|
||||
SavedScriptLine = sc_Line;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_RestorePos
|
||||
//
|
||||
// Restores the previously saved script location
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_RestorePos (void)
|
||||
{
|
||||
if (SavedScriptPtr)
|
||||
{
|
||||
ScriptPtr = SavedScriptPtr;
|
||||
sc_Line = SavedScriptLine;
|
||||
sc_End = false;
|
||||
AlreadyGot = false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_SetCMode
|
||||
//
|
||||
// Enables/disables C mode. In C mode, more characters are considered to
|
||||
// be whole words than in non-C mode.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_SetCMode (bool cmode)
|
||||
{
|
||||
CMode = cmode;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_GetString
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_GetString ()
|
||||
{
|
||||
char *text;
|
||||
bool foundToken;
|
||||
|
||||
CheckOpen();
|
||||
if (AlreadyGot)
|
||||
{
|
||||
AlreadyGot = false;
|
||||
return true;
|
||||
}
|
||||
foundToken = false;
|
||||
sc_Crossed = false;
|
||||
sc_StringQuoted = false;
|
||||
if (ScriptPtr >= ScriptEndPtr)
|
||||
{
|
||||
sc_End = true;
|
||||
return false;
|
||||
}
|
||||
while (foundToken == false)
|
||||
{
|
||||
while (ScriptPtr < ScriptEndPtr && *ScriptPtr <= ' ')
|
||||
{
|
||||
if (*ScriptPtr++ == '\n')
|
||||
{
|
||||
sc_Line++;
|
||||
sc_Crossed = true;
|
||||
}
|
||||
}
|
||||
if (ScriptPtr >= ScriptEndPtr)
|
||||
{
|
||||
sc_End = true;
|
||||
return false;
|
||||
}
|
||||
if ((CMode || *ScriptPtr != ASCII_COMMENT) &&
|
||||
!(ScriptPtr[0] == CPP_COMMENT && ScriptPtr < ScriptEndPtr - 1 &&
|
||||
(ScriptPtr[1] == CPP_COMMENT || ScriptPtr[1] == C_COMMENT)))
|
||||
{ // Found a token
|
||||
foundToken = true;
|
||||
}
|
||||
else
|
||||
{ // Skip comment
|
||||
if (ScriptPtr[0] == CPP_COMMENT && ScriptPtr[1] == C_COMMENT)
|
||||
{ // C comment
|
||||
while (ScriptPtr[0] != C_COMMENT || ScriptPtr[1] != CPP_COMMENT)
|
||||
{
|
||||
if (ScriptPtr[0] == '\n')
|
||||
{
|
||||
sc_Line++;
|
||||
sc_Crossed = true;
|
||||
}
|
||||
// fputc(ScriptPtr[0], sc_Out);
|
||||
ScriptPtr++;
|
||||
if (ScriptPtr >= ScriptEndPtr - 1)
|
||||
{
|
||||
sc_End = true;
|
||||
return false;
|
||||
}
|
||||
// fputs("*/", sc_Out);
|
||||
}
|
||||
ScriptPtr += 2;
|
||||
}
|
||||
else
|
||||
{ // C++ comment
|
||||
while (*ScriptPtr++ != '\n')
|
||||
{
|
||||
// fputc(ScriptPtr[-1], sc_Out);
|
||||
if (ScriptPtr >= ScriptEndPtr)
|
||||
{
|
||||
sc_End = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sc_Line++;
|
||||
sc_Crossed = true;
|
||||
// fputc('\n', sc_Out);
|
||||
}
|
||||
}
|
||||
}
|
||||
text = sc_String;
|
||||
if (*ScriptPtr == ASCII_QUOTE)
|
||||
{ // Quoted string - return string including the quotes
|
||||
*text++ = *ScriptPtr++;
|
||||
sc_StringQuoted = true;
|
||||
while (*ScriptPtr != ASCII_QUOTE)
|
||||
{
|
||||
if (*ScriptPtr >= 0 && *ScriptPtr < ' ')
|
||||
{
|
||||
ScriptPtr++;
|
||||
}
|
||||
else if (*ScriptPtr == '\\')
|
||||
{
|
||||
// Add the backslash character and the following chararcter to the text.
|
||||
// We do not translate the escape sequence in any way, since the only
|
||||
// thing that will happen to this string is that it will be written back
|
||||
// out to disk. Basically, we just need this special case here so that
|
||||
// string reading won't terminate prematurely when a \" sequence is
|
||||
// used to embed a quote mark in the string.
|
||||
*text++ = *ScriptPtr++;
|
||||
*text++ = *ScriptPtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*text++ = *ScriptPtr++;
|
||||
}
|
||||
if (ScriptPtr == ScriptEndPtr
|
||||
|| text == &sc_String[MAX_STRING_SIZE-1])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
*text++ = '"';
|
||||
ScriptPtr++;
|
||||
}
|
||||
else
|
||||
{ // Normal string
|
||||
static const char *stopchars;
|
||||
|
||||
if (CMode)
|
||||
{
|
||||
stopchars = "`~!@#$%^&*(){}[]/=\?+|;:<>,";
|
||||
|
||||
// '-' can be its own token, or it can be part of a negative number
|
||||
if (*ScriptPtr == '-')
|
||||
{
|
||||
*text++ = '-';
|
||||
ScriptPtr++;
|
||||
if (ScriptPtr < ScriptEndPtr || (*ScriptPtr >= '0' && *ScriptPtr <= '9'))
|
||||
{
|
||||
goto grabtoken;
|
||||
}
|
||||
goto gottoken;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stopchars = "{}|=";
|
||||
}
|
||||
if (strchr (stopchars, *ScriptPtr))
|
||||
{
|
||||
*text++ = *ScriptPtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
grabtoken:
|
||||
while ((*ScriptPtr > ' ') && (strchr (stopchars, *ScriptPtr) == NULL)
|
||||
&& (CMode || *ScriptPtr != ASCII_COMMENT)
|
||||
&& !(ScriptPtr[0] == CPP_COMMENT && (ScriptPtr < ScriptEndPtr - 1) &&
|
||||
(ScriptPtr[1] == CPP_COMMENT || ScriptPtr[1] == C_COMMENT)))
|
||||
{
|
||||
*text++ = *ScriptPtr++;
|
||||
if (ScriptPtr == ScriptEndPtr
|
||||
|| text == &sc_String[MAX_STRING_SIZE-1])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gottoken:
|
||||
*text = 0;
|
||||
sc_StringLen = int(text - sc_String);
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MustGetString
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_MustGetString (void)
|
||||
{
|
||||
if (SC_GetString () == false)
|
||||
{
|
||||
SC_ScriptError ("Missing string (unexpected end of file).");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MustGetStringName
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_MustGetStringName (const char *name)
|
||||
{
|
||||
SC_MustGetString ();
|
||||
if (SC_Compare (name) == false)
|
||||
{
|
||||
SC_ScriptError ("Expected '%s', got '%s'.", name, sc_String);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_CheckString
|
||||
//
|
||||
// Checks if the next token matches the specified string. Returns true if
|
||||
// it does. If it doesn't, it ungets it and returns false.
|
||||
//==========================================================================
|
||||
|
||||
bool SC_CheckString (const char *name)
|
||||
{
|
||||
if (SC_GetString ())
|
||||
{
|
||||
if (SC_Compare (name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
SC_UnGet ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_GetNumber
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_GetNumber (void)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
CheckOpen ();
|
||||
if (SC_GetString())
|
||||
{
|
||||
if (strcmp (sc_String, "MAXINT") == 0)
|
||||
{
|
||||
sc_Number = INT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_Number = strtol (sc_String, &stopper, 0);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
SC_ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", sc_String);
|
||||
}
|
||||
}
|
||||
sc_Float = sc_Number;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MustGetNumber
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_MustGetNumber (void)
|
||||
{
|
||||
if (SC_GetNumber() == false)
|
||||
{
|
||||
SC_ScriptError ("Missing integer (unexpected end of file).");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_CheckNumber
|
||||
// similar to SC_GetNumber but ungets the token if it isn't a number
|
||||
// and does not print an error
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_CheckNumber (void)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
//CheckOpen ();
|
||||
if (SC_GetString())
|
||||
{
|
||||
if (strcmp (sc_String, "MAXINT") == 0)
|
||||
{
|
||||
sc_Number = INT_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_Number = strtol (sc_String, &stopper, 0);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
SC_UnGet();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
sc_Float = sc_Number;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_CheckFloat
|
||||
// [GRB] Same as SC_CheckNumber, only for floats
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_CheckFloat (void)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
//CheckOpen ();
|
||||
if (SC_GetString())
|
||||
{
|
||||
sc_Float = strtod (sc_String, &stopper);
|
||||
sc_Number = (int)sc_Float;
|
||||
if (*stopper != 0)
|
||||
{
|
||||
SC_UnGet();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_GetFloat
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_GetFloat (void)
|
||||
{
|
||||
char *stopper;
|
||||
|
||||
CheckOpen ();
|
||||
if (SC_GetString())
|
||||
{
|
||||
sc_Float = strtod (sc_String, &stopper);
|
||||
if (*stopper != 0)
|
||||
{
|
||||
SC_ScriptError("SC_GetFloat: Bad numeric constant \"%s\".\n",sc_String);
|
||||
}
|
||||
sc_Number = (int)sc_Float;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MustGetFloat
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_MustGetFloat (void)
|
||||
{
|
||||
if (SC_GetFloat() == false)
|
||||
{
|
||||
SC_ScriptError ("Missing floating-point number (unexpected end of file).");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_UnGet
|
||||
//
|
||||
// Assumes there is a valid string in sc_String.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_UnGet (void)
|
||||
{
|
||||
AlreadyGot = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_Check
|
||||
//
|
||||
// Returns true if another token is on the current line.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
/*
|
||||
bool SC_Check(void)
|
||||
{
|
||||
char *text;
|
||||
|
||||
CheckOpen();
|
||||
text = ScriptPtr;
|
||||
if(text >= ScriptEndPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
while(*text <= 32)
|
||||
{
|
||||
if(*text == '\n')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
text++;
|
||||
if(text == ScriptEndPtr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(*text == ASCII_COMMENT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MatchString
|
||||
//
|
||||
// Returns the index of the first match to sc_String from the passed
|
||||
// array of strings, or -1 if not found.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int SC_MatchString (const char **strings)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; *strings != NULL; i++)
|
||||
{
|
||||
if (SC_Compare (*strings++))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_MustMatchString
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int SC_MustMatchString (const char **strings)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = SC_MatchString (strings);
|
||||
if (i == -1)
|
||||
{
|
||||
SC_ScriptError (NULL);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_Compare
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool SC_Compare (const char *text)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
return (_stricmp (text, sc_String) == 0);
|
||||
#else
|
||||
return (strcasecmp (text, sc_String) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// SC_ScriptError
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SC_ScriptError (const char *message, ...)
|
||||
{
|
||||
char composed[2048];
|
||||
if (message == NULL)
|
||||
{
|
||||
message = "Bad syntax.";
|
||||
}
|
||||
|
||||
va_list arglist;
|
||||
va_start (arglist, message);
|
||||
vsprintf (composed, message, arglist);
|
||||
va_end (arglist);
|
||||
|
||||
printf ("Script error, line %d:\n%s\n", sc_Line, composed);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CheckOpen
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void CheckOpen(void)
|
||||
{
|
||||
if (ScriptOpen == false)
|
||||
{
|
||||
printf ("SC_ call before SC_Open().\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
42
src/parse/sc_man.h
Normal file
42
src/parse/sc_man.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
void SC_Open (const char *name);
|
||||
void SC_OpenFile (const char *name);
|
||||
void SC_OpenMem (const char *name, char *buffer, int size);
|
||||
void SC_OpenLumpNum (int lump, const char *name);
|
||||
void SC_Close (void);
|
||||
void SC_SetCMode (bool cmode);
|
||||
void SC_SetEscape (bool esc);
|
||||
void SC_SavePos (void);
|
||||
void SC_RestorePos (void);
|
||||
bool SC_GetString (void);
|
||||
void SC_MustGetString (void);
|
||||
void SC_MustGetStringName (const char *name);
|
||||
bool SC_CheckString (const char *name);
|
||||
bool SC_GetNumber (void);
|
||||
void SC_MustGetNumber (void);
|
||||
bool SC_CheckNumber (void);
|
||||
bool SC_CheckFloat (void);
|
||||
bool SC_GetFloat (void);
|
||||
void SC_MustGetFloat (void);
|
||||
void SC_UnGet (void);
|
||||
//boolean SC_Check(void);
|
||||
bool SC_Compare (const char *text);
|
||||
int SC_MatchString (const char **strings);
|
||||
int SC_MustMatchString (const char **strings);
|
||||
void SC_ScriptError (const char *message, ...);
|
||||
void SC_SaveScriptState();
|
||||
void SC_RestoreScriptState();
|
||||
|
||||
extern char *sc_String;
|
||||
extern int sc_StringLen;
|
||||
extern int sc_Number;
|
||||
extern double sc_Float;
|
||||
extern int sc_Line;
|
||||
extern bool sc_End;
|
||||
extern bool sc_Crossed;
|
||||
extern bool sc_FileScripts;
|
||||
extern bool sc_StringQuoted;
|
||||
extern char *sc_ScriptsDir;
|
||||
//extern FILE *sc_Out;
|
20
src/platform/windows/resource.h
Normal file
20
src/platform/windows/resource.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by resource.rc
|
||||
//
|
||||
#define IDD_MAPVIEW 101
|
||||
#define IDC_MAPVIEW 1004
|
||||
#define IDC_STATICNUMBER 1007
|
||||
#define IDC_COMBO3 1010
|
||||
#define IDC_COMBO1 1010
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1011
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
138
src/platform/windows/resource.rc
Normal file
138
src/platform/windows/resource.rc
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winresrc.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_MAPVIEW DIALOGEX 0, 0, 510, 446
|
||||
STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_APPWINDOW
|
||||
CAPTION "ZDRay Map Viewer"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "Custom2",IDC_MAPVIEW,"MapViewer",WS_VSCROLL | WS_HSCROLL,7,7,496,411,WS_EX_CLIENTEDGE
|
||||
PUSHBUTTON "OK",IDOK,7,423,53,16
|
||||
LTEXT "Static",IDC_STATICNUMBER,68,425,60,14
|
||||
COMBOBOX IDC_COMBO1,142,427,123,250,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_MAPVIEW, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 503
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 439
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winresrc.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "ZDRay Raytracer"
|
||||
VALUE "FileVersion", "1.0"
|
||||
VALUE "InternalName", "zdray"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2017 Magnus Norddahl, 2002-2016 Randy Heit, 2009 Christoph Oelckers"
|
||||
VALUE "OriginalFilename", "zdray.exe"
|
||||
VALUE "ProductName", "ZDRay"
|
||||
VALUE "ProductVersion", "1.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
1074
src/viewer/view.cpp
Normal file
1074
src/viewer/view.cpp
Normal file
File diff suppressed because it is too large
Load diff
485
src/wad/wad.cpp
Normal file
485
src/wad/wad.cpp
Normal file
|
@ -0,0 +1,485 @@
|
|||
/*
|
||||
WAD-handling routines.
|
||||
Copyright (C) 2002-2006 Randy Heit
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include "wad.h"
|
||||
|
||||
static const char MapLumpNames[12][9] =
|
||||
{
|
||||
"THINGS",
|
||||
"LINEDEFS",
|
||||
"SIDEDEFS",
|
||||
"VERTEXES",
|
||||
"SEGS",
|
||||
"SSECTORS",
|
||||
"NODES",
|
||||
"SECTORS",
|
||||
"REJECT",
|
||||
"BLOCKMAP",
|
||||
"BEHAVIOR",
|
||||
"SCRIPTS"
|
||||
};
|
||||
|
||||
static const bool MapLumpRequired[12] =
|
||||
{
|
||||
true, // THINGS
|
||||
true, // LINEDEFS
|
||||
true, // SIDEDEFS
|
||||
true, // VERTEXES
|
||||
false, // SEGS
|
||||
false, // SSECTORS
|
||||
false, // NODES
|
||||
true, // SECTORS
|
||||
false, // REJECT
|
||||
false, // BLOCKMAP
|
||||
false, // BEHAVIOR
|
||||
false // SCRIPTS
|
||||
};
|
||||
|
||||
static const char GLLumpNames[5][9] =
|
||||
{
|
||||
"GL_VERT",
|
||||
"GL_SEGS",
|
||||
"GL_SSECT",
|
||||
"GL_NODES",
|
||||
"GL_PVS"
|
||||
};
|
||||
|
||||
FWadReader::FWadReader (const char *filename)
|
||||
: Lumps (NULL), File (NULL)
|
||||
{
|
||||
File = fopen (filename, "rb");
|
||||
if (File == NULL)
|
||||
{
|
||||
throw std::runtime_error("Could not open input file");
|
||||
}
|
||||
|
||||
SafeRead (&Header, sizeof(Header));
|
||||
if (Header.Magic[0] != 'P' && Header.Magic[0] != 'I' &&
|
||||
Header.Magic[1] != 'W' &&
|
||||
Header.Magic[2] != 'A' &&
|
||||
Header.Magic[3] != 'D')
|
||||
{
|
||||
fclose (File);
|
||||
File = NULL;
|
||||
throw std::runtime_error("Input file is not a wad");
|
||||
}
|
||||
|
||||
Header.NumLumps = LittleLong(Header.NumLumps);
|
||||
Header.Directory = LittleLong(Header.Directory);
|
||||
|
||||
if (fseek (File, Header.Directory, SEEK_SET))
|
||||
{
|
||||
throw std::runtime_error("Could not read wad directory");
|
||||
}
|
||||
|
||||
Lumps = new WadLump[Header.NumLumps];
|
||||
SafeRead (Lumps, Header.NumLumps * sizeof(*Lumps));
|
||||
|
||||
for (int i = 0; i < Header.NumLumps; ++i)
|
||||
{
|
||||
Lumps[i].FilePos = LittleLong(Lumps[i].FilePos);
|
||||
Lumps[i].Size = LittleLong(Lumps[i].Size);
|
||||
}
|
||||
}
|
||||
|
||||
FWadReader::~FWadReader ()
|
||||
{
|
||||
if (File) fclose (File);
|
||||
if (Lumps) delete[] Lumps;
|
||||
}
|
||||
|
||||
bool FWadReader::IsIWAD () const
|
||||
{
|
||||
return Header.Magic[0] == 'I';
|
||||
}
|
||||
|
||||
int FWadReader::NumLumps () const
|
||||
{
|
||||
return Header.NumLumps;
|
||||
}
|
||||
|
||||
int FWadReader::FindLump (const char *name, int index) const
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
for (; index < Header.NumLumps; ++index)
|
||||
{
|
||||
if (strnicmp (Lumps[index].Name, name, 8) == 0)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FWadReader::FindMapLump (const char *name, int map) const
|
||||
{
|
||||
int i, j, k;
|
||||
++map;
|
||||
|
||||
for (i = 0; i < 12; ++i)
|
||||
{
|
||||
if (strnicmp (MapLumpNames[i], name, 8) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 12)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = k = 0; j < 12; ++j)
|
||||
{
|
||||
if (strnicmp (Lumps[map+k].Name, MapLumpNames[j], 8) == 0)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
return map+k;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FWadReader::isUDMF (int index) const
|
||||
{
|
||||
index++;
|
||||
|
||||
if (strnicmp(Lumps[index].Name, "TEXTMAP", 8) == 0)
|
||||
{
|
||||
// UDMF map
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool FWadReader::IsMap (int index) const
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (isUDMF(index)) return true;
|
||||
|
||||
index++;
|
||||
|
||||
for (i = j = 0; i < 12; ++i)
|
||||
{
|
||||
if (strnicmp (Lumps[index+j].Name, MapLumpNames[i], 8) != 0)
|
||||
{
|
||||
if (MapLumpRequired[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int FWadReader::FindGLLump (const char *name, int glheader) const
|
||||
{
|
||||
int i, j, k;
|
||||
++glheader;
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
if (strnicmp (Lumps[glheader+i].Name, name, 8) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 5)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = k = 0; j < 5; ++j)
|
||||
{
|
||||
if (strnicmp (Lumps[glheader+k].Name, GLLumpNames[j], 8) == 0)
|
||||
{
|
||||
if (i == j)
|
||||
{
|
||||
return glheader+k;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FWadReader::IsGLNodes (int index) const
|
||||
{
|
||||
if (index + 4 >= Header.NumLumps)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Lumps[index].Name[0] != 'G' ||
|
||||
Lumps[index].Name[1] != 'L' ||
|
||||
Lumps[index].Name[2] != '_')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
index++;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (strnicmp (Lumps[i+index].Name, GLLumpNames[i], 8) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int FWadReader::SkipGLNodes (int index) const
|
||||
{
|
||||
index++;
|
||||
for (int i = 0; i < 5 && index < Header.NumLumps; ++i, ++index)
|
||||
{
|
||||
if (strnicmp (Lumps[index].Name, GLLumpNames[i], 8) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
bool FWadReader::MapHasBehavior (int map) const
|
||||
{
|
||||
return FindMapLump ("BEHAVIOR", map) != -1;
|
||||
}
|
||||
|
||||
int FWadReader::NextMap (int index) const
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
index++;
|
||||
}
|
||||
for (; index < Header.NumLumps; ++index)
|
||||
{
|
||||
if (IsMap (index))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FWadReader::LumpAfterMap (int i) const
|
||||
{
|
||||
int j, k;
|
||||
|
||||
if (isUDMF(i))
|
||||
{
|
||||
// UDMF map
|
||||
i += 2;
|
||||
while (strnicmp(Lumps[i].Name, "ENDMAP", 8) != 0 && i < Header.NumLumps)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
return i+1; // one lump after ENDMAP
|
||||
}
|
||||
|
||||
i++;
|
||||
for (j = k = 0; j < 12; ++j)
|
||||
{
|
||||
if (strnicmp (Lumps[i+k].Name, MapLumpNames[j], 8) != 0)
|
||||
{
|
||||
if (MapLumpRequired[j])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return i+k;
|
||||
}
|
||||
|
||||
void FWadReader::SafeRead (void *buffer, size_t size)
|
||||
{
|
||||
if (fread (buffer, 1, size, File) != size)
|
||||
{
|
||||
throw std::runtime_error("Failed to read");
|
||||
}
|
||||
}
|
||||
|
||||
const char *FWadReader::LumpName (int lump)
|
||||
{
|
||||
static char name[9];
|
||||
strncpy (name, Lumps[lump].Name, 8);
|
||||
name[8] = 0;
|
||||
return name;
|
||||
}
|
||||
|
||||
FWadWriter::FWadWriter (const char *filename, bool iwad)
|
||||
: File (NULL)
|
||||
{
|
||||
File = fopen (filename, "wb");
|
||||
if (File == NULL)
|
||||
{
|
||||
throw std::runtime_error("Could not open output file");
|
||||
}
|
||||
|
||||
WadHeader head;
|
||||
|
||||
if (iwad)
|
||||
{
|
||||
head.Magic[0] = 'I';
|
||||
}
|
||||
else
|
||||
{
|
||||
head.Magic[0] = 'P';
|
||||
}
|
||||
head.Magic[1] = 'W';
|
||||
head.Magic[2] = 'A';
|
||||
head.Magic[3] = 'D';
|
||||
|
||||
SafeWrite (&head, sizeof(head));
|
||||
}
|
||||
|
||||
FWadWriter::~FWadWriter ()
|
||||
{
|
||||
if (File)
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
}
|
||||
|
||||
void FWadWriter::Close ()
|
||||
{
|
||||
if (File)
|
||||
{
|
||||
int32_t head[2];
|
||||
|
||||
head[0] = LittleLong(Lumps.Size());
|
||||
head[1] = LittleLong(ftell (File));
|
||||
|
||||
SafeWrite (&Lumps[0], sizeof(WadLump)*Lumps.Size());
|
||||
fseek (File, 4, SEEK_SET);
|
||||
SafeWrite (head, 8);
|
||||
fclose (File);
|
||||
File = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FWadWriter::CreateLabel (const char *name)
|
||||
{
|
||||
WadLump lump;
|
||||
|
||||
strncpy (lump.Name, name, 8);
|
||||
lump.FilePos = LittleLong(ftell (File));
|
||||
lump.Size = 0;
|
||||
Lumps.Push (lump);
|
||||
}
|
||||
|
||||
void FWadWriter::WriteLump (const char *name, const void *data, int len)
|
||||
{
|
||||
WadLump lump;
|
||||
|
||||
strncpy (lump.Name, name, 8);
|
||||
lump.FilePos = LittleLong(ftell (File));
|
||||
lump.Size = LittleLong(len);
|
||||
Lumps.Push (lump);
|
||||
|
||||
SafeWrite (data, len);
|
||||
}
|
||||
|
||||
void FWadWriter::CopyLump (FWadReader &wad, int lump)
|
||||
{
|
||||
BYTE *data;
|
||||
int size;
|
||||
|
||||
ReadLump<BYTE> (wad, lump, data, size);
|
||||
if (data != NULL)
|
||||
{
|
||||
WriteLump (wad.LumpName (lump), data, size);
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void FWadWriter::StartWritingLump (const char *name)
|
||||
{
|
||||
CreateLabel (name);
|
||||
}
|
||||
|
||||
void FWadWriter::AddToLump (const void *data, int len)
|
||||
{
|
||||
SafeWrite (data, len);
|
||||
Lumps[Lumps.Size()-1].Size += len;
|
||||
}
|
||||
|
||||
void FWadWriter::SafeWrite (const void *buffer, size_t size)
|
||||
{
|
||||
if (fwrite (buffer, 1, size, File) != size)
|
||||
{
|
||||
fclose (File);
|
||||
File = NULL;
|
||||
throw std::runtime_error(
|
||||
"Failed to write. Check that this directory is writable and\n"
|
||||
"that you have enough free disk space.");
|
||||
}
|
||||
}
|
||||
|
||||
FWadWriter &FWadWriter::operator << (BYTE val)
|
||||
{
|
||||
AddToLump (&val, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FWadWriter &FWadWriter::operator << (WORD val)
|
||||
{
|
||||
val = LittleShort(val);
|
||||
AddToLump ((BYTE *)&val, 2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FWadWriter &FWadWriter::operator << (SWORD val)
|
||||
{
|
||||
val = LittleShort(val);
|
||||
AddToLump ((BYTE *)&val, 2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FWadWriter &FWadWriter::operator << (DWORD val)
|
||||
{
|
||||
val = LittleLong(val);
|
||||
AddToLump ((BYTE *)&val, 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FWadWriter &FWadWriter::operator << (fixed_t val)
|
||||
{
|
||||
val = LittleLong(val);
|
||||
AddToLump ((BYTE *)&val, 4);
|
||||
return *this;
|
||||
}
|
||||
|
108
src/wad/wad.h
Normal file
108
src/wad/wad.h
Normal file
|
@ -0,0 +1,108 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "framework/zdray.h"
|
||||
#include "framework/tarray.h"
|
||||
|
||||
struct WadHeader
|
||||
{
|
||||
char Magic[4];
|
||||
int32_t NumLumps;
|
||||
int32_t Directory;
|
||||
};
|
||||
|
||||
struct WadLump
|
||||
{
|
||||
int32_t FilePos;
|
||||
int32_t Size;
|
||||
char Name[8];
|
||||
};
|
||||
|
||||
class FWadReader
|
||||
{
|
||||
public:
|
||||
FWadReader (const char *filename);
|
||||
~FWadReader ();
|
||||
|
||||
bool IsIWAD () const;
|
||||
bool isUDMF(int lump) const;
|
||||
int FindLump (const char *name, int index=0) const;
|
||||
int FindMapLump (const char *name, int map) const;
|
||||
int FindGLLump (const char *name, int glheader) const;
|
||||
const char *LumpName (int lump);
|
||||
bool IsMap (int index) const;
|
||||
bool IsGLNodes (int index) const;
|
||||
int SkipGLNodes (int index) const;
|
||||
bool MapHasBehavior (int map) const;
|
||||
int NextMap (int startindex) const;
|
||||
int LumpAfterMap (int map) const;
|
||||
int NumLumps () const;
|
||||
|
||||
void SafeRead (void *buffer, size_t size);
|
||||
|
||||
// VC++ 6 does not support template member functions in non-template classes!
|
||||
template<class T>
|
||||
friend void ReadLump (FWadReader &wad, int index, T *&data, int &size);
|
||||
|
||||
private:
|
||||
WadHeader Header;
|
||||
WadLump *Lumps;
|
||||
FILE *File;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
void ReadLump (FWadReader &wad, int index, T *&data, int &size)
|
||||
{
|
||||
if ((unsigned)index >= (unsigned)wad.Header.NumLumps)
|
||||
{
|
||||
data = NULL;
|
||||
size = 0;
|
||||
return;
|
||||
}
|
||||
if (fseek (wad.File, wad.Lumps[index].FilePos, SEEK_SET))
|
||||
{
|
||||
throw std::runtime_error("Failed to seek");
|
||||
}
|
||||
size = wad.Lumps[index].Size / sizeof(T);
|
||||
data = new T[size];
|
||||
wad.SafeRead (data, size*sizeof(T));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ReadMapLump (FWadReader &wad, const char *name, int index, T *&data, int &size)
|
||||
{
|
||||
ReadLump (wad, wad.FindMapLump (name, index), data, size);
|
||||
}
|
||||
|
||||
|
||||
class FWadWriter
|
||||
{
|
||||
public:
|
||||
FWadWriter (const char *filename, bool iwad);
|
||||
~FWadWriter ();
|
||||
|
||||
void CreateLabel (const char *name);
|
||||
void WriteLump (const char *name, const void *data, int len);
|
||||
void CopyLump (FWadReader &wad, int lump);
|
||||
void Close ();
|
||||
|
||||
// Routines to write a lump in segments.
|
||||
void StartWritingLump (const char *name);
|
||||
void AddToLump (const void *data, int len);
|
||||
|
||||
FWadWriter &operator << (BYTE);
|
||||
FWadWriter &operator << (WORD);
|
||||
FWadWriter &operator << (SWORD);
|
||||
FWadWriter &operator << (DWORD);
|
||||
FWadWriter &operator << (fixed_t);
|
||||
|
||||
private:
|
||||
TArray<WadLump> Lumps;
|
||||
FILE *File;
|
||||
|
||||
void SafeWrite (const void *buffer, size_t size);
|
||||
};
|
21
zlib/CMakeLists.txt
Normal file
21
zlib/CMakeLists.txt
Normal file
|
@ -0,0 +1,21 @@
|
|||
cmake_minimum_required( VERSION 2.4 )
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUC )
|
||||
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fomit-frame-pointer" )
|
||||
endif( CMAKE_COMPILER_IS_GNUC )
|
||||
|
||||
add_library( z
|
||||
adler32.c
|
||||
compress.c
|
||||
crc32.c
|
||||
deflate.c
|
||||
trees.c
|
||||
zutil.c
|
||||
crc32.h
|
||||
deflate.h
|
||||
gzguts.h
|
||||
trees.h
|
||||
zconf.h
|
||||
zlib.h
|
||||
zutil.h )
|
||||
target_link_libraries( z )
|
179
zlib/adler32.c
Normal file
179
zlib/adler32.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2011 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#define local static
|
||||
|
||||
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
|
||||
|
||||
#define BASE 65521 /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware --
|
||||
try it both ways to see which is faster */
|
||||
#ifdef NO_DIVIDE
|
||||
/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
|
||||
(thank you to John Reiser for pointing this out) */
|
||||
# define CHOP(a) \
|
||||
do { \
|
||||
unsigned long tmp = a >> 16; \
|
||||
a &= 0xffffUL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
} while (0)
|
||||
# define MOD28(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
CHOP(a); \
|
||||
MOD28(a); \
|
||||
} while (0)
|
||||
# define MOD63(a) \
|
||||
do { /* this assumes a is not negative */ \
|
||||
z_off64_t tmp = a >> 32; \
|
||||
a &= 0xffffffffL; \
|
||||
a += (tmp << 8) - (tmp << 5) + tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
tmp = a >> 16; \
|
||||
a &= 0xffffL; \
|
||||
a += (tmp << 4) - tmp; \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD28(a) a %= BASE
|
||||
# define MOD63(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD28(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong adler32_combine_(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* for negative len, return invalid adler32 as a clue for debugging */
|
||||
if (len2 < 0)
|
||||
return 0xffffffffUL;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
MOD63(len2); /* assumes len2 >= 0 */
|
||||
rem = (unsigned)len2;
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum1 >= BASE) sum1 -= BASE;
|
||||
if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 >= BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return adler32_combine_(adler1, adler2, len2);
|
||||
}
|
80
zlib/compress.c
Normal file
80
zlib/compress.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2005 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
|
||||
(sourceLen >> 25) + 13;
|
||||
}
|
425
zlib/crc32.c
Normal file
425
zlib/crc32.c
Normal file
|
@ -0,0 +1,425 @@
|
|||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
|
||||
DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#if !defined(NOBYFOUR) && defined(Z_U4)
|
||||
# define BYFOUR
|
||||
#endif
|
||||
#ifdef BYFOUR
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
|
||||
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local z_crc_t FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const z_crc_t FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
z_crc_t c;
|
||||
int n, k;
|
||||
z_crc_t poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0;
|
||||
for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
|
||||
poly |= (z_crc_t)1 << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (z_crc_t)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = ZSWAP32(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = ZSWAP32(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const z_crc_t FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const z_crc_t FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
|
||||
(unsigned long)(table[n]),
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const z_crc_t FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const z_crc_t FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
uInt len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
z_crc_t endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = (z_crc_t)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *++buf4; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register z_crc_t c;
|
||||
register const z_crc_t FAR *buf4;
|
||||
|
||||
c = ZSWAP32((z_crc_t)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf4++;
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(ZSWAP32(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local uLong crc32_combine_(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case (also disallow negative lengths) */
|
||||
if (len2 <= 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
||||
|
||||
uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off64_t len2;
|
||||
{
|
||||
return crc32_combine_(crc1, crc2, len2);
|
||||
}
|
441
zlib/crc32.h
Normal file
441
zlib/crc32.h
Normal file
|
@ -0,0 +1,441 @@
|
|||
/* crc32.h -- tables for rapid CRC calculation
|
||||
* Generated automatically by crc32.c
|
||||
*/
|
||||
|
||||
local const z_crc_t FAR crc_table[TBLS][256] =
|
||||
{
|
||||
{
|
||||
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
|
||||
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
|
||||
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
|
||||
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
|
||||
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
|
||||
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
|
||||
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
|
||||
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
|
||||
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
|
||||
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
|
||||
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
|
||||
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
|
||||
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
|
||||
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
|
||||
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
|
||||
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
|
||||
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
|
||||
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
|
||||
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
|
||||
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
|
||||
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
|
||||
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
|
||||
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
|
||||
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
|
||||
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
|
||||
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
|
||||
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
|
||||
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
|
||||
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
|
||||
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
|
||||
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
|
||||
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
|
||||
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
|
||||
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
|
||||
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
|
||||
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
|
||||
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
|
||||
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
|
||||
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
|
||||
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
|
||||
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
|
||||
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
|
||||
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
|
||||
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
|
||||
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
|
||||
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
|
||||
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
|
||||
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
|
||||
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
|
||||
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
|
||||
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
|
||||
0x2d02ef8dUL
|
||||
#ifdef BYFOUR
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
|
||||
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
|
||||
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
|
||||
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
|
||||
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
|
||||
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
|
||||
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
|
||||
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
|
||||
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
|
||||
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
|
||||
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
|
||||
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
|
||||
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
|
||||
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
|
||||
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
|
||||
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
|
||||
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
|
||||
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
|
||||
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
|
||||
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
|
||||
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
|
||||
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
|
||||
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
|
||||
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
|
||||
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
|
||||
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
|
||||
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
|
||||
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
|
||||
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
|
||||
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
|
||||
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
|
||||
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
|
||||
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
|
||||
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
|
||||
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
|
||||
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
|
||||
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
|
||||
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
|
||||
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
|
||||
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
|
||||
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
|
||||
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
|
||||
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
|
||||
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
|
||||
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
|
||||
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
|
||||
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
|
||||
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
|
||||
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
|
||||
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
|
||||
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
|
||||
0x9324fd72UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
|
||||
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
|
||||
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
|
||||
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
|
||||
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
|
||||
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
|
||||
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
|
||||
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
|
||||
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
|
||||
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
|
||||
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
|
||||
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
|
||||
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
|
||||
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
|
||||
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
|
||||
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
|
||||
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
|
||||
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
|
||||
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
|
||||
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
|
||||
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
|
||||
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
|
||||
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
|
||||
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
|
||||
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
|
||||
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
|
||||
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
|
||||
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
|
||||
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
|
||||
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
|
||||
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
|
||||
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
|
||||
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
|
||||
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
|
||||
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
|
||||
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
|
||||
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
|
||||
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
|
||||
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
|
||||
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
|
||||
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
|
||||
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
|
||||
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
|
||||
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
|
||||
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
|
||||
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
|
||||
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
|
||||
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
|
||||
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
|
||||
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
|
||||
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
|
||||
0xbe9834edUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
|
||||
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
|
||||
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
|
||||
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
|
||||
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
|
||||
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
|
||||
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
|
||||
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
|
||||
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
|
||||
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
|
||||
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
|
||||
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
|
||||
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
|
||||
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
|
||||
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
|
||||
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
|
||||
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
|
||||
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
|
||||
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
|
||||
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
|
||||
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
|
||||
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
|
||||
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
|
||||
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
|
||||
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
|
||||
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
|
||||
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
|
||||
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
|
||||
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
|
||||
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
|
||||
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
|
||||
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
|
||||
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
|
||||
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
|
||||
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
|
||||
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
|
||||
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
|
||||
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
|
||||
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
|
||||
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
|
||||
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
|
||||
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
|
||||
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
|
||||
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
|
||||
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
|
||||
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
|
||||
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
|
||||
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
|
||||
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
|
||||
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
|
||||
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
|
||||
0xde0506f1UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
|
||||
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
|
||||
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
|
||||
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
|
||||
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
|
||||
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
|
||||
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
|
||||
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
|
||||
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
|
||||
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
|
||||
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
|
||||
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
|
||||
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
|
||||
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
|
||||
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
|
||||
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
|
||||
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
|
||||
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
|
||||
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
|
||||
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
|
||||
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
|
||||
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
|
||||
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
|
||||
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
|
||||
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
|
||||
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
|
||||
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
|
||||
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
|
||||
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
|
||||
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
|
||||
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
|
||||
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
|
||||
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
|
||||
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
|
||||
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
|
||||
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
|
||||
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
|
||||
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
|
||||
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
|
||||
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
|
||||
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
|
||||
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
|
||||
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
|
||||
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
|
||||
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
|
||||
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
|
||||
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
|
||||
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
|
||||
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
|
||||
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
|
||||
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
|
||||
0x8def022dUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
|
||||
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
|
||||
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
|
||||
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
|
||||
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
|
||||
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
|
||||
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
|
||||
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
|
||||
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
|
||||
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
|
||||
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
|
||||
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
|
||||
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
|
||||
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
|
||||
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
|
||||
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
|
||||
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
|
||||
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
|
||||
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
|
||||
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
|
||||
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
|
||||
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
|
||||
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
|
||||
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
|
||||
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
|
||||
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
|
||||
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
|
||||
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
|
||||
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
|
||||
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
|
||||
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
|
||||
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
|
||||
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
|
||||
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
|
||||
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
|
||||
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
|
||||
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
|
||||
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
|
||||
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
|
||||
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
|
||||
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
|
||||
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
|
||||
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
|
||||
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
|
||||
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
|
||||
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
|
||||
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
|
||||
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
|
||||
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
|
||||
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
|
||||
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
|
||||
0x72fd2493UL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
|
||||
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
|
||||
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
|
||||
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
|
||||
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
|
||||
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
|
||||
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
|
||||
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
|
||||
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
|
||||
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
|
||||
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
|
||||
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
|
||||
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
|
||||
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
|
||||
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
|
||||
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
|
||||
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
|
||||
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
|
||||
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
|
||||
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
|
||||
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
|
||||
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
|
||||
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
|
||||
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
|
||||
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
|
||||
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
|
||||
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
|
||||
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
|
||||
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
|
||||
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
|
||||
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
|
||||
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
|
||||
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
|
||||
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
|
||||
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
|
||||
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
|
||||
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
|
||||
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
|
||||
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
|
||||
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
|
||||
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
|
||||
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
|
||||
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
|
||||
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
|
||||
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
|
||||
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
|
||||
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
|
||||
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
|
||||
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
|
||||
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
|
||||
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
|
||||
0xed3498beUL
|
||||
},
|
||||
{
|
||||
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
|
||||
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
|
||||
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
|
||||
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
|
||||
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
|
||||
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
|
||||
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
|
||||
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
|
||||
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
|
||||
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
|
||||
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
|
||||
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
|
||||
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
|
||||
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
|
||||
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
|
||||
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
|
||||
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
|
||||
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
|
||||
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
|
||||
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
|
||||
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
|
||||
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
|
||||
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
|
||||
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
|
||||
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
|
||||
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
|
||||
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
|
||||
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
|
||||
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
|
||||
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
|
||||
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
|
||||
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
|
||||
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
|
||||
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
|
||||
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
|
||||
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
|
||||
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
|
||||
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
|
||||
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
|
||||
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
|
||||
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
|
||||
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
|
||||
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
|
||||
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
|
||||
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
|
||||
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
|
||||
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
|
||||
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
|
||||
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
|
||||
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
|
||||
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
|
||||
0xf10605deUL
|
||||
#endif
|
||||
}
|
||||
};
|
1965
zlib/deflate.c
Normal file
1965
zlib/deflate.c
Normal file
File diff suppressed because it is too large
Load diff
346
zlib/deflate.h
Normal file
346
zlib/deflate.h
Normal file
|
@ -0,0 +1,346 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2012 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef DEFLATE_H
|
||||
#define DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* define NO_GZIP when compiling if you want to disable gzip header and
|
||||
trailer creation by deflate(). NO_GZIP would be used to avoid linking in
|
||||
the crc code when it is not needed. For shared libraries, gzip encoding
|
||||
should be left enabled. */
|
||||
#ifndef NO_GZIP
|
||||
# define GZIP
|
||||
#endif
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define Buf_size 16
|
||||
/* size of bit buffer in bi_buf */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define EXTRA_STATE 69
|
||||
#define NAME_STATE 73
|
||||
#define COMMENT_STATE 91
|
||||
#define HCRC_STATE 103
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
ulg pending_buf_size; /* size of pending_buf */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
uInt pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
gz_headerp gzhead; /* gzip header information to write */
|
||||
uInt gzindex; /* where in extra, name, or comment */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to suppress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
uInt insert; /* bytes at end of window left to insert */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg compressed_len; /* total bit length of compressed file mod 2^32 */
|
||||
ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
ulg high_water;
|
||||
/* High water mark offset in window for initialized bytes -- bytes above
|
||||
* this are set to zero in order to avoid memory check warnings when
|
||||
* longest match routines access bytes past the input. This is then
|
||||
* updated to the new high water mark.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
#define WIN_INIT MAX_MATCH
|
||||
/* Number of bytes after end of data in window to initialize in order to avoid
|
||||
memory checker errors from longest match routines */
|
||||
|
||||
/* in trees.c */
|
||||
void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
|
||||
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
|
||||
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
|
||||
ulg stored_len, int last));
|
||||
|
||||
#define d_code(dist) \
|
||||
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
|
||||
/* Mapping from a distance to a distance code. dist is the distance - 1 and
|
||||
* must not have side effects. _dist_code[256] and _dist_code[257] are never
|
||||
* used.
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
/* Inline versions of _tr_tally for speed: */
|
||||
|
||||
#if defined(GEN_TREES_H) || !defined(STDC)
|
||||
extern uch ZLIB_INTERNAL _length_code[];
|
||||
extern uch ZLIB_INTERNAL _dist_code[];
|
||||
#else
|
||||
extern const uch ZLIB_INTERNAL _length_code[];
|
||||
extern const uch ZLIB_INTERNAL _dist_code[];
|
||||
#endif
|
||||
|
||||
# define _tr_tally_lit(s, c, flush) \
|
||||
{ uch cc = (c); \
|
||||
s->d_buf[s->last_lit] = 0; \
|
||||
s->l_buf[s->last_lit++] = cc; \
|
||||
s->dyn_ltree[cc].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
{ uch len = (length); \
|
||||
ush dist = (distance); \
|
||||
s->d_buf[s->last_lit] = dist; \
|
||||
s->l_buf[s->last_lit++] = len; \
|
||||
dist--; \
|
||||
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
|
||||
s->dyn_dtree[d_code(dist)].Freq++; \
|
||||
flush = (s->last_lit == s->lit_bufsize-1); \
|
||||
}
|
||||
#else
|
||||
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
|
||||
# define _tr_tally_dist(s, distance, length, flush) \
|
||||
flush = _tr_tally(s, distance, length)
|
||||
#endif
|
||||
|
||||
#endif /* DEFLATE_H */
|
193
zlib/gzguts.h
Normal file
193
zlib/gzguts.h
Normal file
|
@ -0,0 +1,193 @@
|
|||
/* gzguts.h -- zlib internal header definitions for gz* operations
|
||||
* Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef _LARGEFILE64_SOURCE
|
||||
# ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE 1
|
||||
# endif
|
||||
# ifdef _FILE_OFFSET_BITS
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h>
|
||||
#endif
|
||||
|
||||
#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
|
||||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEFLATE /* for compatibility with old definition */
|
||||
# define NO_GZCOMPRESS
|
||||
#endif
|
||||
|
||||
#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_VSNPRINTF
|
||||
# ifdef MSDOS
|
||||
/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
|
||||
but for now we just assume it doesn't. */
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __TURBOC__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef WIN32
|
||||
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
|
||||
# if !defined(vsnprintf) && !defined(NO_vsnprintf)
|
||||
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef VMS
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __OS400__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
# ifdef __MVS__
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
/* gz* functions always use library allocation functions */
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
/* get errno and strerror definition */
|
||||
#if defined UNDER_CE
|
||||
# include <windows.h>
|
||||
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
|
||||
#else
|
||||
# ifndef NO_STRERROR
|
||||
# include <errno.h>
|
||||
# define zstrerror() strerror(errno)
|
||||
# else
|
||||
# define zstrerror() "stdio error (consult errno)"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
|
||||
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
|
||||
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
|
||||
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
|
||||
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
|
||||
#endif
|
||||
|
||||
/* default memLevel */
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
|
||||
/* default i/o buffer size -- double this for output when reading */
|
||||
#define GZBUFSIZE 8192
|
||||
|
||||
/* gzip modes, also provide a little integrity check on the passed structure */
|
||||
#define GZ_NONE 0
|
||||
#define GZ_READ 7247
|
||||
#define GZ_WRITE 31153
|
||||
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
|
||||
|
||||
/* values for gz_state how */
|
||||
#define LOOK 0 /* look for a gzip header */
|
||||
#define COPY 1 /* copy input directly */
|
||||
#define GZIP 2 /* decompress a gzip stream */
|
||||
|
||||
/* internal gzip file state data structure */
|
||||
typedef struct {
|
||||
/* exposed contents for gzgetc() macro */
|
||||
struct gzFile_s x; /* "x" for exposed */
|
||||
/* x.have: number of bytes available at x.next */
|
||||
/* x.next: next output data to deliver or write */
|
||||
/* x.pos: current position in uncompressed data */
|
||||
/* used for both reading and writing */
|
||||
int mode; /* see gzip modes above */
|
||||
int fd; /* file descriptor */
|
||||
char *path; /* path or fd for error messages */
|
||||
unsigned size; /* buffer size, zero if not allocated yet */
|
||||
unsigned want; /* requested buffer size, default is GZBUFSIZE */
|
||||
unsigned char *in; /* input buffer */
|
||||
unsigned char *out; /* output buffer (double-sized when reading) */
|
||||
int direct; /* 0 if processing gzip, 1 if transparent */
|
||||
/* just for reading */
|
||||
int how; /* 0: get header, 1: copy, 2: decompress */
|
||||
z_off64_t start; /* where the gzip data started, for rewinding */
|
||||
int eof; /* true if end of input file reached */
|
||||
int past; /* true if read requested past end */
|
||||
/* just for writing */
|
||||
int level; /* compression level */
|
||||
int strategy; /* compression strategy */
|
||||
/* seek request */
|
||||
z_off64_t skip; /* amount to skip (already rewound if backwards) */
|
||||
int seek; /* true if seek request pending */
|
||||
/* error information */
|
||||
int err; /* error code */
|
||||
char *msg; /* error message */
|
||||
/* zlib inflate or deflate stream */
|
||||
z_stream strm; /* stream structure in-place (not a pointer) */
|
||||
} gz_state;
|
||||
typedef gz_state FAR *gz_statep;
|
||||
|
||||
/* shared functions */
|
||||
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
|
||||
#if defined UNDER_CE
|
||||
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
|
||||
#endif
|
||||
|
||||
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
|
||||
value -- needed when comparing unsigned to z_off64_t, which is signed
|
||||
(possible z_off64_t types off_t, off64_t, and long are all signed) */
|
||||
#ifdef INT_MAX
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
|
||||
#else
|
||||
unsigned ZLIB_INTERNAL gz_intmax OF((void));
|
||||
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
|
||||
#endif
|
1224
zlib/trees.c
Normal file
1224
zlib/trees.c
Normal file
File diff suppressed because it is too large
Load diff
128
zlib/trees.h
Normal file
128
zlib/trees.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/* header created automatically with -DGEN_TREES_H */
|
||||
|
||||
local const ct_data static_ltree[L_CODES+2] = {
|
||||
{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
|
||||
{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
|
||||
{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
|
||||
{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
|
||||
{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
|
||||
{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
|
||||
{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
|
||||
{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
|
||||
{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
|
||||
{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
|
||||
{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
|
||||
{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
|
||||
{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
|
||||
{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
|
||||
{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
|
||||
{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
|
||||
{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
|
||||
{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
|
||||
{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
|
||||
{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
|
||||
{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
|
||||
{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
|
||||
{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
|
||||
{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
|
||||
{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
|
||||
{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
|
||||
{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
|
||||
{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
|
||||
{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
|
||||
{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
|
||||
{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
|
||||
{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
|
||||
{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
|
||||
{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
|
||||
{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
|
||||
{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
|
||||
{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
|
||||
{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
|
||||
{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
|
||||
{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
|
||||
{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
|
||||
{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
|
||||
{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
|
||||
{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
|
||||
{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
|
||||
{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
|
||||
{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
|
||||
{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
|
||||
{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
|
||||
{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
|
||||
{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
|
||||
{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
|
||||
{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
|
||||
{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
|
||||
{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
|
||||
{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
|
||||
{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
|
||||
{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
|
||||
};
|
||||
|
||||
local const ct_data static_dtree[D_CODES] = {
|
||||
{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
|
||||
{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
|
||||
{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
|
||||
{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
|
||||
{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
|
||||
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
|
||||
};
|
||||
|
||||
const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
|
||||
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
|
||||
14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
|
||||
18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
|
||||
28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
||||
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
|
||||
};
|
||||
|
||||
const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
|
||||
21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
|
||||
22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||
23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
|
||||
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
|
||||
27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
|
||||
};
|
||||
|
||||
local const int base_length[LENGTH_CODES] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
|
||||
64, 80, 96, 112, 128, 160, 192, 224, 0
|
||||
};
|
||||
|
||||
local const int base_dist[D_CODES] = {
|
||||
0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
|
||||
32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
|
||||
1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
|
||||
};
|
||||
|
506
zlib/zconf.h
Normal file
506
zlib/zconf.h
Normal file
|
@ -0,0 +1,506 @@
|
|||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2012 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZCONF_H
|
||||
#define ZCONF_H
|
||||
|
||||
/*
|
||||
* If you *really* need a unique prefix for all types and library functions,
|
||||
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
|
||||
* Even better than compiling with -DZ_PREFIX would be to use configure to set
|
||||
* this permanently in zconf.h using "./configure --zprefix".
|
||||
*/
|
||||
#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
|
||||
# define Z_PREFIX_SET
|
||||
|
||||
/* all linked symbols */
|
||||
# define _dist_code z__dist_code
|
||||
# define _length_code z__length_code
|
||||
# define _tr_align z__tr_align
|
||||
# define _tr_flush_block z__tr_flush_block
|
||||
# define _tr_init z__tr_init
|
||||
# define _tr_stored_block z__tr_stored_block
|
||||
# define _tr_tally z__tr_tally
|
||||
# define adler32 z_adler32
|
||||
# define adler32_combine z_adler32_combine
|
||||
# define adler32_combine64 z_adler32_combine64
|
||||
# ifndef Z_SOLO
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# endif
|
||||
# define crc32 z_crc32
|
||||
# define crc32_combine z_crc32_combine
|
||||
# define crc32_combine64 z_crc32_combine64
|
||||
# define deflate z_deflate
|
||||
# define deflateBound z_deflateBound
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflatePending z_deflatePending
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflateResetKeep z_deflateResetKeep
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateSetHeader z_deflateSetHeader
|
||||
# define deflateTune z_deflateTune
|
||||
# define deflate_copyright z_deflate_copyright
|
||||
# define get_crc_table z_get_crc_table
|
||||
# ifndef Z_SOLO
|
||||
# define gz_error z_gz_error
|
||||
# define gz_intmax z_gz_intmax
|
||||
# define gz_strwinerror z_gz_strwinerror
|
||||
# define gzbuffer z_gzbuffer
|
||||
# define gzclearerr z_gzclearerr
|
||||
# define gzclose z_gzclose
|
||||
# define gzclose_r z_gzclose_r
|
||||
# define gzclose_w z_gzclose_w
|
||||
# define gzdirect z_gzdirect
|
||||
# define gzdopen z_gzdopen
|
||||
# define gzeof z_gzeof
|
||||
# define gzerror z_gzerror
|
||||
# define gzflush z_gzflush
|
||||
# define gzgetc z_gzgetc
|
||||
# define gzgetc_ z_gzgetc_
|
||||
# define gzgets z_gzgets
|
||||
# define gzoffset z_gzoffset
|
||||
# define gzoffset64 z_gzoffset64
|
||||
# define gzopen z_gzopen
|
||||
# define gzopen64 z_gzopen64
|
||||
# ifdef _WIN32
|
||||
# define gzopen_w z_gzopen_w
|
||||
# endif
|
||||
# define gzprintf z_gzprintf
|
||||
# define gzputc z_gzputc
|
||||
# define gzputs z_gzputs
|
||||
# define gzread z_gzread
|
||||
# define gzrewind z_gzrewind
|
||||
# define gzseek z_gzseek
|
||||
# define gzseek64 z_gzseek64
|
||||
# define gzsetparams z_gzsetparams
|
||||
# define gztell z_gztell
|
||||
# define gztell64 z_gztell64
|
||||
# define gzungetc z_gzungetc
|
||||
# define gzwrite z_gzwrite
|
||||
# endif
|
||||
# define inflate z_inflate
|
||||
# define inflateBack z_inflateBack
|
||||
# define inflateBackEnd z_inflateBackEnd
|
||||
# define inflateBackInit_ z_inflateBackInit_
|
||||
# define inflateCopy z_inflateCopy
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define inflateGetHeader z_inflateGetHeader
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflateMark z_inflateMark
|
||||
# define inflatePrime z_inflatePrime
|
||||
# define inflateReset z_inflateReset
|
||||
# define inflateReset2 z_inflateReset2
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateUndermine z_inflateUndermine
|
||||
# define inflateResetKeep z_inflateResetKeep
|
||||
# define inflate_copyright z_inflate_copyright
|
||||
# define inflate_fast z_inflate_fast
|
||||
# define inflate_table z_inflate_table
|
||||
# ifndef Z_SOLO
|
||||
# define uncompress z_uncompress
|
||||
# endif
|
||||
# define zError z_zError
|
||||
# ifndef Z_SOLO
|
||||
# define zcalloc z_zcalloc
|
||||
# define zcfree z_zcfree
|
||||
# endif
|
||||
# define zlibCompileFlags z_zlibCompileFlags
|
||||
# define zlibVersion z_zlibVersion
|
||||
|
||||
/* all zlib typedefs in zlib.h and zconf.h */
|
||||
# define Byte z_Byte
|
||||
# define Bytef z_Bytef
|
||||
# define alloc_func z_alloc_func
|
||||
# define charf z_charf
|
||||
# define free_func z_free_func
|
||||
# ifndef Z_SOLO
|
||||
# define gzFile z_gzFile
|
||||
# endif
|
||||
# define gz_header z_gz_header
|
||||
# define gz_headerp z_gz_headerp
|
||||
# define in_func z_in_func
|
||||
# define intf z_intf
|
||||
# define out_func z_out_func
|
||||
# define uInt z_uInt
|
||||
# define uIntf z_uIntf
|
||||
# define uLong z_uLong
|
||||
# define uLongf z_uLongf
|
||||
# define voidp z_voidp
|
||||
# define voidpc z_voidpc
|
||||
# define voidpf z_voidpf
|
||||
|
||||
/* all zlib structs in zlib.h and zconf.h */
|
||||
# define gz_header_s z_gz_header_s
|
||||
# define internal_state z_internal_state
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__MSDOS__) && !defined(MSDOS)
|
||||
# define MSDOS
|
||||
#endif
|
||||
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
|
||||
# define OS2
|
||||
#endif
|
||||
#if defined(_WINDOWS) && !defined(WINDOWS)
|
||||
# define WINDOWS
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
|
||||
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
|
||||
# ifndef SYS16BIT
|
||||
# define SYS16BIT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
|
||||
* than 64k bytes at a time (needed on systems with 16-bit int).
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# define MAXSEG_64K
|
||||
#endif
|
||||
#ifdef MSDOS
|
||||
# define UNALIGNED_OK
|
||||
#endif
|
||||
|
||||
#ifdef __STDC_VERSION__
|
||||
# ifndef STDC
|
||||
# define STDC
|
||||
# endif
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# ifndef STDC99
|
||||
# define STDC99
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
|
||||
# define STDC
|
||||
#endif
|
||||
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
|
||||
# define STDC
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
|
||||
# define const /* note: need a more gentle solution here */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ZLIB_CONST) && !defined(z_const)
|
||||
# define z_const const
|
||||
#else
|
||||
# define z_const
|
||||
#endif
|
||||
|
||||
/* Some Mac compilers merge all .h files incorrectly: */
|
||||
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
|
||||
# define NO_DUMMY_DECL
|
||||
#endif
|
||||
|
||||
/* Maximum value for memLevel in deflateInit2 */
|
||||
#ifndef MAX_MEM_LEVEL
|
||||
# ifdef MAXSEG_64K
|
||||
# define MAX_MEM_LEVEL 8
|
||||
# else
|
||||
# define MAX_MEM_LEVEL 9
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
|
||||
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
|
||||
* created by gzip. (Files created by minigzip can still be extracted by
|
||||
* gzip.)
|
||||
*/
|
||||
#ifndef MAX_WBITS
|
||||
# define MAX_WBITS 15 /* 32K LZ77 window */
|
||||
#endif
|
||||
|
||||
/* The memory requirements for deflate are (in bytes):
|
||||
(1 << (windowBits+2)) + (1 << (memLevel+9))
|
||||
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
|
||||
plus a few kilobytes for small objects. For example, if you want to reduce
|
||||
the default memory requirements from 256K to 128K, compile with
|
||||
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
|
||||
Of course this will generally degrade compression (there's no free lunch).
|
||||
|
||||
The memory requirements for inflate are (in bytes) 1 << windowBits
|
||||
that is, 32K for windowBits=15 (default value) plus a few kilobytes
|
||||
for small objects.
|
||||
*/
|
||||
|
||||
/* Type declarations */
|
||||
|
||||
#ifndef OF /* function prototypes */
|
||||
# ifdef STDC
|
||||
# define OF(args) args
|
||||
# else
|
||||
# define OF(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef Z_ARG /* function prototypes for stdarg */
|
||||
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# define Z_ARG(args) args
|
||||
# else
|
||||
# define Z_ARG(args) ()
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The following definitions for FAR are needed only for MSDOS mixed
|
||||
* model programming (small or medium model with some far allocations).
|
||||
* This was tested only with MSC; for other MSDOS compilers you may have
|
||||
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
|
||||
* just define FAR to be empty.
|
||||
*/
|
||||
#ifdef SYS16BIT
|
||||
# if defined(M_I86SM) || defined(M_I86MM)
|
||||
/* MSC small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef _MSC_VER
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
# if (defined(__SMALL__) || defined(__MEDIUM__))
|
||||
/* Turbo C small or medium model */
|
||||
# define SMALL_MEDIUM
|
||||
# ifdef __BORLANDC__
|
||||
# define FAR _far
|
||||
# else
|
||||
# define FAR far
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS) || defined(WIN32)
|
||||
/* If building or using zlib as a DLL, define ZLIB_DLL.
|
||||
* This is not mandatory, but it offers a little performance increase.
|
||||
*/
|
||||
# ifdef ZLIB_DLL
|
||||
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXTERN extern __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXTERN extern __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# endif /* ZLIB_DLL */
|
||||
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
|
||||
* define ZLIB_WINAPI.
|
||||
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
|
||||
*/
|
||||
# ifdef ZLIB_WINAPI
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# endif
|
||||
# include <windows.h>
|
||||
/* No need for _export, use ZLIB.DEF instead. */
|
||||
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
|
||||
# define ZEXPORT WINAPI
|
||||
# ifdef WIN32
|
||||
# define ZEXPORTVA WINAPIV
|
||||
# else
|
||||
# define ZEXPORTVA FAR CDECL
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (__BEOS__)
|
||||
# ifdef ZLIB_DLL
|
||||
# ifdef ZLIB_INTERNAL
|
||||
# define ZEXPORT __declspec(dllexport)
|
||||
# define ZEXPORTVA __declspec(dllexport)
|
||||
# else
|
||||
# define ZEXPORT __declspec(dllimport)
|
||||
# define ZEXPORTVA __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef ZEXTERN
|
||||
# define ZEXTERN extern
|
||||
#endif
|
||||
#ifndef ZEXPORT
|
||||
# define ZEXPORT
|
||||
#endif
|
||||
#ifndef ZEXPORTVA
|
||||
# define ZEXPORTVA
|
||||
#endif
|
||||
|
||||
#ifndef FAR
|
||||
# define FAR
|
||||
#endif
|
||||
|
||||
#if !defined(__MACTYPES__)
|
||||
typedef unsigned char Byte; /* 8 bits */
|
||||
#endif
|
||||
typedef unsigned int uInt; /* 16 bits or more */
|
||||
typedef unsigned long uLong; /* 32 bits or more */
|
||||
|
||||
#ifdef SMALL_MEDIUM
|
||||
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
|
||||
# define Bytef Byte FAR
|
||||
#else
|
||||
typedef Byte FAR Bytef;
|
||||
#endif
|
||||
typedef char FAR charf;
|
||||
typedef int FAR intf;
|
||||
typedef uInt FAR uIntf;
|
||||
typedef uLong FAR uLongf;
|
||||
|
||||
#ifdef STDC
|
||||
typedef void const *voidpc;
|
||||
typedef void FAR *voidpf;
|
||||
typedef void *voidp;
|
||||
#else
|
||||
typedef Byte const *voidpc;
|
||||
typedef Byte FAR *voidpf;
|
||||
typedef Byte *voidp;
|
||||
#endif
|
||||
|
||||
/* ./configure may #define Z_U4 here */
|
||||
|
||||
#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
|
||||
# include <limits.h>
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned long
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
# define Z_U4 unsigned short
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef Z_U4
|
||||
typedef Z_U4 z_crc_t;
|
||||
#else
|
||||
typedef unsigned long z_crc_t;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
|
||||
# define Z_HAVE_STDARG_H
|
||||
#endif
|
||||
|
||||
#ifdef STDC
|
||||
# ifndef Z_SOLO
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <stddef.h> /* for wchar_t */
|
||||
#endif
|
||||
|
||||
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
|
||||
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
|
||||
* though the former does not conform to the LFS document), but considering
|
||||
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
|
||||
* equivalently requesting no 64-bit operations
|
||||
*/
|
||||
#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
|
||||
# undef _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
|
||||
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
|
||||
# define Z_HAVE_UNISTD_H
|
||||
#endif
|
||||
#ifndef Z_SOLO
|
||||
# if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE)
|
||||
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# ifndef z_off_t
|
||||
# define z_off_t off_t
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
|
||||
# define Z_LFS64
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
|
||||
# define Z_LARGE64
|
||||
#endif
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
|
||||
# define Z_WANT64
|
||||
#endif
|
||||
|
||||
#if !defined(SEEK_SET) && !defined(Z_SOLO)
|
||||
# define SEEK_SET 0 /* Seek from beginning of file. */
|
||||
# define SEEK_CUR 1 /* Seek from current position. */
|
||||
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
|
||||
#endif
|
||||
|
||||
#ifndef z_off_t
|
||||
# define z_off_t long
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && defined(Z_LARGE64)
|
||||
# define z_off64_t off64_t
|
||||
#else
|
||||
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
|
||||
# define z_off64_t __int64
|
||||
# else
|
||||
# define z_off64_t z_off_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* MVS linker does not support external names larger than 8 bytes */
|
||||
#if defined(__MVS__)
|
||||
#pragma map(deflateInit_,"DEIN")
|
||||
#pragma map(deflateInit2_,"DEIN2")
|
||||
#pragma map(deflateEnd,"DEEND")
|
||||
#pragma map(deflateBound,"DEBND")
|
||||
#pragma map(inflateInit_,"ININ")
|
||||
#pragma map(inflateInit2_,"ININ2")
|
||||
#pragma map(inflateEnd,"INEND")
|
||||
#pragma map(inflateSync,"INSY")
|
||||
#pragma map(inflateSetDictionary,"INSEDI")
|
||||
#pragma map(compressBound,"CMBND")
|
||||
#pragma map(inflate_table,"INTABL")
|
||||
#pragma map(inflate_fast,"INFA")
|
||||
#pragma map(inflate_copyright,"INCOPY")
|
||||
#endif
|
||||
|
||||
#endif /* ZCONF_H */
|
1744
zlib/zlib.h
Normal file
1744
zlib/zlib.h
Normal file
File diff suppressed because it is too large
Load diff
324
zlib/zutil.c
Normal file
324
zlib/zutil.c
Normal file
|
@ -0,0 +1,324 @@
|
|||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
#ifndef Z_SOLO
|
||||
# include "gzguts.h"
|
||||
#endif
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
const char * const z_errmsg[10] = {
|
||||
"need dictionary", /* Z_NEED_DICT 2 */
|
||||
"stream end", /* Z_STREAM_END 1 */
|
||||
"", /* Z_OK 0 */
|
||||
"file error", /* Z_ERRNO (-1) */
|
||||
"stream error", /* Z_STREAM_ERROR (-2) */
|
||||
"data error", /* Z_DATA_ERROR (-3) */
|
||||
"insufficient memory", /* Z_MEM_ERROR (-4) */
|
||||
"buffer error", /* Z_BUF_ERROR (-5) */
|
||||
"incompatible version",/* Z_VERSION_ERROR (-6) */
|
||||
""};
|
||||
|
||||
|
||||
const char * ZEXPORT zlibVersion()
|
||||
{
|
||||
return ZLIB_VERSION;
|
||||
}
|
||||
|
||||
uLong ZEXPORT zlibCompileFlags()
|
||||
{
|
||||
uLong flags;
|
||||
|
||||
flags = 0;
|
||||
switch ((int)(sizeof(uInt))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1; break;
|
||||
case 8: flags += 2; break;
|
||||
default: flags += 3;
|
||||
}
|
||||
switch ((int)(sizeof(uLong))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 2; break;
|
||||
case 8: flags += 2 << 2; break;
|
||||
default: flags += 3 << 2;
|
||||
}
|
||||
switch ((int)(sizeof(voidpf))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 4; break;
|
||||
case 8: flags += 2 << 4; break;
|
||||
default: flags += 3 << 4;
|
||||
}
|
||||
switch ((int)(sizeof(z_off_t))) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 6; break;
|
||||
case 8: flags += 2 << 6; break;
|
||||
default: flags += 3 << 6;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
flags += 1 << 8;
|
||||
#endif
|
||||
#if defined(ASMV) || defined(ASMINF)
|
||||
flags += 1 << 9;
|
||||
#endif
|
||||
#ifdef ZLIB_WINAPI
|
||||
flags += 1 << 10;
|
||||
#endif
|
||||
#ifdef BUILDFIXED
|
||||
flags += 1 << 12;
|
||||
#endif
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
flags += 1 << 13;
|
||||
#endif
|
||||
#ifdef NO_GZCOMPRESS
|
||||
flags += 1L << 16;
|
||||
#endif
|
||||
#ifdef NO_GZIP
|
||||
flags += 1L << 17;
|
||||
#endif
|
||||
#ifdef PKZIP_BUG_WORKAROUND
|
||||
flags += 1L << 20;
|
||||
#endif
|
||||
#ifdef FASTEST
|
||||
flags += 1L << 21;
|
||||
#endif
|
||||
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1L << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1L << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1L << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
# ifndef verbose
|
||||
# define verbose 0
|
||||
# endif
|
||||
int ZLIB_INTERNAL z_verbose = verbose;
|
||||
|
||||
void ZLIB_INTERNAL z_error (m)
|
||||
char *m;
|
||||
{
|
||||
fprintf(stderr, "%s\n", m);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* exported to allow conversion of error code to string for compress() and
|
||||
* uncompress()
|
||||
*/
|
||||
const char * ZEXPORT zError(err)
|
||||
int err;
|
||||
{
|
||||
return ERR_MSG(err);
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
/* The Microsoft C Run-Time Library for Windows CE doesn't have
|
||||
* errno. We define it as a global variable to simplify porting.
|
||||
* Its value is always 0 and should not be used.
|
||||
*/
|
||||
int errno = 0;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
|
||||
void ZLIB_INTERNAL zmemcpy(dest, source, len)
|
||||
Bytef* dest;
|
||||
const Bytef* source;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = *source++; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
|
||||
int ZLIB_INTERNAL zmemcmp(s1, s2, len)
|
||||
const Bytef* s1;
|
||||
const Bytef* s2;
|
||||
uInt len;
|
||||
{
|
||||
uInt j;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zmemzero(dest, len)
|
||||
Bytef* dest;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = 0; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
|
||||
#ifdef SYS16BIT
|
||||
|
||||
#ifdef __TURBOC__
|
||||
/* Turbo C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
|
||||
* and farmalloc(64K) returns a pointer with an offset of 8, so we
|
||||
* must fix the pointer. Warning: the pointer must be put back to its
|
||||
* original form in order to free it, use zcfree().
|
||||
*/
|
||||
|
||||
#define MAX_PTR 10
|
||||
/* 10*64K = 640K */
|
||||
|
||||
local int next_ptr = 0;
|
||||
|
||||
typedef struct ptr_table_s {
|
||||
voidpf org_ptr;
|
||||
voidpf new_ptr;
|
||||
} ptr_table;
|
||||
|
||||
local ptr_table table[MAX_PTR];
|
||||
/* This table is used to remember the original form of pointers
|
||||
* to large buffers (64K). Such pointers are normalized with a zero offset.
|
||||
* Since MSDOS is not a preemptive multitasking OS, this table is not
|
||||
* protected from concurrent access. This hack doesn't work anyway on
|
||||
* a protected system like OS/2. Use Microsoft C instead.
|
||||
*/
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
voidpf buf = opaque; /* just to make some compilers happy */
|
||||
ulg bsize = (ulg)items*size;
|
||||
|
||||
/* If we allocate less than 65520 bytes, we assume that farmalloc
|
||||
* will return a usable pointer which doesn't have to be normalized.
|
||||
*/
|
||||
if (bsize < 65520L) {
|
||||
buf = farmalloc(bsize);
|
||||
if (*(ush*)&buf != 0) return buf;
|
||||
} else {
|
||||
buf = farmalloc(bsize + 16L);
|
||||
}
|
||||
if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
|
||||
table[next_ptr].org_ptr = buf;
|
||||
|
||||
/* Normalize the pointer to seg:0 */
|
||||
*((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
|
||||
*(ush*)&buf = 0;
|
||||
table[next_ptr++].new_ptr = buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
int n;
|
||||
if (*(ush*)&ptr != 0) { /* object < 64K */
|
||||
farfree(ptr);
|
||||
return;
|
||||
}
|
||||
/* Find the original pointer */
|
||||
for (n = 0; n < next_ptr; n++) {
|
||||
if (ptr != table[n].new_ptr) continue;
|
||||
|
||||
farfree(table[n].org_ptr);
|
||||
while (++n < next_ptr) {
|
||||
table[n-1] = table[n];
|
||||
}
|
||||
next_ptr--;
|
||||
return;
|
||||
}
|
||||
ptr = opaque; /* just to make some compilers happy */
|
||||
Assert(0, "zcfree: ptr not found");
|
||||
}
|
||||
|
||||
#endif /* __TURBOC__ */
|
||||
|
||||
|
||||
#ifdef M_I86
|
||||
/* Microsoft C in 16-bit mode */
|
||||
|
||||
# define MY_ZCALLOC
|
||||
|
||||
#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
|
||||
# define _halloc halloc
|
||||
# define _hfree hfree
|
||||
#endif
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
return _halloc((long)items, size);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
_hfree(ptr);
|
||||
}
|
||||
|
||||
#endif /* M_I86 */
|
||||
|
||||
#endif /* SYS16BIT */
|
||||
|
||||
|
||||
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
|
||||
|
||||
#ifndef STDC
|
||||
extern voidp malloc OF((uInt size));
|
||||
extern voidp calloc OF((uInt items, uInt size));
|
||||
extern void free OF((voidpf ptr));
|
||||
#endif
|
||||
|
||||
voidpf ZLIB_INTERNAL zcalloc (opaque, items, size)
|
||||
voidpf opaque;
|
||||
unsigned items;
|
||||
unsigned size;
|
||||
{
|
||||
if (opaque) items += size - size; /* make compiler happy */
|
||||
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
|
||||
(voidpf)calloc(items, size);
|
||||
}
|
||||
|
||||
void ZLIB_INTERNAL zcfree (opaque, ptr)
|
||||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
free(ptr);
|
||||
if (opaque) return; /* make compiler happy */
|
||||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
||||
|
||||
#endif /* !Z_SOLO */
|
252
zlib/zutil.h
Normal file
252
zlib/zutil.h
Normal file
|
@ -0,0 +1,252 @@
|
|||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2012 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#ifndef ZUTIL_H
|
||||
#define ZUTIL_H
|
||||
|
||||
#ifdef HAVE_HIDDEN
|
||||
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define ZLIB_INTERNAL
|
||||
#endif
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#if defined(STDC) && !defined(Z_SOLO)
|
||||
# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
|
||||
# include <stddef.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef Z_SOLO
|
||||
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
|
||||
#endif
|
||||
|
||||
#ifndef local
|
||||
# define local static
|
||||
#endif
|
||||
/* compile with -Dlocal if your debugger can't find static symbols */
|
||||
|
||||
typedef unsigned char uch;
|
||||
typedef uch FAR uchf;
|
||||
typedef unsigned short ush;
|
||||
typedef ush FAR ushf;
|
||||
typedef unsigned long ulg;
|
||||
|
||||
extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
|
||||
/* (size given to avoid silly warnings with Visual C++) */
|
||||
|
||||
#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
|
||||
|
||||
#define ERR_RETURN(strm,err) \
|
||||
return (strm->msg = (char*)ERR_MSG(err), (err))
|
||||
/* To be used only when the state is known to be valid */
|
||||
|
||||
/* common constants */
|
||||
|
||||
#ifndef DEF_WBITS
|
||||
# define DEF_WBITS MAX_WBITS
|
||||
#endif
|
||||
/* default windowBits for decompression. MAX_WBITS is for compression only */
|
||||
|
||||
#if MAX_MEM_LEVEL >= 8
|
||||
# define DEF_MEM_LEVEL 8
|
||||
#else
|
||||
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
|
||||
#endif
|
||||
/* default memLevel */
|
||||
|
||||
#define STORED_BLOCK 0
|
||||
#define STATIC_TREES 1
|
||||
#define DYN_TREES 2
|
||||
/* The three kinds of block type */
|
||||
|
||||
#define MIN_MATCH 3
|
||||
#define MAX_MATCH 258
|
||||
/* The minimum and maximum match lengths */
|
||||
|
||||
#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
|
||||
|
||||
/* target dependencies */
|
||||
|
||||
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
|
||||
# define OS_CODE 0x00
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__TURBOC__) || defined(__BORLANDC__)
|
||||
# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
|
||||
/* Allow compilation with ANSI keywords only enabled */
|
||||
void _Cdecl farfree( void *block );
|
||||
void *_Cdecl farmalloc( unsigned long nbytes );
|
||||
# else
|
||||
# include <alloc.h>
|
||||
# endif
|
||||
# else /* MSC or DJGPP */
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef AMIGA
|
||||
# define OS_CODE 0x01
|
||||
#endif
|
||||
|
||||
#if defined(VAXC) || defined(VMS)
|
||||
# define OS_CODE 0x02
|
||||
# define F_OPEN(name, mode) \
|
||||
fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
|
||||
#endif
|
||||
|
||||
#if defined(ATARI) || defined(atarist)
|
||||
# define OS_CODE 0x05
|
||||
#endif
|
||||
|
||||
#ifdef OS2
|
||||
# define OS_CODE 0x06
|
||||
# if defined(M_I86) && !defined(Z_SOLO)
|
||||
# include <malloc.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# ifndef Z_SOLO
|
||||
# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
|
||||
# include <unix.h> /* for fdopen */
|
||||
# else
|
||||
# ifndef fdopen
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef TOPS20
|
||||
# define OS_CODE 0x0a
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
|
||||
# define OS_CODE 0x0b
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __50SERIES /* Prime/PRIMOS */
|
||||
# define OS_CODE 0x0f
|
||||
#endif
|
||||
|
||||
#if defined(_BEOS_) || defined(RISCOS)
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
#endif
|
||||
|
||||
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
|
||||
# if defined(_WIN32_WCE)
|
||||
# define fdopen(fd,mode) NULL /* No fdopen() */
|
||||
# ifndef _PTRDIFF_T_DEFINED
|
||||
typedef int ptrdiff_t;
|
||||
# define _PTRDIFF_T_DEFINED
|
||||
# endif
|
||||
# else
|
||||
# define fdopen(fd,type) _fdopen(fd,type)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) && !defined(MSDOS)
|
||||
#pragma warn -8004
|
||||
#pragma warn -8008
|
||||
#pragma warn -8066
|
||||
#endif
|
||||
|
||||
/* provide prototypes for these when building zlib without LFS */
|
||||
#if !defined(_WIN32) && (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
|
||||
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
|
||||
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
|
||||
#endif
|
||||
|
||||
/* common defaults */
|
||||
|
||||
#ifndef OS_CODE
|
||||
# define OS_CODE 0x03 /* assume Unix */
|
||||
#endif
|
||||
|
||||
#ifndef F_OPEN
|
||||
# define F_OPEN(name, mode) fopen((name), (mode))
|
||||
#endif
|
||||
|
||||
/* functions */
|
||||
|
||||
#if defined(pyr) || defined(Z_SOLO)
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
|
||||
/* Use our own functions for small and medium model with MSC <= 5.0.
|
||||
* You may have to use the same strategy for Borland C (untested).
|
||||
* The __SC__ check is for Symantec.
|
||||
*/
|
||||
# define NO_MEMCPY
|
||||
#endif
|
||||
#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
|
||||
# define HAVE_MEMCPY
|
||||
#endif
|
||||
#ifdef HAVE_MEMCPY
|
||||
# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
|
||||
# define zmemcpy _fmemcpy
|
||||
# define zmemcmp _fmemcmp
|
||||
# define zmemzero(dest, len) _fmemset(dest, 0, len)
|
||||
# else
|
||||
# define zmemcpy memcpy
|
||||
# define zmemcmp memcmp
|
||||
# define zmemzero(dest, len) memset(dest, 0, len)
|
||||
# endif
|
||||
#else
|
||||
void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
|
||||
int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
|
||||
void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
|
||||
#endif
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
extern int ZLIB_INTERNAL z_verbose;
|
||||
extern void ZLIB_INTERNAL z_error OF((char *m));
|
||||
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
|
||||
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
|
||||
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
|
||||
# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
|
||||
# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
|
||||
# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
|
||||
#else
|
||||
# define Assert(cond,msg)
|
||||
# define Trace(x)
|
||||
# define Tracev(x)
|
||||
# define Tracevv(x)
|
||||
# define Tracec(c,x)
|
||||
# define Tracecv(c,x)
|
||||
#endif
|
||||
|
||||
#ifndef Z_SOLO
|
||||
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
|
||||
unsigned size));
|
||||
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
|
||||
#endif
|
||||
|
||||
#define ZALLOC(strm, items, size) \
|
||||
(*((strm)->zalloc))((strm)->opaque, (items), (size))
|
||||
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
|
||||
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
|
||||
|
||||
/* Reverse the bytes in a 32-bit value */
|
||||
#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
|
||||
(((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
|
||||
|
||||
#endif /* ZUTIL_H */
|
Loading…
Reference in a new issue