mirror of
https://git.do.srb2.org/STJr/ZenNode.git
synced 2024-11-10 06:42:09 +00:00
Initial commit
This commit is contained in:
commit
2e174e655d
24 changed files with 12891 additions and 0 deletions
339
COPYING
Normal file
339
COPYING
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
675 Mass Ave, Cambridge, MA 02139, 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
|
||||||
|
|
||||||
|
Appendix: 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) 19yy <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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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.
|
1210
DOOM/level.cpp
Normal file
1210
DOOM/level.cpp
Normal file
File diff suppressed because it is too large
Load diff
341
DOOM/level.hpp
Normal file
341
DOOM/level.hpp
Normal file
|
@ -0,0 +1,341 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: level.hpp
|
||||||
|
// Date: 26-Oct-1994
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Object classes for manipulating Doom Maps
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef LEVEL_HPP_
|
||||||
|
#define LEVEL_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( COMMON_HPP_ )
|
||||||
|
#include "common.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ! defined ( WAD_HPP_ )
|
||||||
|
#include "wad.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "thing.hpp"
|
||||||
|
#include "lineDef.hpp"
|
||||||
|
|
||||||
|
struct wThing1 {
|
||||||
|
INT16 xPos; // x position
|
||||||
|
INT16 yPos; // y position
|
||||||
|
UINT16 angle; // direction
|
||||||
|
UINT16 type; // thing type
|
||||||
|
UINT16 attr; // attributes of thing
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wThing2 { // HEXEN
|
||||||
|
UINT16 tid; // Thing ID - for scripts & specials
|
||||||
|
INT16 xPos; // x position
|
||||||
|
INT16 yPos; // y position
|
||||||
|
UINT16 altitude; // starting altitude
|
||||||
|
UINT16 angle; // direction
|
||||||
|
UINT16 type; // thing type
|
||||||
|
UINT16 attr; // attributes of thing
|
||||||
|
UINT8 special; // special type
|
||||||
|
UINT8 arg [5]; // special arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wThing {
|
||||||
|
INT16 xPos; // x position
|
||||||
|
INT16 yPos; // y position
|
||||||
|
UINT16 angle; // in degrees not BAM
|
||||||
|
UINT16 type; // thing type
|
||||||
|
UINT16 attr; // attributes of thing
|
||||||
|
UINT16 tid; // Thing ID - for scripts & specials
|
||||||
|
UINT16 altitude; // starting altitude
|
||||||
|
UINT8 special; // special type
|
||||||
|
UINT8 arg [5]; // special arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wLineDef1 {
|
||||||
|
UINT16 start; // from this vertex ...
|
||||||
|
UINT16 end; // ... to this vertex
|
||||||
|
UINT16 flags;
|
||||||
|
UINT16 type;
|
||||||
|
UINT16 tag; // crossing this linedef activates the sector with the same tag
|
||||||
|
UINT16 sideDef[2]; // sidedef
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wLineDef2 { // HEXEN
|
||||||
|
UINT16 start; // from this vertex ...
|
||||||
|
UINT16 end; // ... to this vertex
|
||||||
|
UINT16 flags;
|
||||||
|
UINT8 special; // special type
|
||||||
|
UINT8 arg [5]; // special arguments
|
||||||
|
UINT16 sideDef[2]; // sidedef
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wLineDef {
|
||||||
|
UINT16 start; // from this vertex ...
|
||||||
|
UINT16 end; // ... to this vertex
|
||||||
|
UINT16 flags;
|
||||||
|
UINT16 type;
|
||||||
|
UINT16 tag; // crossing this linedef activates the sector with the same tag
|
||||||
|
UINT16 sideDef[2]; // sidedef
|
||||||
|
UINT8 special; // special type
|
||||||
|
UINT8 arg [5]; // special arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NO_SIDEDEF (( UINT16 ) -1 )
|
||||||
|
#define RIGHT_SIDEDEF (( UINT16 ) 0 )
|
||||||
|
#define LEFT_SIDEDEF (( UINT16 ) 1 )
|
||||||
|
|
||||||
|
#define EMPTY_TEXTURE 0x002D // UINT16 version of ASCII "-"
|
||||||
|
|
||||||
|
struct wSideDef {
|
||||||
|
INT16 xOff; // X offset for texture
|
||||||
|
INT16 yOff; // Y offset for texture
|
||||||
|
char text1[MAX_LUMP_NAME]; // texture name for the part above
|
||||||
|
char text2[MAX_LUMP_NAME]; // texture name for the part below
|
||||||
|
char text3[MAX_LUMP_NAME]; // texture name for the regular part
|
||||||
|
UINT16 sector; // adjacent sector
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wVertex {
|
||||||
|
INT16 x; // X coordinate
|
||||||
|
INT16 y; // Y coordinate
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wSector {
|
||||||
|
INT16 floorh; // floor height
|
||||||
|
INT16 ceilh; // ceiling height
|
||||||
|
char floorTexture[MAX_LUMP_NAME]; // floor texture
|
||||||
|
char ceilTexture[MAX_LUMP_NAME]; // ceiling texture
|
||||||
|
UINT16 light; // light level (0-255)
|
||||||
|
UINT16 special; // special behaviour (0 = normal, 9 = secret, ...)
|
||||||
|
UINT16 trigger; // sector activated by a linedef with the same tag
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wSegs {
|
||||||
|
UINT16 start; // from this vertex ...
|
||||||
|
UINT16 end; // ... to this vertex
|
||||||
|
UINT16 angle; // angle (0 = east, 16384 = north, ...)
|
||||||
|
UINT16 lineDef; // linedef that this seg goes along*/
|
||||||
|
UINT16 flip; // true if not the same direction as linedef
|
||||||
|
UINT16 offset; // distance from starting point
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wSSector {
|
||||||
|
UINT16 num; // number of Segs in this Sub-Sector
|
||||||
|
UINT16 first; // first Seg
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wBound {
|
||||||
|
INT16 maxy, miny;
|
||||||
|
INT16 minx, maxx; // bounding rectangle
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wNode {
|
||||||
|
INT16 x, y; // starting point
|
||||||
|
INT16 dx, dy; // offset to ending point
|
||||||
|
wBound side[2];
|
||||||
|
UINT16 child[2]; // Node or SSector (if high bit is set)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wReject {
|
||||||
|
UINT16 dummy;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wBlockMap {
|
||||||
|
INT16 xOrigin;
|
||||||
|
INT16 yOrigin;
|
||||||
|
UINT16 noColumns;
|
||||||
|
UINT16 noRows;
|
||||||
|
// UINT16 data [];
|
||||||
|
};
|
||||||
|
|
||||||
|
class DoomLevel {
|
||||||
|
|
||||||
|
struct sLevelLump {
|
||||||
|
bool changed;
|
||||||
|
int byteOrder;
|
||||||
|
int elementSize;
|
||||||
|
int elementCount;
|
||||||
|
UINT32 dataSize;
|
||||||
|
void *rawData;
|
||||||
|
|
||||||
|
sLevelLump ();
|
||||||
|
};
|
||||||
|
|
||||||
|
WAD *m_Wad;
|
||||||
|
wLumpName m_Name;
|
||||||
|
|
||||||
|
bool m_IsHexen;
|
||||||
|
const char *m_Title;
|
||||||
|
const char *m_Music;
|
||||||
|
int m_Cluster;
|
||||||
|
|
||||||
|
wThing *m_ThingData;
|
||||||
|
wLineDef *m_LineDefData;
|
||||||
|
|
||||||
|
sLevelLump m_Map;
|
||||||
|
sLevelLump m_Thing;
|
||||||
|
sLevelLump m_LineDef;
|
||||||
|
sLevelLump m_SideDef;
|
||||||
|
sLevelLump m_Vertex;
|
||||||
|
sLevelLump m_Sector;
|
||||||
|
sLevelLump m_Segs;
|
||||||
|
sLevelLump m_SubSector;
|
||||||
|
sLevelLump m_Node;
|
||||||
|
sLevelLump m_Reject;
|
||||||
|
sLevelLump m_BlockMap;
|
||||||
|
sLevelLump m_Behavior;
|
||||||
|
|
||||||
|
static void ConvertRaw1ToThing ( int, wThing1 *, wThing * );
|
||||||
|
static void ConvertRaw2ToThing ( int, wThing2 *, wThing * );
|
||||||
|
static void ConvertThingToRaw1 ( int, wThing *, wThing1 * );
|
||||||
|
static void ConvertThingToRaw2 ( int, wThing *, wThing2 * );
|
||||||
|
|
||||||
|
static void ConvertRaw1ToLineDef ( int, wLineDef1 *, wLineDef * );
|
||||||
|
static void ConvertRaw2ToLineDef ( int, wLineDef2 *, wLineDef * );
|
||||||
|
static void ConvertLineDefToRaw1 ( int, wLineDef *, wLineDef1 * );
|
||||||
|
static void ConvertLineDefToRaw2 ( int, wLineDef *, wLineDef2 * );
|
||||||
|
|
||||||
|
void ReplaceVertices ( int *, wVertex *, int );
|
||||||
|
|
||||||
|
void DetermineType ();
|
||||||
|
|
||||||
|
bool Load ();
|
||||||
|
bool LoadHexenInfo ();
|
||||||
|
|
||||||
|
bool LoadThings ( bool );
|
||||||
|
bool LoadLineDefs ( bool );
|
||||||
|
|
||||||
|
void StoreThings ();
|
||||||
|
void StoreLineDefs ();
|
||||||
|
|
||||||
|
void NewEntry ( sLevelLump *, int, void * );
|
||||||
|
|
||||||
|
bool ReadEntry ( sLevelLump *, const char *, const wadDirEntry *, const wadDirEntry *, bool );
|
||||||
|
bool UpdateEntry ( sLevelLump *, const char *, const char *, bool );
|
||||||
|
|
||||||
|
void AdjustByteOrderMap ( int );
|
||||||
|
void AdjustByteOrderThing ( int );
|
||||||
|
void AdjustByteOrderLineDef ( int );
|
||||||
|
void AdjustByteOrderSideDef ( int );
|
||||||
|
void AdjustByteOrderVertex ( int );
|
||||||
|
void AdjustByteOrderSector ( int );
|
||||||
|
void AdjustByteOrderSegs ( int );
|
||||||
|
void AdjustByteOrderSubSector ( int );
|
||||||
|
void AdjustByteOrderNode ( int );
|
||||||
|
void AdjustByteOrderReject ( int );
|
||||||
|
void AdjustByteOrderBlockMap ( int );
|
||||||
|
void AdjustByteOrderBehavior ( int );
|
||||||
|
|
||||||
|
void AdjustByteOrder ( int );
|
||||||
|
|
||||||
|
void CleanUpEntry ( sLevelLump * );
|
||||||
|
void CleanUp ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DoomLevel ( const char *, WAD *, bool = true );
|
||||||
|
~DoomLevel ();
|
||||||
|
|
||||||
|
const WAD *GetWAD () const { return m_Wad; }
|
||||||
|
|
||||||
|
const char *Name () const { return m_Name; }
|
||||||
|
const char *Title () const { return m_Title ? m_Title : m_Name; }
|
||||||
|
const char *Music () const { return m_Music ? m_Music : NULL; }
|
||||||
|
int MapCluster () const { return m_Cluster; }
|
||||||
|
|
||||||
|
int ThingCount () const { return m_Thing.elementCount; }
|
||||||
|
int LineDefCount () const { return m_LineDef.elementCount; }
|
||||||
|
int SideDefCount () const { return m_SideDef.elementCount; }
|
||||||
|
int VertexCount () const { return m_Vertex.elementCount; }
|
||||||
|
int SectorCount () const { return m_Sector.elementCount; }
|
||||||
|
int SegCount () const { return m_Segs.elementCount; }
|
||||||
|
int SubSectorCount () const { return m_SubSector.elementCount; }
|
||||||
|
int NodeCount () const { return m_Node.elementCount; }
|
||||||
|
int RejectSize () const { return m_Reject.dataSize; }
|
||||||
|
int BlockMapSize () const { return m_BlockMap.dataSize; }
|
||||||
|
int BehaviorSize () const { return m_Behavior.dataSize; }
|
||||||
|
|
||||||
|
const wThing *GetThings () const { return m_ThingData; }
|
||||||
|
const wLineDef *GetLineDefs () const { return m_LineDefData; }
|
||||||
|
const wSideDef *GetSideDefs () const { return ( wSideDef * ) m_SideDef.rawData; }
|
||||||
|
const wVertex *GetVertices () const { return ( wVertex * ) m_Vertex.rawData; }
|
||||||
|
const wSector *GetSectors () const { return ( wSector * ) m_Sector.rawData; }
|
||||||
|
const wSegs *GetSegs () const { return ( wSegs * ) m_Segs.rawData; }
|
||||||
|
const wSSector *GetSubSectors () const { return ( wSSector * ) m_SubSector.rawData; }
|
||||||
|
const wNode *GetNodes () const { return ( wNode * ) m_Node.rawData; }
|
||||||
|
const wReject *GetReject () const { return ( wReject * ) m_Reject.rawData; }
|
||||||
|
const wBlockMap *GetBlockMap () const { return ( wBlockMap * ) m_BlockMap.rawData; }
|
||||||
|
const UINT8 *GetBehavior () const { return ( UINT8 * ) m_Behavior.rawData; }
|
||||||
|
|
||||||
|
void NewThings ( int, wThing * );
|
||||||
|
void NewLineDefs ( int, wLineDef * );
|
||||||
|
void NewSideDefs ( int, wSideDef * );
|
||||||
|
void NewVertices ( int, wVertex * );
|
||||||
|
void NewSectors ( int, wSector * );
|
||||||
|
void NewSegs ( int, wSegs * );
|
||||||
|
void NewSubSectors ( int, wSSector * );
|
||||||
|
void NewNodes ( int, wNode * );
|
||||||
|
void NewReject ( int, UINT8 * );
|
||||||
|
void NewBlockMap ( int, wBlockMap * );
|
||||||
|
void NewBehavior ( int, char * );
|
||||||
|
|
||||||
|
bool IsValid ( bool, bool = true ) const;
|
||||||
|
bool IsDirty () const;
|
||||||
|
|
||||||
|
void TrimVertices ();
|
||||||
|
void PackVertices ();
|
||||||
|
|
||||||
|
void PackSideDefs ();
|
||||||
|
void UnPackSideDefs ();
|
||||||
|
|
||||||
|
bool UpdateWAD ();
|
||||||
|
void AddToWAD ( WAD *wad );
|
||||||
|
|
||||||
|
sThingDesc *FindThing ( int type );
|
||||||
|
static sLineDefDesc *FindLineDef ( int type );
|
||||||
|
|
||||||
|
sThingDesc *GetThing ( int index );
|
||||||
|
static sLineDefDesc *GetLineDef ( int index );
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ( BYTE_ORDER == LITTLE_ENDIAN )
|
||||||
|
|
||||||
|
inline void DoomLevel::AdjustByteOrderMap ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderThing ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderLineDef ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderSideDef ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderVertex ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderSector ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderSegs ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderSubSector ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderNode ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderReject ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderBlockMap ( int ) {}
|
||||||
|
inline void DoomLevel::AdjustByteOrderBehavior ( int ) {}
|
||||||
|
|
||||||
|
inline void DoomLevel::AdjustByteOrder ( int ) {}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
159
DOOM/lineDef.hpp
Normal file
159
DOOM/lineDef.hpp
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: lineDef.hpp
|
||||||
|
// Date: 23-August-1995
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Object classes for manipulating Doom Map LineDefs
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef LINEDEF_HPP_
|
||||||
|
#define LINEDEF_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( LEVEL_HPP_ )
|
||||||
|
#include "level.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// WAD LINEDEF Flags
|
||||||
|
#define LDF_IMPASSABLE 0x0001
|
||||||
|
#define LDF_BLOCK_MONSTERS 0x0002
|
||||||
|
#define LDF_TWO_SIDED 0x0004
|
||||||
|
#define LDF_UPPER_UNPEGGED 0x0008
|
||||||
|
#define LDF_LOWER_UNPEGGED 0x0010
|
||||||
|
#define LDF_SECRET 0x0020
|
||||||
|
#define LDF_BLOCK_SOUND 0x0040
|
||||||
|
#define LDF_NOT_ON_MAP 0x0080
|
||||||
|
#define LDF_ALREADY_ON_MAP 0x0100
|
||||||
|
|
||||||
|
enum LD_LINE_CLASS {
|
||||||
|
LDC_NONE, // "--"
|
||||||
|
LDC_SPECIAL, // "Special"
|
||||||
|
LDC_DOOR, // "Door"
|
||||||
|
LDC_REMOTE, // "Remote Door"
|
||||||
|
LDC_CEILING, // "Ceiling"
|
||||||
|
LDC_LIFT, // "Lift"
|
||||||
|
LDC_FLOOR, // "Floor"
|
||||||
|
LDC_STAIRS, // "Stairs"
|
||||||
|
LDC_MOVE, // "Moving Floor"
|
||||||
|
LDC_CRUSH, // "Crushing Ceiling"
|
||||||
|
LDC_EXIT, // "Exit"
|
||||||
|
LDC_TELEPORT, // "Teleporter"
|
||||||
|
LDC_LIGHT, // "Light"
|
||||||
|
LDC_UNKNOWN, // "???"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LD_LINE_SPEED {
|
||||||
|
LDS_NONE,
|
||||||
|
LDS_SLOW,
|
||||||
|
LDS_MED,
|
||||||
|
LDS_FAST,
|
||||||
|
LDS_TURBO
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LD_LINE_ACTION {
|
||||||
|
LDA_NONE,
|
||||||
|
LDA_SCROLL,
|
||||||
|
LDA_OPEN,
|
||||||
|
LDA_CLOSE,
|
||||||
|
LDA_RAISE,
|
||||||
|
LDA_LOWER,
|
||||||
|
LDA_START,
|
||||||
|
LDA_STOP,
|
||||||
|
LDA_CHANGE,
|
||||||
|
LDA_TELEPORT,
|
||||||
|
LDA_END,
|
||||||
|
LDA_END_SECRET
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LD_LINE_EFFECTS {
|
||||||
|
LDE_NONE = 0x00000000,
|
||||||
|
|
||||||
|
LDE_NEEDTAG = 0x80000000,
|
||||||
|
|
||||||
|
LDE_LOCK = 0x40000000,
|
||||||
|
|
||||||
|
LDE_MONSTER = 0x20000000,
|
||||||
|
LDE_MONSTER_ONLY = 0x10000000,
|
||||||
|
|
||||||
|
LDE_TRIGGER_MODEL = 0x08000000,
|
||||||
|
LDE_NUMERIC_MODEL = 0x04000000,
|
||||||
|
LDE_MODEL_MASK = 0x0C000000,
|
||||||
|
|
||||||
|
LDE_TX_TEXTURE = 0x02000000,
|
||||||
|
LDE_TX_SPECIAL = 0x01000000,
|
||||||
|
LDE_TX_MASK = 0x03000000,
|
||||||
|
|
||||||
|
LDE_MAX = 0x00800000,
|
||||||
|
LDE_MIN = 0x00400000,
|
||||||
|
|
||||||
|
LDE_MV_HIGHEST = 0x00C00000,
|
||||||
|
LDE_MV_NEXT_HIGHEST = 0x00800000,
|
||||||
|
LDE_MV_LOWEST = 0x00400000,
|
||||||
|
|
||||||
|
LDE_MV_SHORTEST = 0x00300000,
|
||||||
|
LDE_MV_FLOOR = 0x00200000,
|
||||||
|
LDE_MV_CEILING = 0x00100000,
|
||||||
|
|
||||||
|
LDE_MV_EXCLUSIVE = 0x00080000,
|
||||||
|
LDE_MV_INCLUSIVE = 0x00040000,
|
||||||
|
|
||||||
|
LDE_SLOW_HURT = 0x00020000,
|
||||||
|
LDE_FAST_HURT = 0x00010000,
|
||||||
|
LDE_CRUSH = 0x00008000,
|
||||||
|
LDE_SILENT = 0x00004000,
|
||||||
|
LDE_BLINKING = 0x00002000,
|
||||||
|
|
||||||
|
LDE_KEY_BLUE = 0x00000C00,
|
||||||
|
LDE_KEY_YELLOW = 0x00000800,
|
||||||
|
LDE_KEY_RED = 0x00000400,
|
||||||
|
LDE_KEY_MASK = 0x00000C00,
|
||||||
|
|
||||||
|
LDE_MODIFIER_MASK = 0x000003FF
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LDE_TX ( LDE_TRIGGER_MODEL | LDE_TX_TEXTURE )
|
||||||
|
#define LDE_TXP ( LDE_TRIGGER_MODEL | LDE_TX_TEXTURE | LDE_TX_SPECIAL )
|
||||||
|
#define LDE_NXP ( LDE_NUMERIC_MODEL | LDE_TX_TEXTURE | LDE_TX_SPECIAL )
|
||||||
|
#define LDE_HE ( LDE_MV_HIGHEST | LDE_MV_EXCLUSIVE )
|
||||||
|
#define LDE_HEF ( LDE_MV_HIGHEST | LDE_MV_EXCLUSIVE | LDE_MV_FLOOR )
|
||||||
|
#define LDE_HEC ( LDE_MV_HIGHEST | LDE_MV_EXCLUSIVE | LDE_MV_CEILING )
|
||||||
|
#define LDE_LE ( LDE_MV_LOWEST | LDE_MV_EXCLUSIVE )
|
||||||
|
#define LDE_LEF ( LDE_MV_LOWEST | LDE_MV_EXCLUSIVE | LDE_MV_FLOOR )
|
||||||
|
#define LDE_LIC ( LDE_MV_LOWEST | LDE_MV_INCLUSIVE | LDE_MV_CEILING )
|
||||||
|
#define LDE_nhEF ( LDE_MV_NEXT_HIGHEST | LDE_MV_EXCLUSIVE | LDE_MV_FLOOR )
|
||||||
|
#define LDE_F ( LDE_MV_FLOOR )
|
||||||
|
#define LDE_NUM(x) ((x) & LDE_MODIFIER_MASK )
|
||||||
|
|
||||||
|
struct sLineDefDesc {
|
||||||
|
INT16 Type;
|
||||||
|
UINT8 Class;
|
||||||
|
const char *Trigger;
|
||||||
|
UINT8 Speed;
|
||||||
|
UINT8 Duration;
|
||||||
|
UINT8 Action;
|
||||||
|
UINT32 Effects;
|
||||||
|
|
||||||
|
const char *GetClass ();
|
||||||
|
const char *GetDescription ();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
100
DOOM/thing.hpp
Normal file
100
DOOM/thing.hpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: thing.hpp
|
||||||
|
// Date: 23-August-1995
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Object classes for manipulating Doom Map Things
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef THING_HPP_
|
||||||
|
#define THING_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( LEVEL_HPP_ )
|
||||||
|
#include "level.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SHORT
|
||||||
|
typedef short SHORT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define THING_SKILL_1_2 0x0001
|
||||||
|
#define THING_SKILL_3 0x0002
|
||||||
|
#define THING_SKILL_4_5 0x0004
|
||||||
|
#define THING_DEAF 0x0008
|
||||||
|
#define THING_MULTIPLAYER 0x0010
|
||||||
|
#define THING_a 0x0020
|
||||||
|
#define THING_b 0x0040
|
||||||
|
#define THING_c 0x0080
|
||||||
|
#define THING_d 0x0100
|
||||||
|
#define THING_e 0x0200
|
||||||
|
#define THING_f 0x0400
|
||||||
|
|
||||||
|
|
||||||
|
#define TP_NONE 0x00000
|
||||||
|
#define TP_BLOCK 0x00001 // Blocks the player
|
||||||
|
#define TP_PICK 0x00002 // Can be picked up
|
||||||
|
#define TP_SOUND 0x00004 // Sound only: invisible, can be outside of map
|
||||||
|
#define TP_INVIS 0x00008 // Invisible or blurred
|
||||||
|
#define TP_FLOAT 0x00010 // Floats or hangs from the ceiling
|
||||||
|
#define TP_LIGHT 0x00020 // Can be seen in a dark room
|
||||||
|
#define TP_ITEM 0x00040 // Counts towards the item ratio at the end
|
||||||
|
#define TP_KILL 0x00080 // Counts towards the kill ratio at the end
|
||||||
|
#define TP_PLAYER 0x00100 // Player starting point
|
||||||
|
#define TP_HEALTH ( 0x00200 | TP_PICK )
|
||||||
|
#define TP_ARTIFACT ( 0x00400 | TP_PICK | TP_ITEM ) // Artifact
|
||||||
|
#define TP_ARMOR ( 0x00800 | TP_PICK
|
||||||
|
#define TP_WEAPON ( 0x01000 | TP_PICK | TP_ITEM ) // Weapon
|
||||||
|
#define TP_AMMO 0x02000 // Ammunition
|
||||||
|
#define TP_KEY ( 0x04000 | TP_PICK | TP_ITEM )
|
||||||
|
#define TP_MONSTER ( 0x08000 | TP_BLOCK | TP_KILL )
|
||||||
|
#define TP_BAD -1 // Invalid Thing - should not be used
|
||||||
|
|
||||||
|
#define TP_POLYOBJ 0x10000
|
||||||
|
|
||||||
|
#define TP_BONUS ( TP_PICK | TP_ITEM )
|
||||||
|
#define TP_DECORATE TP_BLOCK
|
||||||
|
#define TP_CORPSE TP_DECORATE
|
||||||
|
|
||||||
|
struct sThingDesc {
|
||||||
|
SHORT Type;
|
||||||
|
const char *Name;
|
||||||
|
const char *Sprite;
|
||||||
|
const char *Sequence;
|
||||||
|
SHORT Radius;
|
||||||
|
SHORT Height;
|
||||||
|
SHORT Mass;
|
||||||
|
SHORT Health;
|
||||||
|
SHORT Speed;
|
||||||
|
SHORT Damage;
|
||||||
|
int Properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bullets 10
|
||||||
|
Shotgun 70 ( 7 pellets * 10 )
|
||||||
|
Plasma 20
|
||||||
|
Rockets 100
|
||||||
|
BFG 1000
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
1223
DOOM/wad.cpp
Normal file
1223
DOOM/wad.cpp
Normal file
File diff suppressed because it is too large
Load diff
322
DOOM/wad.hpp
Normal file
322
DOOM/wad.hpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: wad.hpp
|
||||||
|
// Date: 26-Oct-1994
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Object classes for manipulating Doom WAD files
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
// 04-25-01 Added little/big endian conversions
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef WAD_HPP_
|
||||||
|
#define WAD_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( COMMON_HPP_ )
|
||||||
|
#include "common.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ! defined ( __STDIO_H )
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ( BYTE_ORDER == LITTLE_ENDIAN )
|
||||||
|
const UINT32 IWAD_ID = 0x44415749; // ASCII - 'IWAD'
|
||||||
|
const UINT32 PWAD_ID = 0x44415750; // ASCII - 'PWAD'
|
||||||
|
#else
|
||||||
|
const UINT32 IWAD_ID = 0x49574144; // ASCII - 'IWAD'
|
||||||
|
const UINT32 PWAD_ID = 0x50574144; // ASCII - 'PWAD'
|
||||||
|
|
||||||
|
extern UINT32 swap_uint32 ( const unsigned char *ptr );
|
||||||
|
extern UINT16 swap_uint16 ( const unsigned char *ptr );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IS_TYPE(x,y) (( * ( UINT32 * ) ( x )) == (( UINT32 ) y ))
|
||||||
|
|
||||||
|
#define MAX_LUMP_NAME 8
|
||||||
|
|
||||||
|
enum eLumpType {
|
||||||
|
wl_UNCHECKED,
|
||||||
|
wl_UNKNOWN,
|
||||||
|
wl_PALETTE,
|
||||||
|
wl_COLORMAP,
|
||||||
|
wl_DEMO,
|
||||||
|
wl_TEXTURE_LIST,
|
||||||
|
wl_PATCH_NAMES,
|
||||||
|
wl_MIDI_MAPPING,
|
||||||
|
wl_GRAVIS_PATCH,
|
||||||
|
wl_MAP_NAME,
|
||||||
|
wl_MAP_DATA,
|
||||||
|
wl_PC_SPEAKER,
|
||||||
|
wl_SOUND_EFFECT,
|
||||||
|
wl_MUSIC,
|
||||||
|
wl_FLAT,
|
||||||
|
wl_PATCH,
|
||||||
|
wl_SPRITE,
|
||||||
|
wl_GRAPHIC,
|
||||||
|
wl_SCREEN_SHOT,
|
||||||
|
wl_TEXT_SCREEN,
|
||||||
|
wl_SOUND_INFO,
|
||||||
|
wl_SCRIPT,
|
||||||
|
wl_SPECIAL
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eWadType {
|
||||||
|
wt_UNKNOWN,
|
||||||
|
wt_DOOM,
|
||||||
|
wt_DOOM2,
|
||||||
|
wt_HERETIC,
|
||||||
|
wt_HEXEN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eWadStyle {
|
||||||
|
wst_UNKNOWN,
|
||||||
|
wst_FORMAT_1, // DOOM / Heretic
|
||||||
|
wst_FORMAT_2, // DOOM ][
|
||||||
|
wst_FORMAT_3 // Hexen
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eWadStatus {
|
||||||
|
ws_UNKNOWN,
|
||||||
|
ws_OK,
|
||||||
|
ws_CANT_READ,
|
||||||
|
ws_CANT_WRITE,
|
||||||
|
ws_INVALID_WAD,
|
||||||
|
ws_INVALID_FILE,
|
||||||
|
ws_SEEK_ERROR,
|
||||||
|
ws_READ_ERROR,
|
||||||
|
ws_WRITE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wadHeader {
|
||||||
|
char type [4];
|
||||||
|
UINT32 dirSize; // number of Lumps in WAD
|
||||||
|
UINT32 dirStart; // offset to start of directory
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef char wLumpName [ MAX_LUMP_NAME ];
|
||||||
|
|
||||||
|
struct wadDirEntry {
|
||||||
|
UINT32 offset; // offset to start of data
|
||||||
|
UINT32 size; // byte size of data
|
||||||
|
wLumpName name; // name of data block
|
||||||
|
};
|
||||||
|
|
||||||
|
struct wadDirInfo {
|
||||||
|
UINT8 *cacheData;
|
||||||
|
UINT8 *newData;
|
||||||
|
eLumpType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class wadList;
|
||||||
|
|
||||||
|
class wadFilter {
|
||||||
|
public:
|
||||||
|
virtual const char *getFileSpec () const = 0;
|
||||||
|
virtual bool isRecognized ( UINT32, void * ) const = 0;
|
||||||
|
virtual bool isRecognized ( const char * ) const = 0;
|
||||||
|
virtual bool readData ( FILE *, UINT32 *, void ** ) const = 0;
|
||||||
|
virtual bool writeData ( FILE *, UINT32, void * ) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class WAD {
|
||||||
|
|
||||||
|
char *m_Name;
|
||||||
|
FILE *m_File;
|
||||||
|
wadList *m_List;
|
||||||
|
|
||||||
|
bool m_bValid;
|
||||||
|
bool m_bRegistered;
|
||||||
|
bool m_bDirChanged; // wadDirEntry added/deleted
|
||||||
|
|
||||||
|
wadHeader m_Header;
|
||||||
|
wadDirEntry *m_Directory;
|
||||||
|
wadDirInfo *m_DirInfo;
|
||||||
|
eWadStatus m_Status;
|
||||||
|
eWadType m_Type;
|
||||||
|
eWadStyle m_Style;
|
||||||
|
|
||||||
|
const wadDirEntry *m_MapStart;
|
||||||
|
const wadDirEntry *m_MapEnd;
|
||||||
|
const wadDirEntry *m_SpriteStart;
|
||||||
|
const wadDirEntry *m_SpriteEnd;
|
||||||
|
const wadDirEntry *m_PatchStart;
|
||||||
|
const wadDirEntry *m_PatchEnd;
|
||||||
|
const wadDirEntry *m_FlatStart;
|
||||||
|
const wadDirEntry *m_FlatEnd;
|
||||||
|
|
||||||
|
void **m_NewData;
|
||||||
|
|
||||||
|
static int sm_NoFilters;
|
||||||
|
static wadFilter **sm_Filter;
|
||||||
|
|
||||||
|
bool EnlargeDirectory ( int holePos, int entries );
|
||||||
|
bool ReduceDirectory ( int holePos, int entries );
|
||||||
|
|
||||||
|
void FindMarkers ();
|
||||||
|
|
||||||
|
bool ReadHeader ( wadHeader * );
|
||||||
|
bool WriteHeader ( FILE *, wadHeader * );
|
||||||
|
|
||||||
|
bool ReadDirEntry ( wadDirEntry * );
|
||||||
|
bool WriteDirEntry ( FILE *, wadDirEntry * );
|
||||||
|
|
||||||
|
bool ReadDirectory ();
|
||||||
|
bool WriteDirectory ( FILE * );
|
||||||
|
|
||||||
|
UINT32 IndexOf ( const wadDirEntry * ) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WAD ( const char * );
|
||||||
|
~WAD ();
|
||||||
|
|
||||||
|
void SetList ( wadList * );
|
||||||
|
|
||||||
|
static bool IsMap ( const char * );
|
||||||
|
static bool AddFilter ( wadFilter * );
|
||||||
|
|
||||||
|
// Called by wadList::Save
|
||||||
|
void OpenFile ();
|
||||||
|
void CloseFile ();
|
||||||
|
|
||||||
|
bool SaveFile ( const char * = NULL );
|
||||||
|
|
||||||
|
void Type ( eWadType );
|
||||||
|
void Style ( eWadStyle );
|
||||||
|
void Format ( UINT32 );
|
||||||
|
|
||||||
|
const char *Name () const;
|
||||||
|
eWadStatus Status () const;
|
||||||
|
eWadType Type () const;
|
||||||
|
eWadStyle Style () const;
|
||||||
|
UINT32 Format () const;
|
||||||
|
UINT32 FileSize () const;
|
||||||
|
|
||||||
|
bool IsValid () const;
|
||||||
|
bool IsRegistered () const;
|
||||||
|
bool HasChanged () const;
|
||||||
|
bool HasChanged ( const wadDirEntry * ) const;
|
||||||
|
|
||||||
|
eLumpType GetLumpType ( const wadDirEntry * );
|
||||||
|
const char *GetLumpDescription ( eLumpType ) const;
|
||||||
|
const char *GetLumpDescription ( const wadDirEntry * );
|
||||||
|
|
||||||
|
void Seek ( UINT32 );
|
||||||
|
void ReadBytes ( void *, UINT32, UINT32 = 1 );
|
||||||
|
void WriteBytes ( void *, UINT32, UINT32 = 1 );
|
||||||
|
void CopyBytes ( WAD *, UINT32, UINT32 = 1 );
|
||||||
|
|
||||||
|
UINT32 DirSize () const;
|
||||||
|
|
||||||
|
const wadDirEntry *GetDir ( UINT32 ) const;
|
||||||
|
const wadDirEntry *FindDir ( const char *, const wadDirEntry * = NULL, const wadDirEntry * = NULL ) const;
|
||||||
|
|
||||||
|
void *ReadEntry ( const char *, UINT32 *, const wadDirEntry * = NULL, const wadDirEntry * = NULL, bool = false );
|
||||||
|
void *ReadEntry ( const wadDirEntry *, UINT32 *, bool = false );
|
||||||
|
|
||||||
|
bool WriteEntry ( const char *, UINT32, void *, bool, const wadDirEntry * = NULL, const wadDirEntry * = NULL );
|
||||||
|
bool WriteEntry ( const wadDirEntry *, UINT32, void *, bool );
|
||||||
|
|
||||||
|
bool Extract ( const wLumpName *, const char * = NULL ) const;
|
||||||
|
|
||||||
|
bool InsertBefore ( const wLumpName *, const char *, bool, const wadDirEntry * = NULL );
|
||||||
|
bool InsertAfter ( const wLumpName *, const char *, bool, const wadDirEntry * = NULL );
|
||||||
|
|
||||||
|
bool InsertBefore ( const wLumpName *, UINT32, void *, bool, const wadDirEntry * = NULL );
|
||||||
|
bool InsertAfter ( const wLumpName *, UINT32, void *, bool, const wadDirEntry * = NULL );
|
||||||
|
|
||||||
|
bool Remove ( const wLumpName *, const wadDirEntry * = NULL, const wadDirEntry * = NULL );
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void WAD::Format ( UINT32 newFormat ) { * ( UINT32 * ) m_Header.type = newFormat; }
|
||||||
|
inline void WAD::Type ( eWadType newType ) { m_Type = newType; }
|
||||||
|
inline void WAD::Style ( eWadStyle newStyle ) { m_Style = newStyle; }
|
||||||
|
|
||||||
|
inline const char *WAD::Name () const { return m_Name; }
|
||||||
|
inline UINT32 WAD::DirSize () const { return m_Header.dirSize; }
|
||||||
|
inline UINT32 WAD::Format () const { return * ( UINT32 * ) m_Header.type; }
|
||||||
|
inline eWadStatus WAD::Status () const { return m_Status; }
|
||||||
|
inline eWadType WAD::Type () const { return m_Type; }
|
||||||
|
inline eWadStyle WAD::Style () const { return m_Style; }
|
||||||
|
inline bool WAD::IsValid () const { return m_bValid; }
|
||||||
|
inline bool WAD::IsRegistered () const { return m_bRegistered; }
|
||||||
|
|
||||||
|
struct wadListDirEntry {
|
||||||
|
WAD *wad;
|
||||||
|
const wadDirEntry *entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
class wadList {
|
||||||
|
|
||||||
|
struct wadListEntry {
|
||||||
|
WAD *wad;
|
||||||
|
wadListEntry *Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
UINT32 m_DirSize;
|
||||||
|
UINT32 m_MaxSize;
|
||||||
|
wadListDirEntry *m_Directory;
|
||||||
|
eWadType m_Type;
|
||||||
|
eWadStyle m_Style;
|
||||||
|
wadListEntry *m_List;
|
||||||
|
|
||||||
|
UINT32 IndexOf ( const wadListDirEntry * ) const;
|
||||||
|
|
||||||
|
int AddLevel ( UINT32, const wadDirEntry *&, WAD * );
|
||||||
|
void AddDirectory ( WAD *, bool = true );
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
wadList ();
|
||||||
|
~wadList ();
|
||||||
|
|
||||||
|
bool Add ( WAD * );
|
||||||
|
bool Remove ( WAD * );
|
||||||
|
void Clear ();
|
||||||
|
void UpdateDirectory ();
|
||||||
|
|
||||||
|
int wadCount () const;
|
||||||
|
UINT32 FileSize () const;
|
||||||
|
WAD *GetWAD ( int ) const;
|
||||||
|
eWadType Type () const;
|
||||||
|
eWadStyle Style () const;
|
||||||
|
|
||||||
|
bool Save ( const char * = NULL );
|
||||||
|
bool Extract ( const wLumpName *, const char *file = NULL );
|
||||||
|
|
||||||
|
UINT32 DirSize () const;
|
||||||
|
|
||||||
|
const wadListDirEntry *GetDir ( UINT32 ) const;
|
||||||
|
const wadListDirEntry *FindWAD ( const char *, const wadListDirEntry * = NULL, const wadListDirEntry * = NULL ) const;
|
||||||
|
|
||||||
|
bool Contains ( WAD * ) const;
|
||||||
|
bool IsEmpty () const;
|
||||||
|
bool HasChanged () const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline UINT32 wadList::DirSize () const { return m_DirSize; }
|
||||||
|
inline bool wadList::IsEmpty () const { return ( m_List == NULL ) ? true : false; }
|
||||||
|
inline eWadType wadList::Type () const { return m_Type; }
|
||||||
|
inline eWadStyle wadList::Style () const { return m_Style; }
|
||||||
|
|
||||||
|
#endif
|
22
README
Normal file
22
README
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
ZenNode v1.2.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
This is directory tree includes the source code necessary to build ZenNode.
|
||||||
|
Since I don't have a lot of time to spend maintaining the code and there
|
||||||
|
haven't been too many changes in the past few years, I've decided to release
|
||||||
|
the source under the GPL license. See the file COPYING for details.
|
||||||
|
|
||||||
|
Several of the files (i.e. those in the DOOM directory) evolved from earlier
|
||||||
|
projects. They contain functionality that is not used in ZenNode and may not
|
||||||
|
have been kept up to date. I think it all works, but I won't make any
|
||||||
|
guarantees.
|
||||||
|
|
||||||
|
There is a makefile included in the ZenNode directory that can be used as is
|
||||||
|
under Linux. To build ZenNode in any other environment, you can use the
|
||||||
|
makefile as a guide. I've built and tested it under Windows using Borland
|
||||||
|
and Microsoft compilers. Older versions have been compiled under OS/2 using
|
||||||
|
Borland. The code should be portable to other compilers, but it has never
|
||||||
|
been tested.
|
||||||
|
|
||||||
|
Enjoy,
|
||||||
|
Marc
|
1030
ZenNode/ZenMain.cpp
Normal file
1030
ZenNode/ZenMain.cpp
Normal file
File diff suppressed because it is too large
Load diff
1890
ZenNode/ZenNode.cpp
Normal file
1890
ZenNode/ZenNode.cpp
Normal file
File diff suppressed because it is too large
Load diff
235
ZenNode/ZenNode.hpp
Normal file
235
ZenNode/ZenNode.hpp
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: ZenNode.hpp
|
||||||
|
// Date: 26-Oct-1994
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Definitions of structures used by the ZenNode routines
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
// 06-??-95 Added LineDef alias list to speed up the process
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ZENNODE_HPP_
|
||||||
|
#define ZENNODE_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( LEVEL_HPP_ )
|
||||||
|
#include "level.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sBlockMapOptions {
|
||||||
|
bool Rebuild;
|
||||||
|
bool Compress;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sNodeOptions {
|
||||||
|
bool Rebuild;
|
||||||
|
int Method;
|
||||||
|
bool Quiet;
|
||||||
|
bool Unique;
|
||||||
|
bool ReduceLineDefs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sBlockList {
|
||||||
|
int firstIndex; // Index of 1st blockList element matching this one
|
||||||
|
int offset;
|
||||||
|
int count;
|
||||||
|
int *line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sBlockMap {
|
||||||
|
int xOrigin;
|
||||||
|
int yOrigin;
|
||||||
|
int noColumns;
|
||||||
|
int noRows;
|
||||||
|
sBlockList *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned short BAM;
|
||||||
|
typedef long double REAL; // Must have at least 50 significant bits
|
||||||
|
|
||||||
|
struct sVertex {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double l;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SEG {
|
||||||
|
wSegs Data;
|
||||||
|
const wLineDef *LineDef;
|
||||||
|
int Sector;
|
||||||
|
int Side;
|
||||||
|
int AliasFlip;
|
||||||
|
bool Split;
|
||||||
|
bool DontSplit;
|
||||||
|
bool final;
|
||||||
|
sVertex start;
|
||||||
|
sVertex end;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sBSPOptions {
|
||||||
|
int algorithm;
|
||||||
|
bool showProgress;
|
||||||
|
bool reduceLineDefs; // global flag for invisible linedefs
|
||||||
|
bool *ignoreLineDef; // linedefs that can be left out
|
||||||
|
bool *dontSplit; // linedefs that can't be split
|
||||||
|
bool *keepUnique; // unique sector requirements
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sScoreInfo {
|
||||||
|
int index;
|
||||||
|
long metric1;
|
||||||
|
long metric2;
|
||||||
|
int invalid;
|
||||||
|
int total;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define sgn(a) ((0<(a))-((a)<0))
|
||||||
|
|
||||||
|
#define BAM90 (( BAM ) 0x4000 ) // BAM: 90ø ( «ã)
|
||||||
|
#define BAM180 (( BAM ) 0x8000 ) // BAM: 180ø ( ñã)
|
||||||
|
#define BAM270 (( BAM ) 0xC000 ) // BAM: 270ø (-«ã)
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
|
||||||
|
#define SIDE_UNKNOWN -2
|
||||||
|
#define SIDE_LEFT -1
|
||||||
|
#define SIDE_SPLIT 0
|
||||||
|
#define SIDE_RIGHT 1
|
||||||
|
|
||||||
|
#define SIDE_FLIPPED 0xFFFFFFFE
|
||||||
|
#define SIDE_NORMAL 0
|
||||||
|
|
||||||
|
#define LEFT 0
|
||||||
|
#define SPLIT 1
|
||||||
|
#define RIGHT 2
|
||||||
|
|
||||||
|
#define IS_LEFT_RIGHT(s) ( s & 1 )
|
||||||
|
#define FLIP(c,s) ( c ^ s )
|
||||||
|
|
||||||
|
// ---- ZenReject structures to support RMB options ----
|
||||||
|
|
||||||
|
enum REJECT_OPTION_E {
|
||||||
|
OPTION_UNKNOWN,
|
||||||
|
OPTION_MAP_1,
|
||||||
|
OPTION_MAP_2,
|
||||||
|
OPTION_BAND,
|
||||||
|
OPTION_BLIND,
|
||||||
|
OPTION_BLOCK,
|
||||||
|
OPTION_DISTANCE,
|
||||||
|
OPTION_DOOR,
|
||||||
|
OPTION_EXCLUDE,
|
||||||
|
OPTION_GROUP,
|
||||||
|
OPTION_INCLUDE,
|
||||||
|
OPTION_LEFT,
|
||||||
|
OPTION_LENGTH,
|
||||||
|
OPTION_LINE,
|
||||||
|
OPTION_NODOOR,
|
||||||
|
OPTION_NOMAP,
|
||||||
|
OPTION_NOPROCESS,
|
||||||
|
OPTION_ONE,
|
||||||
|
OPTION_PERFECT,
|
||||||
|
OPTION_PREPROCESS,
|
||||||
|
OPTION_PROCESS,
|
||||||
|
OPTION_REPORT,
|
||||||
|
OPTION_RIGHT,
|
||||||
|
OPTION_SAFE,
|
||||||
|
OPTION_TRACE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRejectOptionRMB;
|
||||||
|
struct sOptionTableInfo;
|
||||||
|
|
||||||
|
typedef bool (*PARSE_FUNCTION) ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
|
||||||
|
struct sOptionTableInfo {
|
||||||
|
const char *Name;
|
||||||
|
const char *Syntax;
|
||||||
|
REJECT_OPTION_E Type;
|
||||||
|
PARSE_FUNCTION ParseFunction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRejectOptionRMB {
|
||||||
|
const sOptionTableInfo *Info;
|
||||||
|
bool Inverted;
|
||||||
|
bool Banded;
|
||||||
|
int Data [2];
|
||||||
|
int *List [2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRejectOptions {
|
||||||
|
bool Rebuild;
|
||||||
|
bool Empty;
|
||||||
|
bool Force;
|
||||||
|
bool FindChildren;
|
||||||
|
bool UseGraphs;
|
||||||
|
bool UseRMB;
|
||||||
|
const sRejectOptionRMB *rmb;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ParseOptionRMB ( int, const char *, sRejectOptionRMB * );
|
||||||
|
|
||||||
|
// ----- C99 routines from <math.h> Required by ZenNode -----
|
||||||
|
|
||||||
|
#if ( defined ( __GNUC__ ) && ( __GNUC__ < 3 )) || defined ( __INTEL_COMPILER ) || defined ( __BORLANDC__ )
|
||||||
|
|
||||||
|
#if defined ( X86 )
|
||||||
|
|
||||||
|
__inline long lrint ( double flt )
|
||||||
|
{
|
||||||
|
int intgr;
|
||||||
|
|
||||||
|
__asm__ __volatile__ ("fistpl %0" : "=m" (intgr) : "t" (flt) : "st");
|
||||||
|
|
||||||
|
return intgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
__inline long lrint ( double flt )
|
||||||
|
{
|
||||||
|
// return ( long ) ( flt + 0.5 * sgn ( flt ));
|
||||||
|
return ( long ) ( flt + 0.5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined ( _MSC_VER )
|
||||||
|
|
||||||
|
__inline long lrint ( double flt )
|
||||||
|
{
|
||||||
|
int intgr;
|
||||||
|
|
||||||
|
_asm
|
||||||
|
{
|
||||||
|
fld flt
|
||||||
|
fistp intgr
|
||||||
|
};
|
||||||
|
|
||||||
|
return intgr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern sBlockMap *GenerateBLOCKMAP ( DoomLevel *level );
|
||||||
|
extern int CreateBLOCKMAP ( DoomLevel *level, const sBlockMapOptions &options );
|
||||||
|
extern void CreateNODES ( DoomLevel *level, sBSPOptions *options );
|
||||||
|
extern bool CreateREJECT ( DoomLevel *level, const sRejectOptions &options );
|
||||||
|
|
||||||
|
#endif
|
407
ZenNode/ZenRMB.cpp
Normal file
407
ZenNode/ZenRMB.cpp
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: ZenRMB.cpp
|
||||||
|
// Date: 30-Oct-2000
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: RMB configuration file support for ZenNode
|
||||||
|
//
|
||||||
|
// Copyright (c) 2000-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
#include "ZenNode.hpp"
|
||||||
|
|
||||||
|
DBG_REGISTER ( __FILE__ );
|
||||||
|
|
||||||
|
bool ParseGeneric ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
bool ParseMap ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
bool ParseBAND ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
bool ParseINVERT ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
bool ParseNOPROCESS ( char *, const sOptionTableInfo &, sRejectOptionRMB * );
|
||||||
|
|
||||||
|
sOptionTableInfo ParseTable [] = {
|
||||||
|
{ "BAND", "NNL", OPTION_BAND, ParseBAND },
|
||||||
|
{ "BLIND", "NL", OPTION_BLIND, ParseGeneric },
|
||||||
|
{ "BLOCK", "NN", OPTION_BLOCK, ParseGeneric },
|
||||||
|
{ "DISTANCE", "N", OPTION_DISTANCE, ParseGeneric },
|
||||||
|
{ "DOOR", "N", OPTION_DOOR, ParseGeneric },
|
||||||
|
{ "E*M*", NULL, OPTION_MAP_1, ParseMap },
|
||||||
|
{ "EXCLUDE", "LL", OPTION_EXCLUDE, ParseGeneric },
|
||||||
|
{ "GROUP", "NL", OPTION_GROUP, ParseGeneric },
|
||||||
|
{ "INCLUDE", "LL", OPTION_INCLUDE, ParseGeneric },
|
||||||
|
{ "INVERT", NULL, OPTION_UNKNOWN, ParseINVERT },
|
||||||
|
{ "LEFT", "N", OPTION_LEFT, ParseGeneric },
|
||||||
|
{ "LENGTH", "N", OPTION_LENGTH, ParseGeneric },
|
||||||
|
{ "LINE", "N", OPTION_LINE, ParseGeneric },
|
||||||
|
{ "MAP**", NULL, OPTION_MAP_2, ParseMap },
|
||||||
|
{ "NODOOR", "L", OPTION_NODOOR, ParseGeneric },
|
||||||
|
{ "NOMAP", NULL, OPTION_NOMAP, ParseGeneric },
|
||||||
|
{ "NOPROCESS", NULL, OPTION_NOPROCESS, ParseNOPROCESS },
|
||||||
|
{ "ONE", "NN", OPTION_ONE, ParseGeneric },
|
||||||
|
{ "PERFECT", NULL, OPTION_PERFECT, ParseGeneric },
|
||||||
|
{ "PREPROCESS", "N", OPTION_PREPROCESS, ParseGeneric },
|
||||||
|
{ "PROCESS", "L", OPTION_PROCESS, ParseGeneric },
|
||||||
|
{ "REPORT", "N", OPTION_REPORT, ParseGeneric },
|
||||||
|
{ "RIGHT", "N", OPTION_RIGHT, ParseGeneric },
|
||||||
|
{ "SAFE", "NL", OPTION_SAFE, ParseGeneric },
|
||||||
|
{ "TRACE", "L", OPTION_TRACE, ParseGeneric }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *parseText;
|
||||||
|
static int parseLine;
|
||||||
|
static int lastLine;
|
||||||
|
|
||||||
|
const sOptionTableInfo *FindByType ( REJECT_OPTION_E type )
|
||||||
|
{
|
||||||
|
for ( unsigned i = 0; i < SIZE ( ParseTable ); i++ ) {
|
||||||
|
if ( ParseTable [i].Type == type ) return &ParseTable [i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseError ( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseError", true );
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start ( args, fmt );
|
||||||
|
|
||||||
|
fprintf ( stderr, ( lastLine == parseLine ) ? " " : "Line %3d: ", parseLine );
|
||||||
|
vfprintf ( stderr, fmt, args );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
lastLine = parseLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ParseNumber ( char *&text )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseNumber", true );
|
||||||
|
|
||||||
|
if ( ! isdigit ( *text )) throw "expected a number";
|
||||||
|
|
||||||
|
int number = 0;
|
||||||
|
|
||||||
|
while ( isdigit ( *text )) {
|
||||||
|
number *= 10;
|
||||||
|
number += *text++ - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
int *ParseList ( char *&text, bool strict )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseList", true );
|
||||||
|
|
||||||
|
if (( strict == true ) && ( *text != '(' )) {
|
||||||
|
int *list = new int [ 2 ];
|
||||||
|
list [0] = ParseNumber ( text );
|
||||||
|
list [1] = -1;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool close = false;
|
||||||
|
|
||||||
|
if ( *text == '(' ) {
|
||||||
|
close = true;
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( isspace ( *text )) text++;
|
||||||
|
|
||||||
|
if ( *text == '\0' ) throw "Invalid list";
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
char *ptr = text;
|
||||||
|
if ( isdigit ( *ptr )) {
|
||||||
|
while (( *ptr != '\0' ) && ( *ptr != ')' )) {
|
||||||
|
if ( ! isdigit ( *ptr )) throw "Invalid list";
|
||||||
|
while ( isdigit ( *ptr )) ptr++;
|
||||||
|
if ( *ptr == ',' ) ptr++;
|
||||||
|
while ( isspace ( *ptr )) ptr++;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
/* Is this valid???
|
||||||
|
} else {
|
||||||
|
if ( strncmp ( ptr, "ALL", 3 ) != 0 ) throw "Invalid list";
|
||||||
|
ptr += 3;
|
||||||
|
while ( isspace ( *ptr )) ptr++;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( close == true ) && ( *ptr != ')' )) throw "List must end with a ')'";
|
||||||
|
|
||||||
|
int *list = new int [ count + 1 ];
|
||||||
|
for ( int i = 0; i < count; i++ ) {
|
||||||
|
list [i] = atoi ( text );
|
||||||
|
while ( isdigit ( *text )) text++;
|
||||||
|
if ( *text == ',' ) text++;
|
||||||
|
while ( isspace ( *text )) text++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( close == true ) text++;
|
||||||
|
|
||||||
|
list [count] = -1;
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseGeneric ( char *text, const sOptionTableInfo &info, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseGeneric", true );
|
||||||
|
|
||||||
|
int dataIndex = 0;
|
||||||
|
int listIndex = 0;
|
||||||
|
|
||||||
|
const char *syntax = info.Syntax;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if ( syntax != NULL ) while ( *syntax ) {
|
||||||
|
while ( isspace ( *text )) text++;
|
||||||
|
switch ( *syntax++ ) {
|
||||||
|
case 'N' :
|
||||||
|
option->Data [dataIndex++] = ParseNumber ( text );
|
||||||
|
break;
|
||||||
|
case 'L' :
|
||||||
|
option->List [listIndex++] = ParseList ( text, ( *syntax != '\0' ) ? true : false );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( isspace ( *text )) text++;
|
||||||
|
if (( *text != '\0' ) && ( *text != '#' )) throw "unexpected characters after command";
|
||||||
|
|
||||||
|
option->Info = &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch ( const char *message ) {
|
||||||
|
ParseError ( "Syntax error - %s.", message );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseMap ( char *text, const sOptionTableInfo &info, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
option->Info = &info;
|
||||||
|
|
||||||
|
while ( ! isdigit ( *text )) text--;
|
||||||
|
|
||||||
|
switch ( info.Type ) {
|
||||||
|
case OPTION_MAP_1 :
|
||||||
|
option->Data [0] = text [-2] - '0';
|
||||||
|
option->Data [1] = text [0] - '0';
|
||||||
|
break;
|
||||||
|
case OPTION_MAP_2 :
|
||||||
|
option->Data [0] = ( text [-1] - '0' ) * 10 + ( text [0] - '0' );
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
ParseError ( "Unable to parse map name" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseBAND ( char *text, const sOptionTableInfo &info, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseBAND", true );
|
||||||
|
|
||||||
|
REJECT_OPTION_E type = OPTION_UNKNOWN;
|
||||||
|
|
||||||
|
while ( isspace ( *text )) text++;
|
||||||
|
|
||||||
|
if ( strncmp ( text, "BLIND", 5 ) == 0 ) {
|
||||||
|
type = OPTION_BLIND;
|
||||||
|
text += 5;
|
||||||
|
} else if ( strncmp ( text, "SAFE", 5 ) == 0 ) {
|
||||||
|
type = OPTION_SAFE;
|
||||||
|
text += 4;
|
||||||
|
} else {
|
||||||
|
goto bad_option;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isspace ( *text )) {
|
||||||
|
bool retVal = ParseGeneric ( text, info, option );
|
||||||
|
option->Banded = true;
|
||||||
|
option->Info = FindByType ( type );
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bad_option:
|
||||||
|
|
||||||
|
ParseError ( "Invalid BAND option." );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseINVERT ( char *text, const sOptionTableInfo &info, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseINVERT", true );
|
||||||
|
|
||||||
|
if ( ParseOptionRMB ( -1, text, option ) == true ) {
|
||||||
|
switch ( option->Info->Type ) {
|
||||||
|
case OPTION_BAND :
|
||||||
|
case OPTION_BLIND :
|
||||||
|
case OPTION_SAFE :
|
||||||
|
option->Inverted = true;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
ParseError ( "Invalid %s option '%s'.", info.Name, text );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ParseError ( "Unable to process %s effect.", info.Name );
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseNOPROCESS ( char *text, const sOptionTableInfo &info, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseNOPROCESS", true );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ParseOptionRMB ( int lineNumber, const char *lineText, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ParseOptionRMB", true );
|
||||||
|
|
||||||
|
ASSERT ( lineText != NULL );
|
||||||
|
ASSERT ( option != NULL );
|
||||||
|
|
||||||
|
if ( lineNumber > 0 ) {
|
||||||
|
parseLine = lineNumber;
|
||||||
|
parseText = lineText;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset ( option, 0, sizeof ( sRejectOptionRMB ));
|
||||||
|
|
||||||
|
const char *srcText = lineText;
|
||||||
|
while (( *srcText != '\0' ) && ( isspace ( *srcText ))) srcText++;
|
||||||
|
|
||||||
|
if (( *srcText == '#' ) || ( *srcText == '\0' )) return false;
|
||||||
|
|
||||||
|
size_t length = strlen ( srcText );
|
||||||
|
char *buffer = new char [ length + 1 ];
|
||||||
|
for ( size_t i = 0; i < length; i++ ) {
|
||||||
|
buffer [i] = toupper ( srcText [i] );
|
||||||
|
if (( buffer [i] == '\r' ) || ( buffer [i] == '\n' )) length = i;
|
||||||
|
}
|
||||||
|
buffer [length] = '\0';
|
||||||
|
|
||||||
|
char *start = buffer;
|
||||||
|
char *end = buffer;
|
||||||
|
while (( *end != '\0' ) && ( ! isspace ( *end ))) end++;
|
||||||
|
|
||||||
|
bool retVal = false;
|
||||||
|
|
||||||
|
if ( start != end ) {
|
||||||
|
|
||||||
|
for ( unsigned i = 0; i < SIZE ( ParseTable ); i++ ) {
|
||||||
|
char *src = start;
|
||||||
|
const char *tgt = ParseTable [i].Name;
|
||||||
|
while (( src != end ) && ( *tgt != '\0' )) {
|
||||||
|
if ( *src != *tgt ) {
|
||||||
|
if ( *tgt != '*' ) goto next;
|
||||||
|
if ( ! isdigit ( *src )) goto next;
|
||||||
|
}
|
||||||
|
src++;
|
||||||
|
tgt++;
|
||||||
|
}
|
||||||
|
if (( i + 1 < SIZE ( ParseTable )) && ( strncmp ( buffer, ParseTable [i+1].Name, src - buffer ) == 0 )) {
|
||||||
|
ParseError ( "'%*.*s' is not a unique identifier.", end - buffer, end - buffer, buffer );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
while ( isspace ( *end )) end++;
|
||||||
|
retVal = ParseTable [i].ParseFunction ( end, ParseTable [i], option );
|
||||||
|
goto done;
|
||||||
|
next:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseError ( "Unrecognized effect '%*.*s'.", end - buffer, end - buffer, buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
delete [] buffer;
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintOption ( FILE *file, sRejectOptionRMB *option )
|
||||||
|
{
|
||||||
|
const sOptionTableInfo *info = option->Info;
|
||||||
|
const char *syntax = info->Syntax;
|
||||||
|
|
||||||
|
if ( option->Inverted ) fprintf ( file, "INVERT " );
|
||||||
|
if ( option->Banded ) {
|
||||||
|
syntax = "NNL";
|
||||||
|
fprintf ( file, "BAND " );
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( info->Type ) {
|
||||||
|
case OPTION_MAP_1 :
|
||||||
|
fprintf ( file, "E%dM%d", option->Data [0], option->Data [1] );
|
||||||
|
break;
|
||||||
|
case OPTION_MAP_2 :
|
||||||
|
fprintf ( file, "MAP%02d", option->Data [0] );
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
fprintf ( file, "%s", info->Name );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dataIndex = 0;
|
||||||
|
int listIndex = 0;
|
||||||
|
|
||||||
|
if ( syntax != NULL ) while ( *syntax ) {
|
||||||
|
switch ( *syntax++ ) {
|
||||||
|
case 'N' :
|
||||||
|
fprintf ( file, " %d", option->Data [dataIndex++] );
|
||||||
|
break;
|
||||||
|
case 'L' :
|
||||||
|
int *list;
|
||||||
|
fprintf ( file, " (" );
|
||||||
|
list = option->List [listIndex++];
|
||||||
|
while ( *list != -1 ) fprintf ( file, " %d", *list++ );
|
||||||
|
fprintf ( file, " )" );
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
fprintf ( stderr, "Internal error: Invalid syntax\n" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( file, "\n" );
|
||||||
|
}
|
198
ZenNode/ZenReject-util.cpp
Normal file
198
ZenNode/ZenReject-util.cpp
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
void DotGraph ( sGraph *graph )
|
||||||
|
{
|
||||||
|
int maxMetric = 0;
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
if ( graph->sector [x]->metric > maxMetric ) maxMetric = graph->sector [x]->metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( stderr, "digraph g {\n" );
|
||||||
|
fprintf ( stderr, "\tsize = \"12,12\";\n" );
|
||||||
|
fprintf ( stderr, "\tnode [shape=record];\n" );
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
sSector *sec1 = graph->sector [x];
|
||||||
|
if ( sec1->graphParent != NULL ) fprintf ( stderr, "\t%d -> %d%s;\n", sec1->graphParent->index, sec1->index, ( sec1->loDFS < sec1->indexDFS ) ? " [color=green]" : "" );
|
||||||
|
for ( int i = 0; i < sec1->noNeighbors; i++ ) {
|
||||||
|
sSector *sec2 = sec1->neighbor [i];
|
||||||
|
if ( sec1->graphParent == sec2 ) continue;
|
||||||
|
if (( sec2->graphParent != sec1 ) && ( sec1->index > sec2->index )) fprintf ( stderr, "\t%d -> %d [color=red];\n", sec1->index, sec2->index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
sSector *sec = graph->sector [x];
|
||||||
|
fprintf ( stderr, "\t%d [label=\"%d | { %d | %d | %d } | %d\"];\n", sec->index, sec->loDFS, sec->index, sec->indexDFS, sec->metric, sec->hiDFS );
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( stderr, "}\n" );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeatoGraph ( sGraph *graph )
|
||||||
|
{
|
||||||
|
int maxMetric = 0;
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
if ( graph->sector [x]->metric > maxMetric ) maxMetric = graph->sector [x]->metric;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( stderr, "graph g {\n" );
|
||||||
|
fprintf ( stderr, "\tsize = \"12,12\";\n" );
|
||||||
|
fprintf ( stderr, "\tnode [style=filled,fontcolor=white];\n" );
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
sSector *sec1 = graph->sector [x];
|
||||||
|
for ( int i = 0; i < sec1->noNeighbors; i++ ) {
|
||||||
|
sSector *sec2 = sec1->neighbor [i];
|
||||||
|
if ( sec1->index < sec2->index ) fprintf ( stderr, "\t%d -- %d;\n", sec1->index, sec2->index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) {
|
||||||
|
sSector *sec = graph->sector [x];
|
||||||
|
int color = ( maxMetric != 0 ) ? ( int ) ( 0xFF * sqrt (( double ) sec->metric / ( double ) maxMetric )) : 0;
|
||||||
|
fprintf ( stderr, "\t%d [color=\"#%02X%02X%02X\"%s];\n", sec->index, color, 0, 0, ( color > 0x80 ) ? ",fontcolor=black" : "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf ( stderr, "}\n" );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpGraph ( sGraph *graph )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "%08X:", graph );
|
||||||
|
for ( int x = 0; x < graph->noSectors; x++ ) fprintf ( stderr, " %d", graph->sector [x]->index );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintGraph ( sGraph *graph )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "%08X:\n", graph );
|
||||||
|
|
||||||
|
int artCount = 0, childCount = 0;
|
||||||
|
|
||||||
|
for ( int i = 0; i < graph->noSectors; i++ ) {
|
||||||
|
sSector *sec = graph->sector [i];
|
||||||
|
if ( sec->isArticulation == true ) artCount++;
|
||||||
|
if ( sec->noChildren > 0 ) childCount++;
|
||||||
|
fprintf ( stderr, " %4d(%4d-%4d,%4d,%7d)%s %4d %3d/%3d", sec->index, sec->loDFS, sec->indexDFS, sec->hiDFS, sec->metric, sec->isArticulation ? "*" : " ", sec->noChildren, sec->noActiveNeighbors, sec->noNeighbors );
|
||||||
|
if ( sec->noActiveNeighbors == 2 ) {
|
||||||
|
sSector *sec1 = sec->neighbor [0];
|
||||||
|
sSector *sec2 = sec->neighbor [1];
|
||||||
|
if (( sec1->isArticulation == true ) && ( sec2->isArticulation == true )) {
|
||||||
|
fprintf ( stderr, " -step-" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ( sec->parent != NULL ) {
|
||||||
|
sec = sec->parent;
|
||||||
|
fprintf ( stderr, " %4d%s", sec->index, sec->isArticulation ? "*" : "" );
|
||||||
|
}
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
}
|
||||||
|
fprintf ( stderr, " %4d %3d\n", artCount, childCount );
|
||||||
|
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompareREJECT ( UCHAR *srcPtr, UCHAR *tgtPtr, int noSectors )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "CompareREJECT", true );
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
|
||||||
|
int **vis2hid = new int * [ noSectors ];
|
||||||
|
int **hid2vis = new int * [ noSectors ];
|
||||||
|
|
||||||
|
int *v2hCount = new int [ noSectors ];
|
||||||
|
int *h2vCount = new int [ noSectors ];
|
||||||
|
|
||||||
|
int bits = 8;
|
||||||
|
int srcVal = *srcPtr++;
|
||||||
|
int tgtVal = *tgtPtr++;
|
||||||
|
int dif = srcVal ^ tgtVal;
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
vis2hid [i] = new int [ noSectors ];
|
||||||
|
hid2vis [i] = new int [ noSectors ];
|
||||||
|
memset ( vis2hid [i], 0, noSectors * sizeof ( int ));
|
||||||
|
memset ( hid2vis [i], 0, noSectors * sizeof ( int ));
|
||||||
|
v2hCount [i] = 0;
|
||||||
|
h2vCount [i] = 0;
|
||||||
|
for ( int j = 0; j < noSectors; j++ ) {
|
||||||
|
if ( dif & 1 ) {
|
||||||
|
if ( srcVal & 1 ) {
|
||||||
|
hid2vis [i][h2vCount [i]++] = j;
|
||||||
|
} else {
|
||||||
|
vis2hid [i][v2hCount [i]++] = j;
|
||||||
|
}
|
||||||
|
match = false;
|
||||||
|
}
|
||||||
|
if ( --bits == 0 ) {
|
||||||
|
bits = 8;
|
||||||
|
srcVal = *srcPtr++;
|
||||||
|
tgtVal = *tgtPtr++;
|
||||||
|
dif = srcVal ^ tgtVal;
|
||||||
|
} else {
|
||||||
|
srcVal >>= 1;
|
||||||
|
tgtVal >>= 1;
|
||||||
|
dif >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
if (( v2hCount [i] == 0 ) && ( h2vCount [i] == 0 )) continue;
|
||||||
|
bool v2h = false;
|
||||||
|
for ( int j = 0; j < v2hCount [i]; j++ ) {
|
||||||
|
int index = vis2hid [i][j];
|
||||||
|
if (( v2hCount [i] > v2hCount [index] ) ||
|
||||||
|
(( v2hCount [i] == v2hCount [index] ) && ( i > index ))) {
|
||||||
|
v2h = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool h2v = false;
|
||||||
|
for ( int j = 0; j < h2vCount [i]; j++ ) {
|
||||||
|
int index = hid2vis [i][j];
|
||||||
|
if (( h2vCount [i] > h2vCount [index] ) ||
|
||||||
|
(( h2vCount [i] == h2vCount [index] ) && ( i > index ))) {
|
||||||
|
h2v = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( v2h == true ) {
|
||||||
|
if ( first == false ) printf ( " " );
|
||||||
|
printf ( "vis->hid %5d:", i );
|
||||||
|
for ( int j = 0; j < v2hCount [i]; j++ ) {
|
||||||
|
printf ( " %d", vis2hid [i][j] );
|
||||||
|
}
|
||||||
|
printf ( "\n" );
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if ( h2v == true ) {
|
||||||
|
if ( first == false ) printf ( " " );
|
||||||
|
printf ( "hid->vis %5d:", i );
|
||||||
|
for ( int j = 0; j < h2vCount [i]; j++ ) {
|
||||||
|
printf ( " %d", hid2vis [i][j] );
|
||||||
|
}
|
||||||
|
printf ( "\n" );
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( match == true ) printf ( "Perfect Match\n" );
|
||||||
|
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
delete [] vis2hid [i];
|
||||||
|
delete [] hid2vis [i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] vis2hid;
|
||||||
|
delete [] hid2vis;
|
||||||
|
|
||||||
|
delete [] v2hCount;
|
||||||
|
delete [] h2vCount;
|
||||||
|
|
||||||
|
return match ? 0 : 1;
|
||||||
|
}
|
2437
ZenNode/ZenReject.cpp
Normal file
2437
ZenNode/ZenReject.cpp
Normal file
File diff suppressed because it is too large
Load diff
258
ZenNode/blockmap.cpp
Normal file
258
ZenNode/blockmap.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: blockmap.cpp
|
||||||
|
// Date: 14-Jul-1995
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: This module contains the logic for the BLOCKMAP builder.
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "level.hpp"
|
||||||
|
#include "ZenNode.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
void AddLineDef ( sBlockList *block, int line )
|
||||||
|
{
|
||||||
|
if (( block->count % 16 ) == 0 ) {
|
||||||
|
int size = ( block->count + 16 ) * sizeof ( int );
|
||||||
|
block->line = ( int * ) realloc ( block->line, size );
|
||||||
|
}
|
||||||
|
block->line [ block->count++ ] = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
sBlockMap *GenerateBLOCKMAP ( DoomLevel *level )
|
||||||
|
{
|
||||||
|
Status ( "Creating BLOCKMAP ... " );
|
||||||
|
|
||||||
|
const wVertex *vertex = level->GetVertices ();
|
||||||
|
const wLineDef *lineDef = level->GetLineDefs ();
|
||||||
|
|
||||||
|
int xLeft, xRight, yTop, yBottom;
|
||||||
|
xRight = xLeft = vertex [0].x;
|
||||||
|
yTop = yBottom = vertex [0].y;
|
||||||
|
|
||||||
|
for ( int i = 1; i < level->VertexCount (); i++ ) {
|
||||||
|
if ( vertex [i].x < xLeft ) xLeft = vertex [i].x;
|
||||||
|
if ( vertex [i].x > xRight ) xRight = vertex [i].x;
|
||||||
|
if ( vertex [i].y < yBottom ) yBottom = vertex [i].y;
|
||||||
|
if ( vertex [i].y > yTop ) yTop = vertex [i].y;
|
||||||
|
}
|
||||||
|
|
||||||
|
xLeft -= 8; xRight += 8;
|
||||||
|
yBottom -= 8; yTop += 8;
|
||||||
|
|
||||||
|
int noCols = ( xRight - xLeft ) / 128 + 1;
|
||||||
|
int noRows = ( yTop - yBottom ) / 128 + 1;
|
||||||
|
int totalSize = noCols * noRows;
|
||||||
|
|
||||||
|
sBlockList *blockList = new sBlockList [ totalSize ];
|
||||||
|
for ( int i = 0; i < totalSize; i++ ) {
|
||||||
|
blockList [i].firstIndex = i;
|
||||||
|
blockList [i].offset = 0;
|
||||||
|
blockList [i].count = 0;
|
||||||
|
blockList [i].line = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < level->LineDefCount (); i++ ) {
|
||||||
|
|
||||||
|
const wVertex *vertS = &vertex [ lineDef [i].start ];
|
||||||
|
const wVertex *vertE = &vertex [ lineDef [i].end ];
|
||||||
|
|
||||||
|
long x0 = vertS->x - xLeft;
|
||||||
|
long y0 = vertS->y - yBottom;
|
||||||
|
long x1 = vertE->x - xLeft;
|
||||||
|
long y1 = vertE->y - yBottom;
|
||||||
|
|
||||||
|
int startX = x0 / 128, startY = y0 / 128;
|
||||||
|
int endX = x1 / 128, endY = y1 / 128;
|
||||||
|
|
||||||
|
int index = startX + startY * noCols;
|
||||||
|
|
||||||
|
if ( startX == endX ) {
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
if ( startY != endY ) { // vertical line
|
||||||
|
int dy = (( endY - startY ) > 0 ) ? 1 : -1;
|
||||||
|
do {
|
||||||
|
startY += dy;
|
||||||
|
index += dy * noCols;
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
} while ( startY != endY );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( startY == endY ) { // horizontal line
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
int dx = (( endX - startX ) > 0 ) ? 1 : -1;
|
||||||
|
do {
|
||||||
|
startX += dx;
|
||||||
|
index += dx;
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
} while ( startX != endX );
|
||||||
|
} else { // diagonal line
|
||||||
|
|
||||||
|
int dx = ( x1 - x0 );
|
||||||
|
int dy = ( y1 - y0 );
|
||||||
|
|
||||||
|
int sx = ( dx < 0 ) ? -1 : 1;
|
||||||
|
int sy = ( dy < 0 ) ? -1 : 1;
|
||||||
|
|
||||||
|
x1 *= dy;
|
||||||
|
int nextX = x0 * dy;
|
||||||
|
int deltaX = ( startY * 128 + 64 * ( 1 + sy ) - y0 ) * dx;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
int thisX = nextX;
|
||||||
|
nextX += deltaX;
|
||||||
|
if (( sx * sy * nextX ) >= ( sx * sy * x1 )) nextX = x1, done = true;
|
||||||
|
|
||||||
|
int lastIndex = index + nextX / dy / 128 - thisX / dy / 128;
|
||||||
|
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
while ( index != lastIndex ) {
|
||||||
|
index += sx;
|
||||||
|
AddLineDef ( &blockList [ index ], i );
|
||||||
|
}
|
||||||
|
|
||||||
|
index += sy * noCols;
|
||||||
|
deltaX = ( 128 * dx ) * sy;
|
||||||
|
|
||||||
|
} while ( ! done );
|
||||||
|
|
||||||
|
int lastIndex = endX + endY * noCols;
|
||||||
|
if ( index != lastIndex + sy * noCols ) {
|
||||||
|
AddLineDef ( &blockList [ lastIndex ], i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sBlockMap *blockMap = new sBlockMap;
|
||||||
|
blockMap->xOrigin = xLeft;
|
||||||
|
blockMap->yOrigin = yBottom;
|
||||||
|
blockMap->noColumns = noCols;
|
||||||
|
blockMap->noRows = noRows;
|
||||||
|
blockMap->data = blockList;
|
||||||
|
|
||||||
|
return blockMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CreateBLOCKMAP ( DoomLevel *level, const sBlockMapOptions &options )
|
||||||
|
{
|
||||||
|
// Generate the data
|
||||||
|
sBlockMap *blockMap = GenerateBLOCKMAP ( level );
|
||||||
|
|
||||||
|
Status ( "Packing BLOCKMAP ... " );
|
||||||
|
|
||||||
|
sBlockList *blockList = blockMap->data;
|
||||||
|
|
||||||
|
// Count unique blockList elements
|
||||||
|
int totalSize = blockMap->noColumns * blockMap->noRows;
|
||||||
|
int blockListSize = 0, savings = 0;
|
||||||
|
int zeroIndex = -1;
|
||||||
|
for ( int i = 0; i < totalSize; i++ ) {
|
||||||
|
if ( options.Compress ) {
|
||||||
|
if ( blockList [i].count == 0 ) {
|
||||||
|
if ( zeroIndex != -1 ) {
|
||||||
|
blockList [i].firstIndex = zeroIndex;
|
||||||
|
savings += 0 + 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zeroIndex = i;
|
||||||
|
} else {
|
||||||
|
// Only go back to the beginning of the previous row
|
||||||
|
int rowStart = ( i / blockMap->noColumns ) * blockMap->noColumns;
|
||||||
|
int lastStart = rowStart ? rowStart - blockMap->noColumns : 0;
|
||||||
|
int index = i - 1;
|
||||||
|
while ( index >= lastStart ) {
|
||||||
|
int count = blockList[i].count;
|
||||||
|
if (( blockList[index].count == count ) &&
|
||||||
|
( memcmp ( blockList[i].line, blockList[index].line, count * sizeof ( int )) == 0 )) {
|
||||||
|
blockList [i].firstIndex = index;
|
||||||
|
savings += count + 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
if ( index >= lastStart ) continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blockList [i].firstIndex = i;
|
||||||
|
blockListSize += 2 + blockList [i].count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ( "Saving BLOCKMAP ... " );
|
||||||
|
|
||||||
|
int blockSize = sizeof ( wBlockMap ) +
|
||||||
|
totalSize * sizeof ( INT16 ) +
|
||||||
|
blockListSize * sizeof ( INT16 );
|
||||||
|
char *start = new char [ blockSize ];
|
||||||
|
wBlockMap *map = ( wBlockMap * ) start;
|
||||||
|
map->xOrigin = ( INT16 ) blockMap->xOrigin;
|
||||||
|
map->yOrigin = ( INT16 ) blockMap->yOrigin;
|
||||||
|
map->noColumns = ( UINT16 ) blockMap->noColumns;
|
||||||
|
map->noRows = ( UINT16 ) blockMap->noRows;
|
||||||
|
|
||||||
|
// Fill in data & offsets
|
||||||
|
UINT16 *offset = ( UINT16 * ) ( map + 1 );
|
||||||
|
UINT16 *data = offset + totalSize;
|
||||||
|
for ( int i = 0; i < totalSize; i++ ) {
|
||||||
|
sBlockList *block = &blockList [i];
|
||||||
|
if ( block->firstIndex == i ) {
|
||||||
|
block->offset = data - ( UINT16 * ) start;
|
||||||
|
*data++ = 0;
|
||||||
|
for ( int x = 0; x < block->count; x++ ) {
|
||||||
|
*data++ = ( UINT16 ) block->line [x];
|
||||||
|
}
|
||||||
|
*data++ = ( UINT16 ) -1;
|
||||||
|
} else {
|
||||||
|
block->offset = blockList [ block->firstIndex ].offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
|
||||||
|
for ( int i = 0; i < totalSize; i++ ) {
|
||||||
|
if ( blockList [i].offset > 0xFFFF ) {
|
||||||
|
errors = true;
|
||||||
|
}
|
||||||
|
offset [i] = ( UINT16 ) blockList [i].offset;
|
||||||
|
if ( blockList [i].line ) free ( blockList [i].line );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] blockList;
|
||||||
|
delete blockMap;
|
||||||
|
|
||||||
|
if ( errors == true ) {
|
||||||
|
delete [] start;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
level->NewBlockMap ( blockSize, map );
|
||||||
|
|
||||||
|
return savings * sizeof ( INT16 );
|
||||||
|
}
|
462
ZenNode/bspdiff.cpp
Normal file
462
ZenNode/bspdiff.cpp
Normal file
|
@ -0,0 +1,462 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: bspdiff.cpp
|
||||||
|
// Date: 27-Oct-2000
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Compares two BSP structures and report any differences
|
||||||
|
//
|
||||||
|
// Copyright (c) 2000-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined ( __OS2__ )
|
||||||
|
#define INCL_DOS
|
||||||
|
#define INCL_SUB
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <os2.h>
|
||||||
|
#elif defined ( __WIN32__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
#else
|
||||||
|
#error This program must be compiled as a 32-bit app.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "wad.hpp"
|
||||||
|
#include "level.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
#define VERSION "1.0"
|
||||||
|
#define MAX_LEVELS 50
|
||||||
|
|
||||||
|
#define UNSUPPORTED_FEATURE -1
|
||||||
|
#define UNRECOGNIZED_PARAMETER -2
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ )
|
||||||
|
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
#define cprintf printf
|
||||||
|
|
||||||
|
extern char *strupr ( char *ptr );
|
||||||
|
extern int getch ();
|
||||||
|
extern bool kbhit ();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int GCD ( int A, int B )
|
||||||
|
{
|
||||||
|
if ( A < 0 ) A = -A; else if ( A == 0 ) return 1;
|
||||||
|
if ( B < 0 ) B = -B; else if ( B == 0 ) return 1;
|
||||||
|
|
||||||
|
unsigned twos = 0;
|
||||||
|
while ((( A | B ) & 1 ) == 0 ) {
|
||||||
|
twos++;
|
||||||
|
A >>= 1;
|
||||||
|
B >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (( A & 1 ) == 0 ) A >>= 1; // remove other powers of 2
|
||||||
|
while (( B & 1 ) == 0 ) B >>= 1; // remove other powers of 2
|
||||||
|
|
||||||
|
// A and B both odd at this point!
|
||||||
|
while ( A != B ) {
|
||||||
|
while ( A > B ) {
|
||||||
|
A -= B; // subtractracting smaller odd number
|
||||||
|
// from larger odd number. ( A now even )
|
||||||
|
while (( A & 1 ) == 0 ) A >>= 1; // remove powers of 2
|
||||||
|
}
|
||||||
|
while ( B > A ) {
|
||||||
|
B -= A; // subtractracting smaller odd number
|
||||||
|
// from larger odd number. ( B now even )
|
||||||
|
while (( B & 1 ) == 0 ) B >>= 1; // remove powers of 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( A << twos ); // reapply original powers of two
|
||||||
|
}
|
||||||
|
|
||||||
|
void printHelp ()
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "Usage: nodediff {-options} filename1[.wad] filename2[.wad] [level{+level}]\n" );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " -x+ turn on option -x- turn off option %c = default\n", DEFAULT_CHAR );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " level - ExMy for DOOM / Heretic\n" );
|
||||||
|
fprintf ( stderr, " MAPxx for DOOM II / HEXEN\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseArgs ( int index, const char *argv[] )
|
||||||
|
{
|
||||||
|
bool errors = false;
|
||||||
|
while ( argv [ index ] ) {
|
||||||
|
|
||||||
|
if ( argv [index][0] != '/' ) break;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLevels ( int argIndex, const char *argv[], char names [][MAX_LUMP_NAME], wadList *list )
|
||||||
|
{
|
||||||
|
int index = 0, errors = 0;
|
||||||
|
|
||||||
|
char buffer [128];
|
||||||
|
buffer [0] = '\0';
|
||||||
|
if ( argv [argIndex] ) {
|
||||||
|
strcpy ( buffer, argv [argIndex] );
|
||||||
|
strupr ( buffer );
|
||||||
|
}
|
||||||
|
char *ptr = strtok ( buffer, "+" );
|
||||||
|
|
||||||
|
// See if the user requested specific levels
|
||||||
|
if ( WAD::IsMap ( ptr )) {
|
||||||
|
argIndex++;
|
||||||
|
while ( ptr ) {
|
||||||
|
if ( WAD::IsMap ( ptr ))
|
||||||
|
if ( list->FindWAD ( ptr ))
|
||||||
|
strcpy ( names [index++], ptr );
|
||||||
|
else
|
||||||
|
fprintf ( stderr, " Could not find %s\n", ptr, errors++ );
|
||||||
|
else
|
||||||
|
fprintf ( stderr, " %s is not a valid name for a level\n", ptr, errors++ );
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int size = list->DirSize ();
|
||||||
|
const wadListDirEntry *dir = list->GetDir ( 0 );
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
if ( dir->wad->IsMap ( dir->entry->name )) {
|
||||||
|
if ( index == MAX_LEVELS )
|
||||||
|
fprintf ( stderr, "ERROR: Too many levels in WAD - ignoring %s!\n", dir->entry->name, errors++ );
|
||||||
|
else
|
||||||
|
memcpy ( names [index++], dir->entry->name, MAX_LUMP_NAME );
|
||||||
|
}
|
||||||
|
dir++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset ( names [index], 0, MAX_LUMP_NAME );
|
||||||
|
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
return argIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureExtension ( char *fileName, const char *ext )
|
||||||
|
{
|
||||||
|
size_t length = strlen ( fileName );
|
||||||
|
char *ptr = strrchr ( fileName, '.' );
|
||||||
|
if (( ptr && strchr ( ptr, '\\' )) ||
|
||||||
|
( ! ptr && stricmp ( &fileName[length-4], ext )))
|
||||||
|
strcat ( fileName, ext );
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *TypeName ( eWadType type )
|
||||||
|
{
|
||||||
|
switch ( type ) {
|
||||||
|
case wt_DOOM : return "DOOM";
|
||||||
|
case wt_DOOM2 : return "DOOM2";
|
||||||
|
case wt_HERETIC : return "Heretic";
|
||||||
|
case wt_HEXEN : return "Hexen";
|
||||||
|
default : break;
|
||||||
|
}
|
||||||
|
return "<Unknown>";
|
||||||
|
}
|
||||||
|
|
||||||
|
wadList *getInputFiles ( const char *cmdLine, char *wadFileName )
|
||||||
|
{
|
||||||
|
char *listNames = wadFileName;
|
||||||
|
wadList *myList = new wadList;
|
||||||
|
|
||||||
|
if ( cmdLine == NULL ) return myList;
|
||||||
|
|
||||||
|
char temp [ 256 ];
|
||||||
|
strcpy ( temp, cmdLine );
|
||||||
|
char *ptr = strtok ( temp, "+" );
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
while ( ptr && *ptr ) {
|
||||||
|
char wadName [ 256 ];
|
||||||
|
strcpy ( wadName, ptr );
|
||||||
|
EnsureExtension ( wadName, ".wad" );
|
||||||
|
|
||||||
|
WAD *wad = new WAD ( wadName );
|
||||||
|
if ( wad->Status () != ws_OK ) {
|
||||||
|
const char *msg;
|
||||||
|
switch ( wad->Status ()) {
|
||||||
|
case ws_INVALID_FILE : msg = "The file %s does not exist\n"; break;
|
||||||
|
case ws_CANT_READ : msg = "Can't open the file %s for read access\n"; break;
|
||||||
|
case ws_INVALID_WAD : msg = "%s is not a valid WAD file\n"; break;
|
||||||
|
default : msg = "** Unexpected Error opening %s **\n"; break;
|
||||||
|
}
|
||||||
|
fprintf ( stderr, msg, wadName );
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
if ( ! myList->IsEmpty ()) {
|
||||||
|
cprintf ( "Merging: %s with %s\r\n", wadName, listNames );
|
||||||
|
*wadFileName++ = '+';
|
||||||
|
}
|
||||||
|
if ( myList->Add ( wad ) == false ) {
|
||||||
|
errors++;
|
||||||
|
if ( myList->Type () != wt_UNKNOWN )
|
||||||
|
fprintf ( stderr, "ERROR: %s is not a %s PWAD.\n", wadName, TypeName ( myList->Type ()));
|
||||||
|
else
|
||||||
|
fprintf ( stderr, "ERROR: %s is not the same type.\n", wadName );
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
char *end = wadName + strlen ( wadName ) - 1;
|
||||||
|
while (( end > wadName ) && ( *end != '\\' )) end--;
|
||||||
|
if ( *end == '\\' ) end++;
|
||||||
|
wadFileName += sprintf ( wadFileName, "%s", end );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
if ( wadFileName [-1] == '+' ) wadFileName [-1] = '\0';
|
||||||
|
if ( myList->wadCount () > 1 ) cprintf ( "\r\n" );
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return myList;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline T sgn ( T val ) { return ( val > 0 ) ? 1 : ( val < 0 ) ? -1 : 0; }
|
||||||
|
|
||||||
|
void NormalizeNODES ( wNode *node, int noNodes )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < noNodes; i++ ) {
|
||||||
|
int gcd = GCD ( node [i].dx, node [i].dy );
|
||||||
|
node [i].dx /= gcd;
|
||||||
|
node [i].dy /= gcd;
|
||||||
|
if ( node [i].dx == 0 ) node [i].dy = sgn ( node [i].dy );
|
||||||
|
if ( node [i].dy == 0 ) node [i].dx = sgn ( node [i].dx );
|
||||||
|
if (( node [i].dx < 0 ) || (( node [i].dx == 0 ) && ( node [i].dy < 0 ))) {
|
||||||
|
node [i].dx = -node [i].dx;
|
||||||
|
node [i].dy = -node [i].dy;
|
||||||
|
swap ( node [i].side [0], node [i].side [1] );
|
||||||
|
swap ( node [i].child [0], node [i].child [1] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SortSegs ( const void *ptr1, const void *ptr2 )
|
||||||
|
{
|
||||||
|
int dif = (( wSegs * ) ptr1)->lineDef - (( wSegs * ) ptr2)->lineDef;
|
||||||
|
if ( dif ) return dif;
|
||||||
|
|
||||||
|
return (( wSegs * ) ptr1)->flip - (( wSegs * ) ptr2)->flip ?
|
||||||
|
(( wSegs * ) ptr1)->flip - (( wSegs * ) ptr2)->flip :
|
||||||
|
(( wSegs * ) ptr1)->offset - (( wSegs * ) ptr2)->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinesMatch ( const wNode &node1, const wNode &node2 )
|
||||||
|
{
|
||||||
|
if (( node1.dx != node2.dx ) || ( node1.dy != node2.dy )) return false;
|
||||||
|
|
||||||
|
if ( node1.dx == 0 ) return ( node1.x == node2.x ) ? true : false;
|
||||||
|
if ( node1.dy == 0 ) return ( node1.y == node2.y ) ? true : false;
|
||||||
|
|
||||||
|
double tx = ( double ) ( node2.x - node1.x ) / ( double ) node1.dx;
|
||||||
|
double ty = ( double ) ( node2.y - node1.y ) / ( double ) node1.dy;
|
||||||
|
|
||||||
|
double delta = fabs ( tx - ty );
|
||||||
|
|
||||||
|
if ( delta < 0.001 ) return true;
|
||||||
|
|
||||||
|
if ( delta < 1.000 ) printf ( "tx = %g ty = %g\n", tx, ty );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *locationString;
|
||||||
|
|
||||||
|
void printNode ( const wNode &node, int index )
|
||||||
|
{
|
||||||
|
printf ( "\n%5d - (%5d,%5d) (%5d,%5d) L: %c %5d R: %c %5d",
|
||||||
|
index, node.x, node.y, node.dx, node.dy,
|
||||||
|
( node.child [0] & 0x8000 ) ? 'S' : 'N', node.child [0] & 0x7FFF, ( node.child [1] & 0x8000 ) ? 'S' : 'N', node.child [1] & 0x7FFF );
|
||||||
|
}
|
||||||
|
|
||||||
|
static DoomLevel *srcLevel;
|
||||||
|
static DoomLevel *tgtLevel;
|
||||||
|
|
||||||
|
int CompareSSECTOR ( int srcIndex, int tgtIndex )
|
||||||
|
{
|
||||||
|
srcIndex &= 0x7FFF;
|
||||||
|
tgtIndex &= 0x7FFF;
|
||||||
|
|
||||||
|
// qsort ( segs, noSegs, sizeof ( SEG ), SortSegs );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompareNODE ( int srcIndex, int tgtIndex, char *location )
|
||||||
|
{
|
||||||
|
int length = location - locationString;
|
||||||
|
|
||||||
|
if (( srcIndex & 0x8000 ) != ( tgtIndex & 0x8000 )) {
|
||||||
|
printf ( "\n%*.*s: Leaf != Node", length, length, locationString );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( srcIndex & 0x8000 ) {
|
||||||
|
return CompareSSECTOR ( srcIndex, tgtIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
const wNode &src = srcLevel->GetNodes () [srcIndex];
|
||||||
|
const wNode &tgt = tgtLevel->GetNodes () [tgtIndex];
|
||||||
|
|
||||||
|
if ( LinesMatch ( src, tgt ) == false ) {
|
||||||
|
int length = location - locationString;
|
||||||
|
printf ( "\n%*.*s:", length, length, locationString );
|
||||||
|
printNode ( src, srcIndex );
|
||||||
|
printNode ( tgt, tgtIndex );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
*location = 'R';
|
||||||
|
count += CompareNODE ( src.child [0], tgt.child [0], location + 1 );
|
||||||
|
|
||||||
|
*location = 'L';
|
||||||
|
count += CompareNODE ( src.child [1], tgt.child [1], location + 1 );
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProcessLevel ( char *name, wadList *myList1, wadList *myList2 )
|
||||||
|
{
|
||||||
|
cprintf ( "\r %-*.*s: ", MAX_LUMP_NAME, MAX_LUMP_NAME, name );
|
||||||
|
GetXY ( &startX, &startY );
|
||||||
|
|
||||||
|
int mismatches = 0;
|
||||||
|
|
||||||
|
srcLevel = NULL;
|
||||||
|
tgtLevel = NULL;
|
||||||
|
|
||||||
|
const wadListDirEntry *dir = myList1->FindWAD ( name );
|
||||||
|
srcLevel = new DoomLevel ( name, dir->wad );
|
||||||
|
if ( srcLevel->IsValid ( true ) == false ) {
|
||||||
|
Status ( "This level is not valid... " );
|
||||||
|
mismatches = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = myList2->FindWAD ( name );
|
||||||
|
tgtLevel = new DoomLevel ( name, dir->wad );
|
||||||
|
if ( tgtLevel->IsValid ( true ) == false ) {
|
||||||
|
Status ( "This level is not valid... " );
|
||||||
|
mismatches = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
NormalizeNODES (( wNode * ) srcLevel->GetNodes (), srcLevel->NodeCount ());
|
||||||
|
NormalizeNODES (( wNode * ) tgtLevel->GetNodes (), tgtLevel->NodeCount ());
|
||||||
|
|
||||||
|
int noNodes = max ( srcLevel->NodeCount (), tgtLevel->NodeCount ());
|
||||||
|
|
||||||
|
locationString = new char [ noNodes ];
|
||||||
|
|
||||||
|
mismatches = CompareNODE ( srcLevel->NodeCount () - 1, tgtLevel->NodeCount () - 1, locationString );
|
||||||
|
|
||||||
|
delete [] locationString;
|
||||||
|
|
||||||
|
if ( mismatches == 0 ) Status ( "NODES Match" );
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
cprintf ( "\r\n" );
|
||||||
|
|
||||||
|
delete tgtLevel;
|
||||||
|
delete srcLevel;
|
||||||
|
|
||||||
|
return mismatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ( int argc, const char *argv[] )
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "Compare Version %s (c) 2003-2004 Marc Rousseau\n\n", VERSION );
|
||||||
|
|
||||||
|
if ( argc == 1 ) {
|
||||||
|
printHelp ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveConsoleSettings ();
|
||||||
|
|
||||||
|
int argIndex = 1, changes = 0;
|
||||||
|
|
||||||
|
while ( KeyPressed ()) GetKey ();
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
argIndex = parseArgs ( argIndex, argv );
|
||||||
|
if ( argIndex < 0 ) break;
|
||||||
|
|
||||||
|
char wadFileName1 [ 256 ];
|
||||||
|
wadList *myList1 = getInputFiles ( argv [argIndex++], wadFileName1 );
|
||||||
|
if ( myList1->IsEmpty ()) { changes = -1000; break; }
|
||||||
|
|
||||||
|
char wadFileName2 [ 256 ];
|
||||||
|
wadList *myList2 = getInputFiles ( argv [argIndex++], wadFileName2 );
|
||||||
|
if ( myList2->IsEmpty ()) { changes = -1000; break; }
|
||||||
|
|
||||||
|
cprintf ( "Comparing: %s and %s\r\n\n", wadFileName1, wadFileName2 );
|
||||||
|
|
||||||
|
char levelNames [MAX_LEVELS+1][MAX_LUMP_NAME];
|
||||||
|
argIndex = getLevels ( argIndex, argv, levelNames, myList1 );
|
||||||
|
|
||||||
|
if ( levelNames [0][0] == '\0' ) {
|
||||||
|
fprintf ( stderr, "Unable to find any valid levels in %s\n", wadFileName1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int noLevels = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
changes += ProcessLevel ( levelNames [noLevels++], myList1, myList2 );
|
||||||
|
if ( KeyPressed () && ( GetKey () == 0x1B )) break;
|
||||||
|
|
||||||
|
} while ( levelNames [noLevels][0] );
|
||||||
|
|
||||||
|
cprintf ( "\r\n" );
|
||||||
|
|
||||||
|
delete myList1;
|
||||||
|
delete myList2;
|
||||||
|
|
||||||
|
} while ( argv [argIndex] );
|
||||||
|
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
439
ZenNode/bspinfo.cpp
Normal file
439
ZenNode/bspinfo.cpp
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: bspinfo.cpp
|
||||||
|
// Date: 11-Oct-1995
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: An application to analyze the contents of a BSP tree
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
#include "wad.hpp"
|
||||||
|
#include "level.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
#if defined ( __OS2__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <io.h>
|
||||||
|
#elif defined ( __WIN32__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <io.h>
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#error This program must be compiled as a 32-bit app.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DBG_REGISTER ( __FILE__ );
|
||||||
|
|
||||||
|
#define VERSION "1.3"
|
||||||
|
#define BANNER "BSPInfo Version " VERSION " (c) 1995-2004 Marc Rousseau"
|
||||||
|
#define MAX_LEVELS 99
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
|
||||||
|
extern char *strupr ( char *ptr );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool Tree;
|
||||||
|
} flags;
|
||||||
|
|
||||||
|
void printHelp ()
|
||||||
|
{
|
||||||
|
fprintf ( stderr, "Usage: bspInfo [-options] filename[.wad] [level[+level]]\n" );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " -x+ turn on option -x- turn off option %c = default\n", DEFAULT_CHAR );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " -t - Display NODE tree\n" );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " level - ExMy for DOOM / Heretic\n" );
|
||||||
|
fprintf ( stderr, " MAPxx for DOOM II / HEXEN\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseArgs ( int index, const char *argv [] )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "parseArgs", true );
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
while ( argv [ index ] ) {
|
||||||
|
|
||||||
|
if ( argv [index][0] != '-' ) break;
|
||||||
|
|
||||||
|
char *localCopy = strdup ( argv [ index ]);
|
||||||
|
char *ptr = localCopy + 1;
|
||||||
|
strupr ( localCopy );
|
||||||
|
|
||||||
|
bool localError = false;
|
||||||
|
while ( *ptr && ( localError == false )) {
|
||||||
|
int option = *ptr++;
|
||||||
|
bool setting = true;
|
||||||
|
if (( *ptr == '+' ) || ( *ptr == '-' )) {
|
||||||
|
setting = ( *ptr == '-' ) ? false : true;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
switch ( option ) {
|
||||||
|
case 'T' : flags.Tree = setting; break;
|
||||||
|
default : localError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( localError ) {
|
||||||
|
errors = true;
|
||||||
|
int offset = ptr - localCopy - 1;
|
||||||
|
size_t width = strlen ( ptr ) + 1;
|
||||||
|
fprintf ( stderr, "Unrecognized parameter '%*.*s'\n", width, width, argv [index] + offset );
|
||||||
|
}
|
||||||
|
free ( localCopy );
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLevels ( int argIndex, const char *argv [], char names [][MAX_LUMP_NAME], wadList *list )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "getLevels", true );
|
||||||
|
|
||||||
|
int index = 0, errors = 0;
|
||||||
|
|
||||||
|
char buffer [128];
|
||||||
|
buffer [0] = '\0';
|
||||||
|
if ( argv [argIndex] ) {
|
||||||
|
strcpy ( buffer, argv [argIndex] );
|
||||||
|
strupr ( buffer );
|
||||||
|
}
|
||||||
|
char *ptr = strtok ( buffer, "+" );
|
||||||
|
|
||||||
|
// See if the user requested specific levels
|
||||||
|
if ( WAD::IsMap ( ptr )) {
|
||||||
|
argIndex++;
|
||||||
|
while ( ptr ) {
|
||||||
|
if ( WAD::IsMap ( ptr )) {
|
||||||
|
if ( list->FindWAD ( ptr )) {
|
||||||
|
strcpy ( names [index++], ptr );
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, " Could not find %s\n", ptr, errors++ );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, " %s is not a valid name for a level\n", ptr, errors++ );
|
||||||
|
}
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int size = list->DirSize ();
|
||||||
|
const wadListDirEntry *dir = list->GetDir ( 0 );
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
if ( dir->wad->IsMap ( dir->entry->name )) {
|
||||||
|
// Make sure it's really a level
|
||||||
|
if ( strcmp ( dir[1].entry->name, "THINGS" ) == 0 ) {
|
||||||
|
if ( index == MAX_LEVELS ) {
|
||||||
|
fprintf ( stderr, "ERROR: Too many levels in WAD - ignoring %s!\n", dir->entry->name, errors++ );
|
||||||
|
} else {
|
||||||
|
memcpy ( names [index++], dir->entry->name, MAX_LUMP_NAME );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dir++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset ( names [index], 0, MAX_LUMP_NAME );
|
||||||
|
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return argIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureExtension ( char *fileName, const char *ext )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "EnsureExtension", true );
|
||||||
|
|
||||||
|
// See if the file exists first
|
||||||
|
FILE *file = fopen ( fileName, "rb" );
|
||||||
|
if ( file != NULL ) {
|
||||||
|
fclose ( file );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length = strlen ( fileName );
|
||||||
|
if ( stricmp ( &fileName [length-4], ext ) != 0 ) {
|
||||||
|
strcat ( fileName, ext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *TypeName ( eWadType type )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "TypeName", true );
|
||||||
|
|
||||||
|
const char *name = NULL;
|
||||||
|
switch ( type ) {
|
||||||
|
case wt_DOOM : name = "DOOM"; break;
|
||||||
|
case wt_DOOM2 : name = "DOOM2"; break;
|
||||||
|
case wt_HERETIC : name = "Heretic"; break;
|
||||||
|
case wt_HEXEN : name = "Hexen"; break;
|
||||||
|
default : name = "<Unknown>"; break;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
wadList *getInputFiles ( const char *cmdLine, char *wadFileName )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "getInputFiles", true );
|
||||||
|
|
||||||
|
char *listNames = wadFileName;
|
||||||
|
wadList *myList = new wadList;
|
||||||
|
|
||||||
|
if ( cmdLine == NULL ) return myList;
|
||||||
|
|
||||||
|
char temp [ 256 ];
|
||||||
|
strcpy ( temp, cmdLine );
|
||||||
|
char *ptr = strtok ( temp, "+" );
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
while ( ptr && *ptr ) {
|
||||||
|
char wadName [ 256 ];
|
||||||
|
strcpy ( wadName, ptr );
|
||||||
|
EnsureExtension ( wadName, ".wad" );
|
||||||
|
|
||||||
|
WAD *wad = new WAD ( wadName );
|
||||||
|
if ( wad->Status () != ws_OK ) {
|
||||||
|
const char *msg;
|
||||||
|
switch ( wad->Status ()) {
|
||||||
|
case ws_INVALID_FILE : msg = "The file %s does not exist\n"; break;
|
||||||
|
case ws_CANT_READ : msg = "Can't open the file %s for read access\n"; break;
|
||||||
|
case ws_INVALID_WAD : msg = "%s is not a valid WAD file\n"; break;
|
||||||
|
default : msg = "** Unexpected Error opening %s **\n"; break;
|
||||||
|
}
|
||||||
|
fprintf ( stderr, msg, wadName );
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
if ( ! myList->IsEmpty ()) {
|
||||||
|
cprintf ( "Merging: %s with %s\r\n", wadName, listNames );
|
||||||
|
*wadFileName++ = '+';
|
||||||
|
}
|
||||||
|
if ( myList->Add ( wad ) == false ) {
|
||||||
|
errors++;
|
||||||
|
if ( myList->Type () != wt_UNKNOWN ) {
|
||||||
|
fprintf ( stderr, "ERROR: %s is not a %s PWAD.\n", wadName, TypeName ( myList->Type ()));
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, "ERROR: %s is not the same type.\n", wadName );
|
||||||
|
}
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
char *end = wadName + strlen ( wadName ) - 1;
|
||||||
|
while (( end > wadName ) && ( *end != SEPERATOR )) end--;
|
||||||
|
if ( *end == SEPERATOR ) end++;
|
||||||
|
wadFileName += sprintf ( wadFileName, "%s", end );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( wadFileName [-1] == '+' ) wadFileName [-1] = '\0';
|
||||||
|
if ( myList->wadCount () > 1 ) cprintf ( "\r\n" );
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return myList;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wNode *nodes;
|
||||||
|
int totalDepth;
|
||||||
|
|
||||||
|
int Traverse ( int index, int depth, int &diagonals, int &balance, int &lChildren, int &rChildren )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "Traverse", false );
|
||||||
|
|
||||||
|
const wNode *node = &nodes [ index ];
|
||||||
|
|
||||||
|
if ( flags.Tree ) printf ( "(%5d,%5d) [%5d,%5d]\n", node->x, node->y, node->dx, node->dy );
|
||||||
|
|
||||||
|
if (( node->dx != 0 ) && ( node->dy != 0 )) diagonals++;
|
||||||
|
|
||||||
|
int lIndex = node->child [0];
|
||||||
|
int rIndex = node->child [1];
|
||||||
|
|
||||||
|
if (( lIndex & 0x8000 ) == ( rIndex & 0x8000 )) balance++;
|
||||||
|
|
||||||
|
int lDepth = 0, rDepth = 0;
|
||||||
|
|
||||||
|
depth++;
|
||||||
|
|
||||||
|
if ( flags.Tree ) printf ( "%5d %*.*sLeft - ", depth, depth*2, depth*2, "" );
|
||||||
|
|
||||||
|
if (( lIndex & 0x8000 ) == 0 ) {
|
||||||
|
int left = 0, right = 0;
|
||||||
|
lDepth = Traverse ( lIndex, depth, diagonals, balance, left, right );
|
||||||
|
lChildren = 1 + left + right;
|
||||||
|
} else {
|
||||||
|
if ( flags.Tree ) printf ( "** NONE **\n" );
|
||||||
|
lDepth = depth;
|
||||||
|
totalDepth += depth + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( flags.Tree ) printf ( "%5d %*.*sRight - ", depth, depth*2, depth*2, "" );
|
||||||
|
|
||||||
|
if (( rIndex & 0x8000 ) == 0 ) {
|
||||||
|
int left = 0, right = 0;
|
||||||
|
rDepth = Traverse ( rIndex, depth, diagonals, balance, left, right );
|
||||||
|
rChildren = 1 + left + right;
|
||||||
|
} else {
|
||||||
|
if ( flags.Tree ) printf ( "** NONE **\n" );
|
||||||
|
rDepth = depth;
|
||||||
|
totalDepth += depth + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (( lDepth > rDepth ) ? lDepth : rDepth );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyzeBSP ( DoomLevel *curLevel )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "AnalyzeBSP", true );
|
||||||
|
|
||||||
|
if ( curLevel->IsValid ( true, true ) == false ) {
|
||||||
|
printf ( "******** Invalid level ********" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
totalDepth = 0;
|
||||||
|
|
||||||
|
nodes = curLevel->GetNodes ();
|
||||||
|
int balance = 0, diagonals = 0;
|
||||||
|
if ( flags.Tree ) printf ( "\n\nROOT: " );
|
||||||
|
|
||||||
|
int left = 0;
|
||||||
|
int right = 0;
|
||||||
|
int depth = Traverse ( curLevel->NodeCount () - 1, 0, diagonals, balance, left, right );
|
||||||
|
|
||||||
|
const wSegs *seg = curLevel->GetSegs ();
|
||||||
|
const wLineDef *lineDef = curLevel->GetLineDefs ();
|
||||||
|
|
||||||
|
bool *lineUsed = new bool [ curLevel->LineDefCount ()];
|
||||||
|
memset ( lineUsed, false, sizeof ( bool ) * curLevel->LineDefCount ());
|
||||||
|
for ( int i = 0; i < curLevel->SegCount (); i++, seg++ ) {
|
||||||
|
lineUsed [ seg->lineDef ] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sideDefs = 0;
|
||||||
|
for ( int i = 0; i < curLevel->LineDefCount (); i++ ) {
|
||||||
|
if ( lineUsed [i] == false ) continue;
|
||||||
|
if ( lineDef[i].sideDef[0] != NO_SIDEDEF ) sideDefs++;
|
||||||
|
if ( lineDef[i].sideDef[1] != NO_SIDEDEF ) sideDefs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int splits = curLevel->SegCount () - sideDefs;
|
||||||
|
|
||||||
|
int noLeafs = curLevel->SubSectorCount ();
|
||||||
|
int optDepth = ( int ) ceil ( log (( float ) noLeafs ) / log ( 2.0 ));
|
||||||
|
int maxLeafs = ( int ) pow ( 2, optDepth );
|
||||||
|
int minDepth = noLeafs * ( optDepth + 1 ) - maxLeafs;
|
||||||
|
int maxDepth = noLeafs * (( noLeafs - 1 ) / 2 + 1 ) - 1;
|
||||||
|
|
||||||
|
double minScore = ( double ) minDepth / ( double ) maxDepth;
|
||||||
|
double score = ( double ) minDepth / ( double ) totalDepth;
|
||||||
|
score = ( score - minScore ) / ( 1 - minScore );
|
||||||
|
|
||||||
|
if ( ! flags.Tree ) {
|
||||||
|
float avgDepth = noLeafs ? ( float ) totalDepth / ( float ) noLeafs : 0;
|
||||||
|
printf ( "%2d ", depth );
|
||||||
|
printf ( "%4.1f ", avgDepth );
|
||||||
|
printf ( "%5.3f ", score );
|
||||||
|
printf ( "%5.3f ", ( left < right ) ? ( double ) left / ( double ) right : ( double ) right / ( double ) left );
|
||||||
|
printf ( "%5d - %4.1f%% ", splits, 100.0 * splits / sideDefs );
|
||||||
|
printf ( "%5d - %4.1f%% ", diagonals, 100.0 * diagonals / curLevel->NodeCount ());
|
||||||
|
printf ( "%5d ", curLevel->NodeCount ());
|
||||||
|
printf ( "%5d", curLevel->SegCount ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ( int argc, const char *argv[] )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "main", true );
|
||||||
|
|
||||||
|
SaveConsoleSettings ();
|
||||||
|
|
||||||
|
cprintf ( "%s\r\n\r\n", BANNER );
|
||||||
|
if ( ! isatty ( fileno ( stdout ))) fprintf ( stdout, "%s\n\n", BANNER );
|
||||||
|
if ( ! isatty ( fileno ( stderr ))) fprintf ( stderr, "%s\n\n", BANNER );
|
||||||
|
|
||||||
|
if ( argc == 1 ) {
|
||||||
|
printHelp ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags.Tree = false;
|
||||||
|
|
||||||
|
int argIndex = 1;
|
||||||
|
do {
|
||||||
|
|
||||||
|
argIndex = parseArgs ( argIndex, argv );
|
||||||
|
if ( argIndex < 0 ) break;
|
||||||
|
|
||||||
|
char wadFileName [ 256 ];
|
||||||
|
wadList *myList = getInputFiles ( argv [argIndex++], wadFileName );
|
||||||
|
if ( myList->IsEmpty ()) break;
|
||||||
|
printf ( "Analyzing: %s\n\n", wadFileName );
|
||||||
|
|
||||||
|
char levelNames [MAX_LEVELS+1][MAX_LUMP_NAME];
|
||||||
|
argIndex = getLevels ( argIndex, argv, levelNames, myList );
|
||||||
|
|
||||||
|
if ( levelNames [0][0] == '\0' ) {
|
||||||
|
fprintf ( stderr, "Unable to find any valid levels in %s\n", wadFileName );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! flags.Tree ) {
|
||||||
|
printf ( " Max Avg\n" );
|
||||||
|
printf ( " Depth Depth FOM Balance Splits Diagonals Nodes Segs\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int noLevels = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
const wadListDirEntry *dir = myList->FindWAD ( levelNames [ noLevels ]);
|
||||||
|
DoomLevel *curLevel = new DoomLevel ( levelNames [ noLevels ], dir->wad );
|
||||||
|
printf ( "%8.8s: ", levelNames [ noLevels++ ]);
|
||||||
|
AnalyzeBSP ( curLevel );
|
||||||
|
printf ( "\n" );
|
||||||
|
delete curLevel;
|
||||||
|
|
||||||
|
} while ( levelNames [noLevels][0] );
|
||||||
|
|
||||||
|
printf ( "\n" );
|
||||||
|
|
||||||
|
delete myList;
|
||||||
|
|
||||||
|
} while ( argv [argIndex] );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
494
ZenNode/compare.cpp
Normal file
494
ZenNode/compare.cpp
Normal file
|
@ -0,0 +1,494 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: compare.cpp
|
||||||
|
// Date: 16-Jan-1996
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Compares two REJECT structures and report any differences
|
||||||
|
//
|
||||||
|
// Copyright (c) 1996-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined ( __OS2__ )
|
||||||
|
#define INCL_DOS
|
||||||
|
#define INCL_SUB
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <os2.h>
|
||||||
|
#elif defined ( __WIN32__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincon.h>
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
#include <unistd.h>
|
||||||
|
#else
|
||||||
|
#error This program must be compiled as a 32-bit app.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
#include "wad.hpp"
|
||||||
|
#include "level.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
DBG_REGISTER ( __FILE__ );
|
||||||
|
|
||||||
|
#define VERSION "1.3"
|
||||||
|
#define BANNER "compare Version " VERSION " (c) 1996-2004 Marc Rousseau"
|
||||||
|
#define MAX_LEVELS 99
|
||||||
|
|
||||||
|
#define UNSUPPORTED_FEATURE -1
|
||||||
|
#define UNRECOGNIZED_PARAMETER -2
|
||||||
|
|
||||||
|
#if defined ( __BORLANDC__ )
|
||||||
|
#pragma option -x -xf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
|
||||||
|
extern char *strupr ( char *ptr );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void printHelp ()
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "printHelp", true );
|
||||||
|
|
||||||
|
fprintf ( stderr, "Usage: compare {-options} filename1[.wad] filename2[.wad] [level{+level}]\n" );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " -x+ turn on option -x- turn off option %c = default\n", DEFAULT_CHAR );
|
||||||
|
fprintf ( stderr, "\n" );
|
||||||
|
fprintf ( stderr, " level - ExMy for DOOM / Heretic\n" );
|
||||||
|
fprintf ( stderr, " MAPxx for DOOM II / HEXEN\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int parseArgs ( int index, const char *argv[] )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "parseArgs", true );
|
||||||
|
|
||||||
|
bool errors = false;
|
||||||
|
while ( argv [ index ] ) {
|
||||||
|
|
||||||
|
if ( argv [index][0] != '-' ) break;
|
||||||
|
|
||||||
|
char *localCopy = strdup ( argv [ index ]);
|
||||||
|
char *ptr = localCopy + 1;
|
||||||
|
strupr ( localCopy );
|
||||||
|
|
||||||
|
bool localError = false;
|
||||||
|
while ( *ptr && ( localError == false )) {
|
||||||
|
int option = *ptr++;
|
||||||
|
bool setting = true;
|
||||||
|
if (( *ptr == '+' ) || ( *ptr == '-' )) {
|
||||||
|
setting = ( *ptr == '-' ) ? false : true;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
switch ( option ) {
|
||||||
|
case -1 :
|
||||||
|
default : localError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( localError ) {
|
||||||
|
errors = true;
|
||||||
|
int offset = ptr - localCopy - 1;
|
||||||
|
size_t width = strlen ( ptr ) + 1;
|
||||||
|
fprintf ( stderr, "Unrecognized parameter '%*.*s'\n", width, width, argv [index] + offset );
|
||||||
|
}
|
||||||
|
free ( localCopy );
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getLevels ( int argIndex, const char *argv[], char names [][MAX_LUMP_NAME], wadList *list1, wadList *list2 )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "getLevels", true );
|
||||||
|
|
||||||
|
int index = 0, errors = 0;
|
||||||
|
|
||||||
|
char buffer [128];
|
||||||
|
buffer [0] = '\0';
|
||||||
|
if ( argv [argIndex] ) {
|
||||||
|
strcpy ( buffer, argv [argIndex] );
|
||||||
|
strupr ( buffer );
|
||||||
|
}
|
||||||
|
char *ptr = strtok ( buffer, "+" );
|
||||||
|
|
||||||
|
// See if the user requested specific levels
|
||||||
|
if ( WAD::IsMap ( ptr )) {
|
||||||
|
argIndex++;
|
||||||
|
while ( ptr ) {
|
||||||
|
if ( WAD::IsMap ( ptr )) {
|
||||||
|
if ( list1->FindWAD ( ptr )) {
|
||||||
|
strcpy ( names [index++], ptr );
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, " Could not find %s\n", ptr, errors++ );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, " %s is not a valid name for a level\n", ptr, errors++ );
|
||||||
|
}
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int size = list1->DirSize ();
|
||||||
|
const wadListDirEntry *dir = list1->GetDir ( 0 );
|
||||||
|
for ( int i = 0; i < size; i++ ) {
|
||||||
|
if ( dir->wad->IsMap ( dir->entry->name )) {
|
||||||
|
if ( index == MAX_LEVELS ) {
|
||||||
|
fprintf ( stderr, "ERROR: Too many levels in WAD - ignoring %s!\n", dir->entry->name, errors++ );
|
||||||
|
} else {
|
||||||
|
memcpy ( names [index++], dir->entry->name, MAX_LUMP_NAME );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dir++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset ( names [index], 0, MAX_LUMP_NAME );
|
||||||
|
|
||||||
|
// Remove any maps that aren't in both files
|
||||||
|
for ( int i = 0; names [i][0]; i++ ) {
|
||||||
|
if ( list2->FindWAD ( names [i] ) == NULL ) {
|
||||||
|
memcpy ( names + i, names + i + 1, ( index - i ) * MAX_LUMP_NAME );
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return argIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnsureExtension ( char *fileName, const char *ext )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "EnsureExtension", true );
|
||||||
|
|
||||||
|
// See if the file exists first
|
||||||
|
FILE *file = fopen ( fileName, "rb" );
|
||||||
|
if ( file != NULL ) {
|
||||||
|
fclose ( file );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length = strlen ( fileName );
|
||||||
|
if ( stricmp ( &fileName [length-4], ext ) != 0 ) {
|
||||||
|
strcat ( fileName, ext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *TypeName ( eWadType type )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "TypeName", true );
|
||||||
|
|
||||||
|
const char *name = NULL;
|
||||||
|
switch ( type ) {
|
||||||
|
case wt_DOOM : name = "DOOM"; break;
|
||||||
|
case wt_DOOM2 : name = "DOOM2"; break;
|
||||||
|
case wt_HERETIC : name = "Heretic"; break;
|
||||||
|
case wt_HEXEN : name = "Hexen"; break;
|
||||||
|
default : name = "<Unknown>"; break;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
wadList *getInputFiles ( const char *cmdLine, char *wadFileName )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "getInputFiles", true );
|
||||||
|
|
||||||
|
char *listNames = wadFileName;
|
||||||
|
wadList *myList = new wadList;
|
||||||
|
|
||||||
|
if ( cmdLine == NULL ) return myList;
|
||||||
|
|
||||||
|
char temp [ 256 ];
|
||||||
|
strcpy ( temp, cmdLine );
|
||||||
|
char *ptr = strtok ( temp, "+" );
|
||||||
|
|
||||||
|
int errors = 0;
|
||||||
|
|
||||||
|
while ( ptr && *ptr ) {
|
||||||
|
char wadName [ 256 ];
|
||||||
|
strcpy ( wadName, ptr );
|
||||||
|
EnsureExtension ( wadName, ".wad" );
|
||||||
|
|
||||||
|
WAD *wad = new WAD ( wadName );
|
||||||
|
if ( wad->Status () != ws_OK ) {
|
||||||
|
const char *msg;
|
||||||
|
switch ( wad->Status ()) {
|
||||||
|
case ws_INVALID_FILE : msg = "The file %s does not exist\n"; break;
|
||||||
|
case ws_CANT_READ : msg = "Can't open the file %s for read access\n"; break;
|
||||||
|
case ws_INVALID_WAD : msg = "%s is not a valid WAD file\n"; break;
|
||||||
|
default : msg = "** Unexpected Error opening %s **\n"; break;
|
||||||
|
}
|
||||||
|
fprintf ( stderr, msg, wadName );
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
if ( ! myList->IsEmpty ()) {
|
||||||
|
cprintf ( "Merging: %s with %s\r\n", wadName, listNames );
|
||||||
|
*wadFileName++ = '+';
|
||||||
|
}
|
||||||
|
if ( myList->Add ( wad ) == false ) {
|
||||||
|
errors++;
|
||||||
|
if ( myList->Type () != wt_UNKNOWN ) {
|
||||||
|
fprintf ( stderr, "ERROR: %s is not a %s PWAD.\n", wadName, TypeName ( myList->Type ()));
|
||||||
|
} else {
|
||||||
|
fprintf ( stderr, "ERROR: %s is not the same type.\n", wadName );
|
||||||
|
}
|
||||||
|
delete wad;
|
||||||
|
} else {
|
||||||
|
char *end = wadName + strlen ( wadName ) - 1;
|
||||||
|
while (( end > wadName ) && ( *end != SEPERATOR )) end--;
|
||||||
|
if ( *end == SEPERATOR ) end++;
|
||||||
|
wadFileName += sprintf ( wadFileName, "%s", end );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr = strtok ( NULL, "+" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( wadFileName [-1] == '+' ) wadFileName [-1] = '\0';
|
||||||
|
if ( myList->wadCount () > 1 ) cprintf ( "\r\n" );
|
||||||
|
if ( errors ) fprintf ( stderr, "\n" );
|
||||||
|
|
||||||
|
return myList;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CompareREJECT ( DoomLevel *srcLevel, DoomLevel *tgtLevel )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "CompareREJECT", true );
|
||||||
|
|
||||||
|
bool match = true;
|
||||||
|
int noSectors = srcLevel->SectorCount ();
|
||||||
|
char *srcPtr = ( char * ) srcLevel->GetReject ();
|
||||||
|
char *tgtPtr = ( char * ) tgtLevel->GetReject ();
|
||||||
|
|
||||||
|
int **vis2hid = new int * [ noSectors ];
|
||||||
|
int **hid2vis = new int * [ noSectors ];
|
||||||
|
|
||||||
|
int *v2hCount = new int [ noSectors ];
|
||||||
|
int *h2vCount = new int [ noSectors ];
|
||||||
|
|
||||||
|
int bits = 8;
|
||||||
|
int srcVal = *srcPtr++;
|
||||||
|
int tgtVal = *tgtPtr++;
|
||||||
|
int dif = srcVal ^ tgtVal;
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
vis2hid [i] = new int [ noSectors ];
|
||||||
|
hid2vis [i] = new int [ noSectors ];
|
||||||
|
memset ( vis2hid [i], 0, noSectors * sizeof ( int ));
|
||||||
|
memset ( hid2vis [i], 0, noSectors * sizeof ( int ));
|
||||||
|
v2hCount [i] = 0;
|
||||||
|
h2vCount [i] = 0;
|
||||||
|
for ( int j = 0; j < noSectors; j++ ) {
|
||||||
|
if ( dif & 1 ) {
|
||||||
|
if ( srcVal & 1 ) {
|
||||||
|
hid2vis [i][h2vCount [i]++] = j;
|
||||||
|
} else {
|
||||||
|
vis2hid [i][v2hCount [i]++] = j;
|
||||||
|
}
|
||||||
|
match = false;
|
||||||
|
}
|
||||||
|
if ( --bits == 0 ) {
|
||||||
|
bits = 8;
|
||||||
|
srcVal = *srcPtr++;
|
||||||
|
tgtVal = *tgtPtr++;
|
||||||
|
dif = srcVal ^ tgtVal;
|
||||||
|
} else {
|
||||||
|
srcVal >>= 1;
|
||||||
|
tgtVal >>= 1;
|
||||||
|
dif >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
if (( v2hCount [i] == 0 ) && ( h2vCount [i] == 0 )) continue;
|
||||||
|
bool v2h = false;
|
||||||
|
for ( int j = 0; j < v2hCount [i]; j++ ) {
|
||||||
|
int index = vis2hid [i][j];
|
||||||
|
if (( v2hCount [i] > v2hCount [index] ) ||
|
||||||
|
(( v2hCount [i] == v2hCount [index] ) && ( i > index ))) {
|
||||||
|
v2h = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool h2v = false;
|
||||||
|
for ( int j = 0; j < h2vCount [i]; j++ ) {
|
||||||
|
int index = hid2vis [i][j];
|
||||||
|
if (( h2vCount [i] > h2vCount [index] ) ||
|
||||||
|
(( h2vCount [i] == h2vCount [index] ) && ( i > index ))) {
|
||||||
|
h2v = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( v2h == true ) {
|
||||||
|
if ( first == false ) printf ( " " );
|
||||||
|
printf ( "vis->hid %5d:", i );
|
||||||
|
for ( int j = 0; j < v2hCount [i]; j++ ) {
|
||||||
|
printf ( " %d", vis2hid [i][j] );
|
||||||
|
}
|
||||||
|
printf ( "\n" );
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if ( h2v == true ) {
|
||||||
|
if ( first == false ) printf ( " " );
|
||||||
|
printf ( "hid->vis %5d:", i );
|
||||||
|
for ( int j = 0; j < h2vCount [i]; j++ ) {
|
||||||
|
printf ( " %d", hid2vis [i][j] );
|
||||||
|
}
|
||||||
|
printf ( "\n" );
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( match == true ) printf ( "Perfect Match\n" );
|
||||||
|
|
||||||
|
for ( int i = 0; i < noSectors; i++ ) {
|
||||||
|
delete [] vis2hid [i];
|
||||||
|
delete [] hid2vis [i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] vis2hid;
|
||||||
|
delete [] hid2vis;
|
||||||
|
|
||||||
|
delete [] v2hCount;
|
||||||
|
delete [] h2vCount;
|
||||||
|
|
||||||
|
return match ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProcessLevel ( char *name, wadList *myList1, wadList *myList2 )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "ProcessLevel", true );
|
||||||
|
|
||||||
|
int change;
|
||||||
|
cprintf ( " %-*.*s: ", MAX_LUMP_NAME, MAX_LUMP_NAME, name );
|
||||||
|
GetXY ( &startX, &startY );
|
||||||
|
|
||||||
|
DoomLevel *tgtLevel = NULL;
|
||||||
|
const wadListDirEntry *dir = myList1->FindWAD ( name );
|
||||||
|
DoomLevel *srcLevel = new DoomLevel ( name, dir->wad );
|
||||||
|
if ( srcLevel->IsValid ( true ) == false ) {
|
||||||
|
change = -1000;
|
||||||
|
cprintf ( "The source level is not valid... \r\n" );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = myList2->FindWAD ( name );
|
||||||
|
tgtLevel = new DoomLevel ( name, dir->wad );
|
||||||
|
if ( tgtLevel->IsValid ( true ) == false ) {
|
||||||
|
change = -1000;
|
||||||
|
cprintf ( "The target level is not valid... \r\n" );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ( srcLevel->RejectSize () != tgtLevel->RejectSize ()) {
|
||||||
|
change = -1000;
|
||||||
|
cprintf ( "The reject maps aren't the same size\r\n" );
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
change = CompareREJECT ( srcLevel, tgtLevel );
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
delete tgtLevel;
|
||||||
|
delete srcLevel;
|
||||||
|
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined ( __BORLANDC__ )
|
||||||
|
#include <dir.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main ( int argc, const char *argv[] )
|
||||||
|
{
|
||||||
|
FUNCTION_ENTRY ( NULL, "main", true );
|
||||||
|
|
||||||
|
SaveConsoleSettings ();
|
||||||
|
HideCursor ();
|
||||||
|
|
||||||
|
cprintf ( "%s\r\n\r\n", BANNER );
|
||||||
|
if ( ! isatty ( fileno ( stdout ))) fprintf ( stdout, "%s\n\n", BANNER );
|
||||||
|
if ( ! isatty ( fileno ( stderr ))) fprintf ( stderr, "%s\n\n", BANNER );
|
||||||
|
|
||||||
|
if ( argc == 1 ) {
|
||||||
|
printHelp ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argIndex = 1, changes = 0;
|
||||||
|
|
||||||
|
while ( KeyPressed ()) GetKey ();
|
||||||
|
do {
|
||||||
|
|
||||||
|
argIndex = parseArgs ( argIndex, argv );
|
||||||
|
if ( argIndex < 0 ) break;
|
||||||
|
|
||||||
|
char wadFileName1 [ 256 ];
|
||||||
|
wadList *myList1 = getInputFiles ( argv [argIndex++], wadFileName1 );
|
||||||
|
if ( myList1->IsEmpty ()) { changes = -1000; break; }
|
||||||
|
|
||||||
|
char wadFileName2 [ 256 ];
|
||||||
|
wadList *myList2 = getInputFiles ( argv [argIndex++], wadFileName2 );
|
||||||
|
if ( myList2->IsEmpty ()) { changes = -1000; break; }
|
||||||
|
|
||||||
|
cprintf ( "Comparing: %s and %s\r\n\n", wadFileName1, wadFileName2 );
|
||||||
|
|
||||||
|
char levelNames [MAX_LEVELS+1][MAX_LUMP_NAME];
|
||||||
|
argIndex = getLevels ( argIndex, argv, levelNames, myList1, myList2 );
|
||||||
|
|
||||||
|
if ( levelNames [0][0] == '\0' ) {
|
||||||
|
fprintf ( stderr, "Unable to find any valid levels in %s\n", wadFileName1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int noLevels = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
changes += ProcessLevel ( levelNames [noLevels++], myList1, myList2 );
|
||||||
|
if ( KeyPressed () && ( GetKey () == 0x1B )) break;
|
||||||
|
|
||||||
|
} while ( levelNames [noLevels][0] );
|
||||||
|
|
||||||
|
delete myList1;
|
||||||
|
delete myList2;
|
||||||
|
|
||||||
|
} while ( argv [argIndex] );
|
||||||
|
|
||||||
|
cprintf ( "\r\n" );
|
||||||
|
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
574
ZenNode/console.cpp
Normal file
574
ZenNode/console.cpp
Normal file
|
@ -0,0 +1,574 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: console.cpp
|
||||||
|
// Date: 13-Aug-2000
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Screen I/O routines for ZenNode
|
||||||
|
//
|
||||||
|
// Copyright (c) 2000-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
// 06-??-95 Added Win32 support
|
||||||
|
// 07-19-95 Updated command line & screen logic
|
||||||
|
// 11-19-95 Updated command line again
|
||||||
|
// 12-06-95 Add config & customization file support
|
||||||
|
// 11-??-98 Added Linux support
|
||||||
|
// 04-21-01 Modified Linux code to match Win32 console I/O behavior
|
||||||
|
// 04-26-01 Added SIGABRT to list of 'handled' signals
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined ( __OS2__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <dos.h>
|
||||||
|
#include <io.h>
|
||||||
|
#define INCL_DOS
|
||||||
|
#define INCL_SUB
|
||||||
|
#include <os2.h>
|
||||||
|
#elif defined ( __WIN32__ )
|
||||||
|
#include <conio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
#include <memory.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "level.hpp"
|
||||||
|
#else
|
||||||
|
#error This program must be compiled as a 32-bit app.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
|
||||||
|
static UINT32 curX = 0;
|
||||||
|
static UINT32 curY = 0;
|
||||||
|
|
||||||
|
UINT32 startX, startY;
|
||||||
|
char progress [4] = { 0x7C, 0x2F, 0x2D, 0x5C };
|
||||||
|
int progressIndex;
|
||||||
|
|
||||||
|
#if defined ( __OS2__ )
|
||||||
|
|
||||||
|
static HVIO hVio = 0;
|
||||||
|
static VIOCURSORINFO vioco;
|
||||||
|
static int oldAttr;
|
||||||
|
|
||||||
|
void SaveConsoleSettings ()
|
||||||
|
{
|
||||||
|
VioGetCurType ( &vioco, hVio );
|
||||||
|
oldAttr = vioco.attr;
|
||||||
|
vioco.attr = 0xFFFF;
|
||||||
|
VioSetCurType ( &vioco, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreConsoleSettings ()
|
||||||
|
{
|
||||||
|
vioco.attr = oldAttr;
|
||||||
|
VioSetCurType ( &vioco, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetXY ( UINT32 *x, UINT32 *y )
|
||||||
|
{
|
||||||
|
VioGetCurPos ( y, x, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GotoXY ( UINT32 x, UINT32 y )
|
||||||
|
{
|
||||||
|
curX = x;
|
||||||
|
curY = y;
|
||||||
|
VioSetCurPos ( y, x, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 CurrentTime ()
|
||||||
|
{
|
||||||
|
UINT32 time;
|
||||||
|
DosQuerySysInfo ( QSV_MS_COUNT, QSV_MS_COUNT, &time, 4 );
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Status ( char *message )
|
||||||
|
{
|
||||||
|
int len = strlen ( message );
|
||||||
|
VioWrtCharStr (( BYTE * ) message, len, startY, startX, hVio );
|
||||||
|
VioWrtNChar (( BYTE * ) " ", 80 - ( startX + len ), startY, startX + len, hVio );
|
||||||
|
curY = startY;
|
||||||
|
curX = startX + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoRight ()
|
||||||
|
{
|
||||||
|
VioWrtNChar (( BYTE * ) "R", 1, curY, curX++, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoLeft ()
|
||||||
|
{
|
||||||
|
VioWrtNChar (( BYTE * ) "L", 1, curY, curX - 1 , hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backup ()
|
||||||
|
{
|
||||||
|
curX--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowDone ()
|
||||||
|
{
|
||||||
|
VioWrtNChar (( BYTE * ) "*", 1, curY, curX, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowProgress ()
|
||||||
|
{
|
||||||
|
VioWrtNChar (( BYTE * ) &progress [ progressIndex++ % SIZE ( progress )], 1, curY, curX, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveUp ( int delta )
|
||||||
|
{
|
||||||
|
curY -= delta;
|
||||||
|
VioSetCurPos ( curY, 0, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveDown ( int delta )
|
||||||
|
{
|
||||||
|
curY += delta;
|
||||||
|
VioSetCurPos ( curY, 0, hVio );
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined ( __WIN32__ )
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
#define cprintf _cprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static CONSOLE_SCREEN_BUFFER_INFO screenInfo;
|
||||||
|
static CONSOLE_CURSOR_INFO cursorInfo;
|
||||||
|
static BOOL oldVisible;
|
||||||
|
|
||||||
|
static HANDLE hOutput;
|
||||||
|
static COORD currentPos;
|
||||||
|
|
||||||
|
static LARGE_INTEGER timerFrequency;
|
||||||
|
|
||||||
|
long WINAPI myHandler ( PEXCEPTION_POINTERS )
|
||||||
|
{
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalHandler ( int )
|
||||||
|
{
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
cprintf ( "\r\n" );
|
||||||
|
exit ( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveConsoleSettings ()
|
||||||
|
{
|
||||||
|
hOutput = GetStdHandle ( STD_OUTPUT_HANDLE );
|
||||||
|
GetConsoleCursorInfo ( hOutput, &cursorInfo );
|
||||||
|
GetConsoleScreenBufferInfo ( hOutput, &screenInfo );
|
||||||
|
oldVisible = cursorInfo.bVisible;
|
||||||
|
SetUnhandledExceptionFilter ( myHandler );
|
||||||
|
signal ( SIGBREAK, SignalHandler );
|
||||||
|
signal ( SIGINT, SignalHandler );
|
||||||
|
atexit ( RestoreConsoleSettings );
|
||||||
|
|
||||||
|
QueryPerformanceFrequency ( &timerFrequency );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreConsoleSettings ()
|
||||||
|
{
|
||||||
|
cursorInfo.bVisible = oldVisible;
|
||||||
|
SetConsoleCursorInfo ( hOutput, &cursorInfo );
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideCursor ()
|
||||||
|
{
|
||||||
|
CONSOLE_CURSOR_INFO info = cursorInfo;
|
||||||
|
info.bVisible = FALSE;
|
||||||
|
SetConsoleCursorInfo ( hOutput, &info );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowCursor ()
|
||||||
|
{
|
||||||
|
CONSOLE_CURSOR_INFO info = cursorInfo;
|
||||||
|
info.bVisible = TRUE;
|
||||||
|
SetConsoleCursorInfo ( hOutput, &info );
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetKey ()
|
||||||
|
{
|
||||||
|
int key = 0;
|
||||||
|
UCHAR *ptr = ( UCHAR * ) &key;
|
||||||
|
int ch = getch ();
|
||||||
|
|
||||||
|
if ( ch == 0xE0 ) {
|
||||||
|
*ptr++ = 0x1B;
|
||||||
|
*ptr++ = 0x5B;
|
||||||
|
ch = getch ();
|
||||||
|
switch ( ch ) {
|
||||||
|
case 0x48 : ch = 0x41; break;
|
||||||
|
case 0x50 : ch = 0x42; break;
|
||||||
|
case 0x4D : ch = 0x43; break;
|
||||||
|
case 0x4B : ch = 0x44; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ptr++ = ( UCHAR ) ch;
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyPressed ()
|
||||||
|
{
|
||||||
|
return ( kbhit () != 0 ) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 CurrentTime ()
|
||||||
|
{
|
||||||
|
LARGE_INTEGER time;
|
||||||
|
QueryPerformanceCounter ( &time );
|
||||||
|
|
||||||
|
return ( UINT32 ) ( 1000 * time.QuadPart / timerFrequency.QuadPart );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearScreen ()
|
||||||
|
{
|
||||||
|
DWORD dwActual;
|
||||||
|
COORD origin;
|
||||||
|
origin.X = 0;
|
||||||
|
origin.Y = 0;
|
||||||
|
FillConsoleOutputCharacter ( hOutput, ' ', screenInfo.dwSize.X * screenInfo.dwSize.Y, origin, &dwActual );
|
||||||
|
|
||||||
|
screenInfo.dwCursorPosition.X = 0;
|
||||||
|
screenInfo.dwCursorPosition.Y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetXY ( UINT32 *x, UINT32 *y )
|
||||||
|
{
|
||||||
|
GetConsoleScreenBufferInfo ( hOutput, &screenInfo );
|
||||||
|
*x = screenInfo.dwCursorPosition.X;
|
||||||
|
*y = screenInfo.dwCursorPosition.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GotoXY ( UINT32 x, UINT32 y )
|
||||||
|
{
|
||||||
|
curX = x;
|
||||||
|
curY = y;
|
||||||
|
|
||||||
|
COORD cursor;
|
||||||
|
cursor.X = ( SHORT ) curX;
|
||||||
|
cursor.Y = ( SHORT ) curY;
|
||||||
|
SetConsoleCursorPosition ( hOutput, cursor );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveUp ( int delta )
|
||||||
|
{
|
||||||
|
GetConsoleScreenBufferInfo ( hOutput, &screenInfo );
|
||||||
|
COORD pos;
|
||||||
|
pos.X = ( SHORT ) 0;
|
||||||
|
pos.Y = ( SHORT ) ( screenInfo.dwCursorPosition.Y - delta );
|
||||||
|
SetConsoleCursorPosition ( hOutput, pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveDown ( int delta )
|
||||||
|
{
|
||||||
|
GetConsoleScreenBufferInfo ( hOutput, &screenInfo );
|
||||||
|
COORD pos;
|
||||||
|
pos.X = ( SHORT ) 0;
|
||||||
|
pos.Y = ( SHORT ) ( screenInfo.dwCursorPosition.Y + delta );
|
||||||
|
SetConsoleCursorPosition ( hOutput, pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Status ( char *message )
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
DWORD len = ( DWORD ) strlen ( message );
|
||||||
|
currentPos.X = ( SHORT ) startX;
|
||||||
|
currentPos.Y = ( SHORT ) startY;
|
||||||
|
if ( len != 0 ) {
|
||||||
|
WriteConsoleOutputCharacter ( hOutput, message, len, currentPos, &count );
|
||||||
|
currentPos.X = ( SHORT ) ( currentPos.X + len );
|
||||||
|
}
|
||||||
|
FillConsoleOutputCharacter ( hOutput, ' ', screenInfo.dwSize.X - currentPos.X, currentPos, &count );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoRight ()
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
WriteConsoleOutputCharacter ( hOutput, "R", 1, currentPos, &count );
|
||||||
|
currentPos.X++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoLeft ()
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
currentPos.X--;
|
||||||
|
WriteConsoleOutputCharacter ( hOutput, "L", 1, currentPos, &count );
|
||||||
|
currentPos.X++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backup ()
|
||||||
|
{
|
||||||
|
currentPos.X--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowDone ()
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
WriteConsoleOutputCharacter ( hOutput, "*", 1, currentPos, &count );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowProgress ()
|
||||||
|
{
|
||||||
|
DWORD count;
|
||||||
|
WriteConsoleOutputCharacter ( hOutput, &progress [ progressIndex++ % SIZE ( progress )], 1, currentPos, &count );
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
static FILE *console;
|
||||||
|
static termios stored;
|
||||||
|
static termios term_getch;
|
||||||
|
static termios term_kbhit;
|
||||||
|
static int lastChar;
|
||||||
|
static int keyhit;
|
||||||
|
static bool cursor_visible = true;
|
||||||
|
|
||||||
|
int cprintf ( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start ( args, fmt );
|
||||||
|
|
||||||
|
int ret = vfprintf ( console, fmt, args );
|
||||||
|
|
||||||
|
fflush ( console );
|
||||||
|
|
||||||
|
va_end ( args );
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalHandler ( int signal )
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
memset ( &sa, 0, sizeof ( sa ));
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
switch ( signal ) {
|
||||||
|
case SIGABRT :
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
break;
|
||||||
|
case SIGSEGV :
|
||||||
|
fprintf ( stderr, "Segmentation fault" );
|
||||||
|
case SIGINT :
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
printf ( "\r\n" );
|
||||||
|
exit ( -1 );
|
||||||
|
break;
|
||||||
|
case SIGTSTP :
|
||||||
|
RestoreConsoleSettings ();
|
||||||
|
printf ( "\r\n" );
|
||||||
|
sigaction ( SIGTSTP, &sa, NULL );
|
||||||
|
kill ( getpid (), SIGTSTP );
|
||||||
|
break;
|
||||||
|
case SIGCONT :
|
||||||
|
SaveConsoleSettings ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveConsoleSettings ()
|
||||||
|
{
|
||||||
|
tcgetattr ( 0, &stored );
|
||||||
|
memcpy ( &term_getch, &stored, sizeof ( struct termios ));
|
||||||
|
// Disable echo
|
||||||
|
term_getch.c_lflag &= ~ECHO;
|
||||||
|
// Disable canonical mode, and set buffer size to 1 byte
|
||||||
|
term_getch.c_lflag &= ~ICANON;
|
||||||
|
term_getch.c_cc[VMIN] = 1;
|
||||||
|
|
||||||
|
memcpy ( &term_kbhit, &term_getch, sizeof ( struct termios ));
|
||||||
|
term_kbhit.c_cc[VTIME] = 0;
|
||||||
|
term_kbhit.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
|
// Create a 'console' device
|
||||||
|
console = fopen ( "/dev/tty", "w" );
|
||||||
|
if ( console == NULL ) {
|
||||||
|
console = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
HideCursor ();
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
memset ( &sa, 0, sizeof ( sa ));
|
||||||
|
sa.sa_handler = SignalHandler;
|
||||||
|
sigaction ( SIGINT, &sa, NULL );
|
||||||
|
sigaction ( SIGABRT, &sa, NULL );
|
||||||
|
sigaction ( SIGSEGV, &sa, NULL );
|
||||||
|
sigaction ( SIGTSTP, &sa, NULL );
|
||||||
|
sigaction ( SIGCONT, &sa, NULL );
|
||||||
|
|
||||||
|
atexit ( RestoreConsoleSettings );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreConsoleSettings ()
|
||||||
|
{
|
||||||
|
if ( console != stdout ) {
|
||||||
|
fclose ( console );
|
||||||
|
console = stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
memset ( &sa, 0, sizeof ( sa ));
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigaction ( SIGINT, &sa, NULL );
|
||||||
|
sigaction ( SIGABRT, &sa, NULL );
|
||||||
|
sigaction ( SIGSEGV, &sa, NULL );
|
||||||
|
sigaction ( SIGTSTP, &sa, NULL );
|
||||||
|
sigaction ( SIGCONT, &sa, NULL );
|
||||||
|
|
||||||
|
tcsetattr ( 0, TCSANOW, &stored );
|
||||||
|
|
||||||
|
ShowCursor ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HideCursor ()
|
||||||
|
{
|
||||||
|
if ( cursor_visible == true ) {
|
||||||
|
printf ( "\033[?25l" );
|
||||||
|
fflush ( stdout );
|
||||||
|
cursor_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowCursor ()
|
||||||
|
{
|
||||||
|
if ( cursor_visible == false ) {
|
||||||
|
printf ( "\033[?25h" );
|
||||||
|
fflush ( stdout );
|
||||||
|
cursor_visible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetKey ()
|
||||||
|
{
|
||||||
|
int retVal = lastChar;
|
||||||
|
lastChar = 0;
|
||||||
|
|
||||||
|
if ( keyhit == 0 ) {
|
||||||
|
tcsetattr ( 0, TCSANOW, &term_getch );
|
||||||
|
keyhit = read ( STDIN_FILENO, &retVal, sizeof ( retVal ));
|
||||||
|
}
|
||||||
|
|
||||||
|
keyhit = 0;
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyPressed ()
|
||||||
|
{
|
||||||
|
if ( keyhit == 0 ) {
|
||||||
|
tcsetattr ( 0, TCSANOW, &term_kbhit );
|
||||||
|
keyhit = read ( STDIN_FILENO, &lastChar, sizeof ( lastChar ));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( keyhit != 0 ) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 CurrentTime ()
|
||||||
|
{
|
||||||
|
timeval time;
|
||||||
|
gettimeofday ( &time, NULL );
|
||||||
|
return ( UINT32 ) (( time.tv_sec * 1000 ) + ( time.tv_usec / 1000 ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearScreen ()
|
||||||
|
{
|
||||||
|
printf ( "\033[2J" );
|
||||||
|
fflush ( stdout );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetXY ( UINT32 *x, UINT32 *y )
|
||||||
|
{
|
||||||
|
*x = MAX_LUMP_NAME + 5;
|
||||||
|
*y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GotoXY ( UINT32 x, UINT32 y )
|
||||||
|
{
|
||||||
|
// fprintf ( console, "\033[%d;%dH", y, x );
|
||||||
|
fprintf ( console, "\033[%dG", x );
|
||||||
|
fflush ( console );
|
||||||
|
curX = x;
|
||||||
|
curY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Status ( char *message )
|
||||||
|
{
|
||||||
|
fprintf ( console, "\033[%dG%s\033[K", startX, message );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoRight ()
|
||||||
|
{
|
||||||
|
fprintf ( console, "R" );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GoLeft ()
|
||||||
|
{
|
||||||
|
fprintf ( console, "\033[DL" );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Backup ()
|
||||||
|
{
|
||||||
|
fprintf ( console, "\033[D" );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowDone ()
|
||||||
|
{
|
||||||
|
fprintf ( console, "*\033[D" );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowProgress ()
|
||||||
|
{
|
||||||
|
fprintf ( console, "%c\033[D", progress [ progressIndex++ % SIZE ( progress )] );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveUp ( int delta )
|
||||||
|
{
|
||||||
|
fprintf ( console, "\033[%dA", delta );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoveDown ( int delta )
|
||||||
|
{
|
||||||
|
fprintf ( console, "\033[%dB", delta );
|
||||||
|
fflush ( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
78
ZenNode/console.hpp
Normal file
78
ZenNode/console.hpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: console.hpp
|
||||||
|
// Date: 01-Jun-2002
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
//
|
||||||
|
// Copyright (c) 1998-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef CONSOLE_HPP_
|
||||||
|
#define CONSOLE_HPP_
|
||||||
|
|
||||||
|
#if defined ( __OS2__ ) || defined ( __WIN32__ )
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
#define cprintf _cprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
|
||||||
|
extern int cprintf ( const char *, ... );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SaveConsoleSettings ();
|
||||||
|
void RestoreConsoleSettings ();
|
||||||
|
|
||||||
|
void HideCursor ();
|
||||||
|
void ShowCursor ();
|
||||||
|
|
||||||
|
int GetKey ();
|
||||||
|
bool KeyPressed ();
|
||||||
|
|
||||||
|
UINT32 CurrentTime ();
|
||||||
|
|
||||||
|
void ClearScreen ();
|
||||||
|
|
||||||
|
extern UINT32 startX, startY;
|
||||||
|
|
||||||
|
void GetXY ( UINT32 *x, UINT32 *y );
|
||||||
|
void GotoXY ( UINT32 x, UINT32 y );
|
||||||
|
void MoveUp ( int delta );
|
||||||
|
void MoveDown ( int delta );
|
||||||
|
void PutXY ( UINT32 x, UINT32 y, char *ptr, int length );
|
||||||
|
void Put ( char *ptr, int length );
|
||||||
|
|
||||||
|
// ----- External Functions Required by ZenNode -----
|
||||||
|
|
||||||
|
void Status ( char *message );
|
||||||
|
void GoRight ();
|
||||||
|
void GoLeft ();
|
||||||
|
void Backup ();
|
||||||
|
void ShowDone ();
|
||||||
|
void ShowProgress ();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
91
ZenNode/geometry.hpp
Normal file
91
ZenNode/geometry.hpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: geometry.hpp
|
||||||
|
// Date: 26-October-1994
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef GEOMETRY_HPP_
|
||||||
|
#define GEOMETRY_HPP_
|
||||||
|
|
||||||
|
#if ! defined ( COMMON_HPP_ )
|
||||||
|
#include "common.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sPoint;
|
||||||
|
struct sRectangle;
|
||||||
|
|
||||||
|
struct sPoint {
|
||||||
|
long x;
|
||||||
|
long y;
|
||||||
|
sPoint () { x = 0; y = 0; }
|
||||||
|
sPoint ( long _x, long _y ) { x = _x; y = _y; }
|
||||||
|
bool isInside ( const sRectangle & ) const;
|
||||||
|
bool operator == ( const sPoint &o ) const { return ( x == o.x ) && ( y == o.y ); }
|
||||||
|
bool operator != ( const sPoint &o ) const { return ( x != o.x ) || ( y != o.y ); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sLine {
|
||||||
|
sPoint start;
|
||||||
|
sPoint end;
|
||||||
|
sLine () : start (), end () {}
|
||||||
|
sLine ( const sPoint &s, const sPoint &e ) { start = s; end = e; }
|
||||||
|
int rise () const { return end.y - start.y; }
|
||||||
|
int run () const { return end.x - start.x; }
|
||||||
|
float slope () const { return rise () / ( float ) run (); }
|
||||||
|
bool endMatches ( const sLine & ) const;
|
||||||
|
bool isInside ( const sRectangle & ) const;
|
||||||
|
bool intersects ( const sRectangle & ) const;
|
||||||
|
bool intersects ( const sLine & ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sRectangle {
|
||||||
|
int xLeft, xRight;
|
||||||
|
int yTop, yBottom;
|
||||||
|
sRectangle ();
|
||||||
|
sRectangle ( long, long, long, long );
|
||||||
|
sRectangle ( const sPoint &, const sPoint & );
|
||||||
|
void include ( const sPoint & );
|
||||||
|
void include ( const sRectangle & );
|
||||||
|
long left () const { return xLeft; }
|
||||||
|
long right () const { return xRight; }
|
||||||
|
long top () const { return yTop; }
|
||||||
|
long bottom () const { return yBottom; }
|
||||||
|
long width () const { return xRight - xLeft; }
|
||||||
|
long height () const { return yTop - yBottom; }
|
||||||
|
sPoint center () const { return sPoint (( xLeft + xRight ) / 2, ( yTop + yBottom ) / 2 ); }
|
||||||
|
sPoint tl () const { return sPoint ( xLeft, yTop ); }
|
||||||
|
sPoint bl () const { return sPoint ( xLeft, yBottom ); }
|
||||||
|
sPoint tr () const { return sPoint ( xRight, yTop ); }
|
||||||
|
sPoint br () const { return sPoint ( xRight, yBottom ); }
|
||||||
|
bool isInside ( const sRectangle & ) const;
|
||||||
|
bool intersects ( const sRectangle & ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline sRectangle::sRectangle ()
|
||||||
|
{
|
||||||
|
xLeft = yTop = xRight = yBottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
139
ZenNode/makefile
Normal file
139
ZenNode/makefile
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
# ZenNode makefile for Linux
|
||||||
|
|
||||||
|
CC = g++
|
||||||
|
CFLAGS += -g -O -fstrength-reduce -fno-rtti
|
||||||
|
CFLAGS += -fomit-frame-pointer -foptimize-sibling-calls
|
||||||
|
#CFLAGS += -fbranch-probabilities
|
||||||
|
#CFLAGS += -fprofile-arcs
|
||||||
|
WARNINGS = -Wall -Wno-format -Wstrict-prototypes -Wmissing-prototypes -Winline
|
||||||
|
#CC = /opt/intel/compiler60/ia32/bin/icc
|
||||||
|
#CFLAGS = -g -O3
|
||||||
|
INCLUDES = -I../DOOM -I../common
|
||||||
|
TARGETS = ZenNode bspdiff bspinfo compare
|
||||||
|
|
||||||
|
CFLAGS += -D__LINUX__
|
||||||
|
|
||||||
|
ifdef WIN32
|
||||||
|
CFLAGS += -D__WIN32__
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifdef DEBUG
|
||||||
|
CFLAGS += -DDEBUG
|
||||||
|
LOGGER = ../common/logger/logger.o ../common/logger/string.o
|
||||||
|
CFLAGS += -fexceptions
|
||||||
|
LOGGER += ../common/logger/linux-logger.o
|
||||||
|
LIBS += -lpthread -lrt
|
||||||
|
endif
|
||||||
|
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) $(WARNINGS) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp .o
|
||||||
|
|
||||||
|
all: $(TARGETS)
|
||||||
|
|
||||||
|
depend: clean
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf {.,../DOOM/,../common/logger}/{*.o,*~} $(TARGETS)
|
||||||
|
|
||||||
|
ZenNode: ZenMain.o ZenNode.o ZenReject.o ZenRMB.o blockmap.o console.o ../DOOM/wad.o ../DOOM/level.o $(LOGGER)
|
||||||
|
$(CC) $(LIBS) -o $@ $^
|
||||||
|
|
||||||
|
bspdiff: bspdiff.o console.o ../DOOM/wad.o ../DOOM/level.o $(LOGGER)
|
||||||
|
$(CC) $(LIBS) -o $@ $^
|
||||||
|
|
||||||
|
bspinfo: bspinfo.o console.o ../DOOM/wad.o ../DOOM/level.o $(LOGGER)
|
||||||
|
$(CC) $(LIBS) -o $@ $^
|
||||||
|
|
||||||
|
compare: compare.o console.o ../DOOM/wad.o ../DOOM/level.o $(LOGGER)
|
||||||
|
$(CC) $(LIBS) -o $@ $^
|
||||||
|
|
||||||
|
ZenReject.o: \
|
||||||
|
ZenReject.cpp \
|
||||||
|
ZenReject-util.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
ZenNode.hpp \
|
||||||
|
console.hpp \
|
||||||
|
geometry.hpp
|
||||||
|
|
||||||
|
ZenNode.o: \
|
||||||
|
ZenNode.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
ZenNode.hpp \
|
||||||
|
console.hpp
|
||||||
|
|
||||||
|
ZenMain.o: \
|
||||||
|
ZenMain.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
console.hpp \
|
||||||
|
ZenNode.hpp
|
||||||
|
|
||||||
|
ZenReject.o: \
|
||||||
|
ZenReject.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
ZenNode.hpp \
|
||||||
|
console.hpp \
|
||||||
|
geometry.hpp
|
||||||
|
|
||||||
|
ZenRMB.o: \
|
||||||
|
ZenRMB.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
ZenNode.hpp
|
||||||
|
|
||||||
|
blockmap.o: \
|
||||||
|
blockmap.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
ZenNode.hpp
|
||||||
|
|
||||||
|
console.o: \
|
||||||
|
console.cpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
console.hpp \
|
||||||
|
|
||||||
|
../DOOM/wad.o: \
|
||||||
|
../DOOM/wad.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp
|
||||||
|
|
||||||
|
../DOOM/level.o: \
|
||||||
|
../DOOM/level.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp
|
||||||
|
|
||||||
|
bspdiff.o: \
|
||||||
|
bspdiff.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
console.hpp
|
||||||
|
|
||||||
|
bspinfo.o: \
|
||||||
|
bspinfo.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
console.hpp
|
||||||
|
|
||||||
|
compare.o: \
|
||||||
|
compare.cpp \
|
||||||
|
../common/common.hpp \
|
||||||
|
../common/logger.hpp \
|
||||||
|
../DOOM/wad.hpp \
|
||||||
|
../DOOM/level.hpp \
|
||||||
|
console.hpp
|
258
common/common.hpp
Normal file
258
common/common.hpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: common.hpp
|
||||||
|
// Date:
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description:
|
||||||
|
//
|
||||||
|
// Copyright (c) 1994-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef COMMON_HPP_
|
||||||
|
#define COMMON_HPP_
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Generic definitions
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef UNREFERENCED_PARAMETER
|
||||||
|
#undef UNREFERENCED_PARAMETER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined ( _MSC_VER )
|
||||||
|
#define UNREFERENCED_PARAMETER(x) x
|
||||||
|
#else
|
||||||
|
#define UNREFERENCED_PARAMETER(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define OFFSET_OF(t,x) (( size_t ) & (( t * ) 0 )->( x ))
|
||||||
|
#define SIZE(x) ( sizeof ( x ) / sizeof (( x )[0] ))
|
||||||
|
#define EVER ;;
|
||||||
|
|
||||||
|
typedef signed char INT8;
|
||||||
|
typedef signed short INT16;
|
||||||
|
typedef signed int INT32;
|
||||||
|
|
||||||
|
typedef unsigned char UINT8, UCHAR;
|
||||||
|
typedef unsigned short UINT16;
|
||||||
|
typedef unsigned int UINT32;
|
||||||
|
|
||||||
|
#if defined ( __GNUC__ )
|
||||||
|
|
||||||
|
typedef long long INT64;
|
||||||
|
typedef unsigned long long UINT64;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef __int64 INT64;
|
||||||
|
typedef unsigned __int64 UINT64;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined ( __WIN32__ ) || defined ( __AMIGAOS__ )
|
||||||
|
|
||||||
|
// Undo any previos definitions
|
||||||
|
#define BIG_ENDIAN 1234
|
||||||
|
#define LITTLE_ENDIAN 4321
|
||||||
|
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Use the environments endian definitions
|
||||||
|
#undef __USE_BSD
|
||||||
|
#define __USE_BSD
|
||||||
|
#include <endian.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int (*QSORT_FUNC) ( const void *, const void * );
|
||||||
|
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template < class T > inline void swap ( T &item1, T &item2 )
|
||||||
|
{
|
||||||
|
T temp = item1;
|
||||||
|
item1 = item2;
|
||||||
|
item2 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Platform specific definitions
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined ( __OS2__ ) || defined ( __WIN32__ )
|
||||||
|
|
||||||
|
#define SEPERATOR '\\'
|
||||||
|
#define DEFAULT_CHAR 'û'
|
||||||
|
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
#define SEPERATOR '/'
|
||||||
|
#define DEFAULT_CHAR '*'
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Compiler specific definitions
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if defined ( __BORLANDC__ )
|
||||||
|
|
||||||
|
#if defined ( __BCPLUSPLUS__ ) || defined ( __TCPLUSPLUS__ )
|
||||||
|
#undef NULL
|
||||||
|
#define NULL ( void * ) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (( __BORLANDC__ < 0x0500 ) || defined ( __OS2__ ))
|
||||||
|
|
||||||
|
// Fake out ANSI definitions for deficient compilers
|
||||||
|
#define for if (0); else for
|
||||||
|
|
||||||
|
enum { false, true };
|
||||||
|
class bool {
|
||||||
|
int value;
|
||||||
|
public:
|
||||||
|
operator = ( int x ) { value = x ? true : false; }
|
||||||
|
bool operator ! () { return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class T> inline const T &min ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t2 : t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline const T &max ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t1 : t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined ( _MSC_VER )
|
||||||
|
|
||||||
|
#undef NULL
|
||||||
|
#define NULL 0L
|
||||||
|
|
||||||
|
#define MAXPATH _MAX_PATH
|
||||||
|
#define MAXDRIVE _MAX_DRIVE
|
||||||
|
#define MAXDIR _MAX_DIR
|
||||||
|
#define MAXFNAME _MAX_FNAME
|
||||||
|
#define MAXEXT _MAX_EXT
|
||||||
|
|
||||||
|
#if ( _MSC_VER < 1300 )
|
||||||
|
|
||||||
|
// Fake out ANSI definitions for deficient compilers
|
||||||
|
#define for if (0); else for
|
||||||
|
|
||||||
|
#pragma warning ( disable: 4127 ) // C4127: conditional expression is constant
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma warning ( disable: 4244 ) // C4244: 'xyz' conversion from 'xxx' to 'yyy', possible loss of data
|
||||||
|
#pragma warning( disable : 4290 ) // C4290: C++ exception specification ignored...
|
||||||
|
#pragma warning ( disable: 4514 ) // C4514: 'xyz' unreferenced inline function has been removed
|
||||||
|
|
||||||
|
template <class T> inline const T &min ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t2 : t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline const T &max ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t1 : t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ( _MSC_VER >= 1300 )
|
||||||
|
extern char *strndup ( const char *string, size_t max );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined ( __WATCOMC__ )
|
||||||
|
|
||||||
|
#define M_PI 3.14159265358979323846
|
||||||
|
|
||||||
|
template <class T> inline const T &min ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t2 : t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline const T &max ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t1 : t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined ( __GNUC__ ) || defined ( __INTEL_COMPILER )
|
||||||
|
|
||||||
|
#define MAXPATH FILENAME_MAX
|
||||||
|
#define MAXDRIVE FILENAME_MAX
|
||||||
|
#define MAXDIR FILENAME_MAX
|
||||||
|
#define MAXFNAME FILENAME_MAX
|
||||||
|
#define MAXEXT FILENAME_MAX
|
||||||
|
|
||||||
|
#define O_BINARY 0
|
||||||
|
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
#define strnicmp strncasecmp
|
||||||
|
|
||||||
|
template <class T> inline const T &min ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t2 : t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline const T &max ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t1 : t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined ( __AMIGAOS__ )
|
||||||
|
|
||||||
|
// Fake out ANSI definitions for deficient compilers
|
||||||
|
#define for if (0); else for
|
||||||
|
|
||||||
|
enum { false, true };
|
||||||
|
class bool {
|
||||||
|
int value;
|
||||||
|
public:
|
||||||
|
operator = ( int x ) { value = x ? true : false; }
|
||||||
|
bool operator ! () { return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> inline const T &min ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t2 : t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> inline const T &max ( const T &t1, const T &t2 )
|
||||||
|
{
|
||||||
|
return ( t1 > t2 ) ? t1 : t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char *strdup ( const char *string );
|
||||||
|
extern char *strndup ( const char *string, size_t max );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
185
common/logger.hpp
Normal file
185
common/logger.hpp
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// File: logger.hpp
|
||||||
|
// Date: 15-Apr-1998
|
||||||
|
// Programmer: Marc Rousseau
|
||||||
|
//
|
||||||
|
// Description: Error Logger object header
|
||||||
|
//
|
||||||
|
// Copyright (c) 1998-2004 Marc Rousseau, All Rights Reserved.
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Revision History:
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef LOGGER_HPP_
|
||||||
|
#define LOGGER_HPP_
|
||||||
|
|
||||||
|
#ifdef ERROR
|
||||||
|
#undef ERROR
|
||||||
|
#endif
|
||||||
|
#ifdef ASSERT
|
||||||
|
#undef ASSERT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined ( DEBUG )
|
||||||
|
|
||||||
|
struct LOG_FLAGS {
|
||||||
|
bool FunctionEntry;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern LOG_FLAGS g_LogFlags;
|
||||||
|
|
||||||
|
#define FUNCTION_ENTRY(t,f,l) \
|
||||||
|
void *l_pThis = ( void * ) t; \
|
||||||
|
char *l_FnName = f; \
|
||||||
|
bool l_log = ( g_LogFlags.FunctionEntry == l ) ? true : false; \
|
||||||
|
if ( l_log && g_LogFlags.FunctionEntry ) { \
|
||||||
|
DBG_MINOR_TRACE2 ( l_FnName, l_pThis, "Function entered" ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT(x) (( ! ( x )) ? dbg_Assert ( dbg_FileName, __LINE__, l_FnName, l_pThis, #x ), 1 : 0 )
|
||||||
|
#define ASSERT_BOOL(x) ASSERT ( x )
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined ( _MSC_VER )
|
||||||
|
#pragma warning ( disable: 4127 ) // C4127: conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FUNCTION_ENTRY(t,f,l)
|
||||||
|
#define ASSERT(x)
|
||||||
|
#define ASSERT_BOOL(x) 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TRACE(x) DBG_MAJOR_TRACE2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define EVENT(x) DBG_MINOR_EVENT2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define MINOR_EVENT(x) DBG_MINOR_EVENT2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define MAJOR_EVENT(x) DBG_MAJOR_EVENT2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define STATUS(x) DBG_STATUS2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define WARNING(x) DBG_WARNING2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define ERROR(x) DBG_ERROR2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
#define FATAL(x) DBG_FATAL2 ( l_FnName, l_pThis, ( const char * ) x )
|
||||||
|
|
||||||
|
#if ! defined ( DEBUG )
|
||||||
|
|
||||||
|
#define DBG_REGISTER(x)
|
||||||
|
#define DBG_STRING(x) ""
|
||||||
|
#define DBG_MINOR_TRACE(f,t,x)
|
||||||
|
#define DBG_MINOR_TRACE2(f,t,x)
|
||||||
|
#define DBG_MAJOR_TRACE(f,t,x)
|
||||||
|
#define DBG_MAJOR_TRACE2(f,t,x)
|
||||||
|
#define DBG_MINOR_EVENT(f,t,x)
|
||||||
|
#define DBG_MINOR_EVENT2(f,t,x)
|
||||||
|
#define DBG_MAJOR_EVENT(f,t,x)
|
||||||
|
#define DBG_MAJOR_EVENT2(f,t,x)
|
||||||
|
#define DBG_STATUS(f,t,x)
|
||||||
|
#define DBG_STATUS2(f,t,x)
|
||||||
|
#define DBG_WARNING(f,t,x)
|
||||||
|
#define DBG_WARNING2(f,t,x)
|
||||||
|
#define DBG_ERROR(f,t,x)
|
||||||
|
#define DBG_ERROR2(f,t,x)
|
||||||
|
#define DBG_FATAL(f,t,x)
|
||||||
|
#define DBG_FATAL2(f,t,x)
|
||||||
|
#define DBG_ASSERT(f,t,x) 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DBG_REGISTER(x) static int dbg_FileName = dbg_RegisterFile ( x );
|
||||||
|
#define DBG_STRING(x) x
|
||||||
|
#define DBG_MINOR_TRACE(f,t,x) dbg_Record ( _MINOR_TRACE_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_MINOR_TRACE2(f,t,x) dbg_Record ( _MINOR_TRACE_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_MAJOR_TRACE(f,t,x) dbg_Record ( _MAJOR_TRACE_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_MAJOR_TRACE2(f,t,x) dbg_Record ( _MAJOR_TRACE_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_MINOR_EVENT(f,t,x) dbg_Record ( _MINOR_EVENT_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_MINOR_EVENT2(f,t,x) dbg_Record ( _MINOR_EVENT_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_MAJOR_EVENT(f,t,x) dbg_Record ( _MAJOR_EVENT_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_MAJOR_EVENT2(f,t,x) dbg_Record ( _MAJOR_EVENT_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_STATUS(f,t,x) dbg_Record ( _STATUS_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_STATUS2(f,t,x) dbg_Record ( _STATUS_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_WARNING(f,t,x) dbg_Record ( _WARNING_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_WARNING2(f,t,x) dbg_Record ( _WARNING_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_ERROR(f,t,x) dbg_Record ( _ERROR_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_ERROR2(f,t,x) dbg_Record ( _ERROR_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_FATAL(f,t,x) dbg_Record ( _FATAL_, dbg_FileName, __LINE__, f, t, x )
|
||||||
|
#define DBG_FATAL2(f,t,x) dbg_Record ( _FATAL_, dbg_FileName, __LINE__, f, t, dbg_Stream () << x ), dbg_Stream ().flush ()
|
||||||
|
#define DBG_ASSERT(f,t,x) (( ! ( x )) ? dbg_Assert ( dbg_FileName, __LINE__, f, t, #x ), 1 : 0 )
|
||||||
|
|
||||||
|
enum eLOG_TYPE {
|
||||||
|
_MINOR_TRACE_,
|
||||||
|
_MAJOR_TRACE_,
|
||||||
|
_MINOR_EVENT_,
|
||||||
|
_MAJOR_EVENT_,
|
||||||
|
_STATUS_,
|
||||||
|
_WARNING_,
|
||||||
|
_ERROR_,
|
||||||
|
_FATAL_,
|
||||||
|
LOG_TYPE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
class dbgString {
|
||||||
|
|
||||||
|
friend dbgString &hex ( dbgString & );
|
||||||
|
friend dbgString &dec ( dbgString & );
|
||||||
|
|
||||||
|
int m_Base;
|
||||||
|
bool m_OwnBuffer;
|
||||||
|
char *m_Ptr;
|
||||||
|
char *m_Buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
dbgString ( char * );
|
||||||
|
|
||||||
|
operator const char * ();
|
||||||
|
void flush ();
|
||||||
|
|
||||||
|
dbgString &operator << ( const char * );
|
||||||
|
dbgString &operator << ( char );
|
||||||
|
dbgString &operator << ( unsigned char );
|
||||||
|
dbgString &operator << ( short );
|
||||||
|
dbgString &operator << ( unsigned short );
|
||||||
|
dbgString &operator << ( int );
|
||||||
|
dbgString &operator << ( unsigned int );
|
||||||
|
dbgString &operator << ( long );
|
||||||
|
dbgString &operator << ( unsigned long );
|
||||||
|
/*
|
||||||
|
dbgString &operator << ( __int64 );
|
||||||
|
dbgString &operator << ( unsigned __int64 );
|
||||||
|
*/
|
||||||
|
dbgString &operator << ( double );
|
||||||
|
dbgString &operator << ( void * );
|
||||||
|
dbgString &operator << ( dbgString &(*f) ( dbgString & ));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
dbgString &hex ( dbgString & );
|
||||||
|
dbgString &dec ( dbgString & );
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
dbgString &dbg_Stream ();
|
||||||
|
int dbg_RegisterFile ( const char * );
|
||||||
|
void dbg_Assert ( int, int, const char * , void *, const char * );
|
||||||
|
void dbg_Record ( int, int, int, const char *, void *, const char * );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue