Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 593646 Details for
Bug 830628
Yadex crashes when trying to edit a level.
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
A patch of all the patches in the source RPM including disabled patches
yadex-1.7.0-allpatches.diff (text/plain), 234.57 KB, created by
JC
on 2012-06-22 05:41:34 UTC
(
hide
)
Description:
A patch of all the patches in the source RPM including disabled patches
Filename:
MIME Type:
Creator:
JC
Created:
2012-06-22 05:41:34 UTC
Size:
234.57 KB
patch
obsolete
>diff -Nru yadex-1.7.0-orig/atclib/al_adigits.c yadex-1.7.0/atclib/al_adigits.c >--- yadex-1.7.0-orig/atclib/al_adigits.c 1999-08-01 09:52:00.000000000 -0500 >+++ yadex-1.7.0/atclib/al_adigits.c 2012-06-17 18:47:12.477693118 -0400 >@@ -29,5 +29,11 @@ > #include "atclib.h" > > >-const char al_adigits[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; >+const char al_adigits[36] = >+{ >+'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', >+'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', >+'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', >+'U', 'V', 'W', 'X', 'Y', 'Z' >+}; > >diff -Nru yadex-1.7.0-orig/configure yadex-1.7.0/configure >--- yadex-1.7.0-orig/configure 2003-12-28 11:26:20.000000000 -0500 >+++ yadex-1.7.0/configure 2012-06-17 18:47:59.814991724 -0400 >@@ -408,16 +408,16 @@ > ETCDIR=/etc/$APPNAME/%v > ETCDIRNV=/etc/$APPNAME > MANDIR=/usr/share/man >- SHAREDIR=/usr/share/games/$APPNAME/%v >- SHAREDIRNV=/usr/share/games/$APPNAME >+ SHAREDIR=/usr/share/$APPNAME/%v >+ SHAREDIRNV=/usr/share/$APPNAME > elif expr "$PREFIX" : '//*usr//*local/*$' >/dev/null > then > BINDIR=/usr/local/bin # FHS-ly correct is /usr/local/games > ETCDIR=/etc/$APPNAME/%v > ETCDIRNV=/etc/$APPNAME > MANDIR=/usr/local/man >- SHAREDIR=/usr/local/share/games/$APPNAME/%v >- SHAREDIRNV=/usr/local/share/games/$APPNAME >+ SHAREDIR=/usr/local/share/$APPNAME/%v >+ SHAREDIRNV=/usr/local/share/$APPNAME > elif expr "$PREFIX" : '//*opt/*$' >/dev/null > then > echo '/opt ? Surely you mean /opt/something, Mr. Feynman !' 1>&2 >diff -Nru yadex-1.7.0-orig/docsrc/index.html yadex-1.7.0/docsrc/index.html >--- yadex-1.7.0-orig/docsrc/index.html 2002-05-09 08:36:06.000000000 -0500 >+++ yadex-1.7.0/docsrc/index.html 2012-06-17 18:47:12.477693118 -0400 >@@ -34,6 +34,7 @@ > > <ul> > <li><a href="palette.html">Palette viewer</a> >+<li><a href="preview.html">3D Level Preview</a> > <li><a href="advanced.html">Advanced user's guide</a> > <li><a href="../TODO"><code>TODO</code></a> > <li><a href="yadex.6">The man page for Yadex</a> >diff -Nru yadex-1.7.0-orig/docsrc/preview.html yadex-1.7.0/docsrc/preview.html >--- yadex-1.7.0-orig/docsrc/preview.html 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/docsrc/preview.html 2012-06-17 18:47:12.478693123 -0400 >@@ -0,0 +1,108 @@ >+<html> >+<head> >+<title>Yadex 3D level preview</title> >+</head> >+<body> >+ >+<div align="center"> >+<img src="logo_small.png" alt="Fancy logo"> >+<br>Yadex $VERSION ($SOURCE_DATE) >+<h1>3D Level Preview</h1> >+</div> >+<br> >+<br> >+<br> >+ >+ <h2>What's it for</h2> >+ >+<p>The 3D level preview function lets you get a rough idea of what >+your level looks like, quickly, without all the hassle of saving, >+building nodes and starting DOOM. It is activated by pressing the >+`R' key while editing a level, and draws the player's view that >+you would see within DOOM (with some limitations). While the >+rendering window is up, you can move around the level using the >+cursor keys and toggle things like texturing and sprites on/off. >+ >+ <h2>Key bindings</h2> >+ >+<dl> >+<dt>[<kbd>Left</kbd>] >+<br>[<kbd>Right</kbd>] >+<dd>Turn the view left or right. Use the SHIFT key to >+turn a greater amount. >+ >+<dt>[<kbd>Up</kbd>] >+<br>[<kbd>Down</kbd>] >+<dd>Move the view forward or back. Use the SHIFT key to >+move a greater distance. >+ >+<dt>[<kbd>n</kbd>] >+<br>[<kbd>m</kbd>] >+<dd>Move the view sideways left or right (strafing). Uppercase `N' >+and `M' (i.e. with the SHIFT key) will move a greater distance. >+ >+<dt>[<kbd>c</kbd>] >+<br>[<kbd>d</kbd>] >+<dd>Move the view upwards or downwards (flying). Uppercase `C' and >+`D' (i.e. with the SHIFT key) will move a greater distance. Note >+that you cannot move up or down when "walking" mode is enabled. >+ >+<dt>[<kbd>t</kbd>] >+<dd>Toggle texture mapping. When disabled (the default), all walls, >+ceilings and floors are drawn with solid (somewhat random) colours. >+ >+<dt>[<kbd>s</kbd>] >+<dd>Toggle sprites. >+ >+<dt>[<kbd>w</kbd>] >+<dd>Toggle walking mode. When enabled, the view height is always >+above the current floor. For example, if you move forward over a >+cliff, the view will drop down. When disabled (the default), you can >+fly about the level at any height. >+ >+<dt>[<kbd>Esc</kbd>] >+<br>[<kbd>q</kbd>] >+<dd>Exit the 3D level preview. The current viewing state (position, >+direction, etc) are remembered, and will be used next time the 3D >+preview is activated (unless the player object has been moved, or a >+different level was loaded). >+ >+</dl> >+ >+ <h2>Features</h2> >+ >+<ul> >+<li>No BSP (nodes) required ! >+<li>Textures and flats are drawn exactly like DOOM, including X/Y >+offsets and upper/lower unpegging flags. >+<li>Sky is handled just like in DOOM (but drawn in solid blue). >+</ul> >+ >+ <h2>Limitations</h2> >+ >+<ul> >+<li>No lighting, the level appears full-bright all the time. >+<li>No mid-masked textures (rails, gratings) are drawn. >+<li>Thing sprites (especially monsters) are always drawn facing >+you, even when their direction is away from you. >+<li>Sprite positioning may be inaccurate, because their X and >+Y offsets are not honoured. >+<li>Things that are supposed to hang from the ceiling >+(hanging body parts, chandeliers, etc) will appear on the floor. >+<li>There are some glitches in the current renderer, which look like >+"slimetrails" (vertical lines). >+</ul> >+ >+ <h2>Caveats</h2> >+ >+One last thing. The 3D preview function can use a huge amount of >+memory when texturing and sprites are both enabled (and a large amount >+even when texturing and sprites are both disabled). If your computer >+has a very low amount of memory (e.g. less than 16 MB), then Yadex may >+crash with an out of memory error. I think you are unlikely to hit >+this problem, but if in doubt, save your work first. >+ >+ >+<p><hr>AJA $SELF_DATE >+</body> >+</html> >diff -Nru yadex-1.7.0-orig/GNUmakefile yadex-1.7.0/GNUmakefile >--- yadex-1.7.0-orig/GNUmakefile 2003-12-28 12:23:56.000000000 -0500 >+++ yadex-1.7.0/GNUmakefile 2012-06-17 18:47:51.830941352 -0400 >@@ -53,6 +53,7 @@ > > # Which OS ? > OS := $(shell uname -s | tr A-Z a-z) >+ARCH := $(shell uname -i | tr A-Z a-z) > > # Where your X11 libraries and headers reside. > # Current rule: >@@ -67,7 +68,11 @@ > X11LIBDIR = /usr/openwin/lib > X11INCLUDEDIR = /usr/openwin/include > else >- X11LIBDIR = /usr/X11R6/lib >+ ifeq ($(findstring $(ARCH), x86_64), $(ARCH)) >+ X11LIBDIR = /usr/X11R6/lib64 >+ else >+ X11LIBDIR = /usr/X11R6/lib >+ endif > X11INCLUDEDIR = /usr/X11R6/include > endif > endif >@@ -160,6 +165,7 @@ > s_swapf s_vertices sanity scrnshot \ > selbox selectn selpath selrect \ > serialnum spritdir sticker swapmem \ >+ r_render r_images \ > t_centre t_flags t_prop t_spin \ > textures things trace v_centre \ > v_merge v_polyg vectext verbmsg \ >@@ -237,6 +243,7 @@ > docsrc/legal.html \ > docsrc/packagers_guide.html \ > docsrc/palette.html \ >+ docsrc/preview.html \ > docsrc/reporting.html \ > docsrc/tips.html \ > docsrc/trivia.html \ >@@ -390,19 +397,19 @@ > > .PHONY: install > install: $(OBJDIR)/install >- @scripts/mkinstalldirs $(BINDIR) >- @scripts/mkinstalldirs $(ETCDIR) >- @scripts/mkinstalldirs $(MANDIR) >- @scripts/mkinstalldirs $(MANDIR)/man6 >- @scripts/mkinstalldirs $(SHAREDIR) >- $(OBJDIR)/install -m 755 $(OBJDIR)/yadex $(BINDIR)/yadex-$(VERSION) >- rm -f $(BINDIR)/yadex >- ln -s yadex-$(VERSION) $(BINDIR)/yadex >- $(OBJDIR)/install -m 644 doc/yadex.6 $(MANDIR)/man6/yadex-$(VERSION).6 >- rm -f $(MANDIR)/man6/yadex.6 >- ln -s yadex-$(VERSION).6 $(MANDIR)/man6/yadex.6 >- $(OBJDIR)/install -m 644 -d $(SHAREDIR) $(YGD) >- $(OBJDIR)/install -m 644 -d $(ETCDIR) yadex.cfg >+ @scripts/mkinstalldirs $(DESTDIR)$(BINDIR) >+ @scripts/mkinstalldirs $(DESTDIR)$(ETCDIR) >+ @scripts/mkinstalldirs $(DESTDIR)$(MANDIR) >+ @scripts/mkinstalldirs $(DESTDIR)$(MANDIR)/man6 >+ @scripts/mkinstalldirs $(DESTDIR)$(SHAREDIR) >+ $(OBJDIR)/install -m 755 $(OBJDIR)/yadex $(DESTDIR)$(BINDIR)/yadex-$(VERSION) >+ rm -f $(DESTDIR)$(BINDIR)/yadex >+ ln -s yadex-$(VERSION) $(DESTDIR)$(BINDIR)/yadex >+ $(OBJDIR)/install -m 644 doc/yadex.6 $(DESTDIR)$(MANDIR)/man6/yadex-$(VERSION).6 >+ rm -f $(DESTDIR)$(MANDIR)/man6/yadex.6 >+ ln -s yadex-$(VERSION).6 $(DESTDIR)$(MANDIR)/man6/yadex.6 >+ $(OBJDIR)/install -m 644 -d $(DESTDIR)$(SHAREDIR) $(YGD) >+ $(OBJDIR)/install -m 644 -d $(DESTDIR)$(ETCDIR) yadex.cfg > @echo "---------------------------------------------------------------" > @echo " Yadex is now installed." > @echo >@@ -609,8 +616,9 @@ > # > ######################################################################## > >-# If Makefile.config doesn't exist, give a hint... >+# If Makefile.config or config.h don't exist, give a hint... > $(OBJDIR)/Makefile.config: >+$(OBJDIR)/config.h: > @echo "Sorry guv'nor, but... did you run ./configure ?" >&2 > @false > >@@ -637,7 +645,7 @@ > # Note: the modules of Atclib are not scanned as they all > # depend on $(HEADERS_ATCLIB) and nothing else. > >-yadex.dep: $(SRC_NON_GEN) >+yadex.dep: $(SRC_NON_GEN) src/config.h > @echo "Generating $@" > @makedepend -f- -Y -Iatclib $(SRC_NON_GEN) 2>/dev/null \ > | awk 'sub (/^src/, "") == 1 { \ >diff -Nru yadex-1.7.0-orig/GNUmakefile.orig yadex-1.7.0/GNUmakefile.orig >--- yadex-1.7.0-orig/GNUmakefile.orig 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/GNUmakefile.orig 2012-06-17 18:47:42.118880088 -0400 >@@ -0,0 +1,897 @@ >+# >+# Makefile for Yadex >+# Copyright © André Majorel 1998-2003. >+# AYM 1998-06-10 >+# >+ >+# ATTENTION : GNU MAKE IS REQUIRED ! This makefile uses pattern >+# rules, addprefix, addsuffix, etc. It's not named "GNUmakefile" >+# for nothing. >+ >+######################################################################## >+# >+# Definitions that only hackers >+# might want to change >+# >+######################################################################## >+ >+# The name of the directory where objects and >+# binaries are put. I include the output of >+# "uname -a" to make it easier for me to build >+# Yadex for different platforms from the same >+# source tree. >+SYSTEM := $(shell echo `uname -n`_`uname -a | cksum` | tr -dc '[:alnum:]._-') >+OBJDIR = obj/0 >+DOBJDIR = dobj/0 >+OBJPHYSDIR = obj/$(SYSTEM) >+DOBJPHYSDIR = dobj/$(SYSTEM) >+OBJDIR_ATCLIB = $(OBJDIR)/atclib >+DOBJDIR_ATCLIB = $(DOBJDIR)/atclib >+OBJPHYSDIR_ATCLIB = $(OBJPHYSDIR)/atclib >+DOBJPHYSDIR_ATCLIB = $(DOBJPHYSDIR)/atclib >+ >+# Create all directories and make symlinks to >+# config.cc and config.h. Doing it at the start >+# makes things much simpler later on. >+DUMMY := $(shell \ >+ mkdir -p $(OBJPHYSDIR) $(OBJPHYSDIR_ATCLIB); \ >+ mkdir -p $(DOBJPHYSDIR) $(DOBJPHYSDIR_ATCLIB); \ >+ [ ! -h $(OBJDIR) ] || rm $(OBJDIR); \ >+ [ ! -h $(DOBJDIR) ] || rm $(DOBJDIR); \ >+ ln -s $(SYSTEM) $(OBJDIR); \ >+ ln -s $(SYSTEM) $(DOBJDIR); \ >+ ) >+ >+include $(OBJDIR)/Makefile.config >+ >+######################################################################## >+# >+# Definitions that end users >+# might want to change >+# >+######################################################################## >+ >+# Which OS ? >+OS := $(shell uname -s | tr A-Z a-z) >+ARCH := $(shell uname -i | tr A-Z a-z) >+ >+# Where your X11 libraries and headers reside. >+# Current rule: >+# - AIX has them in /usr/lpp/X11/{lib,include}, >+# - Solaris has them in /usr/openwin/{lib,include}, >+# - all other unices in /usr/X11R6/{lib,include}. >+ifeq ($(findstring $(OS), aix), $(OS)) >+ X11LIBDIR = /usr/lpp/X11/lib >+ X11INCLUDEDIR = /usr/lpp/X11/include >+else >+ ifeq ($(findstring $(OS), solaris sunos), $(OS)) >+ X11LIBDIR = /usr/openwin/lib >+ X11INCLUDEDIR = /usr/openwin/include >+ else >+ ifeq ($(findstring $(ARCH), x86_64), $(ARCH)) >+ X11LIBDIR = /usr/X11R6/lib64 >+ else >+ X11LIBDIR = /usr/X11R6/lib >+ endif >+ X11INCLUDEDIR = /usr/X11R6/include >+ endif >+endif >+ >+# $(CC) and $(CXX) are the C and C++ compiler respectively. They're >+# normally autodetected by ./configure and passed to make through >+# obj/0/Makefile.config. >+#CC = >+#CXX = >+ >+# Options used when compiling Atclib. >+CFLAGS = -O >+ >+# Options used when compiling and linking Yadex. >+# ld is invoked through the C++ compiler so >+# LDFLAGS should not contain options that mean >+# something to the C++ compiler. >+CXXFLAGS = -O >+#CXXFLAGS += -DWHITE_BACKGROUND >+#LDFLAGS = >+ >+# Options used to compile and link the debugging >+# targets. Not used by normal end-user targets. >+# Unlike CFLAGS, CXXFLAGS and LDFLAGS, assume >+# GCC/EGCS. >+DCFLAGS = -g -O >+DCFLAGS += -Wall # GCC warnings >+DCFLAGS += -pedantic # GCC warnings >+DCFLAGS += -Wno-parentheses # GCC warnings >+DCFLAGS += -Wpointer-arith # GCC warnings >+DCFLAGS += -Wcast-qual # GCC warnings >+DCFLAGS += -Wcast-align # GCC warnings >+DCFLAGS += -Wwrite-strings # GCC warnings >+DCFLAGS += -Wmissing-declarations # GCC warnings >+DCFLAGS += -Wmissing-prototypes # GCC warnings >+DCFLAGS += -Winline # GCC warnings >+DCFLAGS += -pg # Profiling >+ >+DCXXFLAGS = -g -O >+DCXXFLAGS += -Wall # GCC warnings >+DCXXFLAGS += -pedantic # GCC warnings >+DCXXFLAGS += -Wno-parentheses # GCC warnings >+DCXXFLAGS += -Wpointer-arith # GCC warnings >+DCXXFLAGS += -Wcast-qual # GCC warnings >+DCXXFLAGS += -Wcast-align # GCC warnings >+DCXXFLAGS += -Wwrite-strings # GCC warnings >+DCXXFLAGS += -Wmissing-declarations # GCC warnings >+DCXXFLAGS += -Wmissing-prototypes # GCC warnings >+#DCXXFLAGS += -Winline # GCC warnings >+DCXXFLAGS += -pg # Profiling >+ >+DLDFLAGS = >+DLDFLAGS += -pg # Profiling >+#DLDFLAGS += -lefence # Electric Fence >+ >+ >+######################################################################## >+# >+# Definitions that only hackers >+# might want to change >+# >+######################################################################## >+ >+MAKEFILE = GNUmakefile >+VERSION := $(shell cat VERSION) >+VERPREV := $(shell test -f VERPREV && cat VERPREV) >+ >+# All the modules of Yadex without path or extension. >+MODULES_YADEX = \ >+ acolours aym bench bitvec \ >+ cfgfile checks colour1 colour2 \ >+ colour3 colour4 config credits \ >+ dependcy dialog disppic drawmap \ >+ edisplay editgrid editlev editloop \ >+ editobj editsave endian editzoom \ >+ entry entry2 events flats \ >+ game gcolour1 gcolour2 gcolour3 \ >+ geom gfx gfx2 gfx3 \ >+ gotoobj help1 help2 highlt \ >+ img imgscale imgspect infobar \ >+ input l_align l_centre l_flags \ >+ l_misc l_prop l_unlink l_vertices \ >+ levels lists locate lumpdir \ >+ macro memory menubar menu \ >+ mkpalette mouse names nop \ >+ objects objinfo oldmenus palview \ >+ patchdir pic2img prefer s_centre \ >+ s_door s_lift s_linedefs s_merge \ >+ s_misc s_prop s_slice s_split \ >+ s_swapf s_vertices sanity scrnshot \ >+ selbox selectn selpath selrect \ >+ serialnum spritdir sticker swapmem \ >+ r_render r_images \ >+ t_centre t_flags t_prop t_spin \ >+ textures things trace v_centre \ >+ v_merge v_polyg vectext verbmsg \ >+ version wadfile wadlist wadnamec \ >+ wadres wads wads2 warn \ >+ windim x_centre x_exchng x_hover \ >+ x_mirror x_rotate x11 xref \ >+ yadex ytime >+ >+# All the modules of Atclib without path or extension. >+MODULES_ATCLIB = \ >+ al_adigits al_aerrno al_astrerror al_fana \ >+ al_fnature al_lateol al_lcount al_lcreate \ >+ al_ldelete al_ldiscard al_lgetpos al_linsert \ >+ al_linsertl al_llength al_lpeek al_lpeekl \ >+ al_lpoke al_lpokel al_lptr al_lread \ >+ al_lreadl al_lrewind al_lseek al_lsetpos \ >+ al_lstep al_ltell al_lwrite al_lwritel \ >+ al_sapc al_saps al_scps al_scpslower \ >+ al_sdup al_sisnum al_strolc >+ >+# The source files of Yadex and Atclib >+SRC_YADEX = $(addprefix src/, $(addsuffix .cc, $(MODULES_YADEX))) >+SRC_ATCLIB = $(addprefix atclib/, $(addsuffix .c, $(MODULES_ATCLIB))) >+ >+# The headers of Yadex and Atclib >+HEADERS_YADEX := $(wildcard src/*.h) >+HEADERS_ATCLIB = atclib/atclib.h >+ >+# All the source files, including the headers. >+SRC = $(filter-out src/config.cc, $(SRC_YADEX)) \ >+ $(filter-out src/config.h, $(HEADERS_YADEX)) \ >+ $(SRC_ATCLIB) $(HEADERS_ATCLIB) >+ >+# The files on which youngest is run. >+SRC_NON_GEN = $(filter-out src/credits.cc src/prefix.cc src/version.cc, $(SRC)) >+ >+# The object files >+OBJ_CONFIG =# $(OBJDIR)/config.o >+DOBJ_CONFIG =# $(DOBJDIR)/config.o >+OBJ_YADEX = $(addprefix $(OBJDIR)/, $(addsuffix .o, $(MODULES_YADEX))) >+DOBJ_YADEX = $(addprefix $(DOBJDIR)/, $(addsuffix .o, $(MODULES_YADEX))) >+OBJ_ATCLIB = $(addprefix $(OBJDIR_ATCLIB)/, $(addsuffix .o,$(MODULES_ATCLIB))) >+DOBJ_ATCLIB = $(addprefix $(DOBJDIR_ATCLIB)/, $(addsuffix .o,$(MODULES_ATCLIB))) >+ >+# The game definition files. >+YGD = $(addprefix ygd/, \ >+ doom.ygd doom02.ygd doom04.ygd doom05.ygd \ >+ doom2.ygd doompr.ygd heretic.ygd hexen.ygd \ >+ strife.ygd strife10.ygd) >+ >+# Files that are used with scripts/process to >+# generate files that are included in the >+# distribution archive. >+DOC1_SRC = \ >+ docsrc/README \ >+ docsrc/README.doc >+ >+# Files that are used with scripts/process to >+# generate files that go in the doc/ directory >+# and are NOT included in the archive. >+DOC2_SRC_HTML = \ >+ docsrc/advanced.html \ >+ docsrc/contact.html \ >+ docsrc/credits.html \ >+ docsrc/deu_diffs.html \ >+ docsrc/editing_docs.html \ >+ docsrc/faq.html \ >+ docsrc/feedback.html \ >+ docsrc/getting_started.html \ >+ docsrc/hackers_guide.html \ >+ docsrc/help.html \ >+ docsrc/index.html \ >+ docsrc/keeping_up.html \ >+ docsrc/legal.html \ >+ docsrc/packagers_guide.html \ >+ docsrc/palette.html \ >+ docsrc/preview.html \ >+ docsrc/reporting.html \ >+ docsrc/tips.html \ >+ docsrc/trivia.html \ >+ docsrc/trouble.html \ >+ docsrc/users_guide.html \ >+ docsrc/wad_specs.html \ >+ docsrc/ygd.html >+ >+DOC2_SRC_MISC = \ >+ docsrc/yadex.6 \ >+# docsrc/yadex.lsm\ >+ >+# Files that must be put in the distribution >+# archive. Most (but not all) are generated from >+# $(DOC1_SRC_*) into the base directory. >+DOC1 = FAQ README doc/README >+ >+# Files that go in the doc/ directory and must >+# NOT be put in the distribution archive. Most >+# are either generated from $(DOC2_SRC_*) or >+# symlinked for docsrc/*.png. >+DOC2 = $(addprefix doc/, $(PIX) $(notdir $(DOC2_SRC_HTML) $(DOC2_SRC_MISC))) >+ >+# Misc. other files that must be put in the >+# distribution archive. >+MISC_FILES = \ >+ boost/boost/config.hpp \ >+ boost/boost/config/compiler/borland.hpp \ >+ boost/boost/config/compiler/comeau.hpp \ >+ boost/boost/config/compiler/common_edg.hpp \ >+ boost/boost/config/compiler/compaq_cxx.hpp \ >+ boost/boost/config/compiler/gcc.hpp \ >+ boost/boost/config/compiler/greenhills.hpp \ >+ boost/boost/config/compiler/hp_acc.hpp \ >+ boost/boost/config/compiler/intel.hpp \ >+ boost/boost/config/compiler/kai.hpp \ >+ boost/boost/config/compiler/metrowerks.hpp \ >+ boost/boost/config/compiler/mpw.hpp \ >+ boost/boost/config/compiler/sgi_mipspro.hpp \ >+ boost/boost/config/compiler/sunpro_cc.hpp \ >+ boost/boost/config/compiler/vacpp.hpp \ >+ boost/boost/config/compiler/visualc.hpp \ >+ boost/boost/config/platform/aix.hpp \ >+ boost/boost/config/platform/beos.hpp \ >+ boost/boost/config/platform/bsd.hpp \ >+ boost/boost/config/platform/cygwin.hpp \ >+ boost/boost/config/platform/hpux.hpp \ >+ boost/boost/config/platform/irix.hpp \ >+ boost/boost/config/platform/linux.hpp \ >+ boost/boost/config/platform/macos.hpp \ >+ boost/boost/config/platform/solaris.hpp \ >+ boost/boost/config/platform/win32.hpp \ >+ boost/boost/config/posix_features.hpp \ >+ boost/boost/config/select_compiler_config.hpp \ >+ boost/boost/config/select_platform_config.hpp \ >+ boost/boost/config/select_stdlib_config.hpp \ >+ boost/boost/config/stdlib/dinkumware.hpp \ >+ boost/boost/config/stdlib/libstdcpp3.hpp \ >+ boost/boost/config/stdlib/modena.hpp \ >+ boost/boost/config/stdlib/msl.hpp \ >+ boost/boost/config/stdlib/roguewave.hpp \ >+ boost/boost/config/stdlib/sgi.hpp \ >+ boost/boost/config/stdlib/stlport.hpp \ >+ boost/boost/config/stdlib/vacpp.hpp \ >+ boost/boost/config/suffix.hpp \ >+ boost/boost/config/user.hpp \ >+ boost/boost/smart_ptr.hpp \ >+ boost/boost/static_assert.hpp \ >+ boost/boost/utility.hpp \ >+ boost/boost/utility/base_from_member.hpp \ >+ boost/boost/utility_fwd.hpp \ >+ cache/copyright.man \ >+ cache/copyright.txt \ >+ cache/pixlist \ >+ cache/srcdate \ >+ cache/uptodate \ >+ configure \ >+ docsrc/copyright \ >+ CHANGES \ >+ COPYING \ >+ COPYING.LIB \ >+ GNUmakefile \ >+ Makefile \ >+ TODO \ >+ VERSION \ >+ yadex.cfg \ >+ yadex.dep >+ >+# The images used in the HTML doc. FIXME: "<img" >+# and "src=" have to be on the same line. These >+# are symlinked into doc/ when $(DOC2) is made. >+PIX = $(shell cat cache/pixlist) >+ >+# The script files. >+SCRIPTS = $(addprefix scripts/, \ >+ copyright \ >+ ftime.1 \ >+ ftime.c \ >+ install.c \ >+ mkinstalldirs \ >+ notexist.c \ >+ process \ >+ youngest) >+ >+# The patches >+PATCHES = $(addprefix patches/, \ >+ README \ >+ 1.5.0_gcc27.diff) >+ >+# All files that must be put in the distribution archive. >+ARC_FILES = $(sort $(DOC1) $(DOC1_SRC) $(DOC2_SRC_HTML) $(DOC2_SRC_MISC)\ >+ $(MISC_FILES) $(addprefix docsrc/, $(PIX)) $(SCRIPTS) $(SRC) $(YGD)\ >+ $(PATCHES)) >+ >+# The "root" directory of the archives. The >+# basename of the archives is also based on this. >+ARCHIVE := yadex-$(VERSION) >+ARCPREV := yadex-$(VERPREV) >+ARCDIFF := yadex-$(VERSION).diff >+ >+# Cosmetic >+CFLAGS := $(strip $(CFLAGS)) >+DCFLAGS := $(strip $(DCFLAGS)) >+CXXFLAGS := $(strip $(CXXFLAGS)) >+DCXXFLAGS := $(strip $(DCXXFLAGS)) >+LDFLAGS := $(strip $(LDFLAGS)) >+DLDFLAGS := $(strip $(DLDFLAGS)) >+ >+ >+######################################################################## >+# >+# Targets for >+# end users. >+# >+######################################################################## >+ >+.PHONY: all >+all: doc yadex.dep yadex $(YGD) >+ >+.PHONY: yadex >+yadex: $(OBJDIR)/yadex >+ >+$(OBJDIR)/yadex: $(OBJ_CONFIG) $(OBJ_YADEX) $(OBJ_ATCLIB) $(MAKEFILE) >+ @echo "** Linking Yadex" >+ $(CXX) $(OBJ_CONFIG) $(OBJ_YADEX) $(OBJ_ATCLIB) -o $@ \ >+ -L$(X11LIBDIR) -lX11 -lm -lc $(LDFLAGS) >+ >+.PHONY: test >+test: >+ $(OBJDIR)/yadex $(A) >+ >+.PHONY: install >+install: $(OBJDIR)/install >+ @scripts/mkinstalldirs $(BINDIR) >+ @scripts/mkinstalldirs $(ETCDIR) >+ @scripts/mkinstalldirs $(MANDIR) >+ @scripts/mkinstalldirs $(MANDIR)/man6 >+ @scripts/mkinstalldirs $(SHAREDIR) >+ $(OBJDIR)/install -m 755 $(OBJDIR)/yadex $(BINDIR)/yadex-$(VERSION) >+ rm -f $(BINDIR)/yadex >+ ln -s yadex-$(VERSION) $(BINDIR)/yadex >+ $(OBJDIR)/install -m 644 doc/yadex.6 $(MANDIR)/man6/yadex-$(VERSION).6 >+ rm -f $(MANDIR)/man6/yadex.6 >+ ln -s yadex-$(VERSION).6 $(MANDIR)/man6/yadex.6 >+ $(OBJDIR)/install -m 644 -d $(SHAREDIR) $(YGD) >+ $(OBJDIR)/install -m 644 -d $(ETCDIR) yadex.cfg >+ @echo "---------------------------------------------------------------" >+ @echo " Yadex is now installed." >+ @echo >+ @echo " Before you run it, enter the paths to your iwads in" >+ @echo " $(ETCDIR)/yadex.cfg or ~/.yadex/yadex.cfg." >+ @echo " When you're done, type \"yadex\" to start." >+ @echo " If you're confused, take a look at doc/index.html." >+ @echo >+ @echo " Happy editing !" >+ @echo "---------------------------------------------------------------" >+ >+.PHONY: clean >+clean: >+ rm -f $(OBJ_CONFIG) $(OBJ_YADEX) $(OBJ_ATCLIB) $(OBJDIR)/yadex >+ rm -f $(DOBJ_CONFIG) $(DOBJ_YADEX) $(DOBJ_ATCLIB) $(DOBJDIR)/yadex >+ rm -f $(OBJDIR)/ftime >+ rm -f $(OBJDIR)/install >+ rm -f $(OBJDIR)/notexist >+ rm -f $(OBJDIR) >+ rm -f $(DOBJDIR) >+ rm -rf doc >+ >+.PHONY: dclean >+dclean: >+ rm -rf $(DOBJPHYSDIR) >+ rm -f $(DOBJDIR) >+ >+.PHONY: doc >+doc: cache/pixlist docdirs $(DOC1) doc2 >+ >+# Have to put it separately because evaluation >+# of $(DOC2) requires cache/pixlist to exist. >+.PHONY: doc2 >+doc2: $(DOC2) >+ >+.PHONY: help >+help: >+ @echo User targets: >+ @echo "make [all] Build everything" >+ @echo "make yadex Build Yadex" >+ @echo "make test [A=args] Test Yadex" >+ @echo "make install Install everything" >+ @echo "make showconf Show current configuration" >+ @echo >+ @echo Hacker targets: >+ @echo "make dall Build debug version of everything" >+ @echo "make dyadex Build debug version of Yadex" >+ @echo "make dtest [A=args] Test debug version of Yadex" >+ @echo "make dg Run debug version of Yadex through gdb" >+ @echo "make dd Run debug version of Yadex through ddd" >+ @echo "make doc Update doc" >+ @echo "make man View man page with man" >+ @echo "make dvi View man page with xdvi" >+ @echo "make ps View man page with gv" >+ @echo "make dist Create distribution archive" >+ @echo "make save Create backup archive" >+ >+ >+######################################################################## >+# >+# Targets meant for >+# hackers only. >+# >+######################################################################## >+ >+# d: Compile and run >+.PHONY: d >+d: dyadex dtest >+ >+.PHONY: save >+save: >+ tar -cjvf yadex-$$(date '+%Y%m%d').tar.bz2 \ >+ --exclude "*.wad" \ >+ --exclude "*.zip" \ >+ --exclude "core" \ >+ --exclude "dos/*" \ >+ --exclude "obj" \ >+ --exclude "dobj" \ >+ --exclude "old/*" \ >+ --exclude "*~" \ >+ --exclude "*.bak" \ >+ --exclude "web/arc" \ >+ --exclude yadex-$$(date '+%Y%m%d').tar.bz2 \ >+ . >+ >+.PHONY: dall >+dall: yadex.dep dyadex $(YGD) >+ >+.PHONY: dyadex >+dyadex: $(DOBJDIR)/yadex >+ >+$(DOBJDIR)/yadex: $(DOBJ_CONFIG) $(DOBJ_YADEX) $(DOBJ_ATCLIB) $(MAKEFILE) >+ @echo "** Linking Yadex" >+ $(CXX) $(DOBJ_CONFIG) $(DOBJ_YADEX) $(DOBJ_ATCLIB) -o $@ \ >+ -L$(X11LIBDIR) -lX11 -lm -lc $(DLDFLAGS) >+ >+.PHONY: dtest >+dtest: >+ $(DOBJDIR)/yadex $(A) >+ gprof $(DOBJDIR)/yadex >gprof.out >+ >+.PHONY: dg >+dg: >+ gdb $(DOBJDIR)/yadex >+ >+.PHONY: dd >+dd: >+ ddd $(DOBJDIR)/yadex >+ >+.PHONY: asm >+asm: $(addprefix $(OBJDIR)/, $(addsuffix .S, $(MODULES_YADEX))) >+ >+# Generate the distribution archives. Requires GNU tar, >+# GNU cp, gzip and optionally bzip2 (if distbz2 is >+# uncommented). >+.PHONY: dist >+dist: changes distimage distgz distdiff #distbz2 >+ @echo "** Removing distribution image tree $(ARCHIVE)" >+ rm -r $(ARCHIVE) >+ >+.PHONY: distimage >+distimage: all $(ARC_FILES) >+ @echo "** Creating distribution image tree $(ARCHIVE)" >+ rm -rf $(ARCHIVE) >+ scripts/mkinstalldirs $(ARCHIVE) >+ @tar -cf - $(ARC_FILES) | (cd $(ARCHIVE); tar -xf -) >+ >+.PHONY: distgz >+distgz: distimage >+ @echo "** Creating tar.gz distribution" >+ tar -czf $(ARCHIVE).tar.gz $(ARCHIVE) >+ >+.PHONY: distbz2 >+distbz2: distimage >+ @echo "** Creating .tar.bz2 distribution" >+ tar -cIf $(ARCHIVE).tar.bz2 $(ARCHIVE) >+ >+.PHONY: distdiff >+TMP0 = $$HOME/tmp >+TMPPREV = $(TMP0)/$(ARCPREV) >+TMPCURR = $(TMP0)/$(ARCHIVE) >+distdiff: >+ @echo "** Building the diff distribution" >+ @echo "Creating the diff" >+ rm -rf $(TMPPREV) $(TMPCURR) $(TMPDIFF) >+ mkdir -p $(TMP0) >+ tar -xzf $(ARCHIVE).tar.gz -C $(TMP0) >+ tar -xzf ../yadex-arc/pub/$(ARCPREV).tar.gz -C $(TMP0) >+ scripts/process docsrc/README.diff >$(TMP0)/$(ARCDIFF) >+ echo >>$(TMP0)/$(ARCDIFF) >+ cd $(TMP0) && (diff -uaNr $(ARCPREV) $(ARCHIVE) >>$(ARCDIFF) || true) >+ @# KLUDGE - On my system, just "! grep" makes make choke >+ true; ! grep "^Binary files .* and .* differ" $(TMP0)/$(ARCDIFF) >+ gzip -f $(TMP0)/$(ARCDIFF) >+ @echo "Verifying the diff" >+ cd $(TMPPREV) && gzip -d <../$(ARCDIFF).gz | patch -p1 >+ @# FIXME remove -N after 1.6 is done, it's there because >+ @# uptodate has been moved between 1.5 and 1.6 and since >+ @# it's empty it remains in $(ARCPREV). >+ cd $(TMP0) && diff -rP $(ARCHIVE) $(ARCPREV) >+ mv $(TMP0)/$(ARCDIFF).gz . >+ @echo "Cleaning up" >+ cd $(TMP0) && rm -rf $(ARCPREV) >+ cd $(TMP0) && rm -rf $(ARCHIVE) >+ >+.PHONY: showconf >+showconf: >+ @echo "ARCHIVE \"$(ARCHIVE)\"" >+ @echo "BINDIR \"$(BINDIR)\"" >+ @echo "CC \"$(CC)\"" >+ @echo "CFLAGS \"$(CFLAGS)\"" >+ @echo "CXX \"$(CXX)\"" >+ @echo "CXXFLAGS \"$(CXXFLAGS)\"" >+ @echo "DCFLAGS \"$(DCFLAGS)\"" >+ @echo "DCXXFLAGS \"$(DCXXFLAGS)\"" >+ @echo "DLDFLAGS \"$(DLDFLAGS)\"" >+ @echo "ETCDIR \"$(ETCDIR)\"" >+ @echo "ETCDIRNV \"$(ETCDIRNV)\"" >+ @echo "HAVE_GETTIMEOFDAY \"$(HAVE_GETTIMEOFDAY)\"" >+ @echo "HAVE_NANOSLEEP \"$(HAVE_NANOSLEEP)\"" >+ @echo "HAVE_SNPRINTF \"$(HAVE_SNPRINTF)\"" >+ @echo "HAVE_USLEEP \"$(HAVE_USLEEP)\"" >+ @echo "LDFLAGS \"$(LDFLAGS)\"" >+ @echo "MANDIR \"$(MANDIR)\"" >+ @echo "OS \"$(OS)\"" >+ @echo "PREFIX \"$(PREFIX)\"" >+ @echo "SHAREDIR \"$(SHAREDIR)\"" >+ @echo "SHAREDIRNV \"$(SHAREDIRNV)\"" >+ @echo "SHELL \"$(SHELL)\"" >+ @echo "SYSTEM \"$(SYSTEM)\"" >+ @echo "VERSION \"$(VERSION)\"" >+ @echo "X11INCLUDEDIR \"$(X11INCLUDEDIR)\"" >+ @echo "X11LIBDIR \"$(X11LIBDIR)\"" >+ @echo "CXX --version \"`$(CXX) --version`\"" >+ @echo "CC --version \"`$(CC) --version`\"" >+ @echo "shell \"$$SHELL\"" >+ @echo "uname \"`uname`\"" >+ >+ >+######################################################################## >+# >+# Internal targets, not meant >+# to be invoked directly >+# >+######################################################################## >+ >+# If Makefile.config or config.h don't exist, give a hint... >+$(OBJDIR)/Makefile.config: >+$(OBJDIR)/config.h: >+ @echo "Sorry guv'nor, but... did you run ./configure ?" >&2 >+ @false >+ >+$(OBJDIR)/files_etc.man: $(OBJDIR)/config.etc $(MAKEFILE) >+ sed 's/%v/$(VERSION)/g; s,.*,.B &/yadex.cfg,' $< >$@ >+ >+$(OBJDIR)/files_share.man: $(OBJDIR)/config.share $(MAKEFILE) >+ sed 's/%v/$(VERSION)/g; s,.*,.BI &/ game .ygd,' $< >$@ >+ >+# Dependencies of the modules of Yadex >+# -Y is here to prevent the inclusion of dependencies on >+# /usr/include/*.h etc. As a side-effect, it generates many >+# warnings, hence "2>/dev/null". >+# >+# The purpose of the awk script is to transform this input : >+# >+# src/foo.o: src/whatever.h >+# >+# into this output : >+# >+# obj/0/foo.o: src/whatever.h >+# dobj/0/foo.o: src/whatever.h >+# >+# Note: the modules of Atclib are not scanned as they all >+# depend on $(HEADERS_ATCLIB) and nothing else. >+ >+yadex.dep: $(SRC_NON_GEN) src/config.h >+ @echo "Generating $@" >+ @makedepend -f- -Y -Iatclib $(SRC_NON_GEN) 2>/dev/null \ >+ | awk 'sub (/^src/, "") == 1 { \ >+ print "'$(OBJDIR)'" $$0; \ >+ print "'$(DOBJDIR)'" $$0; \ >+ next; \ >+ }' >$@ >+ >+cache/copyright.man: $(MAKEFILE) scripts/copyright docsrc/copyright >+ scripts/copyright -m docsrc/copyright >$@ >+ >+cache/copyright.txt: $(MAKEFILE) scripts/copyright docsrc/copyright >+ scripts/copyright -t docsrc/copyright | sed 's/^./ &/' >$@ >+ >+# The YYYY-MM-DD date indicated in the parentheses after the >+# version number is the mtime of the most recent source file >+# (where "being a source file" is defined as "being listed in >+# $(SRC_NON_GEN)"). That string is the output of a perl script, >+# scripts/youngest. Since perl is not necessarily installed on >+# all machines, we cache that string in the file cache/srcdate >+# and include that file in the distribution archive. If we >+# didn't do that, people who don't have perl would be unable to >+# build Yadex. >+# >+# Conceptually, cache/srcdate depends on $(SRC_NON_GEN) and >+# doc/*.html depend on cache/srcdate. However, we can't write the >+# makefile that way because if we did, that would cause two >+# problems. Firstly every time a source file is changed, >+# scripts/youngest would be ran, most of the time for nothing >+# since its output is always the same, unless it's never been >+# run today. Secondly, cache/srcdate being just generated, it's >+# more recent than the content of the doc/ directory. The result >+# would be that the entire doc/ directory would be rebuilt every >+# time a single source file is changed, which is guaranteed to >+# have an unnerving effect on the hacker at the keyboard. >+# >+# Part of the solution is to systematically force the mtime of >+# cache/srcdate to 00:00, today. Thus, cache/srcdate always looks >+# older than the content of the doc/ directory, unless it's not >+# been refreshed yet today. >+# >+# But that's not enough because then cache/srcdate also looks >+# always older than the source files it depends on, and thus >+# make attempts to regenerate it every time make is invoked at >+# all, which would render the very existence of cache/srcdate >+# useless. That's why we have another file, cache/uptodate, that >+# we touch to keep track of the time when we last generated >+# cache/srcdate. >+# >+# If there was a such thing as _date-only_ dependencies, I could >+# get away with just this : >+# >+# cache/srcdate: scripts/youngest >+# cache/srcdate <date_dependency_operator> $(SRC_NON_GEN) >+# if perl -v >/dev/null 2>&1; then\ >+# scripts/youngest >$@;\ >+# else\ >+# blah... >+# doc/*.html <date_dependency_operator> cache/srcdate >+# blah... >+# >+# That would save two calls to "touch", one intermediary >+# dependency (cache/uptodate) and a lot of obfuscation. >+cache/srcdate: cache/uptodate >+ >+cache/uptodate: scripts/youngest $(SRC_NON_GEN) >+ @mkdir -p cache >+ @if perl -v >/dev/null 2>&1; then \ >+ echo Generating cache/srcdate; \ >+ scripts/youngest $(SRC_NON_GEN) >cache/srcdate; \ >+ touch -t `date '+%m%d'`0000 cache/srcdate; \ >+ elif [ -r cache/srcdate ]; then \ >+ echo Perl not available. Keeping old cache/srcdate; \ >+ else \ >+ echo Perl not available. Creating bogus cache/srcdate; \ >+ date '+%Y-%m-%d' >cache/srcdate; \ >+ fi >+ @touch $@; >+ >+# To compile the modules of Yadex >+# (normal and debugging versions) >+include yadex.dep >+ >+# It's simpler to copy config.cc into src/ than to have a >+# compilation rule for just one file. >+src/config.cc: $(OBJDIR)/config.cc >+ cp -p $< $@ >+ >+src/config.h: $(OBJDIR)/config.h >+ cp -p $< $@ >+ >+$(OBJDIR)/%.o: src/%.cc >+ $(CXX) -c -Iatclib -Iboost -I$(X11INCLUDEDIR) $(CXXFLAGS) $< -o $@ >+ >+$(DOBJDIR)/%.o: src/%.cc >+ $(CXX) -c -Iatclib -Iboost -I$(X11INCLUDEDIR) $(DCXXFLAGS) $< -o $@ >+ >+# To compile the modules of Atclib >+# (normal and debugging versions) >+$(OBJDIR_ATCLIB)/%.o: atclib/%.c $(HEADERS_ATCLIB) >+ $(CC) -c $(CFLAGS) $< -o $@ >+ >+$(DOBJDIR_ATCLIB)/%.o: atclib/%.c $(HEADERS_ATCLIB) >+ $(CC) -c $(DCFLAGS) $< -o $@ >+ >+# To see the generated assembly code >+# for the modules of Yadex >+$(OBJDIR)/%.S: src/%.cc $(MAKEFILE) >+ $(CXX) $(CXXFLAGS) -S -fverbose-asm -Iatclib -Iboost -I$(X11INCLUDEDIR)\ >+ $< -o $@ >+ >+# A source file containing the credits >+src/credits.cc: $(MAKEFILE) docsrc/copyright scripts/copyright >+ @echo Generating $@ >+ @echo '// DO NOT EDIT -- generated from docsrc/copyright' >$@ >+ scripts/copyright -c docsrc/copyright >>$@ >+ >+# A source file containing just the date of the >+# most recent source file and the version number >+# (found in ./VERSION) >+src/version.cc: $(SRC_NON_GEN) VERSION cache/srcdate $(MAKEFILE) >+ @echo Generating $@ >+ @printf '// DO NOT EDIT -- generated from VERSION\n\n' >$@ >+ @printf "extern const char *const yadex_source_date = \"%s\";\n" \ >+ `cat cache/srcdate` >>$@ >+ @printf "extern const char *const yadex_version = \"%s\";\n" \ >+ "$(VERSION)" >>$@ >+ >+ >+# -------- Doc-related stuff -------- >+ >+docdirs: >+ @if [ ! -d doc ]; then mkdir doc; fi >+ >+cache/pixlist: $(DOC2_SRC_HTML) >+ @echo Generating $@ >+ @mkdir -p cache >+ @if perl -v >/dev/null 2>/dev/null; then \ >+ perl -ne '@l = m/<img\s[^>]*src="?([^\s">]+)/io; \ >+ print "@l\n" if @l;' $(DOC2_SRC_HTML) | sort | uniq >$@; \ >+ elif [ -f $@ ]; then \ >+ echo "Sorry, you need Perl to refresh $@. Keeping old $@."; \ >+ else \ >+ echo "Sorry, you need Perl to create $@. Creating empty $@."; \ >+ touch $@; \ >+ fi >+ >+events.html: ev evhtml >+ evhtml -- -n $< >$@ >+ >+events.txt: events.html >+ lynx -dump $< >$@ >+ >+changes/changes.html: changes/*.log log2html RELEASE >+ ./log2html -- -r `cat RELEASE` -- $$(ls -r changes/*.log) >$@ >+ >+# changes - update the changelog >+.PHONY: changes >+changes: changes/changes.html >+ w3m -dump -cols 72 $< >CHANGES >+ >+# cns - view the changelog with Netscape >+.PHONY: cns >+cns: >+ netscape -remote "openURL(file:$$(pwd)/changes/changes.html,new-window)" >+ >+# clynx - view the changelog with Lynx >+.PHONY: clynx >+clynx: >+ lynx changes/changes.html >+ >+# cless - view the changelog with less >+.PHONY: cless >+cless: >+ less CHANGES >+ >+# man - view the man page with man >+.PHONY: man >+man: doc/yadex.6 >+ man -l $^ >+ >+# dvi - view the man page with xdvi >+.PHONY: dvi >+dvi: doc/yadex.dvi >+ xdvi $^ >+ >+# ps - view the man page with gv >+.PHONY: ps >+ps: doc/yadex.ps >+ gv $^ >+ >+# Use docsrc/faq.html and not directly >+# doc/faq.html because we don't want FAQ to be >+# remade at first build time. >+FAQ: docsrc/faq.html >+ scripts/process $< >cache/faq.html >+ links -width 72 -dump cache/faq.html >$@ >+ rm cache/faq.html >+ >+doc/yadex.dvi: doc/yadex.6 >+ groff -Tdvi -man $^ >$@ >+ >+doc/yadex.ps: doc/yadex.6 >+ groff -Tps -man $^ >$@ >+ >+ >+# Generate the doc by filtering them through scripts/process >+PROCESS = \ >+ VERSION \ >+ cache/copyright.man \ >+ cache/copyright.txt \ >+ cache/srcdate \ >+ scripts/process \ >+ $(OBJDIR)/ftime \ >+ $(OBJDIR)/files_etc.man \ >+ $(OBJDIR)/files_share.man \ >+ $(OBJDIR)/notexist >+ >+doc/yadex.6: docsrc/yadex.6 $(PROCESS) >+ @echo Generating $@ >+ @scripts/process $< >$@ >+ >+doc/README: docsrc/README.doc $(PROCESS) >+ @echo Generating $@ >+ @scripts/process $< >$@ >+ >+%: docsrc/% $(PROCESS) >+ @echo Generating $@ >+ @scripts/process $< >$@ >+ >+doc/%.html: docsrc/%.html $(PROCESS) >+ @echo Generating $@ >+ @scripts/process $< >$@ >+ >+# The images are just symlinked from docsrc/ to doc/ >+doc/%.png: docsrc/%.png >+ @rm -f $@ >+ @ln -s ../$< $@ >+ >+$(OBJDIR)/ftime: scripts/ftime.c >+ $(CC) $< -o $@ >+ >+$(OBJDIR)/install: scripts/install.c >+ $(CC) $< -o $@ >+ >+$(OBJDIR)/notexist: scripts/notexist.c >+ $(CC) $< -o $@ >+ >+ >diff -Nru yadex-1.7.0-orig/src/editloop.cc yadex-1.7.0/src/editloop.cc >--- yadex-1.7.0-orig/src/editloop.cc 2003-07-05 06:12:32.000000000 -0500 >+++ yadex-1.7.0/src/editloop.cc 2012-06-17 18:47:12.482693150 -0400 >@@ -43,6 +43,7 @@ > #include "entry.h" > #include "entry2.h" > #include "events.h" >+#include "game.h" > #include "gfx.h" > #include "gfx2.h" // show_character_set() show_pcolours() > #include "gfx3.h" >@@ -70,6 +71,7 @@ > #include "x_exchng.h" > #include "x_hover.h" > #include "xref.h" >+#include "r_render.h" > > #ifdef Y_X11 > #include <X11/Xlib.h> >@@ -93,6 +95,7 @@ > > /* prototypes of private functions */ > static int SortLevels (const void *item1, const void *item2); >+static char *GetBehaviorFileName (const char *levelname); > > /* > * SelectLevel >@@ -302,15 +305,28 @@ > "~Quit", 'q', 0, > NULL); > >-e.mb_menu[MBM_EDIT] = new Menu (NULL, >- "~Copy object(s)", 'o', 0, >- "~Add object", YK_INS, 0, >- "~Delete object(s)", YK_DEL, 0, >- "~Exchange object numbers", 24, 0, >- "~Preferences...", YK_F5, 0, >- "~Snap to grid", 'y', MIF_VTICK, &e.grid_snap, 0, >- "~Lock grid step", 'z', MIF_VTICK, &e.grid_step_locked, 0, >- NULL); >+if (yg_level_format == YGLF_HEXEN) >+ e.mb_menu[MBM_EDIT] = new Menu (NULL, >+ "~Copy object(s)", 'o', 0, >+ "~Add object", YK_INS, 0, >+ "~Delete object(s)", YK_DEL, 0, >+ "~Exchange object numbers", 24, 0, >+ "~Preferences...", YK_F5, 0, >+ "~Snap to grid", 'y', MIF_VTICK, &e.grid_snap, 0, >+ "~Lock grid step", 'z', MIF_VTICK, &e.grid_step_locked, 0, >+ "Load ~BEHAVIOR lump", 'b', 0, >+ NULL); >+else >+ e.mb_menu[MBM_EDIT] = new Menu (NULL, >+ "~Copy object(s)", 'o', 0, >+ "~Add object", YK_INS, 0, >+ "~Delete object(s)", YK_DEL, 0, >+ "~Exchange object numbers", 24, 0, >+ "~Preferences...", YK_F5, 0, >+ "~Snap to grid", 'y', MIF_VTICK, &e.grid_snap, 0, >+ "~Lock grid step", 'z', MIF_VTICK, &e.grid_step_locked, 0, >+ NULL); >+ > > // If you change the order of modes here, don't forget > // to modify the <modes> array. >@@ -342,6 +358,7 @@ > "~Next object", 'n', 0, > "~Prev object", 'p', 0, > "~Jump to object...", 'j', 0, >+ "~Find by type", 'f', 0, > NULL); > > e.mb_menu[MBM_MISC_L] = new Menu ("Misc. operations", >@@ -1344,8 +1361,8 @@ > } > } > >- // [F8]: pop up the "Misc. operations" menu >- else if (is.key == YK_F8 >+ // [M]: pop up the "Misc. operations" menu >+ else if (is.key == 'M' > && e.menubar->highlighted () < 0) > { > e.modpopup->set (e.menubar->get_menu (MBI_MISC), 1); >@@ -1706,7 +1723,15 @@ > select_linedefs_path (&e.Selected, e.highlighted.num, YS_TOGGLE); > RedrawMap = 1; > } >- >+ // [E]: add linedef and split sector -- [AJA] >+ else if (is.key == 'E' && e.obj_type == OBJ_VERTICES) >+ { >+ if (e.Selected) >+ { >+ MiscOperations (e.obj_type, &e.Selected, 5); >+ RedrawMap = 1; >+ } >+ } > // [E]: Select/unselect all 1s linedefs in path > else if (is.key == 'E' && e.highlighted._is_linedef ()) > { >@@ -1834,6 +1859,56 @@ > RedrawMap = 1; > } > >+ // [f]: find object by type >+ else if (is.key == 'f' && (! e.global || e.highlighted ())) >+ { >+ Objid find_obj; >+ int otype; >+ obj_no_t omax,onum; >+ find_obj.type = e.highlighted () ? e.highlighted.type : e.obj_type; >+ onum = find_obj.num = e.highlighted () ? e.highlighted.num : 0; >+ omax = GetMaxObjectNum(find_obj.type); >+ switch (find_obj.type) >+ { >+ case OBJ_SECTORS: >+ if ( ! InputSectorType( 84, 21, &otype)) >+ { >+ for (onum = e.highlighted () ? onum + 1 : onum; onum <= omax; onum++) >+ if (Sectors[onum].special == (wad_stype_t) otype) >+ { >+ find_obj.num = onum; >+ GoToObject(find_obj); >+ break; >+ } >+ } >+ break; >+ case OBJ_THINGS: >+ if ( ! InputThingType( 42, 21, &otype)) >+ { >+ for (onum = e.highlighted () ? onum + 1 : onum; onum <= omax; onum++) >+ if (Things[onum].type == (wad_ttype_t) otype) >+ { >+ find_obj.num = onum; >+ GoToObject(find_obj); >+ break; >+ } >+ } >+ break; >+ case OBJ_LINEDEFS: >+ if ( ! InputLinedefType( 0, 21, &otype)) >+ { >+ for (onum = e.highlighted () ? onum + 1 : onum; onum <= omax; onum++) >+ if (LineDefs[onum].type == (wad_ldtype_t) otype) >+ { >+ find_obj.num = onum; >+ GoToObject(find_obj); >+ break; >+ } >+ } >+ break; >+ } >+ RedrawMap = 1; >+ } > #if 0 > // [c]: clear selection and redraw the map > else if (is.key == 'c') >@@ -1921,6 +1996,17 @@ > StretchSelBox = false; > } > >+ // [w]: split sector between vertices >+ else if (is.key == 'w' && e.obj_type == OBJ_VERTICES >+ && e.Selected && e.Selected->next && ! e.Selected->next->next) >+ { >+ SplitSector (e.Selected->next->objnum, e.Selected->objnum); >+ ForgetSelection (&e.Selected); >+ RedrawMap = 1; >+ DragObject = false; >+ StretchSelBox = false; >+ } >+ > // [x]: spin things 1/8 turn clockwise > else if (is.key == 'x' && e.obj_type == OBJ_THINGS > && (e.Selected || e.highlighted ())) >@@ -1987,7 +2073,7 @@ > } > > // [Del]: delete the current object >- else if (is.key == YK_DEL >+ else if (is.key == '\b' > && (e.Selected || e.highlighted ())) /* 'Del' */ > { > if (e.obj_type == OBJ_THINGS >@@ -2015,7 +2101,7 @@ > } > > // [Ins]: insert a new object >- else if (is.key == YK_INS || is.key == YK_INS + YK_SHIFT) /* 'Ins' */ >+ else if (is.key == 'I' || is.key == YK_INS + YK_SHIFT) /* 'Ins' */ > { > SelPtr cur; > int prev_obj_type = e.obj_type; >@@ -2201,12 +2287,34 @@ > RedrawMap = 1; > } > >+ // [Z] Set sector on surrounding linedefs (AJA) >+ else if (is.key == 'Z' && e.pointer_in_window) >+ { >+ if (e.obj_type == OBJ_SECTORS && e.Selected) >+ { >+ SuperSectorSelector (e.pointer_x, e.pointer_y, >+ e.Selected->objnum); >+ } >+ else >+ { >+ SuperSectorSelector (e.pointer_x, e.pointer_y, OBJ_NO_NONE); >+ } >+ RedrawMap = 1; >+ } >+ > // [!] Debug info (not documented) > else if (is.key == '!') > { > DumpSelection (e.Selected); > } > >+ // [R] Render 3D view (AJA) >+ else if (is.key == 'R') >+ { >+ Render3D (); >+ RedrawMap = 1; >+ } >+ > // [@] Show font (not documented) > else if (is.key == '@') > { >@@ -2214,6 +2322,30 @@ > RedrawMap = 1; > } > >+ // [T] Transfer properties to selected objects (AJA) >+ else if (is.key == 'T' && e.Selected >+ && e.highlighted.num >= 0) >+ { >+ switch (e.obj_type) >+ { >+ case OBJ_SECTORS: >+ TransferSectorProperties (e.highlighted.num, e.Selected); >+ RedrawMap = 1; >+ break; >+ case OBJ_THINGS: >+ TransferThingProperties (e.highlighted.num, e.Selected); >+ RedrawMap = 1; >+ break; >+ case OBJ_LINEDEFS: >+ TransferLinedefProperties (e.highlighted.num, e.Selected); >+ RedrawMap = 1; >+ break; >+ default: >+ Beep (); >+ break; >+ } >+ } >+ > // [|] Show colours (not documented) > else if (is.key == '|') > { >@@ -2298,6 +2430,30 @@ > RedrawMap = 1; > } > >+ // Load BEHAVIOR lump (JL) >+ else if (is.key == 'b') >+ { >+ char *acsfile; >+ const char *acsname; >+ if (levelname) >+ acsname = levelname; >+ else >+ acsname = "behavior"; >+ acsfile = GetBehaviorFileName (acsname); >+ FILE* f = fopen(acsfile, "rb"); >+ if (f) >+ { >+ FreeFarMemory(Behavior); >+ fseek(f, 0, SEEK_END); >+ BehaviorSize = ftell(f); >+ Behavior = (u8*)GetFarMemory(BehaviorSize); >+ fseek(f, 0, SEEK_SET); >+ fread(Behavior, BehaviorSize, 1, f); >+ fclose(f); >+ } >+ RedrawMap = 1; >+ } >+ > /* user likes music */ > else if (is.key) > { >@@ -2447,4 +2603,32 @@ > return 0; > } > >+/* >+ get the name of the BEHAVIOR lump file (returns NULL on Esc) >+*/ >+ >+static char *GetBehaviorFileName (const char *levelname) >+{ >+#define BUFSZ 79 >+ char *outfile = (char *) GetMemory (BUFSZ + 1); >+ >+ /* get the file name */ >+ // If no name, find a default one >+ if (! levelname) >+ { >+ levelname = "behavior"; >+ } >+ >+ al_scpslower (outfile, levelname, BUFSZ); >+ al_saps (outfile, ".o", BUFSZ); >+ InputFileName (-1, -1, "Name of the BEHAVIOR script file:", BUFSZ, outfile); >+ /* escape */ >+ if (outfile[0] == '\0') >+ { >+ FreeMemory (outfile); >+ return 0; >+ } >+ return outfile; >+} >+ > >diff -Nru yadex-1.7.0-orig/src/editloop.h yadex-1.7.0/src/editloop.h >--- yadex-1.7.0-orig/src/editloop.h 2000-01-10 08:40:12.000000000 -0500 >+++ yadex-1.7.0/src/editloop.h 2012-06-17 18:47:12.482693150 -0400 >@@ -6,6 +6,9 @@ > > void EditorLoop (const char *); /* SWAP! */ > const char *SelectLevel (int levelno); >+extern int InputSectorType(int x0, int y0, int *number); >+extern int InputLinedefType(int x0, int y0, int *number); >+extern int InputThingType(int x0, int y0, int *number); > > > >diff -Nru yadex-1.7.0-orig/src/editobj.cc yadex-1.7.0/src/editobj.cc >--- yadex-1.7.0-orig/src/editobj.cc 2003-04-24 15:32:39.000000000 -0500 >+++ yadex-1.7.0/src/editobj.cc 2012-06-17 18:49:02.961390180 -0400 >@@ -937,7 +937,7 @@ > struct SideDef *s = SideDefs + l->sidedef1; > strcpy (s->tex1, "-"); > strcpy (s->tex2, "-"); >- strcpy (s->tex3, default_middle_texture); >+ strncpy (s->tex3, default_middle_texture, sizeof(s->tex3)); > } > /* Don't delete the 2nd sidedef, it could be used > by another linedef. And if it isn't, the next >diff -Nru yadex-1.7.0-orig/src/gcolour1.cc yadex-1.7.0/src/gcolour1.cc >--- yadex-1.7.0-orig/src/gcolour1.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/gcolour1.cc 2012-06-17 18:47:12.483693157 -0400 >@@ -127,6 +127,21 @@ > } > verbmsg ("colours: colour %d remapped to %d (delta %d)\n", > IMG_TRANSP, colour0, smallest_delta); >+ >+ rgb_c med_blue (0, 0, 128); >+ sky_colour = 0; >+ smallest_delta = INT_MAX; >+ >+ for (size_t n = 0; n < DOOM_COLOURS; n++) >+ { >+ int delta = med_blue - rgb_values[n]; >+ if (delta < smallest_delta) >+ { >+ sky_colour = n; >+ smallest_delta = delta; >+ } >+ } >+ verbmsg ("Sky Colour remapped to %d (delta %d)\n", sky_colour, smallest_delta); > } > > #endif >diff -Nru yadex-1.7.0-orig/src/gcolour2.cc yadex-1.7.0/src/gcolour2.cc >--- yadex-1.7.0-orig/src/gcolour2.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/gcolour2.cc 2012-06-17 18:47:12.484693164 -0400 >@@ -35,4 +35,5 @@ > > pcolour_t *game_colour = 0; // Pixel values for the DOOM_COLOURS game clrs. > int colour0; // Game colour to which g. colour 0 is remapped >+int sky_colour; // Game colour for a medium sky blue > >diff -Nru yadex-1.7.0-orig/src/gcolour2.h yadex-1.7.0/src/gcolour2.h >--- yadex-1.7.0-orig/src/gcolour2.h 2000-08-10 16:18:16.000000000 -0500 >+++ yadex-1.7.0/src/gcolour2.h 2012-06-17 18:47:12.484693164 -0400 >@@ -10,4 +10,5 @@ > > extern pcolour_t *game_colour; // Pixel values for the DOOM_COLOURS game clrs. > extern int colour0; // Game colour to which g. colour 0 is remapped >+extern int sky_colour; // Game colour for a medium blue sky > >diff -Nru yadex-1.7.0-orig/src/gfx.cc yadex-1.7.0/src/gfx.cc >--- yadex-1.7.0-orig/src/gfx.cc 2003-12-14 19:50:02.000000000 -0500 >+++ yadex-1.7.0/src/gfx.cc 2012-06-17 18:48:17.800105189 -0400 >@@ -310,7 +310,7 @@ > win_vis_id = vis_info->visualid; > #if defined _cplusplus || defined __cplusplus > win_vis_class = vis_info->c_class; >-#elif >+#else > win_vis_class = vis_info->class; > #endif > win_ncolours = vis_info->colormap_size; >diff -Nru yadex-1.7.0-orig/src/levels.cc yadex-1.7.0/src/levels.cc >--- yadex-1.7.0-orig/src/levels.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/levels.cc 2012-06-17 18:47:42.121880099 -0400 >@@ -58,6 +58,8 @@ > VPtr Vertices; /* vertex data */ > int NumSectors; /* number of sectors */ > SPtr Sectors; /* sectors data */ >+u8* Behavior; >+int BehaviorSize; > > // FIXME should be somewhere else > int NumWTexture; /* number of wall textures */ >@@ -95,6 +97,10 @@ > the Level has never been saved yet, > an empty string. */ > >+static u8 DefaultBehavior[16] = { >+ 'A', 'C', 'S', 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 >+}; >+ > void EmptyLevelData (const char *levelname) > { > Things = 0; >@@ -109,6 +115,12 @@ > NumSectors = 0; > Vertices = 0; > NumVertices = 0; >+if (yg_level_format == YGLF_HEXEN) >+ { >+ BehaviorSize = sizeof(DefaultBehavior); >+ Behavior = (u8*) GetFarMemory ((unsigned long) BehaviorSize ); >+ memcpy(Behavior, DefaultBehavior, BehaviorSize); >+ } > } > > >@@ -199,7 +211,7 @@ > { > offset = dir->dir.start; > length = dir->dir.size; >- if (MainWad == Iwad4) // Hexen mode >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode > { > NumThings = (int) (length / WAD_HEXEN_THING_BYTES); > if ((i32) (NumThings * WAD_HEXEN_THING_BYTES) != length) >@@ -234,18 +246,23 @@ > rc = 1; > goto byebye; > } >- if (MainWad == Iwad4) // Hexen mode >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode > for (long n = 0; n < NumThings; n++) > { > u8 dummy2[6]; >- wf->read_i16 (); // Tid >+ wf->read_i16 (&Things[n].tid ); > wf->read_i16 (&Things[n].xpos ); > wf->read_i16 (&Things[n].ypos ); >- wf->read_i16 (); // Height >+ wf->read_i16 (&Things[n].height); > wf->read_i16 (&Things[n].angle); > wf->read_i16 (&Things[n].type ); > wf->read_i16 (&Things[n].when ); >- wf->read_bytes (dummy2, sizeof dummy2); >+ wf->read_u8 (Things[n].special); >+ wf->read_u8 (Things[n].arg1 ); >+ wf->read_u8 (Things[n].arg2 ); >+ wf->read_u8 (Things[n].arg3 ); >+ wf->read_u8 (Things[n].arg4 ); >+ wf->read_u8 (Things[n].arg5 ); > if (wf->error ()) > { > err ("%s: error reading thing #%ld", lump_name, n); >@@ -283,7 +300,7 @@ > NumLineDefs = 0; > else > { >- if (MainWad == Iwad4) // Hexen mode >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode > { > NumLineDefs = (int) (dir->dir.size / WAD_HEXEN_LINEDEF_BYTES); > if ((i32) (NumLineDefs * WAD_HEXEN_LINEDEF_BYTES) != dir->dir.size) >@@ -310,7 +327,7 @@ > rc = 1; > goto byebye; > } >- if (MainWad == Iwad4) // Hexen mode >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode > for (long n = 0; n < NumLineDefs; n++) > { > u8 dummy[6]; >@@ -322,6 +339,10 @@ > wf->read_i16 (&LineDefs[n].sidedef2); > LineDefs[n].type = dummy[0]; > LineDefs[n].tag = dummy[1]; // arg1 often contains a tag >+ LineDefs[n].arg2 = dummy[2]; >+ LineDefs[n].arg3 = dummy[3]; >+ LineDefs[n].arg4 = dummy[4]; >+ LineDefs[n].arg5 = dummy[5]; > if (wf->error ()) > { > err ("%s: error reading linedef #%ld", lump_name, n); >@@ -907,6 +928,37 @@ > } > } > >+// Read BEHAVIOR >+if (yg_level_format == YGLF_HEXEN) >+{ >+const char *lump_name = "BEHAVIOR"; >+verbmsg (" behavior\n"); >+dir = FindMasterDir (Level, lump_name); >+if (dir) >+ { >+ BehaviorSize = (int)dir->dir.size; >+ if (BehaviorSize > 0) >+ { >+ Behavior = (u8*) GetFarMemory ((unsigned long) BehaviorSize ); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ wf->read_bytes (Behavior, BehaviorSize); >+ if (wf->error ()) >+ { >+ err ("%s: error behavior lump", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+} >+ > /* Sanity checking on sidedefs: the sector must exist. I don't > make this a fatal error, though, because it's not exceptional > to find wads with unused sidedefs with a sector# of -1. Well >@@ -1011,16 +1063,10 @@ > FILE *file; > MDirPtr dir; > int n; >-long lump_offset[WAD_LL__]; >-size_t lump_size[WAD_LL__]; >+long lump_offset[WAD_LL__MAX]; >+size_t lump_size[WAD_LL__MAX]; > wad_level_lump_no_t l; > >-if (yg_level_format == YGLF_HEXEN || ! strcmp (Game, "hexen")) >- { >- Notify (-1, -1, "I refuse to save. Hexen mode is still", >- "too badly broken. You would lose data."); >- return 1; >- } > if (! level_name || ! levelname2levelno (level_name)) > { > nf_bug ("SaveLevelData: bad level_name \"%s\", using \"E1M1\" instead.", >@@ -1047,9 +1093,15 @@ > && ! MadeMapChanges > && yg_level_format != YGLF_ALPHA; > >+int NumLumps; >+if (yg_level_format == YGLF_HEXEN) >+ NumLumps = WAD_LL__HEXEN; >+else >+ NumLumps = WAD_LL__DOOM; >+ > // Write the pwad header > WriteBytes (file, "PWAD", 4); // Pwad file >-file_write_i32 (file, WAD_LL__); // Number of entries = 11 >+file_write_i32 (file, NumLumps); // Number of entries = 11 > file_write_i32 (file, 0); // Fix this up later > if (Level) > dir = Level->next; >@@ -1067,11 +1119,30 @@ > ObjectsNeeded (OBJ_THINGS, 0); > for (n = 0; n < NumThings; n++) > { >- file_write_i16 (file, Things[n].xpos ); >- file_write_i16 (file, Things[n].ypos ); >- file_write_i16 (file, Things[n].angle); >- file_write_i16 (file, Things[n].type ); >- file_write_i16 (file, Things[n].when ); >+ if (yg_level_format == YGLF_HEXEN) >+ { >+ file_write_i16 (file, Things[n].tid ); >+ file_write_i16 (file, Things[n].xpos ); >+ file_write_i16 (file, Things[n].ypos ); >+ file_write_i16 (file, Things[n].height); >+ file_write_i16 (file, Things[n].angle); >+ file_write_i16 (file, Things[n].type ); >+ file_write_i16 (file, Things[n].when ); >+ WriteBytes (file, &Things[n].special, 1); >+ WriteBytes (file, &Things[n].arg1, 1 ); >+ WriteBytes (file, &Things[n].arg2, 1 ); >+ WriteBytes (file, &Things[n].arg3, 1 ); >+ WriteBytes (file, &Things[n].arg4, 1 ); >+ WriteBytes (file, &Things[n].arg5, 1 ); >+ } >+ else >+ { >+ file_write_i16 (file, Things[n].xpos ); >+ file_write_i16 (file, Things[n].ypos ); >+ file_write_i16 (file, Things[n].angle); >+ file_write_i16 (file, Things[n].type ); >+ file_write_i16 (file, Things[n].when ); >+ } > } > lump_size[l] = ftell (file) - lump_offset[l]; > if (Level) >@@ -1083,13 +1154,32 @@ > ObjectsNeeded (OBJ_LINEDEFS, 0); > for (n = 0; n < NumLineDefs; n++) > { >- file_write_i16 (file, LineDefs[n].start ); >- file_write_i16 (file, LineDefs[n].end ); >- file_write_i16 (file, LineDefs[n].flags ); >- file_write_i16 (file, LineDefs[n].type ); >- file_write_i16 (file, LineDefs[n].tag ); >- file_write_i16 (file, LineDefs[n].sidedef1); >- file_write_i16 (file, LineDefs[n].sidedef2); >+ if (yg_level_format == YGLF_HEXEN) >+ { >+ u8 dummy[6]; >+ dummy[0] = LineDefs[n].type; >+ dummy[1] = LineDefs[n].tag; >+ dummy[2] = LineDefs[n].arg2; >+ dummy[3] = LineDefs[n].arg3; >+ dummy[4] = LineDefs[n].arg4; >+ dummy[5] = LineDefs[n].arg5; >+ file_write_i16 (file, LineDefs[n].start ); >+ file_write_i16 (file, LineDefs[n].end ); >+ file_write_i16 (file, LineDefs[n].flags ); >+ WriteBytes (file, dummy, 6); >+ file_write_i16 (file, LineDefs[n].sidedef1); >+ file_write_i16 (file, LineDefs[n].sidedef2); >+ } >+ else >+ { >+ file_write_i16 (file, LineDefs[n].start ); >+ file_write_i16 (file, LineDefs[n].end ); >+ file_write_i16 (file, LineDefs[n].flags ); >+ file_write_i16 (file, LineDefs[n].type ); >+ file_write_i16 (file, LineDefs[n].tag ); >+ file_write_i16 (file, LineDefs[n].sidedef1); >+ file_write_i16 (file, LineDefs[n].sidedef2); >+ } > } > lump_size[l] = ftell (file) - lump_offset[l]; > if (Level) >@@ -1221,9 +1311,21 @@ > if (Level) > dir = dir->next; > >+ >+// Write the BEHAVIOR lump >+if (yg_level_format == YGLF_HEXEN) >+{ >+ l = WAD_LL_BEHAVIOR; >+ lump_offset[l] = ftell (file); >+ WriteBytes(file, Behavior, BehaviorSize); >+ lump_size[l] = BehaviorSize; >+ if (Level) >+ dir = dir->next; >+} >+ > // Write the actual directory > long dir_offset = ftell (file); >-for (int L = 0; L < (int) WAD_LL__; L++) >+for (int L = 0; L < (int) NumLumps; L++) > { > file_write_i32 (file, lump_offset[L]); > file_write_i32 (file, lump_size[L]); >@@ -1387,7 +1489,7 @@ > } > NumWTexture = (int) val + 1; > /* read in the offsets for texture1 names */ >- offsets = (i32 *) GetMemory ((long) NumWTexture * 4); >+ offsets = (i32 *) GetMemory ((long) NumWTexture * (sizeof(i32))); > wf->read_i32 (offsets + 1, NumWTexture - 1); > if (wf->error ()) > { >@@ -1445,7 +1547,7 @@ > } > NumWTexture = (int) val + 1; > /* read in the offsets for texture1 names */ >- offsets = (i32 *) GetMemory ((long) NumWTexture * 4); >+ offsets = (i32 *) GetMemory ((long) NumWTexture * sizeof(i32)); > wf->read_i32 (offsets + 1, NumWTexture - 1); > { > // FIXME >@@ -1489,7 +1591,7 @@ > // FIXME > } > /* read in the offsets for texture2 names */ >- offsets = (i32 *) GetMemory ((long) val * 4); >+ offsets = (i32 *) GetMemory ((long) val * sizeof(i32)); > wf->read_i32 (offsets, val); > if (wf->error ()) > { >diff -Nru yadex-1.7.0-orig/src/levels.cc.orig yadex-1.7.0/src/levels.cc.orig >--- yadex-1.7.0-orig/src/levels.cc.orig 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/levels.cc.orig 2012-06-17 18:47:12.486693175 -0400 >@@ -0,0 +1,1811 @@ >+/* >+ * levels.cc >+ * Level loading and saving routines, >+ * global variables used to hold the level data. >+ * BW & RQ sometime in 1993 or 1994. >+ */ >+ >+ >+/* >+This file is part of Yadex. >+ >+Yadex incorporates code from DEU 5.21 that was put in the public domain in >+1994 by Raphaël Quinet and Brendon Wyber. >+ >+The rest of Yadex is Copyright © 1997-2003 André Majorel and others. >+ >+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. >+*/ >+ >+ >+#include "yadex.h" >+#include "bitvec.h" >+#include "dialog.h" >+#include "game.h" >+#include "levels.h" >+#include "objid.h" >+#include "wstructs.h" >+#include "things.h" >+#include "wadfile.h" >+#include "wads.h" >+#include "wads2.h" >+ >+ >+/* >+ FIXME >+ All these variables should be turned >+ into members of a "Level" class. >+*/ >+MDirPtr Level; /* master dictionary entry for the level */ >+int NumThings; /* number of things */ >+TPtr Things; /* things data */ >+int NumLineDefs; /* number of line defs */ >+LDPtr LineDefs; /* line defs data */ >+int NumSideDefs; /* number of side defs */ >+SDPtr SideDefs; /* side defs data */ >+int NumVertices; /* number of vertexes */ >+VPtr Vertices; /* vertex data */ >+int NumSectors; /* number of sectors */ >+SPtr Sectors; /* sectors data */ >+u8* Behavior; >+int BehaviorSize; >+ >+// FIXME should be somewhere else >+int NumWTexture; /* number of wall textures */ >+char **WTexture; /* array of wall texture names */ >+ >+// FIXME all the flat list stuff should be put in a separate class >+size_t NumFTexture; /* number of floor/ceiling textures */ >+flat_list_entry_t *flat_list; // List of all flats in the directory >+ >+int MapMaxX = -32767; /* maximum X value of map */ >+int MapMaxY = -32767; /* maximum Y value of map */ >+int MapMinX = 32767; /* minimum X value of map */ >+int MapMinY = 32767; /* minimum Y value of map */ >+bool MadeChanges; /* made changes? */ >+bool MadeMapChanges; /* made changes that need rebuilding? */ >+unsigned long things_angles; // See levels.h for description. >+unsigned long things_types; // See levels.h for description. >+char Level_name[WAD_NAME + 1]; /* The name of the level (E.G. >+ "MAP01" or "E1M1"), followed by a >+ NUL. If the Level has been created as >+ the result of a "c" command with no >+ argument, an empty string. The name >+ is not necesarily in upper case but >+ it always a valid lump name, not a >+ command line shortcut like "17". */ >+ >+y_file_name_t Level_file_name; /* The name of the file in which >+ the level would be saved. If the >+ level has been created as the result >+ of a "c" command, with or without >+ argument, an empty string. */ >+ >+y_file_name_t Level_file_name_saved; /* The name of the file in >+ which the level was last saved. If >+ the Level has never been saved yet, >+ an empty string. */ >+ >+static u8 DefaultBehavior[16] = { >+ 'A', 'C', 'S', 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 >+}; >+ >+void EmptyLevelData (const char *levelname) >+{ >+Things = 0; >+NumThings = 0; >+things_angles++; >+things_types++; >+LineDefs = 0; >+NumLineDefs = 0; >+SideDefs = 0; >+NumSideDefs = 0; >+Sectors = 0; >+NumSectors = 0; >+Vertices = 0; >+NumVertices = 0; >+if (yg_level_format == YGLF_HEXEN) >+ { >+ BehaviorSize = sizeof(DefaultBehavior); >+ Behavior = (u8*) GetFarMemory ((unsigned long) BehaviorSize ); >+ memcpy(Behavior, DefaultBehavior, BehaviorSize); >+ } >+} >+ >+ >+/* >+ * texno_texname >+ * A convenience function when loading Doom alpha levels >+ */ >+static char *tex_list = 0; >+static size_t ntex = 0; >+static char tex_name[WAD_TEX_NAME + 1]; >+inline const char *texno_texname (i16 texno) >+{ >+if (texno < 0) >+ return "-"; >+else >+ if (yg_texture_format == YGTF_NAMELESS) >+ { >+ sprintf (tex_name, "TEX%04u", (unsigned) texno); >+ return tex_name; >+ } >+ else >+ { >+ if (texno < (i16) ntex) >+ return tex_list + WAD_TEX_NAME * texno; >+ else >+ return "unknown"; >+ } >+} >+ >+ >+/* >+ read in the level data >+*/ >+ >+int ReadLevelData (const char *levelname) /* SWAP! */ >+{ >+int rc = 0; >+MDirPtr dir; >+int OldNumVertices; >+ >+/* No objects are needed: they may be swapped after they have been read */ >+ObjectsNeeded (0); >+ >+/* Find the various level information from the master directory */ >+DisplayMessage (-1, -1, "Reading data for level %s...", levelname); >+Level = FindMasterDir (MasterDir, levelname); >+if (!Level) >+ fatal_error ("level data not found"); >+ >+/* Get the number of vertices */ >+i32 v_offset = 42; >+i32 v_length = 42; >+{ >+const char *lump_name = "BUG"; >+if (yg_level_format == YGLF_ALPHA) // Doom alpha >+ lump_name = "POINTS"; >+else >+ lump_name = "VERTEXES"; >+dir = FindMasterDir (Level, lump_name); >+if (dir == 0) >+ OldNumVertices = 0; >+else >+ { >+ v_offset = dir->dir.start; >+ v_length = dir->dir.size; >+ if (yg_level_format == YGLF_ALPHA) // Doom alpha: skip leading count >+ { >+ v_offset += 4; >+ v_length -= 4; >+ } >+ OldNumVertices = (int) (v_length / WAD_VERTEX_BYTES); >+ if ((i32) (OldNumVertices * WAD_VERTEX_BYTES) != v_length) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+} >+ >+// Read THINGS >+{ >+const char *lump_name = "THINGS"; >+verbmsg ("Reading %s things", levelname); >+i32 offset = 42; >+i32 length; >+dir = FindMasterDir (Level, lump_name); >+if (dir == 0) >+ NumThings = 0; >+else >+ { >+ offset = dir->dir.start; >+ length = dir->dir.size; >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode >+ { >+ NumThings = (int) (length / WAD_HEXEN_THING_BYTES); >+ if ((i32) (NumThings * WAD_HEXEN_THING_BYTES) != length) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+ else // Doom/Heretic/Strife mode >+ { >+ if (yg_level_format == YGLF_ALPHA) // Doom alpha: skip leading count >+ { >+ offset += 4; >+ length -= 4; >+ } >+ size_t thing_size = yg_level_format == YGLF_ALPHA ? 12 : WAD_THING_BYTES; >+ NumThings = (int) (length / thing_size); >+ if ((i32) (NumThings * thing_size) != length) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+ } >+things_angles++; >+things_types++; >+if (NumThings > 0) >+ { >+ Things = (TPtr) GetFarMemory ((unsigned long) NumThings >+ * sizeof (struct Thing)); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (offset); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode >+ for (long n = 0; n < NumThings; n++) >+ { >+ u8 dummy2[6]; >+ wf->read_i16 (&Things[n].tid ); >+ wf->read_i16 (&Things[n].xpos ); >+ wf->read_i16 (&Things[n].ypos ); >+ wf->read_i16 (&Things[n].height); >+ wf->read_i16 (&Things[n].angle); >+ wf->read_i16 (&Things[n].type ); >+ wf->read_i16 (&Things[n].when ); >+ wf->read_u8 (Things[n].special); >+ wf->read_u8 (Things[n].arg1 ); >+ wf->read_u8 (Things[n].arg2 ); >+ wf->read_u8 (Things[n].arg3 ); >+ wf->read_u8 (Things[n].arg4 ); >+ wf->read_u8 (Things[n].arg5 ); >+ if (wf->error ()) >+ { >+ err ("%s: error reading thing #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ else // Doom/Heretic/Strife mode >+ for (long n = 0; n < NumThings; n++) >+ { >+ wf->read_i16 (&Things[n].xpos ); >+ wf->read_i16 (&Things[n].ypos ); >+ wf->read_i16 (&Things[n].angle); >+ wf->read_i16 (&Things[n].type ); >+ if (yg_level_format == YGLF_ALPHA) >+ wf->read_i16 (); // Alpha. Don't know what it's for. >+ wf->read_i16 (&Things[n].when ); >+ if (wf->error ()) >+ { >+ err ("%s: error reading thing #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+} >+ >+// Read LINEDEFS >+if (yg_level_format != YGLF_ALPHA) >+ { >+ const char *lump_name = "LINEDEFS"; >+ verbmsg (" linedefs"); >+ dir = FindMasterDir (Level, lump_name); >+ if (dir == 0) >+ NumLineDefs = 0; >+ else >+ { >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode >+ { >+ NumLineDefs = (int) (dir->dir.size / WAD_HEXEN_LINEDEF_BYTES); >+ if ((i32) (NumLineDefs * WAD_HEXEN_LINEDEF_BYTES) != dir->dir.size) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+ else // Doom/Heretic/Strife mode >+ { >+ NumLineDefs = (int) (dir->dir.size / WAD_LINEDEF_BYTES); >+ if ((i32) (NumLineDefs * WAD_LINEDEF_BYTES) != dir->dir.size) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+ } >+ if (NumLineDefs > 0) >+ { >+ LineDefs = (LDPtr) GetFarMemory ((unsigned long) NumLineDefs >+ * sizeof (struct LineDef)); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ if (yg_level_format == YGLF_HEXEN) // Hexen mode >+ for (long n = 0; n < NumLineDefs; n++) >+ { >+ u8 dummy[6]; >+ wf->read_i16 (&LineDefs[n].start); >+ wf->read_i16 (&LineDefs[n].end); >+ wf->read_i16 (&LineDefs[n].flags); >+ wf->read_bytes (dummy, sizeof dummy); >+ wf->read_i16 (&LineDefs[n].sidedef1); >+ wf->read_i16 (&LineDefs[n].sidedef2); >+ LineDefs[n].type = dummy[0]; >+ LineDefs[n].tag = dummy[1]; // arg1 often contains a tag >+ LineDefs[n].arg2 = dummy[2]; >+ LineDefs[n].arg3 = dummy[3]; >+ LineDefs[n].arg4 = dummy[4]; >+ LineDefs[n].arg5 = dummy[5]; >+ if (wf->error ()) >+ { >+ err ("%s: error reading linedef #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ else // Doom/Heretic/Strife mode >+ for (long n = 0; n < NumLineDefs; n++) >+ { >+ wf->read_i16 (&LineDefs[n].start); >+ wf->read_i16 (&LineDefs[n].end); >+ wf->read_i16 (&LineDefs[n].flags); >+ wf->read_i16 (&LineDefs[n].type); >+ wf->read_i16 (&LineDefs[n].tag); >+ wf->read_i16 (&LineDefs[n].sidedef1); >+ wf->read_i16 (&LineDefs[n].sidedef2); >+ if (wf->error ()) >+ { >+ err ("%s: error reading linedef #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+ } >+ >+// Read SIDEDEFS >+{ >+const char *lump_name = "SIDEDEFS"; >+verbmsg (" sidedefs"); >+dir = FindMasterDir (Level, lump_name); >+if (dir) >+ { >+ NumSideDefs = (int) (dir->dir.size / WAD_SIDEDEF_BYTES); >+ if ((i32) (NumSideDefs * WAD_SIDEDEF_BYTES) != dir->dir.size) >+ warn ("the SIDEDEFS lump has a weird size." >+ " The wad might be corrupt.\n"); >+ } >+else >+ NumSideDefs = 0; >+if (NumSideDefs > 0) >+ { >+ SideDefs = (SDPtr) GetFarMemory ((unsigned long) NumSideDefs >+ * sizeof (struct SideDef)); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ for (long n = 0; n < NumSideDefs; n++) >+ { >+ wf->read_i16 (&SideDefs[n].xoff); >+ wf->read_i16 (&SideDefs[n].yoff); >+ wf->read_bytes (&SideDefs[n].tex1, WAD_TEX_NAME); >+ wf->read_bytes (&SideDefs[n].tex2, WAD_TEX_NAME); >+ wf->read_bytes (&SideDefs[n].tex3, WAD_TEX_NAME); >+ wf->read_i16 (&SideDefs[n].sector); >+ if (wf->error ()) >+ { >+ err ("%s: error reading sidedef #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+} >+ >+/* Sanity checkings on linedefs: the 1st and 2nd vertices >+ must exist. The 1st and 2nd sidedefs must exist or be >+ set to -1. */ >+for (long n = 0; n < NumLineDefs; n++) >+ { >+ if (LineDefs[n].sidedef1 != -1 >+ && outside (LineDefs[n].sidedef1, 0, NumSideDefs - 1)) >+ { >+ err ("linedef %ld has bad 1st sidedef number %d, giving up", >+ n, LineDefs[n].sidedef1); >+ rc = 1; >+ goto byebye; >+ } >+ if (LineDefs[n].sidedef2 != -1 >+ && outside (LineDefs[n].sidedef2, 0, NumSideDefs - 1)) >+ { >+ err ("linedef %ld has bad 2nd sidedef number %d, giving up", >+ n, LineDefs[n].sidedef2); >+ rc = 1; >+ goto byebye; >+ } >+ if (outside (LineDefs[n].start, 0, OldNumVertices -1)) >+ { >+ err ("linedef %ld has bad 1st vertex number %d, giving up", >+ n, LineDefs[n].start); >+ rc = 1; >+ goto byebye; >+ } >+ if (outside (LineDefs[n].end, 0, OldNumVertices - 1)) >+ { >+ err ("linedef %ld has bad 2nd vertex number %d, giving up", >+ n, LineDefs[n].end); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ >+// Read LINES (Doom alpha only) >+if (yg_level_format == YGLF_ALPHA) >+ { >+ const char *lump_name = "LINES"; >+ verbmsg (" lines"); >+ dir = FindMasterDir (Level, lump_name); >+ if (dir) >+ { >+ if ((dir->dir.size - 4) % 36) >+ warn ("the %s lump has a weird size. The wad might be corrupt.\n", >+ lump_name); >+ const size_t nlines = dir->dir.size / 36; >+ NumLineDefs = nlines; >+ NumSideDefs = 2 * nlines; // Worst case. We'll adjust later. >+ LineDefs = (LDPtr) GetFarMemory ((unsigned long) NumLineDefs >+ * sizeof (struct LineDef)); >+ SideDefs = (SDPtr) GetFarMemory ((unsigned long) NumSideDefs >+ * sizeof (struct SideDef)); >+ // Read TEXTURES >+ if (yg_texture_format != YGTF_NAMELESS) >+ { >+ const char *lump_name = "TEXTURES"; >+ bool success = false; >+ ntex = 0; >+ i32 *offset_table = 0; >+ MDirPtr d = FindMasterDir (MasterDir, lump_name); >+ if (! d) >+ { >+ warn ("%s: lump not found in directory\n", lump_name); >+ goto textures_done; >+ } >+ { >+ const Wad_file *wf = d->wadfile; >+ wf->seek (d->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ goto textures_done; >+ } >+ i32 num; >+ wf->read_i32 (&num); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading texture count\n", lump_name); >+ } >+ if (num < 0 || num > 32767) >+ { >+ warn ("%s: bad texture count, giving up\n", lump_name); >+ goto textures_done; >+ } >+ ntex = num; >+ offset_table = new i32[ntex]; >+ for (size_t n = 0; n < ntex; n++) >+ { >+ wf->read_i32 (offset_table + n); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading offsets table\n"); >+ goto textures_done; >+ } >+ } >+ tex_list = (char *) GetMemory (ntex * WAD_TEX_NAME); >+ for (size_t n = 0; n < ntex; n++) >+ { >+ const long offset = d->dir.start + offset_table[n]; >+ wf->seek (offset); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ goto textures_done; >+ } >+ wf->read_bytes (tex_list + WAD_TEX_NAME * n, WAD_TEX_NAME); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading texture names\n", lump_name); >+ goto textures_done; >+ } >+ } >+ success = true; >+ } >+ >+ textures_done: >+ if (offset_table != 0) >+ delete[] offset_table; >+ if (! success) >+ warn ("%s: errors found, won't be able to import texture names\n", >+ lump_name); >+ } >+ >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start + 4); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ size_t s = 0; >+ for (size_t n = 0; n < nlines; n++) >+ { >+ LDPtr ld = LineDefs + n; >+ ld->start = wf->read_i16 (); >+ ld->end = wf->read_i16 (); >+ ld->flags = wf->read_i16 (); >+ wf->read_i16 (); // Unused ? >+ ld->type = wf->read_i16 (); >+ ld->tag = wf->read_i16 (); >+ wf->read_i16 (); // Unused ? >+ i16 sector1 = wf->read_i16 (); >+ i16 xofs1 = wf->read_i16 (); >+ i16 tex1m = wf->read_i16 (); >+ i16 tex1u = wf->read_i16 (); >+ i16 tex1l = wf->read_i16 (); >+ wf->read_i16 (); // Unused ? >+ i16 sector2 = wf->read_i16 (); >+ i16 xofs2 = wf->read_i16 (); >+ i16 tex2m = wf->read_i16 (); >+ i16 tex2u = wf->read_i16 (); >+ i16 tex2l = wf->read_i16 (); >+ if (sector1 >= 0) // Create first sidedef >+ { >+ ld->sidedef1 = s; >+ SDPtr sd = SideDefs + s; >+ sd->xoff = xofs1; >+ sd->yoff = 0; >+ memcpy (sd->tex1, texno_texname (tex1u), sizeof sd->tex1); >+ memcpy (sd->tex2, texno_texname (tex1l), sizeof sd->tex2); >+ memcpy (sd->tex3, texno_texname (tex1m), sizeof sd->tex3); >+ sd->sector = sector1; >+ s++; >+ } >+ else // No first sidedef ! >+ ld->sidedef1 = -1; >+ if (ld->flags & 0x04) // Create second sidedef >+ { >+ ld->sidedef2 = s; >+ SDPtr sd = SideDefs + s; >+ sd->xoff = xofs2; >+ sd->yoff = 0; >+ memcpy (sd->tex1, texno_texname (tex2u), sizeof sd->tex1); >+ memcpy (sd->tex2, texno_texname (tex2l), sizeof sd->tex2); >+ memcpy (sd->tex3, texno_texname (tex2m), sizeof sd->tex3); >+ sd->sector = sector2; >+ s++; >+ } >+ else >+ ld->sidedef2 = -1; >+ if (wf->error ()) >+ { >+ err ("%s: error reading line #%d", lump_name, int (n)); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ // (size_t) to silence GCC warning >+ if ((size_t) NumSideDefs > s) // Almost always true. >+ { >+ NumSideDefs = s; >+ SideDefs = (SDPtr) ResizeFarMemory (SideDefs, >+ (unsigned long) NumSideDefs * sizeof (struct SideDef)); >+ } >+ if (tex_list) >+ FreeMemory (tex_list); >+ tex_list = 0; >+ ntex = 0; >+ } >+ } >+ >+/* Read the vertices. If the wad has been run through a nodes >+ builder, there is a bunch of vertices at the end that are not >+ used by any linedefs. Those vertices have been created by the >+ nodes builder for the segs. We ignore them, because they're >+ useless to the level designer. However, we do NOT ignore >+ unused vertices in the middle because that's where the >+ "string art" bug came from. >+ >+ Note that there is absolutely no guarantee that the nodes >+ builders add their own vertices at the end, instead of at the >+ beginning or right in the middle, AFAIK. It's just that they >+ all seem to do that (1). What if some don't ? Well, we would >+ end up with many unwanted vertices in the level data. Nothing >+ that a good CheckCrossReferences() couldn't take care of. */ >+{ >+verbmsg (" vertices"); >+int last_used_vertex = -1; >+for (long n = 0; n < NumLineDefs; n++) >+ { >+ last_used_vertex = y_max (last_used_vertex, LineDefs[n].start); >+ last_used_vertex = y_max (last_used_vertex, LineDefs[n].end); >+ } >+NumVertices = last_used_vertex + 1; >+// This block is only here to warn me if (1) is false. >+{ >+ bitvec_c vertex_used (OldNumVertices); >+ for (long n = 0; n < NumLineDefs; n++) >+ { >+ vertex_used.set (LineDefs[n].start); >+ vertex_used.set (LineDefs[n].end); >+ } >+ int unused = 0; >+ for (long n = 0; n <= last_used_vertex; n++) >+ { >+ if (! vertex_used.get (n)) >+ unused++; >+ } >+ if (unused > 0) >+ { >+ warn ("this level has unused vertices in the middle.\n"); >+ warn ("total %d, tail %d (%d%%), unused %d (", >+ OldNumVertices, >+ OldNumVertices - NumVertices, >+ NumVertices - unused >+ ? 100 * (OldNumVertices - NumVertices) / (NumVertices - unused) >+ : 0, >+ unused); >+ int first = 1; >+ for (int n = 0; n <= last_used_vertex; n++) >+ { >+ if (! vertex_used.get (n)) >+ { >+ if (n == 0 || vertex_used.get (n - 1)) >+ { >+ if (first) >+ first = 0; >+ else >+ warn (", "); >+ warn ("%d", n); >+ } >+ else if (n == last_used_vertex || vertex_used.get (n + 1)) >+ warn ("-%d", n); >+ } >+ } >+ warn (")\n"); >+ } >+} >+// Now load all the vertices except the unused ones at the end. >+if (NumVertices > 0) >+ { >+ const char *lump_name = "BUG"; >+ Vertices = (VPtr) GetFarMemory ((unsigned long) NumVertices >+ * sizeof (struct Vertex)); >+ if (yg_level_format == YGLF_ALPHA) // Doom alpha >+ lump_name = "POINTS"; >+ else >+ lump_name = "VERTEXES"; >+ dir = FindMasterDir (Level, lump_name); >+ if (dir == 0) >+ goto vertexes_done; // FIXME isn't that fatal ? >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (v_offset); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ MapMaxX = -32767; >+ MapMaxY = -32767; >+ MapMinX = 32767; >+ MapMinY = 32767; >+ for (long n = 0; n < NumVertices; n++) >+ { >+ i16 val; >+ wf->read_i16 (&val); >+ if (val < MapMinX) >+ MapMinX = val; >+ if (val > MapMaxX) >+ MapMaxX = val; >+ Vertices[n].x = val; >+ wf->read_i16 (&val); >+ if (val < MapMinY) >+ MapMinY = val; >+ if (val > MapMaxY) >+ MapMaxY = val; >+ Vertices[n].y = val; >+ if (wf->error ()) >+ { >+ err ("%s: error reading vertex #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+ vertexes_done: >+ ; >+ } >+} >+ >+// Ignore SEGS, SSECTORS and NODES >+ >+// Read SECTORS >+{ >+const char *lump_name = "SECTORS"; >+verbmsg (" sectors\n"); >+dir = FindMasterDir (Level, lump_name); >+if (yg_level_format != YGLF_ALPHA) >+ { >+ if (dir) >+ { >+ NumSectors = (int) (dir->dir.size / WAD_SECTOR_BYTES); >+ if ((i32) (NumSectors * WAD_SECTOR_BYTES) != dir->dir.size) >+ warn ("the %s lump has a weird size." >+ " The wad might be corrupt.\n", lump_name); >+ } >+ else >+ NumSectors = 0; >+ if (NumSectors > 0) >+ { >+ Sectors = (SPtr) GetFarMemory ((unsigned long) NumSectors >+ * sizeof (struct Sector)); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ for (long n = 0; n < NumSectors; n++) >+ { >+ wf->read_i16 (&Sectors[n].floorh); >+ wf->read_i16 (&Sectors[n].ceilh); >+ wf->read_bytes (&Sectors[n].floort, WAD_FLAT_NAME); >+ wf->read_bytes (&Sectors[n].ceilt, WAD_FLAT_NAME); >+ wf->read_i16 (&Sectors[n].light); >+ wf->read_i16 (&Sectors[n].special); >+ wf->read_i16 (&Sectors[n].tag); >+ if (wf->error ()) >+ { >+ err ("%s: error reading sector #%ld", lump_name, n); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+ } >+else // Doom alpha--a wholly different SECTORS format >+ { >+ i32 *offset_table = 0; >+ i32 nsectors = 0; >+ i32 nflatnames = 0; >+ char *flatnames = 0; >+ if (dir == 0) >+ { >+ warn ("%s: lump not found in directory\n", lump_name); // FIXME fatal ? >+ goto sectors_alpha_done; >+ } >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ wf->read_i32 (&nsectors); >+ if (wf->error ()) >+ { >+ err ("%s: error reading sector count", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ if (nsectors < 0) >+ { >+ warn ("Negative sector count. Clamping to 0.\n"); >+ nsectors = 0; >+ } >+ NumSectors = nsectors; >+ Sectors = (SPtr) GetFarMemory ((unsigned long) NumSectors >+ * sizeof (struct Sector)); >+ offset_table = new i32[nsectors]; >+ for (size_t n = 0; n < (size_t) nsectors; n++) >+ wf->read_i32 (offset_table + n); >+ if (wf->error ()) >+ { >+ err ("%s: error reading offsets table", lump_name); >+ rc = 1; >+ goto sectors_alpha_done; >+ } >+ // Load FLATNAME >+ { >+ const char *lump_name = "FLATNAME"; >+ bool success = false; >+ MDirPtr dir2 = FindMasterDir (Level, lump_name); >+ if (dir2 == 0) >+ { >+ warn ("%s: lump not found in directory\n", lump_name); >+ goto flatname_done; // FIXME warn ? >+ } >+ { >+ const Wad_file *wf = dir2->wadfile; >+ wf->seek (dir2->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ goto flatname_done; >+ } >+ wf->read_i32 (&nflatnames); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading flat name count\n", lump_name); >+ nflatnames = 0; >+ goto flatname_done; >+ } >+ if (nflatnames < 0 || nflatnames > 32767) >+ { >+ warn ("%s: bad flat name count, giving up\n", lump_name); >+ nflatnames = 0; >+ goto flatname_done; >+ } >+ else >+ { >+ flatnames = new char[WAD_FLAT_NAME * nflatnames]; >+ wf->read_bytes (flatnames, WAD_FLAT_NAME * nflatnames); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading flat names\n", lump_name); >+ nflatnames = 0; >+ goto flatname_done; >+ } >+ success = true; >+ } >+ } >+ flatname_done: >+ if (! success) >+ warn ("%s: errors found, you'll have to do without flat names\n", >+ lump_name); >+ } >+ for (size_t n = 0; n < (size_t) nsectors; n++) >+ { >+ wf->seek (dir->dir.start + offset_table[n]); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto sectors_alpha_done; >+ } >+ i16 index; >+ wf->read_i16 (&Sectors[n].floorh); >+ wf->read_i16 (&Sectors[n].ceilh ); >+ wf->read_i16 (&index); >+ if (nflatnames && flatnames && index >= 0 && index < nflatnames) >+ memcpy (Sectors[n].floort, flatnames + WAD_FLAT_NAME * index, >+ WAD_FLAT_NAME); >+ else >+ strcpy (Sectors[n].floort, "unknown"); >+ wf->read_i16 (&index); >+ if (nflatnames && flatnames && index >= 0 && index < nflatnames) >+ memcpy (Sectors[n].ceilt, flatnames + WAD_FLAT_NAME * index, >+ WAD_FLAT_NAME); >+ else >+ strcpy (Sectors[n].ceilt, "unknown"); >+ wf->read_i16 (&Sectors[n].light); >+ wf->read_i16 (&Sectors[n].special); >+ wf->read_i16 (&Sectors[n].tag); >+ // Don't know what the tail is for. Ignore it. >+ if (wf->error ()) >+ { >+ err ("%s: error reading sector #%ld", lump_name, long (n)); >+ rc = 1; >+ goto sectors_alpha_done; >+ } >+ } >+ } >+ >+ sectors_alpha_done: >+ if (offset_table != 0) >+ delete[] offset_table; >+ if (flatnames != 0) >+ delete[] flatnames; >+ if (rc != 0) >+ goto byebye; >+ } >+} >+ >+// Read BEHAVIOR >+if (yg_level_format == YGLF_HEXEN) >+{ >+const char *lump_name = "BEHAVIOR"; >+verbmsg (" behavior\n"); >+dir = FindMasterDir (Level, lump_name); >+if (dir) >+ { >+ BehaviorSize = (int)dir->dir.size; >+ if (BehaviorSize > 0) >+ { >+ Behavior = (u8*) GetFarMemory ((unsigned long) BehaviorSize ); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ err ("%s: seek error", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ wf->read_bytes (Behavior, BehaviorSize); >+ if (wf->error ()) >+ { >+ err ("%s: error behavior lump", lump_name); >+ rc = 1; >+ goto byebye; >+ } >+ } >+ } >+} >+ >+/* Sanity checking on sidedefs: the sector must exist. I don't >+ make this a fatal error, though, because it's not exceptional >+ to find wads with unused sidedefs with a sector# of -1. Well >+ known ones include dyst3 (MAP06, MAP07, MAP08), mm (MAP16), >+ mm2 (MAP13, MAP28) and requiem (MAP03, MAP08, ...). */ >+for (long n = 0; n < NumSideDefs; n++) >+ { >+ if (outside (SideDefs[n].sector, 0, NumSectors - 1)) >+ warn ("sidedef %ld has bad sector number %d\n", >+ n, SideDefs[n].sector); >+ } >+ >+// Ignore REJECT and BLOCKMAP >+ >+// Silly statistics >+verbmsg (" %d things, %d vertices, %d linedefs, %d sidedefs, %d sectors\n", >+ (int) NumThings, (int) NumVertices, (int) NumLineDefs, >+ (int) NumSideDefs, (int) NumSectors); >+verbmsg (" Map: (%d,%d)-(%d,%d)\n", MapMinX, MapMinY, MapMaxX, MapMaxY); >+ >+byebye: >+if (rc != 0) >+ err ("%s: errors found, giving up", levelname); >+return rc; >+} >+ >+ >+ >+/* >+ forget the level data >+*/ >+ >+void ForgetLevelData () /* SWAP! */ >+{ >+/* forget the things */ >+ObjectsNeeded (OBJ_THINGS, 0); >+NumThings = 0; >+if (Things != 0) >+ FreeFarMemory (Things); >+Things = 0; >+things_angles++; >+things_types++; >+ >+/* forget the vertices */ >+ObjectsNeeded (OBJ_VERTICES, 0); >+NumVertices = 0; >+if (Vertices != 0) >+ FreeFarMemory (Vertices); >+Vertices = 0; >+ >+/* forget the linedefs */ >+ObjectsNeeded (OBJ_LINEDEFS, 0); >+NumLineDefs = 0; >+if (LineDefs != 0) >+ FreeFarMemory (LineDefs); >+LineDefs = 0; >+ >+/* forget the sidedefs */ >+ObjectsNeeded (OBJ_SIDEDEFS, 0); >+NumSideDefs = 0; >+if (SideDefs != 0) >+ FreeFarMemory (SideDefs); >+SideDefs = 0; >+ >+/* forget the sectors */ >+ObjectsNeeded (OBJ_SECTORS, 0); >+NumSectors = 0; >+if (Sectors != 0) >+ FreeFarMemory (Sectors); >+Sectors = 0; >+ObjectsNeeded (0); >+} >+ >+ >+/* >+ * Save the level data to a pwad file >+ * The name of the level is always obtained from >+ * <level_name>, whether or not the level was created from >+ * scratch. >+ * >+ * The previous contents of the pwad file are lost. Yes, it >+ * sucks but it's not easy to fix. >+ * >+ * The lumps are always written in the same order, the same >+ * as the one in the Doom iwad. The length field of the >+ * marker lump is always set to 0. Its offset field is >+ * always set to the offset of the first lump of the level >+ * (THINGS). >+ * >+ * If the level has been created by editing an existing >+ * level and has not been changed in a way that calls for a >+ * rebuild of the nodes, the VERTEXES, SEGS, SSECTORS, >+ * NODES, REJECT and BLOCKMAP lumps are copied from the >+ * original level. Otherwise, they are created with a >+ * length of 0 bytes and an offset equal to the offset of >+ * the previous lump plus its length. >+ * >+ * Returns 0 on success and non-zero on failure (see errno). >+ */ >+int SaveLevelData (const char *outfile, const char *level_name) /* SWAP! */ >+{ >+FILE *file; >+MDirPtr dir; >+int n; >+long lump_offset[WAD_LL__MAX]; >+size_t lump_size[WAD_LL__MAX]; >+wad_level_lump_no_t l; >+ >+if (! level_name || ! levelname2levelno (level_name)) >+ { >+ nf_bug ("SaveLevelData: bad level_name \"%s\", using \"E1M1\" instead.", >+ level_name); >+ level_name = "E1M1"; >+ } >+DisplayMessage (-1, -1, "Saving data to \"%s\"...", outfile); >+LogMessage (": Saving data to \"%s\"...\n", outfile); >+if ((file = fopen (outfile, "wb")) == NULL) >+ { >+ char buf1[81]; >+ char buf2[81]; >+ y_snprintf (buf1, sizeof buf1, "Can't open \"%.64s\"", outfile); >+ y_snprintf (buf2, sizeof buf1, "for writing (%.64s)", strerror (errno)); >+ Notify (-1, -1, buf1, buf2); >+ return 1; >+ } >+ >+/* Can we reuse the old nodes ? Not if this is a new level from >+ scratch or if the structure of the level has changed. If the >+ level comes from an alpha version of Doom, we can't either >+ because that version of Doom didn't have SEGS, NODES, etc. */ >+bool reuse_nodes = Level >+ && ! MadeMapChanges >+ && yg_level_format != YGLF_ALPHA; >+ >+int NumLumps; >+if (yg_level_format == YGLF_HEXEN) >+ NumLumps = WAD_LL__HEXEN; >+else >+ NumLumps = WAD_LL__DOOM; >+ >+// Write the pwad header >+WriteBytes (file, "PWAD", 4); // Pwad file >+file_write_i32 (file, NumLumps); // Number of entries = 11 >+file_write_i32 (file, 0); // Fix this up later >+if (Level) >+ dir = Level->next; >+else >+ dir = 0; // Useless except to trap accidental dereferences >+ >+// The label (EnMm or MAPnm) >+l = WAD_LL_LABEL; >+lump_offset[l] = ftell (file); // By definition >+lump_size[l] = 0; // By definition >+ >+// Write the THINGS lump >+l = WAD_LL_THINGS; >+lump_offset[l] = ftell (file); >+ObjectsNeeded (OBJ_THINGS, 0); >+for (n = 0; n < NumThings; n++) >+ { >+ if (yg_level_format == YGLF_HEXEN) >+ { >+ file_write_i16 (file, Things[n].tid ); >+ file_write_i16 (file, Things[n].xpos ); >+ file_write_i16 (file, Things[n].ypos ); >+ file_write_i16 (file, Things[n].height); >+ file_write_i16 (file, Things[n].angle); >+ file_write_i16 (file, Things[n].type ); >+ file_write_i16 (file, Things[n].when ); >+ WriteBytes (file, &Things[n].special, 1); >+ WriteBytes (file, &Things[n].arg1, 1 ); >+ WriteBytes (file, &Things[n].arg2, 1 ); >+ WriteBytes (file, &Things[n].arg3, 1 ); >+ WriteBytes (file, &Things[n].arg4, 1 ); >+ WriteBytes (file, &Things[n].arg5, 1 ); >+ } >+ else >+ { >+ file_write_i16 (file, Things[n].xpos ); >+ file_write_i16 (file, Things[n].ypos ); >+ file_write_i16 (file, Things[n].angle); >+ file_write_i16 (file, Things[n].type ); >+ file_write_i16 (file, Things[n].when ); >+ } >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the LINEDEFS lump >+l = WAD_LL_LINEDEFS; >+lump_offset[WAD_LL_LINEDEFS] = ftell (file); >+ObjectsNeeded (OBJ_LINEDEFS, 0); >+for (n = 0; n < NumLineDefs; n++) >+ { >+ if (yg_level_format == YGLF_HEXEN) >+ { >+ u8 dummy[6]; >+ dummy[0] = LineDefs[n].type; >+ dummy[1] = LineDefs[n].tag; >+ dummy[2] = LineDefs[n].arg2; >+ dummy[3] = LineDefs[n].arg3; >+ dummy[4] = LineDefs[n].arg4; >+ dummy[5] = LineDefs[n].arg5; >+ file_write_i16 (file, LineDefs[n].start ); >+ file_write_i16 (file, LineDefs[n].end ); >+ file_write_i16 (file, LineDefs[n].flags ); >+ WriteBytes (file, dummy, 6); >+ file_write_i16 (file, LineDefs[n].sidedef1); >+ file_write_i16 (file, LineDefs[n].sidedef2); >+ } >+ else >+ { >+ file_write_i16 (file, LineDefs[n].start ); >+ file_write_i16 (file, LineDefs[n].end ); >+ file_write_i16 (file, LineDefs[n].flags ); >+ file_write_i16 (file, LineDefs[n].type ); >+ file_write_i16 (file, LineDefs[n].tag ); >+ file_write_i16 (file, LineDefs[n].sidedef1); >+ file_write_i16 (file, LineDefs[n].sidedef2); >+ } >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the SIDEDEFS lump >+l = WAD_LL_SIDEDEFS; >+lump_offset[l] = ftell (file); >+ObjectsNeeded (OBJ_SIDEDEFS, 0); >+for (n = 0; n < NumSideDefs; n++) >+ { >+ file_write_i16 (file, SideDefs[n].xoff); >+ file_write_i16 (file, SideDefs[n].yoff); >+ WriteBytes (file, &(SideDefs[n].tex1), WAD_TEX_NAME); >+ WriteBytes (file, &(SideDefs[n].tex2), WAD_TEX_NAME); >+ WriteBytes (file, &(SideDefs[n].tex3), WAD_TEX_NAME); >+ file_write_i16 (file, SideDefs[n].sector); >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the VERTEXES lump >+l = WAD_LL_VERTEXES; >+lump_offset[WAD_LL_VERTEXES] = ftell (file); >+if (reuse_nodes) >+ { >+ /* Copy the vertices */ >+ ObjectsNeeded (0); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", wad_level_lump[l]); >+ } >+ copy_bytes (file, wf->fp, dir->dir.size); >+ } >+else >+ { >+ /* Write the vertices */ >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ for (n = 0; n < NumVertices; n++) >+ { >+ file_write_i16 (file, Vertices[n].x); >+ file_write_i16 (file, Vertices[n].y); >+ } >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the SEGS, SSECTORS and NODES lumps >+for (n = 0; n < 3; n++) >+ { >+ if (n == 0) >+ l = WAD_LL_SEGS; >+ else if (n == 1) >+ l = WAD_LL_SSECTORS; >+ else if (n == 2) >+ l = WAD_LL_NODES; >+ lump_offset[l] = ftell (file); >+ if (reuse_nodes) >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", wad_level_lump[l]); >+ } >+ copy_bytes (file, wf->fp, dir->dir.size); >+ } >+ lump_size[l] = ftell (file) - lump_offset[l]; >+ if (Level) >+ dir = dir->next; >+ } >+ >+// Write the SECTORS lump >+l = WAD_LL_SECTORS; >+lump_offset[l] = ftell (file); >+ObjectsNeeded (OBJ_SECTORS, 0); >+for (n = 0; n < NumSectors; n++) >+ { >+ file_write_i16 (file, Sectors[n].floorh); >+ file_write_i16 (file, Sectors[n].ceilh ); >+ WriteBytes (file, Sectors[n].floort, WAD_FLAT_NAME); >+ WriteBytes (file, Sectors[n].ceilt, WAD_FLAT_NAME); >+ file_write_i16 (file, Sectors[n].light ); >+ file_write_i16 (file, Sectors[n].special); >+ file_write_i16 (file, Sectors[n].tag ); >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the REJECT lump >+l = WAD_LL_REJECT; >+lump_offset[l] = ftell (file); >+if (reuse_nodes) >+ { >+ /* Copy the REJECT data */ >+ ObjectsNeeded (0); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", wad_level_lump[l]); >+ } >+ copy_bytes (file, wf->fp, dir->dir.size); >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+// Write the BLOCKMAP lump >+l = WAD_LL_BLOCKMAP; >+lump_offset[l] = ftell (file); >+if (reuse_nodes) >+ { >+ ObjectsNeeded (0); >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", wad_level_lump[l]); >+ } >+ copy_bytes (file, wf->fp, dir->dir.size); >+ } >+lump_size[l] = ftell (file) - lump_offset[l]; >+if (Level) >+ dir = dir->next; >+ >+ >+// Write the BEHAVIOR lump >+if (yg_level_format == YGLF_HEXEN) >+{ >+ l = WAD_LL_BEHAVIOR; >+ lump_offset[l] = ftell (file); >+ WriteBytes(file, Behavior, BehaviorSize); >+ lump_size[l] = BehaviorSize; >+ if (Level) >+ dir = dir->next; >+} >+ >+// Write the actual directory >+long dir_offset = ftell (file); >+for (int L = 0; L < (int) NumLumps; L++) >+ { >+ file_write_i32 (file, lump_offset[L]); >+ file_write_i32 (file, lump_size[L]); >+ if (L == (int) WAD_LL_LABEL) >+ file_write_name (file, level_name); >+ else >+ file_write_name (file, wad_level_lump[L].name); >+ } >+ >+/* Fix up the directory start information */ >+if (fseek (file, 8, SEEK_SET)) >+ { >+ char buf1[81]; >+ char buf2[81]; >+ y_snprintf (buf1, sizeof buf1, "%.64s: seek error", outfile); >+ y_snprintf (buf2, sizeof buf2, "(%.64s)", strerror (errno)); >+ Notify (-1, -1, buf1, buf2); >+ fclose (file); >+ return 1; >+ } >+file_write_i32 (file, dir_offset); >+ >+/* Close the file */ >+if (fclose (file)) >+ { >+ char buf1[81]; >+ char buf2[81]; >+ y_snprintf (buf1, sizeof buf1, "%.64s: write error", outfile); >+ y_snprintf (buf2, sizeof buf2, "(%.64s)", strerror (errno)); >+ Notify (-1, -1, buf1, buf2); >+ return 1; >+ } >+ >+/* The file is now up to date */ >+if (! Level || MadeMapChanges) >+ remind_to_build_nodes = 1; >+MadeChanges = 0; >+MadeMapChanges = 0; >+ObjectsNeeded (0); >+ >+/* Update pointers in Master Directory */ >+OpenPatchWad (outfile); >+ >+/* This should free the old "*.bak" file */ >+CloseUnusedWadFiles (); >+ >+/* Update MapMinX, MapMinY, MapMaxX, MapMaxY */ >+// Probably not necessary anymore -- AYM 1999-04-05 >+ObjectsNeeded (OBJ_VERTICES, 0); >+update_level_bounds (); >+return 0; >+} >+ >+ >+/* >+ * flat_list_entry_cmp >+ * Function used by qsort() to sort the flat_list_entry array >+ * by ascending flat name. >+ */ >+static int flat_list_entry_cmp (const void *a, const void *b) >+{ >+return y_strnicmp ( >+ ((const flat_list_entry_t *) a)->name, >+ ((const flat_list_entry_t *) b)->name, >+ WAD_FLAT_NAME); >+} >+ >+ >+/* >+ function used by qsort to sort the texture names >+*/ >+static int SortTextures (const void *a, const void *b) >+{ >+return y_strnicmp (*((const char *const *)a), *((const char *const *)b), >+ WAD_TEX_NAME); >+} >+ >+ >+/* >+ read the texture names >+*/ >+void ReadWTextureNames () >+{ >+MDirPtr dir; >+int n; >+i32 val; >+ >+verbmsg ("Reading texture names\n"); >+ >+// Doom alpha 0.4 : "TEXTURES", no names >+if (yg_texture_lumps == YGTL_TEXTURES >+ && yg_texture_format == YGTF_NAMELESS) >+ { >+ const char *lump_name = "TEXTURES"; >+ dir = FindMasterDir (MasterDir, lump_name); >+ if (dir == NULL) >+ { >+ warn ("%s: lump not found in directory\n", lump_name); >+ goto textures04_done; >+ } >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ goto textures04_done; >+ } >+ wf->read_i32 (&val); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading texture count\n", lump_name); >+ goto textures04_done; >+ } >+ NumWTexture = (int) val + 1; >+ WTexture = (char **) GetMemory ((long) NumWTexture * sizeof *WTexture); >+ WTexture[0] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ strcpy (WTexture[0], "-"); >+ if (WAD_TEX_NAME < 7) nf_bug ("WAD_TEX_NAME too small"); // Sanity >+ for (long n = 0; n < val; n++) >+ { >+ WTexture[n + 1] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ if (n > 9999) >+ { >+ warn ("more than 10,000 textures. Ignoring excess.\n"); >+ break; >+ } >+ sprintf (WTexture[n + 1], "TEX%04ld", n); >+ } >+ } >+ textures04_done: >+ ; >+ } >+ >+// Doom alpha 0.5 : only "TEXTURES" >+else if (yg_texture_lumps == YGTL_TEXTURES >+ && (yg_texture_format == YGTF_NORMAL >+ || yg_texture_format == YGTF_STRIFE11)) >+ { >+ const char *lump_name = "TEXTURES"; >+ i32 *offsets = 0; >+ dir = FindMasterDir (MasterDir, lump_name); >+ if (dir == NULL) // In theory it always exists, though >+ { >+ warn ("%s: lump not found in directory\n", lump_name); >+ goto textures05_done; >+ } >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ goto textures05_done; >+ } >+ wf->read_i32 (&val); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading texture count\n", lump_name); >+ goto textures05_done; >+ } >+ NumWTexture = (int) val + 1; >+ /* read in the offsets for texture1 names */ >+ offsets = (i32 *) GetMemory ((long) NumWTexture * 4); >+ wf->read_i32 (offsets + 1, NumWTexture - 1); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading offsets table\n", lump_name); >+ goto textures05_done; >+ } >+ /* read in the actual names */ >+ WTexture = (char **) GetMemory ((long) NumWTexture * sizeof (char *)); >+ WTexture[0] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ strcpy (WTexture[0], "-"); >+ for (n = 1; n < NumWTexture; n++) >+ { >+ WTexture[n] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ long offset = dir->dir.start + offsets[n]; >+ wf->seek (offset); >+ if (wf->error ()) >+ { >+ warn ("%s: error seeking to error\n", lump_name); >+ goto textures05_done; // FIXME cleanup >+ } >+ wf->read_bytes (WTexture[n], WAD_TEX_NAME); >+ if (wf->error ()) >+ { >+ warn ("%s: error reading texture names\n", lump_name); >+ goto textures05_done; // FIXME cleanup >+ } >+ WTexture[n][WAD_TEX_NAME] = '\0'; >+ } >+ } >+ textures05_done: >+ if (offsets != 0) >+ FreeMemory (offsets); >+ } >+// Other iwads : "TEXTURE1" and possibly "TEXTURE2" >+else if (yg_texture_lumps == YGTL_NORMAL >+ && (yg_texture_format == YGTF_NORMAL >+ || yg_texture_format == YGTF_STRIFE11)) >+ { >+ const char *lump_name = "TEXTURE1"; >+ i32 *offsets = 0; >+ dir = FindMasterDir (MasterDir, lump_name); >+ if (dir != NULL) // In theory it always exists, though >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ // FIXME >+ } >+ wf->read_i32 (&val); >+ if (wf->error ()) >+ { >+ // FIXME >+ } >+ NumWTexture = (int) val + 1; >+ /* read in the offsets for texture1 names */ >+ offsets = (i32 *) GetMemory ((long) NumWTexture * 4); >+ wf->read_i32 (offsets + 1, NumWTexture - 1); >+ { >+ // FIXME >+ } >+ /* read in the actual names */ >+ WTexture = (char **) GetMemory ((long) NumWTexture * sizeof (char *)); >+ WTexture[0] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ strcpy (WTexture[0], "-"); >+ for (n = 1; n < NumWTexture; n++) >+ { >+ WTexture[n] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ wf->seek (dir->dir.start + offsets[n]); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ // FIXME >+ } >+ wf->read_bytes (WTexture[n], WAD_TEX_NAME); >+ if (wf->error ()) >+ { >+ // FIXME >+ } >+ WTexture[n][WAD_TEX_NAME] = '\0'; >+ } >+ FreeMemory (offsets); >+ } >+ { >+ dir = FindMasterDir (MasterDir, "TEXTURE2"); >+ if (dir) /* Doom II has no TEXTURE2 */ >+ { >+ const Wad_file *wf = dir->wadfile; >+ wf->seek (dir->dir.start); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ // FIXME >+ } >+ wf->read_i32 (&val); >+ if (wf->error ()) >+ { >+ // FIXME >+ } >+ /* read in the offsets for texture2 names */ >+ offsets = (i32 *) GetMemory ((long) val * 4); >+ wf->read_i32 (offsets, val); >+ if (wf->error ()) >+ { >+ // FIXME >+ } >+ /* read in the actual names */ >+ WTexture = (char **) ResizeMemory (WTexture, >+ (NumWTexture + val) * sizeof (char *)); >+ for (n = 0; n < val; n++) >+ { >+ WTexture[NumWTexture + n] = (char *) GetMemory (WAD_TEX_NAME + 1); >+ wf->seek (dir->dir.start + offsets[n]); >+ if (wf->error ()) >+ { >+ warn ("%s: seek error\n", lump_name); >+ // FIXME >+ } >+ wf->read_bytes (WTexture[NumWTexture + n], WAD_TEX_NAME); >+ if (wf->error ()) >+ ; // FIXME >+ WTexture[NumWTexture + n][WAD_TEX_NAME] = '\0'; >+ } >+ NumWTexture += val; >+ FreeMemory (offsets); >+ } >+ } >+ } >+else >+ nf_bug ("Invalid texture_format/texture_lumps combination."); >+ >+/* sort the names */ >+qsort (WTexture, NumWTexture, sizeof (char *), SortTextures); >+} >+ >+ >+ >+/* >+ forget the texture names >+*/ >+ >+void ForgetWTextureNames () >+{ >+int n; >+ >+/* forget all names */ >+for (n = 0; n < NumWTexture; n++) >+ FreeMemory (WTexture[n]); >+ >+/* forget the array */ >+NumWTexture = 0; >+FreeMemory (WTexture); >+} >+ >+ >+ >+/* >+ read the flat names >+*/ >+ >+void ReadFTextureNames () >+{ >+MDirPtr dir; >+int n; >+ >+verbmsg ("Reading flat names"); >+NumFTexture = 0; >+ >+for (dir = MasterDir; (dir = FindMasterDir (dir, "F_START", "FF_START"));) >+ { >+ bool ff_start = ! y_strnicmp (dir->dir.name, "FF_START", WAD_NAME); >+ MDirPtr dir0; >+ /* count the names */ >+ dir = dir->next; >+ dir0 = dir; >+ for (n = 0; dir && y_strnicmp (dir->dir.name, "F_END", WAD_NAME) >+ && (! ff_start || y_strnicmp (dir->dir.name, "FF_END", WAD_NAME)); >+ dir = dir->next) >+ { >+ if (dir->dir.start == 0 || dir->dir.size == 0) >+ { >+ if (! (toupper (dir->dir.name[0]) == 'F' >+ && (dir->dir.name[1] == '1' >+ || dir->dir.name[1] == '2' >+ || dir->dir.name[1] == '3' >+ || toupper (dir->dir.name[1]) == 'F') >+ && dir->dir.name[2] == '_' >+ && (! y_strnicmp (dir->dir.name + 3, "START", WAD_NAME - 3) >+ || ! y_strnicmp (dir->dir.name + 3, "END", WAD_NAME - 3)))) >+ warn ("unexpected label \"%.*s\" among flats.\n", >+ WAD_NAME, dir->dir.name); >+ continue; >+ } >+ if (dir->dir.size != 4096) >+ warn ("flat \"%.*s\" has weird size %lu." >+ " Using 4096 instead.\n", >+ WAD_NAME, dir->dir.name, (unsigned long) dir->dir.size); >+ n++; >+ } >+ /* If FF_START/FF_END followed by F_END (mm2.wad), advance >+ past F_END. In fact, this does not work because the F_END >+ that follows has been snatched by OpenPatchWad(), that >+ thinks it replaces the F_END from the iwad. OpenPatchWad() >+ needs to be kludged to take this special case into >+ account. Fortunately, the only consequence is a useless >+ "this wad uses FF_END" warning. -- AYM 1999-07-10 */ >+ if (ff_start && dir && ! y_strnicmp (dir->dir.name, "FF_END", WAD_NAME)) >+ if (dir->next && ! y_strnicmp (dir->next->dir.name, "F_END", WAD_NAME)) >+ dir = dir->next; >+ >+ verbmsg (" FF_START/%s %d", dir->dir.name, n); >+ if (dir && ! y_strnicmp (dir->dir.name, "FF_END", WAD_NAME)) >+ warn ("this wad uses FF_END. That won't work with Doom." >+ " Use F_END instead.\n"); >+ /* get the actual names from master dir. */ >+ flat_list = (flat_list_entry_t *) ResizeMemory (flat_list, >+ (NumFTexture + n) * sizeof *flat_list); >+ for (size_t m = NumFTexture; m < NumFTexture + n; dir0 = dir0->next) >+ { >+ // Skip all labels. >+ if (dir0->dir.start == 0 >+ || dir0->dir.size == 0 >+ || (toupper (dir0->dir.name[0]) == 'F' >+ && (dir0->dir.name[1] == '1' >+ || dir0->dir.name[1] == '2' >+ || dir0->dir.name[1] == '3' >+ || toupper (dir0->dir.name[1]) == 'F') >+ && dir0->dir.name[2] == '_' >+ && (! y_strnicmp (dir0->dir.name + 3, "START", WAD_NAME - 3) >+ || ! y_strnicmp (dir0->dir.name + 3, "END", WAD_NAME - 3)) >+ )) >+ continue; >+ *flat_list[m].name = '\0'; >+ strncat (flat_list[m].name, dir0->dir.name, sizeof flat_list[m].name - 1); >+ flat_list[m].wadfile = dir0->wadfile; >+ flat_list[m].offset = dir0->dir.start; >+ m++; >+ } >+ NumFTexture += n; >+ } >+ >+verbmsg ("\n"); >+ >+/* sort the flats by names */ >+qsort (flat_list, NumFTexture, sizeof *flat_list, flat_list_entry_cmp); >+ >+/* Eliminate all but the last duplicates of a flat. Suboptimal. >+ Would be smarter to start by the end. */ >+for (size_t n = 0; n < NumFTexture; n++) >+ { >+ size_t m = n; >+ while (m + 1 < NumFTexture >+ && ! flat_list_entry_cmp (flat_list + n, flat_list + m + 1)) >+ m++; >+ // m now contains the index of the last duplicate >+ int nduplicates = m - n; >+ if (nduplicates > 0) >+ { >+ memmove (flat_list + n, flat_list + m, >+ (NumFTexture - m) * sizeof *flat_list); >+ NumFTexture -= nduplicates; >+ // Note that I'm too lazy to resize flat_list... >+ } >+ } >+} >+ >+ >+/* >+ * is_flat_name_in_list >+ * FIXME should use bsearch() >+ */ >+int is_flat_name_in_list (const char *name) >+{ >+ if (! flat_list) >+ return 0; >+ for (size_t n = 0; n < NumFTexture; n++) >+ if (! y_strnicmp (name, flat_list[n].name, WAD_FLAT_NAME)) >+ return 1; >+ return 0; >+} >+ >+ >+/* >+ forget the flat names >+*/ >+ >+void ForgetFTextureNames () >+{ >+NumFTexture = 0; >+FreeMemory (flat_list); >+flat_list = 0; >+} >+ >+ >+/* >+ * update_level_bounds - update Map{Min,Max}{X,Y} >+ */ >+void update_level_bounds () >+{ >+MapMaxX = -32767; >+MapMaxY = -32767; >+MapMinX = 32767; >+MapMinY = 32767; >+for (obj_no_t n = 0; n < NumVertices; n++) >+ { >+ int x = Vertices[n].x; >+ if (x < MapMinX) >+ MapMinX = x; >+ if (x > MapMaxX) >+ MapMaxX = x; >+ int y = Vertices[n].y; >+ if (y < MapMinY) >+ MapMinY = y; >+ if (y > MapMaxY) >+ MapMaxY = y; >+ } >+} >+ >diff -Nru yadex-1.7.0-orig/src/levels.h yadex-1.7.0/src/levels.h >--- yadex-1.7.0-orig/src/levels.h 2001-10-13 09:57:33.000000000 -0500 >+++ yadex-1.7.0/src/levels.h 2012-06-17 18:47:12.487693181 -0400 >@@ -28,6 +28,8 @@ > extern int NumSegs; /* number of segments */ > extern int NumSectors; /* number of sectors */ > extern SPtr Sectors; /* sectors data */ >+extern u8* Behavior; >+extern int BehaviorSize; > > // FIXME should be somewhere else > extern int NumWTexture; /* number of wall textures */ >diff -Nru yadex-1.7.0-orig/src/l_prop.cc yadex-1.7.0/src/l_prop.cc >--- yadex-1.7.0-orig/src/l_prop.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/l_prop.cc 2012-06-17 18:47:12.488693187 -0400 >@@ -105,13 +105,13 @@ > * Prototypes of private functions > */ > static char *GetTaggedLineDefFlag (int linedefnum, int flagndx); >-static int InputLinedefType (int x0, int y0, int *number); >+int InputLinedefType (int x0, int y0, int *number); > static const char *PrintLdtgroup (void *ptr); > > > void LinedefProperties (int x0, int y0, SelPtr obj) > { >- char *menustr[8]; >+ char *menustr[12]; > char texname[WAD_TEX_NAME + 1]; > int n, val; > SelPtr cur, sdlist; >@@ -132,9 +132,9 @@ > switch (val) > { > case 1: >- for (n = 0; n < 8; n++) >+ for (n = 0; n < 12; n++) > menustr[n] = (char *) GetMemory (60); >- sprintf (menustr[7], "Edit linedef #%d", obj->objnum); >+ sprintf (menustr[11], "Edit linedef #%d", obj->objnum); > sprintf (menustr[0], "Change flags (Current: %d)", > LineDefs[obj->objnum].flags); > sprintf (menustr[1], "Change type (Current: %d)", >@@ -149,7 +149,16 @@ > LineDefs[obj->objnum].sidedef1); > sprintf (menustr[6], "Change 2nd sidedef ref. (Current: #%d)", > LineDefs[obj->objnum].sidedef2); >- val = vDisplayMenu (x0 + 42, subwin_y0, menustr[7], >+ sprintf (menustr[7], "Change special arg2 (Current: %d)", >+ LineDefs[obj->objnum].arg2); >+ sprintf (menustr[8], "Change special arg3 (Current: %d)", >+ LineDefs[obj->objnum].arg3); >+ sprintf (menustr[9], "Change special arg4 (Current: %d)", >+ LineDefs[obj->objnum].arg4); >+ sprintf (menustr[10], "Change special arg5 (Current: %d)", >+ LineDefs[obj->objnum].arg5); >+ if (yg_level_format == YGLF_HEXEN) >+ val = vDisplayMenu (x0 + 42, subwin_y0, menustr[11], > menustr[0], YK_, 0, > menustr[1], YK_, 0, > menustr[2], YK_, 0, >@@ -157,8 +166,22 @@ > menustr[4], YK_, 0, > menustr[5], YK_, 0, > menustr[6], YK_, 0, >+ menustr[7], YK_, 0, >+ menustr[8], YK_, 0, >+ menustr[9], YK_, 0, >+ menustr[10], YK_, 0, > NULL); >- for (n = 0; n < 8; n++) >+ else >+ val = vDisplayMenu (x0 + 42, subwin_y0, menustr[11], >+ menustr[0], YK_, 0, >+ menustr[1], YK_, 0, >+ menustr[2], YK_, 0, >+ menustr[3], YK_, 0, >+ menustr[4], YK_, 0, >+ menustr[5], YK_, 0, >+ menustr[6], YK_, 0, >+ NULL); >+ for (n = 0; n < 12; n++) > FreeMemory (menustr[n]); > subsubwin_y0 = subwin_y0 + BOX_BORDER + (2 + val) * FONTH; > switch (val) >@@ -269,6 +292,50 @@ > MadeMapChanges = 1; > } > break; >+ >+ case 8: >+ val = InputIntegerValue (x0 + 84, subsubwin_y0, >+ 0, 255, LineDefs[obj->objnum].arg2); >+ if (val != IIV_CANCEL) // Not [esc] >+ { >+ for (cur = obj; cur; cur = cur->next) >+ LineDefs[cur->objnum].arg2 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 9: >+ val = InputIntegerValue (x0 + 84, subsubwin_y0, >+ 0, 255, LineDefs[obj->objnum].arg3); >+ if (val != IIV_CANCEL) // Not [esc] >+ { >+ for (cur = obj; cur; cur = cur->next) >+ LineDefs[cur->objnum].arg3 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 10: >+ val = InputIntegerValue (x0 + 84, subsubwin_y0, >+ 0, 255, LineDefs[obj->objnum].arg4); >+ if (val != IIV_CANCEL) // Not [esc] >+ { >+ for (cur = obj; cur; cur = cur->next) >+ LineDefs[cur->objnum].arg4 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 11: >+ val = InputIntegerValue (x0 + 84, subsubwin_y0, >+ 0, 255, LineDefs[obj->objnum].arg5); >+ if (val != IIV_CANCEL) // Not [esc] >+ { >+ for (cur = obj; cur; cur = cur->next) >+ LineDefs[cur->objnum].arg5 = val; >+ MadeChanges = 1; >+ } >+ break; > } > break; > >@@ -475,7 +542,7 @@ > * Let the user select a linedef type number and return it. > * Returns 0 if OK, <>0 if cancelled > */ >-static int InputLinedefType (int x0, int y0, int *number) >+int InputLinedefType (int x0, int y0, int *number) > { > int r; > int ldtgno = 0; >@@ -547,3 +614,37 @@ > return ((ldtgroup_t *)ptr)->desc; > } > >+/* >+ * TransferLinedefProperties >+ * >+ * Note: right now nothing is done about sidedefs. Being able to >+ * (intelligently) transfer sidedef properties from source line to >+ * destination linedefs could be a useful feature -- though it is >+ * unclear the best way to do it. OTOH not touching sidedefs might >+ * be useful too. >+ * >+ * -AJA- 2001-05-27 >+ */ >+#define LINEDEF_FLAG_KEEP (1 + 4) >+ >+void TransferLinedefProperties (int src_linedef, SelPtr linedefs) >+{ >+ SelPtr cur; >+ wad_ldflags_t src_flags = LineDefs[src_linedef].flags & ~LINEDEF_FLAG_KEEP; >+ >+ for (cur=linedefs; cur; cur=cur->next) >+ { >+ if (! is_obj(cur->objnum)) >+ continue; >+ >+ // don't transfer certain flags >+ LineDefs[cur->objnum].flags &= LINEDEF_FLAG_KEEP; >+ LineDefs[cur->objnum].flags |= src_flags; >+ >+ LineDefs[cur->objnum].type = LineDefs[src_linedef].type; >+ LineDefs[cur->objnum].tag = LineDefs[src_linedef].tag; >+ >+ MadeChanges = 1; >+ } >+} >+ >diff -Nru yadex-1.7.0-orig/src/objects.cc yadex-1.7.0/src/objects.cc >--- yadex-1.7.0-orig/src/objects.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/objects.cc 2012-06-17 18:49:02.960390173 -0400 >@@ -465,12 +465,28 @@ > Things[last].type = Things[copyfrom].type; > Things[last].angle = Things[copyfrom].angle; > Things[last].when = Things[copyfrom].when; >+ Things[last].tid = Things[copyfrom].tid; >+ Things[last].height = Things[copyfrom].height; >+ Things[last].special = Things[copyfrom].special; >+ Things[last].arg1 = Things[copyfrom].arg1; >+ Things[last].arg2 = Things[copyfrom].arg2; >+ Things[last].arg3 = Things[copyfrom].arg3; >+ Things[last].arg4 = Things[copyfrom].arg4; >+ Things[last].arg5 = Things[copyfrom].arg5; > } > else > { > Things[last].type = default_thing; > Things[last].angle = 0; > Things[last].when = 0x07; >+ Things[last].tid = 0; >+ Things[last].height = 0; >+ Things[last].special = 0; >+ Things[last].arg1 = 0; >+ Things[last].arg2 = 0; >+ Things[last].arg3 = 0; >+ Things[last].arg4 = 0; >+ Things[last].arg5 = 0; > } > break; > >@@ -508,6 +524,10 @@ > LineDefs[last].flags = LineDefs[copyfrom].flags; > LineDefs[last].type = LineDefs[copyfrom].type; > LineDefs[last].tag = LineDefs[copyfrom].tag; >+ LineDefs[last].arg2 = LineDefs[copyfrom].arg2; >+ LineDefs[last].arg3 = LineDefs[copyfrom].arg3; >+ LineDefs[last].arg4 = LineDefs[copyfrom].arg4; >+ LineDefs[last].arg5 = LineDefs[copyfrom].arg5; > } > else > { >@@ -516,6 +536,10 @@ > LineDefs[last].flags = 1; > LineDefs[last].type = 0; > LineDefs[last].tag = 0; >+ LineDefs[last].arg2 = 0; >+ LineDefs[last].arg3 = 0; >+ LineDefs[last].arg4 = 0; >+ LineDefs[last].arg5 = 0; > } > LineDefs[last].sidedef1 = OBJ_NO_NONE; > LineDefs[last].sidedef2 = OBJ_NO_NONE; >@@ -543,7 +567,7 @@ > SideDefs[last].yoff = 0; > strcpy (SideDefs[last].tex1, "-"); > strcpy (SideDefs[last].tex2, "-"); >- strcpy (SideDefs[last].tex3, default_middle_texture); >+ strncpy (SideDefs[last].tex3, default_middle_texture, sizeof(SideDefs[last].tex3)); > SideDefs[last].sector = NumSectors - 1; > } > MadeMapChanges = 1; >diff -Nru yadex-1.7.0-orig/src/objects.cc.orig yadex-1.7.0/src/objects.cc.orig >--- yadex-1.7.0-orig/src/objects.cc.orig 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/objects.cc.orig 2012-06-17 18:47:12.489693193 -0400 >@@ -0,0 +1,1252 @@ >+/* >+ * objects.cc >+ * Object handling routines. >+ * BW & RQ sometime in 1993 or 1994. >+ */ >+ >+ >+/* >+This file is part of Yadex. >+ >+Yadex incorporates code from DEU 5.21 that was put in the public domain in >+1994 by Raphaël Quinet and Brendon Wyber. >+ >+The rest of Yadex is Copyright © 1997-2003 André Majorel and others. >+ >+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. >+*/ >+ >+ >+#include "yadex.h" >+#include "drawmap.h" >+#include "gfx.h" >+#include "l_vertices.h" >+#include "levels.h" >+#include "objects.h" >+#include "objid.h" >+#include "s_vertices.h" >+#include "selectn.h" >+#include "things.h" >+ >+ >+/* >+ highlight the selected objects >+*/ >+void HighlightSelection (int objtype, SelPtr list) /* SWAP! */ >+{ >+SelPtr cur; >+ >+if (! list) >+ return; >+for (cur = list; cur; cur = cur->next) >+ HighlightObject (objtype, cur->objnum, GREEN); >+} >+ >+ >+ >+/* >+ get the number of objects of a given type minus one >+*/ >+obj_no_t GetMaxObjectNum (int objtype) >+{ >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ return NumThings - 1; >+ case OBJ_LINEDEFS: >+ return NumLineDefs - 1; >+ case OBJ_SIDEDEFS: >+ return NumSideDefs - 1; >+ case OBJ_VERTICES: >+ return NumVertices - 1; >+ case OBJ_SECTORS: >+ return NumSectors - 1; >+ } >+return -1; >+} >+ >+ >+/* >+ highlight the selected object >+*/ >+void HighlightObject (int objtype, int objnum, int colour) /* SWAP! */ >+{ >+int n, m; >+ >+/* use XOR mode : drawing any line twice erases it */ >+SetDrawingMode (1); >+set_colour (colour); >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ ObjectsNeeded (OBJ_THINGS, 0); >+ m = (get_thing_radius (Things[objnum].type) * 3) / 2; >+ DrawMapLine (Things[objnum].xpos - m, Things[objnum].ypos - m, >+ Things[objnum].xpos - m, Things[objnum].ypos + m); >+ DrawMapLine (Things[objnum].xpos - m, Things[objnum].ypos + m, >+ Things[objnum].xpos + m, Things[objnum].ypos + m); >+ DrawMapLine (Things[objnum].xpos + m, Things[objnum].ypos + m, >+ Things[objnum].xpos + m, Things[objnum].ypos - m); >+ DrawMapLine (Things[objnum].xpos + m, Things[objnum].ypos - m, >+ Things[objnum].xpos - m, Things[objnum].ypos - m); >+ DrawMapArrow (Things[objnum].xpos, Things[objnum].ypos, >+ Things[objnum].angle * 182); >+ break; >+ >+ case OBJ_LINEDEFS: >+ ObjectsNeeded (OBJ_LINEDEFS, OBJ_VERTICES, 0); >+ n = (Vertices[LineDefs[objnum].start].x >+ + Vertices[LineDefs[objnum].end].x) / 2; >+ m = (Vertices[LineDefs[objnum].start].y >+ + Vertices[LineDefs[objnum].end].y) / 2; >+ DrawMapLine (n, m, n + (Vertices[LineDefs[objnum].end].y >+ - Vertices[LineDefs[objnum].start].y) / 3, >+ m + (Vertices[LineDefs[objnum].start].x >+ - Vertices[LineDefs[objnum].end].x) / 3); >+ SetLineThickness (1); >+ DrawMapVector (Vertices[LineDefs[objnum].start].x, >+ Vertices[LineDefs[objnum].start].y, >+ Vertices[LineDefs[objnum].end].x, >+ Vertices[LineDefs[objnum].end].y); >+ if (colour != LIGHTRED && LineDefs[objnum].tag > 0) >+ { >+ for (m = 0; m < NumSectors; m++) >+ if (Sectors[m].tag == LineDefs[objnum].tag) >+ HighlightObject (OBJ_SECTORS, m, LIGHTRED); >+ } >+ SetLineThickness (0); >+ break; >+ >+ case OBJ_VERTICES: >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ { >+ int r = vertex_radius (Scale) * 3 / 2; >+ int scrx0 = SCREENX (Vertices[objnum].x) - r; >+ int scrx9 = SCREENX (Vertices[objnum].x) + r; >+ int scry0 = SCREENY (Vertices[objnum].y) - r; >+ int scry9 = SCREENY (Vertices[objnum].y) + r; >+ DrawScreenLine (scrx0, scry0, scrx9, scry0); >+ DrawScreenLine (scrx9, scry0, scrx9, scry9); >+ DrawScreenLine (scrx9, scry9, scrx0, scry9); >+ DrawScreenLine (scrx0, scry9, scrx0, scry0); >+ } >+ break; >+ >+ case OBJ_SECTORS: >+ { >+ ObjectsNeeded (OBJ_LINEDEFS, OBJ_SIDEDEFS, OBJ_VERTICES, 0); >+ SetLineThickness (1); >+ const int mapx0 = MAPX (0); >+ const int mapy0 = MAPY (ScrMaxY); >+ const int mapx1 = MAPX (ScrMaxX); >+ const int mapy1 = MAPY (0); >+ for (n = 0; n < NumLineDefs; n++) >+ if (LineDefs[n].sidedef1 != -1 >+ && SideDefs[LineDefs[n].sidedef1].sector == objnum >+ || LineDefs[n].sidedef2 != -1 >+ && SideDefs[LineDefs[n].sidedef2].sector == objnum) >+ { >+ const struct Vertex *v1 = Vertices + LineDefs[n].start; >+ const struct Vertex *v2 = Vertices + LineDefs[n].end; >+ if (v1->x < mapx0 && v2->x < mapx0 >+ || v1->x > mapx1 && v2->x > mapx1 >+ || v1->y < mapy0 && v2->y < mapy0 >+ || v1->y > mapy1 && v2->y > mapy1) >+ continue; // Off-screen >+ DrawMapLine (v1->x, v1->y, v2->x, v2->y); >+ } >+ if (colour != LIGHTRED && Sectors[objnum].tag > 0) >+ { >+ for (m = 0; m < NumLineDefs; m++) >+ if (LineDefs[m].tag == Sectors[objnum].tag) >+ HighlightObject (OBJ_LINEDEFS, m, LIGHTRED); >+ } >+ SetLineThickness (0); >+ } >+ break; >+ } >+/* restore normal write mode */ >+SetDrawingMode (0); >+} >+ >+ >+ >+/* >+ delete an object >+*/ >+void DeleteObject (const Objid& obj) /* SWAP! */ >+{ >+SelPtr list; >+ >+list = 0; >+SelectObject (&list, obj.num); >+DeleteObjects (obj.type, &list); >+} >+ >+ >+ >+/* >+ delete a group of objects (*recursive*) >+*/ >+void DeleteObjects (int objtype, SelPtr *list) /* SWAP! */ >+{ >+int n, objnum; >+SelPtr cur; >+ >+MadeChanges = 1; >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ ObjectsNeeded (OBJ_THINGS, 0); >+ if (*list) >+ { >+ things_angles++; >+ things_types++; >+ } >+ while (*list) >+ { >+ objnum = (*list)->objnum; >+ if (objnum < 0 || objnum >= NumThings) // Paranoia >+ { >+ nf_bug ("attempt to delete non-existent thing #%d", objnum); >+ goto next_thing; >+ } >+ // Delete the thing >+ NumThings--; >+ if (NumThings > 0) >+ { >+ for (n = objnum; n < NumThings; n++) >+ Things[n] = Things[n + 1]; >+ Things = (TPtr) ResizeFarMemory (Things, >+ NumThings * sizeof (struct Thing)); >+ } >+ else >+ { >+ FreeFarMemory (Things); >+ Things = 0; >+ } >+ for (cur = (*list)->next; cur; cur = cur->next) >+ if (cur->objnum > objnum) >+ cur->objnum--; >+ next_thing: >+ UnSelectObject (list, objnum); >+ } >+ break; >+ >+ case OBJ_VERTICES: >+ if (*list) >+ MadeMapChanges = 1; >+ while (*list) >+ { >+ objnum = (*list)->objnum; >+ if (objnum < 0 || objnum >= NumVertices) // Paranoia >+ { >+ nf_bug ("attempt to delete non-existent vertex #%d", objnum); >+ goto next_vertex; >+ } >+ // Delete the linedefs bound to this vertex and change the references >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ for (n = 0; n < NumLineDefs; n++) >+ { >+ if (LineDefs[n].start == objnum || LineDefs[n].end == objnum) >+ DeleteObject (Objid (OBJ_LINEDEFS, n--)); >+ else >+ { >+ if (LineDefs[n].start >= objnum) >+ LineDefs[n].start--; >+ if (LineDefs[n].end >= objnum) >+ LineDefs[n].end--; >+ } >+ } >+ // Delete the vertex >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ NumVertices--; >+ if (NumVertices > 0) >+ { >+ for (n = objnum; n < NumVertices; n++) >+ Vertices[n] = Vertices[n + 1]; >+ Vertices = (VPtr) ResizeFarMemory (Vertices, >+ NumVertices * sizeof (struct Vertex)); >+ } >+ else >+ { >+ FreeFarMemory (Vertices); >+ Vertices = 0; >+ } >+ for (cur = (*list)->next; cur; cur = cur->next) >+ if (cur->objnum > objnum) >+ cur->objnum--; >+ next_vertex: >+ UnSelectObject (list, objnum); >+ } >+ break; >+ >+ case OBJ_LINEDEFS: >+ /* In DEU, deleting a linedef was not considered to be a >+ map change. Deleting a _sidedef_ was. In Yadex, >+ sidedefs are not automatically deleted when the linedef >+ is because some sidedefs are shared by more than one >+ linedef. So we need to set MadeMapChanges here. */ >+ if (*list) >+ MadeMapChanges = 1; >+ /* AYM 19980203 I've removed the deletion of sidedefs >+ because if several linedefs use the same sidedef, this >+ would lead to trouble. Instead, I let the xref checking >+ take care of that. */ >+ while (*list) >+ { >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ objnum = (*list)->objnum; >+ if (objnum < 0 || objnum >= NumLineDefs) // Paranoia >+ { >+ nf_bug ("attempt to delete non-existent linedef #%d", objnum); >+ goto next_linedef; >+ } >+ // delete the linedef >+ NumLineDefs--; >+ if (NumLineDefs > 0) >+ { >+ for (n = objnum; n < NumLineDefs; n++) >+ LineDefs[n] = LineDefs[n + 1]; >+ LineDefs = (LDPtr) ResizeFarMemory (LineDefs, >+ NumLineDefs * sizeof (struct LineDef)); >+ } >+ else >+ { >+ FreeFarMemory (LineDefs); >+ LineDefs = 0; >+ } >+ for (cur = (*list)->next; cur; cur = cur->next) >+ if (cur->objnum > objnum) >+ cur->objnum--; >+ next_linedef: >+ UnSelectObject (list, objnum); >+ } >+ break; >+ >+ case OBJ_SIDEDEFS: >+ if (*list) >+ MadeMapChanges = 1; >+ while (*list) >+ { >+ objnum = (*list)->objnum; >+ if (objnum < 0 || objnum >= NumSideDefs) // Paranoia >+ { >+ nf_bug ("attempt to delete non-existent sidedef #%d", objnum); >+ goto next_sidedef; >+ } >+ /* change the linedefs references */ >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ for (n = 0; n < NumLineDefs; n++) >+ { >+ if (LineDefs[n].sidedef1 == objnum) >+ LineDefs[n].sidedef1 = -1; >+ else if (LineDefs[n].sidedef1 >= objnum) >+ LineDefs[n].sidedef1--; >+ if (LineDefs[n].sidedef2 == objnum) >+ LineDefs[n].sidedef2 = -1; >+ else if (LineDefs[n].sidedef2 >= objnum) >+ LineDefs[n].sidedef2--; >+ } >+ /* delete the sidedef */ >+ ObjectsNeeded (OBJ_SIDEDEFS, 0); >+ NumSideDefs--; >+ if (NumSideDefs > 0) >+ { >+ for (n = objnum; n < NumSideDefs; n++) >+ SideDefs[n] = SideDefs[n + 1]; >+ SideDefs = (SDPtr) ResizeFarMemory (SideDefs, >+ NumSideDefs * sizeof (struct SideDef)); >+ } >+ else >+ { >+ FreeFarMemory (SideDefs); >+ SideDefs = 0; >+ } >+ for (cur = (*list)->next; cur; cur = cur->next) >+ if (cur->objnum > objnum) >+ cur->objnum--; >+ next_sidedef: >+ UnSelectObject (list, objnum); >+ } >+ break; >+ case OBJ_SECTORS: >+ while (*list) >+ { >+ objnum = (*list)->objnum; >+ if (objnum < 0 || objnum >= NumSectors) // Paranoia >+ { >+ nf_bug ("attempt to delete non-existent sector #%d", objnum); >+ goto next_sector; >+ } >+ // Delete the sidedefs bound to this sector and change the references >+ // AYM 19980203: Hmm, hope this is OK with multiply used sidedefs... >+ ObjectsNeeded (OBJ_SIDEDEFS, 0); >+ for (n = 0; n < NumSideDefs; n++) >+ if (SideDefs[n].sector == objnum) >+ DeleteObject (Objid (OBJ_SIDEDEFS, n--)); >+ else if (SideDefs[n].sector >= objnum) >+ SideDefs[n].sector--; >+ /* delete the sector */ >+ ObjectsNeeded (OBJ_SECTORS, 0); >+ NumSectors--; >+ if (NumSectors > 0) >+ { >+ for (n = objnum; n < NumSectors; n++) >+ Sectors[n] = Sectors[n + 1]; >+ Sectors = (SPtr) ResizeFarMemory (Sectors, >+ NumSectors * sizeof (struct Sector)); >+ } >+ else >+ { >+ FreeFarMemory (Sectors); >+ Sectors = 0; >+ } >+ for (cur = (*list)->next; cur; cur = cur->next) >+ if (cur->objnum > objnum) >+ cur->objnum--; >+ next_sector: >+ UnSelectObject (list, objnum); >+ } >+ break; >+ default: >+ nf_bug ("DeleteObjects: bad objtype %d", (int) objtype); >+ } >+} >+ >+ >+ >+/* >+ * InsertObject >+ * Insert a new object of type <objtype> at map coordinates >+ * (<xpos>, <ypos>). >+ * >+ * If <copyfrom> is a valid object number, the other properties >+ * of the new object are set from the properties of that object, >+ * with the exception of sidedef numbers, which are forced >+ * to OBJ_NO_NONE. >+ * >+ * The object is inserted at the exact coordinates given. >+ * No snapping to grid is done. >+ */ >+void InsertObject (obj_type_t objtype, obj_no_t copyfrom, int xpos, int ypos) >+ /* SWAP! */ >+{ >+int last; >+ >+ObjectsNeeded (objtype, 0); >+MadeChanges = 1; >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ last = NumThings++; >+ if (last > 0) >+ Things = (TPtr) ResizeFarMemory (Things, >+ (unsigned long) NumThings * sizeof (struct Thing)); >+ else >+ Things = (TPtr) GetFarMemory (sizeof (struct Thing)); >+ Things[last].xpos = xpos; >+ Things[last].ypos = ypos; >+ things_angles++; >+ things_types++; >+ if (is_obj (copyfrom)) >+ { >+ Things[last].type = Things[copyfrom].type; >+ Things[last].angle = Things[copyfrom].angle; >+ Things[last].when = Things[copyfrom].when; >+ Things[last].tid = Things[copyfrom].tid; >+ Things[last].height = Things[copyfrom].height; >+ Things[last].special = Things[copyfrom].special; >+ Things[last].arg1 = Things[copyfrom].arg1; >+ Things[last].arg2 = Things[copyfrom].arg2; >+ Things[last].arg3 = Things[copyfrom].arg3; >+ Things[last].arg4 = Things[copyfrom].arg4; >+ Things[last].arg5 = Things[copyfrom].arg5; >+ } >+ else >+ { >+ Things[last].type = default_thing; >+ Things[last].angle = 0; >+ Things[last].when = 0x07; >+ Things[last].tid = 0; >+ Things[last].height = 0; >+ Things[last].special = 0; >+ Things[last].arg1 = 0; >+ Things[last].arg2 = 0; >+ Things[last].arg3 = 0; >+ Things[last].arg4 = 0; >+ Things[last].arg5 = 0; >+ } >+ break; >+ >+ case OBJ_VERTICES: >+ last = NumVertices++; >+ if (last > 0) >+ Vertices = (VPtr) ResizeFarMemory (Vertices, >+ (unsigned long) NumVertices * sizeof (struct Vertex)); >+ else >+ Vertices = (VPtr) GetFarMemory (sizeof (struct Vertex)); >+ Vertices[last].x = xpos; >+ Vertices[last].y = ypos; >+ if (Vertices[last].x < MapMinX) >+ MapMinX = Vertices[last].x; >+ if (Vertices[last].x > MapMaxX) >+ MapMaxX = Vertices[last].x; >+ if (Vertices[last].y < MapMinY) >+ MapMinY = Vertices[last].y; >+ if (Vertices[last].y > MapMaxY) >+ MapMaxY = Vertices[last].y; >+ MadeMapChanges = 1; >+ break; >+ >+ case OBJ_LINEDEFS: >+ last = NumLineDefs++; >+ if (last > 0) >+ LineDefs = (LDPtr) ResizeFarMemory (LineDefs, >+ (unsigned long) NumLineDefs * sizeof (struct LineDef)); >+ else >+ LineDefs = (LDPtr) GetFarMemory (sizeof (struct LineDef)); >+ if (is_obj (copyfrom)) >+ { >+ LineDefs[last].start = LineDefs[copyfrom].start; >+ LineDefs[last].end = LineDefs[copyfrom].end; >+ LineDefs[last].flags = LineDefs[copyfrom].flags; >+ LineDefs[last].type = LineDefs[copyfrom].type; >+ LineDefs[last].tag = LineDefs[copyfrom].tag; >+ LineDefs[last].arg2 = LineDefs[copyfrom].arg2; >+ LineDefs[last].arg3 = LineDefs[copyfrom].arg3; >+ LineDefs[last].arg4 = LineDefs[copyfrom].arg4; >+ LineDefs[last].arg5 = LineDefs[copyfrom].arg5; >+ } >+ else >+ { >+ LineDefs[last].start = 0; >+ LineDefs[last].end = NumVertices - 1; >+ LineDefs[last].flags = 1; >+ LineDefs[last].type = 0; >+ LineDefs[last].tag = 0; >+ LineDefs[last].arg2 = 0; >+ LineDefs[last].arg3 = 0; >+ LineDefs[last].arg4 = 0; >+ LineDefs[last].arg5 = 0; >+ } >+ LineDefs[last].sidedef1 = OBJ_NO_NONE; >+ LineDefs[last].sidedef2 = OBJ_NO_NONE; >+ break; >+ >+ case OBJ_SIDEDEFS: >+ last = NumSideDefs++; >+ if (last > 0) >+ SideDefs = (SDPtr) ResizeFarMemory (SideDefs, >+ (unsigned long) NumSideDefs * sizeof (struct SideDef)); >+ else >+ SideDefs = (SDPtr) GetFarMemory (sizeof (struct SideDef)); >+ if (is_obj (copyfrom)) >+ { >+ SideDefs[last].xoff = SideDefs[copyfrom].xoff; >+ SideDefs[last].yoff = SideDefs[copyfrom].yoff; >+ strncpy (SideDefs[last].tex1, SideDefs[copyfrom].tex1, WAD_TEX_NAME); >+ strncpy (SideDefs[last].tex2, SideDefs[copyfrom].tex2, WAD_TEX_NAME); >+ strncpy (SideDefs[last].tex3, SideDefs[copyfrom].tex3, WAD_TEX_NAME); >+ SideDefs[last].sector = SideDefs[copyfrom].sector; >+ } >+ else >+ { >+ SideDefs[last].xoff = 0; >+ SideDefs[last].yoff = 0; >+ strcpy (SideDefs[last].tex1, "-"); >+ strcpy (SideDefs[last].tex2, "-"); >+ strcpy (SideDefs[last].tex3, default_middle_texture); >+ SideDefs[last].sector = NumSectors - 1; >+ } >+ MadeMapChanges = 1; >+ break; >+ >+ case OBJ_SECTORS: >+ last = NumSectors++; >+ if (last > 0) >+ Sectors = (SPtr) ResizeFarMemory (Sectors, >+ (unsigned long) NumSectors * sizeof (struct Sector)); >+ else >+ Sectors = (SPtr) GetFarMemory (sizeof (struct Sector)); >+ if (is_obj (copyfrom)) >+ { >+ Sectors[last].floorh = Sectors[copyfrom].floorh; >+ Sectors[last].ceilh = Sectors[copyfrom].ceilh; >+ strncpy (Sectors[last].floort, Sectors[copyfrom].floort, WAD_FLAT_NAME); >+ strncpy (Sectors[last].ceilt, Sectors[copyfrom].ceilt, WAD_FLAT_NAME); >+ Sectors[last].light = Sectors[copyfrom].light; >+ Sectors[last].special = Sectors[copyfrom].special; >+ Sectors[last].tag = Sectors[copyfrom].tag; >+ } >+ else >+ { >+ Sectors[last].floorh = default_floor_height; >+ Sectors[last].ceilh = default_ceiling_height; >+ strncpy (Sectors[last].floort, default_floor_texture, WAD_FLAT_NAME); >+ strncpy (Sectors[last].ceilt, default_ceiling_texture, WAD_FLAT_NAME); >+ Sectors[last].light = default_light_level; >+ Sectors[last].special = 0; >+ Sectors[last].tag = 0; >+ } >+ break; >+ >+ default: >+ nf_bug ("InsertObject: bad objtype %d", (int) objtype); >+ } >+} >+ >+ >+ >+/* >+ check if a (part of a) LineDef is inside a given block >+*/ >+bool IsLineDefInside (int ldnum, int x0, int y0, int x1, int y1) /* SWAP - needs Vertices & LineDefs */ >+{ >+int lx0 = Vertices[LineDefs[ldnum].start].x; >+int ly0 = Vertices[LineDefs[ldnum].start].y; >+int lx1 = Vertices[LineDefs[ldnum].end].x; >+int ly1 = Vertices[LineDefs[ldnum].end].y; >+int i; >+ >+/* do you like mathematics? */ >+if (lx0 >= x0 && lx0 <= x1 && ly0 >= y0 && ly0 <= y1) >+ return 1; /* the linedef start is entirely inside the square */ >+if (lx1 >= x0 && lx1 <= x1 && ly1 >= y0 && ly1 <= y1) >+ return 1; /* the linedef end is entirely inside the square */ >+if ((ly0 > y0) != (ly1 > y0)) >+ { >+ i = lx0 + (int) ((long) (y0 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0)); >+ if (i >= x0 && i <= x1) >+ return true; /* the linedef crosses the y0 side (left) */ >+ } >+if ((ly0 > y1) != (ly1 > y1)) >+ { >+ i = lx0 + (int) ((long) (y1 - ly0) * (long) (lx1 - lx0) / (long) (ly1 - ly0)); >+ if (i >= x0 && i <= x1) >+ return true; /* the linedef crosses the y1 side (right) */ >+ } >+if ((lx0 > x0) != (lx1 > x0)) >+ { >+ i = ly0 + (int) ((long) (x0 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0)); >+ if (i >= y0 && i <= y1) >+ return true; /* the linedef crosses the x0 side (down) */ >+ } >+if ((lx0 > x1) != (lx1 > x1)) >+ { >+ i = ly0 + (int) ((long) (x1 - lx0) * (long) (ly1 - ly0) / (long) (lx1 - lx0)); >+ if (i >= y0 && i <= y1) >+ return true; /* the linedef crosses the x1 side (up) */ >+ } >+return false; >+} >+ >+ >+ >+/* >+ get the sector number of the sidedef opposite to this sidedef >+ (returns -1 if it cannot be found) >+*/ >+int GetOppositeSector (int ld1, bool firstside) /* SWAP! */ >+{ >+int x0, y0, dx0, dy0; >+int x1, y1, dx1, dy1; >+int x2, y2, dx2, dy2; >+int ld2, dist; >+int bestld, bestdist, bestmdist; >+ >+/* get the coords for this LineDef */ >+ObjectsNeeded (OBJ_LINEDEFS, OBJ_VERTICES, 0); >+x0 = Vertices[LineDefs[ld1].start].x; >+y0 = Vertices[LineDefs[ld1].start].y; >+dx0 = Vertices[LineDefs[ld1].end].x - x0; >+dy0 = Vertices[LineDefs[ld1].end].y - y0; >+ >+/* find the normal vector for this LineDef */ >+x1 = (dx0 + x0 + x0) / 2; >+y1 = (dy0 + y0 + y0) / 2; >+if (firstside) >+ { >+ dx1 = dy0; >+ dy1 = -dx0; >+ } >+else >+ { >+ dx1 = -dy0; >+ dy1 = dx0; >+ } >+ >+bestld = -1; >+/* use a parallel to an axis instead of the normal vector (faster method) */ >+if (abs (dy1) > abs (dx1)) >+ { >+ if (dy1 > 0) >+ { >+ /* get the nearest LineDef in that direction (increasing Y's: North) */ >+ bestdist = 32767; >+ bestmdist = 32767; >+ for (ld2 = 0; ld2 < NumLineDefs; ld2++) >+ if (ld2 != ld1 && ((Vertices[LineDefs[ld2].start].x > x1) >+ != (Vertices[LineDefs[ld2].end].x > x1))) >+ { >+ x2 = Vertices[LineDefs[ld2].start].x; >+ y2 = Vertices[LineDefs[ld2].start].y; >+ dx2 = Vertices[LineDefs[ld2].end].x - x2; >+ dy2 = Vertices[LineDefs[ld2].end].y - y2; >+ dist = y2 + (int) ((long) (x1 - x2) * (long) dy2 / (long) dx2); >+ if (dist > y1 && (dist < bestdist >+ || (dist == bestdist && (y2 + dy2 / 2) < bestmdist))) >+ { >+ bestld = ld2; >+ bestdist = dist; >+ bestmdist = y2 + dy2 / 2; >+ } >+ } >+ } >+ else >+ { >+ /* get the nearest LineDef in that direction (decreasing Y's: South) */ >+ bestdist = -32767; >+ bestmdist = -32767; >+ for (ld2 = 0; ld2 < NumLineDefs; ld2++) >+ if (ld2 != ld1 && ((Vertices[LineDefs[ld2].start].x > x1) >+ != (Vertices[LineDefs[ld2].end].x > x1))) >+ { >+ x2 = Vertices[LineDefs[ld2].start].x; >+ y2 = Vertices[LineDefs[ld2].start].y; >+ dx2 = Vertices[LineDefs[ld2].end].x - x2; >+ dy2 = Vertices[LineDefs[ld2].end].y - y2; >+ dist = y2 + (int) ((long) (x1 - x2) * (long) dy2 / (long) dx2); >+ if (dist < y1 && (dist > bestdist >+ || (dist == bestdist && (y2 + dy2 / 2) > bestmdist))) >+ { >+ bestld = ld2; >+ bestdist = dist; >+ bestmdist = y2 + dy2 / 2; >+ } >+ } >+ } >+ } >+else >+ { >+ if (dx1 > 0) >+ { >+ /* get the nearest LineDef in that direction (increasing X's: East) */ >+ bestdist = 32767; >+ bestmdist = 32767; >+ for (ld2 = 0; ld2 < NumLineDefs; ld2++) >+ if (ld2 != ld1 && ((Vertices[LineDefs[ld2].start].y > y1) >+ != (Vertices[LineDefs[ld2].end].y > y1))) >+ { >+ x2 = Vertices[LineDefs[ld2].start].x; >+ y2 = Vertices[LineDefs[ld2].start].y; >+ dx2 = Vertices[LineDefs[ld2].end].x - x2; >+ dy2 = Vertices[LineDefs[ld2].end].y - y2; >+ dist = x2 + (int) ((long) (y1 - y2) * (long) dx2 / (long) dy2); >+ if (dist > x1 && (dist < bestdist >+ || (dist == bestdist && (x2 + dx2 / 2) < bestmdist))) >+ { >+ bestld = ld2; >+ bestdist = dist; >+ bestmdist = x2 + dx2 / 2; >+ } >+ } >+ } >+ else >+ { >+ /* get the nearest LineDef in that direction (decreasing X's: West) */ >+ bestdist = -32767; >+ bestmdist = -32767; >+ for (ld2 = 0; ld2 < NumLineDefs; ld2++) >+ if (ld2 != ld1 && ((Vertices[LineDefs[ld2].start].y > y1) >+ != (Vertices[LineDefs[ld2].end].y > y1))) >+ { >+ x2 = Vertices[LineDefs[ld2].start].x; >+ y2 = Vertices[LineDefs[ld2].start].y; >+ dx2 = Vertices[LineDefs[ld2].end].x - x2; >+ dy2 = Vertices[LineDefs[ld2].end].y - y2; >+ dist = x2 + (int) ((long) (y1 - y2) * (long) dx2 / (long) dy2); >+ if (dist < x1 && (dist > bestdist >+ || (dist == bestdist && (x2 + dx2 / 2) > bestmdist))) >+ { >+ bestld = ld2; >+ bestdist = dist; >+ bestmdist = x2 + dx2 / 2; >+ } >+ } >+ } >+ } >+ >+/* no intersection: the LineDef was pointing outwards! */ >+if (bestld < 0) >+ return -1; >+ >+/* now look if this LineDef has a SideDef bound to one sector */ >+if (abs (dy1) > abs (dx1)) >+ { >+ if ((Vertices[LineDefs[bestld].start].x >+ < Vertices[LineDefs[bestld].end].x) == (dy1 > 0)) >+ x0 = LineDefs[bestld].sidedef1; >+ else >+ x0 = LineDefs[bestld].sidedef2; >+ } >+else >+ { >+ if ((Vertices[LineDefs[bestld].start].y >+ < Vertices[LineDefs[bestld].end].y) != (dx1 > 0)) >+ x0 = LineDefs[bestld].sidedef1; >+ else >+ x0 = LineDefs[bestld].sidedef2; >+ } >+ >+/* there is no SideDef on this side of the LineDef! */ >+if (x0 < 0) >+ return -1; >+ >+/* OK, we got it -- return the Sector number */ >+ObjectsNeeded (OBJ_SIDEDEFS, 0); >+return SideDefs[x0].sector; >+} >+ >+ >+ >+/* >+ copy a group of objects to a new position >+*/ >+void CopyObjects (int objtype, SelPtr obj) /* SWAP! */ >+{ >+int n, m; >+SelPtr cur; >+SelPtr list1, list2; >+SelPtr ref1, ref2; >+ >+if (! obj) >+ return; >+ObjectsNeeded (objtype, 0); >+/* copy the object(s) */ >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ for (cur = obj; cur; cur = cur->next) >+ { >+ InsertObject (OBJ_THINGS, cur->objnum, Things[cur->objnum].xpos, >+ Things[cur->objnum].ypos); >+ cur->objnum = NumThings - 1; >+ } >+ MadeChanges = 1; >+ break; >+ >+ case OBJ_VERTICES: >+ for (cur = obj; cur; cur = cur->next) >+ { >+ InsertObject (OBJ_VERTICES, cur->objnum, Vertices[cur->objnum].x, >+ Vertices[cur->objnum].y); >+ cur->objnum = NumVertices - 1; >+ } >+ MadeChanges = 1; >+ MadeMapChanges = 1; >+ break; >+ >+ case OBJ_LINEDEFS: >+ list1 = 0; >+ list2 = 0; >+ >+ // Create the linedefs and maybe the sidedefs >+ for (cur = obj; cur; cur = cur->next) >+ { >+ int old = cur->objnum; // No. of original linedef >+ int New; // No. of duplicate linedef >+ >+ InsertObject (OBJ_LINEDEFS, old, 0, 0); >+ New = NumLineDefs - 1; >+ >+ if (copy_linedef_reuse_sidedefs) >+ { >+ /* AYM 1997-07-25: not very orthodox (the New linedef and >+ the old one use the same sidedefs). but, in the case where >+ you're copying into the same sector, it's much better than >+ having to create the New sidedefs manually. plus it saves >+ space in the .wad and also it makes editing easier (editing >+ one sidedef impacts all linedefs that use it). */ >+ LineDefs[New].sidedef1 = LineDefs[old].sidedef1; >+ LineDefs[New].sidedef2 = LineDefs[old].sidedef2; >+ } >+ else >+ { >+ /* AYM 1998-11-08: duplicate sidedefs too. >+ DEU 5.21 just left the sidedef references to -1. */ >+ if (is_sidedef (LineDefs[old].sidedef1)) >+ { >+ InsertObject (OBJ_SIDEDEFS, LineDefs[old].sidedef1, 0, 0); >+ LineDefs[New].sidedef1 = NumSideDefs - 1; >+ } >+ if (is_sidedef (LineDefs[old].sidedef2)) >+ { >+ InsertObject (OBJ_SIDEDEFS, LineDefs[old].sidedef2, 0, 0); >+ LineDefs[New].sidedef2 = NumSideDefs - 1; >+ } >+ } >+ cur->objnum = New; >+ if (!IsSelected (list1, LineDefs[New].start)) >+ { >+ SelectObject (&list1, LineDefs[New].start); >+ SelectObject (&list2, LineDefs[New].start); >+ } >+ if (!IsSelected (list1, LineDefs[New].end)) >+ { >+ SelectObject (&list1, LineDefs[New].end); >+ SelectObject (&list2, LineDefs[New].end); >+ } >+ } >+ >+ // Create the vertices >+ CopyObjects (OBJ_VERTICES, list2); >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ >+ // Update the references to the vertices >+ for (ref1 = list1, ref2 = list2; >+ ref1 && ref2; >+ ref1 = ref1->next, ref2 = ref2->next) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ { >+ if (ref1->objnum == LineDefs[cur->objnum].start) >+ LineDefs[cur->objnum].start = ref2->objnum; >+ if (ref1->objnum == LineDefs[cur->objnum].end) >+ LineDefs[cur->objnum].end = ref2->objnum; >+ } >+ } >+ ForgetSelection (&list1); >+ ForgetSelection (&list2); >+ break; >+ >+ case OBJ_SECTORS: >+ ObjectsNeeded (OBJ_LINEDEFS, OBJ_SIDEDEFS, 0); >+ list1 = 0; >+ list2 = 0; >+ // Create the linedefs (and vertices) >+ for (cur = obj; cur; cur = cur->next) >+ { >+ for (n = 0; n < NumLineDefs; n++) >+ if ((((m = LineDefs[n].sidedef1) >= 0 >+ && SideDefs[m].sector == cur->objnum) >+ || ((m = LineDefs[n].sidedef2) >= 0 >+ && SideDefs[m].sector == cur->objnum)) >+ && ! IsSelected (list1, n)) >+ { >+ SelectObject (&list1, n); >+ SelectObject (&list2, n); >+ } >+ } >+ CopyObjects (OBJ_LINEDEFS, list2); >+ /* create the sidedefs */ >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ for (ref1 = list1, ref2 = list2; >+ ref1 && ref2; >+ ref1 = ref1->next, ref2 = ref2->next) >+ { >+ if ((n = LineDefs[ref1->objnum].sidedef1) >= 0) >+ { >+ InsertObject (OBJ_SIDEDEFS, n, 0, 0); >+ n = NumSideDefs - 1; >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ LineDefs[ref2->objnum].sidedef1 = n; >+ } >+ if ((m = LineDefs[ref1->objnum].sidedef2) >= 0) >+ { >+ InsertObject (OBJ_SIDEDEFS, m, 0, 0); >+ m = NumSideDefs - 1; >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ LineDefs[ref2->objnum].sidedef2 = m; >+ } >+ ref1->objnum = n; >+ ref2->objnum = m; >+ } >+ /* create the Sectors */ >+ for (cur = obj; cur; cur = cur->next) >+ { >+ InsertObject (OBJ_SECTORS, cur->objnum, 0, 0); >+ ObjectsNeeded (OBJ_SIDEDEFS, 0); >+ for (ref1 = list1, ref2 = list2; >+ ref1 && ref2; >+ ref1 = ref1->next, ref2 = ref2->next) >+ { >+ if (ref1->objnum >= 0 >+ && SideDefs[ref1->objnum].sector == cur->objnum) >+ SideDefs[ref1->objnum].sector = NumSectors - 1; >+ if (ref2->objnum >= 0 >+ && SideDefs[ref2->objnum].sector == cur->objnum) >+ SideDefs[ref2->objnum].sector = NumSectors - 1; >+ } >+ cur->objnum = NumSectors - 1; >+ } >+ ForgetSelection (&list1); >+ ForgetSelection (&list2); >+ break; >+ } >+} >+ >+ >+ >+/* >+ * MoveObjectsToCoords >+ * Move a group of objects to a new position >+ * >+ * You must first call it with obj == NULL and newx and newy >+ * set to the coordinates of the reference point (E.G. the >+ * object being dragged). >+ * Then, every time the object being dragged has changed its >+ * coordinates, call the it again with newx and newy set to >+ * the new position and obj set to the selection. >+ * >+ * Returns <>0 iff an object was moved. >+ */ >+bool MoveObjectsToCoords ( >+ int objtype, >+ SelPtr obj, >+ int newx, >+ int newy, >+ int grid) /* SWAP! */ >+{ >+int dx, dy; >+SelPtr cur, vertices; >+static int refx, refy; /* previous position */ >+ >+ObjectsNeeded (objtype, 0); >+if (grid > 0) >+ { >+ newx = (newx + grid / 2) & ~(grid - 1); >+ newy = (newy + grid / 2) & ~(grid - 1); >+ } >+ >+// Only update the reference point ? >+if (! obj) >+ { >+ refx = newx; >+ refy = newy; >+ return true; >+ } >+ >+/* compute the displacement */ >+dx = newx - refx; >+dy = newy - refy; >+/* nothing to do? */ >+if (dx == 0 && dy == 0) >+ return false; >+ >+/* move the object(s) */ >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ for (cur = obj; cur; cur = cur->next) >+ { >+ Things[cur->objnum].xpos += dx; >+ Things[cur->objnum].ypos += dy; >+ } >+ refx = newx; >+ refy = newy; >+ MadeChanges = 1; >+ break; >+ >+ case OBJ_VERTICES: >+ for (cur = obj; cur; cur = cur->next) >+ { >+ Vertices[cur->objnum].x += dx; >+ Vertices[cur->objnum].y += dy; >+ } >+ refx = newx; >+ refy = newy; >+ MadeChanges = 1; >+ MadeMapChanges = 1; >+ break; >+ >+ case OBJ_LINEDEFS: >+ vertices = list_vertices_of_linedefs (obj); >+ MoveObjectsToCoords (OBJ_VERTICES, vertices, newx, newy, grid); >+ ForgetSelection (&vertices); >+ break; >+ >+ case OBJ_SECTORS: >+ ObjectsNeeded (OBJ_LINEDEFS, OBJ_SIDEDEFS, 0); >+ vertices = list_vertices_of_sectors (obj); >+ MoveObjectsToCoords (OBJ_VERTICES, vertices, newx, newy, grid); >+ ForgetSelection (&vertices); >+ break; >+ } >+return true; >+} >+ >+ >+ >+/* >+ get the coordinates (approx.) of an object >+*/ >+void GetObjectCoords (int objtype, int objnum, int *xpos, int *ypos) /* SWAP! */ >+{ >+int n, v1, v2, sd1, sd2; >+long accx, accy, num; >+ >+switch (objtype) >+ { >+ case OBJ_THINGS: >+ if (! is_thing (objnum)) // Can't happen >+ { >+ nf_bug ("GetObjectCoords: bad thing# %d", objnum); >+ *xpos = 0; >+ *ypos = 0; >+ return; >+ } >+ ObjectsNeeded (OBJ_THINGS, 0); >+ *xpos = Things[objnum].xpos; >+ *ypos = Things[objnum].ypos; >+ break; >+ >+ case OBJ_VERTICES: >+ if (! is_vertex (objnum)) // Can't happen >+ { >+ nf_bug ("GetObjectCoords: bad vertex# %d", objnum); >+ *xpos = 0; >+ *ypos = 0; >+ return; >+ } >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ *xpos = Vertices[objnum].x; >+ *ypos = Vertices[objnum].y; >+ break; >+ >+ case OBJ_LINEDEFS: >+ if (! is_linedef (objnum)) // Can't happen >+ { >+ nf_bug ("GetObjectCoords: bad linedef# %d", objnum); >+ *xpos = 0; >+ *ypos = 0; >+ return; >+ } >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ v1 = LineDefs[objnum].start; >+ v2 = LineDefs[objnum].end; >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ *xpos = (Vertices[v1].x + Vertices[v2].x) / 2; >+ *ypos = (Vertices[v1].y + Vertices[v2].y) / 2; >+ break; >+ >+ case OBJ_SIDEDEFS: >+ if (! is_sidedef (objnum)) // Can't happen >+ { >+ nf_bug ("GetObjectCoords: bad sidedef# %d", objnum); >+ *xpos = 0; >+ *ypos = 0; >+ return; >+ } >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ for (n = 0; n < NumLineDefs; n++) >+ if (LineDefs[n].sidedef1 == objnum || LineDefs[n].sidedef2 == objnum) >+ { >+ v1 = LineDefs[n].start; >+ v2 = LineDefs[n].end; >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ *xpos = (Vertices[v1].x + Vertices[v2].x) / 2; >+ *ypos = (Vertices[v1].y + Vertices[v2].y) / 2; >+ return; >+ } >+ *xpos = (MapMinX + MapMaxX) / 2; >+ *ypos = (MapMinY + MapMaxY) / 2; >+ // FIXME is the fall through intentional ? -- AYM 2000-11-08 >+ >+ case OBJ_SECTORS: >+ if (! is_sector (objnum)) // Can't happen >+ { >+ nf_bug ("GetObjectCoords: bad sector# %d", objnum); >+ *xpos = 0; >+ *ypos = 0; >+ return; >+ } >+ accx = 0L; >+ accy = 0L; >+ num = 0L; >+ for (n = 0; n < NumLineDefs; n++) >+ { >+ ObjectsNeeded (OBJ_LINEDEFS, 0); >+ sd1 = LineDefs[n].sidedef1; >+ sd2 = LineDefs[n].sidedef2; >+ v1 = LineDefs[n].start; >+ v2 = LineDefs[n].end; >+ ObjectsNeeded (OBJ_SIDEDEFS, 0); >+ if ((sd1 >= 0 && SideDefs[sd1].sector == objnum) >+ || (sd2 >= 0 && SideDefs[sd2].sector == objnum)) >+ { >+ ObjectsNeeded (OBJ_VERTICES, 0); >+ /* if the Sector is closed, all Vertices will be counted twice */ >+ accx += (long) Vertices[v1].x; >+ accy += (long) Vertices[v1].y; >+ num++; >+ accx += (long) Vertices[v2].x; >+ accy += (long) Vertices[v2].y; >+ num++; >+ } >+ } >+ if (num > 0) >+ { >+ *xpos = (int) ((accx + num / 2L) / num); >+ *ypos = (int) ((accy + num / 2L) / num); >+ } >+ else >+ { >+ *xpos = (MapMinX + MapMaxX) / 2; >+ *ypos = (MapMinY + MapMaxY) / 2; >+ } >+ break; >+ >+ default: >+ nf_bug ("GetObjectCoords: bad objtype %d", objtype); // Can't happen >+ *xpos = 0; >+ *ypos = 0; >+ } >+} >+ >+ >+ >+/* >+ find a free tag number >+*/ >+int FindFreeTag () /* SWAP! */ >+{ >+int tag, n; >+bool ok; >+ >+ObjectsNeeded (OBJ_LINEDEFS, OBJ_SECTORS, 0); >+tag = 1; >+ok = false; >+while (! ok) >+ { >+ ok = true; >+ for (n = 0; n < NumLineDefs; n++) >+ if (LineDefs[n].tag == tag) >+ { >+ ok = false; >+ break; >+ } >+ if (ok) >+ for (n = 0; n < NumSectors; n++) >+ if (Sectors[n].tag == tag) >+ { >+ ok = false; >+ break; >+ } >+ tag++; >+ } >+return tag - 1; >+} >+ >+ >diff -Nru yadex-1.7.0-orig/src/pic2img.cc yadex-1.7.0/src/pic2img.cc >--- yadex-1.7.0-orig/src/pic2img.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/pic2img.cc 2012-06-17 18:47:42.122880103 -0400 >@@ -192,7 +192,7 @@ > > ColumnData = (u8 *) GetMemory (TEX_COLUMNBUFFERSIZE); > /* FIXME DOS and pic_width_ > 16000 */ >-NeededOffsets = (i32 *) GetMemory ((long) pic_width_ * 4); >+NeededOffsets = (i32 *) GetMemory ((long) pic_width_ * (sizeof(i32))); > > if (long_offsets) > dir->wadfile->read_i32 (NeededOffsets, pic_width_); >diff -Nru yadex-1.7.0-orig/src/r_images.cc yadex-1.7.0/src/r_images.cc >--- yadex-1.7.0-orig/src/r_images.cc 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/r_images.cc 2012-06-17 18:47:42.122880103 -0400 >@@ -0,0 +1,400 @@ >+/* >+ * r_images.cc >+ * AJA 2002-04-23 (based on textures.cc and flats.cc) >+ */ >+ >+ >+/* >+This file is part of Yadex. >+ >+Yadex incorporates code from DEU 5.21 that was put in the public domain in >+1994 by Raphaël Quinet and Brendon Wyber. >+ >+The rest of Yadex is Copyright © 1997-2000 André Majorel. >+ >+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. >+*/ >+ >+ >+#include "yadex.h" >+#ifdef Y_X11 >+#include <X11/Xlib.h> >+#endif >+#include "dialog.h" >+#include "game.h" /* yg_picture_format */ >+#include "gfx.h" >+#include "levels.h" >+#include "lists.h" >+#include "patchdir.h" >+#include "pic2img.h" >+#include "sticker.h" >+#include "flats.h" >+#include "textures.h" >+#include "wadfile.h" >+#include "wads.h" >+#include "wadres.h" >+#include "wstructs.h" >+ >+#include "r_images.h" >+ >+ >+/* >+ * flat_list_entry_match >+ * Function used by bsearch() to locate a particular >+ * flat in the FTexture. >+ */ >+static int flat_list_entry_match (const void *key, const void *flat_list_entry) >+{ >+return y_strnicmp ((const char *) key, >+ ((const flat_list_entry_t *) flat_list_entry)->name, >+ WAD_FLAT_NAME); >+} >+ >+ >+/* >+ * load a flat into a new image. NULL if not found. >+ */ >+ >+Img * Flat2Img (const wad_flat_name_t& fname) >+{ >+char name[WAD_FLAT_NAME + 1]; >+strncpy (name, fname, WAD_FLAT_NAME); >+name[WAD_FLAT_NAME] = 0; >+ >+flat_list_entry_t *flat = (flat_list_entry_t *) >+ bsearch (name, flat_list, NumFTexture, sizeof *flat_list, >+ flat_list_entry_match); >+ >+if (! flat) // Not found in list >+ return 0; >+ >+int width = DOOM_FLAT_WIDTH; // Big deal ! >+int height = DOOM_FLAT_HEIGHT; >+ >+const Wad_file *wadfile = flat->wadfile; >+wadfile->seek (flat->offset); >+ >+Img *img = new Img (width, height, false); >+ >+wadfile->read_bytes (img->wbuf (), (long) width * height); >+ >+return img; >+} >+ >+ >+/* >+ * load a wall texture ("TEXTURE1" or "TEXTURE2" object) into an image. >+ * Returns NULL if not found or error. >+ */ >+ >+Img * Tex2Img (const wad_tex_name_t& texname) >+{ >+MDirPtr dir = 0; /* main directory pointer to the TEXTURE* entries */ >+i32 *offsets; /* array of offsets to texture names */ >+int n; /* general counter */ >+i16 width, height; /* size of the texture */ >+i16 npatches; /* number of wall patches used to build this texture */ >+i32 numtex; /* number of texture names in TEXTURE* list */ >+i32 texofs; /* offset in the wad file to the texture data */ >+char tname[WAD_TEX_NAME + 1]; /* texture name */ >+char picname[WAD_PIC_NAME + 1]; /* wall patch name */ >+bool have_dummy_bytes; >+int header_size; >+int item_size; >+ >+char name[WAD_TEX_NAME + 1]; >+strncpy (name, texname, WAD_TEX_NAME); >+name[WAD_TEX_NAME] = 0; >+ >+// Iwad-dependant details >+if (yg_texture_format == YGTF_NAMELESS) >+ { >+ have_dummy_bytes = true; >+ header_size = 14; >+ item_size = 10; >+ } >+else if (yg_texture_format == YGTF_NORMAL) >+ { >+ have_dummy_bytes = true; >+ header_size = 14; >+ item_size = 10; >+ } >+else if (yg_texture_format == YGTF_STRIFE11) >+ { >+ have_dummy_bytes = false; >+ header_size = 10; >+ item_size = 6; >+ } >+else >+ { >+ nf_bug ("Bad texture format %d.", (int) yg_texture_format); >+ return 0; >+ } >+ >+/* offset for texture we want. */ >+texofs = 0; >+// Doom alpha 0.4 : "TEXTURES", no names >+if (yg_texture_lumps == YGTL_TEXTURES && yg_texture_format == YGTF_NAMELESS) >+ { >+ dir = FindMasterDir (MasterDir, "TEXTURES"); >+ if (dir != NULL) >+ { >+ dir->wadfile->seek (dir->dir.start); >+ dir->wadfile->read_i32 (&numtex); >+ if (WAD_TEX_NAME < 7) nf_bug ("WAD_TEX_NAME too small"); // Sanity >+ if (! y_strnicmp (name, "TEX", 3) >+ && isdigit (name[3]) >+ && isdigit (name[4]) >+ && isdigit (name[5]) >+ && isdigit (name[6]) >+ && name[7] == '\0') >+ { >+ long num; >+ if (sscanf (name + 3, "%4ld", &num) == 1 >+ && num >= 0 && num < numtex) >+ { >+ dir->wadfile->seek (dir->dir.start + 4 + 4 * num); >+ dir->wadfile->read_i32 (&texofs); >+ texofs += dir->dir.start; >+ } >+ } >+ } >+ } >+// Doom alpha 0.5 : only "TEXTURES" >+else if (yg_texture_lumps == YGTL_TEXTURES >+ && (yg_texture_format == YGTF_NORMAL || yg_texture_format == YGTF_STRIFE11)) >+ { >+ // Is it in TEXTURES ? >+ dir = FindMasterDir (MasterDir, "TEXTURES"); >+ if (dir != NULL) // (Theoretically, it should always exist) >+ { >+ dir->wadfile->seek (dir->dir.start); >+ dir->wadfile->read_i32 (&numtex); >+ /* read in the offsets for texture1 names and info. */ >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); >+ dir->wadfile->read_i32 (offsets, numtex); >+ for (n = 0; n < numtex && !texofs; n++) >+ { >+ dir->wadfile->seek (dir->dir.start + offsets[n]); >+ dir->wadfile->read_bytes (&tname, WAD_TEX_NAME); >+ if (!y_strnicmp (tname, name, WAD_TEX_NAME)) >+ texofs = dir->dir.start + offsets[n]; >+ } >+ FreeMemory (offsets); >+ } >+ } >+// Other iwads : "TEXTURE1" and "TEXTURE2" >+else if (yg_texture_lumps == YGTL_NORMAL >+ && (yg_texture_format == YGTF_NORMAL || yg_texture_format == YGTF_STRIFE11)) >+ { >+ // Is it in TEXTURE1 ? >+ dir = FindMasterDir (MasterDir, "TEXTURE1"); >+ if (dir != NULL) // (Theoretically, it should always exist) >+ { >+ dir->wadfile->seek (dir->dir.start); >+ dir->wadfile->read_i32 (&numtex); >+ /* read in the offsets for texture1 names and info. */ >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); >+ dir->wadfile->read_i32 (offsets, numtex); >+ for (n = 0; n < numtex && !texofs; n++) >+ { >+ dir->wadfile->seek (dir->dir.start + offsets[n]); >+ dir->wadfile->read_bytes (&tname, WAD_TEX_NAME); >+ if (!y_strnicmp (tname, name, WAD_TEX_NAME)) >+ texofs = dir->dir.start + offsets[n]; >+ } >+ FreeMemory (offsets); >+ } >+ // Well, then is it in TEXTURE2 ? >+ if (texofs == 0) >+ { >+ dir = FindMasterDir (MasterDir, "TEXTURE2"); >+ if (dir != NULL) // Doom II has no TEXTURE2 >+ { >+ dir->wadfile->seek (dir->dir.start); >+ dir->wadfile->read_i32 (&numtex); >+ /* read in the offsets for texture2 names */ >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); >+ dir->wadfile->read_i32 (offsets, numtex); >+ for (n = 0; n < numtex && !texofs; n++) >+ { >+ dir->wadfile->seek (dir->dir.start + offsets[n]); >+ dir->wadfile->read_bytes (&tname, WAD_TEX_NAME); >+ if (!y_strnicmp (tname, name, WAD_TEX_NAME)) >+ texofs = dir->dir.start + offsets[n]; >+ } >+ FreeMemory (offsets); >+ } >+ } >+ } >+else >+ nf_bug ("Invalid texture_format/texture_lumps combination."); >+ >+/* texture name not found */ >+if (texofs == 0) >+ return 0; >+ >+/* read the info for this texture */ >+i32 header_ofs; >+if (yg_texture_format == YGTF_NAMELESS) >+ header_ofs = texofs; >+else >+ header_ofs = texofs + WAD_TEX_NAME; >+dir->wadfile->seek (header_ofs + 4); >+dir->wadfile->read_i16 (&width); >+dir->wadfile->read_i16 (&height); >+if (have_dummy_bytes) >+ { >+ i16 dummy; >+ dir->wadfile->read_i16 (&dummy); >+ dir->wadfile->read_i16 (&dummy); >+ } >+dir->wadfile->read_i16 (&npatches); >+ >+/* Compose the texture */ >+Img *texbuf = new Img (width, height, false); >+ >+/* Paste onto the buffer all the patches that the texture is >+ made of. */ >+for (n = 0; n < npatches; n++) >+ { >+ i16 xofs, yofs; // offset in texture space for the patch >+ i16 pnameind; // index of patch in PNAMES >+ >+ dir->wadfile->seek (header_ofs + header_size + (long) n * item_size); >+ dir->wadfile->read_i16 (&xofs); >+ dir->wadfile->read_i16 (&yofs); >+ dir->wadfile->read_i16 (&pnameind); >+ >+ if (have_dummy_bytes) >+ { >+ i16 stepdir; >+ i16 colormap; >+ dir->wadfile->read_i16 (&stepdir); // Always 1, unused. >+ dir->wadfile->read_i16 (&colormap); // Always 0, unused. >+ } >+ >+ /* AYM 1998-08-08: Yes, that's weird but that's what Doom >+ does. Without these two lines, the few textures that have >+ patches with negative y-offsets (BIGDOOR7, SKY1, TEKWALL1, >+ TEKWALL5 and a few others) would not look in the texture >+ viewer quite like in Doom. This should be mentioned in >+ the UDS, by the way. */ >+ if (yofs < 0) >+ yofs = 0; >+ >+ Lump_loc loc; >+ { >+ wad_pic_name_t *wname = patch_dir.name_for_num (pnameind); >+ if (wname == 0) >+ { >+ warn ("texture \"%.*s\": patch %2d has bad index %d.\n", >+ WAD_TEX_NAME, tname, (int) n, (int) pnameind); >+ continue; >+ } >+ patch_dir.loc_by_name ((const char *) *wname, loc); >+ *picname = '\0'; >+ strncat (picname, (const char *) *wname, sizeof picname - 1); >+ } >+ >+ if (LoadPicture (*texbuf, picname, loc, xofs, yofs, 0, 0)) >+ warn ("texture \"%.*s\": patch \"%.*s\" not found.\n", >+ WAD_TEX_NAME, tname, WAD_PIC_NAME, picname); >+ } >+ >+return texbuf; >+} >+ >+ >+/* --- ImageCache methods --- */ >+ >+ >+Img *ImageCache::GetFlat (const wad_flat_name_t& fname) >+{ >+std::string f_str = WadToString(fname); >+ >+flat_map_t::iterator P = flats.find (f_str); >+ >+if (P != flats.end ()) >+ return P->second; >+ >+// flat not in the list yet. Add it. >+ >+Img *result = Flat2Img (fname); >+flats[f_str] = result; >+ >+// note that a NULL return from Flat2Img is OK, it means that no >+// such flat exists. Our renderer will revert to using a solid >+// colour. >+ >+return result; >+} >+ >+ >+Img *ImageCache::GetTex (const wad_tex_name_t& tname) >+{ >+if (tname[0] == 0 || tname[0] == '-') >+ return 0; >+ >+std::string t_str = WadToString(tname); >+ >+tex_map_t::iterator P = textures.find (t_str); >+ >+if (P != textures.end ()) >+ return P->second; >+ >+// texture not in the list yet. Add it. >+ >+Img *result = Tex2Img (tname); >+textures[t_str] = result; >+ >+// note that a NULL return from Tex2Img is OK, it means that no >+// such texture exists. Our renderer will revert to using a solid >+// colour. >+ >+return result; >+} >+ >+ >+Img *ImageCache::GetSprite (const wad_ttype_t& type) >+{ >+sprite_map_t::iterator P = sprites.find (type); >+ >+if (P != sprites.end ()) >+ return P->second; >+ >+// sprite not in the list yet. Add it. >+ >+Img *result = 0; >+ >+const char *sprite_root = get_thing_sprite (type); >+if (sprite_root) >+ { >+ Lump_loc loc; >+ wad_res.sprites.loc_by_root (sprite_root, loc); >+ result = new Img (); >+ >+ if (LoadPicture (*result, sprite_root, loc, 0, 0) != 0) >+ { >+ delete result; >+ result = 0; >+ } >+ } >+ >+// note that a NULL image is OK. Our renderer will just ignore the >+// missing sprite. >+ >+sprites[type] = result; >+return result; >+} >diff -Nru yadex-1.7.0-orig/src/r_images.h yadex-1.7.0/src/r_images.h >--- yadex-1.7.0-orig/src/r_images.h 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/r_images.h 2012-06-17 18:47:12.491693205 -0400 >@@ -0,0 +1,69 @@ >+/* >+ * r_images.h >+ * AJA 2002-04-27 >+ */ >+ >+ >+#ifndef YH_R_IMAGES /* DO NOT INSERT ANYTHING BEFORE THIS LINE */ >+#define YH_R_IMAGES >+ >+ >+#include <map> >+#include <algorithm> >+#include <string> >+ >+ >+struct ImageCache >+{ >+public: >+ typedef std::map<std::string, Img *> flat_map_t; >+ typedef std::map<std::string, Img *> tex_map_t; >+ typedef std::map<wad_ttype_t, Img *> sprite_map_t; >+ >+ flat_map_t flats; >+ tex_map_t textures; >+ sprite_map_t sprites; >+ >+ static std::string WadToString(const wad_flat_name_t& fname) >+ { >+ int len; >+ >+ for (len = 0; len < WAD_NAME && fname[len]; len++) >+ { } >+ >+ return std::string(fname, len); >+ } >+ >+ static void DeleteFlat(const flat_map_t::value_type& P) >+ { >+ delete P.second; >+ } >+ >+ static void DeleteTex(const tex_map_t::value_type& P) >+ { >+ delete P.second; >+ } >+ >+ static void DeleteSprite(const sprite_map_t::value_type& P) >+ { >+ delete P.second; >+ } >+ >+ ~ImageCache () >+ { >+ std::for_each (flats.begin (), flats.end (), DeleteFlat); >+ std::for_each (textures.begin (), textures.end (), DeleteTex); >+ std::for_each (sprites.begin (), sprites.end (), DeleteSprite); >+ >+ flats.clear (); >+ textures.clear (); >+ sprites.clear (); >+ } >+ >+ Img *GetFlat (const wad_flat_name_t& fname); >+ Img *GetTex (const wad_tex_name_t& tname); >+ Img *GetSprite (const wad_ttype_t& type); >+}; >+ >+ >+#endif /* DO NOT ADD ANYTHING AFTER THIS LINE */ >diff -Nru yadex-1.7.0-orig/src/r_render.cc yadex-1.7.0/src/r_render.cc >--- yadex-1.7.0-orig/src/r_render.cc 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/r_render.cc 2012-06-17 18:47:12.491693205 -0400 >@@ -0,0 +1,1275 @@ >+/* >+ * r_render.cc >+ * 3D Rendering >+ * AJA 2002-04-21 >+ */ >+ >+ >+/* >+This file is part of Yadex. >+ >+Yadex incorporates code from DEU 5.21 that was put in the public domain in >+1994 by Raphaël Quinet and Brendon Wyber. >+ >+The rest of Yadex is Copyright © 1997-2000 André Majorel. >+ >+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. >+*/ >+ >+ >+#include "yadex.h" >+ >+#include <math.h> >+#include <vector> >+#include <map> >+#include <algorithm> >+ >+#ifdef Y_X11 >+#include <X11/Xlib.h> >+#include <X11/Xutil.h> >+#endif >+#include "levels.h" >+#include "wstructs.h" >+#include "gfx.h" >+#include "img.h" >+#include "sticker.h" >+#include "gamesky.h" >+#include "things.h" >+#include "wadres.h" >+#include "objid.h" >+#include "objects.h" >+#include "pic2img.h" >+#include "rgb.h" >+#include "gcolour2.h" >+ >+#include "r_render.h" >+#include "r_images.h" >+ >+ >+#define ML_UPPER_UNPEGGED 0x08 >+#define ML_LOWER_UNPEGGED 0x10 >+ >+ >+struct Y_View >+{ >+public: >+ int p_type, px, py; >+ // player type and position. >+ >+ float x, y; >+ int z; >+ // view position. >+ >+ static const int EYE_HEIGHT = 41; >+ // standard height above the floor. >+ >+ float angle; >+ float Sin, Cos; >+ // view direction. >+ >+ int sw, sh; >+ Img *screen; >+ // screen image. >+ >+ bool texturing; >+ bool sprites; >+ bool walking; >+ >+ ImageCache *im_ch; >+ >+ int *thing_floors; >+ >+ Y_View () { memset (this, 0, sizeof *this); } >+ >+ void SetAngle (float new_ang) >+ { >+ angle = new_ang; >+ >+ if (angle >= TWOPI) >+ angle -= TWOPI; >+ else if (angle < 0) >+ angle += TWOPI; >+ >+ Sin = sin (angle); >+ Cos = cos (angle); >+ } >+ >+ void CalcViewZ () >+ { >+ Objid o; >+ GetCurObject (o, OBJ_SECTORS, int (x), int (y)); >+ int secnum = o.num; >+ if (secnum >= 0) >+ z = Sectors[secnum].floorh + EYE_HEIGHT; >+ } >+ >+ void ClearScreen () >+ { >+ memset (screen->wbuf (), colour0, sw * sh); >+ } >+ >+ void PutScreen (int x, int y) >+ { >+ DrawScreenBox3D (x, y, x + BOX_BORDER*2 + sw, y + BOX_BORDER*2 + sh); >+ >+ Sticker sticker (*screen, true); >+ >+ sticker.draw (drw, 't', x + BOX_BORDER, y + BOX_BORDER); >+ } >+ >+ void FindThingFloors () >+ { >+ thing_floors = new int[NumThings]; >+ >+ for (int i = 0; i < NumThings; i++) >+ { >+ Objid o; >+ GetCurObject (o, OBJ_SECTORS, Things[i].xpos, >+ Things[i].ypos); >+ int secnum = o.num; >+ >+ if (secnum < 0) >+ thing_floors[i] = 0; >+ else >+ thing_floors[i] = Sectors[secnum].floorh; >+ } >+ } >+}; >+ >+ >+static Y_View view; >+ >+ >+struct DrawSurf >+{ >+public: >+ enum >+ { >+ K_INVIS = 0, >+ K_FLAT, >+ K_TEXTURE >+ }; >+ int kind; >+ >+ int h1, h2, tex_h; >+ // heights for the surface (h1 is above h2). >+ >+ Img *img; >+ img_pixel_t col; /* used if img is zero */ >+ >+ enum >+ { >+ SOLID_ABOVE = 1, >+ SOLID_BELOW = 2 >+ }; >+ int y_clip; >+ >+ /* CTor */ >+ >+ DrawSurf () { kind = K_INVIS; img = 0; } >+ >+ void FindFlat (const wad_flat_name_t& fname, Sector *sec) >+ { >+ if (view.texturing) >+ { >+ img = view.im_ch->GetFlat (fname); >+ >+ if (img != 0) >+ return; >+ } >+ col = 0x70 + ((sec - Sectors) % 48); >+ } >+ >+ void FindTex (const wad_tex_name_t& tname, LineDef *ld) >+ { >+ if (view.texturing) >+ { >+ img = view.im_ch->GetTex (tname); >+ >+ if (img != 0) >+ return; >+ } >+ col = 0x30 + ((ld - LineDefs) % 64); >+ >+ if (col >= 0x60) >+ col += 0x70; >+ } >+}; >+ >+ >+struct DrawWall >+{ >+public: >+ typedef std::vector<struct DrawWall *> vec_t; >+ >+ Thing *th; >+ // when `th' is non-zero, this is actually a sprite, and `ld' and >+ // `sd' will be zero. Sprites use the info in the `ceil' surface. >+ >+ LineDef *ld; >+ SideDef *sd; >+ Sector *sec; >+ >+ int side; >+ // which side this wall faces (0 right, 1 left) >+ >+ float ang1, dang, cur_ang; >+ float base_ang; >+ // clipped angles >+ >+ float dist, t_dist; >+ float normal; >+ // line constants >+ >+ double iz1, diz, cur_iz; >+ double mid_iz; >+ // distance values (inverted, so they can be lerped) >+ >+ float spr_tx1; >+ // translate coord, for sprite >+ >+ int sx1, sx2; >+ // screen X coordinates >+ >+ int oy1, oy2; >+ // for sprites, the remembered open space to clip to >+ >+ /* surfaces */ >+ >+ DrawSurf ceil; >+ DrawSurf upper; >+ DrawSurf lower; >+ DrawSurf floor; >+ >+ static const double IZ_EPSILON = 0.000001; >+ >+ /* PREDICATES */ >+ >+ struct MidDistCmp >+ { >+ inline bool operator() (const DrawWall * A, const DrawWall * B) const >+ { >+ return A->mid_iz > B->mid_iz; >+ } >+ }; >+ >+ struct DistCmp >+ { >+ inline bool operator() (const DrawWall * A, const DrawWall * B) const >+ { >+ if (fabs (A->cur_iz - B->cur_iz) < IZ_EPSILON) >+ return A->diz > B->diz; >+ >+ return A->cur_iz > B->cur_iz; >+ } >+ }; >+ >+ struct SX1Cmp >+ { >+ inline bool operator() (const DrawWall * A, const DrawWall * B) const >+ { >+ return A->sx1 < B->sx1; >+ } >+ >+ inline bool operator() (const DrawWall * A, int x) const >+ { >+ return A->sx1 < x; >+ } >+ >+ inline bool operator() (int x, const DrawWall * A) const >+ { >+ return x < A->sx1; >+ } >+ }; >+ >+ struct SX2Less >+ { >+ int x; >+ >+ SX2Less (int _x) : x (_x) { } >+ >+ inline bool operator() (const DrawWall * A) const >+ { >+ return A->sx2 < x; >+ } >+ }; >+ >+ /* methods */ >+ >+ void ComputeWallSurface () >+ { >+ Sector *front = sec; >+ Sector *back = 0; >+ >+ if (is_obj (side ? ld->sidedef1 : ld->sidedef2)) >+ { >+ SideDef *bsd = SideDefs + (side ? ld->sidedef1 : ld->sidedef2); >+ >+ if (is_obj (bsd->sector)) >+ back = Sectors + bsd->sector; >+ } >+ >+ bool sky_upper = back && is_sky (front->ceilt) && is_sky (back->ceilt); >+ >+ if ((front->ceilh > view.z || is_sky (front->ceilt)) && ! sky_upper) >+ { >+ ceil.kind = DrawSurf::K_FLAT; >+ ceil.h1 = +99999; >+ ceil.h2 = front->ceilh; >+ ceil.tex_h = ceil.h2; >+ ceil.y_clip = DrawSurf::SOLID_ABOVE; >+ >+ if (is_sky (front->ceilt)) >+ ceil.col = sky_colour; >+ else >+ ceil.FindFlat (front->ceilt, front); >+ } >+ >+ if (front->floorh < view.z) >+ { >+ floor.kind = DrawSurf::K_FLAT; >+ floor.h1 = front->floorh; >+ floor.h2 = -99999; >+ floor.tex_h = floor.h1; >+ floor.y_clip = DrawSurf::SOLID_BELOW; >+ >+ if (is_sky (front->floort)) >+ floor.col = sky_colour; >+ else >+ floor.FindFlat (front->floort, front); >+ } >+ >+ if (! back) >+ { >+ /* ONE-sided line */ >+ >+ lower.kind = DrawSurf::K_TEXTURE; >+ lower.h1 = front->ceilh; >+ lower.h2 = front->floorh; >+ lower.y_clip = DrawSurf::SOLID_ABOVE | DrawSurf::SOLID_BELOW; >+ >+ lower.FindTex (sd->tex3, ld); >+ >+ if (lower.img && (ld->flags & ML_LOWER_UNPEGGED)) >+ lower.tex_h = lower.h2 + lower.img->height (); >+ else >+ lower.tex_h = lower.h1; >+ } >+ else >+ { >+ /* TWO-sided line */ >+ >+ if (back->ceilh < front->ceilh && ! sky_upper) >+ { >+ upper.kind = DrawSurf::K_TEXTURE; >+ upper.h1 = front->ceilh; >+ upper.h2 = back->ceilh; >+ upper.tex_h = upper.h1; >+ upper.y_clip = DrawSurf::SOLID_ABOVE; >+ >+ upper.FindTex (sd->tex1, ld); >+ >+ if (upper.img && ! (ld->flags & ML_UPPER_UNPEGGED)) >+ upper.tex_h = upper.h2 + upper.img->height (); >+ else >+ upper.tex_h = upper.h1; >+ } >+ >+ if (back->floorh > front->floorh) >+ { >+ lower.kind = DrawSurf::K_TEXTURE; >+ lower.h1 = back->floorh; >+ lower.h2 = front->floorh; >+ lower.y_clip = DrawSurf::SOLID_BELOW; >+ >+ lower.FindTex (sd->tex2, ld); >+ >+ if (ld->flags & ML_LOWER_UNPEGGED) >+ lower.tex_h = front->ceilh; >+ else >+ lower.tex_h = lower.h1; >+ } >+ } >+ } >+}; >+ >+ >+struct RendInfo >+{ >+public: >+ DrawWall::vec_t walls; >+ // complete set of walls/sprites to draw. >+ >+ DrawWall::vec_t active; >+ // the active list. Pointers here are always duplicates of ones in >+ // the walls list (no need to `delete' any of them). >+ >+ std::vector<double> depth_x; >+ // inverse distances over X range, 0 when empty. >+ >+ int open_y1; >+ int open_y2; >+ >+ static const double Y_SLOPE = 1.70; >+ >+ static void DeleteWall (DrawWall *P) >+ { >+ delete P; >+ } >+ >+ ~RendInfo () >+ { >+ std::for_each (walls.begin (), walls.end (), DeleteWall); >+ >+ walls.clear (); >+ active.clear (); >+ } >+ >+ void InitDepthBuf (int width) >+ { >+ depth_x.resize (width); >+ >+ std::fill_n (depth_x.begin (), width, 0); >+ } >+ >+ static inline float PointToAngle (float x, float y) >+ { >+ if (-0.01 < x && x < 0.01) >+ return (y > 0) ? HALFPI : (3 * HALFPI); >+ >+ float angle = atan2(y, x); >+ >+ if (angle < 0) >+ angle += TWOPI; >+ >+ return angle; >+ } >+ >+ static inline int AngleToX (float ang) >+ { >+ float t = tan (HALFPI - ang); >+ >+ int x = int (view.sw * t); >+ >+ x = (view.sw + x) / 2; >+ >+ if (x < 0) >+ x = 0; >+ else if (x > view.sw) >+ x = view.sw; >+ >+ return x; >+ } >+ >+ static inline float XToAngle (int x) >+ { >+ x = x * 2 - view.sw; >+ >+ float ang = HALFPI + atan (x / float (view.sw)); >+ >+ if (ang < 0) >+ ang = 0; >+ else if (ang > ONEPI) >+ ang = ONEPI; >+ >+ return ang; >+ } >+ >+ static inline int DeltaToX (double iz, float tx) >+ { >+ int x = int (view.sw * tx * iz); >+ >+ x = (x + view.sw) / 2; >+ >+ return x; >+ } >+ >+ static inline float XToDelta (int x, double iz) >+ { >+ x = x * 2 - view.sw; >+ >+ float tx = x / iz / view.sw; >+ >+ return tx; >+ } >+ >+ static inline int DistToY (double iz, int sec_h) >+ { >+ if (sec_h > 32770) >+ return -9999; >+ >+ if (sec_h < -32770) >+ return +9999; >+ >+ sec_h -= view.z; >+ >+ int y = int (view.sh * sec_h * iz * Y_SLOPE); >+ >+ y = (view.sh - y) / 2; >+ >+ return y; >+ } >+ >+ static inline float YToDist (int y, int sec_h) >+ { >+ sec_h -= view.z; >+ >+ y = y * 2 - view.sh; >+ >+ if (y == 0) >+ return 999999; >+ >+ return view.sh * sec_h * Y_SLOPE / y; >+ } >+ >+ static inline float YToSecH (int y, double iz) >+ { >+ y = y * 2 - view.sh; >+ >+ return view.z - (float (y) / view.sh / iz / Y_SLOPE); >+ } >+ >+ void AddLine (int linenum) >+ { >+ LineDef *ld = LineDefs + linenum; >+ >+ if (! is_obj (ld->start) || ! is_obj (ld->end)) >+ return; >+ >+ float x1 = Vertices[ld->start].x - view.x; >+ float y1 = Vertices[ld->start].y - view.y; >+ float x2 = Vertices[ld->end].x - view.x; >+ float y2 = Vertices[ld->end].y - view.y; >+ >+ float tx1 = x1 * view.Sin - y1 * view.Cos; >+ float ty1 = x1 * view.Cos + y1 * view.Sin; >+ float tx2 = x2 * view.Sin - y2 * view.Cos; >+ float ty2 = x2 * view.Cos + y2 * view.Sin; >+ >+ // reject line if complete behind viewplane >+ if (ty1 <= 0 && ty2 <= 0) >+ return; >+ >+ float angle1 = PointToAngle (tx1, ty1); >+ float angle2 = PointToAngle (tx2, ty2); >+ float span = angle1 - angle2; >+ >+ if (span < 0) >+ span += TWOPI; >+ >+ int side = 0; >+ SideDef *sd; >+ >+ if (span >= ONEPI) >+ side = 1; >+ >+ // ignore the line when there is no facing sidedef >+ if (! is_obj (side ? ld->sidedef2 : ld->sidedef1)) >+ return; >+ >+ sd = SideDefs + (side ? ld->sidedef2 : ld->sidedef1); >+ >+ if (! is_obj (sd->sector)) >+ return; >+ >+ if (side == 1) >+ { >+ float tmp = angle1; >+ angle1 = angle2; >+ angle2 = tmp; >+ } >+ >+ // clip angles to view volume >+ >+ float base_ang = angle1; >+ >+ float leftclip = (3 * ONEPI / 4); >+ float rightclip = ONEPI / 4; >+ >+ float tspan1 = angle1 - rightclip; >+ float tspan2 = leftclip - angle2; >+ >+ if (tspan1 < 0) tspan1 += TWOPI; >+ if (tspan2 < 0) tspan2 += TWOPI; >+ >+ if (tspan1 > HALFPI) >+ { >+ // Totally off the left edge? >+ if (tspan2 >= ONEPI) >+ return; >+ >+ angle1 = leftclip; >+ } >+ >+ if (tspan2 > HALFPI) >+ { >+ // Totally off the left edge? >+ if (tspan1 >= ONEPI) >+ return; >+ >+ angle2 = rightclip; >+ } >+ >+ // convert angles to on-screen X positions >+ int sx1 = AngleToX (angle1); >+ int sx2 = AngleToX (angle2) - 1; >+ >+ if (sx1 > sx2) >+ return; >+ >+ // compute distance from eye to wall >+ float wdx = x2 - x1; >+ float wdy = y2 - y1; >+ >+ float wlen = sqrt (wdx * wdx + wdy * wdy); >+ float dist = fabs ((y1 * wdx / wlen) - (x1 * wdy / wlen)); >+ >+ if (dist < 0.01) >+ return; >+ >+ // compute normal of wall (translated coords) >+ float normal; >+ >+ if (side == 1) >+ normal = PointToAngle (ty2 - ty1, tx1 - tx2); >+ else >+ normal = PointToAngle (ty1 - ty2, tx2 - tx1); >+ >+ // compute inverse distances >+ double iz1 = cos (normal - angle1) / dist / cos (HALFPI - angle1); >+ double iz2 = cos (normal - angle2) / dist / cos (HALFPI - angle2); >+ >+ double diz = (iz2 - iz1) / y_max (1, sx2 - sx1); >+ >+ // create drawwall structure >+ >+ DrawWall *dw = new DrawWall; >+ >+ dw->th = 0; >+ dw->ld = ld; >+ dw->sd = sd; >+ dw->sec = Sectors + sd->sector; >+ >+ dw->side = side; >+ >+ dw->base_ang = base_ang; >+ dw->ang1 = angle1; >+ dw->dang = (angle2 - angle1) / y_max (1, sx2 - sx1); >+ >+ dw->dist = dist; >+ dw->normal = normal; >+ dw->t_dist = tan (base_ang - normal) * dist; >+ >+ dw->iz1 = iz1; >+ dw->diz = diz; >+ dw->mid_iz = iz1 + (sx2 - sx1 + 1) * diz / 2; >+ >+ dw->sx1 = sx1; dw->sx2 = sx2; >+ >+ walls.push_back (dw); >+ } >+ >+ void AddThing (int thingnum) >+ { >+ Thing *th = Things + thingnum; >+ >+ float x = th->xpos - view.x; >+ float y = th->ypos - view.y; >+ >+ float tx = x * view.Sin - y * view.Cos; >+ float ty = x * view.Cos + y * view.Sin; >+ >+ // reject sprite if complete behind viewplane >+ if (ty < 4) >+ return; >+ >+ Img *sprite = view.im_ch->GetSprite (th->type); >+ if (! sprite) >+ return; >+ >+ float tx1 = tx - sprite->width () / 2.0; >+ float tx2 = tx + sprite->width () / 2.0; >+ >+ double iz = 1 / ty; >+ >+ int sx1 = DeltaToX (iz, tx1); >+ int sx2 = DeltaToX (iz, tx2) - 1; >+ >+ if (sx1 < 0) >+ sx1 = 0; >+ >+ if (sx2 >= view.sw) >+ sx2 = view.sw - 1; >+ >+ if (sx1 > sx2) >+ return; >+ >+ int h2 = view.thing_floors[thingnum]; >+ int h1 = h2 + sprite->height (); >+ >+ // create drawwall structure >+ >+ DrawWall *dw = new DrawWall; >+ >+ dw->th = th; >+ dw->ld = 0; >+ dw->sd = 0; >+ dw->sec = 0; >+ >+ dw->spr_tx1 = tx1; >+ >+ dw->ang1 = dw->dang = 0; >+ >+ dw->iz1 = dw->mid_iz = iz; >+ dw->diz = 0; >+ >+ dw->sx1 = sx1; dw->sx2 = sx2; >+ >+ dw->ceil.img = sprite; >+ dw->ceil.h1 = h1; >+ dw->ceil.h2 = h2; >+ >+ walls.push_back (dw); >+ } >+ >+ void ComputeSurfaces () >+ { >+ DrawWall::vec_t::iterator S; >+ >+ for (S = walls.begin (); S != walls.end (); S++) >+ if ((*S)->ld) >+ (*S)->ComputeWallSurface (); >+ } >+ >+ void ClipSolids () >+ { >+ // perform a rough depth sort of the walls and sprites. >+ >+ std::sort (walls.begin (), walls.end (), DrawWall::MidDistCmp ()); >+ >+ // go forwards, from closest to furthest away >+ >+ DrawWall::vec_t::iterator S; >+ >+ for (S = walls.begin (); S != walls.end (); S++) >+ { >+ DrawWall *dw = (*S); >+ >+ if (! dw) >+ continue; >+ >+ int one_sided = dw->ld && ! is_obj (dw->ld->sidedef2); >+ int vis_count = dw->sx2 - dw->sx1 + 1; >+ >+ for (int x = dw->sx1; x <= dw->sx2; x++) >+ { >+ double iz = dw->iz1 + (dw->diz * (x - dw->sx1)); >+ >+ if (iz < depth_x[x]) >+ vis_count--; >+ else if (one_sided) >+ depth_x[x] = iz; >+ } >+ >+ if (vis_count == 0) >+ { >+ delete dw; >+ (*S) = 0; >+ } >+ } >+ >+ // remove null pointers >+ >+ S = std::remove (walls.begin (), walls.end (), (DrawWall *) 0); >+ >+ walls.erase (S, walls.end ()); >+ } >+ >+ void RenderFlatColumn (DrawWall *dw, DrawSurf& surf, >+ int x, int y1, int y2) >+ { >+ img_pixel_t *buf = view.screen->wbuf (); >+ img_pixel_t *wbuf = surf.img->wbuf (); >+ >+ int tw = surf.img->width (); >+ int th = surf.img->height (); >+ >+ float ang = XToAngle (x); >+ float modv = cos (ang - HALFPI); >+ >+ float t_cos = cos (ONEPI + -view.angle + ang) / modv; >+ float t_sin = sin (ONEPI + -view.angle + ang) / modv; >+ >+ buf += x + y1 * view.sw; >+ >+ for (; y1 <= y2; y1++, buf += view.sw) >+ { >+ float dist = YToDist (y1, surf.tex_h); >+ >+ int tx = int ( view.x + t_sin * dist) & (tw - 1); >+ int ty = int (-view.y - t_cos * dist) & (th - 1); >+ >+ *buf = wbuf[ty * tw + tx]; >+ } >+ } >+ >+ void RenderTexColumn (DrawWall *dw, DrawSurf& surf, >+ int x, int y1, int y2) >+ { >+ img_pixel_t *buf = view.screen->wbuf (); >+ img_pixel_t *wbuf = surf.img->wbuf (); >+ >+ int tw = surf.img->width (); >+ int th = surf.img->height (); >+ >+ /* compute texture X coord */ >+ >+ int tx = int (dw->t_dist - tan (dw->cur_ang - dw->normal) * dw->dist); >+ >+ tx = (dw->sd->xoff + tx) & (tw - 1); >+ >+ /* compute texture Y coords */ >+ >+ float base_h = surf.tex_h + dw->sd->yoff; >+ >+ float h1 = base_h - YToSecH (y1, dw->cur_iz); >+ float dh = base_h - YToSecH (y2, dw->cur_iz); >+ >+ dh = (dh - h1) / y_max (1, y2 - y1); >+ >+ buf += x + y1 * view.sw; >+ wbuf += tx; >+ >+ for (; y1 <= y2; y1++, h1 += dh, buf += view.sw) >+ { >+ int ty = int (h1) % th; >+ >+ // handle negative values (use % twice) >+ ty = (ty + th) % th; >+ >+ *buf = wbuf[ty * tw]; >+ } >+ } >+ >+ void RenderSolidColumn (DrawWall *w, DrawSurf& surf, >+ int x, int y1, int y2) >+ { >+ img_pixel_t *buf = view.screen->wbuf (); >+ >+ buf += x + y1 * view.sw; >+ >+ for (; y1 <= y2; y1++, buf += view.sw) >+ { >+ *buf = surf.col; >+ } >+ } >+ >+ inline void RenderWallSurface (DrawWall *dw, DrawSurf& surf, >+ int x) >+ { >+ if (surf.kind == DrawSurf::K_INVIS) >+ return; >+ >+ int y1 = DistToY (dw->cur_iz, surf.h1); >+ int y2 = DistToY (dw->cur_iz, surf.h2) - 1; >+ >+ if (y1 < open_y1) >+ y1 = open_y1; >+ >+ if (y2 > open_y2) >+ y2 = open_y2; >+ >+ if (y1 > y2) >+ return; >+ >+ /* clip the open region */ >+ >+ if (surf.y_clip & DrawSurf::SOLID_ABOVE) >+ if (y2 > open_y1) >+ open_y1 = y2; >+ >+ if (surf.y_clip & DrawSurf::SOLID_BELOW) >+ if (y1 < open_y2) >+ open_y2 = y1; >+ >+ /* fill pixels */ >+ >+ if (! surf.img) >+ { >+ RenderSolidColumn (dw, surf, x, y1, y2); >+ } >+ else switch (surf.kind) >+ { >+ case DrawSurf::K_FLAT: >+ RenderFlatColumn (dw, surf, x, y1, y2); >+ break; >+ >+ case DrawSurf::K_TEXTURE: >+ RenderTexColumn (dw, surf, x, y1, y2); >+ break; >+ } >+ } >+ >+ inline void RenderSprite (DrawWall *dw, int x) >+ { >+ int y1 = DistToY (dw->cur_iz, dw->ceil.h1); >+ int y2 = DistToY (dw->cur_iz, dw->ceil.h2) - 1; >+ >+ if (y1 < dw->oy1) >+ y1 = dw->oy1; >+ >+ if (y2 > dw->oy2) >+ y2 = dw->oy2; >+ >+ if (y1 > y2) >+ return; >+ >+ /* fill pixels */ >+ >+ img_pixel_t *buf = view.screen->wbuf (); >+ img_pixel_t *wbuf = dw->ceil.img->wbuf (); >+ >+ int tw = dw->ceil.img->width (); >+ int th = dw->ceil.img->height (); >+ >+ int tx = int (XToDelta (x, dw->cur_iz) - dw->spr_tx1); >+ >+ if (tx < 0 || tx >= tw) >+ return; >+ >+ float h1 = dw->ceil.h1 - YToSecH (y1, dw->cur_iz); >+ float dh = dw->ceil.h1 - YToSecH (y2, dw->cur_iz); >+ >+ dh = (dh - h1) / y_max (1, y2 - y1); >+ >+ buf += x + y1 * view.sw; >+ wbuf += tx; >+ >+ for (; y1 <= y2; y1++, h1 += dh, buf += view.sw) >+ { >+ int ty = int (h1); >+ >+ if (ty < 0 || ty >= th) >+ continue; >+ >+ img_pixel_t pix = wbuf[ty * tw]; >+ >+ if (pix != IMG_TRANSP) >+ *buf = pix; >+ } >+ } >+ >+ void UpdateActiveList (int x) >+ { >+ DrawWall::vec_t::iterator S, E, P; >+ >+ bool changes = false; >+ >+ // remove walls that have finished. >+ >+ S = active.begin (); >+ E = active.end (); >+ >+ S = std::remove_if (S, E, DrawWall::SX2Less (x)); >+ >+ if (S != E) >+ { >+ active.erase (S, E); >+ changes = true; >+ } >+ >+ // add new walls that start in this column. >+ >+ S = walls.begin (); >+ E = walls.end (); >+ >+ S = std::lower_bound (S, E, x, DrawWall::SX1Cmp ()); >+ E = std::upper_bound (S, E, x, DrawWall::SX1Cmp ()); >+ >+ if (S != E) >+ changes = true; >+ >+ for (; S != E; S++) >+ { >+ active.push_back (*S); >+ } >+ >+ // calculate new depth values >+ >+ S = active.begin (); >+ E = active.end (); >+ >+ for (P=S; (P != E); P++) >+ { >+ DrawWall *dw = (*P); >+ >+ dw->cur_iz = dw->iz1 + dw->diz * (x - dw->sx1); >+ >+ if (P != S && (*(P-1))->cur_iz < dw->cur_iz) >+ changes = true; >+ >+ dw->cur_ang = dw->ang1 + dw->dang * (x - dw->sx1); >+ } >+ >+ // if there are changes, re-sort the active list... >+ >+ if (changes) >+ { >+ std::sort (active.begin (), active.end (), DrawWall::DistCmp ()); >+ } >+ } >+ >+ void RenderWalls () >+ { >+ // sort walls by their starting column, to allow binary search. >+ >+ std::sort (walls.begin (), walls.end (), DrawWall::SX1Cmp ()); >+ >+ active.clear (); >+ >+ for (int x=0; x < view.sw; x++) >+ { >+ // clear vertical depth buffer >+ >+ open_y1 = 0; >+ open_y2 = view.sh - 1; >+ >+ UpdateActiveList (x); >+ >+ // render, front to back >+ >+ DrawWall::vec_t::iterator S, E, P; >+ >+ S = active.begin (); >+ E = active.end (); >+ >+ for (P=S; P != E; P++) >+ { >+ DrawWall *dw = (*P); >+ >+ // for things, just remember the open space >+ if (dw->th) >+ { >+ dw->oy1 = open_y1; >+ dw->oy2 = open_y2; >+ continue; >+ } >+ >+ RenderWallSurface (dw, dw->ceil, x); >+ RenderWallSurface (dw, dw->floor, x); >+ RenderWallSurface (dw, dw->upper, x); >+ RenderWallSurface (dw, dw->lower, x); >+ >+ if (open_y1 >= open_y2) >+ break; >+ } >+ >+ // now render things, back to front >+ >+ if (P == E) >+ P--; >+ >+ for (; P != (S-1); P--) >+ { >+ DrawWall *dw = (*P); >+ >+ if (dw->th) >+ RenderSprite (dw, x); >+ } >+ } >+ } >+ >+ void DoRender3D () >+ { >+ view.ClearScreen (); >+ >+ InitDepthBuf (view.sw); >+ >+ for (int i=0; i < NumLineDefs; i++) >+ AddLine (i); >+ >+ if (view.sprites) >+ for (int j=0; j < NumThings; j++) >+ AddThing (j); >+ >+ ClipSolids (); >+ ComputeSurfaces (); >+ RenderWalls (); >+ } >+}; >+ >+ >+static Thing *FindPlayer (int typenum) >+{ >+for (int i=0; i < NumThings; i++) >+ if (Things[i].type == typenum) >+ return Things + i; >+ >+return 0; >+} >+ >+ >+/* >+ * Render a 3D view from the player's position. >+ */ >+ >+void Render3D () >+{ >+if (! view.p_type) >+ { >+ view.p_type = THING_PLAYER1; >+ view.px = 99999; >+ } >+ >+Thing *player = FindPlayer (view.p_type); >+ >+if (! player) >+ { >+ if (view.p_type != THING_DEATHMATCH) >+ view.p_type = THING_DEATHMATCH; >+ >+ player = FindPlayer (view.p_type); >+ >+ if (! player) >+ return; >+ } >+ >+if (view.px != player->xpos || view.py != player->ypos) >+ { >+ // if player moved, re-create view parameters >+ >+ view.x = view.px = player->xpos; >+ view.y = view.py = player->ypos; >+ >+ view.CalcViewZ (); >+ view.SetAngle (player->angle * ONEPI / 180.0); >+ } >+ >+/* create image */ >+ >+view.sw = 320; >+view.sh = 200; >+ >+view.screen = new Img ((unsigned short int) view.sw, (unsigned short int) view.sh, false); >+view.im_ch = new ImageCache; >+ >+view.FindThingFloors (); >+ >+bool Redraw = true; >+ >+/* input loop */ >+ >+for (;;) >+ { >+ /* render image */ >+ >+ if (Redraw) >+ { >+ if (view.walking) >+ view.CalcViewZ (); >+ >+ RendInfo rend; >+ >+ rend.DoRender3D (); >+ >+ view.PutScreen (40, 40); >+ >+ Redraw = false; >+ } >+ >+ /* handle keypress */ >+ >+ int key = get_key (); >+ >+ if (key == YK_ESC || key == 'q') >+ break; >+ >+ if ((key & ~YK_SHIFT) == YK_LEFT) >+ { >+ view.SetAngle (view.angle + ONEPI / ((key & YK_SHIFT) ? 4 : 8)); >+ Redraw = true; >+ } >+ else if ((key & ~YK_SHIFT) == YK_RIGHT) >+ { >+ view.SetAngle (view.angle -ONEPI / ((key & YK_SHIFT) ? 4 : 8)); >+ Redraw = true; >+ } >+ else if ((key & ~YK_SHIFT) == YK_UP) >+ { >+ view.x += view.Cos * ((key & YK_SHIFT) ? 192 : 32); >+ view.y += view.Sin * ((key & YK_SHIFT) ? 192 : 32); >+ Redraw = true; >+ } >+ else if ((key & ~YK_SHIFT) == YK_DOWN) >+ { >+ view.x -= view.Cos * ((key & YK_SHIFT) ? 192 : 32); >+ view.y -= view.Sin * ((key & YK_SHIFT) ? 192 : 32); >+ Redraw = true; >+ } >+ else if (key == 'n' || key == 'N') >+ { >+ view.x -= view.Sin * ((key == 'N') ? 192 : 32); >+ view.y += view.Cos * ((key == 'N') ? 192 : 32); >+ Redraw = true; >+ } >+ else if (key == 'm' || key == 'M') >+ { >+ view.x += view.Sin * ((key == 'M') ? 192 : 32); >+ view.y -= view.Cos * ((key == 'M') ? 192 : 32); >+ Redraw = true; >+ } >+ else if (key == 'd' || key == 'D') >+ { >+ view.z += (key == 'D') ? 128 : 32; >+ Redraw = true; >+ } >+ else if (key == 'c' || key == 'C') >+ { >+ view.z -= (key == 'C') ? 128 : 32; >+ Redraw = true; >+ } >+ else if (key == 't') >+ { >+ view.texturing = ! view.texturing; >+ Redraw = true; >+ } >+ else if (key == 's') >+ { >+ view.sprites = ! view.sprites; >+ Redraw = true; >+ } >+ else if (key == 'w') >+ { >+ view.walking = ! view.walking; >+ Redraw = true; >+ } >+ else if (key) >+ { >+ // key no good, get another one >+ Beep (); >+ } >+ } >+ >+/* all done */ >+ >+delete view.screen; >+view.screen = 0; >+ >+delete view.im_ch; >+view.im_ch = 0; >+ >+delete[] view.thing_floors; >+view.thing_floors = 0; >+} >+ >diff -Nru yadex-1.7.0-orig/src/r_render.h yadex-1.7.0/src/r_render.h >--- yadex-1.7.0-orig/src/r_render.h 1969-12-31 19:00:00.000000000 -0500 >+++ yadex-1.7.0/src/r_render.h 2012-06-17 18:47:12.492693211 -0400 >@@ -0,0 +1,14 @@ >+/* >+ * r_render.h >+ * AJA 2002-04-27 >+ */ >+ >+ >+#ifndef YH_R_RENDER /* DO NOT INSERT ANYTHING BEFORE THIS LINE */ >+#define YH_R_RENDER >+ >+ >+void Render3D (); >+ >+ >+#endif /* DO NOT ADD ANYTHING AFTER THIS LINE */ >diff -Nru yadex-1.7.0-orig/src/sanity.cc yadex-1.7.0/src/sanity.cc >--- yadex-1.7.0-orig/src/sanity.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/sanity.cc 2012-06-17 18:47:12.492693211 -0400 >@@ -67,10 +67,10 @@ > assert_size (i16, 2); > assert_size (u32, 4); > assert_size (i32, 4); >- assert_size (struct LineDef, 14); >+ assert_size (struct LineDef, 18); > assert_size (struct Sector, 26); > assert_size (struct SideDef, 30); >- assert_size (struct Thing, 10); >+ assert_size (struct Thing, 20); > assert_size (struct Vertex, 4); > assert_wrap (u8, 255, 0); > assert_wrap (i8, 127, -128); >diff -Nru yadex-1.7.0-orig/src/s_misc.cc yadex-1.7.0/src/s_misc.cc >--- yadex-1.7.0-orig/src/s_misc.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/s_misc.cc 2012-06-17 18:47:12.492693211 -0400 >@@ -29,11 +29,15 @@ > > > #include "yadex.h" >+#include <math.h> >+ > #include "entry.h" > #include "gfx.h" > #include "levels.h" > #include "objid.h" > #include "selectn.h" >+#include "objects.h" >+#include "dialog.h" > > > /* >@@ -179,4 +183,340 @@ > MadeChanges = 1; > } > >+ >+static int find_linedef_for_area (int x, int y, int& side) >+{ >+ int n, m, curx; >+ int best_match = -1; >+ >+ curx = 32767; // Oh yes, one more hard-coded constant! >+ >+ for (n = 0; n < NumLineDefs; n++) >+ if ((Vertices[LineDefs[n].start].y > y) >+ != (Vertices[LineDefs[n].end].y > y)) >+ { >+ int lx0 = Vertices[LineDefs[n].start].x; >+ int ly0 = Vertices[LineDefs[n].start].y; >+ int lx1 = Vertices[LineDefs[n].end].x; >+ int ly1 = Vertices[LineDefs[n].end].y; >+ m = lx0 + (int) ((long) (y - ly0) * (long) (lx1 - lx0) >+ / (long) (ly1 - ly0)); >+ if (m >= x && m < curx) >+ { >+ curx = m; >+ best_match = n; >+ } >+ } >+ >+ /* now look if this linedef has a sidedef bound to one sector */ >+ if (best_match < 0) >+ return OBJ_NO_NONE; >+ >+ if (Vertices[LineDefs[best_match].start].y >+ > Vertices[LineDefs[best_match].end].y) >+ side = 1; >+ else >+ side = 2; >+ >+ return best_match; >+} >+ >+/* >+ compute the angle between lines AB and BC, going anticlockwise. >+ result is in degrees 0 - 359. A, B and C are vertex indices. >+ -AJA- 2001-05-09 >+ */ >+#define DEBUG_ANGLE 0 >+ >+static double angle_between_linedefs (int A, int B, int C) >+{ >+ int a_dx = Vertices[B].x - Vertices[A].x; >+ int a_dy = Vertices[B].y - Vertices[A].y; >+ >+ int c_dx = Vertices[B].x - Vertices[C].x; >+ int c_dy = Vertices[B].y - Vertices[C].y; >+ >+ double AB_angle = (a_dx == 0) ? (a_dy >= 0 ? 90 : -90) : >+ atan2 (a_dy, a_dx) * 180 / M_PI; >+ >+ double CB_angle = (c_dx == 0) ? (c_dy >= 0 ? 90 : -90) : >+ atan2 (c_dy, c_dx) * 180 / M_PI; >+ >+ double result = CB_angle - AB_angle; >+ >+ if (result >= 360) >+ result -= 360; >+ >+ while (result < 0) >+ result += 360; >+ >+#if (DEBUG_ANGLE) >+ fprintf(stderr, "ANGLE %1.6f (%d,%d) -> (%d,%d) -> (%d,%d)\n", >+ result, Vertices[A].x, Vertices[A].y, >+ Vertices[B].x, Vertices[B].y, Vertices[C].x, Vertices[C].y); >+#endif >+ >+ return result; >+} >+ >+/* >+ follows the path clockwise from the given start line, adding each >+ line into the appropriate set. If the path is not closed, zero is >+ returned. >+ >+ -AJA- 2001-05-09 >+ */ >+#define DEBUG_PATH 0 >+ >+static int select_sides_in_closed_path (bitvec_c& ld_side1, >+ bitvec_c& ld_side2, int line, int side) >+{ >+ int cur_vert, prev_vert, final_vert; >+ >+ if (side == 1) >+ { >+ ld_side1.set (line); >+ cur_vert = LineDefs[line].end; >+ prev_vert = final_vert = LineDefs[line].start; >+ } >+ else >+ { >+ ld_side2.set (line); >+ cur_vert = LineDefs[line].start; >+ prev_vert = final_vert = LineDefs[line].end; >+ } >+ >+#if (DEBUG_PATH) >+ fprintf(stderr, "PATH: line %d side %d cur %d final %d\n", >+ line, side, cur_vert, final_vert); >+#endif >+ >+ while (cur_vert != final_vert) >+ { >+ int next_line = OBJ_NO_NONE; >+ int next_vert = OBJ_NO_NONE; >+ int next_side; >+ double best_angle = 999; >+ >+ // Look for the next linedef in the path. It's the linedef that >+ // uses the current vertex and is not the current one. >+ >+ for (int n = 0; n < NumLineDefs; n++) >+ { >+ if (n == line) >+ continue; >+ >+ int other_vert; >+ int which_side; >+ >+ if (LineDefs[n].start == cur_vert) >+ { >+ other_vert = LineDefs[n].end; >+ which_side = 1; >+ } >+ else if (LineDefs[n].end == cur_vert) >+ { >+ other_vert = LineDefs[n].start; >+ which_side = 2; >+ } >+ else >+ continue; >+ >+ // found adjoining linedef >+ >+ double angle = angle_between_linedefs (prev_vert, cur_vert, >+ other_vert); >+ >+ if (! is_obj (next_line) || angle < best_angle) >+ { >+ next_line = n; >+ next_vert = other_vert; >+ next_side = which_side; >+ >+ best_angle = angle; >+ } >+ >+ // Continue the search >+ } >+ >+ line = next_line; >+ side = next_side; >+ >+#if (DEBUG_PATH) >+ fprintf(stderr, "PATH NEXT: line %d side %d vert %d angle %1.6f\n", >+ line, side, next_vert, best_angle); >+#endif >+ >+ // None ? Path cannot be closed >+ if (! is_obj (line)) >+ return 0; >+ >+ // Line already seen ? Under normal circumstances this won't >+ // happen, but it _can_ happen and indicates a non-closed >+ // structure >+ if (ld_side1.get (line) || ld_side2.get (line)) >+ return 0; >+ >+ if (side == 1) >+ ld_side1.set (line); >+ else >+ ld_side2.set (line); >+ >+ prev_vert = cur_vert; >+ cur_vert = next_vert; >+ } >+ >+#if (DEBUG_PATH) >+ fprintf(stderr, "PATH CLOSED !\n"); >+#endif >+ >+ return 1; >+} >+ >+/* >+ update the side on a single linedef, using the given sector >+ reference. Will create a new sidedef if necessary. >+ */ >+static void super_set_sector_on_side (int line, wad_sdn_t& side, >+ wad_sdn_t& other, int side_no, int sector) >+{ >+ if (is_obj (side) && SideDefs[side].sector == sector) >+ { >+ // there was no change. >+ return; >+ } >+ >+ int must_flip = 0; >+ >+ if (! is_obj (side)) >+ { >+ // if we're adding a sidedef to a line that has no sides, and >+ // the sidedef would be the 2nd one, then flip the linedef. >+ // Thus we don't end up with invalid lines -- i.e. ones with a >+ // left side but no right side. >+ >+ if (! is_obj (other) && side_no == 2) >+ must_flip = 1; >+ >+ InsertObject (OBJ_SIDEDEFS, OBJ_NO_NONE, 0, 0); >+ side = NumSideDefs - 1; >+ >+ // if we're adding a second side to the linedef, clear out some >+ // of the properties that aren't needed anymore: middle texture, >+ // two-sided flag, and impassible flag. >+ >+ if (is_obj (other)) >+ { >+ strncpy (SideDefs[side].tex3, "-", WAD_TEX_NAME); >+ strncpy (SideDefs[other].tex3, "-", WAD_TEX_NAME); >+ >+ LineDefs[line].flags |= 4; // Set the 2S bit >+ LineDefs[line].flags &= ~1; // Clear the Im bit >+ } >+ } >+ >+ SideDefs[side].sector = sector; >+ >+ if (must_flip) >+ { >+ int temp = LineDefs[line].start; >+ LineDefs[line].start = LineDefs[line].end; >+ LineDefs[line].end = temp; >+ >+ temp = side; >+ side = other; >+ other = temp; >+ } >+ >+ MadeChanges = 1; >+ MadeMapChanges = 1; >+} >+ >+static int super_find_sector_model (bitvec_c& ld_side1, >+ bitvec_c& ld_side2) >+{ >+ for (int line=0; line < NumLineDefs; line++) >+ { >+ int side1 = LineDefs[line].sidedef1; >+ int side2 = LineDefs[line].sidedef2; >+ >+ if (ld_side1.get (line)) >+ if (is_obj (side2)) >+ return SideDefs[side2].sector; >+ >+ if (ld_side2.get (line)) >+ if (is_obj (side1)) >+ return SideDefs[side1].sector; >+ } >+ >+ return OBJ_NO_NONE; >+} >+ >+ >+/* >+ Change the closed sector at the pointer >+ >+ "sector" here really means a bunch of sidedefs that all face >+ inward to the current area under the mouse cursor. Two basic >+ operations: (a) set the sidedef sector references to a completely >+ new sector, or (b) set them to an existing sector. This is >+ controlled by the `new_sec' parameter. >+ >+ -AJA- 2001-05-08 >+ */ >+ >+void SuperSectorSelector (int map_x, int map_y, int new_sec) >+{ >+ int line, side; >+ char msg_buf[200]; >+ >+ line = find_linedef_for_area (map_x, map_y, side); >+ >+ if (! is_obj (line)) >+ { >+ Beep (); >+ sprintf (msg_buf, "Chosen area is not closed"); >+ Notify (-1, -1, msg_buf, NULL); >+ return; >+ } >+ >+ bitvec_c ld_side1 (NumLineDefs); >+ bitvec_c ld_side2 (NumLineDefs); >+ >+ int closed = select_sides_in_closed_path (ld_side1, ld_side2, >+ line, side); >+ >+ if (! closed) >+ { >+ Beep (); >+ sprintf (msg_buf, "Area chosen is not closed"); >+ Notify (-1, -1, msg_buf, NULL); >+ return; >+ } >+ >+ // -AJA- FIXME: look for "islands", closed linedef paths that lie >+ // completely inside the area, i.e. not connected to the main path. >+ // Example: the two pillars at the start of MAP01 of DOOM 2. See >+ // GetOppositeSector() and the end of SplitSector() for a possible >+ // algorithm. >+ >+ if (! is_obj (new_sec)) >+ { >+ int model = super_find_sector_model (ld_side1, ld_side2); >+ InsertObject (OBJ_SECTORS, model, 0, 0); >+ new_sec = NumSectors - 1; >+ } >+ >+ for (line=0; line < NumLineDefs; line++) >+ { >+ if (ld_side1.get (line)) >+ super_set_sector_on_side (line, LineDefs[line].sidedef1, >+ LineDefs[line].sidedef2, 1, new_sec); >+ >+ else if (ld_side2.get (line)) >+ super_set_sector_on_side (line, LineDefs[line].sidedef2, >+ LineDefs[line].sidedef1, 2, new_sec); >+ } >+} >+ > /* end of file */ >diff -Nru yadex-1.7.0-orig/src/s_prop.cc yadex-1.7.0/src/s_prop.cc >--- yadex-1.7.0-orig/src/s_prop.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/s_prop.cc 2012-06-17 18:47:12.493693218 -0400 >@@ -259,4 +259,67 @@ > } > } > >+/* >+ * InputSectorType >+ * Let the user select a sector type number and return it >+ * Returns 0 if OK, <>0 if cancelled >+ */ >+int InputSectorType (int x0, int y0, int *number) >+{ >+ int val; >+ val = 0; >+ *number = 0; >+ Menu_data_st menudata (stdef); >+ if (DisplayMenuList (x0 , y0, "Select type", menudata, &val) >+ < 0) >+ return 1; >+ // KLUDGE last element of stdef means "enter value" >+ if (val == al_lcount (stdef) - 1) >+ { >+ val = InputIntegerValue (x0 + 84, >+ y0 + BOX_BORDER + (3 + val) * FONTH, >+ -32768, 32767, 0); >+ if (val == IIV_CANCEL) // [Esc] >+ return 1; >+ } >+ else >+ { >+ if (al_lseek (stdef, val, SEEK_SET)) >+ fatal_error ("%s SP1 (%s)\n", >+ msg_unexpected, al_astrerror (al_aerrno)); >+ val = CUR_STDEF->number; >+ } >+ if (val < 0) return 1; //unsuccessful >+ *number = val; >+ return 0; //successful >+} >+ >+/* >+ * TransferSectorProperties >+ * >+ * -AJA- 2001-05-27 >+ */ >+void TransferSectorProperties (int src_sector, SelPtr sectors) >+{ >+ SelPtr cur; >+ >+ for (cur=sectors; cur; cur=cur->next) >+ { >+ if (! is_obj(cur->objnum)) >+ continue; >+ >+ strncpy (Sectors[cur->objnum].floort, Sectors[src_sector].floort, >+ WAD_FLAT_NAME); >+ strncpy (Sectors[cur->objnum].ceilt, Sectors[src_sector].ceilt, >+ WAD_FLAT_NAME); >+ >+ Sectors[cur->objnum].floorh = Sectors[src_sector].floorh; >+ Sectors[cur->objnum].ceilh = Sectors[src_sector].ceilh; >+ Sectors[cur->objnum].light = Sectors[src_sector].light; >+ Sectors[cur->objnum].special = Sectors[src_sector].special; >+ Sectors[cur->objnum].tag = Sectors[src_sector].tag; >+ >+ MadeChanges = 1; >+ } >+} > >diff -Nru yadex-1.7.0-orig/src/s_split.cc yadex-1.7.0/src/s_split.cc >--- yadex-1.7.0-orig/src/s_split.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/s_split.cc 2012-06-17 18:47:12.493693218 -0400 >@@ -36,6 +36,7 @@ > #include "s_linedefs.h" > #include "selectn.h" > #include "x_hover.h" >+#include "entry.h" > > > /* >diff -Nru yadex-1.7.0-orig/src/textures.cc yadex-1.7.0/src/textures.cc >--- yadex-1.7.0-orig/src/textures.cc 2003-04-24 15:50:36.000000000 -0500 >+++ yadex-1.7.0/src/textures.cc 2012-06-17 18:47:42.123880109 -0400 >@@ -177,7 +177,7 @@ > goto textures_done; > } > // Read in the offsets for texture1 names and info >- offsets = (i32 *) GetMemory ((long) numtex * 4); >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); > wf->read_i32 (offsets, numtex); > if (wf->error ()) > { >@@ -233,7 +233,7 @@ > goto texture1_done; > } > // Read in the offsets for texture1 names and info >- offsets = (i32 *) GetMemory ((long) numtex * 4); >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); > wf->read_i32 (offsets, numtex); > if (wf->error ()) > { >@@ -286,7 +286,7 @@ > goto texture2_done; > } > // Read in the offsets for TEXTURE2 names >- offsets = (i32 *) GetMemory ((long) numtex * 4); >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); > wf->read_i32 (offsets, numtex); > if (wf->error ()) > { >@@ -514,7 +514,7 @@ > dir->wadfile->seek (dir->dir.start); > dir->wadfile->read_i32 (&numtex); > // Read in the offsets for texture1 names and info >- offsets = (i32 *) GetMemory ((long) numtex * 4); >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); > dir->wadfile->read_i32 (offsets, numtex); > for (n = 0; n < numtex && !texofs; n++) > { >@@ -534,7 +534,7 @@ > dir->wadfile->seek (dir->dir.start); > dir->wadfile->read_i32 (&numtex); > // Read in the offsets for texture2 names >- offsets = (i32 *) GetMemory ((long) numtex * 4); >+ offsets = (i32 *) GetMemory ((long) numtex * sizeof(i32)); > dir->wadfile->read_i32 (offsets); > for (n = 0; n < numtex && !texofs; n++) > { >diff -Nru yadex-1.7.0-orig/src/t_prop.cc yadex-1.7.0/src/t_prop.cc >--- yadex-1.7.0-orig/src/t_prop.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/t_prop.cc 2012-06-17 18:47:12.493693218 -0400 >@@ -36,16 +36,18 @@ > #include "gfx.h" > #include "levels.h" > #include "oldmenus.h" >+#include "objid.h" >+#include "objects.h" > #include "selectn.h" > #include "things.h" > >- > /* > * Private functions prototypes > */ >-static int InputThingType (int x0, int y0, int *number); > static const char *PrintThinggroup (void *ptr); > static const char *PrintThingdef (void *ptr); >+int InputThingType (int x0, int y0, int *number); >+int InputLinedefType (int x0, int y0, int *number); > > > /* >@@ -60,9 +62,9 @@ > SelPtr cur; > int subwin_y0; > >-for (n = 0; n < 6; n++) >+for (n = 0; n < 14; n++) > menustr[n] = (char *) GetMemory (60); >-sprintf (menustr[5], "Edit thing #%d", obj->objnum); >+sprintf (menustr[13], "Edit thing #%d", obj->objnum); > sprintf (menustr[0], "Change type (Current: %s)", > get_thing_name (Things[obj->objnum].type)); > sprintf (menustr[1], "Change angle (Current: %s)", >@@ -73,14 +75,47 @@ > Things[obj->objnum].xpos); > sprintf (menustr[4], "Change Y position (Current: %d)", > Things[obj->objnum].ypos); >-val = vDisplayMenu (x0, y0, menustr[5], >+sprintf (menustr[5], "Change Z position (Current: %d)", >+ Things[obj->objnum].height); >+sprintf (menustr[6], "Change TID (Current: %d)", >+ Things[obj->objnum].tid); >+sprintf (menustr[7], "Change special (Current: %d)", >+ Things[obj->objnum].special); >+sprintf (menustr[8], "Change arg1 (Current: %d)", >+ Things[obj->objnum].arg1); >+sprintf (menustr[9], "Change arg2 (Current: %d)", >+ Things[obj->objnum].arg2); >+sprintf (menustr[10], "Change arg3 (Current: %d)", >+ Things[obj->objnum].arg3); >+sprintf (menustr[11], "Change arg4 (Current: %d)", >+ Things[obj->objnum].arg4); >+sprintf (menustr[12], "Change arg5 (Current: %d)", >+ Things[obj->objnum].arg5); >+if (yg_level_format == YGLF_HEXEN) // Hexen mode >+val = vDisplayMenu (x0, y0, menustr[13], >+ menustr[0], YK_, 0, >+ menustr[1], YK_, 0, >+ menustr[2], YK_, 0, >+ menustr[3], YK_, 0, >+ menustr[4], YK_, 0, >+ menustr[5], YK_, 0, >+ menustr[6], YK_, 0, >+ menustr[7], YK_, 0, >+ menustr[8], YK_, 0, >+ menustr[9], YK_, 0, >+ menustr[10], YK_, 0, >+ menustr[11], YK_, 0, >+ menustr[12], YK_, 0, >+ NULL); >+else >+val = vDisplayMenu (x0, y0, menustr[13], > menustr[0], YK_, 0, > menustr[1], YK_, 0, > menustr[2], YK_, 0, > menustr[3], YK_, 0, > menustr[4], YK_, 0, > NULL); >-for (n = 0; n < 6; n++) >+for (n = 0; n < 14; n++) > FreeMemory (menustr[n]); > subwin_y0 = y0 + BOX_BORDER + (2 + val) * FONTH; > switch (val) >@@ -241,6 +276,93 @@ > MadeChanges = 1; > } > break; >+ >+ case 6: >+ val = InputIntegerValue (x0 + 42, subwin_y0, -32768, 32767, >+ Things[obj->objnum].height); >+ if (val != IIV_CANCEL) >+ { >+ n = val - Things[obj->objnum].height; >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].height += n; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 7: >+ val = InputIntegerValue (x0 + 42, subwin_y0, -32768, 32767, >+ Things[obj->objnum].tid); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].tid = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 8: >+ if (! InputLinedefType (x0 + 42, subwin_y0, &val)) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].special = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 9: >+ val = InputIntegerValue (x0 + 42, subwin_y0, 0, 255, >+ Things[obj->objnum].arg1); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].arg1 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 10: >+ val = InputIntegerValue (x0 + 42, subwin_y0, 0, 255, >+ Things[obj->objnum].arg2); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].arg2 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 11: >+ val = InputIntegerValue (x0 + 42, subwin_y0, 0, 255, >+ Things[obj->objnum].arg3); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].arg3 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 12: >+ val = InputIntegerValue (x0 + 42, subwin_y0, 0, 255, >+ Things[obj->objnum].arg4); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].arg4 = val; >+ MadeChanges = 1; >+ } >+ break; >+ >+ case 13: >+ val = InputIntegerValue (x0 + 42, subwin_y0, 0, 255, >+ Things[obj->objnum].arg5); >+ if (val != IIV_CANCEL) >+ { >+ for (cur = obj; cur; cur = cur->next) >+ Things[cur->objnum].arg5 = val; >+ MadeChanges = 1; >+ } >+ break; > } > } > >@@ -250,7 +372,7 @@ > * Let the user select a thing number and return it. > * Returns 0 if OK, <>0 if cancelled > */ >-static int InputThingType (int x0, int y0, int *number) >+int InputThingType (int x0, int y0, int *number) > { > int r; > int tgno = 0; >@@ -331,4 +453,30 @@ > } > > >+/* >+ * TransferThingProperties >+ * >+ * -AJA- 2001-05-27 >+ */ >+void TransferThingProperties (int src_thing, SelPtr things) >+{ >+ SelPtr cur; >+ >+ for (cur=things; cur; cur=cur->next) >+ { >+ if (! is_obj(cur->objnum)) >+ continue; >+ >+ Things[cur->objnum].angle = Things[src_thing].angle; >+ Things[cur->objnum].type = Things[src_thing].type; >+ Things[cur->objnum].when = Things[src_thing].when; >+ >+ MadeChanges = 1; >+ >+ things_types++; >+ things_angles++; >+ } >+} >+ >+ > /* end of file */ >diff -Nru yadex-1.7.0-orig/src/wadlist.cc yadex-1.7.0/src/wadlist.cc >--- yadex-1.7.0-orig/src/wadlist.cc 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/wadlist.cc 2012-06-17 18:48:05.519027705 -0400 >@@ -52,6 +52,7 @@ > > Wad_list_priv::Wad_list_priv () > { >+ iter = list.begin (); > rewound = true; > } > >@@ -80,6 +81,7 @@ > */ > void Wad_list::rewind () const > { >+ priv->iter = priv->list.begin (); > priv->rewound = true; > } > >@@ -98,10 +100,7 @@ > bool Wad_list::get (Wad_file *& wf) > { > if (priv->rewound) >- { >- priv->iter = priv->list.begin (); > priv->rewound = false; >- } > else > ++priv->iter; > >@@ -119,10 +118,7 @@ > bool Wad_list::get (const Wad_file *& wf) const > { > if (priv->rewound) >- { >- priv->iter = priv->list.begin (); > priv->rewound = false; >- } > else > ++priv->iter; > >@@ -157,26 +153,12 @@ > */ > void Wad_list::del () > { >- list_t::iterator i; >- >- if (priv->rewound) >- { >- i = priv->list.begin (); >- } >- else >- { >- i = priv->iter; >- } >- if (i == priv->list.end ()) >+ if (priv->iter == priv->list.end ()) > { > nf_bug ("Wad_list::del: attempt to delete last item"); > return; > } >- priv->iter = priv->list.erase (i); >+ priv->iter = priv->list.erase (priv->iter); > if (priv->iter == priv->list.begin ()) >- { >- priv->iter = 0; // Catch bugs > priv->rewound = true; >- } > } >- >diff -Nru yadex-1.7.0-orig/src/wstructs.h yadex-1.7.0/src/wstructs.h >--- yadex-1.7.0-orig/src/wstructs.h 2003-03-28 07:37:32.000000000 -0500 >+++ yadex-1.7.0/src/wstructs.h 2012-06-17 18:47:12.493693218 -0400 >@@ -84,14 +84,30 @@ > typedef i16 wad_tflags_t; > struct Thing > { >+ i16 tid; > wad_coord_t xpos; // FIXME rename to "x" > wad_coord_t ypos; // FIXME rename to "y" >+ wad_z_t height; > wad_tangle_t angle; > wad_ttype_t type; > wad_tflags_t when; // FIXME rename to "flags" >+ u8 special; >+ u8 arg1; >+ u8 arg2; >+ u8 arg3; >+ u8 arg4; >+ u8 arg5; > }; > typedef struct > { >+ wad_coord_t xpos; // FIXME rename to "x" >+ wad_coord_t ypos; // FIXME rename to "y" >+ wad_tangle_t angle; >+ wad_ttype_t type; >+ wad_tflags_t when; // FIXME rename to "flags" >+} wad_doom_thing_t; >+typedef struct >+{ > i16 tid; > wad_coord_t x; > wad_coord_t y; >@@ -121,11 +137,25 @@ > wad_ldflags_t flags; > wad_ldtype_t type; > wad_tag_t tag; >+ u8 arg2; >+ u8 arg3; >+ u8 arg4; >+ u8 arg5; > wad_sdn_t sidedef1; // # of first (right) sidedef > wad_sdn_t sidedef2; // # of second (left) sidedef or 0xffff > }; > typedef struct > { >+ wad_vn_t start; // # of start vertex >+ wad_vn_t end; // # of end vertex >+ wad_ldflags_t flags; >+ wad_ldtype_t type; >+ wad_tag_t tag; >+ wad_sdn_t sidedef1; // # of first (right) sidedef >+ wad_sdn_t sidedef2; // # of second (left) sidedef or 0xffff >+} wad_doom_linedef_t; >+typedef struct >+{ > wad_vn_t start; > wad_vn_t end; > wad_ldflags_t flags; >@@ -197,8 +227,11 @@ > WAD_LL_SECTORS, > WAD_LL_REJECT, > WAD_LL_BLOCKMAP, >- // Hexen has a BEHAVIOR lump here >- WAD_LL__ >+ WAD_LL_BEHAVIOR, >+ >+ WAD_LL__MAX, >+ WAD_LL__HEXEN = WAD_LL__MAX, >+ WAD_LL__DOOM = WAD_LL_BEHAVIOR > } wad_level_lump_no_t; > > typedef struct >@@ -207,7 +240,7 @@ > size_t item_size; > } wad_level_lump_def_t; > >-const wad_level_lump_def_t wad_level_lump[WAD_LL__] = >+const wad_level_lump_def_t wad_level_lump[WAD_LL__MAX] = > { > { 0, 0 }, // Label -- no fixed name > { "THINGS", WAD_THING_BYTES }, >@@ -219,8 +252,8 @@ > { "NODES", 0 }, > { "SECTORS", WAD_SECTOR_BYTES }, > { "REJECT", 0 }, >- { "BLOCKMAP", 0 } >- // Hexen has a BEHAVIOR lump here >+ { "BLOCKMAP", 0 }, >+ { "BEHAVIOR", 0 } > }; > > >diff -Nru yadex-1.7.0-orig/src/yadex.h yadex-1.7.0/src/yadex.h >--- yadex-1.7.0-orig/src/yadex.h 2003-12-14 19:37:45.000000000 -0500 >+++ yadex-1.7.0/src/yadex.h 2012-06-17 18:47:42.124880118 -0400 >@@ -98,11 +98,11 @@ > #define F_I16_D "hd" > #define F_I16_H "hX" > >-typedef unsigned long u32; >+typedef unsigned int u32; > #define F_U32_D "lu" > #define F_U32_H "lX" > >-typedef signed long i32; >+typedef signed int i32; > #define F_I32_D "ld" > #define F_I32_H "lX" > >@@ -479,6 +479,7 @@ > > // l_prop.cc (previously in editobj.cc) > void LinedefProperties (int x0, int y0, SelPtr obj); >+void TransferLinedefProperties (int src_linedef, SelPtr linedefs); > > // l_unlink.cc > void unlink_sidedef (SelPtr linedefs, int side1, int side2); >@@ -541,13 +542,16 @@ > void DistributeSectorCeilings (SelPtr); /* SWAP! */ > void RaiseOrLowerSectors (SelPtr obj); > void BrightenOrDarkenSectors (SelPtr obj); >+void SuperSectorSelector (int map_x, int map_y, int new_sec); > > // s_prop.cc (previously in editobj.cc) > void SectorProperties (int x0, int y0, SelPtr obj); >+void TransferSectorProperties (int src_sector, SelPtr sectors); > > // s_split.cc (previously in objects.cc) > void SplitSector (int, int); /* SWAP! */ > void SplitLineDefsAndSector (int, int); /* SWAP! */ >+void MultiSplitLineDefsAndSector (int, int); /* SWAP! */ > > // swapmem.cc > void InitSwap (void); >@@ -560,6 +564,7 @@ > // selrect.cc > // t_prop.c (previously in editobj.c) > void ThingProperties (int x0, int y0, SelPtr obj); >+void TransferThingProperties (int src_thing, SelPtr things); > > // v_merge.cc > void DeleteVerticesJoinLineDefs (SelPtr ); /* SWAP! */ >diff -Nru yadex-1.7.0-orig/yadex.cfg yadex-1.7.0/yadex.cfg >--- yadex-1.7.0-orig/yadex.cfg 2003-03-30 08:08:13.000000000 -0500 >+++ yadex-1.7.0/yadex.cfg 2012-06-17 18:47:59.814991724 -0400 >@@ -20,16 +20,17 @@ > # 9 doompr Doom press release pre-beta (/pub/idgames/historic/doomprbt.zip) > # 10 strife10 Strife 1.0 (demo or commercial) > >- iwad1 = /usr/local/share/games/doom/doom.wad >- iwad2 = /usr/local/share/games/doom2/doom2.wad >- iwad3 = /usr/local/share/games/heretic/heretic.wad >- iwad4 = /usr/local/share/games/hexen/hexen.wad >- iwad5 = /usr/local/share/games/strife/strife1.wad >- iwad6 = /usr/local/share/games/doom02/doom.wad >- iwad7 = /usr/local/share/games/doom04/doom.wad >- iwad8 = /usr/local/share/games/doom05/doom.wad >- iwad9 = /usr/local/share/games/doompr/doompres.wad >- iwad10 = /usr/local/share/games/strife10/strife1.wad >+ iwad1 = /usr/share/doom/doom.wad >+# iwad2 = /usr/share/doom/doom2.wad >+ iwad2 = /usr/share/doom/freedoom.wad >+ iwad3 = /usr/share/doom/heretic.wad >+ iwad4 = /usr/share/doom/hexen.wad >+ iwad5 = /usr/share/doom/strife1.wad >+ iwad6 = /usr/share/doom/doom.wad >+ iwad7 = /usr/share/doom/doom.wad >+ iwad8 = /usr/share/doom/doom.wad >+ iwad9 = /usr/share/doom/doompres.wad >+ iwad10 = /usr/share/doom/strife1.wad > > # Name of the patch wads you want to load. None by default. > >diff -Nru yadex-1.7.0-orig/ygd/hexen.ygd yadex-1.7.0/ygd/hexen.ygd >--- yadex-1.7.0-orig/ygd/hexen.ygd 2002-12-30 21:53:33.000000000 -0500 >+++ yadex-1.7.0/ygd/hexen.ygd 2012-06-17 18:47:12.494693225 -0400 >@@ -108,6 +108,7 @@ > ldt 101 x "?? Scroll right" "?? Scroll_Texture_Right" > ldt 102 x "?? Scroll up" "?? Scroll_Texture_Up" > ldt 103 x "?? Scroll down" "?? Scroll_Texture_Down" >+ldt 109 L "?? Force lightng" "?? Light_ForceLightning" > ldt 110 L "?? Raise light" "?? Light_RaiseByValue" > ldt 111 L "?? Lower light" "?? Light_LowerByValue" > ldt 112 L "?? Set light" "?? Light_ChangeToValue" >@@ -136,25 +137,12 @@ > # > > st 0 " Normal" "Normal" >-st 1 " Phased light" "light phased" # FIXME >-st 2 " Light start" "lightsequencestart" # FIXME >-st 3 " Light specl1" "lightsequencespecial1" # FIXME >-st 4 " Light specl2" "lightsequencespecial2" # FIXME >-st 9 " Secret" "Sector counts toward secret count" >+st 1 " Phased light" "light phased" >+st 2 " Light start" "lightsequencestart" >+st 3 " Light specl1" "lightsequencespecial1" >+st 4 " Light specl2" "lightsequencespecial2" > st 26 " Stairs1" "Stairs special 1" > st 27 " Stairs2" "Stairs special 2" >-st 40 " Wind east 1" "Wind east force 1" >-st 41 " Wind east 2" "Wind east force 2" >-st 42 " Wind east 3" "Wind east force 3" >-st 43 " Wind north 1" "Wind north force 1" >-st 44 " Wind north 2" "Wind north force 2" >-st 45 " Wind north 3" "Wind north force 3" >-st 46 " Wind south 1" "Wind south force 1" >-st 47 " Wind south 2" "Wind south force 2" >-st 48 " Wind south 3" "Wind south force 3" >-st 49 " Wind west 1" "Wind west force 1" >-st 50 " Wind west 2" "Wind west force 2" >-st 51 " Wind west 3" "Wind west force 3" > st 198 " Lightning 64" "Indoor lightning, +64 units" > st 199 " Lightning 32" "Indoor lightning, +32 units" > st 200 " Sky2" "Use MAPINFO sky2" >@@ -191,17 +179,21 @@ > thinggroup p rgb:4/f/4 "Player" > thinggroup m rgb:f/0/0 "Monster" > thinggroup w rgb:f/a/0 "Weapon" >-thinggroup a rgb:8/5/0 "Ammunition" >+thinggroup a rgb:8/5/0 "Mana" > thinggroup h rgb:2/8/0 "Health & armour" >+thinggroup A rgb:2/8/0 "Artifacts" >+thinggroup q rgb:2/8/0 "Quest items" > thinggroup b rgb:2/8/0 "Misc. bonus" > thinggroup k rgb:f/0/f "Key" > thinggroup P rgb:6/6/c "Plants" >+thinggroup t rgb:6/6/c "Stalagm. & stalact." >+thinggroup g rgb:6/6/c "Gargoyle statues" >+thinggroup T rgb:6/6/c "Table stuff" >+thinggroup D rgb:6/6/c "Dungeon stuff" > thinggroup d rgb:6/6/c "Misc. decoration" > thinggroup l rgb:6/6/c "Light source" >-#thinggroup g rgb:6/6/c "Gory decoration" >-#thinggroup c rgb:6/6/c "Corpse" >-thinggroup e rgb:0/b/d "Environment sound" >-thinggroup s rgb:0/b/d "Ambient sound" >+thinggroup s rgb:0/b/d "Sound" >+thinggroup S rgb:0/b/d "Special" > > # > # Definition of things >@@ -210,56 +202,268 @@ > # <desc> must not exceed 19 characters. > # > >-thing 1 p - 16 "Player 1 start" PLAY >-thing 2 p - 16 "Player 2 start" PLAY >-thing 3 p - 16 "Player 3 start" PLAY >-thing 4 p - 16 "Player 4 start" PLAY >+thing 1 p - 16 "Player 1 start *" PLAY >+thing 2 p - 16 "Player 2 start *" PLAY >+thing 3 p - 16 "Player 3 start *" PLAY >+thing 4 p - 16 "Player 4 start *" PLAY > thing 11 p - 16 "Deathmatch start" PLAYF1 > thing 14 p - 16 "Teleport exit" TELE >+thing 9100 p - 16 "Player 5 start *" PLAY >+thing 9101 p - 16 "Player 6 start *" PLAY >+thing 9102 p - 16 "Player 7 start *" PLAY >+thing 9103 p - 16 "Player 8 start *" PLAY > >-thing 31 m - 32 "Demon" DEMN >+thing 31 m - 32 "Chaos serpent" DEMN >+thing 34 m - 40 "Reiver" WRTH > thing 107 m - 20 "Centaur" CENT >+thing 114 m - 44 "Dark bishop" BISH > thing 115 m - 20 "Centaur leader" CENTF >-thing 120 m - 17 "Serpent leader" SSPTK # Not too sure... >-thing 121 m - 17 "Serpent" SSDV # Not too sure... >-thing 8020 m - 22 "Ice guy" ICEY >+thing 120 m - 17 "Stalker leader" SSPTK >+thing 121 m - 17 "Stalker" SSDV >+thing 254 m - 40 "Death wyvern *" DRAG >+thing 8020 m - 22 "Wendigo" ICEY >+thing 8080 m - 64 "Chaos serpent (gas)" DEM2 >+thing 10011 m - 40 "Reiver leader" WRTH > thing 10030 m - 25 "Ettin" ETTN >-thing 10060 m - 20 "Fire demon" FDMN >- >-thing 10 w - 17 "Serpent staff" WCSS # Cleric >-thing 53 w - 17 "Frost chards" WMCS # Mage >-thing 8010 w - 17 "Timon's axe" WFAX # Fighter >+thing 10060 m - 20 "Fire gargoyle" FDMN >+thing 10080 m - 80 "Heresiarch" SORC >+thing 10100 m - 32 "Zedek (fighter)" PLAYA8 >+thing 10101 m - 32 "Traductus (cleric)" CLERA8 >+thing 10102 m - 32 "Menelkir (mage)" MAGEA8 >+thing 10200 m - 20 "Korax" KORX >+ >+thing 10 w - 17 "Serpent staff" WCSS >+thing 12 w - 20 "Quietus blade" WFR1 >+thing 13 w - 20 "Quietus guard" WFR2 >+thing 16 w - 20 "Quietus hilt" WFR3 >+thing 18 w - 20 "Wraithverge head" WCH1 >+thing 19 w - 20 "Wraithverge center" WCH2 >+thing 20 w - 20 "Wraithverge grip" WCH3 >+thing 21 w - 20 "Bloodscourge head" WMS1 >+thing 22 w - 20 "Bloodscourge center" WMS2 >+thing 23 w - 20 "Bloodscourge grip" WMS3 >+thing 53 w - 17 "Frost chards" WMCS >+thing 123 w - 10 "Hammer of retributn" WFHM >+thing 8009 w - 10 "Firestorm" WCFM >+thing 8010 w - 17 "Timon's axe" WFAX >+thing 8040 w - 20 "Arc of death" WMLG > > thing 122 a - 17 "Blue manna" MAN1 > thing 124 a - 17 "Green manna" MAN2 > thing 8004 a - 17 "Combined manna" MAN3 > > thing 81 h - 17 "Crystal vial" PTN1 >-thing 82 h - 17 "Quartz flask" PTN2 >-thing 8000 h - 17 "Flechette" PSBG >+thing 8005 h - 10 "Mesh armor" ARM1 >+thing 8006 h - 20 "Falcon shield" ARM2 > thing 8007 h - 17 "Platinum helmet" ARM3 >+thing 8008 h - 20 "Amulet of warding" ARM4 > >-thing 314 k - 17 "Stone (?) key" KEY7 >+thing 30 A - 20 "Porkalator" ARTIPORK >+thing 32 A - 20 "Mystic urn" ARTISPHL >+thing 33 A - 20 "Torch" ARTITRCH >+thing 36 A - 20 "Chaos device" ARTIATLP >+thing 82 A - 17 "Quartz flask" PTN2 >+thing 83 A - 20 "Wings of wrath" SOAR >+thing 84 A - 20 "Icon of defender" INVU >+thing 86 A - 15 "Dark servant" ARTISUMN >+thing 8000 A - 17 "Flechette" PSBG >+thing 8002 A - 20 "Boots of speed" ARTISPED >+thing 8003 A - 20 "Krater of might" ARTIBMAN >+thing 8041 A - 20 "Dragonskin bracers" ARTIBRAC >+thing 10040 A - 20 "Banishment device" ARTITELO >+thing 10110 A - 20 "Disc of repulsion" ARTIBLST >+thing 10120 A - 20 "Mystic ambient inc" ARTIHRAD >+ >+thing 9002 q - 20 "Yorick's skull" ARTISKLL >+thing 9003 q - 20 "Heart of D'Sparil" ARTIBGEM >+thing 9004 q - 20 "Ruby planet" ARTIGEMR >+thing 9005 q - 20 "Emerald planet 1" ARTIGEMG >+thing 9006 q - 20 "Sapphire planet 1" ARTIGEMB >+thing 9007 q - 20 "Daemon codex" ABK1 >+thing 9008 q - 20 "Liber oscura" ABK2 >+thing 9009 q - 20 "Emerald planet 2" ARTIGMG2 >+thing 9010 q - 20 "Sapphire planet 2" ARTIGMB2 >+thing 9014 q - 20 "Flame mask" ARTISKL2 >+thing 9015 q - 20 "Glaive seal" ARTIFWEP >+thing 9016 q - 20 "Holy relic" ARTICWEP >+thing 9017 q - 20 "Sigil of the Magus" ARTIMWEP >+thing 9018 q - 20 "Clock gear 1" ARTIGEAR >+thing 9019 q - 20 "Clock gear 2" ARTIGER2 >+thing 9020 q - 20 "Clock gear 3" ARTIGER3 >+thing 9021 q - 20 "Clock gear 4" ARTIGER4 >+ >+thing 8030 k - 10 "Steel key" KEY1 >+thing 8031 k - 10 "Cave key" KEY2 >+thing 8032 k - 10 "Axe key" KEY3 >+thing 8033 k - 10 "Fire key" KEY4 >+thing 8034 k - 10 "Emerald key" KEY5 >+thing 8035 k - 10 "Dungeon key" KEY6 >+thing 8036 k - 10 "Silver key" KEY7 >+thing 8037 k - 10 "Rusted key" KEY8 >+thing 8038 k - 10 "Horn key" KEY9 >+thing 8039 k - 10 "Swamp key" KEYA >+thing 8200 k - 10 "Castle key" KEYB > >+thing 24 P - 20 "Tree trunk (brown)" TRE1 >+thing 25 P - 20 "Tree trunk (brownD)" TRE1 > thing 26 P - 17 "Swamp tree tall" TRE2 > thing 27 P - 17 "Swamp tree short" TRE3 >+thing 28 P - 20 "Tree stump (splint)" STM1 >+thing 29 P - 20 "Tree stump" STM2 >+thing 39 P - 20 "Mushroom (large, L)" MSH1 >+thing 40 P - 20 "Mushroom (large, R)" MSH2 >+thing 41 P - 20 "Mushroom (med, L)" MSH3 >+thing 42 P - 20 "Mushroom (small, R)" MSH4 >+thing 44 P - 20 "Mushroom (small)" MSH5 >+thing 45 P - 20 "Mushroom (small, F)" MSH6 >+thing 46 P - 20 "Mushroom (small, B)" MSH7 >+thing 47 P - 20 "Mushroom (small, M)" MSH8 >+thing 60 P - 20 "Vine" TRE3 > thing 78 P - 17 "Tree leaning right" TRE4 > thing 79 P - 17 "Tree leaning left" TRE5 > thing 80 P - 17 "Gnarled tree right" TRE6 > thing 87 P - 17 "Gnarled tree left" TRE7 >+thing 113 P - 10 "Blowing leaves" LEF1 > thing 8062 P - 17 "Dead tree" TRDT > thing 8068 P - 17 "Conic tree" XMAS >- >-thing 48 d - 17 "Stalactite+gmite" SGMP >-thing 72 d - 17 "Statue" STT2 >-thing 74 d - 17 "Short statue" STT4 >+thing 8101 P - 20 "Shrub (small)" SHB1 >+thing 8102 P - 20 "Shrub (large)" SHB2 >+thing 8103 P - 20 "Bucket (hanging)" BCKT >+thing 8104 P - 20 "Mushroom (explodng)" SHRM >+ >+thing 48 t - 17 "Stalactite+gmite" SGMP >+thing 49 t - 20 "Stalagmite (large)" SGM1 >+thing 50 t - 20 "Stalagmite (medium)" SGM2 >+thing 51 t - 20 "Stalagmite (small)" SGM3 >+thing 52 t - 20 "Stalactite (large)" SLC1 >+thing 56 t - 20 "Stalactite (medium)" SLC2 >+thing 57 t - 20 "Stalactite (small)" SLC3 >+thing 89 t - 20 "Ice stalactite(lrg)" ICT1 >+thing 90 t - 20 "Ice stalactite(med)" ICT2 >+thing 91 t - 20 "Ice stalactite(sml)" ICT3 >+thing 92 t - 20 "Ice stalactite(tny)" ICT4 >+thing 93 t - 20 "Ice stalagmite(lrg)" ICM1 >+thing 94 t - 20 "Ice stalagmite(med)" ICM2 >+thing 95 t - 20 "Ice stalagmite(sml)" ICM3 >+thing 96 t - 20 "Ice stalagmite(tny)" ICM4 >+ >+thing 5 g - 20 "Gargoyle statue w/s" STTW >+thing 72 g - 17 "Stone gargoyle tall" STT2 >+thing 73 g - 20 "Ice gargoyle tall" STT3 >+thing 74 g - 17 "Stone gargoyle shrt" STT4 >+thing 76 g - 20 "Ice gargoyle short" STT5 >+thing 8044 g - 20 "Wooden gargoyle tal" GAR1 >+thing 8045 g - 20 "Fire gargoyle tall" GAR2 >+thing 8046 g - 20 "Red gargoyle tall" GAR3 >+thing 8047 g - 20 "Wooden gargoyle tal" GAR4 >+thing 8048 g - 20 "Metal gargoyle tall" GAR5 >+thing 8049 g - 20 "Fire gargoyle short" GAR6 >+thing 8050 g - 20 "Red gargoyle short" GAR7 >+thing 8051 g - 20 "Wooden gargoyle srt" GAR8 >+thing 8052 g - 20 "Metal gargoyle shrt" GAR9 >+thing 9011 g - 20 "Gargoyle statue" STWN >+ >+thing 8500 T - 20 "Stein (tall)" TST1 >+thing 8501 T - 20 "Stein (short)" TST2 >+thing 8502 T - 20 "Candle w/spider web" TST3 >+thing 8503 T - 20 "Candle (short)" TST4 >+thing 8504 T - 20 "Candle (tall)" TST5 >+thing 8505 T - 20 "Goblet (spilled)" TST6 >+thing 8506 T - 20 "Goblet (tall)" TST7 >+thing 8507 T - 20 "Goblet (short)" TST8 >+thing 8508 T - 20 "Goblet w/silver bnd" TST9 >+thing 8509 T - 20 "Meat cleaver" TST0 >+ >+thing 61 D - 20 "Corpse impaled" CPS1 >+thing 62 D - 20 "Corpse sleeping" CPS2 >+thing 71 D - 20 "Corpse hung legs" CPS3 >+thing 108 D - 20 "Corpse hung" CPS4 >+thing 109 D - 20 "Corpse bleeding" CPS5 >+thing 110 D - 20 "Corpse chained" CPS6 >+thing 111 D - 10 "Pool of blood" BDPL >+thing 8067 D - 20 "Iron maiden" IRON >+thing 8071 D - 20 "Chain (short)" CHNS >+thing 8072 D - 20 "Chain (long)" CHNSB0 >+thing 8073 D - 20 "Chain heart on hook" CHNSC0 >+thing 8074 D - 20 "Chain w/large hook" CHNSD0 >+thing 8075 D - 20 "Chain w/small hook" CHNSE0 >+thing 8076 D - 20 "Chain w/spiked ball" CHNSF0 >+thing 8077 D - 20 "Chain skull on hook" CHNSG0 >+ >+thing 6 d - 20 "Rock w/moss (tiny)" RCK1 >+thing 7 d - 20 "Rock w/moss (small)" RCK2 >+thing 9 d - 20 "Rock w/moss (medium)" RCK3 >+thing 15 d - 20 "Rock w/moss (large)" RCK4 >+thing 37 d - 20 "Stump w/moss (short)" STM3 >+thing 38 d - 20 "Stump w/moss (tall)" STM4 >+thing 58 d - 20 "Moss (three strands)" MSS1 >+thing 59 d - 20 "Moss (one strand)" MSS2 >+thing 63 d - 20 "Tombstone (R.I.P.)" TMS1 >+thing 64 d - 20 "Tombstone (Shane)" TMS2 >+thing 65 d - 20 "Tombstone (large cross)" TMS3 >+thing 66 d - 20 "Tombstone (Brian R.)" TMS4 >+thing 67 d - 20 "Tombstone (circular cross)" TMS5 >+thing 68 d - 20 "Tombstone (small cross on pedestal)" TMS6 >+thing 69 d - 20 "Tombstone (Brian P.)" TMS7 > thing 77 d - 17 "Banner" BNR1 >- >-thing 54 l - 17 "Torch" WLTR >-thing 8061 l - 17 "FIXME" BRTR >- >-thing 314 e - 17 "Bogus sound" >- >-thing 314 s - 17 "Bogus sound" >- >- >+thing 88 d - 20 "Log" LOGG >+thing 97 d - 20 "Rock formation (large, brown)" RKBL >+thing 98 d - 20 "Rock formation (small, brown)" RKBS >+thing 99 d - 20 "Rock formation (small, gray)" RKBK >+thing 100 d - 20 "Rubble (large)" RBL1 >+thing 101 d - 20 "Rubble (small)" RBL2 >+thing 102 d - 20 "Rubble (medium)" RBL3 >+thing 103 d - 20 "Vase on pedestal" VASE >+thing 104 d - 20 "Pot (tall, skinny) *" POT1 >+thing 105 d - 20 "Pot (medium, skinny) *" POT2 >+thing 106 d - 20 "Pot (short, chipped) *" POT3 >+thing 140 d - 20 "Sparkling red smoke" TSMK >+thing 8064 d - 20 "Suit of armor *" SUIT >+thing 8065 d - 40 "Bell" BBLL >+thing 8100 d - 20 "Barrel" BARL >+thing 9012 d - 20 "Pedestal" GMPD >+thing 10001 d - 20 "Fog (small) *" FOGS >+thing 10002 d - 20 "Fog (medium) *" FOGM >+thing 10003 d - 20 "Fog (large) *" FOGL >+thing 10090 d - 20 "Spike (down)" TSPKC0 >+thing 10091 d - 20 "Spike (up)" TSPK >+ >+thing 17 l - 20 "Chandelier w/flame" CDLR >+thing 54 l - 17 "Wall torch w/flame" WLTR >+thing 55 l - 20 "Wall torch" WLTRI0 >+thing 116 l - 10 "Brazier w/flame" TWTR >+thing 117 l - 10 "Brazier" TWTRI0 >+thing 119 l - 20 "Candles" CNDL >+thing 8042 l - 20 "Minotaur statue f" FBUL >+thing 8043 l - 20 "Minotaur statue" FBULH0 >+thing 8060 l - 20 "Fire skull" FSKL >+thing 8061 l - 17 "Brazier w/flame sm" BRTR >+thing 8063 l - 20 "Chandelier" CDLRD0 >+thing 8066 l - 20 "Candle (blue)" CAND >+thing 8069 l - 20 "Cauldron (w/flame)" CDRNB0 >+thing 8070 l - 20 "Cauldron" CDRN >+thing 10500 l - 20 "Flame (small, t) *" FFSM >+thing 10501 l - 20 "Flame (small, cnt)" FFSMC0 >+thing 10502 l - 20 "Flame (large, t) *" FFLG >+thing 10503 l - 20 "Flame (large, cnt)" FFLGF0 >+ >+thing 1400 s - 20 "Stone" TELE >+thing 1401 s - 20 "Heavy" TELE >+thing 1402 s - 20 "Metal" TELE >+thing 1403 s - 20 "Creak" TELE >+thing 1404 s - 20 "Silent" TELE >+thing 1405 s - 20 "Lava" TELE >+thing 1406 s - 20 "Water" TELE >+thing 1407 s - 20 "Ice" TELE >+thing 1408 s - 20 "Earth crack" TELE >+thing 1409 s - 20 "Metal2" TELE >+thing 1410 s - 20 "Wind blowing" TELE >+ >+thing 118 S - 10 "Magic step" TLGL >+thing 3000 S - 20 "Polyobject anchor" ICPRD0 >+thing 3001 S - 20 "Start spot" SBFXH0 >+thing 3002 S - 20 "Start spot w/crush" SBFXC0 >+thing 9001 S - 10 "Map spot *" TELEC0 >+thing 9013 S - 10 "Map spot w/gravity" TELED0 >+thing 10000 S - 20 "Spawn fog *" SPIRK0 >+thing 10225 S - 20 "Spawn bat *" ABATC3C7
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 830628
:
590809
| 593646 |
603298