mirror of
https://github.com/ZDoom/zdbsp.git
synced 2024-11-21 11:21:19 +00:00
Initial commit of zdbsp.
SVN r12 (trunk)
This commit is contained in:
parent
fbbfdcf196
commit
24d4f0b45c
57 changed files with 21226 additions and 0 deletions
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.
|
1146
Unused/nodebuild.cpp-nogl
Normal file
1146
Unused/nodebuild.cpp-nogl
Normal file
File diff suppressed because it is too large
Load diff
98
Unused/nodebuild.h-nogl
Normal file
98
Unused/nodebuild.h-nogl
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include "doomdata.h"
|
||||
#include "workdata.h"
|
||||
#include "tarray.h"
|
||||
|
||||
class FNodeBuilder
|
||||
{
|
||||
struct FPrivSeg
|
||||
{
|
||||
int v1, v2;
|
||||
int sidedef;
|
||||
int linedef;
|
||||
int frontsector;
|
||||
int backsector;
|
||||
int next;
|
||||
int nextforvert;
|
||||
int loopnum; // loop number for split avoidance (0 means splitting is okay)
|
||||
angle_t angle;
|
||||
fixed_t offset;
|
||||
|
||||
int planenum;
|
||||
FPrivSeg *hashnext;
|
||||
};
|
||||
struct FPrivVert
|
||||
{
|
||||
fixed_t x, y;
|
||||
WORD segs; // segs that use this vertex as v1
|
||||
|
||||
bool operator== (const FPrivVert &other)
|
||||
{
|
||||
return x == other.x && y == other.y;
|
||||
}
|
||||
};
|
||||
union USegPtr
|
||||
{
|
||||
int SegNum;
|
||||
FPrivSeg *SegPtr;
|
||||
};
|
||||
public:
|
||||
struct FPolyStart
|
||||
{
|
||||
int polynum;
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
FNodeBuilder (FLevel &level,
|
||||
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
||||
const char *name);
|
||||
|
||||
void GetVertices (WideVertex *&verts, int &count);
|
||||
void GetSegs (MapSeg *&segs, int &count);
|
||||
void GetNodes (MapNode *&nodes, int &count);
|
||||
void GetSubsectors (MapSubsector *&ssecs, int &count);
|
||||
|
||||
private:
|
||||
TArray<node_t> Nodes;
|
||||
TArray<MapSubsector> Subsectors;
|
||||
TArray<FPrivSeg> Segs;
|
||||
TArray<FPrivVert> Vertices;
|
||||
TArray<USegPtr> SegList;
|
||||
TArray<BYTE> PlaneChecked;
|
||||
|
||||
TArray<int> Touched; // Loops a splitter touches on a vertex
|
||||
TArray<int> Colinear; // Loops with edges colinear to a splitter
|
||||
|
||||
FLevel &Level;
|
||||
|
||||
// Progress meter stuff
|
||||
int SegsStuffed;
|
||||
const char *MapName;
|
||||
|
||||
void FindUsedVertices (WideVertex *vertices, int max);
|
||||
void BuildTree ();
|
||||
void MakeSegsFromSides ();
|
||||
void GroupSegPlanes ();
|
||||
void FindPolyContainers (TArray<FPolyStart> &spots, TArray<FPolyStart> &anchors);
|
||||
bool GetPolyExtents (int polynum, fixed_t bbox[4]);
|
||||
int MarkLoop (int firstseg, int loopnum);
|
||||
void AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg);
|
||||
int CreateNode (WORD set, fixed_t bbox[4]);
|
||||
int CreateSubsector (WORD set, fixed_t bbox[4]);
|
||||
bool CheckSubsector (WORD set, node_t &node, int setsize);
|
||||
int SelectSplitter (WORD set, node_t &node, int step, bool nosplit);
|
||||
void SplitSegs (WORD set, node_t &node, WORD &outset0, WORD &outset1);
|
||||
int Heuristic (node_t &node, WORD set, bool honorNoSplit);
|
||||
int ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2);
|
||||
int CountSegs (WORD set) const;
|
||||
|
||||
static int SortSegs (const void *a, const void *b);
|
||||
|
||||
// < 0 : in front of line
|
||||
// == 0 : on line
|
||||
// > 0 : behind line
|
||||
|
||||
inline int PointOnSide (int x, int y, int x1, int y1, int dx, int dy);
|
||||
fixed_t InterceptVector (const node_t &splitter, const FPrivSeg &seg);
|
||||
|
||||
void PrintSet (int l, WORD set);
|
||||
};
|
215
Unused/rejectbuilder.cpp
Normal file
215
Unused/rejectbuilder.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
// The old code used the same algorithm as DoomBSP:
|
||||
//
|
||||
// Represent each sector by its bounding box. Then for each pair of
|
||||
// sectors, see if any chains of one-sided lines can walk from one
|
||||
// side of the convex hull for that pair to the other side.
|
||||
//
|
||||
// It works, but it's far from being perfect. It's quite easy for
|
||||
// this algorithm to consider two sectors as being visible from
|
||||
// each other when they are really not. But it won't erroneously
|
||||
// flag two sectors as obstructed when they're really not, and that's
|
||||
// the only thing that really matters when building a REJECT lump.
|
||||
//
|
||||
// Because that was next to useless, I scrapped that code and adapted
|
||||
// Quake's vis utility to work in a 2D world. Since this is basically vis,
|
||||
// it depends on GL nodes being present to function. As the usefulness
|
||||
// of a REJECT lump is debatable, I have chosen to not compile this module
|
||||
// in with ZDBSP. Save yourself some space and run ZDBSP with the -r option.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include "rejectbuilder.h"
|
||||
#include "templates.h"
|
||||
|
||||
bool MergeVis=1;
|
||||
|
||||
FRejectBuilder::FRejectBuilder (FLevel &level)
|
||||
: Level (level), testlevel (2), totalvis (0)
|
||||
{
|
||||
LoadPortals ();
|
||||
|
||||
if (MergeVis)
|
||||
{
|
||||
MergeLeaves ();
|
||||
MergeLeafPortals ();
|
||||
}
|
||||
|
||||
CountActivePortals ();
|
||||
CalcVis ();
|
||||
|
||||
BuildReject ();
|
||||
}
|
||||
|
||||
FRejectBuilder::~FRejectBuilder ()
|
||||
{
|
||||
}
|
||||
|
||||
BYTE *FRejectBuilder::GetReject ()
|
||||
{
|
||||
WORD *sectormap;
|
||||
int i, j;
|
||||
|
||||
int rejectSize = (Level.NumSectors*Level.NumSectors + 7) / 8;
|
||||
BYTE *reject = new BYTE[rejectSize];
|
||||
memset (reject, 0xff, rejectSize);
|
||||
|
||||
int pvs_size = (Level.NumGLSubsectors * Level.NumGLSubsectors) + 7 / 8;
|
||||
Level.GLPVS = new BYTE[pvs_size];
|
||||
Level.GLPVSSize = pvs_size;
|
||||
memset (Level.GLPVS, 0, pvs_size);
|
||||
|
||||
sectormap = new WORD[Level.NumGLSubsectors];
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i)
|
||||
{
|
||||
const MapSegGLEx *seg = &Level.GLSegs[Level.GLSubsectors[i].firstline];
|
||||
sectormap[i] = Level.Sides[Level.Lines[seg->linedef].sidenum[seg->side]].sector;
|
||||
}
|
||||
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i)
|
||||
{
|
||||
int rowpvs = i*Level.NumGLSubsectors;
|
||||
int rowrej = sectormap[i]*Level.NumSectors;
|
||||
BYTE *bytes = visBytes + i*leafbytes;
|
||||
for (j = 0; j < Level.NumGLSubsectors; ++j)
|
||||
{
|
||||
if (bytes[j>>3] & (1<<(j&7)))
|
||||
{
|
||||
int mark = rowpvs + j;
|
||||
Level.GLPVS[mark>>3] |= 1<<(mark&7);
|
||||
|
||||
mark = rowrej + sectormap[j];
|
||||
reject[mark>>3] &= ~(1<<(mark&7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reject;
|
||||
}
|
||||
|
||||
void FRejectBuilder::BuildReject ()
|
||||
{
|
||||
}
|
||||
|
||||
inline const WideVertex *FRejectBuilder::GetVertex (WORD vertnum)
|
||||
{
|
||||
return &Level.Vertices[vertnum];
|
||||
}
|
||||
|
||||
FRejectBuilder::FLeaf::FLeaf ()
|
||||
: numportals (0), merged (-1), portals (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
FRejectBuilder::FLeaf::~FLeaf ()
|
||||
{
|
||||
if (portals != NULL)
|
||||
{
|
||||
delete[] portals;
|
||||
}
|
||||
}
|
||||
|
||||
int FRejectBuilder::PointOnSide (const FPoint &point, const FLine &line)
|
||||
{
|
||||
return FNodeBuilder::PointOnSide (point.x, point.y, line.x, line.y, line.dx, line.dy);
|
||||
}
|
||||
|
||||
void FRejectBuilder::LoadPortals ()
|
||||
{
|
||||
WORD *segleaf;
|
||||
int i, j, k, max;
|
||||
VPortal *p;
|
||||
FLeaf *l;
|
||||
FWinding *w;
|
||||
|
||||
portalclusters = Level.NumGLSubsectors;
|
||||
|
||||
for (numportals = 0, i = 0; i < Level.NumGLSegs; ++i)
|
||||
{
|
||||
if (Level.GLSegs[i].partner != DWORD_MAX)
|
||||
{
|
||||
++numportals;
|
||||
}
|
||||
}
|
||||
|
||||
// these counts should take advantage of 64 bit systems automatically
|
||||
leafbytes = ((portalclusters+63)&~63)>>3;
|
||||
leaflongs = leafbytes/sizeof(long);
|
||||
|
||||
portalbytes = ((numportals+63)&~63)>>3;
|
||||
portallongs = portalbytes/sizeof(long);
|
||||
|
||||
portals = new VPortal[numportals];
|
||||
memset (portals, 0, numportals*sizeof(VPortal));
|
||||
|
||||
leafs = new FLeaf[portalclusters];
|
||||
|
||||
numVisBytes = portalclusters*leafbytes;
|
||||
visBytes = new BYTE[numVisBytes];
|
||||
|
||||
segleaf = new WORD[Level.NumGLSegs];
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i)
|
||||
{
|
||||
j = Level.GLSubsectors[i].firstline;
|
||||
max = j + Level.GLSubsectors[i].numlines;
|
||||
|
||||
for (; j < max; ++j)
|
||||
{
|
||||
segleaf[j] = i;
|
||||
}
|
||||
}
|
||||
|
||||
p = portals;
|
||||
l = leafs;
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i, ++l)
|
||||
{
|
||||
j = Level.GLSubsectors[i].firstline;
|
||||
max = j + Level.GLSubsectors[i].numlines;
|
||||
|
||||
// Count portals in this leaf
|
||||
for (; j < max; ++j)
|
||||
{
|
||||
if (Level.GLSegs[j].partner != DWORD_MAX)
|
||||
{
|
||||
++l->numportals;
|
||||
}
|
||||
}
|
||||
|
||||
if (l->numportals == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
l->portals = new VPortal *[l->numportals];
|
||||
|
||||
for (k = 0, j = Level.GLSubsectors[i].firstline; j < max; ++j)
|
||||
{
|
||||
const MapSegGLEx *seg = &Level.GLSegs[j];
|
||||
|
||||
if (seg->partner == DWORD_MAX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// create portal from seg
|
||||
l->portals[k++] = p;
|
||||
|
||||
w = &p->winding;
|
||||
w->points[0] = GetVertex (seg->v1);
|
||||
w->points[1] = GetVertex (seg->v2);
|
||||
|
||||
p->hint = seg->linedef != NO_INDEX;
|
||||
p->line.x = w->points[1].x;
|
||||
p->line.y = w->points[1].y;
|
||||
p->line.dx = w->points[0].x - p->line.x;
|
||||
p->line.dy = w->points[0].y - p->line.y;
|
||||
p->leaf = segleaf[seg->partner];
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] segleaf;
|
||||
}
|
330
Unused/rejectbuilder.cpp-nogl
Normal file
330
Unused/rejectbuilder.cpp-nogl
Normal file
|
@ -0,0 +1,330 @@
|
|||
// This is the same algorithm used by DoomBSP:
|
||||
//
|
||||
// Represent each sector by its bounding box. Then for each pair of
|
||||
// sectors, see if any chains of one-sided lines can walk from one
|
||||
// side of the convex hull for that pair to the other side.
|
||||
//
|
||||
// It works, but it's far from being perfect. It's quite easy for
|
||||
// this algorithm to consider two sectors as being visible from
|
||||
// each other when they are really not. But it won't erroneously
|
||||
// flag two sectors as obstructed when they're really not, and that's
|
||||
// the only thing that really matters when building a REJECT lump.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "rejectbuilder.h"
|
||||
#include "templates.h"
|
||||
|
||||
FRejectBuilder::FRejectBuilder (FLevel &level)
|
||||
: Level (level), BlockChains (NULL)
|
||||
{
|
||||
RejectSize = (Level.NumSectors*Level.NumSectors + 7) / 8;
|
||||
Reject = new BYTE[RejectSize];
|
||||
memset (Reject, 0, RejectSize);
|
||||
|
||||
FindSectorBounds ();
|
||||
FindBlockChains ();
|
||||
BuildReject ();
|
||||
}
|
||||
|
||||
FRejectBuilder::~FRejectBuilder ()
|
||||
{
|
||||
FBlockChain *chain, *next;
|
||||
|
||||
chain = BlockChains;
|
||||
while (chain != NULL)
|
||||
{
|
||||
next = chain->Next;
|
||||
delete chain;
|
||||
chain = next;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE *FRejectBuilder::GetReject ()
|
||||
{
|
||||
return Reject;
|
||||
}
|
||||
|
||||
void FRejectBuilder::FindSectorBounds ()
|
||||
{
|
||||
int i;
|
||||
|
||||
SectorBounds = new BBox[Level.NumSectors];
|
||||
|
||||
for (i = 0; i < Level.NumSectors; ++i)
|
||||
{
|
||||
SectorBounds[i].Bounds[LEFT] = SectorBounds[i].Bounds[BOTTOM] = INT_MAX;
|
||||
SectorBounds[i].Bounds[RIGHT] = SectorBounds[i].Bounds[TOP] = INT_MIN;
|
||||
}
|
||||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||
{
|
||||
int secnum = Level.Sides[Level.Lines[i].sidenum[0]].sector;
|
||||
SectorBounds[secnum].AddPt (Level.Vertices[Level.Lines[i].v1]);
|
||||
SectorBounds[secnum].AddPt (Level.Vertices[Level.Lines[i].v2]);
|
||||
}
|
||||
if (Level.Lines[i].sidenum[1] != NO_INDEX)
|
||||
{
|
||||
int secnum = Level.Sides[Level.Lines[i].sidenum[1]].sector;
|
||||
SectorBounds[secnum].AddPt (Level.Vertices[Level.Lines[i].v1]);
|
||||
SectorBounds[secnum].AddPt (Level.Vertices[Level.Lines[i].v2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FRejectBuilder::FindBlockChains ()
|
||||
{
|
||||
bool *marked = new bool[Level.NumLines];
|
||||
WORD *nextForVert = new WORD[Level.NumLines];
|
||||
WORD *firstLine = new WORD[Level.NumVertices];
|
||||
int i, j, k;
|
||||
FBlockChain *chain;
|
||||
FPoint pt;
|
||||
TArray<FPoint> pts;
|
||||
|
||||
memset (nextForVert, 0xff, Level.NumLines*sizeof(*nextForVert));
|
||||
memset (firstLine, 0xff, Level.NumVertices*sizeof(*firstLine));
|
||||
memset (marked, 0, Level.NumLines*sizeof(*marked));
|
||||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
if (Level.Lines[i].sidenum[0] == NO_INDEX || Level.Lines[i].sidenum[1] != NO_INDEX)
|
||||
{
|
||||
marked[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextForVert[Level.Lines[i].v1] = firstLine[Level.Lines[i].v1];
|
||||
firstLine[Level.Lines[i].v1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
if (marked[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pt.x = Level.Vertices[Level.Lines[i].v1].x >> FRACBITS;
|
||||
pt.y = Level.Vertices[Level.Lines[i].v1].y >> FRACBITS;
|
||||
pts.Clear ();
|
||||
pts.Push (pt);
|
||||
chain = new FBlockChain;
|
||||
chain->Bounds(LEFT) = chain->Bounds(RIGHT) = pt.x;
|
||||
chain->Bounds(TOP) = chain->Bounds(BOTTOM) = pt.y;
|
||||
|
||||
for (j = i; j != NO_INDEX; )
|
||||
{
|
||||
marked[j] = true;
|
||||
pt.x = Level.Vertices[Level.Lines[j].v2].x >> FRACBITS;
|
||||
pt.y = Level.Vertices[Level.Lines[j].v2].y >> FRACBITS;
|
||||
pts.Push (pt);
|
||||
chain->Bounds.AddPt (pt);
|
||||
|
||||
k = firstLine[Level.Lines[j].v2];
|
||||
if (k == NO_INDEX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (nextForVert[k] == NO_INDEX)
|
||||
{
|
||||
j = marked[k] ? NO_INDEX : k;
|
||||
}
|
||||
else
|
||||
{
|
||||
int best = NO_INDEX;
|
||||
angle_t bestang = ANGLE_MAX;
|
||||
angle_t ang1 = PointToAngle (Level.Vertices[Level.Lines[j].v2].x - Level.Vertices[Level.Lines[j].v1].x,
|
||||
Level.Vertices[Level.Lines[j].v2].y - Level.Vertices[Level.Lines[j].v1].y) + (1 << 31);
|
||||
|
||||
while (k != NO_INDEX)
|
||||
{
|
||||
if (!marked[k])
|
||||
{
|
||||
angle_t ang2 = PointToAngle (Level.Vertices[Level.Lines[k].v2].x - Level.Vertices[Level.Lines[k].v1].x,
|
||||
Level.Vertices[Level.Lines[k].v2].y - Level.Vertices[Level.Lines[k].v1].y) + (1 << 31);
|
||||
angle_t angdiff = ang2 - ang1;
|
||||
|
||||
if (angdiff < bestang && angdiff > 0)
|
||||
{
|
||||
bestang = angdiff;
|
||||
best = k;
|
||||
}
|
||||
}
|
||||
k = nextForVert[k];
|
||||
}
|
||||
|
||||
j = best;
|
||||
}
|
||||
}
|
||||
|
||||
chain->NumPoints = pts.Size();
|
||||
chain->Points = new FPoint[chain->NumPoints];
|
||||
memcpy (chain->Points, &pts[0], chain->NumPoints*sizeof(*chain->Points));
|
||||
chain->Next = BlockChains;
|
||||
BlockChains = chain;
|
||||
}
|
||||
}
|
||||
|
||||
void FRejectBuilder::HullSides (const BBox &box1, const BBox &box2, FPoint sides[4])
|
||||
{
|
||||
static const int vertSides[4][2] = {
|
||||
{ LEFT, BOTTOM },
|
||||
{ LEFT, TOP },
|
||||
{ RIGHT, TOP },
|
||||
{ RIGHT, BOTTOM }
|
||||
};
|
||||
static const int stuffSpots[4] = { 0, 3, 2, 1 };
|
||||
|
||||
const int *boxp1, *boxp2;
|
||||
|
||||
boxp1 = box2.Bounds;
|
||||
boxp2 = box1.Bounds;
|
||||
|
||||
for (int mainBox = 2; mainBox != 0; )
|
||||
{
|
||||
const int *stuffs = stuffSpots + (--mainBox)*2;
|
||||
int outerEdges[4];
|
||||
|
||||
outerEdges[LEFT] = boxp1[LEFT] <= boxp2[LEFT];
|
||||
outerEdges[TOP] = boxp1[TOP] >= boxp2[TOP];
|
||||
outerEdges[RIGHT] = boxp1[RIGHT] >= boxp2[RIGHT];
|
||||
outerEdges[BOTTOM] = boxp1[BOTTOM] <= boxp2[BOTTOM];
|
||||
|
||||
for (int vertex = 0; vertex < 4; ++vertex)
|
||||
{
|
||||
if (outerEdges[(vertex-1)&3] != outerEdges[vertex])
|
||||
{
|
||||
FPoint *pt = &sides[stuffs[outerEdges[vertex]]];
|
||||
pt->x = boxp1[vertSides[vertex][0]];
|
||||
pt->y = boxp1[vertSides[vertex][1]];
|
||||
}
|
||||
}
|
||||
|
||||
boxp1 = box1.Bounds;
|
||||
boxp2 = box2.Bounds;
|
||||
}
|
||||
}
|
||||
|
||||
int FRejectBuilder::PointOnSide (const FPoint *pt, const FPoint &lpt1, const FPoint &lpt2)
|
||||
{
|
||||
return (pt->y - lpt1.y) * (lpt2.x - lpt1.x) >= (pt->x - lpt1.x) * (lpt2.y - lpt1.y);
|
||||
}
|
||||
|
||||
bool FRejectBuilder::ChainBlocks (const FBlockChain *chain,
|
||||
const BBox *hullBounds, const FPoint *hullPts)
|
||||
{
|
||||
int startSide, side, i;
|
||||
|
||||
if (chain->Bounds[LEFT] > hullBounds->Bounds[RIGHT] ||
|
||||
chain->Bounds[RIGHT] < hullBounds->Bounds[LEFT] ||
|
||||
chain->Bounds[TOP] < hullBounds->Bounds[BOTTOM] ||
|
||||
chain->Bounds[BOTTOM] > hullBounds->Bounds[TOP])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
startSide = -1;
|
||||
|
||||
for (i = 0; i < chain->NumPoints; ++i)
|
||||
{
|
||||
const FPoint *pt = &chain->Points[i];
|
||||
|
||||
if (PointOnSide (pt, hullPts[1], hullPts[2]))
|
||||
{
|
||||
startSide = -1;
|
||||
continue;
|
||||
}
|
||||
if (PointOnSide (pt, hullPts[3], hullPts[0]))
|
||||
{
|
||||
startSide = -1;
|
||||
continue;
|
||||
}
|
||||
if (PointOnSide (pt, hullPts[0], hullPts[1]))
|
||||
{
|
||||
side = 0;
|
||||
}
|
||||
else if (PointOnSide (pt, hullPts[2], hullPts[3]))
|
||||
{
|
||||
side = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (startSide == -1 || startSide == side)
|
||||
{
|
||||
startSide = side;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FRejectBuilder::BuildReject ()
|
||||
{
|
||||
int s1, s2;
|
||||
|
||||
for (s1 = 0; s1 < Level.NumSectors-1; ++s1)
|
||||
{
|
||||
printf (" Reject: %3d%%\r", s1*100/Level.NumSectors);
|
||||
for (s2 = s1 + 1; s2 < Level.NumSectors; ++s2)
|
||||
{
|
||||
BBox HullBounds;
|
||||
FPoint HullPts[4];
|
||||
const BBox *sb1, *sb2;
|
||||
|
||||
sb1 = &SectorBounds[s1];
|
||||
sb2 = &SectorBounds[s2];
|
||||
|
||||
int pos = s1*Level.NumSectors + s2;
|
||||
if (Reject[pos>>3] & (1<<(pos&7)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Overlapping and touching sectors are considered to always
|
||||
// see each other.
|
||||
if (sb1->Bounds[LEFT] <= sb2->Bounds[RIGHT] &&
|
||||
sb1->Bounds[RIGHT] >= sb2->Bounds[LEFT] &&
|
||||
sb1->Bounds[TOP] >= sb2->Bounds[BOTTOM] &&
|
||||
sb1->Bounds[BOTTOM] <= sb2->Bounds[TOP])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
HullBounds(LEFT) = MIN (sb1->Bounds[LEFT], sb2->Bounds[LEFT]);
|
||||
HullBounds(RIGHT) = MAX (sb1->Bounds[RIGHT], sb2->Bounds[RIGHT]);
|
||||
HullBounds(BOTTOM) = MIN (sb1->Bounds[BOTTOM], sb2->Bounds[BOTTOM]);
|
||||
HullBounds(TOP) = MAX (sb1->Bounds[TOP], sb2->Bounds[TOP]);
|
||||
|
||||
HullSides (*sb1, *sb2, HullPts);
|
||||
|
||||
for (FBlockChain *chain = BlockChains; chain != NULL; chain = chain->Next)
|
||||
{
|
||||
if (ChainBlocks (chain, &HullBounds, HullPts))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (chain == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Reject[pos>>3] |= 1 << (pos & 7);
|
||||
pos = s2*Level.NumSectors + s1;
|
||||
Reject[pos>>3] |= 1 << (pos & 7);
|
||||
}
|
||||
}
|
||||
printf (" Reject: 100%%\n");
|
||||
}
|
278
Unused/rejectbuilder.cpp-slow
Normal file
278
Unused/rejectbuilder.cpp-slow
Normal file
|
@ -0,0 +1,278 @@
|
|||
// This is the same algorithm used by DoomBSP:
|
||||
//
|
||||
// Represent each sector by its bounding box. Then for each pair of
|
||||
// sectors, see if any chains of one-sided lines can walk from one
|
||||
// side of the convex hull for that pair to the other side.
|
||||
//
|
||||
// It works, but it's far from being perfect. It's quite easy for
|
||||
// this algorithm to consider two sectors as being visible from
|
||||
// each other when they are really not. But it won't erroneously
|
||||
// flag two sectors as obstructed when they're really not, and that's
|
||||
// the only thing that really matters when building a REJECT lump.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include "rejectbuilder.h"
|
||||
#include "templates.h"
|
||||
|
||||
FRejectBuilder::FRejectBuilder (FLevel &level)
|
||||
: Level (level)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = Level.NumGLSubsectors * Level.NumGLSubsectors;
|
||||
SubSeeMatrix = new BYTE[i];
|
||||
memset (SubSeeMatrix, 0, i);
|
||||
|
||||
SegSubsectors = new WORD[Level.NumGLSegs];
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i)
|
||||
{
|
||||
for (int j = 0; j < Level.GLSubsectors[i].numlines; ++j)
|
||||
{
|
||||
SegSubsectors[j + Level.GLSubsectors[i].firstline] = i;
|
||||
}
|
||||
}
|
||||
|
||||
BuildReject ();
|
||||
}
|
||||
|
||||
FRejectBuilder::~FRejectBuilder ()
|
||||
{
|
||||
delete[] SubSeeMatrix;
|
||||
delete[] SegSubsectors;
|
||||
}
|
||||
|
||||
BYTE *FRejectBuilder::GetReject ()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
int rejectSize = (Level.NumSectors*Level.NumSectors + 7) / 8;
|
||||
BYTE *reject = new BYTE[rejectSize];
|
||||
memset (reject, 0xff, rejectSize);
|
||||
|
||||
int pvs_size = (Level.NumGLSubsectors * Level.NumGLSubsectors) + 7 / 8;
|
||||
Level.GLPVS = new BYTE[pvs_size];
|
||||
Level.GLPVSSize = pvs_size;
|
||||
memset (Level.GLPVS, 0, pvs_size);
|
||||
|
||||
for (i = 0; i < Level.NumGLSubsectors; ++i)
|
||||
{
|
||||
int row = i*Level.NumGLSubsectors;
|
||||
int sector1 =
|
||||
Level.Sides[
|
||||
Level.Lines[
|
||||
Level.GLSegs[
|
||||
Level.GLSubsectors[i].firstline].linedef]
|
||||
.sidenum[
|
||||
Level.GLSegs[
|
||||
Level.GLSubsectors[i].firstline].side]]
|
||||
.sector;
|
||||
int srow = sector1*Level.NumSectors;
|
||||
for (j = 0; j < Level.NumGLSubsectors; ++j)
|
||||
{
|
||||
if (SubSeeMatrix[row + j])
|
||||
{
|
||||
int sector2 =
|
||||
Level.Sides[
|
||||
Level.Lines[
|
||||
Level.GLSegs[
|
||||
Level.GLSubsectors[j].firstline].linedef]
|
||||
.sidenum[
|
||||
Level.GLSegs[
|
||||
Level.GLSubsectors[j].firstline].side]]
|
||||
.sector;
|
||||
int l = (srow + sector2) >> 3;
|
||||
int r = (srow + sector2) & 7;
|
||||
reject[l] &= ~(1 << r);
|
||||
|
||||
l = (row + j) >> 3;
|
||||
r = (row + j) & 7;
|
||||
Level.GLPVS[l] |= 1 << r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reject;
|
||||
}
|
||||
|
||||
void FRejectBuilder::BuildReject ()
|
||||
{
|
||||
int s1, s2;
|
||||
|
||||
for (s1 = 0; s1 < Level.NumGLSubsectors; ++s1)
|
||||
{
|
||||
//printf (" Reject: %3d%%\r",s1*100/Level.NumGLSubsectors);
|
||||
printf ("%d/%d\r", s1, Level.NumGLSubsectors);
|
||||
|
||||
// A subsector can always see itself
|
||||
SourceRow = s1 * Level.NumGLSubsectors;
|
||||
SubSeeMatrix[SourceRow + s1] = 1;
|
||||
|
||||
WORD pusher = s1;
|
||||
|
||||
for (s2 = 0; s2 < Level.GLSubsectors[s1].numlines; ++s2)
|
||||
{
|
||||
int segnum = s2 + Level.GLSubsectors[s1].firstline;
|
||||
const MapSegGL *seg = &Level.GLSegs[segnum];
|
||||
if (seg->partner == NO_INDEX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
SourceSeg = segnum;
|
||||
SegRow = segnum * Level.NumGLSegs;
|
||||
|
||||
TracePath (s1, seg);
|
||||
}
|
||||
}
|
||||
printf (" Reject: 100%%\n");
|
||||
}
|
||||
|
||||
inline const WideVertex *FRejectBuilder::GetVertex (WORD vertnum)
|
||||
{
|
||||
if (vertnum & 0x8000)
|
||||
{
|
||||
return &Level.GLVertices[vertnum & 0x7fff];
|
||||
}
|
||||
else
|
||||
{
|
||||
return &Level.Vertices[vertnum];
|
||||
}
|
||||
}
|
||||
|
||||
void FRejectBuilder::TracePath (int subsector, const MapSegGL *window)
|
||||
{
|
||||
// Neighboring subsectors can always see each other
|
||||
SubSeeMatrix[SourceRow + SegSubsectors[window->partner]] = 1;
|
||||
const MapSubsector *backsub = &Level.GLSubsectors[SegSubsectors[window->partner]];
|
||||
|
||||
Portal source;
|
||||
|
||||
source.Subsector = backsub;
|
||||
source.Left = GetVertex (window->v1);
|
||||
source.Right = GetVertex (window->v2);
|
||||
|
||||
PortalStack.Clear ();
|
||||
PortalStack.Push (source);
|
||||
|
||||
fixed_t wdx = source.Right->x - source.Left->x;
|
||||
fixed_t wdy = source.Right->y - source.Left->y;
|
||||
|
||||
// printf ("start window %d\n", window - Level.GLSegs);
|
||||
|
||||
for (int i = 0; i < backsub->numlines; ++i)
|
||||
{
|
||||
int segnum = backsub->firstline + i;
|
||||
|
||||
if (segnum == window->partner)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const MapSegGL *cseg = &Level.GLSegs[segnum];
|
||||
|
||||
if (cseg->partner == NO_INDEX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const WideVertex *cv1 = GetVertex (cseg->v1);
|
||||
const WideVertex *cv2 = GetVertex (cseg->v2);
|
||||
|
||||
if (FNodeBuilder::PointOnSide (cv1->x, cv1->y, source.Left->x, source.Left->y, wdx, wdy) == 0 &&
|
||||
FNodeBuilder::PointOnSide (cv2->x, cv2->y, source.Left->x, source.Left->y, wdx, wdy) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
TracePathDeep (cseg);
|
||||
}
|
||||
}
|
||||
|
||||
void FRejectBuilder::TracePathDeep (const MapSegGL *window)
|
||||
{
|
||||
SubSeeMatrix[SourceRow + SegSubsectors[window->partner]] = 1;
|
||||
const MapSubsector *backsub = &Level.GLSubsectors[SegSubsectors[window->partner]];
|
||||
size_t j;
|
||||
|
||||
for (j = PortalStack.Size(); j-- > 0; )
|
||||
{
|
||||
if (PortalStack[j].Subsector == backsub)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Portal entrance;
|
||||
|
||||
entrance.Subsector = backsub;
|
||||
entrance.Left = GetVertex (window->v1);
|
||||
entrance.Right = GetVertex (window->v2);
|
||||
PortalStack.Push (entrance);
|
||||
|
||||
fixed_t wdx = entrance.Right->x - entrance.Left->x;
|
||||
fixed_t wdy = entrance.Right->y - entrance.Left->y;
|
||||
|
||||
//printf ("deep through %d\n", window - Level.GLSegs);
|
||||
|
||||
for (int i = 0; i < backsub->numlines; ++i)
|
||||
{
|
||||
int segnum = backsub->firstline + i;
|
||||
|
||||
if (segnum == window->partner)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const MapSegGL *cseg = &Level.GLSegs[segnum];
|
||||
|
||||
if (cseg->partner == NO_INDEX)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const WideVertex *cv1 = GetVertex (cseg->v1);
|
||||
const WideVertex *cv2 = GetVertex (cseg->v2);
|
||||
|
||||
if (FNodeBuilder::PointOnSide (cv1->x, cv1->y, entrance.Left->x, entrance.Left->y, wdx, wdy) <= 0 &&
|
||||
FNodeBuilder::PointOnSide (cv2->x, cv2->y, entrance.Left->x, entrance.Left->y, wdx, wdy) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fixed_t leftx = PortalStack[0].Left->x;
|
||||
fixed_t lefty = PortalStack[0].Left->y;
|
||||
fixed_t rightx = PortalStack[0].Right->x;
|
||||
fixed_t righty = PortalStack[0].Right->y;
|
||||
|
||||
fixed_t leftdx = cv1->x - leftx;
|
||||
fixed_t leftdy = cv1->y - lefty;
|
||||
fixed_t rightdx = rightx - cv2->x;
|
||||
fixed_t rightdy = righty - cv2->y;
|
||||
|
||||
if (FNodeBuilder::PointOnSide (cv1->x, cv1->y, rightx, righty, rightdx, rightdy) >= 0 ||
|
||||
FNodeBuilder::PointOnSide (cv2->x, cv2->y, leftx, lefty, leftdx, leftdy) >= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = PortalStack.Size(); j-- > 1; )
|
||||
{
|
||||
if (FNodeBuilder::PointOnSide (PortalStack[j].Left->x, PortalStack[j].Left->y,
|
||||
rightx, righty, rightdx, rightdy) >= 0 ||
|
||||
FNodeBuilder::PointOnSide (PortalStack[j].Right->x, PortalStack[j].Right->y,
|
||||
leftx, lefty, leftdx, leftdy) >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == 0)
|
||||
{
|
||||
TracePathDeep (cseg);
|
||||
}
|
||||
}
|
||||
PortalStack.Pop (entrance);
|
||||
}
|
211
Unused/rejectbuilder.h
Normal file
211
Unused/rejectbuilder.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
// A slight adaptation of Quake's vis utility.
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "tarray.h"
|
||||
#include "doomdata.h"
|
||||
|
||||
class FRejectBuilder
|
||||
{
|
||||
public:
|
||||
FRejectBuilder (FLevel &level);
|
||||
~FRejectBuilder ();
|
||||
|
||||
BYTE *GetReject ();
|
||||
|
||||
private:
|
||||
void BuildReject ();
|
||||
void LoadPortals ();
|
||||
inline const WideVertex *GetVertex (WORD vertnum);
|
||||
FLevel &Level;
|
||||
|
||||
/* Looky! Stuff from vis.h: */
|
||||
|
||||
// seperator caching helps a bit
|
||||
//#define SEPERATORCACHE
|
||||
|
||||
// can't have more seperators than the max number of points on a winding
|
||||
static const int MAX_SEPERATORS = 2;
|
||||
static const int MAX_PORTALS = 65536*2/3;
|
||||
static const int MAX_MAP_LEAFS = 32768;
|
||||
static const int MAX_PORTALS_ON_LEAF = MAX_PORTALS;
|
||||
|
||||
struct FPoint
|
||||
{
|
||||
fixed_t x, y;
|
||||
|
||||
const FPoint &operator= (const WideVertex *other)
|
||||
{
|
||||
x = other->x;
|
||||
y = other->y;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
struct FLine : public FPoint
|
||||
{
|
||||
fixed_t dx, dy;
|
||||
|
||||
void Flip ()
|
||||
{
|
||||
x += dx;
|
||||
y += dy;
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
}
|
||||
};
|
||||
|
||||
struct FWinding
|
||||
{
|
||||
FPoint points[2];
|
||||
};
|
||||
|
||||
struct FPassage
|
||||
{
|
||||
FPassage *next;
|
||||
BYTE cansee[1]; //all portals that can be seen through this passage
|
||||
};
|
||||
|
||||
enum VStatus
|
||||
{
|
||||
STAT_None,
|
||||
STAT_Working,
|
||||
STAT_Done
|
||||
};
|
||||
|
||||
struct VPortal
|
||||
{
|
||||
bool removed;
|
||||
bool hint;
|
||||
FLine line; // neighbor is on front/right side
|
||||
int leaf; // neighbor
|
||||
|
||||
FWinding winding;
|
||||
VStatus status;
|
||||
BYTE *portalfront; // [portals], preliminary
|
||||
BYTE *portalflood; // [portals], intermediate
|
||||
BYTE *portalvis; // [portals], final
|
||||
|
||||
int nummightsee; // bit count on portalflood for sort
|
||||
FPassage *passages; // there are just as many passages as there
|
||||
// are portals in the leaf this portal leads to
|
||||
};
|
||||
|
||||
struct FLeaf
|
||||
{
|
||||
FLeaf ();
|
||||
~FLeaf ();
|
||||
|
||||
int numportals;
|
||||
int merged;
|
||||
VPortal **portals;
|
||||
};
|
||||
|
||||
struct PStack
|
||||
{
|
||||
BYTE mightsee[MAX_PORTALS/8]; // bit string
|
||||
PStack *next;
|
||||
FLeaf *leaf;
|
||||
VPortal *portal; // portal exiting
|
||||
FWinding *source;
|
||||
FWinding *pass;
|
||||
|
||||
FWinding windings[3]; // source, pass, temp in any order
|
||||
bool freewindings[3];
|
||||
|
||||
FLine portalline;
|
||||
int depth;
|
||||
#ifdef SEPERATORCACHE
|
||||
FLine seperators[2][MAX_SEPERATORS];
|
||||
int numseperators[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct FThreadData
|
||||
{
|
||||
VPortal *base;
|
||||
int c_chains;
|
||||
PStack pstack_head;
|
||||
};
|
||||
|
||||
int numportals;
|
||||
int portalclusters;
|
||||
|
||||
VPortal *portals;
|
||||
FLeaf *leafs;
|
||||
|
||||
int c_portaltest, c_portalpass, c_portalcheck;
|
||||
int c_portalskip, c_leafskip;
|
||||
int c_vistest, c_mighttest;
|
||||
int c_chains;
|
||||
|
||||
int testlevel;
|
||||
|
||||
BYTE *uncompressed;
|
||||
|
||||
int leafbytes, leaflongs;
|
||||
int portalbytes, portallongs;
|
||||
|
||||
int numVisBytes;
|
||||
BYTE *visBytes;
|
||||
|
||||
int totalvis;
|
||||
|
||||
void LeafFlow (int leafnum);
|
||||
|
||||
void BasePortalVis (int portalnum);
|
||||
void BetterPortalVis (int portalnum);
|
||||
void PortalFlow (int portalnum);
|
||||
void PassagePortalFlow (int portalnum);
|
||||
void CreatePassages (int portalnum);
|
||||
void PassageFlow (int portalnum);
|
||||
|
||||
VPortal *sorted_portals[65536];
|
||||
|
||||
static int CountBits (BYTE *bits, int numbits);
|
||||
|
||||
void SortPortals ();
|
||||
static int PComp (const void *a, const void *b);
|
||||
int LeafVectorFromPortalVector (BYTE *portalbits, BYTE *leafbits);
|
||||
void ClusterMerge (int leafnum);
|
||||
|
||||
void PassageMemory ();
|
||||
void CalcFastVis ();
|
||||
void CalcVis ();
|
||||
void CalcPortalVis ();
|
||||
void CalcPassagePortalVis ();
|
||||
|
||||
int CountActivePortals ();
|
||||
|
||||
bool pacifier;
|
||||
int workcount;
|
||||
int dispatch;
|
||||
int oldf;
|
||||
int oldcount;
|
||||
|
||||
void RunThreadsOnIndividual (int workcnt, bool showpacifire, void (FRejectBuilder::*func)(int));
|
||||
int GetThreadWork ();
|
||||
|
||||
void CheckStack (FLeaf *leaf, FThreadData *thread);
|
||||
|
||||
FWinding *AllocStackWinding (PStack *stack) const;
|
||||
void FreeStackWinding (FWinding *w, PStack *stack) const;
|
||||
|
||||
FWinding *VisChopWinding (FWinding *in, PStack *stack, FLine *split);
|
||||
FWinding *ClipToSeperators (FWinding *source, FWinding *pass, FWinding *target, bool flipclip, PStack *stack);
|
||||
void RecursiveLeafFlow (int leafnum, FThreadData *thread, PStack *prevstack);
|
||||
void RecursivePassageFlow (VPortal *portal, FThreadData *thread, PStack *prevstack);
|
||||
void RecursivePassagePortalFlow (VPortal *portal, FThreadData *thread, PStack *prevstack);
|
||||
FWinding *PassageChopWinding (FWinding *in, FWinding *out, FLine *split);
|
||||
int AddSeperators (FWinding *source, FWinding *pass, bool flipclip, FLine *seperators, int maxseperators);
|
||||
void SimpleFlood (VPortal *srcportal, int leafnum);
|
||||
void RecursiveLeafBitFlow (int leafnum, BYTE *mightsee, BYTE *cansee);
|
||||
|
||||
int PointOnSide (const FPoint &point, const FLine &line);
|
||||
|
||||
bool TryMergeLeaves (int l1num, int l2num);
|
||||
void UpdatePortals ();
|
||||
void MergeLeaves ();
|
||||
FWinding *TryMergeWinding (FWinding *f1, FWinding *f2, const FLine &line);
|
||||
void MergeLeafPortals ();
|
||||
bool Winding_PlanesConcave (const FWinding *w1, const FWinding *w2, const FLine &line1, const FLine &line2);
|
||||
};
|
77
Unused/rejectbuilder.h-nogl
Normal file
77
Unused/rejectbuilder.h-nogl
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "zdbsp.h"
|
||||
#include "tarray.h"
|
||||
#include "doomdata.h"
|
||||
|
||||
class FRejectBuilder
|
||||
{
|
||||
struct FPoint
|
||||
{
|
||||
int x, y;
|
||||
};
|
||||
|
||||
struct BBox
|
||||
{
|
||||
int Bounds[4];
|
||||
|
||||
const int &operator[] (int index) const
|
||||
{
|
||||
return Bounds[index];
|
||||
}
|
||||
int &operator() (int index)
|
||||
{
|
||||
return Bounds[index];
|
||||
}
|
||||
void AddPt (int x, int y)
|
||||
{
|
||||
if (x < Bounds[LEFT]) Bounds[LEFT] = x;
|
||||
if (x > Bounds[RIGHT]) Bounds[RIGHT] = x;
|
||||
if (y < Bounds[BOTTOM]) Bounds[BOTTOM] = y;
|
||||
if (y > Bounds[TOP]) Bounds[TOP] = y;
|
||||
}
|
||||
void AddPt (WideVertex vert)
|
||||
{
|
||||
AddPt (vert.x >> FRACBITS, vert.y >> FRACBITS);
|
||||
}
|
||||
void AddPt (FPoint pt)
|
||||
{
|
||||
AddPt (pt.x, pt.y);
|
||||
}
|
||||
};
|
||||
|
||||
struct FBlockChain
|
||||
{
|
||||
FBlockChain() : Points(0) {}
|
||||
~FBlockChain() { if (Points) delete[] Points; }
|
||||
|
||||
BBox Bounds;
|
||||
FPoint *Points;
|
||||
int NumPoints;
|
||||
FBlockChain *Next;
|
||||
};
|
||||
|
||||
enum { LEFT, TOP, RIGHT, BOTTOM };
|
||||
friend struct BBox;
|
||||
|
||||
public:
|
||||
FRejectBuilder (FLevel &level);
|
||||
~FRejectBuilder ();
|
||||
|
||||
BYTE *GetReject ();
|
||||
|
||||
private:
|
||||
void FindSectorBounds ();
|
||||
void FindBlockChains ();
|
||||
void HullSides (const BBox &box1, const BBox &box2, FPoint sides[4]);
|
||||
bool ChainBlocks (const FBlockChain *chain, const BBox *hullBounds, const FPoint *hullPts);
|
||||
void BuildReject ();
|
||||
|
||||
inline int PointOnSide (const FPoint *pt, const FPoint &lpt1, const FPoint &lpt2);
|
||||
|
||||
BBox *SectorBounds;
|
||||
BYTE *Reject;
|
||||
|
||||
FLevel &Level;
|
||||
int RejectSize;
|
||||
|
||||
FBlockChain *BlockChains;
|
||||
};
|
40
Unused/rejectbuilder.h-slow
Normal file
40
Unused/rejectbuilder.h-slow
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "zdbsp.h"
|
||||
#include "tarray.h"
|
||||
#include "doomdata.h"
|
||||
|
||||
class FRejectBuilder
|
||||
{
|
||||
public:
|
||||
FRejectBuilder (FLevel &level);
|
||||
~FRejectBuilder ();
|
||||
|
||||
BYTE *GetReject ();
|
||||
|
||||
private:
|
||||
struct Portal
|
||||
{
|
||||
const MapSubsector *Subsector;
|
||||
const WideVertex *Left;
|
||||
const WideVertex *Right;
|
||||
};
|
||||
enum ESegSeeStatus
|
||||
{
|
||||
MIGHT_SEE,
|
||||
CAN_SEE,
|
||||
CANNOT_SEE
|
||||
};
|
||||
|
||||
void BuildReject ();
|
||||
void TracePath (int subsector, const MapSegGL *window);
|
||||
void TracePathDeep (const MapSegGL *window);
|
||||
inline const WideVertex *GetVertex (WORD vertnum);
|
||||
|
||||
BYTE *SubSeeMatrix;
|
||||
WORD *SegSubsectors;
|
||||
TArray<Portal> PortalStack;
|
||||
|
||||
FLevel &Level;
|
||||
|
||||
int SourceRow;
|
||||
int SourceSeg, SegRow;
|
||||
};
|
580
Unused/vis.cpp
Normal file
580
Unused/vis.cpp
Normal file
|
@ -0,0 +1,580 @@
|
|||
// An adaptation of the Quake vis utility.
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include "rejectbuilder.h"
|
||||
#include "templates.h"
|
||||
|
||||
bool FastVis=0;
|
||||
bool NoPassageVis=1;
|
||||
bool NoSort;
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
GetThreadWork
|
||||
|
||||
=============
|
||||
*/
|
||||
int FRejectBuilder::GetThreadWork ()
|
||||
{
|
||||
int r;
|
||||
int f;
|
||||
|
||||
if (dispatch == workcount)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pacifier)
|
||||
{
|
||||
if (dispatch >= workcount-1)
|
||||
{
|
||||
fprintf (stderr, "100%%\n");
|
||||
}
|
||||
else if (oldcount < 0 || dispatch - oldcount > 200)
|
||||
{
|
||||
oldcount = dispatch;
|
||||
f = 100*dispatch / workcount;
|
||||
if (f != oldf)
|
||||
{
|
||||
oldf = f;
|
||||
fprintf (stderr, "% 3d%%\b\b\b\b", f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = dispatch++;
|
||||
|
||||
return r;
|
||||
}
|
||||
void FRejectBuilder::RunThreadsOnIndividual (int workcnt, bool showpacifier, void(FRejectBuilder::*func)(int))
|
||||
{
|
||||
int work;
|
||||
|
||||
pacifier = showpacifier;
|
||||
workcount = workcnt;
|
||||
dispatch = 0;
|
||||
oldf = -1;
|
||||
oldcount = -1;
|
||||
|
||||
while (-1 != (work = GetThreadWork ()))
|
||||
{
|
||||
(this->*func) (work);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
/*
|
||||
=============
|
||||
SortPortals
|
||||
|
||||
Sorts the portals from the least complex, so the later ones can reuse
|
||||
the earlier information.
|
||||
=============
|
||||
*/
|
||||
int FRejectBuilder::PComp (const void *a, const void *b)
|
||||
{
|
||||
return (*(VPortal **)a)->nummightsee - (*(VPortal **)b)->nummightsee;
|
||||
}
|
||||
void FRejectBuilder::SortPortals ()
|
||||
{
|
||||
for (int i = 0; i < numportals; i++)
|
||||
{
|
||||
sorted_portals[i] = &portals[i];
|
||||
}
|
||||
|
||||
if (!NoSort)
|
||||
{
|
||||
qsort (sorted_portals, numportals, sizeof(sorted_portals[0]), PComp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
LeafVectorFromPortalVector
|
||||
==============
|
||||
*/
|
||||
int FRejectBuilder::LeafVectorFromPortalVector (BYTE *portalbits, BYTE *leafbits)
|
||||
{
|
||||
int i, j, leafnum;
|
||||
VPortal *p;
|
||||
int c_leafs;
|
||||
|
||||
|
||||
for (i = 0; i < numportals; i++)
|
||||
{
|
||||
if (portalbits[i>>3] & (1<<(i&7)) )
|
||||
{
|
||||
p = portals+i;
|
||||
leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
|
||||
//printf ("pleaf: from %d to %d\n", i, p->leaf);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < portalclusters; j++)
|
||||
{
|
||||
leafnum = j;
|
||||
while (leafs[leafnum].merged >= 0)
|
||||
{
|
||||
leafnum = leafs[leafnum].merged;
|
||||
}
|
||||
//if the merged leaf is visible then the original leaf is visible
|
||||
if (leafbits[leafnum>>3] & (1<<(leafnum&7)))
|
||||
{
|
||||
leafbits[j>>3] |= (1<<(j&7));
|
||||
}
|
||||
}
|
||||
|
||||
c_leafs = CountBits (leafbits, portalclusters);
|
||||
|
||||
return c_leafs;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============
|
||||
ClusterMerge
|
||||
|
||||
Merges the portal visibility for a leaf
|
||||
===============
|
||||
*/
|
||||
void FRejectBuilder::ClusterMerge (int leafnum)
|
||||
{
|
||||
FLeaf *leaf;
|
||||
BYTE portalvector[MAX_PORTALS/8];
|
||||
BYTE uncompressed[MAX_MAP_LEAFS/8];
|
||||
int i, j;
|
||||
int numvis, mergedleafnum;
|
||||
VPortal *p;
|
||||
int pnum;
|
||||
|
||||
// OR together all the portalvis bits
|
||||
|
||||
mergedleafnum = leafnum;
|
||||
while (leafs[mergedleafnum].merged >= 0)
|
||||
{
|
||||
mergedleafnum = leafs[mergedleafnum].merged;
|
||||
}
|
||||
|
||||
memset (portalvector, 0, portalbytes);
|
||||
leaf = &leafs[mergedleafnum];
|
||||
for (i = 0; i < leaf->numportals; i++)
|
||||
{
|
||||
p = leaf->portals[i];
|
||||
if (p->removed)
|
||||
continue;
|
||||
|
||||
if (p->status != STAT_Done)
|
||||
{
|
||||
throw exception("portal not done");
|
||||
}
|
||||
for (j = 0; j < portallongs; j++)
|
||||
{
|
||||
((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
|
||||
}
|
||||
pnum = p - portals;
|
||||
portalvector[pnum>>3] |= 1<<(pnum&7);
|
||||
}
|
||||
|
||||
memset (uncompressed, 0, leafbytes);
|
||||
|
||||
// convert portal bits to leaf bits
|
||||
uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7));
|
||||
numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
|
||||
|
||||
totalvis += numvis;
|
||||
|
||||
//printf ("cluster %4i : %4i visible\n", leafnum, numvis);
|
||||
|
||||
memcpy (visBytes + leafnum*leafbytes, uncompressed, leafbytes);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcPortalVis
|
||||
==================
|
||||
*/
|
||||
void FRejectBuilder::CalcPortalVis ()
|
||||
{
|
||||
#ifdef MREDEBUG
|
||||
_printf("%6d portals out of %d", 0, numportals);
|
||||
//get rid of the counter
|
||||
RunThreadsOnIndividual (numportals, false, PortalFlow);
|
||||
#else
|
||||
RunThreadsOnIndividual (numportals, true, PortalFlow);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcPassagePortalVis
|
||||
==================
|
||||
*/
|
||||
|
||||
void FRejectBuilder::CalcPassagePortalVis ()
|
||||
{
|
||||
PassageMemory();
|
||||
|
||||
#ifdef MREDEBUG
|
||||
_printf("%6d portals out of %d", 0, numportals);
|
||||
RunThreadsOnIndividual (numportals, false, CreatePassages);
|
||||
_printf("\n");
|
||||
_printf("%6d portals out of %d", 0, numportals);
|
||||
RunThreadsOnIndividual (numportals, false, PassagePortalFlow);
|
||||
_printf("\n");
|
||||
#else
|
||||
RunThreadsOnIndividual (numportals, true, CreatePassages);
|
||||
printf (" Vis 3: ");
|
||||
RunThreadsOnIndividual (numportals, true, PassagePortalFlow);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcFastVis
|
||||
==================
|
||||
*/
|
||||
void FRejectBuilder::CalcFastVis ()
|
||||
{
|
||||
// fastvis just uses mightsee for a very loose bound
|
||||
for (int i = 0; i < numportals; i++)
|
||||
{
|
||||
portals[i].portalvis = portals[i].portalflood;
|
||||
portals[i].status = STAT_Done;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
CalcVis
|
||||
==================
|
||||
*/
|
||||
void FRejectBuilder::CalcVis ()
|
||||
{
|
||||
printf (" Vis 1: ");
|
||||
RunThreadsOnIndividual (numportals, true, BasePortalVis);
|
||||
|
||||
// RunThreadsOnIndividual (numportals, true, BetterPortalVis);
|
||||
|
||||
SortPortals ();
|
||||
|
||||
printf (" Vis 2: ");
|
||||
if (FastVis)
|
||||
CalcFastVis();
|
||||
else if (NoPassageVis)
|
||||
CalcPortalVis ();
|
||||
else
|
||||
CalcPassagePortalVis();
|
||||
//
|
||||
// assemble the leaf vis lists by oring and compressing the portal lists
|
||||
//
|
||||
printf ("creating leaf vis...\n");
|
||||
for (int i = 0; i < portalclusters; i++)
|
||||
{
|
||||
ClusterMerge (i);
|
||||
}
|
||||
|
||||
printf ("Average clusters visible: %i\n", totalvis / portalclusters);
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Winding_PlanesConcave
|
||||
=============
|
||||
*/
|
||||
bool FRejectBuilder::Winding_PlanesConcave (const FWinding *w1, const FWinding *w2,
|
||||
const FLine &line1, const FLine &line2)
|
||||
{
|
||||
// check if one of the points of winding 1 is at the front of the line of winding 2
|
||||
if (PointOnSide (w1->points[0], line2) < 0 ||
|
||||
PointOnSide (w1->points[1], line2) < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if one of the points of winding 2 is at the front of the line of winding 1
|
||||
if (PointOnSide (w2->points[0], line1) < 0 ||
|
||||
PointOnSide (w2->points[1], line1) < 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
TryMergeLeaves
|
||||
============
|
||||
*/
|
||||
bool FRejectBuilder::TryMergeLeaves (int l1num, int l2num)
|
||||
{
|
||||
int i, j, numportals;
|
||||
FLeaf *l1, *l2;
|
||||
VPortal *p1, *p2;
|
||||
VPortal *portals[MAX_PORTALS_ON_LEAF];
|
||||
|
||||
l1 = &leafs[l1num];
|
||||
for (i = 0; i < l1->numportals; i++)
|
||||
{
|
||||
p1 = l1->portals[i];
|
||||
if (p1->leaf == l2num) continue;
|
||||
l2 = &leafs[l2num];
|
||||
for (j = 0; j < l2->numportals; j++)
|
||||
{
|
||||
p2 = l2->portals[j];
|
||||
if (p2->leaf == l1num) continue;
|
||||
//
|
||||
if (Winding_PlanesConcave (&p1->winding, &p2->winding, p1->line, p2->line))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
l1 = &leafs[l1num];
|
||||
l2 = &leafs[l2num];
|
||||
numportals = 0;
|
||||
//the leaves can be merged now
|
||||
for (i = 0; i < l1->numportals; i++)
|
||||
{
|
||||
p1 = l1->portals[i];
|
||||
if (p1->leaf == l2num)
|
||||
{
|
||||
p1->removed = true;
|
||||
continue;
|
||||
}
|
||||
portals[numportals++] = p1;
|
||||
}
|
||||
for (j = 0; j < l2->numportals; j++)
|
||||
{
|
||||
p2 = l2->portals[j];
|
||||
if (p2->leaf == l1num)
|
||||
{
|
||||
p2->removed = true;
|
||||
continue;
|
||||
}
|
||||
portals[numportals++] = p2;
|
||||
}
|
||||
delete[] l1->portals;
|
||||
l1->portals = NULL;
|
||||
l1->numportals = 0;
|
||||
delete[] l2->portals;
|
||||
l2->portals = new VPortal *[numportals];
|
||||
for (i = 0; i < numportals; i++)
|
||||
{
|
||||
l2->portals[i] = portals[i];
|
||||
}
|
||||
l2->numportals = numportals;
|
||||
l1->merged = l2num;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
UpdatePortals
|
||||
============
|
||||
*/
|
||||
void FRejectBuilder::UpdatePortals ()
|
||||
{
|
||||
int i;
|
||||
VPortal *p;
|
||||
|
||||
for (i = 0; i < numportals; i++)
|
||||
{
|
||||
p = &portals[i];
|
||||
if (!p->removed)
|
||||
{
|
||||
while (leafs[p->leaf].merged >= 0)
|
||||
{
|
||||
p->leaf = leafs[p->leaf].merged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
MergeLeaves
|
||||
|
||||
try to merge leaves but don't merge through hint splitters
|
||||
============
|
||||
*/
|
||||
void FRejectBuilder::MergeLeaves ()
|
||||
{
|
||||
int i, j, nummerges, totalnummerges;
|
||||
FLeaf *leaf;
|
||||
VPortal *p;
|
||||
|
||||
totalnummerges = 0;
|
||||
do
|
||||
{
|
||||
printf (".");
|
||||
nummerges = 0;
|
||||
for (i = 0; i < portalclusters; i++)
|
||||
{
|
||||
leaf = &leafs[i];
|
||||
//if this leaf is merged already
|
||||
if (leaf->merged >= 0)
|
||||
continue;
|
||||
//
|
||||
for (j = 0; j < leaf->numportals; j++)
|
||||
{
|
||||
p = leaf->portals[j];
|
||||
//
|
||||
if (p->removed)
|
||||
continue;
|
||||
//never merge through hint portals
|
||||
if (p->hint)
|
||||
continue;
|
||||
if (TryMergeLeaves(i, p->leaf))
|
||||
{
|
||||
UpdatePortals();
|
||||
nummerges++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
totalnummerges += nummerges;
|
||||
} while (nummerges);
|
||||
printf("\r%6d leaves merged\n", totalnummerges);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
TryMergeWinding
|
||||
============
|
||||
*/
|
||||
|
||||
FRejectBuilder::FWinding *FRejectBuilder::TryMergeWinding (FWinding *f1, FWinding *f2, const FLine &line)
|
||||
{
|
||||
static FWinding result;
|
||||
int i, j;
|
||||
|
||||
//
|
||||
// find a common point
|
||||
//
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
for (j = 0; j < 2; ++j)
|
||||
{
|
||||
if (f1->points[i].x == f2->points[j].x &&
|
||||
f1->points[i].y == f2->points[j].y)
|
||||
{
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no shared point
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
//
|
||||
// if the lines are colinear, the point can be removed
|
||||
//
|
||||
if (PointOnSide (f2->points[0], line) != 0 ||
|
||||
PointOnSide (f2->points[1], line) != 0)
|
||||
{ // not colinear
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// build the new segment
|
||||
//
|
||||
if (i == 0)
|
||||
{
|
||||
result.points[0] = f2->points[!j];
|
||||
result.points[1] = f1->points[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
result.points[0] = f1->points[0];
|
||||
result.points[1] = f2->points[!j];
|
||||
}
|
||||
return &result;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
MergeLeafPortals
|
||||
============
|
||||
*/
|
||||
void FRejectBuilder::MergeLeafPortals ()
|
||||
{
|
||||
int i, j, k, nummerges, hintsmerged;
|
||||
FLeaf *leaf;
|
||||
VPortal *p1, *p2;
|
||||
FWinding *w;
|
||||
|
||||
nummerges = 0;
|
||||
hintsmerged = 0;
|
||||
for (i = 0; i < portalclusters; i++)
|
||||
{
|
||||
leaf = &leafs[i];
|
||||
if (leaf->merged >= 0) continue;
|
||||
for (j = 0; j < leaf->numportals; j++)
|
||||
{
|
||||
p1 = leaf->portals[j];
|
||||
if (p1->removed)
|
||||
continue;
|
||||
for (k = j+1; k < leaf->numportals; k++)
|
||||
{
|
||||
p2 = leaf->portals[k];
|
||||
if (p2->removed)
|
||||
continue;
|
||||
if (p1->leaf == p2->leaf)
|
||||
{
|
||||
w = TryMergeWinding (&p1->winding, &p2->winding, p1->line);
|
||||
if (w)
|
||||
{
|
||||
p1->winding = *w;
|
||||
if (p1->hint && p2->hint)
|
||||
hintsmerged++;
|
||||
p1->hint |= p2->hint;
|
||||
p2->removed = true;
|
||||
nummerges++;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (k < leaf->numportals)
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("%6d portals merged\n", nummerges);
|
||||
printf("%6d hint portals merged\n", hintsmerged);
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
CountActivePortals
|
||||
============
|
||||
*/
|
||||
int FRejectBuilder::CountActivePortals ()
|
||||
{
|
||||
int num, hints, j;
|
||||
VPortal *p;
|
||||
|
||||
num = 0;
|
||||
hints = 0;
|
||||
for (j = 0; j < numportals; j++)
|
||||
{
|
||||
p = portals + j;
|
||||
if (p->removed)
|
||||
continue;
|
||||
if (p->hint)
|
||||
hints++;
|
||||
num++;
|
||||
}
|
||||
printf("%6d of %d active portals\n", num, numportals);
|
||||
printf("%6d hint portals\n", hints);
|
||||
return num;
|
||||
}
|
1345
Unused/visflow.cpp
Normal file
1345
Unused/visflow.cpp
Normal file
File diff suppressed because it is too large
Load diff
455
blockmapbuilder.cpp
Normal file
455
blockmapbuilder.cpp
Normal file
|
@ -0,0 +1,455 @@
|
|||
/*
|
||||
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 <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "templates.h"
|
||||
#include "tarray.h"
|
||||
#include "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;
|
||||
int i;
|
||||
WORD line;
|
||||
|
||||
if (Level.NumVertices <= 0)
|
||||
return;
|
||||
|
||||
// Find map extents for the blockmap
|
||||
minx = maxx = Level.Vertices[0].x;
|
||||
miny = maxy = Level.Vertices[0].y;
|
||||
|
||||
for (i = 1; i < Level.NumVertices; ++i)
|
||||
{
|
||||
if (Level.Vertices[i].x < minx) minx = Level.Vertices[i].x;
|
||||
else if (Level.Vertices[i].x > maxx) maxx = Level.Vertices[i].x;
|
||||
if (Level.Vertices[i].y < miny) miny = Level.Vertices[i].y;
|
||||
else if (Level.Vertices[i].y > maxy) maxy = Level.Vertices[i].y;
|
||||
}
|
||||
|
||||
maxx >>= FRACBITS;
|
||||
minx >>= FRACBITS;
|
||||
maxy >>= FRACBITS;
|
||||
miny >>= 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 (size_t 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);
|
||||
}
|
||||
|
18
blockmapbuilder.h
Normal file
18
blockmapbuilder.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "doomdata.h"
|
||||
#include "workdata.h"
|
||||
#include "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);
|
||||
};
|
177
doomdata.h
Normal file
177
doomdata.h
Normal file
|
@ -0,0 +1,177 @@
|
|||
#ifndef __DOOMDATA_H__
|
||||
#define __DOOMDATA_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
BOXTOP, BOXBOTTOM, BOXLEFT, BOXRIGHT
|
||||
};
|
||||
|
||||
struct MapVertex
|
||||
{
|
||||
short x, y;
|
||||
};
|
||||
|
||||
struct WideVertex
|
||||
{
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
struct MapSideDef
|
||||
{
|
||||
short textureoffset;
|
||||
short rowoffset;
|
||||
char toptexture[8];
|
||||
char bottomtexture[8];
|
||||
char midtexture[8];
|
||||
short sector;
|
||||
};
|
||||
|
||||
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 MapSector
|
||||
{
|
||||
short floorheight;
|
||||
short ceilingheight;
|
||||
char floorpic[8];
|
||||
char ceilingpic[8];
|
||||
short lightlevel;
|
||||
short special;
|
||||
short tag;
|
||||
};
|
||||
|
||||
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 MapSegGL
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
WORD linedef;
|
||||
WORD side;
|
||||
WORD partner;
|
||||
};
|
||||
|
||||
struct MapSegGLEx
|
||||
{
|
||||
WORD v1;
|
||||
WORD v2;
|
||||
WORD 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 MapNodeEx
|
||||
{
|
||||
short 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 FLevel
|
||||
{
|
||||
FLevel ();
|
||||
~FLevel ();
|
||||
|
||||
WideVertex *Vertices; int NumVertices;
|
||||
MapSideDef *Sides; int NumSides;
|
||||
MapLineDef2 *Lines; int NumLines;
|
||||
MapSector *Sectors; int NumSectors;
|
||||
MapSubsectorEx *Subsectors; int NumSubsectors;
|
||||
MapSeg *Segs; int NumSegs;
|
||||
MapNodeEx *Nodes; int NumNodes;
|
||||
MapThing2 *Things; int NumThings;
|
||||
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;
|
||||
|
||||
void RemoveExtraLines ();
|
||||
void RemoveExtraSides ();
|
||||
void RemoveExtraSectors ();
|
||||
};
|
||||
|
||||
const int BLOCKSIZE = 128;
|
||||
const int BLOCKFRACSIZE = BLOCKSIZE<<FRACBITS;
|
||||
const int BLOCKBITS = 7;
|
||||
const int BLOCKFRACBITS = FRACBITS+7;
|
||||
|
||||
#endif //__DOOMDATA_H__
|
133
getopt.h
Normal file
133
getopt.h
Normal file
|
@ -0,0 +1,133 @@
|
|||
/* 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
|
||||
{
|
||||
#if defined (__STDC__) && __STDC__
|
||||
const char *name;
|
||||
#else
|
||||
char *name;
|
||||
#endif
|
||||
/* 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))
|
||||
#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__ */
|
||||
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
getopt1.c
Normal file
189
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 */
|
524
main.cpp
Normal file
524
main.cpp
Normal file
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
The main glue for ZDBSP.
|
||||
Copyright (C) 2002,2003 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
|
||||
|
||||
#define HAVE_TIMING 0
|
||||
#define START_COUNTER(s,e,f)
|
||||
#define END_COUNTER(s,e,f)
|
||||
|
||||
// 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 <math.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "wad.h"
|
||||
#include "processor.h"
|
||||
#include "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 ();
|
||||
|
||||
// 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;
|
||||
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 GLOnly = false;
|
||||
|
||||
// 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'},
|
||||
{"gl-only", no_argument, 0, 'x'},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
static const char short_opts[] = "wVgGvbNrReEm:o:f:p:s:d:PqtzZx";
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
bool fixSame = false;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
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 exception("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, " %g 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: %g seconds.\n")
|
||||
}
|
||||
catch (exception msg)
|
||||
{
|
||||
printf ("%s\n", msg.what());
|
||||
return 20;
|
||||
}
|
||||
|
||||
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 'z':
|
||||
CompressNodes = true;
|
||||
CompressGLNodes = true;
|
||||
break;
|
||||
case 'Z':
|
||||
CompressNodes = true;
|
||||
CompressGLNodes = false;
|
||||
break;
|
||||
case 'x':
|
||||
GLOnly = true;
|
||||
BuildGLNodes = true;
|
||||
ConformNodes = false;
|
||||
break;
|
||||
case 'q':
|
||||
NoPrune = true;
|
||||
break;
|
||||
case 't':
|
||||
NoTiming = true;
|
||||
break;
|
||||
case 'V':
|
||||
ShowVersion ();
|
||||
exit (0);
|
||||
break;
|
||||
case 1000:
|
||||
ShowUsage ();
|
||||
exit (0);
|
||||
default:
|
||||
printf ("Try `zdbsp --help' for more information.\n");
|
||||
exit (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ShowUsage
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ShowUsage ()
|
||||
{
|
||||
printf (
|
||||
"Usage: zdbsp [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"
|
||||
" -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 number of segs to consider at each node\n"// (default 64)\n"
|
||||
" -s, --split-cost=NNN Adjusts the cost for splitting segs\n"// (default 8)\n"
|
||||
" -d, --diagonal-cost=NNN Adjusts the cost for avoiding diagonal splitters\n"// (default 16)\n"
|
||||
" -P, --no-polyobjs Do not check for polyobject subsector splits\n"
|
||||
" -z, --compress Compress the nodes (including GL nodes, if created)\n"
|
||||
" -Z, --compress-normal Compress normal nodes but not GL nodes\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\n"
|
||||
);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ShowVersion
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ShowVersion ()
|
||||
{
|
||||
printf ("ZDBSP " ZDBSP_VERSION "\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
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PointToAngle
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
angle_t PointToAngle (fixed_t x, fixed_t y)
|
||||
{
|
||||
const double rad2bam = double(1<<30) / M_PI;
|
||||
double ang = atan2 (double(y), double(x));
|
||||
if (ang < 0.0)
|
||||
{
|
||||
ang = 2*M_PI+ang;
|
||||
}
|
||||
return angle_t(ang * rad2bam) << 1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Warn
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void Warn (const char *format, ...)
|
||||
{
|
||||
va_list marker;
|
||||
|
||||
if (!ShowWarnings)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
va_start (marker, format);
|
||||
vprintf (format, marker);
|
||||
va_end (marker);
|
||||
}
|
1108
nodebuild.cpp
Normal file
1108
nodebuild.cpp
Normal file
File diff suppressed because it is too large
Load diff
189
nodebuild.h
Normal file
189
nodebuild.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
#include "doomdata.h"
|
||||
#include "workdata.h"
|
||||
#include "tarray.h"
|
||||
|
||||
struct FEventInfo
|
||||
{
|
||||
int Vertex;
|
||||
DWORD FrontSeg;
|
||||
};
|
||||
|
||||
struct FEvent
|
||||
{
|
||||
FEvent *Parent, *Left, *Right;
|
||||
enum { RED, BLACK } Color;
|
||||
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);
|
||||
void Delete (FEvent *event);
|
||||
FEvent *FindEvent (double distance) const;
|
||||
void DeleteAll ();
|
||||
|
||||
private:
|
||||
FEvent Nil;
|
||||
FEvent *Root;
|
||||
FEvent *Spare;
|
||||
|
||||
void LeftRotate (FEvent *event);
|
||||
void RightRotate (FEvent *event);
|
||||
void DeleteFixUp (FEvent *event);
|
||||
void DeletionTraverser (FEvent *event);
|
||||
FEvent *Successor (FEvent *event) const;
|
||||
FEvent *Predecessor (FEvent *event) const;
|
||||
};
|
||||
|
||||
class FNodeBuilder
|
||||
{
|
||||
struct FPrivSeg
|
||||
{
|
||||
int v1, v2;
|
||||
int 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
|
||||
{
|
||||
fixed_t x, y;
|
||||
DWORD segs; // segs that use this vertex as v1
|
||||
DWORD segs2; // segs that use this vertex as v2
|
||||
|
||||
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;
|
||||
};
|
||||
public:
|
||||
struct FPolyStart
|
||||
{
|
||||
int polynum;
|
||||
fixed_t x, y;
|
||||
};
|
||||
|
||||
FNodeBuilder (FLevel &level,
|
||||
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
||||
const char *name, bool makeGLnodes);
|
||||
|
||||
void GetVertices (WideVertex *&verts, int &count);
|
||||
void GetNodes (MapNodeEx *&nodes, int &nodeCount,
|
||||
MapSeg *&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 int PointOnSide (int x, int y, int x1, int y1, int dx, int dy);
|
||||
|
||||
private:
|
||||
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
|
||||
FLevel &Level;
|
||||
bool GLNodes;
|
||||
|
||||
// Progress meter stuff
|
||||
int SegsStuffed;
|
||||
const char *MapName;
|
||||
|
||||
void FindUsedVertices (WideVertex *vertices, int max);
|
||||
int SelectVertexExact (FPrivVert &vertex);
|
||||
void BuildTree ();
|
||||
void MakeSegsFromSides ();
|
||||
FPrivSeg *CheckSegForDuplicate (const FPrivSeg *check);
|
||||
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, fixed_t bbox[4]);
|
||||
DWORD CreateSubsector (DWORD set, fixed_t bbox[4]);
|
||||
void CreateSubsectorsForReal ();
|
||||
bool CheckSubsector (DWORD set, node_t &node, DWORD &splitseg, int setsize);
|
||||
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);
|
||||
DWORD SplitSeg (DWORD segnum, int splitvert, int v1InFront);
|
||||
int Heuristic (node_t &node, DWORD set, bool honorNoSplit);
|
||||
int ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2);
|
||||
int CountSegs (DWORD set) const;
|
||||
|
||||
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<MapSeg> &segs, MapSubsectorEx *subs, int node, short bbox[4]);
|
||||
int StripMinisegs (TArray<MapSeg> &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);
|
||||
|
||||
static int SortSegs (const void *a, const void *b);
|
||||
|
||||
double InterceptVector (const node_t &splitter, const FPrivSeg &seg);
|
||||
|
||||
void PrintSet (int l, DWORD set);
|
||||
};
|
407
nodebuild_events.cpp
Normal file
407
nodebuild_events.cpp
Normal file
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
A red-black tree implementation for building minisegs.
|
||||
Copyright (C) 2002,2003 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 "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
|
||||
FEventTree::FEventTree ()
|
||||
: Root (&Nil), Spare (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void FEventTree::LeftRotate (FEvent *x)
|
||||
{
|
||||
FEvent *y = x->Right;
|
||||
x->Right = y->Left;
|
||||
if (y->Left != &Nil)
|
||||
{
|
||||
y->Left->Parent = x;
|
||||
}
|
||||
y->Parent = x->Parent;
|
||||
if (x->Parent != &Nil)
|
||||
{
|
||||
Root = y;
|
||||
}
|
||||
else if (x == x->Parent->Left)
|
||||
{
|
||||
x->Parent->Left = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x->Parent->Right = y;
|
||||
}
|
||||
y->Left = x;
|
||||
x->Parent = y;
|
||||
}
|
||||
|
||||
void FEventTree::RightRotate (FEvent *x)
|
||||
{
|
||||
FEvent *y = x->Left;
|
||||
x->Left = y->Right;
|
||||
if (y->Right != &Nil)
|
||||
{
|
||||
y->Right->Parent = x;
|
||||
}
|
||||
y->Parent = x->Parent;
|
||||
if (x->Parent != &Nil)
|
||||
{
|
||||
Root = y;
|
||||
}
|
||||
else if (x == x->Parent->Left)
|
||||
{
|
||||
x->Parent->Left = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
x->Parent->Right = y;
|
||||
}
|
||||
y->Right = x;
|
||||
x->Parent = y;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
z->Color = FEvent::RED;
|
||||
while (z != Root && z->Parent->Color != FEvent::RED)
|
||||
{
|
||||
if (z->Parent == z->Parent->Parent->Left)
|
||||
{
|
||||
y = z->Parent->Parent->Right;
|
||||
if (y->Color == FEvent::RED)
|
||||
{
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
y->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
z = z->Parent->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z == z->Parent->Right)
|
||||
{
|
||||
z = z->Parent;
|
||||
LeftRotate (z);
|
||||
}
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
RightRotate (z->Parent->Parent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
y = z->Parent->Parent->Left;
|
||||
if (y->Color == FEvent::RED)
|
||||
{
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
y->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
z = z->Parent->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (z == z->Parent->Left)
|
||||
{
|
||||
z = z->Parent;
|
||||
RightRotate (z);
|
||||
}
|
||||
z->Parent->Color = FEvent::BLACK;
|
||||
z->Parent->Parent->Color = FEvent::RED;
|
||||
RightRotate (z->Parent->Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FEventTree::Delete (FEvent *z)
|
||||
{
|
||||
FEvent *x, *y;
|
||||
|
||||
if (z->Left == &Nil || z->Right == &Nil)
|
||||
{
|
||||
y = z;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = Successor (z);
|
||||
}
|
||||
if (y->Left != &Nil)
|
||||
{
|
||||
x = y->Left;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = y->Right;
|
||||
}
|
||||
x->Parent = y->Parent;
|
||||
if (y->Parent == &Nil)
|
||||
{
|
||||
Root = x;
|
||||
}
|
||||
else if (y == y->Parent->Left)
|
||||
{
|
||||
y->Parent->Left = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
y->Parent->Right = x;
|
||||
}
|
||||
if (y != z)
|
||||
{
|
||||
z->Distance = y->Distance;
|
||||
z->Info = y->Info;
|
||||
}
|
||||
if (y->Color == FEvent::BLACK)
|
||||
{
|
||||
DeleteFixUp (x);
|
||||
}
|
||||
|
||||
y->Left = Spare;
|
||||
Spare = y;
|
||||
}
|
||||
|
||||
void FEventTree::DeleteFixUp (FEvent *x)
|
||||
{
|
||||
FEvent *w;
|
||||
|
||||
while (x != Root && x->Color == FEvent::BLACK)
|
||||
{
|
||||
if (x == x->Parent->Left)
|
||||
{
|
||||
w = x->Parent->Right;
|
||||
if (w->Color == FEvent::RED)
|
||||
{
|
||||
w->Color = FEvent::BLACK;
|
||||
x->Parent->Color = FEvent::RED;
|
||||
LeftRotate (x->Parent);
|
||||
w = x->Parent->Right;
|
||||
}
|
||||
if (w->Left->Color == FEvent::BLACK && w->Right->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Color = FEvent::RED;
|
||||
x = x->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->Right->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Left->Color = FEvent::BLACK;
|
||||
w->Color = FEvent::RED;
|
||||
RightRotate (w);
|
||||
w = x->Parent->Right;
|
||||
}
|
||||
w->Color = x->Parent->Color;
|
||||
x->Parent->Color = FEvent::BLACK;
|
||||
w->Right->Color = FEvent::BLACK;
|
||||
LeftRotate (x->Parent);
|
||||
x = Root;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
w = x->Parent->Left;
|
||||
if (w->Color == FEvent::RED)
|
||||
{
|
||||
w->Color = FEvent::BLACK;
|
||||
x->Parent->Color = FEvent::RED;
|
||||
RightRotate (x->Parent);
|
||||
w = x->Parent->Left;
|
||||
}
|
||||
if (w->Right->Color == FEvent::BLACK && w->Left->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Color = FEvent::RED;
|
||||
x = x->Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (w->Left->Color == FEvent::BLACK)
|
||||
{
|
||||
w->Right->Color = FEvent::BLACK;
|
||||
w->Color = FEvent::RED;
|
||||
LeftRotate (w);
|
||||
w = x->Parent->Left;
|
||||
}
|
||||
w->Color = x->Parent->Color;
|
||||
x->Parent->Color = FEvent::BLACK;
|
||||
w->Left->Color = FEvent::BLACK;
|
||||
RightRotate (x->Parent);
|
||||
x = Root;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
349
nodebuild_extract.cpp
Normal file
349
nodebuild_extract.cpp
Normal file
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
Routines for extracting usable data from the new BSP tree.
|
||||
Copyright (C) 2002,2003 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 "zdbsp.h"
|
||||
#include "nodebuild.h"
|
||||
#include "templates.h"
|
||||
|
||||
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 = short(orgnode->x >> FRACBITS);
|
||||
newnode->y = short(orgnode->y >> FRACBITS);
|
||||
newnode->dx = short(orgnode->dx >> FRACBITS);
|
||||
newnode->dy = short(orgnode->dy >> FRACBITS);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
first = Subsectors[subsector].firstline;
|
||||
max = first + Subsectors[subsector].numlines;
|
||||
count = 0;
|
||||
|
||||
accumx = accumy = 0.0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#if 0
|
||||
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: %5d(%5d,%5d)->%5d(%5d,%5d) - %3.3f\n", j,
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
|
||||
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++;
|
||||
}
|
||||
#if 0
|
||||
printf ("+%d\n", bestj);
|
||||
#endif
|
||||
prevAngle -= bestdiff;
|
||||
seg->storedseg = PushGLSeg (segs, seg);
|
||||
count++;
|
||||
prev = seg;
|
||||
if (seg->v2 == firstVert)
|
||||
{
|
||||
prev = seg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
if (prev->v2 != firstVert)
|
||||
{
|
||||
PushConnectingGLSeg (subsector, segs, prev->v2, firstVert);
|
||||
count++;
|
||||
}
|
||||
|
||||
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;
|
||||
newseg.side = newseg.linedef != NO_INDEX
|
||||
? Level.Lines[newseg.linedef].sidenum[1] == seg->sidedef ? 1 : 0
|
||||
: 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;
|
||||
}
|
||||
}
|
||||
|
||||
void FNodeBuilder::GetNodes (MapNodeEx *&outNodes, int &nodeCount,
|
||||
MapSeg *&outSegs, int &segCount,
|
||||
MapSubsectorEx *&outSubs, int &subCount)
|
||||
{
|
||||
short bbox[4];
|
||||
TArray<MapSeg> 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 MapSeg[segCount];
|
||||
memcpy (outSegs, &segs[0], segCount*sizeof(MapSeg));
|
||||
}
|
||||
|
||||
int FNodeBuilder::RemoveMinisegs (MapNodeEx *nodes,
|
||||
TArray<MapSeg> &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 >> FRACBITS;
|
||||
newnode->y = orgnode->y >> FRACBITS;
|
||||
newnode->dx = orgnode->dx >> FRACBITS;
|
||||
newnode->dy = orgnode->dy >> FRACBITS;
|
||||
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<MapSeg> &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
|
||||
{
|
||||
MapSeg 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;
|
||||
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;
|
||||
}
|
388
nodebuild_gl.cpp
Normal file
388
nodebuild_gl.cpp
Normal file
|
@ -0,0 +1,388 @@
|
|||
/*
|
||||
Routines only necessary for building GL-friendly nodes.
|
||||
Copyright (C) 2002,2003 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 "zdbsp.h"
|
||||
#include "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 dx = double(v->x - node.x);
|
||||
double dy = double(v->y - node.y);
|
||||
double dist = dx*dx + dy*dy;
|
||||
|
||||
if (node.dx != 0)
|
||||
{
|
||||
if ((node.dx > 0 && dx < 0.0) || (node.dx < 0 && dx > 0.0))
|
||||
{
|
||||
dist = -dist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((node.dy > 0 && dy < 0.0) || (node.dy < 0 && dy > 0.0))
|
||||
{
|
||||
dist = -dist;
|
||||
}
|
||||
}
|
||||
|
||||
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 ()
|
||||
{
|
||||
for (size_t 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;
|
||||
}
|
||||
|
||||
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) at %d(%d,%d)\n", seg,
|
||||
Segs[seg].v1, Segs[seg].v2,
|
||||
event->Info.Vertex,
|
||||
Vertices[event->Info.Vertex].x>>16,
|
||||
Vertices[event->Info.Vertex].y>>16));
|
||||
|
||||
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 = -1;
|
||||
newseg.loopnum = 0;
|
||||
newseg.next = DWORD_MAX;
|
||||
newseg.planefront = true;
|
||||
|
||||
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;
|
||||
}
|
500
nodebuild_utility.cpp
Normal file
500
nodebuild_utility.cpp
Normal file
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
Various utility functions.
|
||||
Copyright (C) 2002,2003 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 <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "nodebuild.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)
|
||||
{
|
||||
size_t *map = (size_t *)alloca (max*sizeof(size_t));
|
||||
int i;
|
||||
FPrivVert newvert;
|
||||
|
||||
memset (&map[0], -1, sizeof(size_t)*max);
|
||||
|
||||
newvert.segs = DWORD_MAX;
|
||||
newvert.segs2 = DWORD_MAX;
|
||||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
int v1 = Level.Lines[i].v1;
|
||||
int v2 = Level.Lines[i].v2;
|
||||
|
||||
if (map[v1] == (size_t)-1)
|
||||
{
|
||||
newvert.x = oldverts[v1].x;
|
||||
newvert.y = oldverts[v1].y;
|
||||
map[v1] = SelectVertexExact (newvert);
|
||||
}
|
||||
if (map[v2] == (size_t)-1)
|
||||
{
|
||||
newvert.x = oldverts[v2].x;
|
||||
newvert.y = oldverts[v2].y;
|
||||
map[v2] = SelectVertexExact (newvert);
|
||||
}
|
||||
|
||||
Level.Lines[i].v1 = map[v1];
|
||||
Level.Lines[i].v2 = map[v2];
|
||||
}
|
||||
InitialVertices = Vertices.Size ();
|
||||
Level.NumOrgVerts = InitialVertices;
|
||||
}
|
||||
|
||||
int FNodeBuilder::SelectVertexExact (FPrivVert &vertex)
|
||||
{
|
||||
for (size_t i = 0; i < Vertices.Size(); ++i)
|
||||
{
|
||||
if (Vertices[i].x == vertex.x && Vertices[i].y == vertex.y)
|
||||
{
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
return (int)Vertices.Push (vertex);
|
||||
}
|
||||
|
||||
// For every sidedef in the map, create a corresponding seg.
|
||||
|
||||
void FNodeBuilder::MakeSegsFromSides ()
|
||||
{
|
||||
FPrivSeg *share1, *share2;
|
||||
FPrivSeg seg;
|
||||
int i, j;
|
||||
|
||||
seg.next = DWORD_MAX;
|
||||
seg.loopnum = 0;
|
||||
seg.offset = 0;
|
||||
seg.partner = DWORD_MAX;
|
||||
|
||||
for (i = 0; i < Level.NumLines; ++i)
|
||||
{
|
||||
if (Level.Lines[i].sidenum[0] != NO_INDEX)
|
||||
{
|
||||
WORD backside;
|
||||
|
||||
seg.linedef = i;
|
||||
seg.sidedef = Level.Lines[i].sidenum[0];
|
||||
backside = Level.Lines[i].sidenum[1];
|
||||
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
||||
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
||||
seg.v1 = Level.Lines[i].v1;
|
||||
seg.v2 = Level.Lines[i].v2;
|
||||
seg.nextforvert = Vertices[seg.v1].segs;
|
||||
seg.nextforvert2 = Vertices[seg.v2].segs2;
|
||||
share1 = CheckSegForDuplicate (&seg);
|
||||
if (share1 == NULL)
|
||||
{
|
||||
seg.angle = PointToAngle (Vertices[seg.v2].x-Vertices[seg.v1].x,
|
||||
Vertices[seg.v2].y-Vertices[seg.v1].y);
|
||||
j = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = j;
|
||||
Vertices[seg.v2].segs2 = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Linedefs %d and %d share endpoints.\n", i, share1->linedef);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf ("Linedef %d does not have a front side.\n", i);
|
||||
}
|
||||
|
||||
if (Level.Lines[i].sidenum[1] != NO_INDEX)
|
||||
{
|
||||
WORD backside;
|
||||
|
||||
seg.linedef = i;
|
||||
seg.sidedef = Level.Lines[i].sidenum[1];
|
||||
backside = Level.Lines[i].sidenum[0];
|
||||
seg.frontsector = Level.Sides[seg.sidedef].sector;
|
||||
seg.backsector = backside != NO_INDEX ? Level.Sides[backside].sector : -1;
|
||||
seg.v1 = Level.Lines[i].v2;
|
||||
seg.v2 = Level.Lines[i].v1;
|
||||
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);
|
||||
share2 = CheckSegForDuplicate (&seg);
|
||||
if (share2 == NULL)
|
||||
{
|
||||
j = (int)Segs.Push (seg);
|
||||
Vertices[seg.v1].segs = j;
|
||||
Vertices[seg.v2].segs2 = j;
|
||||
|
||||
if (Level.Lines[i].sidenum[0] != NO_INDEX && share1 == NULL)
|
||||
{
|
||||
Segs[j-1].partner = j;
|
||||
Segs[j].partner = j-1;
|
||||
}
|
||||
}
|
||||
else if (share2->linedef != share1->linedef)
|
||||
{
|
||||
printf ("Linedefs %d and %d share endpoints.\n", i, share2->linedef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for another seg with the same start and end vertices as this one.
|
||||
// Combined with its use above, this will find two-sided lines that are shadowed
|
||||
// by another one- or two-sided line, and it will also find one-sided lines that
|
||||
// shadow each other. It will not find one-sided lines that share endpoints but
|
||||
// face opposite directions. Although they should probably be a single two-sided
|
||||
// line, leaving them in will not generate bad nodes.
|
||||
|
||||
FNodeBuilder::FPrivSeg *FNodeBuilder::CheckSegForDuplicate (const FNodeBuilder::FPrivSeg *check)
|
||||
{
|
||||
DWORD segnum;
|
||||
|
||||
// Check for segs facing the same direction
|
||||
for (segnum = check->nextforvert; segnum != DWORD_MAX; segnum = Segs[segnum].nextforvert)
|
||||
{
|
||||
if (Segs[segnum].v2 == check->v2)
|
||||
{
|
||||
return &Segs[segnum];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// 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()));
|
||||
|
||||
planenum = (planenum+7)/8;
|
||||
PlaneChecked.Reserve (planenum);
|
||||
}
|
||||
|
||||
// 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 (size_t i = 0; i < spots.Size(); ++i)
|
||||
{
|
||||
FPolyStart *spot = &spots[i];
|
||||
fixed_t bbox[4];
|
||||
|
||||
if (GetPolyExtents (spot->polynum, bbox))
|
||||
{
|
||||
FPolyStart *anchor;
|
||||
|
||||
size_t 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 (size_t 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 (closestseg >= 0)
|
||||
{
|
||||
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 != 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])
|
||||
{
|
||||
size_t 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;
|
||||
size_t vert;
|
||||
|
||||
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 (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;
|
||||
}
|
BIN
poly_bad.png
Normal file
BIN
poly_bad.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 471 B |
BIN
poly_mov.png
Normal file
BIN
poly_mov.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 458 B |
BIN
poly_new.png
Normal file
BIN
poly_new.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 457 B |
1268
processor.cpp
Normal file
1268
processor.cpp
Normal file
File diff suppressed because it is too large
Load diff
95
processor.h
Normal file
95
processor.h
Normal file
|
@ -0,0 +1,95 @@
|
|||
#ifndef __PROCESSOR_H__
|
||||
#define __PROCESSOR_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "wad.h"
|
||||
#include "doomdata.h"
|
||||
#include "workdata.h"
|
||||
#include "tarray.h"
|
||||
#include "nodebuild.h"
|
||||
#include "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 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);
|
||||
|
||||
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);
|
||||
void WriteGLSegs (FWadWriter &out);
|
||||
void WriteGLSSect (FWadWriter &out);
|
||||
void WriteGLNodes (FWadWriter &out);
|
||||
|
||||
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 MapSeg *segs, int numsegs);
|
||||
void WriteGLSegsZ (ZLibOut &out, const MapSegGLEx *segs, int numsegs);
|
||||
void WriteNodesZ (ZLibOut &out, const MapNodeEx *nodes, int numnodes);
|
||||
|
||||
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;
|
||||
|
||||
FLevel Level;
|
||||
|
||||
TArray<FNodeBuilder::FPolyStart> PolyStarts;
|
||||
TArray<FNodeBuilder::FPolyStart> PolyAnchors;
|
||||
|
||||
bool Extended;
|
||||
|
||||
FWadReader &Wad;
|
||||
int Lump;
|
||||
};
|
||||
|
||||
#endif //__PROCESSOR_H__
|
20
resource.h
Normal file
20
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
|
103
resource.rc
Normal file
103
resource.rc
Normal file
|
@ -0,0 +1,103 @@
|
|||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "ZDBSP 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 ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
207
tarray.h
Normal file
207
tarray.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
** tarray.h
|
||||
** Templated, automatically resizing array
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2001 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __TARRAY_H__
|
||||
#define __TARRAY_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
template <class T>
|
||||
class TArray
|
||||
{
|
||||
public:
|
||||
TArray ()
|
||||
{
|
||||
Most = 0;
|
||||
Count = 0;
|
||||
Array = NULL;
|
||||
}
|
||||
TArray (int max)
|
||||
{
|
||||
Most = max;
|
||||
Count = 0;
|
||||
Array = new T[max];
|
||||
}
|
||||
TArray (const TArray<T> &other)
|
||||
{
|
||||
DoCopy (other);
|
||||
}
|
||||
TArray<T> &operator= (const TArray<T> &other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
if (Array != NULL)
|
||||
{
|
||||
delete[] Array;
|
||||
}
|
||||
DoCopy (other);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~TArray ()
|
||||
{
|
||||
if (Array)
|
||||
free (Array);
|
||||
}
|
||||
T &operator[] (size_t index) const
|
||||
{
|
||||
return Array[index];
|
||||
}
|
||||
size_t Push (const T &item)
|
||||
{
|
||||
if (Count >= Most)
|
||||
{
|
||||
Most = (Most >= 16) ? Most + Most / 2 : 16;
|
||||
Realloc (Count, Most);
|
||||
}
|
||||
Array[Count] = item;
|
||||
return Count++;
|
||||
}
|
||||
bool Pop (T &item)
|
||||
{
|
||||
if (Count > 0)
|
||||
{
|
||||
item = Array[--Count];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Delete (int index)
|
||||
{
|
||||
if (index < Count-1)
|
||||
memmove (Array + index, Array + index + 1, (Count - index) * sizeof(T));
|
||||
else if (index < Count)
|
||||
Count--;
|
||||
}
|
||||
void Realloc (size_t count, size_t most)
|
||||
{
|
||||
T *copy = new T[most];
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
copy[i] = Array[i];
|
||||
}
|
||||
delete[] Array;
|
||||
Array = copy;
|
||||
}
|
||||
void ShrinkToFit ()
|
||||
{
|
||||
if (Most > Count)
|
||||
{
|
||||
Most = Count;
|
||||
if (Most == 0)
|
||||
{
|
||||
if (Array != NULL)
|
||||
{
|
||||
free (Array);
|
||||
Array = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Realloc (Count, Most);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Grow Array to be large enough to hold amount more entries without
|
||||
// further growing.
|
||||
void Grow (size_t amount)
|
||||
{
|
||||
if (Count + amount > Most)
|
||||
{
|
||||
const size_t choicea = Count + amount;
|
||||
const size_t choiceb = Most + Most/2;
|
||||
Most = (choicea > choiceb ? choicea : choiceb);
|
||||
Realloc (Count, Most);
|
||||
}
|
||||
}
|
||||
// Resize Array so that it has exactly amount entries in use.
|
||||
void Resize (size_t amount)
|
||||
{
|
||||
if (Count < amount)
|
||||
{
|
||||
Grow (amount - Count);
|
||||
}
|
||||
else if (Count > amount)
|
||||
{
|
||||
Count = amount;
|
||||
}
|
||||
}
|
||||
// Reserves amount entries at the end of the array, but does nothing
|
||||
// with them.
|
||||
size_t Reserve (size_t amount)
|
||||
{
|
||||
if (Count + amount > Most)
|
||||
{
|
||||
Grow (amount);
|
||||
}
|
||||
size_t place = Count;
|
||||
Count += amount;
|
||||
return place;
|
||||
}
|
||||
size_t Size () const
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
size_t Max () const
|
||||
{
|
||||
return Most;
|
||||
}
|
||||
void Clear ()
|
||||
{
|
||||
Count = 0;
|
||||
}
|
||||
private:
|
||||
T *Array;
|
||||
size_t Most;
|
||||
size_t Count;
|
||||
|
||||
void DoCopy (const TArray<T> &other)
|
||||
{
|
||||
Most = Count = other.Count;
|
||||
if (Count != 0)
|
||||
{
|
||||
Array = new T[Most];
|
||||
for (size_t i = 0; i < Count; ++i)
|
||||
{
|
||||
Array[i] = other.Array[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Array = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif //__TARRAY_H__
|
202
templates.h
Normal file
202
templates.h
Normal file
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
** templates.h
|
||||
** Some useful template functions
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2001 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __TEMPLATES_H__
|
||||
#define __TEMPLATES_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#endif //__TEMPLATES_H__
|
423
wad.cpp
Normal file
423
wad.cpp
Normal file
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
WAD-handling routines.
|
||||
Copyright (C) 2002,2003 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 exception("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 exception("Input file is not a wad");
|
||||
}
|
||||
|
||||
Header.NumLumps = LONG(Header.NumLumps);
|
||||
Header.Directory = LONG(Header.Directory);
|
||||
|
||||
if (fseek (File, Header.Directory, SEEK_SET))
|
||||
{
|
||||
throw exception("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 = LONG(Lumps[i].FilePos);
|
||||
Lumps[i].Size = LONG(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::IsMap (int index) const
|
||||
{
|
||||
int i, j;
|
||||
|
||||
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 FindLump ("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;
|
||||
|
||||
++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 exception("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 exception("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 head[2];
|
||||
|
||||
head[0] = LONG(Lumps.Size());
|
||||
head[1] = LONG(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 = LONG(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 = LONG(ftell (File));
|
||||
lump.Size = LONG(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 exception(
|
||||
"Failed to write. Check that this directory is writable and\n"
|
||||
"that you have enough free disk space.");
|
||||
}
|
||||
}
|
107
wad.h
Normal file
107
wad.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
#ifndef __WAD_H__
|
||||
#define __WAD_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "zdbsp.h"
|
||||
#include "tarray.h"
|
||||
|
||||
struct WadHeader
|
||||
{
|
||||
char Magic[4];
|
||||
__int32 NumLumps;
|
||||
__int32 Directory;
|
||||
};
|
||||
|
||||
struct WadLump
|
||||
{
|
||||
__int32 FilePos;
|
||||
__int32 Size;
|
||||
char Name[8];
|
||||
};
|
||||
|
||||
class FWadReader
|
||||
{
|
||||
public:
|
||||
FWadReader (const char *filename);
|
||||
~FWadReader ();
|
||||
|
||||
bool IsIWAD () 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 exception("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);
|
||||
|
||||
private:
|
||||
TArray<WadLump> Lumps;
|
||||
FILE *File;
|
||||
|
||||
void SafeWrite (const void *buffer, size_t size);
|
||||
};
|
||||
|
||||
#endif //__WAD_H__
|
29
workdata.h
Normal file
29
workdata.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef __WORKDATA_H__
|
||||
#define __WORKDATA_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "zdbsp.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;
|
||||
};
|
||||
|
||||
|
||||
#endif //__WORKDATA_H__
|
398
zdbsp.dsp
Normal file
398
zdbsp.dsp
Normal file
|
@ -0,0 +1,398 @@
|
|||
# Microsoft Developer Studio Project File - Name="zdbsp" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=zdbsp - Win32 Release
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "zdbsp.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "zdbsp.mak" CFG="zdbsp - Win32 Release"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "zdbsp - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "zdbsp - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "zdbsp - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir ".\Release"
|
||||
# PROP BASE Intermediate_Dir ".\Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir ".\Release"
|
||||
# PROP Intermediate_Dir ".\Release"
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /tlb".\Release\zdbsp.tlb" /win32
|
||||
# ADD MTL /nologo /tlb".\Release\zdbsp.tlb" /win32
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /Ot /Og /Oi /Oy /Ob2 /Gy /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GA /GF /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /Ot /Og /Oi /Oy /Ob2 /Gy /I "zlib" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GA /GF /c
|
||||
# SUBTRACT CPP /YX /Yc /Yu
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ELSEIF "$(CFG)" == "zdbsp - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir ".\Debug"
|
||||
# PROP BASE Intermediate_Dir ".\Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir ".\Debug"
|
||||
# PROP Intermediate_Dir ".\Debug"
|
||||
# PROP Target_Dir ""
|
||||
MTL=midl.exe
|
||||
# ADD BASE MTL /nologo /tlb".\Debug\zdbsp.tlb" /win32
|
||||
# ADD MTL /nologo /tlb".\Debug\zdbsp.tlb" /win32
|
||||
# ADD BASE CPP /nologo /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /GZ /c
|
||||
# ADD CPP /nologo /W3 /GX /ZI /Od /I "zlib" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT BASE LINK32 /pdb:none
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# SUBTRACT LINK32 /pdb:none
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "zdbsp - Win32 Release"
|
||||
# Name "zdbsp - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Group "Reject(ed)"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Unused\rejectbuilder.cpp
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Unused\rejectbuilder.h
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Unused\vis.cpp
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Unused\visflow.cpp
|
||||
# PROP Exclude_From_Build 1
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\blockmapbuilder.cpp
|
||||
DEP_CPP_BLOCK=\
|
||||
".\blockmapbuilder.h"\
|
||||
".\doomdata.h"\
|
||||
".\tarray.h"\
|
||||
".\templates.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\getopt.c
|
||||
DEP_CPP_GETOP=\
|
||||
".\getopt.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=getopt1.c
|
||||
DEP_CPP_GETOPT=\
|
||||
".\getopt.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\main.cpp
|
||||
DEP_CPP_MAIN_=\
|
||||
".\blockmapbuilder.h"\
|
||||
".\doomdata.h"\
|
||||
".\getopt.h"\
|
||||
".\nodebuild.h"\
|
||||
".\processor.h"\
|
||||
".\tarray.h"\
|
||||
".\wad.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nodebuild.cpp
|
||||
DEP_CPP_NODEB=\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\tarray.h"\
|
||||
".\templates.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=nodebuild_events.cpp
|
||||
DEP_CPP_NODEBU=\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\tarray.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=nodebuild_extract.cpp
|
||||
DEP_CPP_NODEBUI=\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\tarray.h"\
|
||||
".\templates.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=nodebuild_gl.cpp
|
||||
DEP_CPP_NODEBUIL=\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\tarray.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=nodebuild_utility.cpp
|
||||
DEP_CPP_NODEBUILD=\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\tarray.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\processor.cpp
|
||||
DEP_CPP_PROCE=\
|
||||
".\blockmapbuilder.h"\
|
||||
".\doomdata.h"\
|
||||
".\nodebuild.h"\
|
||||
".\processor.h"\
|
||||
".\tarray.h"\
|
||||
".\wad.h"\
|
||||
".\workdata.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\view.cpp
|
||||
DEP_CPP_VIEW_=\
|
||||
".\doomdata.h"\
|
||||
".\tarray.h"\
|
||||
".\templates.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wad.cpp
|
||||
DEP_CPP_WAD_C=\
|
||||
".\tarray.h"\
|
||||
".\wad.h"\
|
||||
".\zdbsp.h"\
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\blockmapbuilder.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\doomdata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=getopt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nodebuild.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\processor.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tarray.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\templates.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wad.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\workdata.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zdbsp.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Resource Files"
|
||||
|
||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\resource.rc
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "zlib"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\adler32.c
|
||||
DEP_CPP_ADLER=\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\compress.c
|
||||
DEP_CPP_COMPR=\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\crc32.c
|
||||
DEP_CPP_CRC32=\
|
||||
".\zlib\crc32.h"\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
".\zlib\zutil.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\crc32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\deflate.c
|
||||
DEP_CPP_DEFLA=\
|
||||
".\zlib\deflate.h"\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
".\zlib\zutil.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\deflate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\trees.c
|
||||
DEP_CPP_TREES=\
|
||||
".\zlib\deflate.h"\
|
||||
".\zlib\trees.h"\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
".\zlib\zutil.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\trees.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\zconf.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\zlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\zutil.c
|
||||
DEP_CPP_ZUTIL=\
|
||||
".\zlib\zconf.h"\
|
||||
".\zlib\zlib.h"\
|
||||
".\zlib\zutil.h"\
|
||||
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib\zutil.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zdbsp.html
|
||||
# End Source File
|
||||
# End Target
|
||||
# End Project
|
29
zdbsp.dsw
Normal file
29
zdbsp.dsw
Normal file
|
@ -0,0 +1,29 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "zdbsp"=zdbsp.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
134
zdbsp.h
Normal file
134
zdbsp.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
#ifndef __ZDBSP_H__
|
||||
#define __ZDBSP_H__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <exception>
|
||||
|
||||
#define ZDBSP_VERSION "1.5"
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
|
||||
#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;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned __int32 angle_t;
|
||||
|
||||
angle_t PointToAngle (fixed_t x, fixed_t y);
|
||||
|
||||
static const WORD NO_INDEX = 0xffff;
|
||||
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, ...);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#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)
|
||||
|
||||
#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));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define SHORT(x) (x)
|
||||
#define LONG(x) (x)
|
||||
|
||||
#endif //__ZDBSP_H__
|
476
zdbsp.html
Normal file
476
zdbsp.html
Normal file
|
@ -0,0 +1,476 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>ZDBSP Documentation</TITLE>
|
||||
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
|
||||
<META NAME="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<H1>About ZDBSP</H1>
|
||||
<P>ZDBSP is a stand-alone version of ZDoom's internal node builder. This node
|
||||
builder was written with two design goals in mind:</P>
|
||||
<OL>
|
||||
<LI>
|
||||
It must be fast. The original node builder was just going to be used to fix map
|
||||
errors in ZDoom. After adding GL nodes support, ZDoomGL also started using it
|
||||
as a preprocessing step for any maps without existing GL nodes. In both
|
||||
cases, the node builder needed to be quick in order to minimize the
|
||||
time the user was forced to wait before playing a map.
|
||||
<LI>
|
||||
Polyobject bleeding must be minimized. The node builder was tested with the
|
||||
standard Hexen maps and several user maps, and it has been able to prevent
|
||||
bleeding on all properly-formed maps. (Note that it is impossible to prevent
|
||||
polyobject bleeding in all circumstances. See the polyobjects section below for
|
||||
rules you should follow for best results.)</LI></OL>
|
||||
<h1>License</h1>
|
||||
<p>This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public
|
||||
License</a> as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.</p>
|
||||
<p>This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.</p>
|
||||
<p>You can also find a copy of the license as the file COPYING in the source
|
||||
distribution.</p>
|
||||
<H1>Using ZDBSP with WadAuthor</H1>
|
||||
<P>First, copy zdbsp.exe to your WadAuthor directory. Then start WadAuthor and
|
||||
choose "Options..." from its Tools menu. Select the "Files" tab and choose
|
||||
"External" for Node Building. This activates the Command text box so that you
|
||||
can type text into it. Copy and paste any of the following into it based on
|
||||
what you want to do.</P>
|
||||
<P>Create a map that can be played with Doom or any source port:</P>
|
||||
<BLOCKQUOTE dir="ltr" style="MARGIN-RIGHT: 0px">
|
||||
<P>zdbsp -R -m$_Mapname $_Wadfile -o$_Wadfile</P>
|
||||
</BLOCKQUOTE>
|
||||
<P dir="ltr">Create a map that will only be played with ZDoom. This will be
|
||||
ZDoom-only because it creates a zero-length REJECT lump. ZDoom is smart enough
|
||||
to know that a zero-length REJECT lump is the same thing as a REJECT lump
|
||||
filled with zeros, so you can save space:</P>
|
||||
<BLOCKQUOTE dir="ltr" style="MARGIN-RIGHT: 0px">
|
||||
<P dir="ltr">zdbsp -r -m$_Mapname $_Wadfile -o$_Wadfile</P>
|
||||
</BLOCKQUOTE>
|
||||
<P dir="ltr">Create a map with both regular and GL nodes so that ZDoomGL does not
|
||||
need to build GL nodes:</P>
|
||||
<BLOCKQUOTE dir="ltr" style="MARGIN-RIGHT: 0px">
|
||||
<P dir="ltr">zdbsp -rg -m$_Mapname $_Wadfile -o$_Wadfile</P>
|
||||
</BLOCKQUOTE>
|
||||
<H1 dir="ltr">ZDBSP command line options</H1>
|
||||
<P dir="ltr">ZDBSP supports several command line options to affect its behavior. If
|
||||
you forget what they are, you can view a quick summary of them by running ZDBSP
|
||||
without any options. They are also listed below in more detail than the listing
|
||||
ZDBSP provides. Note that these options are case-sensitive, so -r is not the
|
||||
same thing as -R. You can use either the long form of an option or the short
|
||||
form depending on your preference.</P>
|
||||
<dl>
|
||||
<dt>--help</dt>
|
||||
<dd>
|
||||
Displays a summary of all ZDBSP's command line options, as if you had run ZDBSP
|
||||
without any options.</dd>
|
||||
<dt>--version or -V</dt>
|
||||
<dd>
|
||||
Displays ZDBSP's version number.</dd>
|
||||
<dt>--map=<i>MAP</i> or -m<i>MAP</i></dt>
|
||||
<dd>
|
||||
When you use this option, ZDBSP will only build the nodes for one map in a wad
|
||||
instead of rebuilding the nodes for every map contained in the wad. <i>MAP</i> should
|
||||
be the map's full name (e.g. MAP01 or E1M1)</dd>
|
||||
<dt>--output=<i>FILE</i> or -o<i>FILE</i></dt>
|
||||
<dd>
|
||||
Normally, ZDBSP creates a new wad named tmp.wad. You can use this option to
|
||||
make it write to a different file instead. In the case of WadAuthor, this is
|
||||
used to make ZDBSP overwrite the original file with the new one, because that
|
||||
is what WadAuthor expects the nodebuilder to do.</dd>
|
||||
<dt>--no-prune or -q</dt>
|
||||
<dd>
|
||||
When you use this option, ZDBSP will not remove unused sidedefs or sectors from
|
||||
a map. ZDBSP will always remove 0-length linedefs from a map even when you use
|
||||
this option because it is possible for them to make the game crash under
|
||||
certain circumstances. Moreover, ZDoom will itself remove 0-length linedefs and
|
||||
rebuild the nodes if it finds any.</dd>
|
||||
<dt>--no-nodes or -N</dt>
|
||||
<dd>
|
||||
This option causes ZDBSP to take the node information from the old wad file and
|
||||
write it to the new wad file. I can't think of any reason why you would want to
|
||||
do this, but it is provided as an option nonetheless.</dd>
|
||||
<dt>--gl or -g</dt>
|
||||
<dd>
|
||||
This option causes ZDBSP to build two sets of nodes for a map: One set of
|
||||
regular nodes and one set of GL nodes. Because ZDBSP is doing twice the work,
|
||||
it will take twice as long to finish.</dd>
|
||||
<dt>--gl-matching or -G</dt>
|
||||
<dd>
|
||||
Like the previous option, this one will also make ZDBSP generate GL nodes.
|
||||
However, it will only build one set of nodes and then strip the extra GL
|
||||
information from them to create the normal nodes. Because of this, it is faster
|
||||
than the previous option when you want to create GL nodes, but the normal nodes
|
||||
will generally be less efficient because they were created from the GL nodes.</dd>
|
||||
<dt>--compress or -z</dt>
|
||||
<dd>Compresses the node information. Compressed nodes take up less space than
|
||||
uncompressed nodes, and they are also the only way to save nodes with more than 65535 segs.
|
||||
If GL nodes are built, they will be compressed as well.</dd>
|
||||
<dt>--compress-normal or -Z</dt>
|
||||
<dd>This is exactly like the previous option, except GL nodes will not be compressed.</dd>
|
||||
<dt>--empty-blockmap or -b</dt>
|
||||
<dd>
|
||||
This option writes a zero-length BLOCKMAP to the wad. As of this writing, ZDoom
|
||||
is the only port that will detect this and build the BLOCKMAP itself.</dd>
|
||||
<dt>--empty-reject or -r</dt>
|
||||
<dd>
|
||||
When this option is used, ZDBSP will write a zero-length REJECT to the wad. As
|
||||
of this writing, ZDoom is the only port that supports this. A zero-length
|
||||
REJECT is the same thing as a reject filled with zeros. Since ZDBSP does not
|
||||
generate a REJECT table, and the usefulness of having a REJECT is questionable,
|
||||
you should always use this option if you intend for the map to be played solely
|
||||
with ZDoom.</dd>
|
||||
<dt>--zero-reject or -R</dt>
|
||||
<dd>
|
||||
This option is similar to the previous one, except ZDBSP will actually write
|
||||
out a full-sized REJECT lump filled with zeros. If you play with ZDoom, this is
|
||||
just wasted space, but other ports and Doom itself require a full-sized REJECT
|
||||
lump to work.</dd>
|
||||
<dt>--no-reject or -E</dt>
|
||||
<dd>
|
||||
This option makes ZDBSP copy the REJECT lump from the old wad to the new wad
|
||||
unchanged. However, if it detects that the old REJECT is the wrong size for the
|
||||
number of sectors in the map, it will be removed as if you had used the
|
||||
--empty-reject option.</dd>
|
||||
<dt>--no-polyobjs or -P</dt>
|
||||
<dd>
|
||||
This option disables ZDBSP's polyobject detection code. If you are building
|
||||
nodes for a map without polyobjects, you might be able to save a fraction of a
|
||||
second from the build time by using this option, but there is generally no
|
||||
reason to use it.</dd>
|
||||
<dt>--no-timing or -t</dt>
|
||||
<dd>
|
||||
If you don't care how long it takes to build nodes, use this option and ZDBSP
|
||||
won't tell you.</dd>
|
||||
<dt>--warn or -w</dt>
|
||||
<dd>
|
||||
Displays extra warning messages that ZDBSP might generate while building GL
|
||||
nodes. The nodes will still be usable if warnings occur, and warnings are not
|
||||
unlikely. If you have strange display problems with GL nodes, turning on the
|
||||
warning messages may help you locate the problem.</dd>
|
||||
<dt>--partition=<i>NNN</i> or -p<i>NNN</i></dt>
|
||||
<dd>
|
||||
This option controls the maximum number of segs that will be considered for
|
||||
splitters at each node. The default is 64. By increasing it, you might be able
|
||||
to generate "better" nodes, but you get diminishing returns the higher you make
|
||||
it. High values are also slower than low ones.</dd>
|
||||
<dt>--split-cost=<i>NNN</i> or -s<i>NNN</i></dt>
|
||||
<dd>
|
||||
This option adjusts how hard ZDBSP tries to avoid splitting segs. The default
|
||||
value is 8. By increasing this, ZDBSP will try harder to avoid splitting segs.
|
||||
If you decrease it, ZDBSP will split segs more frequently. More splits mean the
|
||||
BSP tree will usually be more balanced, but it will also take up more room.</dd>
|
||||
<dt>--diagonal-cost=<i>NNN</i> or -d<i>NNN</i></dt>
|
||||
<dd>
|
||||
This option controls how hard ZDBSP tries to avoid using diagonal splitters.
|
||||
The default value is 16. A higher value means that diagonal splitters will be
|
||||
more likely to be used. This can sometimes help to reduce the number of segs in
|
||||
a map. The reason avoiding diagonal splitters is important is because normal
|
||||
nodes do not store any fractional information for the vertices that segs use,
|
||||
so you are more likely to see slime trails with diagonal splitters than with
|
||||
horizontal or vertical splitters.</dd>
|
||||
<dt>--view or -v</dt>
|
||||
<dd>
|
||||
Under Windows, this displays a viewer that will let you inspect a map's
|
||||
subsectors, nodes, and REJECT. To scroll the map around, drag it with your
|
||||
right mouse button. The viewer was created to assist with debugging with the GL
|
||||
nodes. It is not very user-friendly nor is it bug-free. In fact, if you try to
|
||||
build nodes for more than one map with this option, there is a good chance
|
||||
ZDBSP will crash.</dd>
|
||||
</dl>
|
||||
<h1>Polyobjects</h1>
|
||||
<p>One of ZDBSP's most important features is that it tries very hard to avoid
|
||||
polyobject bleeding. To make this feature work, however, you must design your
|
||||
maps properly. You do this be ensuring that your polyobjects are always shown
|
||||
inside a <i>convex</i> sector. This is referring to the area where the
|
||||
polyobjects appear in the game, not where they appear in an editor. If you do
|
||||
not know what convex means, think of triangles, squares and circles. They are
|
||||
all convex. If you have a sector shaped like the letter C, that is not convex.</p>
|
||||
<p>Ironically, an example of what <i>not</i> to do is in Hexen's MAP01. The
|
||||
polyobject doors at the very start of that map do not appear in a convex area.
|
||||
ZDBSP has been tuned so that they will display properly with the default
|
||||
options, but you should not count on this for your own maps.</p>
|
||||
<p>If ZDBSP has to split a linedef around a polyobject's display area, it will
|
||||
print a message indicating where this happened so that you can inspect the area
|
||||
and fix it. For example, when you use ZDBSP on hexen.wad, it outputs these
|
||||
warnings for MAP01:</p>
|
||||
<pre class="code"> Split seg 929 (-1176,1312)-(-1088,1312) of sector 265 on line 572
|
||||
Split seg 931 (-1088,1312)-(-1000,1312) of sector 265 on line 573</pre>
|
||||
<p>The important pieces of information here are the coordinates of the segs that
|
||||
were split and the lines those segs were made from. In this case, both lines
|
||||
572 and 573 were split. Because they surround a polyobject's display area,
|
||||
ideally they should not be split, so you need to look at the map in an editor
|
||||
to determine what made them split. This happens because the area is not convex,
|
||||
so you need to look for a line in the same "loop" that, if you made it longer,
|
||||
could cross the line that was split. In this example, lines 575 and 579 are
|
||||
responsible for splitting line 572, and lines 576 and 578 are responsible for
|
||||
splitting line 573. You can fix the error by reworking the area so that it is
|
||||
convex, either by moving lines 575, 579, 576, and 578, or by adding additional
|
||||
lines to separate each half into four convex pieces.
|
||||
</p>
|
||||
<p>Below are some illustrations. The areas where the two polyobjects appear have
|
||||
been highlighted.</p>
|
||||
<blockquote>
|
||||
<p align="center">This first image shows the area as it appears in hexen.wad,
|
||||
unmodified. Note that neither side is convex, so ZDBSP will need to split each
|
||||
side into two subsectors. The extra subsectors have been highlighted in a
|
||||
brighter color to illustrate how ZDBSP splits them.<br />
|
||||
<img src="poly_bad.png" alt="The Original Area"></p>
|
||||
<p align="center">In the next image, the lines have been moved to make each side
|
||||
convex.<br />
|
||||
<img src="poly_mov.png" alt="Convex Areas made by Moving Lines">
|
||||
</p>
|
||||
<p align="center">In the final image, new two-sided lines have been added to make
|
||||
each polyobject's display area rectangular. Unlike the line-moving method
|
||||
above, this does not alter the area's appearance. Notice that this looks a lot
|
||||
like the way ZDBSP split them in the first image. The difference is that by
|
||||
adding the extra lines yourself, you have control over how the split is done
|
||||
and ZDBSP does not need to guess about the best way to make the area convex.<br />
|
||||
<img src="poly_new.png" alt="Convex Areas made by Adding Lines"></p>
|
||||
</blockquote>
|
||||
<p>Unfortunately, if you use WadAuthor, ZDBSP's output window will not normally
|
||||
appear long enough for you to actually read it. You can get around this by
|
||||
adding the -v option to the zdbsp command line that WadAuthor uses (see the
|
||||
Using ZDBSP with WadAuthor section). Then its output will stay around until you
|
||||
close the ZDBSP viewer.</p>
|
||||
<h1>Compressed Nodes</h1>
|
||||
<p>The following information describes the format used to store compressed nodes.
|
||||
If you are just a regular user, you can skip this section.</p>
|
||||
<p>Compressed nodes contain all the same information as regular nodes but are
|
||||
stored in a single lump and compressed as a zlib data stream. They also support
|
||||
more than 65535 segs and vertices by storing them using four bytes instead of
|
||||
two.</p>
|
||||
<p>The first four bytes of the compressed nodes are a four-character (uncompressed)
|
||||
signature. This can be either 'ZNOD' for regular nodes or 'ZGLN' for GL nodes.
|
||||
Following the signature is the zlib data stream. For a description of its
|
||||
format, see the zlib documentation. When you decompress it, the following
|
||||
information is obtained in this order:</p>
|
||||
<ol>
|
||||
<li>
|
||||
Vertex information</li>
|
||||
<li>
|
||||
Subsector information</li>
|
||||
<li>
|
||||
Segs information</li>
|
||||
<li>
|
||||
Nodes information</li></ol>
|
||||
<h2>Types</h2>
|
||||
<p>The following sections use these types:</p>
|
||||
<dl>
|
||||
<dt><b>BYTE</b></dt><dd>A single unsigned byte. The number can be in the range [0,
|
||||
255].</dd>
|
||||
<dt><b>WORD</b></dt><dd>An unsigned integer stored in two bytes. The number can be
|
||||
in the range [0, 65535].</dd>
|
||||
<dt><b>SWORD</b></dt><dd>A signed integer stored in two bytes. The number can be
|
||||
in the range [-32768, 32767].</dd>
|
||||
<dt><b>DWORD</b></dt><dd>An unsigned integer stored in four bytes. The number can
|
||||
be in the range [0, 4294967295].</dd>
|
||||
<dt><b>FIXED</b></dt><dd>A signed 16.16 fixed-point number stored in four bytes. The
|
||||
most-significant two bytes store the integer part of the number, and the
|
||||
least-significant two bytes store the fractional part of the number. The number can
|
||||
be in the approximate range [-32768.99998, 32767.99998].</dd>
|
||||
</dl>
|
||||
<p>All multi-byte numbers are stored with their least significant byte first (i.e.
|
||||
little-endian).</p>
|
||||
<h2>Vertex information</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>OrgVerts</i></td>
|
||||
<td>Number of vertices used from the VERTEXES lump</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>NewVerts</i></td>
|
||||
<td>Number of additional vertices that follow</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" bgcolor="#dddddd">Repeat <i>NewVerts</i> times:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FIXED</td>
|
||||
<td><i>X</i></td>
|
||||
<td>X-Coordinate</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FIXED</td>
|
||||
<td><i>Y</i></td>
|
||||
<td>Y-Coordinate</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>These are all the <i>additional</i> vertices that the segs use. Unlike normal
|
||||
nodes, extra vertices are not added to the VERTEXES lump. When determining
|
||||
which vertex <i>v</i> a seg uses, if <i>v</i> < <i>OrgVerts</i>, then <i>v</i> is
|
||||
a vertex in the VERTEXES lump. Otherwise, when <i>v</i> >= <i>OrgVerts</i>, <i>v</i>
|
||||
- <i>OrgVerts</i> is the index of a vertex stored here.</p>
|
||||
<p>Like version 2 GL nodes, the vertices stored here are represented as 16.16 fixed
|
||||
point numbers in order to maintain the full precision of the Doom engine.</p>
|
||||
<h2>Subsector information</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>NumSubsectors</i></td>
|
||||
<td>Number of subsectors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" bgcolor="#dddddd">Repeat <i>NumSubsectors</i> times:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td>NumSegs</td>
|
||||
<td>Number of segs for this subsector</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Unlike normal nodes, the first seg in each subsector is not stored. This can be
|
||||
inferred by the ordering of the subsectors. The first subsector always starts
|
||||
at seg 0, and each following subsector begins with the seg immediately after
|
||||
the previous subsector's last seg.</p>
|
||||
<h2>Segs information</h2>
|
||||
<p>The specific layout for this section depends on whether the data stream
|
||||
represents normal nodes or GL nodes. In each case, the segs are stored in an 11
|
||||
byte structure, but their contents differ slightly. <i>There is no padding to make
|
||||
these align to DWORD boundaries.</i>
|
||||
</p>
|
||||
<h3>Normal nodes ('ZNOD' signature)</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>NumSegs</i></td>
|
||||
<td>Number of segs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" bgcolor="#dddddd">Repeat <i>NumSegs</i> times:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>v1</i></td>
|
||||
<td>Seg's first vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>v2</i></td>
|
||||
<td>Seg's second vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WORD</td>
|
||||
<td><i>line</i></td>
|
||||
<td>The linedef this seg came from</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BYTE</td>
|
||||
<td><i>side</i></td>
|
||||
<td>The linedef's side this seg came from (0=front, 1=back)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Note that unlike uncompressed nodes, the seg's angle and offset are not
|
||||
included. ZDoom does not need this information, and other ports that wish to
|
||||
support compressed nodes can recompute them trivially.</p>
|
||||
<h3>GL nodes ('ZGLN' signature)</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>NumSegs</i></td>
|
||||
<td>Number of segs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" bgcolor="#dddddd">Repeat <i>NumSegs</i> times:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>v1</i></td>
|
||||
<td>Seg's first vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>partner</i></td>
|
||||
<td>Seg's partner seg (0xFFFFFFFF if none)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>WORD</td>
|
||||
<td><i>line</i></td>
|
||||
<td>The linedef this seg came from (0xFFFFFFFF if none)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BYTE</td>
|
||||
<td><i>side</i></td>
|
||||
<td>The linedef's side this seg came from (0=front, 1=back) (ignored if no line)</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Unlike standard GL nodes, each seg's second vertex is not stored. This is
|
||||
because GL subsectors must form a closed area. In other words, one seg's second
|
||||
vertex is the same as the next seg's first vertex. The subsector information
|
||||
contains everything you need to know to close each area and start a new one.</p>
|
||||
<p>Example: Suppose you have not read any segs yet, and the first subsector has
|
||||
four segs. Therefore, the second vertex for the first four segs can be
|
||||
determined to be:</p>
|
||||
<blockquote><table>
|
||||
<tr>
|
||||
<td>Seg 0</td>
|
||||
<td>Second vertex is Seg 1's first vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seg 1</td>
|
||||
<td>Second vertex is Seg 2's first vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seg 2</td>
|
||||
<td>Second vertex is Seg 3's first vertex</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Seg 3</td>
|
||||
<td>Second vertex is Seg 0's first vertex (because this is the last seg in the
|
||||
subsector)</td>
|
||||
</tr>
|
||||
</table>
|
||||
</blockquote>
|
||||
<p>So for each subsector, all but the last seg's second vertex will be the same as
|
||||
the next seg's first vertex. The last seg's second vertex will be the same as
|
||||
the first seg's first vertex.</p>
|
||||
<h2>Node information</h2>
|
||||
<p>This is really no different from standard nodes.</p>
|
||||
<table>
|
||||
<tr>
|
||||
<td>DWORD</td>
|
||||
<td><i>NumNodes</i></td>
|
||||
<td>Number of nodes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3" bgcolor="#dddddd">Repeat <i>NumNodes</i> times:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4 SWORDs</td>
|
||||
<td><i>X</i>, <i>Y</i>, <i>dX</i>, <i>dY</i></td>
|
||||
<td>Splitter for this node</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4 SWORDs</td>
|
||||
<td><i>Top</i>, <i>Bottom</i>, <i>Left</i>, <i>Right</i></td>
|
||||
<td>Bounding box for <i>Child0</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4 SWORDs</td>
|
||||
<td><i>Top</i>, <i>Bottom</i>, <i>Left</i>, <i>Right</i></td>
|
||||
<td>Bounding box for <i>Child1</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2 DWORDs</td>
|
||||
<td><i>Child0</i>, <i>Child1</i></td>
|
||||
<td>References to child nodes or subsectors</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>As with standard nodes, a child's high bit is set to indicate that it is a
|
||||
subsector and cleared to indicate that it is another node. Just remember that
|
||||
the child references are stored using four bytes each instead of two.</p>
|
||||
<h2>Compressed node storage</h2>
|
||||
<p>Normal nodes (signature 'ZNOD') are stored in a map's NODES lump. Bear in mind
|
||||
that compressed nodes are contained entirely within a single lump rather than
|
||||
in three separate lumps.</p>
|
||||
<p>GL nodes (signature 'ZGLN') are stored in a map's SSECTORS lump. Unlike regular
|
||||
GL nodes, no new lumps are created for compressed GL nodes.</p>
|
||||
<p>The SEGS lump is left unused and should be written with a length of 0. I may
|
||||
find some way to "hijack" this lump in the future, so programs that read
|
||||
compressed nodes must not assume that if the SEGS lump is non-empty, then
|
||||
compressed nodes are not used.</p>
|
||||
</BODY>
|
||||
</HTML>
|
21
zdbsp.sln
Normal file
21
zdbsp.sln
Normal file
|
@ -0,0 +1,21 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zdbsp", "zdbsp.vcproj", "{3C32111E-76E8-47C9-95A6-A103C861F45F}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{3C32111E-76E8-47C9-95A6-A103C861F45F}.Debug.ActiveCfg = Debug|Win32
|
||||
{3C32111E-76E8-47C9-95A6-A103C861F45F}.Debug.Build.0 = Debug|Win32
|
||||
{3C32111E-76E8-47C9-95A6-A103C861F45F}.Release.ActiveCfg = Release|Win32
|
||||
{3C32111E-76E8-47C9-95A6-A103C861F45F}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
334
zdbsp.vcproj
Normal file
334
zdbsp.vcproj
Normal file
|
@ -0,0 +1,334 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="zdbsp"
|
||||
SccProjectName=""
|
||||
SccLocalPath="">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="4"
|
||||
GlobalOptimizations="TRUE"
|
||||
InlineFunctionExpansion="2"
|
||||
EnableIntrinsicFunctions="TRUE"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="0"
|
||||
OptimizeForWindowsApplication="TRUE"
|
||||
AdditionalIncludeDirectories="zlib"
|
||||
PreprocessorDefinitions="WIN32,NDEBUG,_CONSOLE"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\Release/zdbsp.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
OutputFile=".\Release/zdbsp.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Release/zdbsp.pdb"
|
||||
SubSystem="1"
|
||||
OptimizeForWindows98="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Release/zdbsp.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="zlib"
|
||||
PreprocessorDefinitions="WIN32,_DEBUG,_CONSOLE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\Debug/zdbsp.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalOptions="/MACHINE:I386"
|
||||
OutputFile=".\Debug/zdbsp.exe"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\Debug/zdbsp.pdb"
|
||||
SubSystem="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\Debug/zdbsp.tlb"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<File
|
||||
RelativePath=".\blockmapbuilder.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\getopt.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="getopt1.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\main.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nodebuild.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="nodebuild_events.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="nodebuild_extract.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="nodebuild_gl.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="nodebuild_utility.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\processor.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\view.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wad.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Reject(ed)"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\Unused\rejectbuilder.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Unused\rejectbuilder.h">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Unused\vis.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Unused\visflow.cpp">
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="TRUE">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl">
|
||||
<File
|
||||
RelativePath=".\blockmapbuilder.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\doomdata.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="getopt.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\nodebuild.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\processor.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tarray.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\templates.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\wad.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\workdata.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zdbsp.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
|
||||
<File
|
||||
RelativePath=".\resource.rc">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="zlib"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\zlib\adler32.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\compress.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\crc32.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\crc32.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\deflate.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\deflate.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\trees.c">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\trees.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zconf.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zlib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zlib\zutil.c">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\zdbsp.html">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
1
zipbin.bat
Normal file
1
zipbin.bat
Normal file
|
@ -0,0 +1 @@
|
|||
kzip %1 release\zdbsp.exe zdbsp.html *.png
|
4
zipsrc.bat
Normal file
4
zipsrc.bat
Normal file
|
@ -0,0 +1,4 @@
|
|||
zip -9 %1 COPYING *.cpp *.h *.c *.rc *.ds? *.sln *.vcproj unused/* zlib/*
|
||||
kzip b%1 COPYING *.cpp *.h *.c *.rc *.ds? *.sln *.vcproj
|
||||
zipmix %1 b%1
|
||||
del b%1
|
74
zlib/adler32.c
Normal file
74
zlib/adler32.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2003 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521UL /* 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) {s1 += buf[i]; s2 += s1;}
|
||||
#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);
|
||||
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int k;
|
||||
|
||||
if (buf == Z_NULL) return 1L;
|
||||
|
||||
while (len > 0) {
|
||||
k = len < NMAX ? (int)len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16) {
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0) do {
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
} while (--k);
|
||||
MOD(s1);
|
||||
MOD(s2);
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
79
zlib/compress.c
Normal file
79
zlib/compress.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2002 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) + 11;
|
||||
}
|
311
zlib/crc32.c
Normal file
311
zlib/crc32.c
Normal file
|
@ -0,0 +1,311 @@
|
|||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2003 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 about a factor
|
||||
* of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#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
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
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 */
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long 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()
|
||||
{
|
||||
unsigned long c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)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] = REV(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] = REV(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
|
||||
#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 unsigned long 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 unsigned long FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", 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 unsigned long FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty) make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long 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;
|
||||
unsigned 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)) {
|
||||
u4 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 u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 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 u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 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)(REV(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
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 unsigned long 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
|
||||
}
|
||||
};
|
1502
zlib/deflate.c
Normal file
1502
zlib/deflate.c
Normal file
File diff suppressed because it is too large
Load diff
326
zlib/deflate.h
Normal file
326
zlib/deflate.h
Normal file
|
@ -0,0 +1,326 @@
|
|||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-2002 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 INIT_STATE 42
|
||||
#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 */
|
||||
int pending; /* nb of bytes in the pending buffer */
|
||||
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
|
||||
Byte data_type; /* UNKNOWN, BINARY or ASCII */
|
||||
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 supress 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 */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#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.
|
||||
*/
|
||||
|
||||
} 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.
|
||||
*/
|
||||
|
||||
/* in trees.c */
|
||||
void _tr_init OF((deflate_state *s));
|
||||
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
void _tr_align OF((deflate_state *s));
|
||||
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
|
||||
#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 _length_code[];
|
||||
extern uch _dist_code[];
|
||||
#else
|
||||
extern const uch _length_code[];
|
||||
extern const uch _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 */
|
1215
zlib/trees.c
Normal file
1215
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 _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 _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
|
||||
};
|
||||
|
323
zlib/zconf.h
Normal file
323
zlib/zconf.h
Normal file
|
@ -0,0 +1,323 @@
|
|||
/* zconf.h -- configuration of the zlib compression library
|
||||
* Copyright (C) 1995-2003 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.
|
||||
*/
|
||||
#ifdef Z_PREFIX
|
||||
# define deflateInit_ z_deflateInit_
|
||||
# define deflate z_deflate
|
||||
# define deflateEnd z_deflateEnd
|
||||
# define inflateInit_ z_inflateInit_
|
||||
# define inflate z_inflate
|
||||
# define inflateEnd z_inflateEnd
|
||||
# define deflateInit2_ z_deflateInit2_
|
||||
# define deflateSetDictionary z_deflateSetDictionary
|
||||
# define deflateCopy z_deflateCopy
|
||||
# define deflateReset z_deflateReset
|
||||
# define deflatePrime z_deflatePrime
|
||||
# define deflateParams z_deflateParams
|
||||
# define deflateBound z_deflateBound
|
||||
# define inflateInit2_ z_inflateInit2_
|
||||
# define inflateSetDictionary z_inflateSetDictionary
|
||||
# define inflateSync z_inflateSync
|
||||
# define inflateSyncPoint z_inflateSyncPoint
|
||||
# define inflateCopy z_inflateCopy
|
||||
# define inflateReset z_inflateReset
|
||||
# define compress z_compress
|
||||
# define compress2 z_compress2
|
||||
# define compressBound z_compressBound
|
||||
# define uncompress z_uncompress
|
||||
# define adler32 z_adler32
|
||||
# define crc32 z_crc32
|
||||
# define get_crc_table z_get_crc_table
|
||||
|
||||
# define Byte z_Byte
|
||||
# define uInt z_uInt
|
||||
# define uLong z_uLong
|
||||
# define Bytef z_Bytef
|
||||
# define charf z_charf
|
||||
# define intf z_intf
|
||||
# define uIntf z_uIntf
|
||||
# define uLongf z_uLongf
|
||||
# define voidpf z_voidpf
|
||||
# define voidp z_voidp
|
||||
#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__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#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
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
|
||||
# include <sys/types.h> /* for off_t */
|
||||
# include <unistd.h> /* for SEEK_* and off_t */
|
||||
# ifdef VMS
|
||||
# include <unixio.h> /* for off_t */
|
||||
# endif
|
||||
# define z_off_t off_t
|
||||
#endif
|
||||
#ifndef SEEK_SET
|
||||
# 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(__OS400__)
|
||||
#define NO_vsnprintf
|
||||
#endif
|
||||
|
||||
#if defined(__MVS__)
|
||||
# define NO_vsnprintf
|
||||
# ifdef FAR
|
||||
# undef FAR
|
||||
# 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 */
|
1200
zlib/zlib.h
Normal file
1200
zlib/zlib.h
Normal file
File diff suppressed because it is too large
Load diff
319
zlib/zutil.c
Normal file
319
zlib/zutil.c
Normal file
|
@ -0,0 +1,319 @@
|
|||
/* zutil.c -- target dependent utility functions for the compression library
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
#ifndef NO_DUMMY_DECL
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
#endif
|
||||
|
||||
#ifndef STDC
|
||||
extern void exit OF((int));
|
||||
#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 (sizeof(uInt)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1; break;
|
||||
case 8: flags += 2; break;
|
||||
default: flags += 3;
|
||||
}
|
||||
switch (sizeof(uLong)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 2; break;
|
||||
case 8: flags += 2 << 2; break;
|
||||
default: flags += 3 << 2;
|
||||
}
|
||||
switch (sizeof(voidpf)) {
|
||||
case 2: break;
|
||||
case 4: flags += 1 << 4; break;
|
||||
case 8: flags += 2 << 4; break;
|
||||
default: flags += 3 << 4;
|
||||
}
|
||||
switch (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 += 1 << 16;
|
||||
#endif
|
||||
#ifdef NO_GZIP
|
||||
flags += 1 << 17;
|
||||
#endif
|
||||
#ifdef PKZIP_BUG_WORKAROUND
|
||||
flags += 1 << 20;
|
||||
#endif
|
||||
#ifdef FASTEST
|
||||
flags += 1 << 21;
|
||||
#endif
|
||||
#ifdef STDC
|
||||
# ifdef NO_vsnprintf
|
||||
flags += 1 << 25;
|
||||
# ifdef HAS_vsprintf_void
|
||||
flags += 1 << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_vsnprintf_void
|
||||
flags += 1 << 26;
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
flags += 1 << 24;
|
||||
# ifdef NO_snprintf
|
||||
flags += 1 << 25;
|
||||
# ifdef HAS_sprintf_void
|
||||
flags += 1 << 26;
|
||||
# endif
|
||||
# else
|
||||
# ifdef HAS_snprintf_void
|
||||
flags += 1 << 26;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
return flags;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
# ifndef verbose
|
||||
# define verbose 0
|
||||
# endif
|
||||
int z_verbose = verbose;
|
||||
|
||||
void 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)
|
||||
/* does not exist on WCE */
|
||||
int errno = 0;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MEMCPY
|
||||
|
||||
void 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 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 zmemzero(dest, len)
|
||||
Bytef* dest;
|
||||
uInt len;
|
||||
{
|
||||
if (len == 0) return;
|
||||
do {
|
||||
*dest++ = 0; /* ??? to be unrolled */
|
||||
} while (--len != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#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 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 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 zcalloc (voidpf opaque, unsigned items, unsigned size)
|
||||
{
|
||||
if (opaque) opaque = 0; /* to make compiler happy */
|
||||
return _halloc((long)items, size);
|
||||
}
|
||||
|
||||
void 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 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 zcfree (opaque, ptr)
|
||||
voidpf opaque;
|
||||
voidpf ptr;
|
||||
{
|
||||
free(ptr);
|
||||
if (opaque) return; /* make compiler happy */
|
||||
}
|
||||
|
||||
#endif /* MY_ZCALLOC */
|
258
zlib/zutil.h
Normal file
258
zlib/zutil.h
Normal file
|
@ -0,0 +1,258 @@
|
|||
/* zutil.h -- internal interface and configuration of the compression library
|
||||
* Copyright (C) 1995-2003 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
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
# include <stddef.h>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef NO_ERRNO_H
|
||||
extern int errno;
|
||||
#else
|
||||
# include <errno.h>
|
||||
#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
|
||||
# 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
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if defined(MACOS) || defined(TARGET_OS_MAC)
|
||||
# define OS_CODE 0x07
|
||||
# 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
|
||||
|
||||
#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))
|
||||
# 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
|
||||
|
||||
/* 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(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
|
||||
# ifndef HAVE_VSNPRINTF
|
||||
# define HAVE_VSNPRINTF
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__CYGWIN__)
|
||||
# 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)
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif
|
||||
# endif
|
||||
# ifdef __SASC
|
||||
# define NO_vsnprintf
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRERROR
|
||||
extern char *strerror OF((int));
|
||||
# define zstrerror(errnum) strerror(errnum)
|
||||
#else
|
||||
# define zstrerror(errnum) ""
|
||||
#endif
|
||||
|
||||
#if defined(pyr)
|
||||
# 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
|
||||
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
|
||||
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
|
||||
extern void zmemzero OF((Bytef* dest, uInt len));
|
||||
#endif
|
||||
|
||||
/* Diagnostic functions */
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
extern int z_verbose;
|
||||
extern void 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
|
||||
|
||||
|
||||
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
|
||||
void zcfree OF((voidpf opaque, voidpf ptr));
|
||||
|
||||
#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);}
|
||||
|
||||
#endif /* ZUTIL_H */
|
Loading…
Reference in a new issue