diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..449ffea --- /dev/null +++ b/CHANGES @@ -0,0 +1,213 @@ +THIS IS A GENERATED FILE -- DO NOT EDIT ! +Edit docsrc/changes.html instead. + + History of changes for DeuTex + + DeuTex 4.0.1 (AYM 1999-09-10) + + + CLI: reworked the command line arguments parsing, with the + following consequences. + o Options can now be abbreviated freely, as long as the + abbreviation is not ambiguous. For example, you can use + -heretic, -hereti, -heret, -here or -her but not -he + because that could also be the abbreviation for -help + (or -hexen, for that matter). On the other hand, -h is + allowed because it's not an abbreviation (there's really + a -h option). + o -heretic and -hexen now work (they were "hidden" by + -h[elp]). + o -v@ has been split in -v0, -v1 ... -v5 because the new + code does not allow excess characters after an option. + -vstring where string is anything else than "0" through + "5" now triggers an error (it used to be accepted + silently). I hope no one relied on the old undocumented + behaviour. + o Certain silly command line arguments that would have + worked before would now trigger an error. For example, + it used to be possible to type -extramarital or + -extermination for -extract but not anymore. The old + code defined relatively short options (-ext) and + accepted command line arguments as long as the defined + option was an initial substring of the command line + argument. The new code does the reverse; it defines + relatively long options (-extract) and accepts command + line argument as long as they're an initial substring of + the defined option. + + Code: replaced direct testing of __MSDOS__, __OS2__, + __GNUC__, __BORLANDC__ by DT_CC and DT_OS. This is hopefully + going to make Udo's job a bit easier. + + Code: now uses the same fopen() modes for all platforms: + "{rw}b" for binary mode and "{rw}" for text mode, as per the + ANSI/ISO C standard. This will fix the problem Udo Munk + reported with the Cygwin build opening binary files in text + mode and thus failing miserably. Note that certain DOS C + compilers can be configured so that "{rw}" opens files in + binary mode. Don't do that ! If you have problems with text + files on DOS, make sure your C compiler is configured so that + "{rw}" opens files in text mode. + + Code: added to the distribution archive gifcodec.c that I had + forgotten to include (it's not used anyway). + + Code: added to the distribution archive + src/{deusf,deusfos,deutex,deutexos}.def that I had forgotten + to include. I guess that's Windows/OS/2-only stuff. + + Doc: updated making.txt and renamed it as INSTALL for + homogeneity. Removed obsolete reference to alpha.sh and the + file itself. + + Doc: made more legal updates. + + Doc: documented DOOMWADDIR in the man page. + + Misc: changed the default graphics format for Unix from GIF + to PPM, so that fewer user sites are broken if and when GIF + support is removed. For the same reason, added a warning + message when -gif is used or the first time an image is read + from a GIF file. + + Misc: changed the lookup order for images to PPM, BMP, GIF + (was BMP, GIF, PPM). + + Platform: fixed a couple of things that didn't work on 16-bit + platforms (real-mode DOS). + + Platform: now compiles on DOS with Borland C++ 4.0. + + Platform: now compiles on DOS with MSC 6.0. The MSC 6.0 build + is functional but limited because it can't allocate blocks + larger than 64 kB, which is insufficient for certain images. + I can't use halloc() instead of malloc() because it does not + supporting resizing (i.e. there's no hrealloc() function). + + Platform: in response to Udo's remarks, DJGPP and Cygwin are + now properly identified (__DJGPP__ and __CYGWIN__). + + Platform: added sanity checks on specified-size types Int32 + and friends. + + DeuTex 4.0.0a3 (AYM 1999-09-05) + + + Code: removed incongruous #define-ing of O_BINARY and + SEEK_SET. + + Code: after Udo Munk's report, fixed warnings in + o src/color.c(74) + o src/ident.c(583) + o src/ident.c(658) + o src/mkwad.c(78) + o src/mkwad.c(79) + o src/mkwad.c(80) + o src/mkwad.c(81) + o src/picture.c(903) + o src/picture.c(912) + + Doc: updated making.txt. + + Legal: as agreed to by Olivier Montanuy, DeuTex is now + entirely GPL'd. Well, almost entirely, since it includes code + written by different authors in lzw.c and elsewhere. Changed + the notices in the source files and added new file LICENSE to + clarify things. + + Makefile: should now work with all C compilers (removed -Wall + from CFLAGS). + + Makefile: clean now removes the DOS executables if they + exist. + + Makefile: does not compile with debug information in by + default anymore. + + Makefile: new targets dall, ddt, dds, ddeutex and ddeusf for + compiling with debug information and all warnings. + + Makefile: new target help. + + Makefile: new target distdos. + + Platform: replaced unlink() by remove() for portability. + Thanks to Udo for reporting this. + + Platform: on 8.3 filesystems, make should not choke on + docsrc/changes.html anymore. Thanks to Udo for reporting + this. + + Sound: corrected some misleading endianness comments in + sound.c. + + DeuTex 4.0.0a2 (AYM 1999-08-14) + + + Game: easier to use with Strife (now looks for "strife1.wad", + new option "-strife"). + + Game: easier to use with Hexen (new option "-hexen"). + + Command line: new options "-hexen" and "-strife". + + Command line: new option "--version" (prints version number + and returns 0). + + Doc: various changes in the man page, in the output of + "-help" and "-man" and elsewhere. + + Makefile: various improvements. + + Distribution: set modes straight. + + DeuTex 4.0.0a1 (AYM 1999-08-12) + + + General: fixed many segfaults that were caused by attempts to + fclose (NULL). + + Game: Strife is now supported. + + Wad: new options -be, -le, -ibe, -ile, -obe and -ole to + control the endianness of the wads. Caution: don't use them + if you don't know what you're doing ! As far as I know, wads + are always little-endian regardless of the architecture of + the host. Therefore, I see no reason for someone in his/her + right mind to create a big-endian wad. Those options are here + more for the sake of completeness than anything else. + + Wad: made "%" legal in names, to deal with Strife's + "INVFONG%" and "INVFONY%". + + Wad, graphics: end-of-flats marker is now F_END by default + instead of FF_END. The reason for this change is that, with + F_END, you don't need DeuSF to get Doom to see your new + flats. Should you need to, it's still possible to get FF_END + by using -fend. + + Graphics: the default transparent colour is now rgb:00/2f/2f. + It used to be cyan (rgb:00/ff/ff) which was blindingly + bright, especially compared to the usually dark colours used + in Doom textures. It's no fun to tweak shades of dark brown + on a cyan background. + To reuse images done with/for a previous version of DeuTex, + you need to either invoke DeuTex with "-rgb 0 255 255" or + convert your images by replacing all occurrences of colour + (0, 255, 255) by colour (0, 47, 47). To preserve + compatibility with WinTex, I didn't change the default + transparent colour in WinTex mode ; it's still (0, 255, 255). + + Graphics: fixed segfaults due to bug in conversion of bitmap + images to Doom pictures. Occured in certain 2-pixel high + images such as STBFN045 in the Strife iwad. + + Graphics: now supports pictures and textures up to 509 high + (was limited to 128). + + Graphics: now supports pictures and textures up to 1024 wide + (was limited to 512). + + Graphics: new option "-pf" to deal with the different picture + format in the Doom alpha iwad (the underlying functionality + is not implemented yet !) + + Graphics: using -ppm does not cause anymore DeuTex to abort + with "Bug: *** psvit ***". + + Graphics: fixed "-ppm" message. + + Sound, platform: a bug that must have prevented reading .wav + files on big endian machines has been squashed. + + Command line: options can't start with a slash ("/") anymore. + I don't think anyone used it and was a silly feature for a + Unix program. + + Command line: not case insensitive anymore. + + Command line: changed the wording of error messages to use + "option" instead of "command". + + Command line: added options "-?" and "--help" as synonyms for + "-help". + + Doc: new option "-man" to print help in troff -man source + format for inclusion in the man page. + + Doc: the version number is now a free-form string. + + Doc: Made on-line help more compact. + + Doc: updated "making.txt". + + Doc: made a proper README file. + + Makefile: renamed "unix" target as "strip". + + Makefile: new target "install". + + Makefile: new target "dist". + + Platform: reworked the handling of endianness. DeuTex used to + deal with that through a set of macros that swapped bytes + whenever the required endianness was not the same as the + native endianness. To known the native endianness, DeuTex + relied on a macro defined via -D. + There were two problems with this scheme. Firstly, Olivier + got the meaning of "little endian" and "big endian" backwards + and defining LITTLE_ENDIAN in fact caused DeuTex to believe + it was being compiled for a big endian machine. As the glibc + headers happen to define LITTLE_ENDIAN if the machine is + little endian, compiling DeuTex on a glibc little endian + Linux system was impossible unless you made changes to the + source. + The other, more fundamental, objection against the old + approach is that, as it needed the user to tell it about the + native endianness by modifying the makefile, it prevented + unattended builds and made things difficult for naive users. + The new method eliminates this problem by using a different + algorithm that does not need to know the native endianness. + The end result is that you don't have to worry about + endianness anymore. + + Internal: in TXTinit(), removed useless "% 0xFF" in index of + TXTval. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..a3f6b12 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/COPYING.LIB b/COPYING.LIB new file mode 100644 index 0000000..161a3d1 --- /dev/null +++ b/COPYING.LIB @@ -0,0 +1,482 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..8d432eb --- /dev/null +++ b/INSTALL @@ -0,0 +1,253 @@ + + + DeuTex/DeuSf compilation + + by Olivier Montanuy + Revised AYM 1999-08-12 + + + + **************************** + * Structure of the sources * + **************************** + +DeuTex and DeuSF share the same sources. +When compiling, you must include all sources and define one of +those flags so that the C pre-processor knows which part to select: + +- DeuSF to compile DeuSF +- DeuTex to compile DeuTex +For a windows DLL +- LDeuTex to compile DeuTex.DLL for Windoze + + + *********************** + * Generic Unix-like * + *********************** + +Type + + make + make install <- as root + +See near the end of the file for any OS-specific details. + + + *************** + * DOS * + * Windows 95 * + * Windows 98 * + * Windows NT * + *************** + +Borland C++ +Turbo C++ + + DeuTex can be built with Borland C++ 4.0. Other versions of the + Borland compilers might work too but they've not been tried. To + compile, type + + dos\buildbc dir + + where dir is the directory where the compiler is installed, + followed by a backslash (E.G. "dos\buildbc c:\bc4\"). Once + deusf.exe and deutex.exe are built, copy them manually to a + directory in your path. + + Don't try to use the makefile; due to idiosyncrasies in the CLI of + bcc, limitations of Borland make and of the FAT filesystem, it + won't work. There are old project files lying around in old but + they've not been updated since 1995 so don't use them either. + + The compiler can be configured so that "{rw}" opens files in + binary mode. Don't do that ! If you have problems with text files + on DOS, make sure the compiler is configured so that "{rw}" opens + files in _text_ mode (that's the default). + +Microsoft C + + As of version 4, DeuTex can be built with MSC 6.0. Other versions + of MSC might work too, but have not been tried. To compile with + MSC 5.1, you would have to remove the #error directives, since + these are not supported in that version. + + To compile, type + + dos\buildmsc + + (that script assumes INCLUDE, LIB and PATH are properly set up). + Once deusf.exe and deutex.exe are built, copy them manually to a + directory in your path. + + The compiler can be configured so that "{rw}" opens files in + binary mode. Don't do that ! If you have problems with text files + on DOS, make sure the compiler is configured so that "{rw}" opens + files in _text_ mode (that's the default). + +DJGPP 2.* + + Thanks to Udo Munk, DeuTex can now be built with DJGPP. + + You need a Unix toolset comprising ln, sh and touch. Certain + targets also require cp, GNU find, lynx, rm, tar, tr zip and a + Unix mkdir but those are maintainer targets and you probably don't + need them. + + If you build on a 8.3 filesystem (plain old FAT), make is going to + choke when trying to "touch .deutex" and "touch .deusf". Replace + all occurrences of ".deutex" and ".deusf" by "_deutex" and + "_deusf" in the makefile and start again. + + To compile, type + + make + + If it doesn't work, tell me about it. You will get a warning about + ftruncate() being undeclared. ftruncate() is supposed to be a Unix + function. If you have a unistd.h header, try to insert a "#include + " in tools.c. Else, I don't know what to do. + + After deusf.exe and deutex.exe are created, copy them to a + directory in your path. + +Cygwin + + Thanks to Udo Munk, DeuTex can now be built with Cygwin. + + You need a Unix toolset comprising ln, sh and touch. Certain + targets also require cp, GNU find, lynx, rm, tar, tr zip and a + Unix mkdir but those are maintainer targets and you probably don't + need them. + + If you build on a 8.3 filesystem (plain old FAT), make is going to + choke when trying to "touch .deutex" and "touch .deusf". Replace + all occurrences of ".deutex" and ".deusf" by "_deutex" and + "_deusf" in the makefile and start again. + + To compile, type + + make + + and then copy deusf.exe and deutex.exe to a directory in your + path. If it doesn't work, tell me about it. + + + *************** + * Windoze 3.1 * + *************** + by Olivier Montanuy + +Use the DOS deutex version under windows, with a suitable deutex.pif + +.DLL +DeuTex itself can't be compiled as a 16-bit windoze DLL (too big). +the lbdeutex is for the visual basic shell. + + + **************** + * Unix SUN O/S * + **************** + by Olivier Montanuy + +Unix: Sun Sparc 1, 10, 20, IPX +gcc: 2.5.8 +The makefile provided for Unix and Linux does not compile .o +objects. it compiles .ot for DeuTex and .os for DeuSF. +That little trick is useful to avoid linker problems. +type: make + make install (as root) + + + ******************** + * Silicon Graphics * + ******************** + by Chuck Rossi + +type: make + make install (as root) + + + ********************** + * Linux * + ********************** + by Per Allansson + and Andr� Majorel + +Linux: kernel 1.1.52, 2.0.34; libc 4.5.26, glibc 2.0.7 +gcc: 2.5.8, 2.7.2.3 +type: make + make install (as root) + + + ****************************** + * DEC Alpha 64 bit processor * + ****************************** + by James Bonfield + jkb@mrc-molecular-biology.cambridge.ac.uk + + + ************** + * OS/2 2 2.1 * + ************** + +Borland C++ +Turbo C++ + + Might work. See the corresponding paragraphs in the DOS section. + +Microsoft C + + Might work. See the corresponding paragraphs in the DOS section. + +IBM C Set++ 2.1 (by mark.mathews@channel1.com) + + For DEUTEXOS.EXE you need deutexos.mak and deutexos.def + To make DEUTEXOS.EXE type: nmake -f deutexos.mak + + For DEUSFOS.EXE you need deusfos.mak and deusfos.def + To make DEUSFOS.EXE type : nmake -f deusfos.mak + + AYM 1999-08-12: Where are deutexos.mak and deusfos.mak ? Better use + the main makefile anyway... + + + ************************ + * Porting DeuTex/DeuSF * + ************************ + +The name of the OS DeuTex is being compiled for is in DT_OS, defined in +deutex.h : + + #define DT_OS 'd' /* MS-DOS */ + #define DT_OS 'o' /* OS/2 */ + #define DT_OS 'u' /* Unix (in fact, anything else) */ + +The name of the compiler is in DT_CC, defined in deutex.h : + + #define DT_CC 'b' /* Borland C */ + #define DT_CC 'c' /* GCC/EGCS with Cygwin */ + #define DT_CC 'd' /* DJGPP */ + #define DT_CC 'g' /* GCC/EGCS */ + #define DT_CC 'i' /* IBM C Set++ */ + #define DT_CC 'm' /* Microsoft C */ + #define DT_CC '?' /* Unknown compiler */ + +Testing the existence of other macros, such as __MSDOS__, __GNUC__ etc. +is discouraged. Use DT_OS and DT_CC instead. + +DeuTex uses specified size types Int16, Int32, UInt32, etc. Those are +defined in deutex.h. The definitions are believed to be correct for all +16-bit and 32-bit platforms. 64-bit platforms might require some +tweaking there. There is an alternate set of #define directives under +#ifdef __alpha but a clever use of limits.h and/or inttypes.h might be a +better idea. If you're the lucky owner of a 64-bit machine, send me your +diffs. Note that DeuTex and DeuSF check that the specified size types +are correctly defined and warn you if they aren't. + +Some structures related to pictures or to DOOM assumes that no word or +long word alignement occur. if the entries are not put contiguously, +DeuTex/DeuSF will not work, but there will be no warning. + +Most of the O/S related functions are in tools.c. + + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0a4659f --- /dev/null +++ b/LICENSE @@ -0,0 +1,73 @@ + License terms for DeuTex + +------------------------------------------------------------------------ + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + and Copyright � 1999 Andr� Majorel. + +The parts of DeuTex that have been written by Olivier Montanuy, +Kevin McGrail, Andr� Majorel and other contributors are +distributed under the terms of version 2 of the GNU general +public license (GPL). + +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 Library General Public +License along with this library; if not, write to the Free +Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307, USA. + +------------------------------------------------------------------------ + +However, the DeuTex distribution includes material that was +written by other people or distributed under different licenses : + +1. DeuTex incorporates code derived from DEU 5.21. DEU 5.21 was + put in the public domain in 1994 by Rapha�l Quinet and Brendon + Wyber. No part of DeuTex is public-domain, however. + +2. The file gifcodec.c is Copyright � 1995 David Kaplan. + +3. The file lzw.c contains the following notes : + + > Copyright 1993, David Koblas (koblas@netcom.com) + > + > Permission to use, copy, modify, and to distribute this software + > and its documentation for any purpose is hereby granted without + > fee, provided that the above copyright notice appear in all + > copies and that both that copyright notice and this permission + > notice appear in supporting documentation. There is no + > representations about the suitability of this software for + > any purpose. this software is provided "as is" without express + > or implied warranty. + + > This file is derived from ppmtogif.c and giftoppm.c + > only the compression/decompression routines were kept. + > + > Based on GIFENCOD by David Rowley . + > A Lempel-Zim compression based on "compress". + > + > Copyright (C) 1989 by Jef Poskanzer. + > + > Permission to use, copy, modify, and distribute this software and + > its documentation for any purpose and without fee is hereby + > granted, provided that the above copyright notice appear in all + > copies and that both that copyright notice and this permission + > notice appear in supporting documentation. This software is + > provided "as is" without express or implied warranty. + > + > The Graphics Interchange Format(c) is the Copyright property of + > CompuServe Incorporated. GIF(sm) is a Service Mark property of + > CompuServe Incorporated. + +4. The files endianio.c and endianm.c are Copyright � Andr� Majorel 1999 + and available under the terms of the LGPL. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..33dbde3 --- /dev/null +++ b/Makefile @@ -0,0 +1,243 @@ +# Makefile of DeuTex/DeuSF +# by Per Allansson, Olivier Montanuy and Andr� Majorel +# +# Platform-specific notes: +# +# Unix User targets should work on all Unices. Some _developer_ +# targets, however, require lynx, GCC or GNU tar and gzip. +# +# DOS "make [all]" should work with any C compiler. +# "make install" will most likely not work. You'll have to +# install the executables by hand. +# +# Others Don't know. Send feedback to the maintainer. +# + +PREFIX=/usr/local + +# Compiled by users +CFLAGS = -O2 +CC = cc +LDFLAGS = + +# Compiled by developers +DCFLAGS = -g -Wall +DCC = gcc +DLDFLAGS = -g + +#DEFINES = -DDT_ALPHA + +######### do not edit after this line ######### +DISTARC = deutex-$$(cat VERSION).tar.gz # "deutex-4.0.0.tar.gz" +DISTARCDOS = dtex$$(tr -cd '[0-9]' $@ + +strip: deutex deusf + strip deutex + strip deusf + +doc: $(DOC) + +CHANGES: docsrc/changes.htm* VERSION + echo 'THIS IS A GENERATED FILE -- DO NOT EDIT !' >$@ + echo 'Edit docsrc/changes.html instead.' >>$@ + lynx -dump $< >>$@ + +README: docsrc/README VERSION scripts/process + scripts/process $< $(SRC_NON_GEN) >$@ + +TODO: docsrc/todo.htm* VERSION + echo 'THIS IS A GENERATED FILE -- DO NOT EDIT !' >$@ + echo 'Edit docsrc/todo.html instead.' >>$@ + lynx -dump $< >>$@ + +deutex.6: docsrc/deutex.6 VERSION scripts/process + scripts/process $< $(SRC_NON_GEN) >$@ + +deusf.6: deutex.6 + @if [ ! -e $@ ]; then ln -s $< $@; fi + @if [ ! -L $@ ]; then echo "Can't overwrite $@"; false; fi + +clean: + rm -f $(OBJTEX) $(OBJSF) $(DOBJTEX) $(DOBJSF) deutex deusf + if [ -f deutex.exe ]; then rm deutex.exe; fi + if [ -f deusf.exe ]; then rm deusf.exe; fi + +# dist - make the distribution archive for Unix (.tar.gz) +dist: $(DISTFILES) + mkdir -p $(DISTDIR) + cp -dpP $(DISTFILES) $(DISTDIR) + tar -zcf $(DISTARC) $(DISTDIR) + rm -rf $(DISTDIR) + +# distdos - make the distribution archive DOS (.zip, 8+3) +distdos: $(DISTFILES) + mkdir -p $(DISTDIRDOS) + cp -dpP $(DISTFILES) $(DISTDIRDOS) + if [ -e $(DISTARCDOS) ]; then rm $(DISTARCDOS); fi + zip -D -X -9 -r $(DISTARCDOS) $(DISTDIRDOS) + rm -rf $(DISTDIRDOS) + printf 'DeuTex %s\nhttp://www.teaser.fr/~amajorel/deutex/'\ + "$$(cat VERSION)" | zip -z $(DISTARCDOS) + +# save - your daily backup +save: + tar -zcvf ../deutex-$$(date '+%Y%m%d').tar.gz\ + --exclude "*~" --exclude "*.o"\ + --exclude "*.os" --exclude "*.ot" . + +help: + @echo "Targets for end users:" + @echo " make [all] Build DeuTex, DeuSF and the doc" + @echo " make install Install DeuTex, DeuSF and the doc" + @echo + @echo "Targets for developers:" + @echo " make doc Just the doc" + @echo " make dall Same as ddeutex + ddeusf" + @echo " make ddt Same as ddeutex" + @echo " make dds Same as ddeusf" + @echo " make ddeutex Debug version of DeuTex -> ./deutex" + @echo " make ddeusf Debug version of DeuSF -> ./deusf" + @echo " make dist Distribution archive -> ./deutex-VERSION.tar.gz" + @echo " make distdos Distribution archive -> ./dtexVERSION.zip" + @echo " make save Backup archive -> ../deutex-YYYYMMDD.tar.gz" + @echo " make strip Strip ./deutex and ./deusf" + @echo " make clean Remove executables and object files" + + diff --git a/README b/README new file mode 100644 index 0000000..50cd4d8 --- /dev/null +++ b/README @@ -0,0 +1,38 @@ +DeuTex 4.0.1 + +WHAT ARE DEUTEX AND DEUSF + + DeuTex and DeuSF are programs than can do many things with Doom, + Heretic, Hexen and Strife wad files such as extracting and inserting + graphics, sounds, levels and other resources. See the manual for + details (docsrc/dtexman6.txt). + +BUILDING AND INSTALLING ON UNIX + + You need a reasonably standard Unix environment with a C compiler, + such as Linux. + 1) Type "make" + 2) As root, type "make install" + See INSTALL for details. + +BUILDING AND INSTALLING ON DOS + + You need a C compiler, such as DJGPP, Cygwin or Borland C. See + INSTALL. + +LEGAL + + Most of this program is GPL'd but some of it is available under + other licenses. 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 LICENSE for specific information and copyright notices. All + trademarks are the property of their owners. + +CONTACT + + Home page http://www.teaser.fr/~amajorel/deutex/ + General newbie questions news:rec.games.computer.doom.editing + Maintainer Andr� Majorel . + +-- AYM 1999-09-09 diff --git a/TODO b/TODO new file mode 100644 index 0000000..1031685 --- /dev/null +++ b/TODO @@ -0,0 +1,121 @@ +THIS IS A GENERATED FILE -- DO NOT EDIT ! +Edit docsrc/todo.html instead. + + To-do list for DeuTex + + * In the directives file and textures files, "include" directive to + include the rest of another block/file. + * In the directives file and textures files, allow references to + environment variables (E.G. $E(name)) + * In the directives file and textures files, allow user variables + (E.G. $(name)) + * Make it easier to let a texture have a description identical to + another texture + * In the directives file, add a mean to import all/only named/all + except named flats as patches. + * In the directives file, add a mean to import all/only named/all + except named patches as flats. This implies 1) accepting flats + larger than 64�64 (by clipping) 2) converting transparent pixels + to a certain colour (which one ?). + * In the directives file, add a mean to automatically generate a + texture for all/only named/all except named patches. The height of + the automatic texture is 128, its width is the least power of two + wide enough to contain the patch. The automatic texture is filled + with the patch by tiling, starting from the top left corner. The + name of the automatic texture is the name of the patch. + * Patches > 255 high + * Make sure that support for Strife is complete. + * When doing -xtract/-make of strife0.wad, creates .au sound files + but is not able to read them back ("WAV: Can't read dsswish.au" or + something like that). + * Instead of allowing any and all characters in the script file, + require them to be quoted. And, when doing -xtract, produce the + script file with the appropriate quotes... Since, under Unix, the + only characters that are not allowed in a file name are NUL and + "/", I don't see why DeuTex should prevent users from extracting + lumps with weird characters in their names. However, that might + cause compatilibity problems with the DOS version. + * The presence of the GIF routines might prevent DeuTex to be + distributed in the "free" section of Debian. Would it be + sufficient to #ifdef them out ? + * Finish -pf + * RAWtoPPM() forgets to replace occurrences of the transparent + colour by its nearest colour. Thus, CEIL4_1 is extracted with a + cyan background. + * The command line interface is not always intuitive and fussy about + the position of certain options. + * Regarding audio support, Matthew W. Miller + offered the following comment on 1999-07-04 : + + Audio handling in deutex (I'm referring to the irix 5.3 version's + included source code) is, I believe, based on dmgraph, but is + pretty dire in any case. + Imported sounds are all resampled to 11025 Hz, even though that + hasn't been necessary since some time between v1.2 and v1.666 + (basically, any version that uses the item-respawn sound has the + improved sound engine). Exasperatingly, lxdoom (or maybe sndserv?) + takes several steps back by expecting sounds to be *raw* 11025 Hz + data. You may be able to set new options to reflect this. + Also, one would hope that eventually one or more of the source + ports will start to support bitrates other than 8 bit, and (maybe?) + stereo samples. You may want to start leaning on various source + ports' programmers to get their acts together and start coming to + some sort of agreement. ;) + Importation of .wav files is pretty crufty. Like dmgraph before it, + the deutex 5.3 source expects there to be just one big 'data' + chunk, and doesn't notice the 'info' chunks that certain stupid + Windows programs (*cough*cough*CoolEdit*GoldWave*cough*) insist on + putting in (usually with copyright messages for the program itself, + which in a just world would be illegal). Greater explanation of all + this whacky chunk business can be found at: + [1]http://www.compsoc.man.ac.uk/~maniac/resource_web/wav_file_forma + t/ (wav1.htm, wav2.htm, wav3.htm, 4.htm, 5.htm) + Essentially, you want to clip out the first 'data' chunk and ignore + crap like 'info', 'inam', 'list', or whatever. + * TBD: New options -fstart and -fend to control the start-of-flats + and end-of-flats markers used in pwads. Default to FF_START and + F_END respectively. Warning: here again, don't use those options + just because they're here. The default markers are perfectly fine, + and they conform to the de-facto standard. If you deviate from + them, you're asking for trouble. + * -f_end + * In the doc, mention that negative patch Y-offsets are forced to 0 + by the engine. + * Why does DeuTex sometimes includes patches even if you don't + mention them explicitly and sometimes doesn't ? + * Make a DOS binary distribution with all filenames 8.3, all + documentation in CRLF & CP437 format, no sources, no makefile, + only DOS executables. + * Options shouldn't care whether there is space between them and + their argument. + * Man page: mention that some options are DeuTex-only, not DeuSF. + * Man page: insert `deutex -man` automatically. + * Alpha port: look into 64-bit longs. + * -check shouldn't require an argument. It should use the iwad by + default. + * -main should be implemented for DeuTex as well. + * DeuTex should not look for doom.wad in the directory set by + -heretic ! + * WAV to Doom sound: the warning "shrinking ... to 11025" should + mention the name of the file or appear only once. + * PPM to Doom graphics: the warning "quantisation is slow" should + either mention the name of the file or appear only once. + * Determine why converting Doom graphics to PPM and back does not + yield the same thing. This also happens with BMP but much less so. + * Bug: certain flats seem to be extracted with certain pixels set to + the transparent colour (Doom's CEIL4_1). DeuTex 3.6 for DOS + exhibits the same problem [1]. + * Hexen: DeuTex does not handle the BEHAVIOR lumps correctly. + * Hexen: does not extract graphics quite correctly (applies + transparent colour translation to opaque images such as FINALE1 + and FINALE2. This is probably related to [1]. + * Hexen: when trying to build back the hexen wad, got +Color palette is unknown +WARNING unknown palette. Using colour 0xff as transparentcolour. +Some graphics may appear moth-eaten. +Making lumps +Bug: *** idinx *** + +References + + 1. http://www.compsoc.man.ac.uk/~maniac/resource_web/wav_file_format/ diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..1454f6e --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +4.0.1 diff --git a/deusf.6 b/deusf.6 new file mode 120000 index 0000000..9b354de --- /dev/null +++ b/deusf.6 @@ -0,0 +1 @@ +deutex.6 \ No newline at end of file diff --git a/deutex.6 b/deutex.6 new file mode 100644 index 0000000..49970f9 --- /dev/null +++ b/deutex.6 @@ -0,0 +1,346 @@ +.\" This file is part of DeuTex. +.\" +.\" DeuTex incorporates code derived from DEU 5.21 that was put in the +.\" public domain in 1994 by Rapha�l Quinet and Brendon Wyber. +.\" +.\" DeuTex is Copyright � 1994-1995 Olivier Montanuy, +.\" Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., +.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +.\" +.TH DEUTEX 6 1999-09-10 "DeuTex 4.0.1" +.SH NAME +deutex, deusf \- do things with wad files +.SH SYNOPSIS +.BR "deutex \-?" | \-h | \-help | \-\-help +.br +.B deutex \-\-version +.br +.B deutex \-man +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-make \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-wadir \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-check \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-usedtex \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-unused \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-xtract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-get \fP\fIentry \fP\fR[\fP\fIin.wad\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-pknormal \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-pkgrahix \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-add \fP\fIincomplete.wad out.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-append \fP\fIincomplete.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-join \fP\fIincomplete.wad in.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-merge \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-restor\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-as \fP\fIsprite.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-af \fP\fIflats.wad\fP + +.BR "deusf \-?" | \-h | \-help | \-\-help +.br +.B deusf \-\-version +.br +.BI "deusf " options +.br +.SH DESCRIPTION +DeuTex is a wad composer for Doom, Heretic, Hexen and Strife. It can be used +to extract the lumps of a wad and save them as individual files or the +reverse, and much more. + +When extracting a lump to a file, it does not just copy the raw data, it +converts it to an appropriate format (such as PPM for graphics, Sun audio for +samples, etc.). Conversely, when it reads files for inclusion in pwads, it +does the necessary conversions (for example, from PPM to Doom picture format). + +DeuSF is a trimmed version of DeuTex that is used to merge sprites and flats +from a pwad into an iwad, which is sometimes necessary because Doom and its +breed do not handle sprites in pwads well. + +See \fBdocsrc/dtexman6.txt\fP for more information on DeuTex and DeuSF. +.SH OPTIONS +.TP 14 +\fB\-?\fP +Print list of options. +.TP 14 +\fB\-h\fP +Same as above. +.TP 14 +\fB\-help\fP +Same as above. +.TP 14 +\fB\--help\fP +Same as above. +.TP 14 +\fB\-man\fP +Print list of options in troff -man format. +.TP 14 +\fB\--version\fP +Print version number. +.TP 14 +\fB\-syntax\fP +Print the syntax of wad creation directives. +.TP 14 +\fB\-win \fP\fIdoom data info select colour\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-wim \fP\fIdoom select\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-debug\fP +Debug mode. +.TP 14 +\fB\-overwrite\fP +(opt.) Overwrite all. +.TP 14 +\fB\-wtx \fP\fIiwad\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-doom \fP\fIdir\fP +(opt.) Indicate the directory of Doom/Doom II. +.TP 14 +\fB\-heretic \fP\fIdir\fP +(opt.) Indicate the directory of Heretic. +.TP 14 +\fB\-hexen \fP\fIdir\fP +(opt.) Indicate the directory of Hexen. +.TP 14 +\fB\-strife \fP\fIdir\fP +(opt.) Indicate the directory of Strife. +.TP 14 +\fB\-dir \fP\fIdir\fP +(opt.) Indicate the working directory. +.TP 14 +\fB\-deu\fP +(opt.) Add 64k of junk to workaround a bug of DEU 5.21. +.TP 14 +\fB\-rgb \fP\fIr g b\fP +(opt.) Specify the transparent colour (default 0/47/47). +.TP 14 +\fB\-gif\fP +(opt.) Save pictures as GIF (.gif). +.TP 14 +\fB\-bmp\fP +(opt.) Save pictures as BMP (.bmp). +.TP 14 +\fB\-ppm\fP +(opt.) Save pictures as rawbits (P6) PPM (.ppm). +.TP 14 +\fB\-au\fP +(opt.) Save sound as Sun audio (.au). +.TP 14 +\fB\-wav\fP +(opt.) Save sound as wave (.wav). +.TP 14 +\fB\-voc\fP +(opt.) Save sound as voc (.voc). +.TP 14 +\fB\-fullsnd\fP +(opt.) Save sound lumps beyond declared length. +.TP 14 +\fB\-levels\fP +(opt.) Select levels. +.TP 14 +\fB\-lumps\fP +(opt.) Select lumps. +.TP 14 +\fB\-sounds\fP +(opt.) Select sounds. +.TP 14 +\fB\-musics\fP +(opt.) Select musics. +.TP 14 +\fB\-textures\fP +(opt.) Select textures. +.TP 14 +\fB\-graphics\fP +(opt.) Select graphics. +.TP 14 +\fB\-s_end\fP +(opt.) Use S_END for sprites, not SS_END. +.TP 14 +\fB\-george\fP +Same as above. +.TP 14 +\fB\-sprites\fP +(opt.) Select sprites. +.TP 14 +\fB\-patches\fP +(opt.) Select patches. +.TP 14 +\fB\-flats\fP +(opt.) Select flats. +.TP 14 +\fB\-v0\fP +(opt.) Set verbosity level to 0. +.TP 14 +\fB\-v1\fP +(opt.) Set verbosity level to 1. +.TP 14 +\fB\-v2\fP +(opt.) Set verbosity level to 2. +.TP 14 +\fB\-v3\fP +(opt.) Set verbosity level to 3. +.TP 14 +\fB\-v4\fP +(opt.) Set verbosity level to 4. +.TP 14 +\fB\-v5\fP +(opt.) Set verbosity level to 5. +.TP 14 +\fB\-be\fP +(opt.) Assume all wads are big endian (default LE). +.TP 14 +\fB\-le\fP +(opt.) Assume all wads are little endian (default). +.TP 14 +\fB\-ibe\fP +(opt.) Input wads are big endian (default LE). +.TP 14 +\fB\-ile\fP +(opt.) Input wads are little endian (default). +.TP 14 +\fB\-obe\fP +(opt.) Create big endian wads (default LE). +.TP 14 +\fB\-ole\fP +(opt.) Create little endian wads (default). +.TP 14 +\fB\-pf \fP\fR{\fP\fBnormal\fP\fR|\fP\fBalpha\fP\fR}\fP +(opt.) Picture format (default is "normal"). +.TP 14 +\fB\-iwad\fP +(opt.) Compose iwad, not pwad. +.TP 14 +\fB\-make \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Make a pwad, from the creation directives. +.TP 14 +\fB\-build \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Same as above. +.TP 14 +\fB\-create \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Same as above. +.TP 14 +\fB\-wadir \fP\fIin.wad\fP +List and identify entries in a wad. +.TP 14 +\fB\-check \fP\fIin.wad\fP +Check the textures. +.TP 14 +\fB\-test \fP\fIin.wad\fP +Same as above. +.TP 14 +\fB\-usedtex \fP\fIin.wad\fP +List textures used in all levels. +.TP 14 +\fB\-unused \fP\fIin.wad\fP +Find unused spaces in a wad. +.TP 14 +\fB\-xtract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +Extract some/all entries from a wad. +.TP 14 +\fB\-extract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +Same as above. +.TP 14 +\fB\-get \fP\fIentry \fP\fR[\fP\fIin.wad\fP\fR]\fP +Get a wad entry from main wad or in.wad. +.TP 14 +\fB\-pknormal \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +Detect identical normal. +.TP 14 +\fB\-pkgfx \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +Detect identical graphics. +.TP 14 +\fB\-add \fP\fIincomplete.wad out.wad\fP +Add sprites & flats of a pwad to those of Doom. +.TP 14 +\fB\-append \fP\fIincomplete.wad\fP +Append sprites & flats of Doom to a pwad. +.TP 14 +\fB\-join \fP\fIincomplete.wad in.wad\fP +Append sprites & flats of Doom to a pwad. +.TP 14 +\fB\-merge \fP\fIin.wad\fP +Merge doom.wad and a pwad. +.TP 14 +\fB\-restore\fP +Restore doom.wad and the pwad. +.TP 14 +\fB\-as \fP\fIsprite.wad\fP +Append all sprites to the wad. +.TP 14 +\fB\-af \fP\fIflats.wad\fP +Append all floors/ceilings to the wad. +.SH ENVIRONMENT +.TP +.B DOOMWADDIR +The directory where the iwad resides. The value of this +environment variable is overridden by \fB\-main\fP, \fB\-doom\fP +and friends. +.SH BUGS +See \fBTODO\fP. +.SH LEGAL +Most of this program is GPL'd but some of it is available under +other licenses. 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 LICENSE for specific information and copyright notices. All +trademarks are the property of their owners. +.SH AUTHOR +The original author of DeuTex is Olivier Montanuy. + +From 1994 to 1996, DeuTex was maintained by Olivier Montanuy + with help from Per Allansson +, James Bonfield +, Sharon Bowles, Mark +Mathews and Chuck Rossi. The +original manual was written by Kevin McGrail . + +The current maintainer is Andr� Majorel . + +Questions and bug reports should be sent to the current +maintainer, \fInot\fP to the original authors. +.SH SEE ALSO +.B man \-k doom wad diff --git a/docsrc/README b/docsrc/README new file mode 100644 index 0000000..2b4cc45 --- /dev/null +++ b/docsrc/README @@ -0,0 +1,40 @@ +DeuTex $VERSION + +WHAT ARE DEUTEX AND DEUSF + + DeuTex and DeuSF are programs than can do many things with Doom, + Heretic, Hexen and Strife wad files such as extracting and inserting + graphics, sounds, levels and other resources. See the manual for + details (docsrc/dtexman6.txt). + +BUILDING AND INSTALLING ON UNIX + + You need a reasonably standard Unix environment with a C compiler, + such as Linux. + 1) Type "make" + 2) As root, type "make install" + See making.txt for details. + +BUILDING AND INSTALLING ON DOS + + You need a C development environment with "make" and a C compiler, + such as DJGPP, Cygwin or Borland C. + 1) Type "make" + 2) Copy the new "deutex.exe" and "deusf.exe" somewhere in your PATH. + See making.txt for details. + +LEGAL + + DeuTex is Copyright Olivier Montanuy 1994-1995 and Copyright Andr� + Majorel 1999 and available under the terms of the GPL, except lzw.c + which is Copyright David Koblas and others and available under the + terms of the PBMPLUS license. See LICENSE. + All trademarks are the property of their owners. + +CONTACT + + Home page : http://www.teaser.fr/~amajorel/deutex/ + General newbie questions : news:rec.games.computer.doom.editing + Maintainer : Andr� Majorel . + +-- AYM $SELF_DATE diff --git a/docsrc/changes.html b/docsrc/changes.html new file mode 100644 index 0000000..06a3acb --- /dev/null +++ b/docsrc/changes.html @@ -0,0 +1,325 @@ + + +History of changes for DeuTex + + +

History of changes for DeuTex

+ +
+

DeuTex 4.0.1 (AYM 1999-09-10) +
+
    +

  • CLI: reworked the command line arguments parsing, with + the following consequences. + +
      +
    • Options can now be abbreviated freely, as long as the + abbreviation is not ambiguous. For example, you can use + -heretic, -hereti, -heret, + -here or -her but not -he + because that could also be the abbreviation for -help + (or -hexen, for that matter). On the other hand, + -h is allowed because it's not an abbreviation + (there's really a -h option). + +
    • -heretic and -hexen now work (they + were "hidden" by -h[elp]). + +
    • -v@ has been split in -v0, + -v1 ... -v5 because the new code does not + allow excess characters after an option. + -vstring where string is anything + else than "0" through "5" now triggers an + error (it used to be accepted silently). I hope no one relied on the + old undocumented behaviour. + +
    • Certain silly command line arguments that would have worked + before would now trigger an error. For example, it used to be + possible to type -extramarital or + -extermination for -extract but not + anymore. The old code defined relatively short options + (-ext) and accepted command line arguments as long as + the defined option was an initial substring of the command line + argument. The new code does the reverse; it defines relatively long + options (-extract) and accepts command line argument as + long as they're an initial substring of the defined option. + +
    + +

  • Code: replaced direct testing of __MSDOS__, + __OS2__, __GNUC__, + __BORLANDC__ by DT_CC and + DT_OS. This is hopefully going to make Udo's job a + bit easier. + +

  • Code: now uses the same fopen() modes for + all platforms: "{rw}b" for binary mode and + "{rw}" for text mode, as per the ANSI/ISO C + standard. This will fix the problem Udo Munk reported with the + Cygwin build opening binary files in text mode and thus failing + miserably. Note that certain DOS C compilers can be configured + so that "{rw}" opens files in binary mode. + Don't do that ! If you have problems with text files on + DOS, make sure your C compiler is configured so that + "{rw}" opens files in text mode. + +

  • Code: added to the distribution archive + gifcodec.c that I had forgotten to include (it's + not used anyway). + +

  • Code: added to the distribution archive + src/{deusf,deusfos,deutex,deutexos}.def that I had + forgotten to include. I guess that's Windows/OS/2-only stuff. + +

  • Doc: updated making.txt and renamed it as + INSTALL for homogeneity. Removed obsolete reference + to alpha.sh and the file itself. + +

  • Doc: made more legal updates. + +

  • Doc: documented DOOMWADDIR in the man page. + +

  • Misc: changed the default graphics format for Unix from + GIF to PPM, so that fewer user sites are broken if and when GIF + support is removed. For the same reason, added a warning message + when -gif is used or the first time an image is + read from a GIF file. + +

  • Misc: changed the lookup order for images to PPM, BMP, + GIF (was BMP, GIF, PPM). + +

  • Platform: fixed a couple of things that didn't work on + 16-bit platforms (real-mode DOS). + +

  • Platform: now compiles on DOS with Borland C++ 4.0. + +

  • Platform: now compiles on DOS with MSC 6.0. The MSC 6.0 + build is functional but limited because it can't allocate blocks + larger than 64 kB, which is insufficient for certain images. I + can't use halloc() instead of malloc() + because it does not supporting resizing (i.e. there's no + hrealloc() function). + +

  • Platform: in response to Udo's remarks, DJGPP and Cygwin + are now properly identified (__DJGPP__ and + __CYGWIN__). + +

  • Platform: added sanity checks on specified-size types + Int32 and friends. + +
+ + +

DeuTex 4.0.0a3 (AYM 1999-09-05) +
+
    +

  • Code: removed incongruous #define-ing of + O_BINARY and SEEK_SET. + +

  • Code: after Udo Munk's report, fixed warnings in +
      +
    • src/color.c(74) +
    • src/ident.c(583) +
    • src/ident.c(658) +
    • src/mkwad.c(78) +
    • src/mkwad.c(79) +
    • src/mkwad.c(80) +
    • src/mkwad.c(81) +
    • src/picture.c(903) +
    • src/picture.c(912) +
    + +

  • Doc: updated making.txt. + +

  • Legal: as agreed to by Olivier Montanuy, DeuTex is now + entirely GPL'd. Well, almost entirely, since it + includes code written by different authors in lzw.c + and elsewhere. Changed the notices in the source files and added + new file LICENSE to clarify things. + +

  • Makefile: should now work with all C compilers (removed + -Wall from CFLAGS). + +

  • Makefile: clean now removes the DOS + executables if they exist. + +

  • Makefile: does not compile with debug information in by + default anymore. + +

  • Makefile: new targets dall, + ddt, dds, ddeutex + and ddeusf for compiling with debug + information and all warnings. + +

  • Makefile: new target help. + +

  • Makefile: new target distdos. + +

  • Platform: replaced unlink() by + remove() for portability. Thanks to Udo for + reporting this. + +

  • Platform: on 8.3 filesystems, make should not choke on + docsrc/changes.html anymore. Thanks to Udo for + reporting this. + +

  • Sound: corrected some misleading endianness + comments in sound.c. + +
+ +

DeuTex 4.0.0a2 (AYM 1999-08-14) +
+
    +

  • Game: easier to use with Strife (now looks for + "strife1.wad", new option "-strife"). + +

  • Game: easier to use with Hexen (new option + "-hexen"). + +

  • Command line: new options "-hexen" and + "-strife". + +

  • Command line: new option "--version" (prints + version number and returns 0). + +

  • Doc: various changes in the man page, in the output of + "-help" and "-man" and elsewhere. + +

  • Makefile: various improvements. + +

  • Distribution: set modes straight. + +
+ +

DeuTex 4.0.0a1 (AYM 1999-08-12) +
+
    +

  • General: fixed many segfaults that were caused by + attempts to fclose (NULL). + +

  • Game: Strife is now supported. + +

  • Wad: new options -be, -le, + -ibe, -ile, -obe and + -ole to control the endianness of the wads. + Caution: don't use them if you don't know what + you're doing ! As far as I know, wads are always + little-endian regardless of the architecture of the host. + Therefore, I see no reason for someone in his/her right mind to + create a big-endian wad. Those options are here more for the + sake of completeness than anything else. + +

  • Wad: made "%" legal in names, to deal with + Strife's "INVFONG%" and + "INVFONY%".

    + +

  • Wad, graphics: end-of-flats marker is now + F_END by default instead of FF_END. + The reason for this change is that, with F_END, you + don't need DeuSF to get Doom to see your new flats. Should you + need to, it's still possible to get FF_END by using + -fend. + +

  • Graphics: the default transparent colour is now + rgb:00/2f/2f. It used to be cyan (rgb:00/ff/ff) which was + blindingly bright, especially compared to the usually dark + colours used in Doom textures. It's no fun to tweak shades of + dark brown on a cyan background. + +

    To reuse images done with/for a previous version of DeuTex, + you need to either invoke DeuTex with "-rgb 0 255 + 255" or convert your images by replacing all occurrences + of colour (0, 255, 255) by colour (0, 47, 47). To preserve + compatibility with WinTex, I didn't change the default + transparent colour in WinTex mode ; it's still (0, 255, + 255). + +

  • Graphics: fixed segfaults due to bug in conversion of + bitmap images to Doom pictures. Occured in certain 2-pixel high + images such as STBFN045 in the Strife iwad. + +

  • Graphics: now supports pictures and textures up to 509 + high (was limited to 128). + +

  • Graphics: now supports pictures and textures up to 1024 + wide (was limited to 512). + +

  • Graphics: new option "-pf" to deal with the + different picture format in the Doom alpha iwad (the underlying + functionality is not implemented yet !) + +

  • Graphics: using -ppm does not cause anymore + DeuTex to abort with "Bug: *** psvit ***". + +

  • Graphics: fixed "-ppm" message. + +

  • Sound, platform: a bug that must have prevented reading + .wav files on big endian machines has been + squashed. + +

  • Command line: options can't start with a slash + ("/") anymore. I don't think anyone used it and was + a silly feature for a Unix program. + +

  • Command line: not case insensitive anymore. + +

  • Command line: changed the wording of error messages to + use "option" instead of "command". + +

  • Command line: added options "-?" and + "--help" as synonyms for "-help". + +

  • Doc: new option "-man" to print help in + troff -man source format for inclusion in the man + page. + +

  • Doc: the version number is now a free-form string. + +

  • Doc: Made on-line help more compact. + +

  • Doc: updated "making.txt". + +

  • Doc: made a proper README file. + +

  • Makefile: renamed "unix" target as + "strip". + +

  • Makefile: new target "install". + +

  • Makefile: new target "dist". + +

  • Platform: reworked the handling of endianness. DeuTex + used to deal with that through a set of macros that swapped + bytes whenever the required endianness was not the same as the + native endianness. To known the native endianness, DeuTex relied + on a macro defined via -D. + +

    There were two problems with this scheme. Firstly, Olivier + got the meaning of "little endian" and "big endian" backwards + and defining LITTLE_ENDIAN in fact caused DeuTex to + believe it was being compiled for a big endian machine. As the + glibc headers happen to define LITTLE_ENDIAN if the + machine is little endian, compiling DeuTex on a glibc little + endian Linux system was impossible unless you made changes to + the source. + +

    The other, more fundamental, objection against the old + approach is that, as it needed the user to tell it about the + native endianness by modifying the makefile, it prevented + unattended builds and made things difficult for naive users. + +

    The new method eliminates this problem by using a different + algorithm that does not need to know the native endianness. The + end result is that you don't have to worry about endianness + anymore. + +

  • Internal: in TXTinit(), removed useless + "% 0xFF" in index of TXTval. + +
+ +
+ + + diff --git a/docsrc/deutex.6 b/docsrc/deutex.6 new file mode 100644 index 0000000..87aef69 --- /dev/null +++ b/docsrc/deutex.6 @@ -0,0 +1,346 @@ +.\" This file is part of DeuTex. +.\" +.\" DeuTex incorporates code derived from DEU 5.21 that was put in the +.\" public domain in 1994 by Rapha�l Quinet and Brendon Wyber. +.\" +.\" DeuTex is Copyright � 1994-1995 Olivier Montanuy, +.\" Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., +.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +.\" +.TH DEUTEX 6 $DATE "DeuTex $VERSION" +.SH NAME +deutex, deusf \- do things with wad files +.SH SYNOPSIS +.BR "deutex \-?" | \-h | \-help | \-\-help +.br +.B deutex \-\-version +.br +.B deutex \-man +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-make \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-wadir \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-check \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-usedtex \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-unused \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-xtract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-get \fP\fIentry \fP\fR[\fP\fIin.wad\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-pknormal \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-pkgrahix \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-add \fP\fIincomplete.wad out.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-append \fP\fIincomplete.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-join \fP\fIincomplete.wad in.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-merge \fP\fIin.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-restor\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-as \fP\fIsprite.wad\fP +.br +\fBdeutex\fP [\fIoptions\fP] +.B \-af \fP\fIflats.wad\fP + +.BR "deusf \-?" | \-h | \-help | \-\-help +.br +.B deusf \-\-version +.br +.BI "deusf " options +.br +.SH DESCRIPTION +DeuTex is a wad composer for Doom, Heretic, Hexen and Strife. It can be used +to extract the lumps of a wad and save them as individual files or the +reverse, and much more. + +When extracting a lump to a file, it does not just copy the raw data, it +converts it to an appropriate format (such as PPM for graphics, Sun audio for +samples, etc.). Conversely, when it reads files for inclusion in pwads, it +does the necessary conversions (for example, from PPM to Doom picture format). + +DeuSF is a trimmed version of DeuTex that is used to merge sprites and flats +from a pwad into an iwad, which is sometimes necessary because Doom and its +breed do not handle sprites in pwads well. + +See \fBdocsrc/dtexman6.txt\fP for more information on DeuTex and DeuSF. +.SH OPTIONS +.TP 14 +\fB\-?\fP +Print list of options. +.TP 14 +\fB\-h\fP +Same as above. +.TP 14 +\fB\-help\fP +Same as above. +.TP 14 +\fB\--help\fP +Same as above. +.TP 14 +\fB\-man\fP +Print list of options in troff -man format. +.TP 14 +\fB\--version\fP +Print version number. +.TP 14 +\fB\-syntax\fP +Print the syntax of wad creation directives. +.TP 14 +\fB\-win \fP\fIdoom data info select colour\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-wim \fP\fIdoom select\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-debug\fP +Debug mode. +.TP 14 +\fB\-overwrite\fP +(opt.) Overwrite all. +.TP 14 +\fB\-wtx \fP\fIiwad\fP +(opt.) WinTex shortcut. +.TP 14 +\fB\-doom \fP\fIdir\fP +(opt.) Indicate the directory of Doom/Doom II. +.TP 14 +\fB\-heretic \fP\fIdir\fP +(opt.) Indicate the directory of Heretic. +.TP 14 +\fB\-hexen \fP\fIdir\fP +(opt.) Indicate the directory of Hexen. +.TP 14 +\fB\-strife \fP\fIdir\fP +(opt.) Indicate the directory of Strife. +.TP 14 +\fB\-dir \fP\fIdir\fP +(opt.) Indicate the working directory. +.TP 14 +\fB\-deu\fP +(opt.) Add 64k of junk to workaround a bug of DEU 5.21. +.TP 14 +\fB\-rgb \fP\fIr g b\fP +(opt.) Specify the transparent colour (default 0/47/47). +.TP 14 +\fB\-gif\fP +(opt.) Save pictures as GIF (.gif). +.TP 14 +\fB\-bmp\fP +(opt.) Save pictures as BMP (.bmp). +.TP 14 +\fB\-ppm\fP +(opt.) Save pictures as rawbits (P6) PPM (.ppm). +.TP 14 +\fB\-au\fP +(opt.) Save sound as Sun audio (.au). +.TP 14 +\fB\-wav\fP +(opt.) Save sound as wave (.wav). +.TP 14 +\fB\-voc\fP +(opt.) Save sound as voc (.voc). +.TP 14 +\fB\-fullsnd\fP +(opt.) Save sound lumps beyond declared length. +.TP 14 +\fB\-levels\fP +(opt.) Select levels. +.TP 14 +\fB\-lumps\fP +(opt.) Select lumps. +.TP 14 +\fB\-sounds\fP +(opt.) Select sounds. +.TP 14 +\fB\-musics\fP +(opt.) Select musics. +.TP 14 +\fB\-textures\fP +(opt.) Select textures. +.TP 14 +\fB\-graphics\fP +(opt.) Select graphics. +.TP 14 +\fB\-s_end\fP +(opt.) Use S_END for sprites, not SS_END. +.TP 14 +\fB\-george\fP +Same as above. +.TP 14 +\fB\-sprites\fP +(opt.) Select sprites. +.TP 14 +\fB\-patches\fP +(opt.) Select patches. +.TP 14 +\fB\-flats\fP +(opt.) Select flats. +.TP 14 +\fB\-v0\fP +(opt.) Set verbosity level to 0. +.TP 14 +\fB\-v1\fP +(opt.) Set verbosity level to 1. +.TP 14 +\fB\-v2\fP +(opt.) Set verbosity level to 2. +.TP 14 +\fB\-v3\fP +(opt.) Set verbosity level to 3. +.TP 14 +\fB\-v4\fP +(opt.) Set verbosity level to 4. +.TP 14 +\fB\-v5\fP +(opt.) Set verbosity level to 5. +.TP 14 +\fB\-be\fP +(opt.) Assume all wads are big endian (default LE). +.TP 14 +\fB\-le\fP +(opt.) Assume all wads are little endian (default). +.TP 14 +\fB\-ibe\fP +(opt.) Input wads are big endian (default LE). +.TP 14 +\fB\-ile\fP +(opt.) Input wads are little endian (default). +.TP 14 +\fB\-obe\fP +(opt.) Create big endian wads (default LE). +.TP 14 +\fB\-ole\fP +(opt.) Create little endian wads (default). +.TP 14 +\fB\-pf \fP\fR{\fP\fBnormal\fP\fR|\fP\fBalpha\fP\fR}\fP +(opt.) Picture format (default is "normal"). +.TP 14 +\fB\-iwad\fP +(opt.) Compose iwad, not pwad. +.TP 14 +\fB\-make \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Make a pwad, from the creation directives. +.TP 14 +\fB\-build \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Same as above. +.TP 14 +\fB\-create \fP\fR[\fP\fIdirctivs.txt\fP\fR] \fP\fIout.wad\fP +Same as above. +.TP 14 +\fB\-wadir \fP\fIin.wad\fP +List and identify entries in a wad. +.TP 14 +\fB\-check \fP\fIin.wad\fP +Check the textures. +.TP 14 +\fB\-test \fP\fIin.wad\fP +Same as above. +.TP 14 +\fB\-usedtex \fP\fIin.wad\fP +List textures used in all levels. +.TP 14 +\fB\-unused \fP\fIin.wad\fP +Find unused spaces in a wad. +.TP 14 +\fB\-xtract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +Extract some/all entries from a wad. +.TP 14 +\fB\-extract \fP\fIin.wad \fP\fR[\fP\fIdirctivs.txt\fP\fR]\fP +Same as above. +.TP 14 +\fB\-get \fP\fIentry \fP\fR[\fP\fIin.wad\fP\fR]\fP +Get a wad entry from main wad or in.wad. +.TP 14 +\fB\-pknormal \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +Detect identical normal. +.TP 14 +\fB\-pkgfx \fP\fIin.wad \fP\fR[\fP\fIout.txt\fP\fR]\fP +Detect identical graphics. +.TP 14 +\fB\-add \fP\fIincomplete.wad out.wad\fP +Add sprites & flats of a pwad to those of Doom. +.TP 14 +\fB\-append \fP\fIincomplete.wad\fP +Append sprites & flats of Doom to a pwad. +.TP 14 +\fB\-join \fP\fIincomplete.wad in.wad\fP +Append sprites & flats of Doom to a pwad. +.TP 14 +\fB\-merge \fP\fIin.wad\fP +Merge doom.wad and a pwad. +.TP 14 +\fB\-restore\fP +Restore doom.wad and the pwad. +.TP 14 +\fB\-as \fP\fIsprite.wad\fP +Append all sprites to the wad. +.TP 14 +\fB\-af \fP\fIflats.wad\fP +Append all floors/ceilings to the wad. +.SH ENVIRONMENT +.TP +.B DOOMWADDIR +The directory where the iwad resides. The value of this +environment variable is overridden by \fB\-main\fP, \fB\-doom\fP +and friends. +.SH BUGS +See \fBTODO\fP. +.SH LEGAL +Most of this program is GPL'd but some of it is available under +other licenses. 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 LICENSE for specific information and copyright notices. All +trademarks are the property of their owners. +.SH AUTHOR +The original author of DeuTex is Olivier Montanuy. + +From 1994 to 1996, DeuTex was maintained by Olivier Montanuy + with help from Per Allansson +, James Bonfield +, Sharon Bowles, Mark +Mathews and Chuck Rossi. The +original manual was written by Kevin McGrail . + +The current maintainer is Andr� Majorel . + +Questions and bug reports should be sent to the current +maintainer, \fInot\fP to the original authors. +.SH SEE ALSO +.B man \-k doom wad diff --git a/docsrc/dtexman6.txt b/docsrc/dtexman6.txt new file mode 100644 index 0000000..ecfae8c --- /dev/null +++ b/docsrc/dtexman6.txt @@ -0,0 +1,4568 @@ + + + + + +____________ __________________________ +\ \ \ / / +| _______ \ \_______ ________/ / +| |\_____\ \ \______\ / \______\/ +| | | | |\ | | / +| | | | || __________ ____ ____ | | | __________ _____ ____ +| | | | || \ _____/ / \ / \ \ / \ | | | \ _____/ /| \ / \ / \ +| | | | || | |\___\/ | |/ | |/ | | | | |\___\/ \ \ \ / / / +| | | _/ || | |_|____ | || | || | | | | |_|___ \ \ \/ / / +| | |_/ __/ | | ____/ / | || | || | | | | ___/ / \/ \/ +| |/ __/ __/ | |\__\/ | || | || | | | | |\_\/ / /\ \ +\ / __/ | |_|_____ | \|__/ || | | | | |_|_____ / / |\ \ + \ / _/ /______/ / /_______/| /___| | /______/ / /__/ /\ \__\ + \ / / \______\/ \________/ \____\| \______\/ \__\/ \|__| + \/ / + \/ + + + + + + + + + + + + + + + + + DEUTEX/DEUSF 3.6 + July 1995 + + wad composition tool for Doom + Copyright (c) Olivier Montanuy 1994/95 + Copyright (c) Andr� Majorel 1999 + + Manual Edited by Kevin McGrail + (hevkev@sfo.com) + + + + Trouble shooting and support: + + On Usenet: the newsgroup rec.computers.games.editing + On Compuserve: The ACTION forum (Doom Utilities) + + + Serious trouble or identified bug: + + E-mail directly to the maintainer + amajorel@teaser.fr + + Note that this product is Freeware, and that support + only depends on the good will of the involved people. + Be tolerant. Don't expect prompt answers. + + + + + +------------------------ Data Utility License ------------------------- +Doom(tm) is a trademark of Id Software, Inc. +The Doom characters and the Id Software logo are trademarks of Id +Software, Inc. Doom Copyright (c) 1993. Id Software Inc. All rights +reserved. This utility product is not a product of Id Software, Inc. +and has not been approved by Id Software, Inc. Id Software will not +provide technical support for this product. The purchaser of this +utility product may not distribute for money or other consideration +any software data created and/or modified by the use of this utility +product. +----------------------------------------------------------------------- + + +***************************** DISCLAIMER ***************************** + + 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 LICENSE + for specific information. + +************************** CONVIVIALITY ****************************** + +For obvious reasons of reliability and portability, this tool is not +GUI oriented, and learning to use it will be as painful as learning +to use some complex Unix command. +If you're not a Unix kind of guy, get WinTex, a cool Visual Basic +program that I wrote for people like you. It has all the power of +DeuTex (since it can call DeuTex) but it's much easier to use. + +*********************************************************************** + + + ++ *NEW* - Lines beginning with a '+' indicate information added since ++ the manual for DeuTex v3.1 came out. ++ DeuTex 3.6 is mainly compatible with version 3.4 to 3.1 but not with ++ versions 2.9 and below. Changes are minor, however. + + As of version 3.6, DeuTex/DeuSF can be considered as finished. + Almost all the features a normal human would require are there + I only need to add something to build/modify a wad fast, in order + to facilitate the building of preview pwads. Normally, the join + commands should make this useless, but you never know... + + The sources of DeuTex 3.4 are out, and those of DeuTex 3.6 should + follow soon. They might be out when you read this manual. + + + page i + + +************************** Table of Contents *************************** + + +Data Utility License i +Disclaimer i +Conviviality i +Table of Contents ii +Features v +What's New? vi + + + ---------------------------- + *** [PART ONE] GETTING STARTED *** 1 + ---------------------------- + + + +Chapter 1 OVERVIEW 1 + + + A) What is DeuTex? 2 + B) Installation 2 + C) Directories and DeuTex 4 + D) What do I need? 4 + E) What do I do? 4 + F) What is DeuSF for? 5 + G) What are the Palettes For? 5 + + +Chapter 2 TEST-ME or What's inside TRINITY.wad? 7 + + + A) About Test-Me 7 + B) Listing the Directory 7 + C) Decomposing TRINITY.wad 7 + D) Recomposing TRINITY.wad as TRINIDAD.wad 8 + E) Customizing TRINITY.wad 8 + + +Chapter 3 WORKING WITH WADS 9 + + + INTRODUCTION 9 + + A) How to Decompose a pwad 9 + B) How to Create a pwad with new textures 10 + C) How to Create a pwad with new sprites and flats 11 + + 1) Sprite and flat replacement 11 + 2) Changing the number of sprite viewpoints 12 + + D) How to Create a pwad with new SOUNDS 14 + + +Chapter 4 WinTex 15 + + + + + + + + + page ii + + + + +********************** Table of Contents (cont) ************************ + + + + ----------------------------- + *** [PART TWO] DETAILS, DETAILS *** 16 + ----------------------------- + + + +Chapter 5 DIRECTORY STRUCTURE 16 + + + A) levels/ 17 + B) lumps/ 18 + C) textures/ 19 + D) sounds/ 20 + E graphics/ 20 + F) sprites/ 21 + G) flats/ 21 + H) patches/ 22 + + + +Chapter 6 DEUTEX COMMANDS 23 + + + A) Complete Command Reference 23 + B) Help Commands 23 + C) Optional Commands 23 + D) Commands to Compose or Decompose wads 25 + E) Commands for merging pwads into the Main iwad 26 + + + +Chapter 7 DEUSF COMMANDS 28 + + + A) Overview 28 + B) Complete Command Reference 29 + C) Help Commands 29 + D) Optional Commands 30 + E) Mandatory Commands 30 + + + +Chapter 8 FORMATS 31 + + + A) The wad Creation Directive (wadINFO.TXT) 31 + + 1) Overview 31 + 2) wadINFO.TXT format 32 + 3) An example wadINFO.TXT Listing 36 + + B) The Texture Definition File (TEXTURE1.TXT) 39 + + 1) Overview 39 + 2) An Example TEXTURE1.TXT Listing 41 + + + page iii + + + + +********************** Table of Contents (cont) ************************ + + + + + --------------------------- + *** [PART THREE] ALL THE REST *** 43 + --------------------------- + + + + +Chapter 9 NECESSARY STUFF 43 + + + + A) License Agreement 43 + B) Legal Stuff 44 + C) Where to get DeuTex/DeuSF 45 + D) Version Information 46 + E) Known Problems 47 + F) Thanx 48 + G) Final Words 50 + + + +APPENDICES + + + I) Switch Textures in DOOM.wad 51 + II) Animated Wall Textures in DOOM.wad 56 + III) Sound names for Doom 58 + + A) Sounds found in BOTH Doom I and Doom II 58 + B) Sounds found ONLY in Doom II 60 + C) Converting DMAUD sounds for DeuTex 62 + + IV) DeuTex and DeuSF Command Summaries 64 + + A) DeuTex Commands 64 + B) DeuSF Commands 65 + + + + + + + + + + + + + + + + + + + + + page iv + + + + +****************************** FEATURES ******************************* + + ------------ + DeuTex + ------------ + +DeuTex stands stands for DEU's Texture Companion, because it used to +deal only with Doom textures. Now it can do much more! +DEU is a Doom level editor by Brendon Wyber and Raphael Quinet, and +DeuTex was originally derived from the code of DEU 5.21. DeuTex uses +various contributions for particular file formats. + +DEUTEX Features: + +- Ported on all Doom platforms (DOS,OS/2,Linux,SGIx,Unix) +- Reverse engineer existing pwads. +- Compose your own wall Textures, by reusing existing Doom + patches or adding your own patches as .BMP or .GIF files. +- Load sounds as .WAV, .AU or .VOC files. +- Load PC Speaker sounds as a serial of number (in text). +- Load music entries as .MUS files. (from MIDItoMUS) +- Add your own floors. +- Add your own sprites. +- Simple wad creation directives from a text file. +- Simple directory structure for the resources. +- Work in batch mode, like a compiler. +- A Windows shell can be used to make your life easier. +- Compatible with Level editors (like DEU,WinDEU). +- Merge a pwad into the main iwad, recreating the wad directory, + so that ANY or ALL kinds of sprites and/or Flats can be defined, + while distributing only the changed ones in the pwad. +- Extract Graphics, Bitmaps and Lumps out of your favorite pwad, + for contemplation or reuse. (WITH wad AUTHOR AGREEMENT ONLY!) +- Check your pwad for errors in Texture definitions. +- Create animated walls with (almost) any sequence of pictures. +- Create a non repeating sky Texture. + + ------------- + DEUSF + ------------- + +DeuSF stands for DEU Sprite and Flats. It is mainly used to +compensate a bug in Doom sprite and flats handling. + +DeuSF was inspired by DMADDS by Bernd Kreimeier, but is more powerful +and much cleaner. Like DMADDS, DeuSF compensates for a bug in Doom +concerning the treatment of external sprite and flat pwads. It will +enables you to distribute pwads containing only the sprites and/or flats +that you wish to replace. There are some caveats here, so read the +manual! DeuSF can read DMADDS files, but its' preferred pwad composer is +of course DeuTex, since pwads composed for DMADDS are very dirty inside. + +DEUSF Features: + +- Recreate a complete sprite and/or Flat pwad from a partial sprite + and/or Flat pwad and the main wad of Doom. + +WARNING: The sprite names VILE[, VILE\ and VILE] are not valid DOS file + names, so DeuTex replaces them with VILE$, VILE@ and VILE# when + extracting them to files. Use these names for your files, too. + + page v + + +***************************** WHAT'S NEW? ***************************** + ++ New in DeuTex 4.0 ++ - Lots :-) + ++ New in DeuTex 3.8 ++ - ? + + New in DeuTex 3.6 + + - Possibility to take an entry from an existing pwad + If the file that contains your entry as extension .wad, deutex will + attempt to read it, and find your entry inside it. + - Bug corrections (there was still some left...) + - Wall patches must now be explicitly declared. If they are not, + DeuTex will try to find them in PATCHES\, as usual. + + New in DeuTex 3.5 + + - Bug corrections, as usual (there can't be much left!) + - New command -s_end for those that use new sprite names... + - Detection of textures that can cause Medusa effect + + + Added in DeuTex 3.4 + + - Many many corrections of small bugs (and compiler errors, dammit!) + - function -usedtex to find the texture use in all levels + - Overwrite switch (-o) to replace data (when you really want it). + - A fully working merge and join function (I hope) + - Improved support for WinTex + + Added in DeuTex 3.3 + + - Added a -get function to retrieve a single wad entry + - Improvements to -merge so that it can be used with Heretic + NOTE: HERETIC V1.0 CAN'T USE EXTERNAL SPRITE wad. + THIS IS A BUG IN HERETIC, NOT DEUTEX, DEUSF OR NWT + - Sound formats corrected (at least) but compression not supported. + - Now -merge and -app, -join preserve the file time, not only the + contents so that you can still patch your iwad after -merge. + - A _DEUTEX_ entry is added in the wad directory + - New [MUSICS] section and MUSICS subdirectory. + - Small patch to prevent DCK from bugging at modified iwads + - DeuTex can now read duplicate sections in Wadinfo.txt + when extracting new data, if wadinfo.txt exist , it appended + + SUPPORTED + + + Doom registered 1.1 to 1.9 and above + Doom2 1.6 to 1.9 and above + Heretic registered 1.0 and (probably) above + + NOT SUPPORTED (by request of Id software) + + Doom shareware + Heretic shareware + + It is possible for a hacker to modify DeuTex/DeuSF and make + it compatible with Doom or Heretic shareware. + If you're *that* short of money that you're ready to hack a + prog to save 40$ and the pleasure to be supporting one of the + very best game company, please don't distribute your version + of DeuTex/DeuSF, because I have no time to spend answering + questions about a hacked DeuTex that could possibly fail + very differently than the original. + + + page vi + + + + + ---------------------------- + *** [PART ONE] GETTING STARTED *** + ---------------------------- + + +CHAPTER 1 +****************************** OVERVIEW ******************************* + +DeuTex is a GREAT program! + + +(preceding claim inserted over the objections of Olivier Montanuy) ;-) + + +*********************** A Note About This Manual *********************** + +There is a lot of redundancy in the manual. This is intentional. The +manual is intended to be used as a reference. When you have a question +on a particular aspect of DeuTex, look up a likely entry in the Table of +Contents, and read that entry. It should have the information you need. +This is to prevent you from having to jump around from page to page to +figure out a procedure in DeuTex. This doesn't mean that sections are +identical. Each section attacks a problem from a different viewpoint. +If one section doesn't help you, maybe a different 'angle' will. + +************************************************************************ + +This manual has a lot of trees in it. This chapter will give you a view +of the forest. DeuTex and DeuSF are powerful programs that will let you +do almost anything you can imagine in composing or manipulating pwads. +Notice the word composing. Deutex is an Orchestra Conductor. It can +perform whatever music you write for it brilliantly, but you must +supply the musicians. A pwad consists of many parts. DeuTex coordinates +those parts to give you the pwad you desire, but it doesn't create +them. With DeuTex you have access to all the resources in the Doom1 or +Doom2 iwads. Since it does so many things, it might seem a little +confusing at first glance. Don't worry. If you are familiar with Doom +(read Matt Fell's Doom specs and Hank Leukart's DoomFAQ), then all you +need to learn about DeuTex is it's organization. + +There are so many resources in Doom that it isn't reasonable to put them +all in one directory. DeuTex uses a subdirectory for each entry type. +Using these subdirectories is easy once they're explained. + +Deutex makes it possible to use a simple, straightforward method for +working with custom graphics (and sounds). The approach is as follows: + + 1) Put your resource files in subdirectories such as FLATS, SPRITES, + etc., further discussed below. + + 2) Use a `Wadinfo' file called something like `goodies.txt' to tell + Deutex how to assemble the resources into a pwad. + + 3) Run `deutex -make goodies.txt goodies.wad' to make the pwad. + +Now you can play your level with the resources, without any fuss +(unless, of course, something has gone wrong along the way). + + + + + page 1 + + + + +This method works for any resource. You can make sound-only wads that +will play with any version of Doom. You can include Level maps in a +multi-level pwad. DeuTex will put the Levels where you want them, +regardless of the internal EnMm OR MAPnm of the Level. If the finished +pwad doesn't contain new sprites or Flats, it can be played as is. +Otherwise, it can be rendered playable with DeuSF, which can be freely +distributed with your pwads. + +The DeuTex Visual Basic shell let's you use the Windows environment to +distribute those entries in the right directory, and then execute the +-make command. It doesn't change the way DeuTex works, it only makes +your life easier. + + --------------- +A) WHAT IS DEUTEX? + --------------- + +DeuTex is a pwad compiler. It allows you to organize ALL the resources +you modify, and group them into your pwad in a single step. This +eliminates the need for running a different program for each type of +editing you want to do (DMAUD, DMGRAPH, DMADDS, etc). + +DeuTex is NOT a: + map editor, (use DEU, DoomCAD, WadEdit...) + nodes builder, (use DEU, BSP, IDBSP,...) + reject map builder (use RMB or REJECT) + DOOM.EXE editor (use DEHACKED) + +Your Level map with nodes, reject and blockmap already calculated is +just another resource to DeuTex. If you don't want to redefine or create +Textures, Flats, sounds, etc. in your pwad, you don't need DeuTex. + + On the other hand, if you redefine LOTS of stuff, + you'll wonder how you ever got along without it. + +If you've worked with wads before, you know how many times you have to +go in and change something! With DeuTex, you just edit the resource you +want to change, throw it back in it's subdirectory, and run a batch +file to put everything together again. + + ------------ +B) INSTALLATION + ------------ + +DeuTex comes in zipped format. Naturally, you need a copy of PKUNZIP +(v2.04G) to unzip it. If you don't have one, go get it! It's probably +available the same place you got DeuTex. PKUNZIP also exist for Unix. + +The file name is DEUTEX35.ZIP or something like it. This manual is valid +for DeuTex versions 3.6 and above. Some information is not applicable to +previous versions, and may cause you problems. Be forewarned! + +Installing DeuTex: + +DeuTex and DeuSF should be put somewhere in your path, e.g. under +C:\DOS in DOS, ~/bin under Linux/Unix, etc. This is not ABSOLUTELY +necessary, as you can put a copy in your working directory each time +or specify path names in all the commands, but, believe me, it makes +life much simpler. + + + page 2 + + + + +You should enable DeuTex/DeuSF to locate your Doom or Doom2 files +by creating an environment variable DOOMWADDIR that points to +your Doom path like this: + +For DOS, put the line 'SET DOOMWADDIR=C:\GAMES\DOOM' in AUTOEXEC.BAT. + +For Unix with sh, ksh or Bash, use 'export DOOMWADDIR=~/games/doom' +in .profile. + +For Unix with csh or tcsh, use 'setenv DOOMWADDIR ~/games/doom' in .tcshrc. + +This is more important for the Linux/Unix version, since with DOS +the command deutex -doom will achieve the same result. In +DOS, it's possible to get an 'out of environment space' error if you +have too many variables defined in autoexec.bat (including path, etc). +If this occurs, use DOS Help for the SHELL command to find out how to +increase your environment space. + + Of course, DeuTex will only work if the REGISTERED + version DOOM.wad or DOOM2.wad is available. + +Should you be in dire need of disk space, or should you wish to use +DeuTex on a machine that can't run Doom, you can use DeuTex to build a +fake DOOM.wad or DOOM2.wad, keeping only the structure of the directory +and the entries PLAYPAL, TEXTURE1, TEXTURE2 and PNAMES. Of course, to do +this, you first need a complete registered DOOM.wad or DOOM2.wad, and +even then it's a real pain. Beware to keep that file for yourself ONLY. + +The archive for DeuTex 3.6 contains the following files. For +illustration purposes, the diagram assumes you put DEUTEX36.ZIP +in the root directory (C:\). Directory information is embedded +in the zip file, so use the PKUNZIP -d option: + + PKUNZIP DEUTEX36.ZIP will produce: + +C:\deutex36.zip + |_ + \DEUTEX\ deusf.exe - DeuSF program. + deutex.exe - DeuTex program. + + dtexman6.txt - This manual. + file_id.diz - For BBS use. + + readme.txt - Short description of DeuTex/DeuSF. + + doom.pal - Doom palette, PaintShop Pro format. + heretic.pal - Heretic palette, PaintShop Pro format. + + test-me.zip - a ZIP file containing batch files + to test DeuTex with Trinity.wad + + + + +You may end up moving the palettes if you want them in their native +application's directory. + +WinTex, the Visual Basic shell for DeuTex, has gone so huge and +powerful that it can't be included in the deutex files anymore. +It will be available separately, as WINTEX35.ZIP. + + + + + page 3 + + ---------------------- +C) DIRECTORIES AND DeuTex + ---------------------- + +Chapter 5 tells you all about the directories DeuTex uses, but this +section will give you the general picture. I'm going to use an +imaginary cake making machine to explain DeuTex's directories (I know, +I know, it's stupid! ). To make cake with this machine, you put your +flour in one, container, raisins in another, sugar another, milk, +icing, walnuts, chocolate, eggs, etc. All your best stuff, each in it's +own place. Then you flip the switch, and the machine thumps and smokes, +and voila! Cake! + +DeuTex works in the same way . You put your Map in one box, sounds in +another, textures, patches, graphics, lumps, sprites and flats all in +their own boxes. If you don't want raisins today, leave the sprites box +empty. When all is in place, flip the switch (DeuTex -make, in a batch +file preferably), DeuTex thumps and smokes for a little while, and +voila! pwad! + + --------------- +D) WHAT DO I NEED? + --------------- + +************************** User Requirements ************************* + +ATTENTION: DeuTex is not completely trivial to use. It requires a + fully functional processing unit, with a least 10000 meg + of available neurons, some basic DOS and Doom specs dynamic + libraries and at least 1 or 2 hours of spare processing + time at a minimum 80% attention rate. You have been warned. + +SUGGESTION: If you use DeuTex, try New Wad Tool, too. The two tools + combine very well together under DOS. (NWT is not available + for other O/S). + +************************ Hardware Requirements *********************** + +This program is an ordinary DOS executable, compiled in a HUGE memory +model, with 386 instructions. It does not make use of a math +coprocessor. It should run with about 500k of free base memory, or less. +It might not run under a 286. It was tested on a Compaq LITE 4/33c and +an IBM Thinkpad 755c. + +DOS/GO32, Unix, Linux, OS/2, SGiX and Alpha versions are also available. + + ------------- +E) WHAT DO I DO? + ------------- + +Please read this Manual before asking questions. I know it's boring, but +this IS freeware, and I have limited time to support it. Bug reports ARE +appreciated IF they come with the files you were using when the bug +occurred, and a full description of it. + +Read and be familiar with all the Doom literature you can, especially +the 'unofficial' DOOM SPECS 1.6 by Matt Fell. You don't need to read the +file formats, but you need to understand what the different entries are +for, and the tricks and limitations of Doom. + + + + + + page 4 + + + + +DeuTex makes some checks on your pwad, but I don't have time to program +for all possible errors. Become familiar with the various editors you +need to create the resources used in this program. DeuTex does not edit +things. It puts the things YOU edit together. For editing, use the best +sound or Graphic editor you can afford. + +When the foregoing is done, you take all your cool stuff. You put it in +DeuTex's boxes. You give DeuTex the directions on what to DO with your +stuff. You run DeuTex. That's All, Folks. + + + + + ------------------ +F) WHAT IS DEUSF FOR? + ------------------ + + +DeuSF is a program to help overcome some of Doom's limitations, +and still be able to distribute a reasonable sized pwad. With +sprites and flats, you have to replace EVERYTHING in order for +Doom to work right. This makes for a big pwad (3 to 5 megs), and +it's illegal to take Id's sprites or flats from Doom, put them in +your pwad, and then distribute them. + +DeuSF allows you to replace as few sprites and flats as you desire, +and distribute ONLY THOSE with your pwad. With the appropriate batch +file, it will change things at the USER's site to enable your pwad to +play, without stepping on toes, or asking people to download multi- +megabyte single Level pwads! + +Another advantage of DeuSF is that it makes sprite pwads playable with +either Doom or Doom2 using the same install.bat file. Isn't that great? + + + + + -------------------------- +G) WHAT ARE THE PALETTES FOR? + -------------------------- + + +doom.pal (Doom palette, for PaintShop PRO 3.0 shareware program) +heretic.pal (same, but for Heretic) + + +These are the color palettes used by Doom and Heretic. + +If you edit or create any graphics (patches, sprites, etc.) in your +favorite graphics program, the colors will most likely be different +from the ones used in Doom. When they are inserted in a pwad, they +need to be 'quantized', which is a fancy word for color-matched. +Although this sounds simple, it can actually be quite involved. DeuTex +can quantize colors, but it's not optimised for that, so quantization +might be quite poor: there is no dithering. +Quantisation of colors is a serious job, meant to be done by specialised +programs. + + + + + page 5 + + + + +What should you do before inserting a picture with DeuTex? + +* AVOID regular patterns, like squares/stripes. These patterns are prone + to create ugly aliasing when scaled by Doom. +* SMOOTH it! I mean, apply a low pass filter so that it appears blurred. + This will also hide some of the aliasing effects of scaling. +* QUANTIZE your colors with one of the supplied Doom palettes. DeuTex is + optimised for the original Doom palette. If you use another palette, + it will be slower. DeuTex will quantize your colors to the Doom colors + using a strange alchemy. No dithering. +* TRANSPARENT areas should be made of A UNIQUE COLOR, preferably CYAN + (r=0,g=255,b=255, but you can specify another color to DeuTex.) + + WARNING: Some lame programs don't support full 0-255 range. CYAN could + be r=0, g=252, b=252. Experiment first. + +The enclosed palettes are in the format of two good graphics programs. +Use them to quantize your pictures before you feed them to DeuTex. + +doompal.pal is in the format used by PAINTSHOP PRO v2, a popular +shareware graphics program with excellent color conversion capabilities. + +To convert with doompal.pal in PAINT SHOP PRO: + + - Load the file you want to convert. + - Select *Colors* from the menu bar. + - Select *Load Palette* from the drop-down menu. + - Browse to find doompal.pal and select it. + - In the 'apply palette to image using' box, select *error diffusion*. + - Select *OK*. + +PaintShop Pro will then quantize your image to the Doom palette. + + - Select *File* from the menu bar. + - Select *Save As* from the drop-down menu. + - Select *BMP - OS/2 or Windows Bitmap* from 'List files of type'. + - Select *Windows RGB Encoded* from 'File Sub-format'. + - Select *OK*. + +Doom will now display your Graphic pretty much as you expect. + +If you want to make a .PBM (portable bitmap), use ppmquant on your +picture, with doompal.ppm as the reference for colors. + + Alternatively, if you extract a Doom Graphic with DeuTex, it will + contain the Doom palette. You can then feed it to your favorite + program, and let it extract the palette for later reuse. + + WARNING: + Experiment with this first, as your program might not do what you + expect it to. For example ZSoft's PC Paintbrush will load the Doom + Graphic correctly and allow you to save the palette. However, if you + take a 24 bit image and load the palette, nothing will happen. You can + let PC Paintbrush convert the image to 256 colors (which it will do + poorly), and then apply the palette. The results will be grotesque, + because it doesn't quantize when applying a palette. A Doom palette + saved in this program would be useful only for Graphics you want to + hand-draw from scratch. The moral is, if you don't know what you're + doing, experiment first before using a Graphic you don't want to lose. + + + page 6 + + + +CHAPTER 2 + +*************** TEST-ME or What's inside TRINITY.wad? ***************** + + ------------- +A) About TEST-ME + ------------- + + TRINITY.BAT let's you have a quick overview of some of the + capabilities of DeuTex so you can decide if it's worth the trouble. + +TRINITY.BAT does the following: + + It lists the contents of TRINITY.wad (with identifications). + It decomposes TRINITY.wad and builds TRINIDAD.wad. + All this in only 3 trivial DeuTex commands. + +Requirements: + +- You must have TRINITY.wad, the great pwad by Steve McCrea. + (available on ftp.cdrom.com as TRINITY2.ZIP and + in the Compuserve GAMERS FORUM LIB 8 as TRINTY.ZIP) +- Doom must be in the \DOOM directory (\DOOM2 could work too) +- TRINITY.wad must be in the current directory. +- You must have *some* room left on your disk :-) +- You must be running DOS 5.0 or higher. +- You must NOT reuse any part TRINITY.wad without crediting Steve. + +Description of the file, TRINITY.BAT: + + ---------------------- +B) Listing the directory + ---------------------- + + rem ***DeuTex*** + deutex -doom \doom -wadir TRINITY.wad + ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ + (a) (b) + +(a)---> This tells DeuTex that DOOM.wad and DOOM.EXE are in the + \DOOM directory. OPTIONAL. +(b)---> This tells DeuTex to list the directory of TRINITY.wad + reporting the entry types. Types *could* be wrong, but not + with Trinity. + + ------------------------ +C) Decomposing TRINITY.wad: + ------------------------ + + rem ***DeuTex*** + deutex -doom \DOOM -dir . -xtract TRINITY.wad + ^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^ + (a) (b) (c) + +(a)---> The same as before. +(b)---> This tells DeuTex that it must store the result in '.' (which is + the current directory). You could skip (b), since '.' is the + default, or you could specify another directory, like -dir TEST. +(c)---> This tells DeuTex to extract all entries from TRINITY.wad. + + + + page 7 + + + + + ---------------------------------------- +D) Recomposing TRINITY.wad as TRINIDAD.wad: + ---------------------------------------- + + rem ***DeuTex**** + deutex -doom \doom -dir . -make wadINFO.TXT TRINIDAD.wad + ^^^^^^^^^^^ ^^^^^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ + (a) (b) (c) (d) + +(a)---> The same as before. +(b)---> The same as before. +(c)---> This tells DeuTex to create a new pwad, from the + creation directives contained in wadINFO.TXT. +(d)---> This is the name of the created pwad. + + + ------------------------ + E) Customizing TRINITY.wad: + ------------------------ + + You can edit wadINFO.TXT, the format is pretty simple to guess. + (see Chapter 8 - FORMATS for a precise definition.) + +- A line that begins with a ';' or '#' is a comment. DeuTex ignores it. +- Don't touch any lines with [xxxx] (they are section delimiters). + ++ Lets look at the [MUSICS] section: + ++ [MUSICS] + D_E1M1 + ++ This tells DeuTex to go into the \MUSICS subdirectory and get a file + called D_E1M1.MUS, which is the music of TRINITY.wad. You might + wish to delete this D_E1M1 if your sound card crashes while playing + trinity. + + You can add your own music, for Episode 1 Mission 2 by editing: + ++ [MUSICS] + D_E1M1 + D_E1M2 + + Of course, the file D_E1M2.MUS must exist... You can generate it + from D_E1M2.MID (MIDI format) by using MIDI2MUS. + + + +BEWARE: DeuTex is NOT fool proof yet. It should not crash your + computer, but the generated pwad may crash Doom if you make + mistakes. I'm very sorry for this, but I have more urgent + optimizations to do than foolproofing. However, the pwad + generated here should not crash Doom, if you use the real + TRINITY.wad as a basis. + + + + + + + + + page 8 + + + + +CHAPTER 3 +************************** WORKING WITH wads ************************** + + ------------ +A) INTRODUCTION + ------------ + +Read the DOOM SPECS: +Sorry. This is still unavoidable, because of the various tricks and +limits of Doom. If you have a problem, there is a VERY GOOD chance +it's referred to somewhere in Matt Fell's SPECS. + +NOTE: In the following discussion, avoid these common mistakes: + +Hall of Mirrors with new Textures: + + First, create your Level. + Then, build the nodes and reject. + Then add the new Textures. + +Why? We don't know. leonardc@halcyon.com reported he saw a hall of +mirrors with old versions of DeuTex that didn't first load the old Doom +Textures. It seems to be a problem with the node builders. + +Tutti Frutti and Medusa Effect: + +See the DOOM specs, and Chapter 8 - FORMATS. +If Doom attempts to display part of a Texture not covered by a patch, +you'll see some ugly garbage (usually has pinks and greens, thus 'Tutti +Frutti'). The same thing happens if you use more than one patch on a +Texture with transparent areas, or walls with see-thru portions on upper +or lower Textures. If the area is big enough, it will slow the display +to a crawl ('Medusa Effect' - Looks like snakes and turns you to stone). + +Doom reports a void column and exits: + +One of your Textures has a column with no patches. Use DeuTex -check on +a pwad before running Doom. It reports Textures that have void columns. + + Other bugs: + + Mail me a description of the bug, together with any configuration + files. Don't expect a quick answer, though. + + ----------------------- +B) How to decompose a pwad + ----------------------- + +First check that all the entries are identified correctly: + + DEUTEX -wadir NEWBIE.wad This will list the directory. + +Then try: + + DEUTEX -unused NEWBIE.wad This will tell you if there is any wasted + data in the pwad. It's always funny to see + how DMGRAPH and DMAUD waste *some* data. + This won't tell you about any data wasted + by incorrect entry formats, though. + + + page 9 + + +To extract entries in the pwad: ++ ++DEUTEX -get SPOSA1 DOOM.wad Extract the entry SPOSA1 from DOOM.wad ++ + DEUTEX -xtract NEWBIE.wad Extract all the entries in NEWBIE.wad. + A directory structure is created, and the + entries are put in the subdirectories. + A file wadINFO.TXT is created, to describe + the contents of the pwad. + + DEUTEX -sound -xtract NEWBIE.wad Only the sounds are extracted and + placed in the \SOUNDS subdirectory, + which is created if it doesn't exist. + +NOTE: Some obsolete pwad tools used to declare patches, Flats and sprites + without the normal markers. DeuTex attempts to compensate, but + it could be that some entries will be identified incorrectly. + DeuTex will then consider them as LUMPS or as GRAPHICS. So if you + don't find a sprite in .\SPRITES\, look in .\GRAPHICS\. + You will then have to declare them in the [SPRITES] section again. + + +Once you have decomposed a pwad, you can rebuild it with: + +DEUTEX -make wadINFO.TXT NEWBIE.wad + +wadINFO.TXT already exists, because it was automatically created during +the extraction of NEWBIE.wad (cool, no?). Make sure you delete or move +the previous version of NEWBIE.wad before you remake it, because DeuTex +will not overwrite your files (you might not like it :-]). + +NOTE: DEUTEX puts a signature in the first few bytes of a created pwad, + to identify which version of DEUTEX was used. + + + -------------------------------------- +C) How to create a pwad with new Textures + -------------------------------------- + + First list Doom's Textures, as a reference: + + DEUTEX -texture -extract + + This will extract all the Textures from the main iwad. They will be + written to TEXTURE1.TXT (and TEXTURE2.TXT for Doom1 only). These text + files will be placed in the subdirectory \TEXTURES, which will be + created if it doesn't exist. These files make it easy for you to + redefine existing Textures by cutting them out and pasting them into + YOUR Texture definition file. Note that it's not wise to redefine + textures from Doom or Doom, except if you're redefining an animation. + + When you will wish to define new textures, you will put those textures + in a texture file, which is no more than a specially formatted text file + (no, it's not a picture) that you will put in .\TEXTURES, and that + you will declare in the [TEXTURE1] section of wadINFO.TXT. + This Texture file need not contain all the textures in Doom, only those + that you wish to redefine. It's a bad idea to keep all the textures + from Doom in your texture file. Let DeuTex handle that. + + There can be more than one texture file, which is convenient if you + have already created textures for another wad and wish to import them. + + + page 10 + + Note that if you define a texture more than once, only the last + version read by deutex will be put in the wad. + Not also that if you define a texture that has the same name as + a texture + + + + NOTE: For DOOM1/Heretic only, use one file for redefined Textures + from OLDTEX1.TXT, and another file for redefined Textures + from OLDTEX2.TXT. Since DeuTex v3.3, wadINFO.TXT uses a second + Texture section called [TEXTURE2] for redefined OLDTEX2 files. + + + DeuTex 3.3 doesn't care if OLDTEX1.TXT or OLDTEX2.TXT exist. + DeuTex 2.x used to require that all the old textures be present, + but now DeuTex 3.3 first read the internal Doom texture definitions, + then reads the file you tell it to read, for new definitions. + If you mistakenly define the same Texture in multiple files, + only the last declared version will be used. Of course, that means + that if you redefine a Doom texture your version will be used. + +Declare TEXTURE1 in the [TEXTURE1] section of wadINFO.TXT. +Then build your pwad: + +DEUTEX -make wadINFO.TXT NEWBIE.wad + +At this point, it would be a good idea to +check your new pwad for Texture errors: + +DEUTEX -check NEWBIE.wad + + + ----------------------------------------------- +D) How to create a pwad with new sprites and Flats + ----------------------------------------------- + +******** 1) Sprite and flat replacement + +BEWARE: Sprite replacement is tricky. If some needed sprites are + missing Doom will lock up. Check your work often. + +Put your sprite files in \SPRITES in .GIF or .BMP format. +Put your Flat files in \FLATS in .GIF or .BMP format. +Declare your sprite NAMES in the [SPRITES] section of wadINFO.TXT. +Declare your Flat NAMES in the [FLATS] section of wadINFO.TXT. +Use only the NAME in wadINFO.TXT, without the .GIF or .BMP extension. + + Since DeuTex 3.1: + The '=' label lets your sprites keep the names YOU have given + them. It tells wadINFO.TXT what Doom sprite you mean to replace. + This enables you to name your sprite files as you damn wish. + +If you want to replace *ALL* of the sprites and Flats in Doom (crazy): + +DEUTEX -iwad -make wadINFO.TXT NEWBIE.wad + +NEWBIE.wad will be directly usable by Doom. + +Remember: replacing only part of the sprites and Flats mean you'll +need DeuSF to install your pwad, but it will be compatible with ALL +versions of Doom and Doom2. Redefining all the sprites is not a good +idea unless you really mean it. + + + page 11 + + + + +To replace *SOME* of the sprites and/or Flats in Doom (better): + +DEUTEX -make wadINFO.TXT NEWBIE.wad + +This NEWBIE.wad will be much smaller and easier to distribute. +BUT: This NEWBIE.wad will cause Doom to lock up when it starts!(bad) + + So, if you want to replace only *SOME* of the sprites and Flats in + Doom, you have 3 choices: + +DEUTEX -merge NEWBIE.wad Modifies DOOM.wad or DOOM2.wad. + (Safe, fast, and small) + +DEUSF -append NEWBIE.wad Modifies NEWBIE.wad. + (Safer, still fast, wastes some space) + +DEUSF -add NEWBIE.wad NEWBIE2.wad Creates NEWBIE2.wad. + (Safest, not slow, more space wasted) ++ ++ NEW! To merge two pwads that both redefine sprites and/or Flats: ++ ++ DEUSF -join FIRST.wad SECOND.wad (FIRST.wad now contains both wads) + + +NOTE: The steps above are performed at the end users' site, preferably + from a batch file supplied with your pwad. This means the user + must have DeuSF, which can be distributed freely with your pwad, + or DeuTex, which has some restrictions on distribution. See the + License Agreement at the end of this manual for the restrictions + on distributing DeuTex. + +The -sprite command is used to add only sprites, ignoring the Flats: + +DEUSF -sprite -app NEWBIE.wad + +The -flat command is used to add only Flats, without the sprites: + +DEUSF -flat -add NEWBIE.wad NEWBIE2.wad + + + ******** 2) HOW to ADD or REMOVE SPRITE VIEWPOINTS + + DeuTex allows you to alter the number of viewpoints a sprite displays + in your pwad. DOOM.EXE predetermines the 'behavior' of a given sprite + name, but it doesn't predetermine the number of viewpoints. A sprite + MUST, however, always have either ONE viewpoint or EIGHT viewpoints. + Viewpoints are numbered as follows: + + Front + + 1 + 2 | 8 + \____|____/ + | | + 3 -- | SPRITE | -- 7 + |_________| + / | \ + 4 | 6 + 5 + + + page 12 + + + + + The FULL NAME of the sprite determines the viewpoint of that sprite: + + BAR1A2.bmp + \ /| \________________ + \/ | \ + ________________/ | The last number is the viewpoint. A + / | zero here means the sprite has only + The first four letters are the | one viewpoint. If not zero, there + sprite name as recognized by | MUST be 8 files for each 'frame' of + DOOM.EXE. They are the same for | the Sprite. + all entries of a given Sprite. | + | + This is the 'frame' number of the Sprite. Animated + Sprites will have consecutive letters here for each + frame (A is frame one, B is frame two, etc.). DOOM.EXE + predetermines how many frames a Sprite uses, so you can + not animate an electrical column, for instance. + + Sometimes, you will see a Sprite entry that has 2 viewpoints in one + Sprite, like BOSSA2A8. This means that the same Graphic is used for + viewpoints A2 and A8 (front-left and front-right). When Doom sees + this, it uses the Graphic as is for A2, and mirrors it for A8. + + In the above example BAR1 is the Barrel Sprite. Doom does a 2 frame + animation on barrels (the slime flickers), so the whole entry is: + + BAR1A0 + BAR1B0 + + This disregards the explosion (BEXP) Sprite + that is used when you shoot a Barrel. + + If you want to change the Barrel Sprite to an 8 viewpoint + Sprite, you will need to create 16 Graphics: + + BAR1A1 + BAR1B1 + BAR1A2 + BAR1B2 + BAR1A3 + BAR1B3 + BAR1A4 + BAR1B4 + BAR1A5 + BAR1B5 + BAR1A6 + BAR1B6 + BAR1A7 + BAR1B7 + BAR1A8 + BAR1B8 + + This gives you 8 viewpoints for EACH frame of the animation. If you + only replaced BAR1A1 thru 8, you would see your new Graphic flash to a + barrel a couple of times a second, because you didn't replace the 2nd + frame. If you add a 3rd frame (BAR1C1 etc.), it will be ignored by + Doom because DOOM.EXE already knows a barrel has only 2 frames. + + + + + page 13 + + + + + Alternatively, you could take an Imp and give it only 1 viewpoint by + taking only one of the views for each animation frame and naming it + TROOA0.bmp (with the correct letter for the frame you're using). The + Sprite will look kind of funny moving around, since it will only face + one direction the whole time. + ++ Special Sprites replacements: ++ ++ Some of you like to define their own sprites names, via a dehacked ++ patch. This trick is useful, because if you use custom sprite names ++ in your pwad, then it need not be completed by all the sprites from ++ the iwad. However, it will need a S_END appended at the end, otherwise ++ the game will not work. ++ So use the switch -s_end when you build your sprite wad with DeuTex. ++ Example: deutex -s_end -make myweapons.wad + + + ---------------------------------- + E) How to create pwad with new sounds + ---------------------------------- + +First put your sound files in the .\SOUNDS directory. +Then, declare the sound NAMES in the [SOUNDS] section of wadINFO.TXT. +See APPENDIX IV for a listing of the sound names recognized by Doom. +Then build your pwad: + +DEUTEX -make wadINFO.TXT NEWBIE.wad + +Sound effects: [DSxxxxxx.WAV or DSxxxxxx.AU] + + Supported formats are WAV, AU (Sun Audio) and VOC. + Use only the 8 bits per sample, non-compressed, mono sounds. + Do not use Stereo, 16 bit sounds or ADPCM compression. + +PC speaker sounds: [DPxxxxxx.TXT] + + Text files containing a list of numbers from 1-255. + + + +Musics are different from sound files. They describe only the +notes to be played. They can't be obtained from normal sounds. +There is one music defined for each level of Doom or Heretic. +It has a special name, that is related to the level name (except +in Doom2) +Musics are declared in the [MUSICS] section, and placed in the +.\MUSICS directory. + +Music: [D_xxxxxx.MUS] + + They must be in MUS format. You can convert MIDI files to MUS files + by using MIDI2MUS.EXE (thanks to -dtt-> of Id software). + + You can get a list of musics by typing: + deutex -musics -wadir + This will help you guess the names of the musics. + + + + + + page 14 + + + +CHAPTER 4 + +************************** Visual Basic Shell ************************** + + ------------------------------------- + WinTex + The MS Windows shell for DeuTex. + version 3.41 + ------------------------------------- + + + + + +WinTex 3.41 is a tool designed to make DeuTex real easy to use. +It runs under Windows, and is written in C and Visual Basic. + +WinTex will prepare the data that DeuTex will compile into a wad. +It's real easy to figure out, once you know how deutex works, and + it will do for you all the stuff that deutex can't help you do + (like adjusting the sprites offsets, composing the textures). + +With WinTex, you can use your own level editor, sound editor, music +editor, picture editor, text editor, node builder, reject builder, +and rely on good old DeuTex to make the tedious job of wad +composition and wad merging. + +Actually, the windows part is only for the presentation, not for the real +work. Windows is too unsafe to do any serious job... + +WinTex is the best way to use DeuTex, provided you have Windows 3.1. +(WinTex is a 16-bit application, to spare you compatibility troubles) + +You will need VBRUN300.DLL in your windows/system directory, of course, +as this is a Visual Basic application. The other DLL and VBX are +provided with WinTex. + + + + + + + + + + + + + + + + + + + + + + + + + + + page 15 + + + + + ----------------------------- + *** [PART TWO] DETAILS, DETAILS *** + ----------------------------- + + +CHAPTER 5 + +************************* DIRECTORY STRUCTURE ************************* + +DeuTex uses the following directory structure to store Doom entries. +First create a directory (call it MYwadIR or whatever) for your pwad. +Make sure DeuTex is on your path, or put a copy of it in MYwadIR. Put +a copy of the pwad you are working on (MYwad.wad) in MYwadIR. + +Type: DeuTex -xtract mywad.wad + +DeuTex will automatically create the appropriate subdirectories and put +all the wad's entries in the proper place. It will also create a file +named wadINFO.TXT in MYwadIR. If your pwad is a bare map Level with no +additions yet, you should get something like: + + \MYwadIR\--------mywad.wad + | wadinfo.txt + | DeuTex.exe (optional, if not on your path) + |_ + \LEVELS\------EnMm.wad + +Note that DeuTex will not OVERWRITE any existing files. In the example +above, if you type DeuTex -xtract AGAIN, you will get an error message +telling you the files already exist. You have to delete wadinfo.txt and +EnMm.wad (or move them somewhere else) for xtract to work again. If you +lose something you wanted to keep, don't blame DeuTex, it's innocent! + + Now type : DeuTex <-doom doom directory> -textures -extract + +DeuTex will read the Textures from Doom.wad or DOOM2.wad, list them in +a file called TEXTURE1.TXT (and TEXTURE2.TXT for DOOM 1) and store them +in a directory called \TEXTURES, which it will create if it doesn't +exist. + +NOTE: The <-doom doom directory> command is optional. Take a look at + Chapter 6 - DEUTEX COMMANDS for a more complete description of + when you should use it. + +Your working directory should now look like this: + + \MYwadIR\-----mywad.wad + | wadinfo.txt + | DeuTex (optional) + |_ + | \LEVELS\----EnMm.wad + |_ + \TEXTURES\---texture1.txt + texture2.txt + +If your pwad had any other resources (Sprites, Flats, sounds, etc.) in +it and you used DeuTex -xtract, it would extract those resources, too. +Then it would create the proper directory and store them in it. + + + + page 16 + + + + +If you want to add something to your pwad, put it in the proper +subdirectory (create it if it's not there), and tell wadinfo.txt about +it. Chapter 8 - FORMATS describes wadinfo.txt in detail. + +Then type: DeuTex -make wadinfo.txt mywad.wad + +DeuTex will read wadinfo.txt and go get all the resources it asks for +from the directories. Then it will create mywad.wad from them. Note +that if you create a pwad from the above example, it won't be any +different than what you started out with! You need to put some +ingredients into the mix before you see any results. THAT's what the +other directories are for. + +Again note that DeuTex won't overwrite mywad.wad if it exists. Since +most of the stuff you'll do with DeuTex will be from a batch file, have +it handle your housekeeping whatever way you like. Something like the +following works pretty well: + + del mywad.wad + DeuTex -make wadinfo.txt mywad.wad + copy C:\DOOM\wads\mywad.wad mywad.bak + copy mywad.wad C:\DOOM\wads\mywad.wad + +This way, if you find out you've really screwed things up when you test +your pwad, there's always a copy of the previous version to use. + +DEUTEX SUBDIRECTORIES: + + -------- +A) \LEVELS + -------- + +'Bare' pwads go here! A bare pwad is one that you have edited and +constructed the nodes, reject, and blockmap. The pwad will then +contain only the following 11 entries in IT'S directory: EnMm(MAPnm), +THINGS, LINEDEFS, SIDEDEFS, VERTEXES, SEGS, SSECTORS, NODES, SECTORS, +REJECT, and BLOCKMAP. + +BEWARE: BLOCKMAP REJECT SSECTOR SEGS are not optional! they must have + been generated by your Level editor (along with BSP, IDBSP, + REJECT, RMB, whatever). + + THE FILES PUT HERE MUST BE DECLARED IN THE [LEVELS] SECTION OF + wadINFO.TXT. ALL FILES MUST BE IN THE FORM EnMm.wad OR MAPnm.wad OR + EQUATED TO EnMm or MAPnm in wadINFO.TXT. + + Suppose you have edited two Levels named PLAGUE.wad and E3M4.wad. You + want the combined pwad to replace E1M2 and E3M4 in DOOM.wad. You would + edit the [LEVELS] section of wadINFO.TXT to read: + + [LEVELS] + E1M2 =PLAGUE + E3M4 + + This tells DeuTex to look in the LEVELS\ subdirectory for PLAGUE.wad + and E3M4.wad and to combine them in the final pwad as E1M2 and E3M4. + + + + + + page 17 + + + + + ------- +B) \LUMPS + ------- + +Lumps are raw data for Doom with the extension .LMP. If you have +edited or created any of them for your pwad, put them here. The +following files are the LMPs used by Doom. You can insert something +else if you like, and Doom will ignore it. It's a mystery why anyone +would do this, but wad builders are a mysterious bunch! + +*********************** Lumps recognized by Doom ********************** + +PLAYPAL.LMP Color PALETTES (14 of them consisting of 256 RGB triplets + each - 768 bytes/palette). The first one contains the + normal Doom colors. The others temporarily 'tint' the + screen colors for different events in Doom. (Item pickup, + Hurt and Berserk Reds, Radsuit Green etc...) + +COLORMAP.LMP Color MAPS. There are 34 of these,consisting of + 256 bytes each. These are NOT RGB triplets. They map + whatever PLAYPAL currently being displayed by Doom to + darker colors corresponding to the light level in a + sector. These mapped colors are what you see on the + screen. The first map (map 0) corresponds to a light + level of 247-255, and doesn't change the display at all. + The 32nd map (map 31) corresponds to a light level of 0-7 + and maps almost all colors to the darkest one in the + presently use PLAYPAL. Map 32 makes everything black and + white for 'invulnerability'. Map 33 is all zeros. + +ENDOOM.LMP Text displayed when leaving Doom. Use A program + like TED or ENDOOMER to edit this text. + (DO NOT REMOVE THE ID COPYRIGHT!) + +DEMO1.LMP / Demos recorded by Doom. +DEMO2.LMP < e.g. DOOM -record DEMO2 -file MYwad.wad +DEMO3.LMP \ Then move DEMO2.LMP here, and that's all! + +DMXGUS.LMP (DOOM1) / Text file remapping MIDI instruments +DMXGUSC.LMP (DOOM2) \ for the Gravis Ultra Sound card. + +GENMIDI Instrument mapping for GENMIDI compatible cards. + +*********************************************************************** + +Suppose you have edited ENDOOM.LMP and recorded a new DEMO1.LMP for +your pwad. Just put copies of them here, and declare them in the [LUMPS] +section of wadINFO.TXT like this: + + [LUMPS] + ENDOOM + DEMO1 + + This tells DeuTex to look here for ENDOOM.LMP and DEMO1.LMP + +*********************************************************************** + ++ To replace the Heretic TITLE screens, put a 320x200 picture in the LUMPS ++ subdirectory and declare it as you would declare a TITLE lump. ++ DeuTex will know that it must convert it to the special RAW format. + + page 18 + + + + + ---------- + C) \TEXTURES + ---------- + + NOTE: DOOM1/Heretic contains 2 Texture entries, TEXTURE1 and TEXTURE2. + this is because of differences between the shareware and registered + versions. If you are using DeuTex with Doom2, just ignore any + references to TEXTURE2. It doesn't exist in DOOM2.wad. + + This subdirectory contains a text file(s) describing the Texture + changes you want in your pwad (Chapter 8 describes Texture definition + files). Your file can be given any name you want (prefer TEXTURE1.TXT + or TEXTURE2.TXT). This name (without extension) is then entered in the + [TEXTURE1] section of wadINFO.TXT. + + FILES PUT HERE HAVE THE EXTENSION (.TXT). THE TITLE OF ANY FILE PUT + HERE MUST BE DECLARED IN THE [TEXTURE1] SECTION OF wadINFO.TXT. + + The file names OLDTEX1.TXT and OLDTEX2.TXT are reserved. Due to an + amazing bug (in Doom?), if Doom's Texture list contains any new or + redefined Textures before all the UNCHANGED Textures are listed, it + produces HOM (Hall of Mirrors) errors. Previous versions of DeuTex + dealt with this problem by requiring a copy of TEXTURE1.TXT (with any + redefined Textures deleted) here in the \TEXTURES subdirectory. This + is no longer necessary with version 3.3. DeuTex now reads the original + TEXTURE1 from the main iwad while creating your pwad. It then reads + your new Textures and automatically sorts , deletes, and combines all + entries. Olivier's too good to you guys >;-] + + EXAMPLES: + + If you want to add ONLY new Textures: + + - Put your definition file here (e.g. TEXTURE1.TXT), and declare + TEXTURE1 in the [TEXTURE1] section of (wadINFO.TXT). + + If you want to redefine Textures in TEXTURE1: + + - Run DeuTex -dmtextures to get the Textures. + - Cut the Textures to be redefined from OLDTEX1.TXT and paste + them into TEXTURE1.TXT. Edit them or change them as you wish. + - You can delete OLDTEX2.TXT and OLDTEX1.TXT now if you want. + - Declare TEXTURE1 in the [TEXTURE1] section of wadINFO.TXT. + + If you want to redefine Textures in TEXTURE2: + + - Run DeuTex -dmtextures to get the Textures. + - Cut the Textures to redefine out of OLDTEX2.TXT and put + them in TEXTURE2.TXT. Edit and change them as you wish. + - You can delete OLDTEX1.TXT and OLDTEX2.TXT now if you want. + - Declare TEXTURE2 in the [TEXTURE2] section of wadINFO.TXT. + +APPENDICES I and II contain lists of the animated and switch Textures +from DOOM.wad (Not the new ones from DOOM2, sorry. Use DeuTex to make +your own list). Copy the portion you want to edit into TEXTURE1.TXT. +It's a little easier than hunting through the entire OLDTEX1.TXT files. +Beware: some textures change a lot, between Doom and Doom2. + + + + + page 19 + + + + + -------------------- +D) \SOUNDS and \MUSICS + -------------------- + ++ Put your new sound files here in the correct format. They must have ++ the same name as the sound you want to replace (Appendix IV lists the ++ Sound names used in Doom1 and Doom2. It also lists the sound names for ++ each DMAUD sound number). Put the sound NAME (no extension) in the ++ [SOUNDS] section of wadINFO.TXT. + +DeuTex uses the following formats for Doom sound files: + +MUSIC: (D_xxxxxx.MUS) for Doom/Doom2 + (MUS_xxxx.MUS) for Heretic +MUS format (RAW format, which can be created from MIDI +files with MIDI2MUS.EXE, provided by ddt). + +SOUNDCARD SOUND EFFECTS: (DSxxxxxx.WAV) for Doom/Doom2 + (xxxxxxx.wav) for Heretic +Windows WAVE file (.WAV). Use a converter if you prefer .AU. +Preferably use 11025 sample/second for your recording. +VOC format is supported only for 11025 sample/s (DeuTex can't convert). + +PC-SPEAKER: (DPxxxxxx.TXT) only for Doom +Text files (.TXT) with numbers 0-255 + +WARNING: DeuTex assumes that any file name beginning with: + 'D_' or 'MUS_' is music. + 'DS' is sound card sound effect. + 'DP' is PC speaker sound effect. ++ Suppose you've created new music for Level E1M5 called D_E1M5.MUS. You ++ also want to replace DSSHOTGN with a your file called PTOOEY.WAV. You ++ would put the files here and edit your wadINFO.TXT as follows: ++ ++ [MUSICS] ++ D_E1M5 ++ [SOUNDS] ++ DSSHOTGN =PTOOEY ++ ++ This tells DeuTex to look here for D_E1M5.MUS and PTOOEY.WAV. ++ It will replace the sound DSSHOTGN with PTOOEY.WAV + + ---------- +E) \GRAPHICS + ---------- + +For Doom pictures other than Sprites, Flats or Textures. Put the +changed Graphic FILE here in .BMP or .GIF format, and enter the NAME +(without extension) in the [GRAPHICS] section of wadINFO.TXT. + +Suppose you have created a new TITLEPIC.BMP, and want SURRENDR.BMP to +replace VICTORY2. Just put the files here and declare them in the +[GRAPHICS] part of wadINFO.TXT, like: + + [GRAPHICS] + TITLEPIC + VICTORY2 = SURRENDR + + DeuTex will look here for TITLEPIC.BMP and SURRENDR.BMP (or .GIF). + It will use SURRENDR.BMP for VICTORY2. + + page 20 + + + + +************ Some examples of Graphic entries in DOOM.wad ************* + +HELP1 The HELP screen for Doom 1.666. +HELP2 Second HELP screen for Doom 1.666. +HELP The HELP screen for Doom 2. +TITLEPIC The title pic for Doom (320 x 200). +CREDIT The credits for Doom (Don't touch!). +VICTORY2 The background of the victory scenes. +STCFNxx The fonts for Doom. +STxxxxx Description of the status bar. +M_xxxxx Description of the menus. + +You can read Matt Fell's DOOMSPEC for other entries, or extract +them for yourself with DeuTex -graphic -xtract DOOM.wad. + + --------- +F) \SPRITES + --------- + +Put your new Sprites here in (.BMP) or (.GIF) format. + +WARNING: DOOM WILL LOCK UP IF YOU ATTEMPT TO REPLACE ONLY SOME OF THE + EXISTING SPRITES! Either replace all the Sprites with DEUTEX + -iwad -make or replace only some of the Sprites and use DEUSF + -add, DEUSF -append or DEUTEX -merge. + + Suppose you want to redefine SPOSA1 and TROOB2. You want to replace + them with SPOSA1.GIF and LIZARD.BMP. Put the files here, and then + declare them in the [SPRITES] section of wadINFO.TXT, like: + + [SPRITES] + SPOSA1 + TROOB2 =LIZARD + + DeuTex will look here for SPOSA1.BMP (or .GIF) and LIZARD.BMP. + + ------- +G) \FLATS + ------- + +For new floors and ceilings as 64x64 (.BMP) or (.GIF) files. + +WARNING: TO USE YOUR NEW FLATS, YOU MUST MERGE YOUR pwad WITH THE MAIN + iwad, OR USE DEUSF TO PUT ALL THE iwad FLATS INTO YOUR pwad. + +Sorry, but this is a limitation of Doom, not of DeuTex. Flats inserted +here will not crash Doom when the pwad is run because I don't use the +regular F_START F_END delimiters that confuse Doom. Your pwad *WILL* +fail when it references those Flats, so heed the warning above. + + Suppose you want MUDDY.BMP as a new Flat, and HATCH.GIF to replace + FLOOR1_7. Put the FILES here, and declare them in wadINFO.TXT, like: + + [FLATS] + MUDDY + FLOOR1_7 =HATCH + + DeuTex will look here for MUDDY.BMP and HATCH.BMP (Then HATCH.GIF), + and replace FLOOR1_7 with HATCH.GIF. BUT, SEE WARNING ABOVE! + + + page 21 + + + --------- +H) \PATCHES + --------- + +The patches are the pictures that compose the textures. These +pictures are often used for more than one texture. ++ Since DeuTex 3.6: ++ The patches are handled pretty much like Graphics, except that ++ they are to be declared in the [PATCHES] section, and the ++ corresponding picture put in the .\PATCHES subdirectory. ++ ++ Older versions of DeuTex didn't require you to declare your patches, ++ they were loaded automatically if required, but this could lead to ++ confusion. Now, if you want to replace an existing patch, you must ++ declare it explicitly. ++ DeuTex can guess the patches you need when it reads the textures ++ definitions. For compatibility with older versions, DeuTex will attempt ++ to load a patch from .\PATCHES if it detects that this patch is used. + +For every new patch that is used in the texture definitions, there +must be a corresponding entry in the [PATCHES] section, and a +corresponding picture file in the .\PATCHES subdirectory. + +EXAMPLE: + +Suppose you want to create a new Texture called MYDOOR, which contains +two new patches called WOODEN0 and KNOB0, and a modified WARNA0 patch. +The new Texture also contains the existing EXIT1 patch. + +FIRST: Put WOODEN0.BMP, KNOB0.GIF, and WARNA0.BMP here. + +THEN: Define your new Texture in TEXTURE1.TXT as shown below: + + MYDOOR 256 128 ; a 256x128 wall with ... + * WOODEN0 0 0 ; a 256x128 background + * KNOB0 64 100 ; and a small knob at (64,100) + * WARNA0 128 12 ; a lite at top/center + * EXIT1 128 32 ; the word exit in the center + +THEN: Put TEXTURE1.TXT in the \TEXTURES subdirectory. + +THEN: Tell wadINFO.TXT that TEXTURE1.TXT is the file containing new or + modified Textures by declaring it in the [TEXTURE1] section: + + [TEXTURE1] + TEXTURE1 + +THEN: Declare your new patches + + [PATCHES] + KNOB0 + WOODEN0 + WARNA0 + +DeuTex will read TEXTURE1.TXT from \TEXTURES. TEXTURE1.TXT tells DeuTex +that a new texture called MYDOOR is 256 pixels wide, and 128 pixels high. +The asterisks tell DeuTex to look here for the patches WOODEN0.BMP, +KNOB0.BMP, WARNA0.BMP and EXIT1.BMP. The numbers tell it where the +patches go on MYDOOR. Note that WOODEN0 had better be 256x128 or bigger, +or there will be at least one void column, and Doom will complain and +stop. If an existing patch is called for, and no entry by that name +exists here, the old patch will be used. + + page 22 + + + + +CHAPTER 6 + +*************************** DeuTex Commands *************************** + + -------------------------- +A) COMPLETE COMMAND REFERENCE + -------------------------- + +Actually it's not complete, but those commands not mentioned here +are for the Visual Basic Shell, and you'll never use them. Commands +with an '*' are not implemented in the VB version. I forgot them. +All optional commands must appear before non-optional ones or else +they will be ignored. The Command Line Format is: + DEUTEX <-optional cmd.> ,..., <-non-optional cmd.>,...,etc. + ++ Note: since DeuTex 3.5, upper case commands are accepted. ++ You will generally need to type only the first 3 letter of a command. + + ------------- +B) HELP COMMANDS + ------------- + + -help* This one won't help you a lot, but it + will give you the parameters. + + -syntax* Prints a short listing of the format of wad creation + directives (wadinfo.txt). See the FORMATS Chapter in + this manual for a more complete explanation. + + ----------------- +C) OPTIONAL COMMANDS + ----------------- + + -doom + + Use this command to indicate the directory containing + DOOM.wad and DOOM.EXE or DOOM2.wad and DOOM2.EXE. + + If this command is not used, DeuTex looks first in the + current directory for Doom. Then it looks in the current + directory for DOOM2. Then it looks in the root directory of + the current drive for a directory called Doom, and finally + looks in the root directory of the current drive for a + directory called Doom2. The first Doom it finds is used. + + EXAMPLE: DEUTEX -doom C:\GAMES\DOOM + + -dir + + DEFAULT IS: CURRENT DIRECTORY. This defines the working + directory, into which you or DeuTex will put the wad + creation directives (wadINFO.TXT). All subdirectories + containing pwad parts will branch from here. The completely + assembled pwad will also reside here. + + -deu* Use this if you want DeuTex to add 64K of junk at the end + of your pwad. Why? To compensate for a bug in DEU 5.21, + that makes it sometimes crash when viewing pictures. + That bug is corrected in DEU 5.3. + + + page 23 + + + + + -rgb + + Let's you pick what *exact* color DeuTex will use for Doom's + transparent color. The default is CYAN(R=0, G=255, B=255). + + EXPLANATION: + Doom allows transparent areas in textures. Although there + are 256 colors in the Doom palette, only 255 of them act + as colors. Color number 247 (CYAN R=0 G=255 B=255) is used + by Doom as a 'switch' to make that pixel invisible. + + When DeuTex imports your new graphics into a pwad, it must + assign each pixel one of the Doom colors. For most of the + 16 million colors possible in an RGB format such as .BMP + and .GIF, it is just a matter of finding the most + appropriate colors in the Doom palette to map to your + graphic. However, CYAN is more of a 'switch' than a color. + It wouldn't be appropriate for DeuTex to say "anything CLOSE + to CYAN is transparent". That would be like saying "anything + close to linedef type 39 is a teleport". Transparency is a + switch, and has to be exact. + + Some graphics programs may not be able to meet this + requirement. For example, some programs limit you to 64 (0-63) + increments each in Red, Green and Blue. They multiply the + result by 4 to get the true RGB value. This is fine for most + purposes, but not for Doom. + + In any such program, the closest you can get to CYAN is, + 0 for Red, 63 for Blue and 63 for Green. When multiplied + to get a true RGB value, this becomes R=0, G=252,B=252. + You couldn't tell the difference by looking, but DeuTex can. + It will take this value and say "Hmmm... Light Blue". Your + graphic will be disappointing when you see it in Doom :-< + -rgb 0 252 252 will make you smile again :-) + + Another example of when you might want to use this command + is if you use a raytracer to create your graphics. Most of + these programs render the background as black. If you use + the option -rgb 0 0 0, things will be much easier. + + -bmp File format to use when EXTRACTING pictures. DeuTex will + -gif recognize either one when STORING pictures in a pwad. The + -ppm DOS version defaults to .BMP; the UNIX version defaults to + .GIF. Avoid the 24bit BMP format! Use 8bit (256 color) and + have the color quantization done by a serious program. Mine + works if you need it, but it's lame. See "What are the + Palettes For?" in Chapter 1. + + -wave File format to use when EXTRACTING sounds (DeuTex will + -au recognize either one when INSERTING sounds). The DOS + -voc version defaults to .WAV; the UNIX version defaults to .AU. + + + + + + + + + + page 24 + + + + + -level These tell DeuTex to select Sprites, patches, sounds, etc. + -lump when composing/decomposing/merging pwads. These commands + -texture can be combined. By default, all entries are selected. + -sound + -graphic + -sprite + -patch + -flat + + -iwad To be used with -make, this command makes an iwad instead + of a pwad. This is necessary if you are building a pwad + which contains all the Sprites and/or all the Flats. This + enables you to rebuild the DOOM.wad if really needed. + + + -------------------------------------- +D) COMMANDS TO COMPOSE OR DECOMPOSE pwads + -------------------------------------- + + -wadir + + Directory list, with entry identification. Exact + entry identification is sometimes impossible in a + pwad. In that case, Sprites, Flats or patches might + be reported as Graphics. + + -xtract + -extract + + Will extract Lumps, Graphics, Flats, patches, Sprites, + sounds and Levels from a wad and put them into a + subdirectory having the same name (all .LMPs in \LUMPS, etc). + Also lists any Texture entries of the wad in a file called + TEXTURE1.TXT, which it puts in a subdirectory called + \TEXTURES. If you are extracting the main DOOM1 wad, a + second Texture file, TEXTURE2.TXT will be extracted. DOOM2 + does not have a TEXTURE2 entry. If a given subdirectory + does not exist, it will be created. Also creates the file + wadINFO.TXT in the working directory. The working directory + is the directory the command is entered from unless -dir is + used to specify one. See the Chapter 8 - FORMATS for a + description of wadINFO.TXT, TEXTURE1.TXT and TEXTURE2.TXT. + This command will not overwrite already existing entries. + It will complain and stop instead. + + + -get + + Will retrieve the entry called as picture, sound or + lump, from . if is unspecified + this default to the main wad. + This is no more than an emulation of DMGRAPH/DMAUD. + ++ -usedtex ++ ++ This command will scan the level files in the pwad, and report ++ all the texture names that are affectively used. ++ Use this when you convert pwads from Doom to Doom2 or Heretic ++ so as to know which texture you really need. + + + page 25 page 25 + + + + +-make +-build +-create + + Reads wadINFO.TXT and uses it to compose MYOWN.wad from the + files in the subdirectories. See FORMATS for a description + of wadINFO.TXT. MYOWN.wad will be created in the current + directory. If it already exists, it WON'T be overwritten, + so it must be deleted or moved to create a new version. This + command replaces DMGRAPH, DMMUS, DMTEX and DMAUD. (DMAUD + recognises more formats than .WAV and .AU, but it doesn't + work with Doom v1.666 or Doom2). + ++ -s_end ++ This switch is only related to an ugly trick with sprites. ++ This special switch shall be placed *before* -make when ++ you want to build a special sprite pwad. Such a pwad require ++ that you patch the game executable, so it's not for newbies. ++ Don't use that switch unless you really mean it. + + +-check + + Will look for any Textures defined in MYOWN.wad which contain + void columns that would crash Doom. Use this after modifying + Textures (Similar to the way you use checks in DEU). ++ It will also report the textures that cannot be used in a ++ Two sided wall (a medusa effect would happen if you used them). + +-unused + + Checks for unused bytes in a pwad. Reports all the unused + zones, total number of byte wasted, and the repartition + depending on size of wasted areas. + + + --------------------------------------------- +E) COMMANDS FOR MERGING pwads INTO THE MAIN iwad + --------------------------------------------- + +-merge + + Will put the entries of MYOWN.wad into the main Doom.wad + file, thereby removing all restrictions Doom puts on pwads. + This is much safer and much cleaner than inserting or + restoring entries with DMGRAPH or such, but your iwad IS + modified. Usually used for Sprites and Flats. + +-restore Will restore DOOM.wad and the merged MYOWN.wad. To be + used after the -merge command, to undo the job. Files are + reconstructed using information stored in the iwad at the + time the -merge is done. + +-join + ++ Will join two pwads: mysecond.wad is put inside myfirst.wad. ++ Great for combining pwads! ++ If entries are duplicated, mysecond.wad has priority ++ If custom textures are defined in both wads, they are ++ preserved, but those of mysecond.wad have priority. + + page 26 + +-app + ++ Appends all sprites and flats to a pwad. ++ this is necessary before a pwad defining custom sprites and ++ Flats is used with Doom. Doesn't work with Heretic 1.0, ++ but it should... another bug of Heretic... + ++ -as + ++ Same as -sprites -app. Appends only Sprites. ++ (-as does the same thing as the corresponding NWT command) + ++ -af + ++ Same as -flats -app. Appends only Flats. ++ (-af does the same thing as the corresponding NWT command) + + +-add + + Same thing as -app, but mysprite.wad is not modified. + final.wad is generated instead. Avoid this, it waste space. + (this is only for compatibility with the old DMADDS tool). + + +SAFEGUARD: + - ONLY 8 BYTES of DOOM.wad are modified + - If all else fails, you can restore your iwad by hand. + - Only about 32k of additional disk space are needed. + - MYOWN.wad is put INTACT into DOOM.wad. It can then be + deleted since -restore recreates it. This is barely a + modification at all! + +How does it work? + + - Restoration information is added at the end of the iwad. + - Then the pwad is pasted intact at the end of the iwad. + - The iwad directory is rebuilt (about 32K) and appended. + - The pointer to the Doom directory is modified (8 bytes). + +After all that mess, a directory entry called _DEUTEX_ is added. it is +of no use for Doom/Heretic, and is just ignored. But if you modify +your wad with some other tool, this entry will still point to the +restoration information, enabling DeuTex to salvage the wad. + +I did my best to make this command the safest possible. I have tested +this command thoroughly and believe it can be trusted. Be aware, +however, that the resulting iwad might not work with Doom if the +included pwad does not respect some conventions about Sprites and +Flats. If this happens, the files are still safe, just -restore them. + +The conventions a pwad must follow are: + + -There must be F_START or FF_START before the first Flat. + -There must be S_START or SS_START before the first Sprite. + +Sorry, but there is NO OTHER WAY if we want to be able to add new +Sprites and Flats that are unreferenced in DOOM.wad. +It would be vain to compare the sprites names with those of the iwad, +because it's DOOM.EXE that determines which sprites are which, not +the iwad. And as DOOM.EXE can be hacked, and sprites vary with versions +of Doom, there is really no other choice. + + + page 27 + + + + +CHAPTER 7 +*************************** DeuSF Commands **************************** + + -------- +A) OVERVIEW + -------- + +DeuSF is an improved replacement for DMADDS. It adapts to all versions +of Doom, requires a less perverted pwad structure, and can append to a +pwad rather than generating a new pwad (thereby saving space). DeuSF +works with pwads composed for DMADDS, and should work for ones composed +for DMADDF. Of course, the PREFERRED pwad composer for DeuSF is DeuTex! + ++ The code for DeuSF is 100% the same as that of DeuTex. ++ All the commands of DeuSF are the same as the DeuTex equivalent, but ++ since DeuSF is smaller, it's more suitable for distribution. + +DeuSF need only be applied to pwads that contain: + + -some Sprites to replace those of DOOM.wad. + -some Flats to replace those of DOOM.wad. + +DeuSF need NOT be used if: + + - the pwad contains *all* the Sprites of DOOM.wad + - the pwad contains *all* the Flats of DOOM.wad + - the pwad contains Sprites which are not referenced in + DOOM.EXE. (a DeHacked patch is needed to have them work) + +DeuSF can only be used on pwads that respect a precise format: + + - Sprites are identified only if comprised between: + + S_START or SS_START and S_END or SS_END + + -Flats (floor/ceilings) are identified only if they occur between: + + F_START or FF_START and F_END or FF_END + +If this format is NOT respected, DeuSF might fail to identify entries +correctly. This is because in iwad and pwad entries there is nothing +internal to a Sprite or Flat that identifies it as such. This format is +generated by DeuTex automatically, and is compatible with DMADDS. + +DeuSF is meant to be distributed with your pwad, so it has no +restrictions on distribution (Unlike DeuTex, see License Section). This +lets you send DeuSF with your pwad, along with a batch file like the +one in the following example. Your pwad contains new Sprites and Flats, +but not all of them. Your batch file might read: + + DeuSF -app mywad.wad + DOOM -file mywad.wad -warp x x + DeuSF -res mywad.wad + +First, DeuSF appends the Sprites and Flats from DOOM.wad to mywad.wad. +Then the pwad is played. The last command deletes the appended Sprites +and Flats from mywad.wad, restoring it to it's original condition. +This kind of pwad should PREFERABLY be built with DeuTex. + + + + page 28 + + + + +An example of DeuSF usage on ALIENDOOM 2.2: + + DeuSF -doom c:\doom -sprite -add ALIENGFX.wad ALINGRFX.wad + + DeuSF reads ALIENGFX.wad to find what Sprites are missing. It then + extracts them from DOOM.wad and creates a new pwad, ALINGRFX.wad from + the original pwad and the extracted Sprites. DOOM.wad and the original + ALIENGFX.wad are unchanged. + +Even better: + + DeuSF -doom c:\doom -sprite -app ALIENGFX.wad > aliengfx.log + + DeuSF reads ALIENGFX.wad to find what Sprites are missing. It then + extracts them from DOOM.wad and appends them to ALIENGFX.wad. DOOM.wad + is unchanged. If -res doesn't work for any reason, ALIENGFX.wad can be + restored by hand from the information in aliengfx.log + + You *should* take the time to evaluate this tool even if you're + not convinced at all. Trust that this time won't be wasted. + DeuSF -join, -merge, -app, -res commands are incredibly more + powerful than those of DMADDS. NWT duplicate some of the + features of DeuSF, but isn't par to DeuSF (as of NWT version 1.03). + Great care involved in designing those DeuSF functions, and DeuSF in not + only the most powerful, it's also the only one ported to other O/S. + Let me insist that you should use DeuSF to install your wads. + + + + -------------------------- +B) COMPLETE COMMAND REFERENCE + -------------------------- + + All optional commands must appear before all + non-optional ones. Otherwise, they are ignored. + +Command Line Format: +DeuSF ,...,,...,etc. + + +******** 1) HELP COMMANDS + + -help Lists these parameters. + + -format Displays a summary of the format conventions + a pwad must follow so that DeuSF can recognize + Sprites and Flats properly. + + -wadir + + Scrolls the entries in the pwad directory down the screen, + along with what type DeuSF thinks each entry is (Sprite, + Flat, Graphic, etc.). For a pwad with many entries, you + may want to pipe this command (i.e. DeuSF -wadir | more) + to ease readability. Used to check if DeuSF recognises all + the entries correctly, for instance when there is a problem + with -app or -add. + + + + + page 29 + + + + +******** 2) OPTIONAL COMMANDS + + + + -doom + + Use this command to indicate the directory containing the + DOOM.wad and DOOM.EXE you want to use. See the description + in the DeuTex command reference for default information. + + For example: DeuSF -doom C:\GAMES\DOOM + + -sprite Use with -add or -app, to add only Sprites or only Flats. If + -flat neither of these commands is present, DeuSF will add both. + + + + +******** 3) MANDATORY COMMANDS (one of these will always be used) + + + +-add (same as in DeuTex) + + Will create a new file, ALLSF.wad, containing all the + Sprites and/or Flats of DOOM.wad together with those + contained in MYOWN.wad. This is exactly like DMADDS + ...but cleaner. + +-app (same as in DeuTex) + + Will append to MYOWN.wad only those Sprites and/or Flats + of DOOM which are not redefined. This saves disk space, + compared to -add command. + +-join + + Will append to THIS.wad all the Sprites and Flats contained in + THAT.wad. This function enables you to merge two Sprite and/or + Flats pwads obtained from different sources. I added this + command so that I could play CHOOK and BARNEY together. + TEXTURES and PNAMES entries of both THIS.wad and THAT.wad. + If entries are conflicting, those of THAT.wad have priority. + Avoid conflicts! -join is not really clever. + + NOTE: After using -join on pwads, you still have to + use -app on the combined pwad to append the + remaining Sprites and Flats from Doom. + +-res (same as in DeuTex) + + Restores a pwad which had been modified with -app command. + Quite safe. Performs the same function as -restore in DeuTex. + If a pwad was merged inside another one (using -join), then + that pwad regenerated also. Now *that's* real cool! + + + + + + + page 30 + + + + +CHAPTER 8 + +******************************* FORMATS ******************************* + + ---------------------------- +A) The wad Creation Directive + wadINFO.TXT + ---------------------------- + +******** 1) OVERVIEW + +The creation directive file is used by the DeuTex -make command to +compile a pwad containing all of the desired enhancements. It is +automatically generated by the -xtract command and placed in the +working directory (e.g. MYwad\). You can rename this file whatever you +like, and reference it when you use the -make or -merge commands. + ++ The file lists most of the entries which will be present in the pwad ++ file (with the exception of PATCHES and PNAMES, see note below). It is ++ structured similarly to a Windows .ini file with sections headed by ++ names enclosed in brackets.It contains up to 7 sections: [LEVELS], ++ [LUMPS], [TEXTURE1], [SOUNDS], [GRAPHICS], [SPRITES] and [FLATS]. ++ For DOOM1, there can be an eighth section called [TEXTURE2]. ++ ++ All sections are optional. Starting with DeuTex version 3.0, the order ++ of the sections is not critical. The name of the section IS critical, ++ and must be spelled correctly. + +NOTE: There is no [PATCHES] section. Patch loading is automatic. If a + new patch is referenced in a Texture, DeuTex will look for it in + \PATCHES. If there is a patch in \PATCHES with the same name + as an existing patch, DeuTex will automatically find it and load + it. There is no need to reference a redefined patch in a Texture + definition, unless it is part of a new or redefined Texture. There + is also no need to define PNAMES. PNAMES creation is automatic. + + The names TEXTURE1 and TEXTURE2 refer to the OLDTEX1.TXT and + OLDTEX2.TXT files as extracted from Doom. Unlike previous versions, + DeuTex doesn't need these files. They exist only for you. They are + useful in examining the makeup of textures in the wad. They also make + redefining existing Textures easier by allowing you to cut and paste + instead of typing the redefined Texture from scratch. DeuTex 3.3 takes + all the information on existing Textures directly from the main wad + while building your pwad. Any new definitions supplied by you will + override those in Doom. A warning will be given to inform you of this. + This is a great improvement and makes DeuTex even easier than before! + + Previous versions of this manual also generated confusion over where, + how, and if you need to use OLDTEX2.TXT (then named TEXTURE2.TXT) + The short answer from now on is: NOWHERE, NOHOW and NO! + + Since DeuTex 3.1, [TEXTURE1] and [TEXTURE2] are separate sections. + There is ONLY ONE case where you will use [TEXTURE2]. This is when you + are using Doom1 and you redefine a TEXTURE2 Texture. OLDTEX2.TXT does + NOT need to be present, even in this situation. Use it for your edits. + + If your pwad is for Doom2, or is for Doom1 and doesn't change any + TEXTURE2 Textures, IGNORE all references to TEXTURE2 in this document! + + + + page 31 + + + + +******** 2) EXACT FORMAT for wadINFO.TXT + + + + The following pages show the exact format for all the entries in a + pwad Creation Directive File (i.e. wadINFO.TXT or YOURNAME.TXT). + All main sections are optional. Order of sections is unimportant. + + + The Symbols used in the Format Listing are as follows: + + + SYMBOL DEFINITION +_______________________________________________________________________ +| | | +| x and y | Numbers for offsets, levels, etc. | +|________________________|____________________________________________| +| | | +| aaaa, bbbb and cccc | YOUR name for a given item (8 char max). | +|________________________|____________________________________________| +| | | +| qqqq, rrrr and ssss | VARIABLE parts of a Doom name. | +|________________________|____________________________________________| +| | | +| CAPITAL LETTERS | MANDATORY parts of an entry. | +|________________________|____________________________________________| +| | | +| Doom name '=' aaaa | DeuTex will insert 'aaaa' as 'Doom name'. | +|________________________|____________________________________________| +| | | +| brackets [ ] | Define main sections in the file. | +|________________________|____________________________________________| +| | | +| parentheses ( ) | These entries are optional. | +|________________________|____________________________________________| +| | | +| asterisk '*' | Reuse the resource from the previous line. | +|________________________|____________________________________________| +| | | +| dot+comma ';' | 'Comment' follows. (Windoze standard) | +| pound sign '#' | 'Comment' follows. Rest of line ignored. | +|________________________|____________________________________________| +| | | +| 'white space' (spaces) | Ignored by DeuTex. | +|________________________|____________________________________________| + + + + + + + + + + + + + + + + + page 32 + + + + + Listing of the Format for wadINFO.TXT: + + ; + ; DeuTex by Olivier Montanuy + ; + ; pwad creation directives + ; + ; + [LEVELS] ; Section to define the Level of your map(s). + ; + MAPnm (=aaaa) ; If '=aaaa' and '=bbbb' are used, looks in \LEVELS for + EnMm (=bbbb) ; aaaa.wad and bbbb.wad. If '=aaaa' and '=bbbb' are not + ; used, looks in \LEVELS for MAPnm.wad and EnMm.wad. + ; Combines them into one pwad containing MAPnm and EnMm + ; + ; DeuTex does not care about the internal Level of + ; aaaa.wad or MAPnm.wad. It will output the pwad as + ; whatever MAPnm or EnMm is put here. Easy conversion. + ; + ; EnMm can be E1M1 thru E3M9. + ; MAPnm can be MAP01 thru MAP35. + ; MAPS 33, 34 and 35 will play, but can only be entered + ; by IDCLEV. An EXIT LEVEL switch on 33, 34 and 35 will + ; just return you to DOS. + ; + ; If EnMm and MAPnm are entered in the same pwad, EnMm + ; will play from Doom1 and MAPnm will play from Doom2, + ; IF there are no Texture additions to the pwad. It is + ; still possible with Textures, but is a can of worms, + ; and you'd better know what you're doing. + ; + ; Thus, it is possible to make a 62 Level pwad with + ; DeuTex, although some imagination would be needed to + ; overcome the limitations of Levels 33, 34 and 35 in + ; Doom2, and only about half the wad would be available + ; to each Doom engine. This may be useless, but since + ; it's possible, it is included here. + ; + ; + [LUMPS] ; Section to define any .LMP data you want to add. + ; Chapter 5, Section B) describes Lumps. + ; + qqqq (=aaaa) ; If '= aaaa' is used, looks in \LUMPS for aaaa.LMP. If + ; '= aaaa' is not used, looks for qqqq.LMP. Installs the + ; .LMP data in the pwad to replace qqqq in Doom. + ; + rrrr (*) ; If '*' is used, .LMP from the previous entry is used + ; for this entry as well. When you play the pwad, qqqq + ; will be used for both qqqq AND rrrr. + ; + ; + + + + + + + + + + + page 33 + + + + + [TEXTURE1] ; Section for declaring what Texture definition files you + ; want to use when compiling your pwad. + ; + aaaa ; First loads TEXTURE1 from the main Doom or Doom2 wad. + (bbbb) ; Then looks in \TEXTURES for aaaa.TXT. Compiles your pwad + (cccc) ; Texture directory by: TEXTURE1 - (redefined Textures in + ; aaaa.TXT)+(ALL textures in aaaa.TXT) = TEXTURE1 in pwad. + ; + ; If 'bbbb' and 'cccc' are used, DeuTex searches for + ; bbbb.TXT in \TEXTURES, RE-edits the TEXTURE1 entry using + ; it, then gets cccc.TXT and repeats the process. This + ; means that if any duplicate Texture names exist in aaaa, + ; bbbb and cccc, only the entry from the last file listed + ; will be present in the final pwad. + ; + [TEXTURE2] ; Used only for Doom1. Shows what Texture definition + aaaa ; file(s) to use for TEXTURE2. Similar to above. + ; + ; + [SOUNDS] ; Section to define your modified sound entries. + ; + DSqqqq (=aaaa) ; If '=aaaa' is used, looks in \SOUNDS for aaaa.WAV + ; (sound effect). If '= aaaa' isn't used, looks for + ; DSqqqq.WAV. Uses file to replace Doom sound DSqqqq. + ; + DPqqqq (=aaaa) ; If '=aaaa' is used, looks in \SOUNDS for aaaa.TXT + ; (PC Speaker sound). If '= aaaa' is not used, looks + ; in \SOUNDS for DPqqqq.TXT. Uses file to replace + ; Doom PC Speaker sound DPqqqq. + ; + D_qqqq (=aaaa) ; If '=aaaa' is used, looks in \SOUNDS for aaaa.MUS + ; (Music file in Doom's .MUS format). If '=aaaa' is + ; not used, looks for D_qqqq.MUS. Uses file to replace + ; Doom Music D_qqqq. + ; + D_rrrr (*) ; If '*' is used, the sound from the previous entry is + ; used for this entry as well. In this example, when + ; you play your pwad, D_qqqq will be used for both + ; D_qqqq AND D_rrrr. + ; + ; + [GRAPHICS] ; Section used to declare Graphics other than + ; Sprites, Flats, or Textures. See Chapter 5, + ; Section E) or Matt Fell's Doom specs for a + ; description of Graphic entries in Doom. + ; + qqqq (xx)(yy) (=aaaa) ; If '=aaaa' is used, looks in \GRAPHICS for + ; aaaa.BMP. If not found, looks for aaaa.GIF. + ; If '=aaaa' is not used, looks for qqqq.BMP + ; or .GIF. Inserts the file in pwad for entry + ; qqqq. xx and yy are the horizontal and + ; vertical offsets used when inserting the + ; Graphic into it's defined area. The defined + ; defined area is predetermined by DOOM.EXE + ; from the Graphic name. + ; + + + + + + page 34 + + + + + ; For example, all Graphics beginning with STF + ; are placed in a box 31 x35 pixels big at the + ; center of the Status Bar. This is where the + ; player's face shows up. The xx and yy values + ; move the Graphic around in this box. Positive + ; values move it left (xx) and up (yy). + ; + rrrr (*) ; If '*' is used, will re-use the Graphic from + ; the previous line for rrrr too. + ; + ; + [SPRITES] ; Section used to declare Sprites. Consult the + ; following for more information on modifying + ; Sprites in Doom: + ; Chapter 3 - Section C) + ; Chapter 5 - Section F) + ; Chapter 6 - Section E) + ; Chapter 7 - All Sections + ; + qqqq (xx)(yy) (=aaaa) ; If '=aaaa' is used, looks for aaaa.BMP or + ; .GIF in \SPRITES. If '=aaaa' is not used, + ; looks for qqqq.BMP or GIF. Inserts the file + ; into the pwad to replace the Sprite qqqq. + ; + rrrr (*) ; '*' tells DeuTex to use the previous entry + ; (qqqq) for this Sprite as well. + ; + ; + [FLATS] ; Section for declaring modified Flats. Limitations + ; are similar to the ones for modifying Sprites. See + ; [SPRITES] section above for places to find info. + ; + qqqq (=aaaa) ; If '=aaaa' is used, looks for aaaa.BMP or .GIF in + ; \FLATS. If '=aaaa' is not used, looks for qqqq.BMP or + ; .GIF. Inserts file into pwad as replacement for qqqq. + ; + ; There are no insertion points for Flats, since they + ; all MUST be 64x64. + ; + ; + ; End File. + + + + + + + + + + + + + + + + + + + + + page 35 + + + + +******** 3) An EXAMPLE LISTING of wadINFO.TXT + +The following is a commented example of pwad creation directives, +A space or any text after a ';' or '#' to the end of a line is ignored. +Not all entries need be present, and order of [SECTIONS] is optional. + +************************ wadINFO.TXT ***************************** +; +; The [LEVELS] section defines the Doom1 Levels and Doom2 maps. +; +[LEVELS] +E1M2 ;file loaded: LEVELS\E1M2.wad +MAP04 ;file loaded: LEVELS\MAP04.wad +E2M3 =TRINITY ;file loaded: LEVELS\TRINITY.wad + ;if more than one Level, E2M3 is read +; +; All .wads referred to here must contain the 11 entries that +; define a Level, including NODES, BLOCKMAP and REJECT. Use +; IDBSP and RMB to build them. +; +; The [LUMPS] section defines the Lumps of raw data for Doom. +; +[LUMPS] +ENDOOM ;file loaded: LUMPS\ENDOOM.LMP +DEMO1 ;file loaded: LUMPS\DEMO1.LMP +DEMO2 =KILLJOHN ;file loaded: LUMPS\KILLJOHN.LMP +; +; See Directory Structure - LUMPS\ for a precise description of all +; these entries. Apart from the DEMO or possibly ENDOOM, there is no +; real need to mess with them. DEMOs can be recorded by DOOM. +; +; The [TEXTURE1] section lists the names of the Texture definition files +; from \TEXTURES that are to be used for TEXTURE1. +; +[TEXTURE1] ;DeuTex will first read TEXTURE1 in DOOM.wad +; +TEXTURE1 ;file read: \TEXTURES\TEXTURE1.TXT +MYWALLS ;file read: \TEXTURES\MYWALLS.TXT +MYSWITCH ;file read: \TEXTURES\MYSWITCH.TXT +; +; The new Textures found in these files are placed at the end of the +; Texture list. If they have the same name as an entry in OLDTEX1, +; (that is: the old Doom texture) then that entry is deleted. +; +; The [TEXTURE2] entry is not needed for Doom2 +; +[TEXTURE2] ;DeuTex will first read TEXTURE2 in DOOM.wad. +; +TEXTURE2 ;file read: \TEXTURES\TEXTURE2.TXT +; +; The new Textures found in this file are placed at the end of the +; Texture list. If they have the same name as an entry in TEXTURE2, +; that entry is deleted. +; +; BEWARE: don't duplicate TEXTURE1 entries in TEXTURE2. +; Doom Doesn't care, but it crashes some Level +; editors. +; + + + + page 36 + + + + +; The [MUSICS] section defines MUSIC +; +D_E2M3 ;file loaded: SOUNDS\D_E2M3.MUS (doom1 music). +D_RUNNIN ;file loaded: SOUNDS\D_RUNNIN.MUS (doom2 music). +D_ROMERO * ;no file loaded! The '*' copies D_RUNNIN to D_ROMERO. + ;now Doom will think D_ROMERO=D_RUNNIN. +D_SHAWN3 =KATEBUSH ;file loaded: SOUNDS\KATEBUSH.MUS. + ;The music for SHAWN3 will be KATEBUSH. +; +; D_E2M3 is the music for Episode2 Mission 3 of Doom. +; In Doom2, it's a real mess. The Music name is not related +; to the Level name, but to the guy who made the Level. +; MUS format can be obtained from MIDI with MIDI2MUS, or +; converted back to MIDI by MUS2MIDI (by just_joe). +; These are separate utilities (too technical for DeuTex) +; +; The [SOUNDS] section defines PCSOUNDS and WAVE SOUNDS +; +[SOUNDS] +DSSLOP ;file loaded: SOUNDS\DSSLOP.WAV, .AU or .VOC +DSPISTOL =BOIING ;file loaded: SOUNDS\BOIING.WAV, .AU or .VOC + ;this is a WAV sound, meant for sound cards. +; +DPSLOP ;file loaded: SOUNDS\DPSLOP.TXT + ;this is a PC speaker sound. +; +; The WAV, AU and VOC format were hacked. +; DeuTex can't read compressed data. +; The format PC-speaker sound is a list of integers +; (range 1-255). related to sound pitch... +; +; +; The [GRAPHICS] section defines all the fixed pictures. +; (Not Sprites, patches, or Flats) +; +[GRAPHICS] +WIMAP1 ;file loaded: GRAPHICS\WIMAP1.BMP. +STHURT1 23 45 ;file loaded: GRAPHICS\STHURT1.BMP. + ;set the insertion point to 23,45. +STHURT2 * ;Doom will use STHURT1 for STHURT2. +VICTORY2 0 12 =SULACCO ;file loaded: GRAPHICS\SULACCO.BMP + ;set the insertion point to 0,12. + ;SULACCO.BMP will now replace VICTORY2. +; +; Fixed pictures include: opening screen, +; texts (!), menus, status bar, ending pictures ... +; You can only use names already defined in Doom. +; Otherwise Doom will ignore them. (you'll be warned :-) +; +; This section declares the Sprites. +; +[SPRITES] +BOSSB1 ;File loaded: SPRITES\BOSSB1.BMP or .GIF + ;calculate insertion point by itself. +BOSSA1 10 20 ;File loaded: SPRITES\BOSSA1.BMP or .GIF + ;set the insertion point to 10,20. +BOSSA2A8 * ;DeuTex will set BOSSA2A8 equal to BOSSA1 +VILEA1 30 40 =BILLGATE ;File loaded: SPRITES\BILLGATE.BMP or .GIF + ;VILEA1 will now be BILLGATE.BMP + + + page 37 + + + + +; If you redefine ALL sprites, use the -iwad option. +; Otherwise, you'll have to use DeuSF to rebuild a complete Sprite pwad +; each time the wad is played. This is because of a limitation of Doom +; which still has not been removed (ask Id software about it). +; +; +; Don't declare your patches. +; A patch, say xxxx, will automatically be loaded into +; the pwad from the file PATCHES\xxxx.BMP (or .GIF) if: +; +; 'xxxx' is referenced in one of the Texture files, as a patch. +; or 'xxxx' exists as a patch in the original Doom. +; +; +; +; The [FLATS] section declares the Floors and Ceilings +; +[FLATS] +GRASS ;file loaded: FLATS\GRASS.BMP (or .GIF) +HERBE * ;Doom will think HERBE is the same as GRASS +BLOOD1 = MUDDY ;file loaded: FLATS\MUDDY.BMP + ; All these files must be 64x64 pixel pictures. +; +; You can define new Flat names, or redefine existing Flats, but unless +; you redefine the complete list of Flats, and use the -iwad option, you +; need to use DeuSF to rebuild the complete Flat list whenever you want +; to use the pwad. +; +; +; wad creation directives end here. +; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page 38 + + + + + ----------------------------------- +B. The Texture Definitions Text File + \TEXTURES\MYTEXT.TXT + ----------------------------------- + +******** 1) OVERVIEW + +Some Notes on Texture definitions: + + - READ the DOOM SPECS by Matt Fell. + - You can create Textures for transparent walls (see DeuTex + Commands -rgb), but make sure that they're composed of only + one patch. Otherwise, you'll get the Medusa Effect. + - Avoid using a Texture less than 128 pixels high on a + wall higher than the Texture (Tutti Frutti effect). + - Texture widths should be rounded to the next power + of 2. (8,16,64,128,256,512,1024 are usable) + - Patches composing Textures can not be more than 320 pixels wide. + - Doom will ignore any portion of Textures higher than 128 pixels. + - You can create a non repeating sky Texture: + Define the SKY1 (or SKY2, SKY3, RSKY1, RSKY2, RSKY3) entry as a + 1024x128 area cover it with patches. Note that SKY patches appear + horizontally inverted. 0=east, 256=north, 512=west, 768=south. + - Make sure all Textures are completely covered by patches. + Otherwise, Doom will puke (void column error). + - You can create animated walls with (almost) any sequence of + pictures. No known limit in the number of frames (27 is OK!). + The way to do this is: + Edit the Textures of one of Doom's existing animated walls + (beginning and end). Use the original names for these entries. + They are coded into DOOM.EXE. Add the other frames for your + animation between these entries in your Texture list. + - READ the DOOM SPE.... Well, you get the picture >;-{]> + +Once you have created a new pwad, check it with the -check command. +DeuTex will complain if: + + - Any Texture width is NOT a power of 2 (2,4,8,16,32,64,128,etc). + (Doom will round to the next lower power of 2) + - Any Texture height is greater than 128. + (Doom ignores everything above 128) + - Any Texture is not completely covered by patches. + (Doom will exit with a void column error) + - A Level tries to use of an undefined Texture. + +A Texture entry consists of: + +(Texture Name) (WIDTH) (HEIGHT) +* (Patch1) (X offset)(Y offset) +* (Patch2) (X offset)(Y offset) +* (Patch3) (X offset)(Y offset) + . . . . + . . . . + . . . . +* (PatchN) (X offset)(Y offset) + +This format is supported by both New Wad Tool and the Visual Basic +shell for DeuTex, so use the one you prefer, to build your Textures. + + + + page 39 + + + + +Texture names are 8 characters or less. +Width and Height are in pixels. +An asterisk '*' identifies the following word as a PNAME. +Patch names are 8 characters or less. +X and Y offsets are pixel measurements. +Offsets are measured from upper-left corner (0,0). +X = positive. Offset patch to the right. +X = negative. Offset patch to the left. +Y = positive. Offset patch down. +Y = negative. Offset patch up. + + + + + + +The following figure is a feeble attempt to illustrate this: + + + + + + _______________________ +| | ^ +| PATCH 1 | | +| Both x and y | Y +| have negative | | +| offsets. _______|_v_______________________________________ +| | | ^ | ^ +| | | | TEXTURE | | +| | | | | | +| | | Y | | +| | | | | | +|_______________|_______| | | H + | __v_______________________ | E + <----- X ----->| | | | I + | | PATCH 2: | | G + | | Both x and y have | | H + |<------- X ------->| positive offsets. | | T + | | | | | + | | | | | + | | | | | + | |__________________________| | | + | | | + |_________________________________________________| v + + <-------------------- WIDTH ---------------------> + + + + TEXTURE DEFINITION SHOWING PATCH OFFSETS + + + + + + + + + + + page 40 + + + + +******** 2) An EXAMPLE LISTING of MYTEXT.TXT + + Texture Definition File Example + +*************************** TEXTURE1.TXT ****************************** +; +; Anything following a ';' or ';' is ignored (comment). +; +; An asterisk '*' at the beginning of a line indicates a patch. +; +; ASHWALL is a Texture 64 pixels wide, and 128 pixels high. +; It contains only one patch, W104_1, with no offset. +; +ASHWALL 64 128 +* W104_1 0 0 +; +; BIGDOOR7 is a Texture of size 256x128 (X size, Y size) composed of two +; patches, W105_1 and W105_1 placed at offset -4,-4 and offset 124, -4. +; +BIGDOOR7 256 128 +* W105_1 -4 -4 +* W105_1 124 -4 +; +; FLOWER is a new Texture (didn't exist in DOOM.wad). +; It is composed of an old patch. +; +FLOWER 32 128 +* TP5_1 0 0 +; +; BLODGR2 redefines the old BLODGR2 Texture +; to be composed of the new patch BIRDY +; +BLODGR2 34 128 +* BIRDY 0 0 +; +; A new Texture, HADDOCK, composed of new and old patches. +; +HADDOCK 64 128 +* FISH1 0 0 +* BIGFISH 23 44 +* TP5_1 0 0 +; +; Example of wall animation. +; +; Start with the first entry of an existing animation (FIREBLU1). +; Insert additional entries as needed for your animation (ZZZ...). +; End with the closing entry of the existing animation (FIREBLU2). +; When FIREBLU1 is used in your pwad, it will have your animation! +; Notice that the example uses sprites as patches. Doom don't know +; and Doom don't care! +; +FIREBLU1 128 128 ;First frame is a redefined +* WALL62_1 0 0 ;Doom animated Texture. These +* BOSSA1 83 47 ;are called in the DOOM.EXE. +* GOR2A0 20 -70 +ZZZA 128 128 ;Frame 2 inserted. +* WALL62_1 0 0 +* BOSSB1 75 47 +* GOR2A0 20 -50 + + + page 41 + + + + +ZZZB 128 128 ;Frame 3 inserted. +* WALL62_1 0 0 +* BOSSC1 71 47 +* GOR2A0 20 -35 +ZZZC 128 128 ;Frame 4 inserted. +* WALL62_1 0 0 +* BOSSD1 61 47 +* GOR2A0 20 -25 +ZZZD 128 128 ;Frame 5 inserted. +* WALL62_1 0 0 +* BOSSF1 47 47 +* GOR2A0 20 -20 +ZZZE 128 128 ;Frame 6 inserted. +* WALL62_1 0 0 +* BOSSE8 54 47 +* GOR2A0 20 -17 +ZZZF 128 128 ;Frame 7 inserted. +* WALL62_1 0 0 +* BOSSE7 68 47 +* GOR2A0 20 -16 +ZZZG 128 128 ;Frame 8 inserted. +* WALL62_1 0 0 +* BOSSE6 64 47 +* GOR2A0 20 -17 +ZZZH 128 128 ;Frame 9 inserted. +* WALL62_1 0 0 +* BOSSF5 60 47 +* GOR2A0 20 -20 +ZZZI 128 128 ;Frame 10 inserted. +* WALL62_1 0 0 +* BOSSF4 63 47 +* GOR2A0 20 -25 +ZZZJ 128 128 ;Frame 11 inserted. +* WALL62_1 0 0 +* BOSSD2D8 64 47 +* GOR2A0 20 35 +ZZZK 128 128 ;Frame 12 inserted. +* WALL62_1 0 0 +* BOSSB1 68 47 +* GOR2A0 20 -50 +ZZZL 128 128 ;Frame 13 inserted. +* WALL62_1 0 0 +* BOSSC1 70 47 +* GOR2A0 20 -70 +FIREBLU2 128 128 ;Fourteenth Frame is an +* WALL62_1 0 0 ;edited FIREBLU2, which is +* BOSSB1 73 47 ;the last frame of the +* GOR2A0 20 -64 ;Doom animated Texture. +; +; End of example +; +; +; file ends here. bye! + + + + + + + + + page 42 + + + + + --------------------------- + *** [PART THREE] ALL THE REST *** + --------------------------- + + +CHAPTER 9 +*************************** NECESSARY STUFF *************************** + + + + ------------------------------ +A) DeuTex/DeuSF License Agreement + ------------------------------ + + +See LICENSE. + + page 43 + + + + + ----------- +B) Legal Stuff + ----------- + + +See LICENSE. + + page 44 + + + + + ------------------------- +C) Where to get DeuTex/DeuSF + ------------------------- + + + The primary site for DeuTex is + http://www.teaser.fr/~amajorel/deutex/ + + DeuTex and DeuSF are meant to be available by anonymous + FTP on Internet sites: the same as of those of DEU: + + ftp.cdrom.com,ftp.luth.se,iglou.com,... + /pub/doom/utils/graphics_editing/deutex + + + + + DeuTex and DeuSF are available on Compuserve, by special + request of Dr. Sleep: + + GAMERS FORUM LIB 8 ACTION GAME AIDS [CIS:GAMERS] + PC WORLD FORUM LIB 22 The DOOM ROOM [CIS:PWOFORUM] + + +You might also want to try: + +WinTex +The graphic interface for DeuTex + +NWT by Denis Moeller +A very good DOS Tool, easy to use. ideal for making small changes +to a wad. unsuitable for handling large set of entries. +Texture text format is compatible with DeuTex. + + +DOOMTEX by Steve McCrea +A list of tools to generate Textures. It's not exactly user friendly, +but successfully used for TRINITY.wad. For hackers only :-) I *do* hope +you'll find DeuTex a bit easier to use, but Steve was a pioneer in +the area of Texture editing! + +WACKER by Keith Wilkins +A Graphic Texture editor. I could not test it, but it should be good. +It would be a good idea to use it in combination with DeuTex. + + + + + + + + + + page 45 + + + + -------------- +D) Known Problems + -------------- + +- Color quantization is faster, but optimised for the Doom and Heretic + palettes supplied with DeuTex. Else, it's slower and a bit lossy. + +- Identification of entry types does not always work with pwads made by + programs other than DeuTex. There is no general solution to this + problem, only my best effort. Sprites and Flats could be missed if + certain conventions are not respected. Misidentified entries are + stored as Lumps. + +- GIF format defaults to GIF87. + +- No MIDI support. MUS format is too complex to understand. No time. + +- DeuSF does NOT test that all REQUIRED sprite viewpoints are available + if you change the number of viewpoints. Doom will lock up if you + forget one of the sprite viewpoints. + +- If the -app command is interrupted, the pwad file becomes bigger due + to appended waste data, but it is still operational. + +- DeuSF says stupid things if no command is given. + +- See TODO. + +*Limitations of Doom + +- Sprites in pwads only work if you don't reuse existing sprites. Use + DeuSF or DMADDS if you want to replace sprites. Actually, DeuTex + -merge will also work. (and better!) + +- Flats don't work in pwads. Use DeuSF or DMADDS if you want to + replace Flats. Deutex -merge will also work. (and better!) + +*Limitations of Heretic + +- Sprites in pwad don't work at all. use -merge. I don't know why... + + + + + + + + + + + + + + + + + + page 46 + + + + + ------ +E) THANKS + ------ + + +First, thanks to you for taking the time to evaluate DeuTex/DeuSF. +I know my program is not trivial to use, and might be tricky to +understand, but I really think it's worth the trouble. + + +DeuTex/DeuSF would not have existed without the help of these people: + + + Steve McCrea Author of TRINITY.wad and DOOMTEX. + + Raphael Quinet Examples of GIF and DEU code. + (quinet@montefiore.ulg.ac.be) + + Denis Moeller Author of NWT. Securisation and + (denis@doomsday.sh.de) compatibility of DeuTex and NWT. + + Elias Papavassilopoulos Doom technical information. + (ep104@cus.cam.ac.uk) + + Matt Fell Doom specs version 1.666 + (matt.burnet@acebbs.com) + + Keith Wilkins Author of Wacker, first Texture + (spike@nectech.demon.co.uk) composer. Try it! + + Tom Neff Doom technical information. + (tneff) + + Bernd Kreimeier Author of DMADDS/DMADDF + (bernd@nero.uni-bonn.de) + + Dewi Morgan Unashamed flattery that lead me to + (D.Morgan@bradford.ac.uk) create DeuSF from DeuTex code. + + Id software For the DEUTEX/DeuSF test bench, also + (help@idsoftware.com) known as 'Doom', 'Doom2' or 'Heretic' + + Raven software For those cool graphics in Heretic. + (and for messing with color palettes) + +Special Thanx to: + + + Mark Mathews DeuTex OS/2, DJGPP port. + (mark.mathews@channel1.com) Improvements and suggestions. + + Per Allansson DeuTex Linux version. + (c91peral@und.ida.liu.se) + + James Bonfield DeuTex DEC ALPHA port + + Chuck Rossi DeuTex SGIx port + + Sharon Bowles Detection of possible medusa effect + + Udo Munk DJGPP and Cygwin port + + page 47 + + + + + + -------------- + THANKS (cont.) + -------------- + + + +Thanks to all of you who reported bugs and proposed corrections +or generally supported my efforts: + + + Leonard Czajka leonardc@halcyon.halcyon.com + Herve.Benvel Herve.Benvel@inria.fr + Paolo Hutchison paolo@netcom.com + M. Kernaghan mkernagh@julian.uwo.ca + Thierry Vermat vermat@evol10.univ-lyon1.fr + Jeremy Blackman ranma@eskimo.com + Jason Mezzacca 72510.3424@compuserve.com + C. Gasparo cgasparo@cymbal.aix.calpoly.edu + Avery Andrews andaling@durras.anu.edu.au + (I'm maybe forgetting you!) + + + Thanks to Justin Fisher for letting me use DeuTex and DeuSF on a + new install for Alien-TC (despite all the small mistakes I made). + + Now comes the guy YOU all want to thank: + + HevKev, also known as Kevin McGrail, novice Manual Editor. + 74107.1254@compuserve.com + + + Before his contribution, I was the only one who knew how to use DeuTex. + Now some of you might understand enough about DeuTex to use it in your + great Doom conversions project. + + + + + + + + + + + + + + + + + + + + + + + + + + + page 48 + + + + + ----------- +F) FINAL WORDS + (AT LAST) + ----------- + + +Thanx for trying DeuTex. + + + I did my best to make it the easy to use, bug free, and portable. + However, it's not entirely trivial to use. + I can't spend my life on a freeware tool. + + + If you can't understand this tool, chances are your contribution + to Doom fandom will be quite limited. Remember, I only worked to make + your life as simple as it could be, so that even non-specialists + could produce something cool for Doom. + + + But don't forget that it takes some time, some dedication, and + some genius also, to make something as great as Aliens-TC. + + + + + Olivier Montanuy, + +E-Mail: + Olivier.Montanuy@wanadoo.fr +Address: + Manoir de Keringant, St Quay Perros, 22700 Perros Guirec, FRANCE + This is in Bretagne (Brittany), the westernmost part of France. +Phone: + +33 96482047 (time: UTC+1. Note this, Californian users!) + modem: USR 14400 Worldport LITE Modem Fax.(this is not a BBS) + + + + + + + + + + + + + + + + + + + + + + + + page 49 + + + + +APPENDIX I Switch Textures in DOOM.wad + + +SW1BRCOM 128 128 +* WALL62_1 0 0 +* SW1S0 48 72 +SW1BRN1 64 128 +* WALL02_2 0 56 +* WALL02_2 0 0 +* SW3S0 16 75 +SW1BRN2 64 128 +* WALL02_2 0 56 +* WALL02_2 0 0 +* SW4S0 20 79 +SW1BRNGN 64 128 +* WALL62_2 0 0 +* SW4S0 20 80 +SW1BROWN 128 128 +* WALL62_1 0 0 +* SW3S1 48 72 +SW1COMM 64 72 +* W13_1 0 0 +* SW1S0 15 18 +SW1COMP 64 128 +* COMP03_4 0 64 +* COMP04_5 0 0 +* COMP03_4 32 64 +* SW2S0 16 72 +SW1DIRT 64 128 +* WALL00_7 32 0 +* WALL00_6 16 0 +* SW1S0 16 20 +* WALL00_6 0 -16 +* WALL00_7 48 0 +SW1EXIT 32 72 +* W32_4 0 0 +* SW2S0 0 16 +* W33_8 0 64 +SW1GRAY 64 128 +* W31_1 0 0 +* W31_1 0 64 +* SW2S0 16 70 +SW1GRAY1 64 128 +* W31_1 0 64 +* W31_1 0 0 +* SW4S0 19 79 +SW1METAL 64 128 +* WALL03_7 0 0 +* WALL03_7 0 64 +* SW4S0 20 68 +SW1PIPE 128 128 +* TP2_2 0 0 +* SW3S0 48 76 + + + + + + + + + page 50 + + + + +SW1SLAD 64 128 +* WLA128_1 0 0 +* WARNB0 24 73 +SW1STARG 128 128 +* SW19_3 64 0 +* SW19_4 0 0 +* SW3S0 48 76 +SW1STON1 64 128 +* W28_8 0 64 +* W28_8 0 0 +* SW1S0 16 78 +SW1STON2 64 128 +* W28_5 0 0 +* W28_8 0 64 +* WARNB0 24 73 +SW1STONE 64 128 +* WALL01_1 0 0 +* WALL01_2 16 0 +* WALL01_3 32 0 +* WALL01_4 48 0 +* WALL01_1 0 72 +* WALL01_2 16 72 +* WALL01_3 32 72 +* WALL01_4 48 72 +* W33_8 0 64 +* W33_8 0 120 +* SW1S0 16 72 +SW1STRTN 64 128 +* SW12_4 0 0 +* SW12_5 32 0 +* SW1S0 16 72 +SW2BRCOM 128 128 +* WALL62_1 0 0 +* SW1S1 48 72 +SW2BRN1 64 128 +* STEP07 32 72 +* STEP07 0 72 +* WALL02_2 0 56 +* WALL02_2 0 0 +* SW3S1 16 75 +SW2BRN2 64 128 +* WALL02_2 0 56 +* WALL02_2 0 0 +* SW4S1 20 79 +SW2BRNGN 64 128 +* WALL62_2 0 0 +* SW4S1 20 80 +SW2BROWN 128 128 +* WALL62_1 0 0 +* SW3S0 48 72 +SW2COMM 64 72 +* W13_1 0 0 +* SW1S1 15 18 + + + + + + + + + page 51 + + + + +SW2COMP 64 128 +* COMP03_4 0 64 +* COMP04_5 0 0 +* COMP03_4 32 64 +* SW2S1 16 72 +SW2DIRT 64 128 +* WALL00_8 48 0 +* WALL00_7 32 0 +* WALL00_6 16 0 +* WALL00_5 0 -1 +* SW1S1 16 20 +SW2EXIT 32 72 +* W32_4 0 0 +* SW2S1 0 16 +* W33_8 0 64 +SW2GRAY 64 128 +* W31_1 0 0 +* W31_1 0 64 +* SW2S1 16 70 +SW2GRAY1 64 128 +* W31_1 0 64 +* W31_1 0 0 +* SW4S1 19 79 +SW2METAL 64 128 +* WALL03_7 0 0 +* WALL03_7 0 64 +* SW4S1 20 68 +SW2PIPE 128 128 +* TP2_2 0 0 +* SW3S1 48 76 +SW2SLAD 64 128 +* WLA128_1 0 0 +* WARNA0 24 73 +SW2STARG 128 128 +* SW19_3 64 0 +* SW19_4 0 0 +* SW3S1 48 76 +SW2STON1 64 128 +* W28_8 0 64 +* W28_8 0 0 +* SW1S1 16 78 +SW2STON2 64 128 +* W28_8 0 64 +* WARNA0 24 73 +* W28_5 0 0 +SW2STONE 64 128 +* WALL01_1 0 0 +* WALL01_2 16 0 +* WALL01_3 32 0 +* WALL01_4 48 0 +* WALL01_1 0 72 +* WALL01_2 16 72 +* WALL01_3 32 72 +* WALL01_4 48 72 +* W33_8 0 64 +* W33_8 0 120 +* SW1S1 16 72 + + + + + page 52 + + + + +SW2STRTN 64 128 +* SW12_4 0 0 +* SW12_5 32 0 +* SW1S1 16 72 +; +SW1BLUE 64 128 +* COMP03_1 0 0 +* COMP03_2 0 64 +* SW2_7 14 66 +SW1CMT 64 128 +* WALL54_1 -42 0 +* SW3S1 16 72 +SW1GARG 64 128 +* WALL47_2 0 0 +* WALL42_6 12 62 +SW1GSTON 64 128 +* WALL48_2 0 0 +* SW2_7 13 67 +SW1HOT 64 128 +* WALL49_1 0 0 +* SW2_7 12 66 +SW1LION 64 128 +* WALL47_2 0 0 +* WALL42_5 11 62 +SW1SATYR 64 128 +* WALL47_2 0 0 +* WALL42_1 12 62 +SW1SKIN 64 128 +* HELL6_3 0 0 +* SW2_5 0 59 +SW1VINE 64 128 +* WALL00_1 0 -16 +* W106_1 0 0 +* SW4S0 20 84 +SW1WOOD 64 128 +* WALL40_2 -64 0 +* SW2_7 14 66 +SW2BLUE 64 128 +* COMP03_1 0 0 +* COMP03_2 0 64 +* SW2_8 14 66 +SW2CMT 64 128 +* WALL54_1 -42 0 +* SW3S0 16 72 +SW2GARG 64 128 +* WALL47_2 0 0 +* WALL47_5 12 62 +SW2GSTON 64 128 +* WALL48_2 0 0 +* SW2_8 13 67 +SW2HOT 64 128 +* WALL49_1 0 0 +* SW2_8 12 66 + + + + + + + + + page 53 + + + + +SW2LION 64 128 +* WALL47_2 0 0 +* WALL47_4 11 62 +SW2SATYR 64 128 +* WALL47_2 0 0 +* WALL47_3 12 62 +SW2SKIN 64 128 +* HELL6_3 0 0 +* SW2_6 0 59 +SW2VINE 64 128 +* WALL00_1 0 -16 +* W106_1 0 0 +* SW4S1 20 84 +SW2WOOD 64 128 +* WALL40_2 -64 0 +* SW2_8 14 66 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page 54 + + + + +APPENDIX II Animated Wall Textures in DOOM.wad + + +SLADRIP1 64 128 +* WALL57_2 0 0 +SLADRIP2 64 128 +* WALL57_3 0 0 +SLADRIP3 64 128 +* WALL57_4 0 0 +SLADWALL 64 128 +* WLA128_1 0 0 +; +BLODGR1 32 128 +* TP5_1 0 0 +BLODGR2 32 128 +* TP5_2 0 0 +BLODGR3 32 128 +* TP5_3 0 0 +BLODGR4 32 128 +* TP5_4 0 0 +; +BLODRIP1 32 128 +* RP2_1 0 0 +BLODRIP2 32 128 +* RP2_2 0 0 +BLODRIP3 32 128 +* RP2_3 0 0 +BLODRIP4 32 128 +* RP2_4 0 0 +; +FIREBLU1 128 128 +* W65B_1 0 0 +FIREBLU2 128 128 +* W65B_2 0 0 +; +FIRELAV2 128 128 +* W73A_2 0 0 +FIRELAV3 128 128 +* W73B_1 0 0 +FIRELAVA 128 128 +* W73A_1 0 0 +; +FIREMAG1 128 128 +* W74A_1 0 0 +FIREMAG2 128 128 +* W74A_2 0 0 +FIREMAG3 128 128 +* W74B_1 0 0 +; +FIREWALA 128 112 +* WALL23_1 0 0 +FIREWALB 128 112 +* WALL23_2 0 0 +FIREWALL 128 112 +* WALL22_1 0 0 + + + + + + + page 55 + + + + +GSTFONT1 64 128 +* WALL58_1 0 0 +GSTFONT2 64 128 +* WALL58_2 0 0 +GSTFONT3 64 128 +* WALL58_3 0 0 +; +ROCKRED1 128 128 +* WALL64_2 0 0 +ROCKRED2 128 128 +* W64B_1 0 0 +ROCKRED3 128 128 +* W64B_2 0 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page 56 + + + + +APPENDIX III Listing of sound names for Doom I and II + +*Ripped off from DMAUD by Bill Neisius* +Then corrected and expanded to include Doom II sounds for this manual. +DeuTex uses Doom's sound names rather than the artificial sound numbers +used in DMAUD. A Conversion table for this follows. + +NOTE: An asterisk '*' means the sound is used for multiple functions. + + --------------------------------------- +A) SOUNDS FOUND IN BOTH DOOM I and DOOM II + --------------------------------------- + + Weapons + +DSPISTOL* Pistol firing +DSSGCOCK* Shotgun cocking +DSSHOTGN Shotgun firing (followed by cock) +DSSAWUP Chainsaw start +DSSAWIDL Chainsaw idle +DSSAWFUL Chainsaw with trigger pulled +DSSAWHIT Chainsaw hitting monster +DSRLAUNC Rocket Launcher firing +DSBAREXP* Rocket exploding +DSFIRSHT Fireballs shot or passing +DSFIRXPL* Fireball hitting object +DSPUNCH Player punching +DSPLASMA Plasma Gun firing +DSFIRXPL* Plasma Round hitting object +DSBFG BFG9000 firing +DSRXPLOD BFG9000 round exploding + + Objects + +DSPSTART Floor/Lift starting +DSPSTOP Floor/Lift stops (Clunk) +DSSTNMOV Stairs/ceilings moving +DSDOROPN Mechanical Door opening +DSDORCLS Mechanical Door closing +DSBDOPN Fast Door Open +DSBDCLS Fast Door Close +DSSWTCHN* Switch 'thunk' sound +DSSWTCHX Switch 'pop' sound +DSTELEPT Player/Monster teleport +DSSLOP GUTS/SLOP (What the name says) +DSITMBK Item Return in MultiPlayer +DSBAREXP* Barrel explosion + + Player + +DSSKLDTH Player Push on wall +DSNOWAY Player blocked by wall +DSOOF Player hitting ground +DSWPNUP Weapon pickup +DSITEMUP Item pickup +DSGETPOW Power up sound (Soul Sphere, etc.) +DSPLPAIN Player injured +DSPLDETH Player dying scream +DSPDIEHI Player higher dying scream + + + page 57 + + + + + Former Humans + +DSPOSACT Former Human nearby breathing +DSPOSIT1 Former Human sees Player +DSPOSIT2 Former Human sees Player +DSPOSIT3 Former Human sees Player +DSPOPAIN* Former Human injured +DSPODTH1 Former Human Death Moan +DSPODTH2 Former Human Death Moan +DSPODTH3 Former Human Death Yell + + Imps + +DSBGACT Imps nearby oinking +DSBGSIT1 Imp sees Player +DSBGSIT2 Imp sees Player +DSCLAW* Imp clawing Player +DSPOPAIN* Imp injured +DSBGDTH1 Imp dying +DSBGDTH2 Imp dying + + Demons/Spectres + +DSSGTSIT Demon/Spectre sees Player +DSDMACT* Demon/Spectre nearby +DSSGTATK Demon/Spectre chomping Player +DSDMPAIN* Demon/Spectre injured +DSSGTDTH Demon/Spectre dying + + Cacodemons + +DSCACSIT Cacodemon sees player +DSDMACT* Cacodemon nearby +DSDMPAIN* Cacodemon injured +DSCACDTH Cacodemon dying + + Barons of Hell + +DSBRSSIT Baron sees Player +DSDMACT* Baron nearby +DSCLAW* Baron clawing Player +DSDMPAIN* Baron injured +DSBRSDTH Baron dying + + Lost Souls + +DSSKLATK Lost Soul attacking +DSDMACT* Lost Soul nearby +DSDMPAIN* Lost Soul injured +DSFIRXPL* Lost Soul dying + + Spider Demon + +DSSPISIT Spider Demon sees Player +DSMETAL Spider Demon walking +DSSPIDTH Spider Demon dying + + + + + + page 58 + + + + + Cyber Demon + +DSCYBSIT Cyber Demon sees Player +DSHOOF Cyber Demon walking +DSCYBDTH Cyber Demon dying + + Miscellaneous + +DSPISTOL* Menu selections +DSPISTOL* Kills, Items, Secrets & Time at end of Level screen +DSSWTCHN* Esc to main menu +DSBAREXP* Level finished explosion at end of Level screen +DSSGCOCK* Proceed to next Level at end of Level screen +DSTINK "TINK" To Chat in Modem Play + + + ---------------------------- +B) SOUNDS FOUND ONLY in DOOM II + ---------------------------- + + + Weapons + +DSDBOPN Open Super Shotgun +DSDBCLS Close Super Shotgun +DSDBLOAD Reload Super Shotgun +DSDSHTGN Fire Super Shotgun + + Revenant + +DSSKESIT Revenant sees Player +DSSKEACT Revenant nearby +DSSKEATK Revenant fires missile +DSSKESWG Revenant swings at player +DSSKEPCH Revenant punches player +DSSKEDTH Revenant dying + + Mancubus + +DSMANSIT Mancubus sees Player +DSMANATK Mancubus attacks +DSMNPAIN Mancubus injured +DSMANDTH Mancubus dying + + Pain Elemental + +DSPESIT Pain Elemental sees Player +DSPEPAIN Pain Elemental injured +DSPEDTH Pain Elemental dying + + Arachnotron + +DSBSPSIT Arachnotron sees Player +DSBSPWLK Arachnotron walking +DSBSPACT Arachnotron nearby +DSBSPDTH Arachnotron dying + + + + + + page 59 + + + + + Hell Knight + +DSKNTSIT Hell Knight sees Player +DSDMACT* Hell Knight nearby +DSCLAW* Hell Knight clawing Player +DSDMPAIN* Hell Knight injured +DSKNTDTH Hell Knight dying + + Arch-Vile + +DSVILSIT Arch Vile sees Player +DSVILACT Arch Vile nearby +DSVILATK Arch Vile attacks +DSFLAMST Arch Vile shoots Flame? +DSFLAME Arch Vile's Flame arrives +DSVIPAIN Arch Vile injured +DSVILDTH Arch Vile dying + + Final Boss + +DSBOSSIT Final Boss sees Player 'to win the game...' reversed +DSBOSPIT Final Boss spits Cube +DSBOSCUB Final Boss Cube lands and expands +DSBOSPN Final Boss injured +DSBOSDTH Final Boss dying + + Wolfenstein + +DSSSSIT Wolfenstein SS sees player. 'Schultstaffel'-'SS' +DSSSDTH Wolfenstein SS dying. 'mein lieben' -'My Life!' +DSKEENPN Commander Keen injured +DSKEENDT Commander Keen dying + + Unknown + +DSRADIO Phone sound? Modem play? + + + + + + + + + + + + + + + + + + + + + + + + + + page 60 + + + + ++ ---------------------------------- ++ C) CONVERTING DMAUD sounds for DEUTEX ++ ---------------------------------- ++ ++ ++ ++ For all you DMAUD users out there, here's a chart you can use to ++ convert those DMAUD sound Numbers to Doom or DEUTEX sound names. ++ ++ ++ ++ DMAUD NO. DEUTEX/Doom Name ++ ++ ++ 1 DSPISTOL ++ 2 DSSHOTGN ++ 3 DSSGCOCK ++ 4 DSSAWUP ++ 5 DSSAWIDL ++ 6 DSSAWFUL ++ 7 DSSAWHIT ++ 8 DSRLAUNC ++ 9 DSRXPLOD ++ 10 DSFIRSHT ++ 11 DSFIRXPL ++ 12 DSPSTART ++ 13 DSPSTOP ++ 14 DSDOROPN ++ 15 DSDORCLS ++ 16 DSSTNMOV ++ 17 DSSWTCHN ++ 18 DSSWTCHX ++ 19 DSPLPAIN ++ 20 DSDMPAIN ++ 21 DSPOPAIN ++ 22 DSSLOP ++ 23 DSITEMUP ++ 24 DSWPNUP ++ 25 DSOOF ++ 26 DSTELEPT ++ 27 DSPOSIT1 ++ 28 DSPOSIT2 ++ 29 DSPOSIT3 ++ 30 DSBGSIT1 ++ 31 DSBGSIT2 ++ 32 DSSGTSIT ++ 33 DSBRSSIT ++ 34 DSSGTATK ++ 35 DSCLAW ++ 36 DSPLDETH ++ 37 DSPODTH1 ++ 38 DSPODTH2 ++ 39 DSPODTH3 + + + + + + + + + page 61 + + + + ++ 40 DSBGDTH1 ++ 41 DSBGDTH2 ++ 42 DSSGTDTH ++ 43 DSBRSDTH ++ 44 DSPOSACT ++ 45 DSBGACT ++ 46 DSDMACT ++ 47 DSNOWAY ++ 48 DSBAREXP ++ 49 DSPUNCH ++ 50 DSPLASMA ++ 51 DSBFG ++ 52 DSCACSIT ++ 53 DSCYBSIT ++ 54 DSSPISIT ++ 55 DSSKLATK ++ 56 DSCACDTH ++ 57 DSSKLDTH ++ 58 DSCYBDTH ++ 59 DSSPIDTH ++ 60 DSHOOF ++ 61 DSMETAL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page 62 + + + +APPENDIX IV DeuTex and DeuSF COMMAND SUMMARIES + + --------------- +A) DeuTex COMMANDS + --------------- + +Command Line Format: DEUTEX <-optional cmds.> <-other cmds.> + +******** 1) STAND ALONE COMMANDS: + +-dmtextures Lists the Doom Textures in TEXTURE?.TXT. +-check Will look for Textures containing void columns. +-help Lists the parameters. +-syntax Prints short listing of the format of wadINFO.TXT. +-unused Checks for unused bytes in a pwad. + +******** 2) OPTIONAL COMMANDS: + +-doom Defines the Doom or Doom2 directory. +-dir Defines the working directory. +-deu* Add 64K at the end of your pwad for DEU. +-rgb Defines the color used for 'transparent'. +-bmp \_________________/ Format used when EXTRACTING pictures. DeuTex +-gif / \ recognizes both when STORING pictures. +-ppm / +-wave \_______________/ Format used when EXTRACTING sounds. DeuTex +-au / \ recognizes both when INSERTING sounds). +-voc / +-fullsnd* For extracting oversize sound entries. +-level \ / These tell DeuTex to select sprites, patches, +-lump \ / sounds, etc. when composing, decomposing, or +-texture \___________/ merging pwads. Commands can be combined. +-sound / \ By default, all entries are selected. +-graphic / \ Those switches can be combined. +-sprite / +-patch / +-flat / +-o tells deutex it can overwrite the data file if they exist +-s_end tells deutex to use S_END not SS_END for sprite pwads + (note: if you're not a hacker, this is useless to you.) + +******** 3) OTHER COMMANDS: + +-iwad Used with -make, makes iwad instead of a pwad. +-wadir Directory list, with entry identification. +-get Get a single entry from a wad +-extract Extracts resources from a pwad and puts them + into a subdirectory having the resource name. +-usedtex List the textures used in a wad. + +-make Reads wadINFO.TXT and uses it to + compose MYOWN.wad from the files in the subdirectories. + +-merge Will merge MYOWN.wad with DOOM.wad. +-restore Will restore DOOM.wad and the merged MYOWN.wad. +-join Will merge THIS.wad with MYOWN.wad +-app Will append Doom sprites to MYOWN.wad +-res Will restore MYOWN.wad + All these commands are like those of DeuSF +-as Appends all sprites. Short for -sprites -app +-af Appends all flats. Short for -flats -app + + page 63 + + + + + -------------- +B) DeuSF COMMANDS + -------------- + + +Command Line Format: DeuSF + + + +******** 1) STAND ALONE COMMANDS: + + +-help Lists these parameters. + +-format Displays format conventions a pwad must follow. + +-wadir Lists the entries in the pwad directory. + + +******** 2) OPTIONAL COMMANDS: + + +-doom Defines the Doom or Doom2 directory. + +-sprite Used with -add or -app, to add only sprites or only Flats. If +-flat neither of these commands is present, DeuSF will add both. + + +******** 3) MANDATORY COMMANDS: + +these are the same as the equivalent DeuTex commands. +DeuSF is only a small version of DeuTex, meant to install +sprites and Flats pwad on the disk of the end user. + +-merge Will merge MYOWN.wad with DOOM.wad. +-restore Will restore DOOM.wad and the merged MYOWN.wad. +-join Will merge THIS.wad with MYOWN.wad +-app Will append Doom sprites to MYOWN.wad +-res Will restore MYOWN.wad + All these commands are like those of DeuSF +-as Appends all sprites. Short for -sprites -app +-af Appends all flats. Short for -flats -app + + + + + + + + + + + + + + + + + + + + Page 64 diff --git a/docsrc/hackers_guide.html b/docsrc/hackers_guide.html new file mode 100644 index 0000000..ad10353 --- /dev/null +++ b/docsrc/hackers_guide.html @@ -0,0 +1,69 @@ + + +Hacker's guide + + +

Hacker's guide

+ +

Endianness

+ +Some files contain numbers that have a fixed endianness, +independent from the endianness of the CPU DeuTex happens to run +on. These call for some special treatment, as the C language has +no provision for reading and writing integers otherwise than in +the native endianness. + +
    +
  • To read an integer from a file with a particular endianness, +use use fread_i16_le(), +fread_i16_be(), fread_i32_le() and +fread_i32_be(). The first argument is the file +descriptor, the second argument is a pointer on a variable that +will receive the value read from the file.

    + +
  • To write an integer to a file with a particular endianness, +use fwrite_i16_le(), fwrite_i16_be(), +fwrite_i32_le() and fwrite_i32_be(). +The first argument is the file descriptor, the second argument +is the value to write.

    + +
  • To read an integer with a particular endianness from a +memory area, use read_i16_le(), +read_i16_be(), read_i32_le() and +read_i32_be(). The first argument is a pointer on +the memory area, the second argument is a pointer on a variable +that will receive the value read from the memory area. +Alternatively, you can use the peek_i*() functions +that take no second argument but instead return the read value. +

    + +
  • To write an integer with a particular endianness to a memory +area, use write_i16_le(), +write_i16_be, write_i32_le() and +write_i32_be(). The first argument is a pointer on +the memory area, the second argument is the value to write. + +
+ +Mnemonic to remember the arguments order : the object that +has a defined endianness is considered central and therefore +always comes first. + +Here is some sample code and the result of running it. + +
+fwrite_i32_be (stdout, 0x12345678);
+fwrite_i32_le (stdout, 0x12345678);
+fwrite_i16_be (stdout, 0xabcd);
+fwrite_i16_le (stdout, 0xabcd);
+
+ +
+12 34 56 78 78 56 34 12 AB CD CD AB
+
+ + + + + + diff --git a/docsrc/todo.html b/docsrc/todo.html new file mode 100644 index 0000000..b432f01 --- /dev/null +++ b/docsrc/todo.html @@ -0,0 +1,171 @@ + + +To-do list for DeuTex + + + +

To-do list for DeuTex

+ +
    +
  • In the directives file and textures files, "include" directive to include +the rest of another block/file. + +

  • In the directives file and textures files, allow references to +environment variables (E.G. $E(name)) + +

  • In the directives file and textures files, allow user variables (E.G. + $(name)) + +

  • Make it easier to let a texture have a description identical to another +texture + +

  • In the directives file, add a mean to import all/only named/all except +named flats as patches. + +

  • In the directives file, add a mean to import all/only named/all except +named patches as flats. This implies 1) accepting flats larger than +64×64 (by clipping) 2) converting transparent pixels to a certain +colour (which one ?). + +

  • In the directives file, add a mean to automatically generate a texture +for all/only named/all except named patches. The height of the automatic +texture is 128, its width is the least power of two wide enough to contain the +patch. The automatic texture is filled with the patch by tiling, starting from +the top left corner. The name of the automatic texture is the name of the +patch. + +

  • Patches > 255 high + +

  • Make sure that support for Strife is complete. + +

  • When doing -xtract/-make of +strife0.wad, creates .au sound files but is not able +to read them back ("WAV: Can't read dsswish.au" or something like + that). + +

  • Instead of allowing any and all characters in the script file, require +them to be quoted. And, when doing -xtract, produce the script +file with the appropriate quotes... Since, under Unix, the only characters +that are not allowed in a file name are NUL and "/", I don't see +why DeuTex should prevent users from extracting lumps with weird characters in +their names. However, that might cause compatilibity problems with the DOS +version. + +

  • The presence of the GIF routines might prevent DeuTex to be distributed +in the "free" section of Debian. Would it be sufficient to #ifdef them out ? + +

  • Finish -pf + +

  • RAWtoPPM() forgets to replace occurrences of the +transparent colour by its nearest colour. Thus, CEIL4_1 is +extracted with a cyan background. + +

  • The command line interface is not always intuitive and fussy about the +position of certain options. + +

  • Regarding audio support, Matthew W. Miller +<mattm@infinet.com> offered the following comment on +1999-07-04 : + +
    +

    Audio handling in deutex (I'm referring to the irix +5.3 version's included source code) is, I believe, based on dmgraph, but +is pretty dire in any case. + +

    Imported sounds are all resampled to 11025 Hz, even though that +hasn't been necessary since some time between v1.2 and v1.666 (basically, +any version that uses the item-respawn sound has the improved sound +engine). Exasperatingly, lxdoom (or maybe sndserv?) takes several steps +back by expecting sounds to be *raw* 11025 Hz data. You may be able to +set new options to reflect this. + +

    Also, one would hope that eventually one or more of the source +ports will start to support bitrates other than 8 bit, and (maybe?) stereo +samples. You may want to start leaning on various source ports' +programmers to get their acts together and start coming to some sort of +agreement. ;) + +

    Importation of .wav files is pretty crufty. Like dmgraph before +it, the deutex 5.3 source expects there to be just one big 'data' chunk, +and doesn't notice the 'info' chunks that certain stupid Windows programs +(*cough*cough*CoolEdit*GoldWave*cough*) insist on putting in (usually with +copyright messages for the program itself, which in a just world would be +illegal). Greater explanation of all this whacky chunk business can be +found at: + +http://www.compsoc.man.ac.uk/~maniac/resource_web/wav_file_format/ +(wav1.htm, wav2.htm, wav3.htm, 4.htm, 5.htm) + +

    Essentially, you want to clip out the first 'data' chunk and ignore crap +like 'info', 'inam', 'list', or whatever. +

    + +

  • TBD: New options -fstart and -fend to control +the start-of-flats and end-of-flats markers used in pwads. Default to +FF_START and F_END respectively. +Warning: here again, don't use those options just because +they're here. The default markers are perfectly fine, and they conform to the +de-facto standard. If you deviate from them, you're asking for trouble. + +

  • -f_end + +

  • In the doc, mention that negative patch Y-offsets are forced to 0 by +the engine. + +

  • Why does DeuTex sometimes includes patches even if you don't mention +them explicitly and sometimes doesn't ? + +

  • Make a DOS binary distribution with all filenames 8.3, all +documentation in CRLF & CP437 format, no sources, no makefile, only DOS +executables. + +

  • Options shouldn't care whether there is space between them and their +argument. + +

  • Man page: mention that some options are DeuTex-only, not DeuSF. + +

  • Man page: insert `deutex -man` automatically. + +

  • Alpha port: look into 64-bit longs. + +

  • -check shouldn't require an argument. It should use the +iwad by default. + +

  • -main should be implemented for DeuTex as well. + +

  • DeuTex should not look for doom.wad in the directory set +by -heretic ! + +

  • WAV to Doom sound: the warning "shrinking ... to 11025" should mention +the name of the file or appear only once. + +

  • PPM to Doom graphics: the warning "quantisation is slow" should either +mention the name of the file or appear only once. + +

  • Determine why converting Doom graphics to PPM and back does not yield +the same thing. This also happens with BMP but much less so. + +

  • Bug: certain flats seem to be extracted with certain pixels set to the +transparent colour (Doom's CEIL4_1). DeuTex 3.6 for DOS exhibits +the same problem [1]. + +

  • Hexen: DeuTex does not handle the BEHAVIOR lumps correctly. + +

  • Hexen: does not extract graphics quite correctly (applies transparent +colour translation to opaque images such as FINALE1 and +FINALE2. This is probably related to [1]. + +

  • Hexen: when trying to build back the hexen wad, got +
    +Color palette is unknown
    +WARNING unknown palette. Using colour 0xff as transparentcolour.
    +Some graphics may appear moth-eaten.
    +Making lumps
    +Bug: *** idinx ***
    +
    + + +
+ + + diff --git a/dos/buildbc.bat b/dos/buildbc.bat new file mode 100644 index 0000000..c687d53 --- /dev/null +++ b/dos/buildbc.bat @@ -0,0 +1,22 @@ +@echo off +rem buildbc.bat - build DeuTex with Borland C++ +rem AYM 1999-09-09 + +if "%1" == "" goto usage +if not "%2" == "" goto usage +set bcdir=%1 + +cd src +echo Building DeuTex +bcc -mh -I%bcdir%include -L%bcdir%lib -DDeuTex -e..\deutex.exe *.c +echo Building DeuSF +bcc -mh -I%bcdir%include -L%bcdir%lib -DDeuSF -e..\deusf.exe *.c +cd .. +goto end + +:usage +echo Usage: buildbc (dir) +echo (dir) The directory where Borland C is installed, +echo followed by a backslash (E.G. "c:\bc4\"). + +:end diff --git a/dos/buildmsc.bat b/dos/buildmsc.bat new file mode 100644 index 0000000..68f7dbe --- /dev/null +++ b/dos/buildmsc.bat @@ -0,0 +1,10 @@ +@echo off +rem buildmsc.bat - build DeuTex with MSC +rem AYM 1999-09-09 + +cd src +echo Building DeuTex +cl -AH -W2 -DDeuTex -Fe..\deutex.exe *.c +echo Building DeuSF +cl -AH -W2 -DDeuSF -Fe..\deusf.exe *.c +cd .. diff --git a/old/deusf.ide b/old/deusf.ide new file mode 100644 index 0000000..f29767f Binary files /dev/null and b/old/deusf.ide differ diff --git a/old/deutex.ide b/old/deutex.ide new file mode 100644 index 0000000..0408b0a Binary files /dev/null and b/old/deutex.ide differ diff --git a/old/dos2unix.sh b/old/dos2unix.sh new file mode 100755 index 0000000..a249624 --- /dev/null +++ b/old/dos2unix.sh @@ -0,0 +1,11 @@ +#! /bin/csh -f +# +# In case you don't have the dos2unix command: +# here is the fastest and simplest solution... +# +# 08-Mar-96, Jack Leunissen +# +foreach i ( *.[ch] makefile ) + tr -d '\015' < $i > tmp + mv tmp $i +end diff --git a/old/readme.txt b/old/readme.txt new file mode 100644 index 0000000..b21f4de --- /dev/null +++ b/old/readme.txt @@ -0,0 +1,17 @@ + + + This is the source code for DeuTex 3.4, a tool to customise + DOOM and HERETIC WAD files. + + + This code can compile on DOS, OS2 and Unix systems + but the DLL part is only meant for 16-bit Windows. + see the file making.txt for more information + + + Have fun with it, but remember it's copyrighted, not public domain. + That means I keep some rights on it. + + Olivier Montanuy + + diff --git a/old/save.bat b/old/save.bat new file mode 100644 index 0000000..5fffc0b --- /dev/null +++ b/old/save.bat @@ -0,0 +1 @@ +pkzip -ex ..\dtexsf.zip *.c *.h *.def *.prj *.ide *.bat *.txt *.cmd *.mak *.sh makefile \ No newline at end of file diff --git a/scripts/process b/scripts/process new file mode 100755 index 0000000..210fe9b --- /dev/null +++ b/scripts/process @@ -0,0 +1,19 @@ +#!/bin/sh +# +# process - expand certain macro expressions in text files +# Usage: process [ ...] +# AYM 1999-08-13 +# + +# In , replace occurrences of +# - "$DATE" by the YYYY-MM-DD current time, +# - "$SELF_DATE" by the YYYY-MM-DD mtime of , +# - "$SOURCE_DATE" by the YYYY-MM-DD mtime of the most recent reffile, +# - "$VERSION" by the contents of the file ./VERSION. +# Output is written on stdout. + +file=$1 +shift +sed -e "s/\$DATE/$(date +%Y-%m-%d)/; + s/\$SELF_DATE/$(find $file -printf '%TY-%Tm-%Td')/; + s/\$VERSION/$(cat VERSION)/" $file diff --git a/src/color.c b/src/color.c new file mode 100644 index 0000000..c35bde7 --- /dev/null +++ b/src/color.c @@ -0,0 +1,401 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/*select your quantisation method*/ +/*#define QUANTSLOW*/ +#define QUANTHASH + + +#include "deutex.h" +#include "tools.h" +#include "color.h" + + +/*compile only for DeuTex*/ +#if defined DeuTex + +#ifdef QUANTHASH +/*************** COL module: quantisation ************/ +/* +** hash table +** +*/ +UInt8 COLindex( UInt8 R, UInt8 G, UInt8 B,UInt8 index); +UInt8 COLpalMatch( UInt8 R, UInt8 G, UInt8 B); + + +static struct PIXEL huge *COLpal; +static struct PIXEL COLinv; +static UInt8 COLinvisib; +static Bool COLok=FALSE; + + +const int COLsame = 3; +Int16 COLdiff( UInt8 R, UInt8 G, UInt8 B, UInt8 idx) +{ + register struct PIXEL huge *pixel = &COLpal[(Int16)(idx&0xFF)]; + register Int16 d; /*signed*/ + register Int16 e=0; + d= (((Int16)R)&0xFF) - (((Int16) pixel->R) &0xFF); + d>>=1; + e+= d*d; + d= (((Int16)G)&0xFF) - (((Int16) pixel->G) &0xFF); + d>>=1; + e+= d*d; + d= (((Int16)B)&0xFF) - (((Int16) pixel->B) &0xFF); + d>>=1; + e+= d*d; + if(e<0) return 0x7FFF; + return e; +} +UInt8 COLpalMatch( UInt8 R, UInt8 G, UInt8 B) +{ Int16 i,test,min=0x7FFF; + UInt8 idxmin='\0'; + if(COLok!=TRUE) Bug("COLok"); + for(i=0;i<256;i++) + { if((UInt8)i!=COLinvisib) + { test=COLdiff(R,G,B,(UInt8)i); + if(test>8; + res &= HashMask; + return (Int16) res; +} +/* +void COLhashPrint(void) +{ Int16 idx,i; + UInt8 res; + UInt8 buff[64]; + Int16 count=0; + for(idx=0;idx2) + { if(res==COLhash[(nextidx-1)&HashMask]) + fprintf(COLfp,"multi %d in %d\n",(int)res,nextidx); + idx=((Int16)res)&0xFF; + fprintf(COLfp,"%d\t%d\t%d\t*\n",(int)(R-COLpal[idx].R),(int)(G-COLpal[idx].G),(int)(B-COLpal[idx].B)); + + } +*/ + return res; + } + } + /*no good solution. slow match*/ + return COLpalMatch(R,G,B); +} + + + + + + +void COLinit( UInt8 invR, UInt8 invG, UInt8 invB,char huge *Colors, Int16 Colsz) +{ Int16 i; + const char *name = NULL; + /*Int16 R,G,B;*/ + if(COLok!=FALSE) Bug("COLok"); + if(Colsz< 256*sizeof(struct PIXEL)) Bug("Color entry too small"); + COLok=TRUE; + COLpal= (struct PIXEL huge *)Malloc(256*sizeof(struct PIXEL)); + for(i=0;i<256;i++) + { COLpal[i].R=Colors[i*3+0]; + COLpal[i].G=Colors[i*3+1]; + COLpal[i].B=Colors[i*3+2]; + } +#if 1 /*supposedly exact...*/ + if (COLpal[0].R == 0 && COLpal[0].G == 0 && COLpal[0].B == 0 + && COLpal[0xf7].R == 0 && COLpal[0xf7].G == 0 && COLpal[0xf7].B == 0) + { i = 0xf7; + name = "Doom"; + } + else if (COLpal[35].R == 255 && COLpal[35].G == 255 && COLpal[35].B == 255 + && COLpal[255].R == 255 && COLpal[255].G == 255 && COLpal[255].B == 255) + { i = 0xff; + name = "Heretic"; + } + else if (0) /* FIXME */ + { + name = "Hexen"; + } + else if (COLpal[0].R == 0 && COLpal[0].G == 0 && COLpal[0].B == 0 + && COLpal[240].R == 0 && COLpal[240].G == 0 && COLpal[240].B == 0) + { i = 0xf0; + name = "Strife"; + } + else + { i = 0xff; + name = NULL; + } +#else /*screws some little points, on some sprites*/ + i=0xFF; /*DOOM and HERETIC*/ +#endif + /* + ** correction to doom palette + */ + COLinvisib= (UInt8)(i&0xFF); + Info("Color palette is %s\n", name ? name : "unknown"); + if (name == NULL) + Info ("WARNING unknown palette. Using colour 0xff as transparent" + "colour.\nSome graphics may appear moth-eaten.\n"); + COLinv.R=COLpal[i].R=invR; + COLinv.G=COLpal[i].G=invG; + COLinv.B=COLpal[i].B=invB; + /* + ** init hash table + */ + COLhash=(UInt8 huge *)Malloc(HashSz); + Memset(COLhash,COLinvisib,HashSz); /*clear hash table*/ + + for(i=0;i<256;i++) + { if((UInt8)i!=COLinvisib) + COLputColHash(i,COLpal[i].R,COLpal[i].G,COLpal[i].B); + } +} +void COLfree(void) +{ if(COLok!=TRUE) Bug("COLok"); + COLok=FALSE; + Free(COLpal); + Free(COLhash); +} + UInt8 COLinvisible(void) +{ if(COLok!=TRUE) Bug("COLok"); + return COLinvisib; +} + +struct PIXEL huge *COLdoomPalet(void) +{ if(COLok!=TRUE) Bug("COLok"); + return COLpal; +} +UInt8 COLindex( UInt8 R, UInt8 G, UInt8 B, UInt8 index) +{ Int16 i; + if(COLok!=TRUE) Bug("COLok"); + /*check for invisible color*/ + if(R==COLinv.R) + if(G==COLinv.G) + if(B==COLinv.B) + return COLinvisib; + /*check for DOOM palette*/ + i= ((Int16)index)&0xFF; + if(R==COLpal[i].R) + if(G==COLpal[i].G) + if(B==COLpal[i].B) + return index; + /*else, check hash palette*/ + i=(Int16)COLgetIndexHash(R,G,B); + return (UInt8)i; +} + +#endif /*QUANTHASH*/ + + + + + + + + + + + + + + + + + +#ifdef QUANTSLOW +/*************** COL module: quantisation ************/ +/* +** implemented as the most stupid color quantisation +** ever to be seen on this sector of the galaxy +** +*/ + + +static struct PIXEL huge *COLpal; +static struct PIXEL COLinv; +static UInt8 COLinvisib; +static Bool COLok=FALSE; + + + +void COLinit( UInt8 invR, UInt8 invG, UInt8 invB,UInt8 huge *Colors, Int16 Colsz) +{ Int16 i; + UInt8 r,g,b; + + if(COLok!=FALSE) Bug("COLok"); + if(Colsz< 256*sizeof(struct PIXEL)) Bug("Color entry too small"); + COLok=TRUE; + COLpal= (struct PIXEL huge *)Malloc(256*sizeof(struct PIXEL)); + /* + ** possible bug: the color corresponding to the + ** CYAN is assumed to be the second one with 0 0 0 + ** this is because CYAN is supressed. + */ + for(i=0;i<256;i++) + { r=Colors[i*3+0]; + g=Colors[i*3+1]; + b=Colors[i*3+2]; + COLpal[i].R=r; + COLpal[i].G=g; + COLpal[i].B=b; + if(r==0)if(g==0)if(b==0) + COLinvisib=( UInt8)(i&0xFF); + } + if(COLinvisib!=(UInt8)0xF7)Warning("Strange PLAYPAL invisible color"); + if(COLinvisib==0)ProgError("PLAYPAL is not correct"); + /* + ** correction to doom palette + */ + i=((Int16)COLinvisib)&0xFF; + COLinv.R=COLpal[i].R=invR; + COLinv.G=COLpal[i].G=invG; + COLinv.B=COLpal[i].B=invB; +} + UInt8 COLinvisible(void) +{ if(COLok!=TRUE) Bug("COLok"); + return COLinvisib; +} + +struct PIXEL huge *COLdoomPalet(void) +{ if(COLok!=TRUE) Bug("COLok"); + return COLpal; +} + + + +Int16 COLdiff( UInt8 r, UInt8 g, UInt8 b, UInt8 idx); +UInt8 COLindex( UInt8 R, UInt8 G, UInt8 B,UInt8 index) +{ Int16 i; + Int16 test,min=0x7FFF; + UInt8 idx,idxmin; + if(COLok!=TRUE) Bug("COLok"); + + if(R==COLinv.R)if(G==COLinv.G)if(B==COLinv.B) return COLinvisib; + /*check for DOOM palette*/ + i= ((Int16)index)&0xFF; + if(R==COLpal[i].R) + if(G==COLpal[i].G) + if(B==COLpal[i].B) + return index; + /*Best color match: slow*/ + idx=(UInt8)0; + for(i=0;i<256;i++) + { if(idx!=COLinvisib) + { test=COLdiff(R,G,B,idx); + if(test0)? d:-d; + d= ((Int16)g) - ((Int16) COLpal[index].G); + e+= (d>0)? d:-d; + d= ((Int16)b) - ((Int16) COLpal[index].B); + e+= (d>0)? d:-d; + return e; +} +#endif /*QUANTSLOW*/ + +#endif /*DeuTex*/ diff --git a/src/color.h b/src/color.h new file mode 100644 index 0000000..0e5efb3 --- /dev/null +++ b/src/color.h @@ -0,0 +1,35 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/*init colors before any operation*/ +void COLinit( UInt8 invR, UInt8 invG, UInt8 invB,char huge *Colors,Int16 Colsz); +void COLfree(void); + + +/*cross reference for picture.c only*/ +struct PIXEL{ UInt8 R; UInt8 G; UInt8 B;}; +UInt8 COLindex(UInt8 R, UInt8 G, UInt8 B,UInt8 idx); +UInt8 COLinvisible(void); +struct PIXEL huge *COLdoomPalet(void); +/*end of cross reference for picture.c*/ diff --git a/src/compose.c b/src/compose.c new file mode 100644 index 0000000..9ca4941 --- /dev/null +++ b/src/compose.c @@ -0,0 +1,640 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "mkwad.h" +#include "texture.h" +#include "ident.h" +#include "color.h" +#include "picture.h" +#include "sound.h" +#include "text.h" + +/*compile only for DeuTex*/ +#if defined DeuTex + +static void AddSomeJunk(char *file); +/************Begin Tex2Ascii module ************************* +** +** Translate TEXTURE1,TEXTURE2 and PNAME in +** a texture list for future modifications +*/ +extern char file[128]; + +/***************End Tex2ascii module ******************/ + + + + + + + + + + + + + + + + + + + + + + + +/* +** +** make a PWAD from creation directives +** load levels,lumps, +** create textures +** load sounds, pics, sprites, patches, flats, +*/ + + +/* +** Can't handle PATCHES redefined from WAD +*/ +Bool CMPOcopyFromWAD(Int32 *size,struct WADINFO *rwad,char *DataDir,char *Dir,char *nam,char *filenam) +{ static struct WADINFO pwad; + Int16 entry; + if(MakeFileName(file,DataDir,Dir,"",filenam,"WAD")!=TRUE) + return FALSE; + WADRopenR(&pwad,file); + entry=WADRfindEntry(&pwad,nam); + if(entry>=0) + { *size=WADRwriteWADentry(rwad,&pwad,entry); + } + WADRclose(&pwad); + if(entry<=0)return FALSE; + return TRUE; +} +/* +** find a picture. +** must=TRUE is picture must exist +** returns picture type +*/ +Int16 CMPOloadPic(Int32 *size,struct WADINFO *rwad,char *file,char *DataDir,char *Dir,char *nam,char *filenam, Int16 Type, Int16 OfsX, Int16 OfsY) +{ int res=PICNONE; + if(MakeFileName(file,DataDir,Dir,"",filenam,"ppm")==TRUE) + res=PICPPM; + else if(MakeFileName(file,DataDir,Dir,"",filenam,"bmp")==TRUE) + res=PICBMP; + else if(MakeFileName(file,DataDir,Dir,"",filenam,"gif")==TRUE) + { + static int gif_warning = 0; + res=PICGIF; + if (! gif_warning) + { + Warning ("GIF support may go away in the future. Switch to PPM or BMP."); + gif_warning = 1; + } + } + else if(CMPOcopyFromWAD(size,rwad,DataDir,Dir,nam,filenam)==TRUE) + return PICWAD; + if(res!=PICNONE) + *size = PICsaveInWAD(rwad,file,Type,OfsX,OfsY,res); + else if(Type!=PLUMP) + Warning("Could not find file %s, .ppm, .bmp or .gif",file); + return res; +} + +struct WADINFO *CMPOrwad; +char *CMPOwadout=NULL; +void CMPOerrorAction(void) +{ if(CMPOwadout==NULL) return; + WADRclose(CMPOrwad); /*close file*/ + Unlink(CMPOwadout); /*delete file*/ +} + + + +void CMPOmakePWAD( char *doomwad,WADTYPE type, char *PWADname, + char *DataDir,char *texin, NTRYB select, + char trnR, char trnG, char trnB, Bool George) +{ /* + ** type PWAD as we are generating a real PWAD + */ + Int32 start=0, size=0; + static char name[8]; + static char filenam[8]; + /*PNAMES */ + Int16 nbPatchs,p; + Bool NeedPNAME=FALSE; + Bool FoundOne=FALSE; + Bool Repeat; + IMGTYPE Picture; + /*optional insertion point*/ + Int16 X,Y; + /*text file to read*/ + static struct TXTFILE *TXT; + /*DOOM wad*/ + static struct WADINFO iwad,pwad; + /*result wad file*/ + static struct WADINFO rwad; + /*for Pnames*/ + Int16 entry;char huge *EntryP;Int32 EntrySz=0; + char huge *Colors; + /* initialisation*/ + + Info("Translating %s into a %cWAD %s\n",texin,(type==IWAD)?'I':'P',PWADname); + + /*open iwad,get iwad directory*/ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + + TXT= TXTopenR(texin); + WADRopenW(&rwad,PWADname,type); /* fake IWAD or real PWAD */ + /* + ** dirty: set error handler to delete the wad out file, + ** if an error occurs. + */ + CMPOrwad = &rwad; + CMPOwadout = PWADname; + ProgErrorAction(CMPOerrorAction); + /* + ** levels! add your own new levels to DOOM! + ** read level from a PWAD file + */ + if(select&BLEVEL) + { if(TXTseekSection(TXT,"LEVELS")) + { while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { p=IDENTlevel(name); + if(p<0) ProgError("Illegal level name %.8s",name); + if(MakeFileName(file,DataDir,"LEVELS","",filenam,"WAD")!=TRUE) + ProgError("Can't find Level WAD %s",file); + Detail("Reading level WAD file %s\n",file); + WADRwriteWADlevel(&rwad,file,name); + } + } + } + /* + ** prepare palette for graphics + */ + /*find PLAYPAL*/ + if(select&(BGRAPHIC|BSPRITE|BPATCH|BFLAT)) + { /*should read playpal file if exist*/ + entry=WADRfindEntry(&iwad,"PLAYPAL"); + if(entry<0) ProgError("Can't find PLAYPAL in main WAD"); + Colors=WADRreadEntry(&iwad,entry,&EntrySz); + COLinit(trnR,trnG,trnB,Colors,(Int16)EntrySz); + Free(Colors); + } + /* + ** + ** lumps. non graphic raw data for DOOM + */ + if(select&BLUMP) + { start=size=0; + if(TXTseekSection(TXT,"LUMPS")) + { Phase("Making Lumps\n"); + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if(Repeat!=TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(MakeFileName(file,DataDir,"LUMPS","",filenam,"LMP")==TRUE) + { size=WADRwriteLump(&rwad,file); + } + else + { Picture=CMPOloadPic(&size,&rwad,file,DataDir,"LUMPS",name,filenam,PLUMP,X,Y); + if(Picture==PICNONE) + if(CMPOcopyFromWAD(&size,&rwad,DataDir,"LUMPS",name,filenam)!=TRUE) + ProgError("Can't find Lump or picture file %s.",file); + } + } + WADRdirAddEntry(&rwad,start,size,name); + } + } + } + /* + ** initialise list of patch names + */ + if(select&(BTEXTUR|BPATCH)) + { entry=WADRfindEntry(&iwad,"PNAMES"); + if(entry<0) ProgError("Can't find PNAMES in main WAD"); + EntryP=WADRreadEntry(&iwad,entry,&EntrySz); + PNMinit(EntryP,EntrySz); + Free(EntryP); + NeedPNAME = FALSE; + } + /* + ** read texture1 + */ + if(select&BTEXTUR) + { if(TXTseekSection(TXT,"TEXTURE1")) + { Phase("Making Texture1\n"); + TXUinit(); + entry=WADRfindEntry(&iwad,"TEXTURE1"); + if(entry>=0) + { EntryP=WADRreadEntry(&iwad,entry,&EntrySz); + TXUreadTEXTURE(EntryP,EntrySz,NULL,0,TRUE); + Free(EntryP); + } + else Warning("Can't find TEXTURE1 in main WAD"); + FoundOne=FALSE; + /*read TEXTURES composing TEXTURE1*/ + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if(MakeFileName(file,DataDir,"TEXTURES","",name,"TXT")==TRUE) + { Detail("Reading texture file %s\n",file); + TXUreadTexFile(file,TRUE); + NeedPNAME=TRUE; + FoundOne=TRUE; + } + else if(MakeFileName(file,DataDir,"TEXTURES","",name,"WAD")==TRUE) + { Detail("Reading texture WAD %s\n",file); + WADRopenR(&pwad,file); + entry=WADRfindEntry(&pwad,"TEXTURE1"); + if(entry>=0) + { EntryP=WADRreadEntry(&pwad,entry,&EntrySz); + TXUreadTEXTURE(EntryP,EntrySz,NULL,0,TRUE); + Free(EntryP); + NeedPNAME=TRUE; + FoundOne=TRUE; + } + WADRclose(&pwad); + } + else + ProgError("Can't find texture list %s",file); + } + /*write texture*/ + if(FoundOne==TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start= WADRposition(&rwad); + size = TXUwriteTEXTUREtoWAD(&rwad); + WADRdirAddEntry(&rwad,start,size,"TEXTURE1"); + } + TXUfree(); + } + } + /* + ** read texture2 + */ + if(select&BTEXTUR) + { if(TXTseekSection(TXT,"TEXTURE2")) + { Phase("Making Texture2\n"); + TXUinit(); + entry=WADRfindEntry(&iwad,"TEXTURE2"); + if(entry>=0) + { EntryP=WADRreadEntry(&iwad,entry,&EntrySz); + TXUreadTEXTURE(EntryP,EntrySz,NULL,0,TRUE); + Free(EntryP); + } + else Warning("Can't find TEXTURE2 in main WAD"); + FoundOne=FALSE; + /*read TEXTURES composing TEXTURE2*/ + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if(MakeFileName(file,DataDir,"TEXTURES","",name,"TXT")==TRUE) + { Detail("Reading texture file %s\n",file); + TXUreadTexFile(file,TRUE); + NeedPNAME=TRUE; + FoundOne=TRUE; + } + else if(MakeFileName(file,DataDir,"TEXTURES","",name,"WAD")==TRUE) + { Detail("Reading texture WAD %s\n",file); + WADRopenR(&pwad,file); + entry=WADRfindEntry(&pwad,"TEXTURE2"); + if(entry>=0) + { EntryP=WADRreadEntry(&pwad,entry,&EntrySz); + TXUreadTEXTURE(EntryP,EntrySz,NULL,0,TRUE); + Free(EntryP); + NeedPNAME=TRUE; + FoundOne=TRUE; + } + WADRclose(&pwad); + } + else + ProgError("Can't find texture list %s",file); + } + /*write texture*/ + if(FoundOne==TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start= WADRposition(&rwad); + size = TXUwriteTEXTUREtoWAD(&rwad); + WADRdirAddEntry(&rwad,start,size,"TEXTURE2"); + } + TXUfree(); + } + } + /* + ** PNAME + */ + if(select&BTEXTUR) + { if(NeedPNAME) /*write PNAME in PWAD*/ + { /*write entry PNAME*/ + Phase("Making Pnames\n"); + WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + size =PNMwritePNAMEtoWAD(&rwad); + WADRdirAddEntry(&rwad,start,size,"PNAMES"); + } + } + /* + ** + ** sounds. all sounds entries + */ + if(select&BSOUND) + { start=size=0; + if(TXTseekSection(TXT,"SOUNDS")) + { Phase("Making Sounds\n"); + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if(Repeat!=TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"TXT")==TRUE) + { size=SNDcopyPCSoundInWAD(&rwad,file); + Detail("Read PC Sound as file %s\n",file); + } + else + { if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"WAV")==TRUE) + { size=SNDcopyInWAD(&rwad,file,SNDWAV); + } + else if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"AU")==TRUE) + { size=SNDcopyInWAD(&rwad,file,SNDAU); + } + else if(MakeFileName(file,DataDir,"SOUNDS","",filenam,"VOC")==TRUE) + { size=SNDcopyInWAD(&rwad,file,SNDVOC); + } + else if(CMPOcopyFromWAD(&size,&rwad,DataDir,"SOUNDS",name,filenam)!=TRUE) + ProgError("Can't find Sound %s, AU or WAV or WAD",file); + Detail("Read Sound in file %s\n",file); + } + } + WADRdirAddEntry(&rwad,start,size,name); + } + } + } + /* + ** + ** Musics + */ + if(select&BMUSIC) + { start=size=0; + if(TXTseekSection(TXT,"MUSICS")) + { Phase("Making Musics\n"); + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if(Repeat!=TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + /*Music*/ + if(MakeFileName(file,DataDir,"MUSICS","",filenam,"MUS")==TRUE) + { size=WADRwriteLump(&rwad,file); + Detail("Read Music as MUS file %s\n",file); + } + else if(CMPOcopyFromWAD(&size,&rwad,DataDir,"MUSICS",name,filenam)!=TRUE) + ProgError("Can't find Music %s",file); + } + WADRdirAddEntry(&rwad,start,size,name); + } + } + } + /* + ** ordinary graphics + */ + if(select&BGRAPHIC) + { start=size=0; + if(TXTseekSection(TXT,"GRAPHICS")) + { Phase("Making Graphics\n"); + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) + { if(Repeat!=TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + Picture=CMPOloadPic(&size,&rwad,file,DataDir,"GRAPHICS",name,filenam,PGRAPH,X,Y); + } + WADRdirAddEntry(&rwad,start,size,name); + } + } + } + /* + ** SS_START + ** sprites + ** SS_END + */ + if(select&BSPRITE) + { start=size=0; + if(TXTseekSection(TXT,"SPRITES")) + { Phase("Making Sprites\n"); + FoundOne=FALSE; + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) + { /* first sprite seen? */ + if((Repeat!=TRUE)||(FoundOne!=TRUE)) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(FoundOne!=TRUE) + { if(type==IWAD) + WADRdirAddEntry(&rwad,start,0L,"S_START"); + else + WADRdirAddEntry(&rwad,start,0L,"SS_START"); + } + FoundOne=TRUE; + CMPOloadPic(&size,&rwad,file,DataDir,"SPRITES",name,filenam,PSPRIT,X,Y); + } + WADRdirAddEntry(&rwad,start,size,name); + } + if(FoundOne==TRUE) + { WADRalign4(&rwad); + start=WADRposition(&rwad); + if((type==IWAD)||(George==TRUE)) + WADRdirAddEntry(&rwad,start,0L,"S_END"); + else + WADRdirAddEntry(&rwad,start,0L,"SS_END"); + } + } + } + /* + ** Try to load WALL patches + ** even if no new textures (old patches could be redefined) + */ + /* write new patches in PWAD*/ + /* read the name of the new textures and insert them*/ + /* between P_START and P_END for future completion*/ + + if(select&BPATCH) + { FoundOne=FALSE; + /* + ** First look for patches in [PATCHES] + */ + start=size=0; + if(TXTseekSection(TXT,"PATCHES")) + { Phase("Making Wall Patches\n"); + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE)==TRUE) + { if((Repeat!=TRUE)||(FoundOne!=TRUE)) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(FoundOne==FALSE) + { if(type==IWAD) + { WADRdirAddEntry(&rwad,start,0L,"P_START"); + WADRdirAddEntry(&rwad,start,0L,"P1_START"); + } + else + WADRdirAddEntry(&rwad,start,0L,"PP_START"); + } + FoundOne=TRUE; + CMPOloadPic(&size,&rwad,file,DataDir,"PATCHES",name,filenam,PPATCH,X,Y); + } + WADRdirAddEntry(&rwad,start,size,name); + } + } + /* + ** Check if all the needed patches are defined. + */ + nbPatchs=PNMgetNbOfPatch(); + for(p=0;p=0) + { Output("Reusing DOOM entry %.8s as patch\n",name); + } + /*search in current PWAD*/ + else if(WADRfindEntry(&rwad,name)<0) + { /*PATCH not found in current WAD, load automatically + **from the PATCH directory + */ + WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + Picture=CMPOloadPic(&size,&rwad,file,DataDir,"PATCHES",name,filenam,PPATCH,INVALIDINT,INVALIDINT); + if(Picture!=PICNONE) + { if(FoundOne==FALSE) + { Phase("Making Wall Patches\n"); + if(type==IWAD) + { WADRdirAddEntry(&rwad,start,0L,"P_START"); + WADRdirAddEntry(&rwad,start,0L,"P1_START"); + } + else + WADRdirAddEntry(&rwad,start,0L,"PP_START"); + } + FoundOne=TRUE; + WADRdirAddEntry(&rwad,start,size,name); + } + } + } + if(FoundOne==TRUE) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(type==IWAD) + { WADRdirAddEntry(&rwad,start,0L,"P1_END"); + WADRdirAddEntry(&rwad,start,0L,"P2_START"); + WADRdirAddEntry(&rwad,start,0L,"P2_END"); + WADRdirAddEntry(&rwad,start,0L,"P3_START"); + WADRdirAddEntry(&rwad,start,0L,"P3_END"); + WADRdirAddEntry(&rwad,start,0L,"P_END"); + } + else + WADRdirAddEntry(&rwad,start,0L,"PP_END"); + } + } + /* + ** clear off Pnames + */ + if(select&(BTEXTUR|BPATCH)) + { PNMfree(); + } + /* FF_START + ** Flats + ** F_END AYM 1998-12-22 (was FF_END) + */ + if(select&BFLAT) + { if(TXTseekSection(TXT,"FLATS")) + { Phase("Making Flats\n"); + FoundOne=FALSE; + while(TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,FALSE)==TRUE) + { if((Repeat!=TRUE)||(FoundOne!=TRUE)) + { WADRalign4(&rwad); /*align entry on Int32 word*/ + start=WADRposition(&rwad); + if(FoundOne==FALSE) + { if(type==IWAD) + { WADRdirAddEntry(&rwad,start,0L,"F_START"); + WADRdirAddEntry(&rwad,start,0L,"F1_START"); + } + else + WADRdirAddEntry(&rwad,start,0L,"FF_START"); + } + FoundOne=TRUE; + CMPOloadPic(&size,&rwad,file,DataDir,"FLATS",name,filenam,PFLAT,INVALIDINT,INVALIDINT); + } + WADRdirAddEntry(&rwad,start,size,name); + } + if(FoundOne==TRUE) + { start=WADRposition(&rwad); + if(type==IWAD) + { WADRdirAddEntry(&rwad,start,0L,"F1_END"); + WADRdirAddEntry(&rwad,start,0L,"F2_START"); + WADRdirAddEntry(&rwad,start,0L,"F2_END"); + WADRdirAddEntry(&rwad,start,0L,"F3_START"); + WADRdirAddEntry(&rwad,start,0L,"F3_END"); + WADRdirAddEntry(&rwad,start,0L,"F_END"); + } + else + WADRdirAddEntry(&rwad,start,0L,"F_END"); /* AYM 1998-12-22 */ + } + } + } + /* + ** exit from graphic + */ + if(select&(BGRAPHIC|BSPRITE|BPATCH|BFLAT)) COLfree(); + /* + ** iwad not needed anymore + */ + WADRclose(&iwad); + /* + ** the end + */ + TXTcloseR(TXT); + WADRwriteDir(&rwad); /* write the WAD directory */ + ProgErrorCancel(); + WADRclose(&rwad); + /*add some junk at end of wad file, for DEU 5.21*/ + if(type==PWAD) AddSomeJunk(PWADname); +} + + + + + + + + + +/***************** Hack the IWAD *********************/ +extern Int16 HowMuchJunk; +static char Junk[]="*** This junk is here for DEU 5.21. I am repeating myself anyway.... ********"; +static void AddSomeJunk(char *file) +{ FILE *out;Int16 n; + out=fopen(file,FOPEN_AB); /*open R/W at the end*/ + if(out==NULL) ProgError("Can't write file %s\n",file); + for(n=0;n +#include "tools.h" +#include "mkwad.h" +#include "merge.h" +#include "extract.h" +#include "wadio.h" +#include "picture.h" + + +/*compile only for DeuTex*/ +#if (defined DeuTex)||(defined DeuSF) + + +/* +** global variables for commands +*/ +char file[128]; /* general use file name*/ + +static WADTYPE Type; /*IWAD type*/ +static NTRYB Select; + +static char *DataDir=NULL; +static char *DoomDir=NULL; +static char MainWAD[128]; /* name of the main wad file */ +#if defined DeuTex +static char WadInf[128]; /* name of the wadinfo file */ +static Bool WadInfOk; +Int16 HowMuchJunk; /* junk to add*/ +static IMGTYPE Picture; /* save as PPM, BMP or GIF ? */ +static SNDTYPE Sound; /* save as WAV, VOC or AU ? */ +static Bool fullSND; +static Bool WSafe; +static Bool George; +#endif /*DeuTex*/ +char trnR,trnG,trnB; + + +static int is_prefix (const char *s1, const char *s2); + + +/* +** commands +*/ +void COMhelp(int argc, char **argv); +void COMmanopt(int argc, char **argv); +void COMformat(int argc, char **argv); +/* +** WinTex comand line replaces +** -out +** -v3 +** -doom doom directory +** -dir data directory +** -sel select byte +** -colRrGgBb red = (R-'A')*16+(r-'A') +*/ +#if defined DeuTex +void COMwintxn(int argc, char **argv) +{ char *num; + PrintInit(TRUE); /*-out*/ + PrintVerbosity(3); /*-v3*/ + DoomDir=argv[1]; /*doom*/ + DataDir=argv[2]; /*data*/ + MakeFileName(WadInf,DataDir,"","",argv[3],"TXT"); + WadInfOk=TRUE; + Select|= atoi(argv[4]); /*select*/ + num = argv[5]; /*colour*/ + if(strlen(num)<6) ProgError("Bad Color"); + trnR= (((num[0]&0xF)<<4)+(num[1]&0xF))&0xFF; + trnG= (((num[2]&0xF)<<4)+(num[3]&0xF))&0xFF; + trnB= (((num[4]&0xF)<<4)+(num[5]&0xF))&0xFF; + Info("Transparent colour is R=%d G=%d B=%d\n", + ((int)trnR&0xFF),((int)trnG&0xFF),((int)trnB&0xFF)); + (void)argc; +} +void COMwintxm(int argc, char **argv) +{ PrintInit(TRUE); /*-out*/ + PrintVerbosity(3); /*-v3*/ + DoomDir=argv[1]; /*doom*/ + DataDir="."; + Select|= atoi(argv[2]); /*select*/ + trnR= 0;trnG= 255;trnB= 255; + (void)argc; +} +#endif /*DeuTex*/ +void COMwintex(int argc, char **argv) +{ PrintInit(TRUE); /*-out*/ + PrintVerbosity(3); /*-v3*/ + DoomDir=NULL; + strncpy(MainWAD,argv[1],128);/*main*/ + DataDir="."; + Select|= BALL; /*select*/ + trnR= 0;trnG= 255;trnB= 255; + (void)argc; +} +void COMverbose(int argc, char **argv) +{ PrintVerbosity(argv[0][2]-'0'); + Info("Verbosity level is %c.\n",argv[0][2]); + (void)argc; +} +void COMdoom(int argc, char **argv) +{ DoomDir=argv[1]; + Info("Main directory: %s.\n",DoomDir); + (void)argc; +} +void COMmain(int argc, char **argv) +{ DoomDir=NULL; + strncpy(MainWAD,argv[1],128); + Info("Main IWAD file: %s.\n",MainWAD); + (void)argc; +} +void COMwadir(int argc, char **argv) +{ XTRlistDir(MainWAD,((argc<2)? NULL: argv[1]),Select); +} +void COMadd(int argc, char **argv) +{ ADDallSpriteFloor(argv[2],MainWAD,argv[1],Select); + (void)argc; +} +void COMapp(int argc, char **argv) +{ ADDappendSpriteFloor(MainWAD,argv[1],Select); + (void)argc; +} +void COMapps(int argc, char **argv) +{ Select= (BALL) & (~BFLAT); /*no flats*/ + ADDappendSpriteFloor(MainWAD,argv[1],Select); + (void)argc; +} +void COMappf(int argc, char **argv) +{ Select= (BALL) & (~BSPRITE); /*no sprites*/ + ADDappendSpriteFloor(MainWAD,argv[1],Select); + (void)argc; +} +void COMjoin(int argc, char **argv) +{ ADDjoinWads(MainWAD,argv[1],argv[2],Select); + (void)argc; +} +void COMmerge(int argc, char **argv) +{ Select = BALL; + PSTmergeWAD(MainWAD,argv[1],Select); + (void)argc; +} +void COMrestor(int argc, char **argv) +{ HDRrestoreWAD((argc>=2)? argv[1]:MainWAD); +} + + +#if defined DeuSF +/* +** Selections +*/ +void COMsprit(int argc, char **argv) +{ Select&= ~BFLAT; + Info("Select SPRITES\n"); + (void)argc;(void)argv; +} +void COMflat(int argc, char **argv) +{ Select&= ~BSPRITE; + Info("Select FLATS\n"); + (void)argc;(void)argv; +} +#endif /*DeuSF*/ +#if defined DeuTex +/* +** Selections +*/ +void COMsprit(int argc, char **argv) +{ Select|=BSPRITE; + Info("Select SPRITES\n"); + (void)argc;(void)argv; +} +void COMflat(int argc, char **argv) +{ Select|=BFLAT; + Info("Select FLATS\n"); + (void)argc;(void)argv; +} +void COMlevel(int argc, char **argv) +{ Select|=BLEVEL; + Info("Select LEVELS\n"); + (void)argc;(void)argv; +} +void COMlump(int argc, char **argv) +{ Select|=BLUMP; + Info("Select LUMPS\n"); + (void)argc;(void)argv; +} +void COMtextur(int argc, char **argv) +{ Select|=BTEXTUR; + Info("Select TEXTURES\n"); + (void)argc;(void)argv; +} +void COMsound(int argc, char **argv) +{ Select|=BSOUND; + Info("Select SOUNDS\n"); + (void)argc;(void)argv; +} +void COMmusic(int argc, char **argv) +{ Select|=BMUSIC; + Info("Select MUSICS\n"); + (void)argc;(void)argv; +} +void COMgraphic(int argc, char **argv) +{ Select|=BGRAPHIC; + Info("Select GRAPHICS\n"); + (void)argc;(void)argv; +} +void COMpatch(int argc, char **argv) +{ Select|=BPATCH; + Info("Select PATCHES\n"); + (void)argc;(void)argv; +} +void COMgeorge(int argc, char **argv) +{ George=TRUE; + Info("Use S_END for sprites.\n"); + (void)argc;(void)argv; +} + + +void PicDebug(char *file,char *DataDir,char *name); + + +void COMdebug(int argc, char **argv) +{ +#if 1 +#include "color.h" + static struct WADINFO iwad; + Int16 pnm; + char huge *Colors; Int32 Pnamsz=0; + iwad.ok=0; + WADRopenR(&iwad,MainWAD); + pnm=WADRfindEntry(&iwad,"PLAYPAL"); + if(pnm<0) ProgError("Can't find PLAYPAL in Main WAD"); + Colors=WADRreadEntry(&iwad,pnm,&Pnamsz); + COLinit(trnR,trnG,trnB,Colors,(Int16)Pnamsz); + Free(Colors); + WADRclose(&iwad); + PicDebug(file,DataDir,(argc<2)? "test":argv[1]); + COLfree(); +#endif + (void)argc;(void)argv; +} +void COMdeu(int argc, char **argv) +{ HowMuchJunk=MAXJUNK64; + Info("Some junk will be added at end of WAD, for DEU 5.21.\n"); + (void)argc;(void)argv; +} +void COMdir(int argc, char **argv) +{ DataDir=argv[1]; + Info("Files will be saved in directory %s.\n",DataDir); + (void)argc; +} +void COMfullsnd(int argc, char **argv) +{ fullSND=TRUE; + Info("Saving complete sounds.\n"); + (void)argc;(void)argv; +} +void COMstroy(int argc, char **argv) +{ WSafe=FALSE; + Info("Overwrite existing files.\n"); + if(argc)(void)argv; +} +void COMgif(int argc, char **argv) +{ Picture=PICGIF; + Info("Saving pictures as GIF (.gif)\n"); + (void)argc;(void)argv; +} +void COMbmp(int argc, char **argv) +{ Picture=PICBMP; + Info("Saving pictures as BMP (.bmp)\n"); + (void)argc;(void)argv; +} +void COMppm(int argc, char **argv) +{ Picture=PICPPM; + Info("Saving pictures as rawbits (P6) PPM (.ppm)\n"); + (void)argc;(void)argv; +} +void COMau(int argc, char **argv) +{ Sound=SNDAU; + Info("Save sounds as Sun audio (.au)\n"); + (void)argc;(void)argv; +} +void COMwave(int argc, char **argv) +{ Sound=SNDWAV; + Info("Save sounds as wave (.wav)\n"); + (void)argc;(void)argv; +} +void COMvoc(int argc, char **argv) +{ Sound=SNDVOC; + Info("Save sounds as voc (.voc)\n"); + (void)argc;(void)argv; +} +void COMrgb(int argc, char **argv) +{ trnR=(char)(atoi(argv[1])&0xFF); + trnG=(char)(atoi(argv[2])&0xFF); + trnB=(char)(atoi(argv[3])&0xFF); + Info("Transparent colour is R=%d G=%d B=%d\n", + ((int)trnR&0xFF),((int)trnG&0xFF),((int)trnB&0xFF)); + (void)argc; +} + +void COMle (int argc, char **argv) +{ + set_input_wad_endianness (0); + set_output_wad_endianness (0); + (void) argc; + (void) argv; +} + +void COMbe (int argc, char **argv) +{ + set_input_wad_endianness (1); + set_output_wad_endianness (1); + (void) argc; + (void) argv; +} + +void COMile (int argc, char **argv) +{ + set_input_wad_endianness (0); + (void) argc; + (void) argv; +} + +void COMibe (int argc, char **argv) +{ + set_input_wad_endianness (1); + (void) argc; + (void) argv; +} + +void COMole (int argc, char **argv) +{ + set_output_wad_endianness (0); + (void) argc; + (void) argv; +} + +void COMobe (int argc, char **argv) +{ + set_output_wad_endianness (1); + (void) argc; + (void) argv; +} + +void COMpf (int argc, char **argv) +{ + if (argc == 2 && ! strcmp (argv[1], "alpha")) + picture_format = PF_ALPHA; + else if (argc == 2 && ! strcmp (argv[1], "normal")) + picture_format = PF_NORMAL; + else + ProgError ("Usage is \"-pf {normal|alpha}\""); +} + +/* +** Build an IWAD +** +*/ +void COMiwad(int argc, char **argv) +{ Type=IWAD; + Info("Build an IWAD file.\n"); + (void)argc;(void)argv; +} +/* +** Main Commands +** +*/ + +void COMmake(int argc, char **argv) +{ char *wadinf,*wadout; + if(WadInfOk==FALSE) + { MakeFileName(WadInf,DataDir,"","","WADINFO","TXT"); + } + if(argc<=2){wadinf=WadInf;wadout=argv[1];} + else {wadinf=argv[1];wadout=argv[2];} + CMPOmakePWAD(MainWAD,Type,wadout,DataDir,wadinf,Select,trnR,trnG,trnB,George); + (void)argc; +} +void COMxtra(int argc, char **argv) +{ char *wadinf, *wadin; + if(WadInfOk==FALSE) + { MakeFileName(WadInf,DataDir,"","","WADINFO","TXT"); + } + if(argc<=1){wadin=MainWAD;}else{wadin=argv[1];} + if(argc<=2){wadinf=WadInf;}else{wadinf=argv[2];} + XTRextractWAD(MainWAD,DataDir,wadin,wadinf,Picture,Sound,fullSND,Select,trnR,trnG,trnB,WSafe); +} +void COMget(int argc, char **argv) +{ XTRgetEntry(MainWAD,DataDir,((argc<3)? MainWAD: argv[2]),argv[1],Picture,Sound,fullSND,trnR,trnG,trnB); +} +void COMpackNorm(int argc, char **argv) +{ XTRcompakWAD(DataDir,(argc>1)? argv[1]: MainWAD,(argc>2)? argv[2]:NULL,FALSE); +} +void COMpackGfx(int argc, char **argv) +{ XTRcompakWAD(DataDir,(argc>1)? argv[1]: MainWAD,(argc>2)? argv[2]:NULL,TRUE); +} +void COMvoid(int argc, char **argv) +{ XTRvoidSpacesInWAD(argv[1]); + (void)argc; +} +void COMusedtex(int argc, char **argv) +{ XTRtextureUsed((argc>1)? argv[1]: MainWAD); +} +#endif /*DeuTex*/ + +void COMcheck(int argc, char **argv) +{ XTRstructureTest(MainWAD,argv[1]); + (void)argc; +} + + +typedef char COMTYPE; +#define END 1 +#define NIL 2 +#define OPT 3 +#define CMD 4 +typedef struct +{ COMTYPE type; + char argc; + char *com; + void (*exec)(int argc, char **argv); + char *use; + char *help; +} comdef_t; + +static comdef_t Com[]= +{ + {NIL,0,"?", COMhelp, NULL, "print list of options"}, + {NIL,0,"h", COMhelp, NULL, NULL}, + {NIL,0,"help", COMhelp, NULL, NULL}, + {NIL,0,"-help", COMhelp, NULL, NULL}, +#ifdef DeuTex + {NIL,0,"man", COMmanopt, NULL, "print list of options in troff -man format"}, +#endif + {NIL,0,"-version", NULL, NULL, "print version number"}, + {NIL,0,"syntax", COMformat, NULL, "print the syntax of wad creation directives"}, +#if defined DeuTex + {OPT,5,"win", COMwintxn, " ","WinTex shortcut"}, + {CMD,0,"debug", COMdebug, NULL, "Debug mode"}, + {OPT,0,"overwrite",COMstroy, NULL, "overwrite all"}, +#endif /*DeuTex*/ + {OPT,1,"wtx", COMwintex, "","WinTex shortcut"}, + {OPT,1,"doom", COMdoom, "","indicate the directory of Doom/Doom II"}, + {OPT,1,"heretic", COMdoom, "","indicate the directory of Heretic"}, + {OPT,1,"hexen", COMdoom, "","indicate the directory of Hexen"}, + {OPT,1,"strife", COMdoom, "","indicate the directory of Strife"}, +#if defined DeuTex + {OPT,1,"dir", COMdir, "","indicate the working directory"}, + {OPT,0,"deu", COMdeu, NULL, "add 64k of junk to workaround a bug of DEU 5.21"}, + + {OPT,3,"rgb", COMrgb, " ","specify the transparent colour (default 0/47/47)"}, + {OPT,0,"gif", COMgif, NULL, "save pictures as GIF (.gif)"}, + {OPT,0,"bmp", COMbmp, NULL, "save pictures as BMP (.bmp)"}, + {OPT,0,"ppm", COMppm, NULL, "save pictures as rawbits (P6) PPM (.ppm)"}, + {OPT,0,"au", COMau, NULL, "save sound as Sun audio (.au)"}, + {OPT,0,"wav", COMwave, NULL, "save sound as wave (.wav)"}, + {OPT,0,"voc", COMvoc, NULL, "save sound as voc (.voc)"}, + {OPT,0,"fullsnd", COMfullsnd,NULL, "save sound lumps beyond declared length"}, + + {OPT,0,"levels", COMlevel, NULL, "select levels"}, + {OPT,0,"lumps", COMlump , NULL, "select lumps"}, + {OPT,0,"sounds", COMsound, NULL, "select sounds"}, + {OPT,0,"musics", COMmusic, NULL, "select musics"}, + {OPT,0,"textures", COMtextur, NULL, "select textures"}, + {OPT,0,"graphics", COMgraphic,NULL, "select graphics"}, + /*by request from George Hamlin*/ + {OPT,0,"s_end", COMgeorge, NULL, "use S_END for sprites, not SS_END"}, + {OPT,0,"george", COMgeorge, NULL, NULL}, +#endif /*DeuTex*/ + {OPT,0,"sprites", COMsprit, NULL, "select sprites"}, +#if defined DeuTex + {OPT,0,"patches", COMpatch, NULL, "select patches"}, +#endif /*DeuTex*/ + {OPT,0,"flats", COMflat, NULL, "select flats"}, + {OPT,0,"v0", COMverbose,NULL, "set verbosity level to 0"}, + {OPT,0,"v1", COMverbose,NULL, "set verbosity level to 1"}, + {OPT,0,"v2", COMverbose,NULL, "set verbosity level to 2"}, + {OPT,0,"v3", COMverbose,NULL, "set verbosity level to 3"}, + {OPT,0,"v4", COMverbose,NULL, "set verbosity level to 4"}, + {OPT,0,"v5", COMverbose,NULL, "set verbosity level to 5"}, +#if defined DeuTex + {OPT,0,"be", COMbe, NULL, "assume all wads are big endian (default LE)"}, + {OPT,0,"le", COMle, NULL, "assume all wads are little endian (default)"}, + {OPT,0,"ibe", COMibe, NULL, "input wads are big endian (default LE)"}, + {OPT,0,"ile", COMile, NULL, "input wads are little endian (default)"}, + {OPT,0,"obe", COMobe, NULL, "create big endian wads (default LE)"}, + {OPT,0,"ole", COMole, NULL, "create little endian wads (default)"}, + {OPT,1,"pf", COMpf, "{normal|alpha}", "picture format (default is \"normal\")"}, +#endif /* DeuTex */ + +#if defined DeuTex + {OPT,0,"iwad", COMiwad, NULL, "compose iwad, not pwad"}, + + {CMD,1,"make", COMmake, "[] ","make a pwad, from the creation directives"}, + {CMD,1,"build", COMmake, "[] ",NULL}, + {CMD,1,"create", COMmake, "[] ",NULL}, +#endif /*DeuTex*/ + +#if defined DeuSF + {OPT,1,"main", COMmain, NULL, "Indicate main wad"}, +#endif + {CMD,0,"wadir", COMwadir, "","list and identify entries in a wad"}, + {CMD,1,"check", COMcheck, "","check the textures"}, + {CMD,1,"test", COMcheck, "",NULL}, +#if defined DeuTex + {CMD,0,"usedtex", COMusedtex,"","list textures used in all levels"}, + {NIL,1,"unused", COMvoid, "","find unused spaces in a wad"}, + {CMD,0,"xtract", COMxtra, " []","extract some/all entries from a wad"}, + {CMD,0,"extract", COMxtra, " []",NULL}, + {CMD,1,"get", COMget, " []","get a wad entry from main wad or in.wad"}, + {CMD,1,"pknormal", COMpackNorm," []","Detect identical normal"}, + {CMD,1,"pkgfx", COMpackGfx," []","Detect identical graphics"}, +#endif /*DeuTex*/ + + {CMD,2,"add", COMadd, " ","add sprites & flats of a pwad to those of Doom"}, + {CMD,1,"append", COMapp, "","append sprites & flats of Doom to a pwad"}, + {CMD,2,"join", COMjoin, " ","append sprites & flats of Doom to a pwad"}, + {CMD,1,"merge", COMmerge, "","merge doom.wad and a pwad"}, + {CMD,0,"restore", COMrestor, NULL, "restore doom.wad and the pwad"}, + {CMD,1,"as", COMapps, "","append all sprites to the wad"}, + {CMD,1,"af", COMappf, "","append all floors/ceilings to the wad"}, + {END,0,"", COMhelp, NULL, ""} +}; + +int main( int argc, char **argv) +{ char c; + FILE *fp; + + /* Options for which you don't want the banners */ + if (argc == 2 && ! strcmp (argv[1], "--version")) + { + printf ("%s %s\n", DEUTEXNAME, deutex_version); + return 0; + } +#ifdef DeuTex + if (argc == 2 && ! strcmp (argv[1], "-man")) /* Sorry for the ugliness */ + { + COMmanopt (argc, argv); + return 0; + } +#endif +#ifdef DT_ALPHA + printf ( + "+-----------------------------------------------------------+\n" + "| THIS IS ALPHA SOFTWARE. DON'T EXPECT IT TO COMPILE OR |\n" + "| RUN SMOOTHLY. DON'T EXPECT THE DOCUMENTATION TO BE |\n" + "| ACCURATE OR UP TO DATE. THERE MIGHT BE SERIOUS BUGS. |\n" + "| MAKE BACKUP COPIES OF YOUR DATA. |\n" + "+-----------------------------------------------------------+\n\n"); +#endif + printf ( + "+---------------------------------------------------+\n" + "| Send questions and bug reports to the current |\n" + "| maintainer, Andr� Majorel , |\n" + "| NOT to Olivier Montanuy ! |\n" + "+---------------------------------------------------+\n\n"); + + /* Sanity checks */ + check_types (); + + /* + ** default parameters + */ +#if defined DeuTex + WadInfOk=FALSE; + George=FALSE; +#if DT_OS == 'd' + Picture = PICBMP; + Sound = SNDWAV; +#elif DT_OS == 'o' + Picture = PICBMP; + Sound = SNDWAV; +#else /*Unix*/ + Picture = PICPPM; + Sound = SNDAU; +#endif + trnR=0;trnG=47;trnB=47; + fullSND = FALSE; + WSafe = TRUE; + HowMuchJunk= 0; + Select = 0; +#endif /*DeuTex*/ +#if defined DeuSF + Select = BALL; +#endif /*DeuSF*/ + Type = PWAD; + + ProgErrorCancel();/*no error handler defined*/ + +#if defined __OS2__ || defined (__GNUC__) + /*setbuf(stdout,(char *)NULL);*/ + setvbuf(stdout,NULL,_IOLBF,BUFSIZ); +#endif /*OS2*/ + /* + ** print on screen or file? + */ + PrintInit(FALSE); + PrintVerbosity(2); + /* + ** copyright notice + */ + PrintCopyright(); + /* + ** directories + */ + DataDir = "."; /*work directory*/ + DoomDir = getenv("DOOMWADDIR"); + if(DoomDir == NULL) + DoomDir = "."; + else + Phase("Doom directory is %.128s\n",DoomDir); + /* + ** Command line + */ + argc--;argv++; + if(argc>30) ProgError("too many arguments"); + + /* Parse the command line from left to right. + Try to match the each argument against the + longest possible option defined. */ + while(argc>0) + { const comdef_t *d = Com + sizeof Com / sizeof *Com - 1; + const char *arg = *argv; + if (*arg != '-') + ProgError("Argument \"%s\": expected an option", arg); + arg++; + + { + const comdef_t *w; + for (w = Com; w->type != END; w++) + { + if (is_prefix (arg, w->com)) + { + if (! strcmp (arg, w->com)) /* Exact match. */ + { + d = w; + goto got_it; + } + if (d->type != END) /* Ambiguous partial match. */ + ProgError ("\"-%s\" is ambiguous (-%s, -%s)", arg, d->com, w->com); + /* Unambiguous partial match. */ + d = w; + } + } + } +got_it: + + if (argc - 1 < d->argc) + ProgError("Usage: %s%s%s", + d->com, + d->use ? " " : "", + d->use ? d->use : ""); + switch(d->type) + { case END: + ProgError("Option %s is not defined.",argv[0]); + PrintExit(); + return 0; + case NIL: + d->exec(argc,argv); + PrintExit(); + return 0; + case OPT: + d->exec(argc,argv); + break; + case CMD: + /*find DOOM,HERETIC*/ + if(DoomDir==NULL) + { /* + ** check if file exists + */ + fp=fopen(MainWAD,FOPEN_RB); + if(fp!=NULL) + fclose(fp); /* AYM 1999-01-13 once again, the code assumed + that calling fclose with a NULL pointer is + a normal thing to do. */ + if(fp==NULL) DoomDir="."; + } + if(DoomDir!=NULL) + { /* + ** look for main wad + */ + if( MakeFileName(MainWAD,DoomDir,"","","doom","wad")!=TRUE + && MakeFileName(MainWAD,DoomDir,"","","doom2","wad")!=TRUE + && MakeFileName(MainWAD,DoomDir,"","","heretic","wad")!=TRUE + && MakeFileName(MainWAD,DoomDir,"","","hexen","wad")!=TRUE + && MakeFileName(MainWAD,DoomDir,"","","strife1","wad")!=TRUE + && MakeFileName(MainWAD,".", "","","doom","wad")!=TRUE + && MakeFileName(MainWAD,".", "","","doom2","wad")!=TRUE + && MakeFileName(MainWAD,".", "","","heretic","wad")!=TRUE + && MakeFileName(MainWAD,".", "","","hexen","wad")!=TRUE + && MakeFileName(MainWAD,".", "","","strife1","wad")!=TRUE) + ProgError("Can't find any of doom.wad, doom2.wad, heretic.wad," + " hexen.wad, strife1.wad"); + } + /*selection bytes*/ +#if defined DeuTex + if(!(Select&BALL)) Select = BALL; + if (Picture == PICGIF) + Warning ("GIF support may go away in the future." + " Use PPM or BMP instead."); +#endif /*DeuTex*/ + d->exec(argc,argv); + PrintExit(); + return 0; + } + argv += d->argc + 1; + argc -= d->argc + 1; + } + NoCommandGiven(); + PrintExit(); + return -1; +} + + + + +/* +** Print Help +*/ +#define COLUMN1_WIDTH 22 +void COMhelp(int argc, char **argv) +{ const comdef_t *d; + Output("Help for %s:\n",DEUTEXNAME); + for(d = Com; d->type != END; d++) + { + char buf[200]; + sprintf (buf, "-%s", d->com); + if (d->use) + { + strcat (buf, " "); + strcat (buf, d->use); + } + if (strlen (buf) > COLUMN1_WIDTH) + Output ("%s\n%*s ", buf, COLUMN1_WIDTH, ""); + else + Output("%-*s ", COLUMN1_WIDTH, buf); + Output ("%s", d->type == OPT ? "(opt.) " : ""); + if (d->help) + Output ("%c%s.", toupper (d->help[0]), d->help + 1); + else + Output ("Same as above."); + putchar ('\n'); + } + (void)argc;(void)argv; +} + +#if defined DeuTex +static char *Format[] = +{ "* Format of PWAD creation directives *", + "This format is conform to MS-Windows .INI Files.", + "Sections are named [LEVELS] [LUMPS] [SOUNDS]", + "[MUSICS] [TEXTURE1] [TEXTURE2] [GRAPHICS]", + "[SPRITES] [PATCHES] and [FLATS]", + "Entries have format:", + "{name}= {filename} {offsetX} {offsetY}", + "A '*' at the end of the definition means that the", + "entry will be exactly the same as the previous one.", + NULL +}; +#endif /*DeuTex*/ +#if defined DeuSF +static char *Format[] = +{ "To work with this progam, your PWAD must respect this format:", + "- Either S_START or SS_START before the first SPRITE entry", + "- Either S_END or SS_END after the last SPRITE entry", + "- Either F_START or FF_START before the first FLAT entry", + "- Either F_END or FF_END after the last FLAT entry", + "This format has been found compatible with DMADDS 1.0.", + "Warning:", + "Flats declared in PWAD will be put at the end of the FLAT list.", + "You can completely replace an animation of FLATs, but you cannot", + "replace only part of an animation.", + NULL +}; +#endif /*DeuSF*/ +void COMformat(int argc, char **argv) +{ int i; + for(i=0;Format[i]!=NULL;i++) + { Output("%s\n",Format[i]); + } + (void)argc;(void)argv; +} + + +/* + * COMmanopt + * List options like COMhelp but in troff -man source format. + */ +#ifdef DeuTex +static char stack[10]; + +static void spush (char c) +{ + if (strlen (stack) + 1 >= sizeof stack) + return; + stack[strlen (stack) + 1] = '\0'; + stack[strlen (stack)] = c; +} + + +#if 0 +static char speektop (void) +{ + if (! *stack) + return '\0'; + return stack[strlen (stack) - 1]; +} +#endif + + +static char spop (void) +{ + char c; + if (! *stack) + return '\0'; + c = stack[strlen (stack) - 1]; + stack[strlen (stack) - 1] = '\0'; + return c; +} + + +static char last_font; +static char troff_stack[10]; + +static void troff_start (void) +{ + last_font = '\0'; + *troff_stack = '\0'; +} + + +static void troff_end (void) +{ + if (last_font) + fputs ("\\fP", stdout); + last_font = '\0'; +} + + +static void troff_push (char font) +{ + if (strlen (troff_stack) + 1 >= sizeof troff_stack) + return; + troff_stack[strlen (troff_stack) + 1] = '\0'; + troff_stack[strlen (troff_stack)] = font; +} + + +static void troff_pop (void) +{ + if (! *troff_stack) + return; + troff_stack[strlen (troff_stack) - 1] = '\0'; +} + + +static char troff_tos (void) +{ + if (! *troff_stack) + return '\0'; + return troff_stack[strlen (troff_stack) - 1]; +} + + +static void troff_putc (char c/*, char font*/) +{ + if (troff_tos () && troff_tos () != last_font) + { + if (last_font) + fputs ("\\fP", stdout); + fprintf (stdout, "\\f%c", troff_tos ()); + last_font = troff_tos (); + } + fputc (c, stdout); +} + + +static void troff_puts (const char *s/*, char font*/) +{ + if (troff_tos () && troff_tos () != last_font) + { + if (last_font) + fputs ("\\fP", stdout); + fprintf (stdout, "\\f%c", troff_tos ()); + last_font = troff_tos (); + } + fputs (s, stdout); +} + + +void COMmanopt(int argc, char **argv) +{ const comdef_t *d; + for (d = Com; d->type != END; d++) + { + const char *p = d->use; + *stack = '\0'; + troff_start (); + troff_puts (".TP 14\n"); + + /* Print the option name in bold */ + troff_push ('B'); + troff_puts ("\\-"); + troff_puts (d->com); + troff_pop (); + if (p) + troff_putc (' '); + + /* Print the arguments. What's between < > is in italic, + [ ] { | } are in normal roman, the rest is in bold. */ + if (p) + while (*p) /* Print one arg. for each iteration */ + { + if (isspace (*p)) + troff_putc (' '); + while (isspace (*p)) + p++; + troff_push ('B'); + for (; *p && *p != ' '; p++) + { + if (*p == '[' || *p == '{') + { + spush (*p); + troff_push ('R'); + troff_putc (*p); + troff_pop (); + } + else if (*p == '<') + { + spush (*p); + troff_push ('I'); + } + else if (*p == ']' || *p == '}') + { + spop (); + troff_push ('R'); + troff_putc (*p); + troff_pop (); + } + else if (*p == '>') + { + spop (); + troff_pop (); + } + else if (*p == '|') + { + troff_push ('R'); + troff_putc ('|'); + troff_pop (); + } + else + troff_putc (*p); + } + troff_pop (); + } + troff_end (); + troff_putc ('\n'); + + /* Print the description */ + troff_start (); + if (d->help == NULL) + { + if (d > Com && d->exec == d[-1].exec) + troff_puts ("Same as above.\n"); + else + troff_puts ("(no description)\n"); + } + else + { + if (d->type == OPT) + troff_puts ("(opt.) "); + troff_putc (toupper (*d->help)); + troff_puts (d->help + 1); + troff_putc ('.'); + troff_putc ('\n'); + } + troff_end (); + } + (void)argc;(void)argv; +} +#endif /* DeuTex */ + + +/* + * is_prefix + * Return non-zero iff s1 is a prefix of s2 + */ +static int is_prefix (const char *s1, const char *s2) +{ + for (;; s1++, s2++) + { + if (*s1 == '\0') + return 1; + if (*s2 != *s1) + return 0; + } +} + +#endif /*DeuTex and DeuSF*/ diff --git a/src/deutex.def b/src/deutex.def new file mode 100644 index 0000000..46c1ad6 --- /dev/null +++ b/src/deutex.def @@ -0,0 +1,7 @@ +NAME DEUTEX + +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +HEAPSIZE 2048 +STACKSIZE 8192 diff --git a/src/deutex.h b/src/deutex.h new file mode 100644 index 0000000..6c3efef --- /dev/null +++ b/src/deutex.h @@ -0,0 +1,266 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/*use old GIF encoder, new one is doing errors*/ +#define NEWGIFE 0 +/*use old GIF decoder, new one is down*/ +#define NEWGIFD 0 +/************ Important defines ************* +#define DeuTex for DOS .EXE Unix Linux OS/2 +#define DeuSF for DOS .EXE Unix Linux OS/2 +*********************************************/ + +#if defined (__alpha) /*__ALPHA__ for Alpha processor?*/ +/*long = int64 on a 64bit processor*/ +typedef char Int8; +typedef short Int16; +typedef int Int32; +typedef unsigned char UInt8; +typedef unsigned short UInt16; +typedef unsigned int UInt32; +#else +/*long = Int32 on a 32 bit processor*/ +typedef char Int8; +typedef short Int16; +typedef long Int32; +typedef unsigned char UInt8; +typedef unsigned short UInt16; +typedef unsigned long UInt32; +#endif + +#if defined DeuTex +#if defined DeuSF +/*DeuTex and DeuSF are mutualy exclusive*/ +#error You cant compile DeuTex and DeuSF at the same time +#else /*compiling DeuTex*/ +#define DEUTEXNAME "DeuTex" +#define COMMANDNAME "deutex" +#endif +#else /*compiling DeuSF*/ +#if defined DeuSF +#define DEUTEXNAME "DeuSF" +#define COMMANDNAME "deusf" +#else /*one of DeuTex or DeuSF must be defined*/ +#error Please define one of DeuTex or DeuSF (with -DDeuTex or -DDeuSF) +#endif +#endif + +/* DeuTex version */ +extern const char deutex_version[]; + +/* Try to guess the target OS and set DT_OS accordingly */ +#if defined __MSDOS__ /* Borland C and DJGPP define __MSDOS__ */\ + || defined MSDOS /* Microsoft C defines MSDOS */ +# define DT_OS 'd' +#elif defined __OS2__ /* IBM C Set++ and Borland C define __OS2__ ? */\ + || defined OS2 /* Microsoft C defines OS2 (I think) */ +# define DT_OS 'o' +#else /* None of the above. Assume Unix. */ +# define DT_OS 'u' +#endif + +/* Try to guess the compiler and set DT_CC accordingly */ +#if defined __BORLANDC__ +# define DT_CC 'b' /* Borland C */ +#elif defined __CYGWIN__ || defined __CYGWIN32__ +# define DT_CC 'c' /* GCC/EGCS with Cygwin */ +#elif defined __DJGPP__ +# define DT_CC 'd' /* DJGPP */ +#elif defined __GNUC__ +# define DT_CC 'g' /* GCC/EGCS */ +#elif defined MSDOS || defined _MSC_VER +# define DT_CC 'm' /* Microsoft C */ +#elif defined __OS2__ && ! defined __BORLANDC__ +# define DT_CC 'i' /* IBM C Set++ */ +#else +# define DT_CC '?' /* Unknown compiler */ +#endif + +/* For real-mode 16-bit compilers, the huge memory model is + required. For all other compilers, the "huge" qualifier + is meaningless and must be hidden. */ +#if DT_OS == 'd' && DT_CC == 'b' +# if ! defined __HUGE__ +# error Please compile in huge memory model (-mh) +# endif +#elif DT_OS == 'd' && DT_CC == 'm' +# if ! defined M_I86HM +# error Please compile in huge memory model (-AH) +# endif +#elif DT_OS == 'o' && DT_CC == 'i' /* Not sure about this one */ + /* Do nothing */ +#else +# define huge +#endif + +#include +#include +#include + +/* fopen() modes */ +#define FOPEN_RB "rb" +#define FOPEN_RBP "rb+" +#define FOPEN_WB "wb" +#define FOPEN_RT "r" +#define FOPEN_WT "w" +#define FOPEN_AT "a" +#define FOPEN_AB "a" + +#define MEMORYCACHE (0x8000L) +/* steps to increase size of WAD directory*/ +#define MAXPWADDIR (128) +/*Add 64000 bytes of pure junk, because of a bug in DEU5.21 */ +#define MAXJUNK64 (1000) +/*special value, means int is not valid*/ +#define INVALIDINT (-6666) +/*indicate an extern WAD entry*/ +#define EXTERNAL (0x80000000L) + +typedef Int16 Bool; +#define TRUE 1 +#define FALSE 0 + + +/* Wad magic numbers */ +#define IWADMAGIC 0x5749 +#define PWADMAGIC 0x5750 +#define WADMAGIC 0x4441 + +/*type of WAD files. correspond to 1st half of name*/ +typedef Int16 WADTYPE; +#define IWAD (IWADMAGIC) +#define PWAD (PWADMAGIC) + + +/************ deutex.c ************/ +/* Entry selection Bits*/ +typedef Int16 NTRYB; +#define BLEVEL (0x01) +#define BLUMP (0x02) +#define BSOUND (0x04) +#define BTEXTUR (0x08) +#define BGRAPHIC (0x10) +#define BSPRITE (0x20) +#define BPATCH (0x40) +#define BFLAT (0x80) +#define BMUSIC (0x100) +#define BALL (0x1FF) + +typedef Int16 SNDTYPE; +#define SNDNONE (0) +#define SNDAU (1) +#define SNDWAV (2) +#define SNDVOC (3) +typedef Int16 IMGTYPE; +#define PICNONE (0) +#define PICBMP (1) +#define PICGIF (2) +#define PICPPM (3) +#define PICTGA (4) +#define PICWAD (5) + + + + + + +/****************** mkwad.c ********************/ +/*wad directory*/ +struct WADDIR /*same as in doom*/ +{ Int32 start; /*start of entry*/ + Int32 size; /*size of entry*/ + char name[8]; /*name of entry*/ +}; + +struct WADINFO +{ Int32 ntry; /*entries in dir*/ + Int32 dirpos; /*position of dir*/ + struct WADDIR huge *dir; /*directory */ + Int32 maxdir; /*max nb of entry in dir*/ + Int32 wposit; /*position for write*/ + Int32 maxpos; /*farther referenced byte in WAD*/ + FILE *fd; /*file */ + Bool ok; /*security ok&1=read ok&2=write*/ +}; + + + +/********************ident.c********************/ +typedef Int16 PICTYPE; +#define PGRAPH (2) +#define PWEAPN (4) +#define PSPRIT (6) +#define PPATCH (8) +#define PFLAT (0xA) +#define PLUMP (0xC) + +typedef Int16 ENTRY; +#define EMASK (0xFF00) +#define EVOID (0) +#define ELEVEL (0x100) +#define EMAP (0x200)/*Levels (doom1) and Maps(Doom2)*/ +#define ELUMP (0x300) +#define ETEXTUR (0x400) +#define EPNAME (0x500)/*textures*/ +#define ESOUND (0x600) +#define ESNDPC (0x601) +#define ESNDWAV (0x602) +#define EGRAPHIC (0x700) +#define ESPRITE (0x800) +#define EPATCH (0x900) +#define EPATCH1 (0x901) +#define EPATCH2 (0x902) +#define EPATCH3 (0x903) +#define EFLAT (0xA00) +#define EFLAT1 (0xA01) +#define EFLAT2 (0xA02) +#define EFLAT3 (0xA03) +#define EMUSIC (0xB00) +#define EDATA (0x1000) +#define EZZZZ (0x7F00) /*unidentified entries*/ + + + + +/******************* lists.c ********************/ + + +/*deutex.c: misc*/ +Bool LetsHaveFunBaby(long guesswhat); +/*compose.c: TEXTURE list*/ +/*compose.c: TEXTURE insertion...rather, WAD composition*/ +void CMPOmakePWAD( char *doomwad,WADTYPE type, char *PWADname, + char *DataDir,char *texin,NTRYB select, + char trnR, char trnG, char trnB,Bool George); +/*substit.c: DOOM.EXE string substitution*/ +void EXE2list(FILE *out,char *doomexe,Int32 start,Int16 thres); +void EXEsubstit(char *texin,char *doomexe,Int32 start,Int16 thres); + +void XTRlistDir(char *doomwad,char *wadin,NTRYB select); + +void XTRvoidSpacesInWAD(char *wadin); + +void XTRcompakWAD(char *DataDir,char *wadin, char *texout,Bool ShowIdx); +void XTRstructureTest(char *doomwad,char *wadin); +void XTRtextureUsed(char *wadin); diff --git a/src/deutexos.def b/src/deutexos.def new file mode 100644 index 0000000..4e8e605 --- /dev/null +++ b/src/deutexos.def @@ -0,0 +1,6 @@ +NAME DEUTEXOS WINDOWCOMPAT +DESCRIPTION 'DEUTEXOS' +PROTMODE +HEAPSIZE 32768 +STACKSIZE 16384 + \ No newline at end of file diff --git a/src/endianio.c b/src/endianio.c new file mode 100644 index 0000000..6431f6a --- /dev/null +++ b/src/endianio.c @@ -0,0 +1,175 @@ +/* + * endianio.c + * File I/O with explicit endianness. + * + * Those functions allow to read little-endian and + * big-endian integers from a file regardless of the + * endianness of the CPU. + * + * This code has been tested on 16-bit and 32-bit C + * compilers. + * + * Adapted from Yadex by AYM on 1999-03-06. + */ + + +/* +This file is Copyright � 1999 Andr� Majorel. + +This file is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + +This file 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 Library General Public License for more +details. + +You should have received a copy of the GNU Library General Public License +along with this file; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "endianio.h" + + +/* + * fread_i16_be + * Read a big-endian 16-bit signed integer from file . + * Returns 0 on success, != 0 on failure. + */ +int fread_i16_be (FILE *fd, i16 *buf) +{ + *buf = (getc (fd) << 8) + | getc (fd); + return feof (fd) || ferror (fd); +} + + +/* + * fread_i16_le + * Read a little-endian 16-bit signed integer from file . + * Returns 0 on success, != 0 on failure. + */ +int fread_i16_le (FILE *fd, i16 *buf) +{ + *buf = getc (fd) + | (getc (fd) << 8); + return feof (fd) || ferror (fd); +} + + +/* + * fread_i32_be + * Read a big-endian 32-bit signed integer from file . + * Returns 0 on success, != 0 on failure. + */ +int fread_i32_be (FILE *fd, i32 *buf) +{ + *buf = ((i32) getc (fd) << 24) + | ((i32) getc (fd) << 16) + | ((u16) getc (fd) << 8) + | getc (fd); + return feof (fd) || ferror (fd); +} + + +/* + * fread_i32_le + * Read a little-endian 32-bit signed integer from file . + * Returns 0 on success, != 0 on failure. + */ +int fread_i32_le (FILE *fd, i32 *buf) +{ + *buf = getc (fd) + | ((u16) getc (fd) << 8) + | ((i32) getc (fd) << 16) + | ((i32) getc (fd) << 24); + return feof (fd) || ferror (fd); +} + + +/* + * fread_u16_le + * Read a little-endian 16-bit unsigned integer from file . + * Returns 0 on success, != 0 on failure. + */ +int fread_u16_le (FILE *fd, u16 *buf) +{ + *buf = getc (fd) + | (getc (fd) << 8); + return feof (fd) || ferror (fd); +} + + +/* + * fwrite_i16_le + * Write a little-endian 16-bit signed integer to file . + * Returns 0 on success, != 0 on failure. + */ +int fwrite_i16_le (FILE *fd, i16 buf) +{ + putc ( buf & 0xff, fd); + putc ((buf >> 8) & 0xff, fd); + return feof (fd) || ferror (fd); +} + + +/* + * fwrite_i16_be + * Write a big-endian 16-bit signed integer to file . + * Returns 0 on success, != 0 on failure. + */ +int fwrite_i16_be (FILE *fd, i16 buf) +{ + putc ((buf >> 8) & 0xff, fd); + putc ( buf & 0xff, fd); + return feof (fd) || ferror (fd); +} + + +/* + * fwrite_i32_le + * Write a little-endian 32-bit signed integer to file . + * Returns 0 on success, != 0 on failure. + */ +int fwrite_i32_le (FILE *fd, i32 buf) +{ + putc ( buf & 0xff, fd); + putc ((buf >> 8) & 0xff, fd); + putc ((buf >> 16) & 0xff, fd); + putc ((buf >> 24) & 0xff, fd); + return feof (fd) || ferror (fd); +} + + +/* + * fwrite_i32_be + * Write a big-endian 32-bit signed integer to file . + * Returns 0 on success, != 0 on failure. + */ +int fwrite_i32_be (FILE *fd, i32 buf) +{ + putc ((buf >> 24) & 0xff, fd); + putc ((buf >> 16) & 0xff, fd); + putc ((buf >> 8) & 0xff, fd); + putc ( buf & 0xff, fd); + return feof (fd) || ferror (fd); +} + + +/* + * fwrite_u16_le + * Write a little-endian 16-bit unsigned integer to file . + * Returns 0 on success, != 0 on failure. + */ +int fwrite_u16_le (FILE *fd, u16 buf) +{ + putc ( buf & 0xff, fd); + putc ((buf >> 8) & 0xff, fd); + return feof (fd) || ferror (fd); +} + diff --git a/src/endianio.h b/src/endianio.h new file mode 100644 index 0000000..19552fd --- /dev/null +++ b/src/endianio.h @@ -0,0 +1,29 @@ +/* + * endianio.h + * Endianness-independant file I/O. + * + * Those functions allow to read little-endian and + * big-endian integers from a file regardless of the + * endianness of the CPU. + * + * Adapted from Yadex by AYM on 1999-03-06. + */ + + +/* Use the names DeuTex provides */ +#define i16 Int16 +#define i32 Int32 +#define u16 UInt16 +#define u32 UInt32 + +int fread_i16_le (FILE *fd, i16 *buf); +int fread_i16_be (FILE *fd, i16 *buf); +int fread_i32_le (FILE *fd, i32 *buf); +int fread_i32_be (FILE *fd, i32 *buf); +int fread_u16_le (FILE *fd, u16 *buf); +int fwrite_i16_le (FILE *fd, i16 buf); +int fwrite_i16_be (FILE *fd, i16 buf); +int fwrite_i32_le (FILE *fd, i32 buf); +int fwrite_i32_be (FILE *fd, i32 buf); +int fwrite_u16_le (FILE *fd, u16 buf); + diff --git a/src/endianm.c b/src/endianm.c new file mode 100644 index 0000000..1b62530 --- /dev/null +++ b/src/endianm.c @@ -0,0 +1,143 @@ +/* + * endianm.c + * Endianness-independant memory access. + * + * Those functions allow to retrieve little-endian and + * big-endian integers from a memory area regardless of + * the endianness of the CPU. + * + * This code has been tested on 16-bit and 32-bit C + * compilers. + * + * AYM 1999-07-04 + */ + + +/* +This file is Copyright � 1999 Andr� Majorel. + +This file is free software; you can redistribute it and/or modify it under +the terms of the GNU Library General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) any +later version. + +This file 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 Library General Public License for more +details. + +You should have received a copy of the GNU Library General Public License +along with this file; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "endianm.h" + + +/* + * read_i16_le + * Read a little-endian 16-bit signed integer from memory area + * pointed to by . + */ +void read_i16_le (const void *ptr, i16 *buf) +{ + *buf = ((const unsigned char *) ptr)[0] + | (((const unsigned char *) ptr)[1] << 8); +} + + +/* + * read_i32_le + * Read a little-endian 32-bit signed integer from memory area + * pointed to by . + */ +void read_i32_le (const void *ptr, i32 *buf) +{ + *buf = ((const unsigned char *) ptr)[0] + | ((u16) ((const unsigned char *) ptr)[1] << 8) + | ((i32) ((const unsigned char *) ptr)[2] << 16) + | ((i32) ((const unsigned char *) ptr)[3] << 24); +} + + +/* + * peek_i16_le + * Read a little-endian 16-bit signed integer from memory area + * pointed to by . + */ +i16 peek_i16_le (const void *ptr) +{ + return ((const unsigned char *) ptr)[0] + | (((const unsigned char *) ptr)[1] << 8); +} + + +/* + * peek_i32_be + * Read a big-endian 32-bit signed integer from memory area + * pointed to by . + */ +i32 peek_i32_be (const void *ptr) +{ + return ((i32) (((const unsigned char *) ptr)[0]) << 24) + | ((i32) (((const unsigned char *) ptr)[1]) << 16) + | ((u16) (((const unsigned char *) ptr)[2]) << 8) + | ((const unsigned char *) ptr)[3]; +} + + +/* + * peek_i32_le + * Read a little-endian 32-bit signed integer from memory area + * pointed to by . + */ +i32 peek_i32_le (const void *ptr) +{ + return ((const unsigned char *) ptr)[0] + | ((u16) ((const unsigned char *) ptr)[1] << 8) + | ((i32) ((const unsigned char *) ptr)[2] << 16) + | ((i32) ((const unsigned char *) ptr)[3] << 24); +} + + +/* + * write_i16_le + * Write a little-endian 16-bit signed integer to memory area + * pointed to by . + */ +void write_i16_le (void *ptr, i16 val) +{ + ((unsigned char *) ptr)[0] = val; + ((unsigned char *) ptr)[1] = val >> 8; +} + + +/* + * write_i32_be + * Write a big-endian 32-bit signed integer to memory area + * pointed to by . + */ +void write_i32_be (void *ptr, i32 val) +{ + ((unsigned char *) ptr)[0] = val >> 24; + ((unsigned char *) ptr)[1] = val >> 16; + ((unsigned char *) ptr)[2] = val >> 8; + ((unsigned char *) ptr)[3] = val; +} + + +/* + * write_i32_le + * Write a little-endian 32-bit signed integer to memory area + * pointed to by . + */ +void write_i32_le (void *ptr, i32 val) +{ + ((unsigned char *) ptr)[0] = val; + ((unsigned char *) ptr)[1] = val >> 8; + ((unsigned char *) ptr)[2] = val >> 16; + ((unsigned char *) ptr)[3] = val >> 24; +} + diff --git a/src/endianm.h b/src/endianm.h new file mode 100644 index 0000000..4f5f02e --- /dev/null +++ b/src/endianm.h @@ -0,0 +1,38 @@ +/* + * endianm.h + * Endianness-independant memory access. + * + * Those functions allow to retrieve little-endian and + * big-endian integers from a memory area regardless of + * the endianness of the CPU. + * + * AYM 1999-07-04 + */ + + +/* Use the names DeuTex provides */ +#ifndef i16 +# define i16 Int16 +#endif + +#ifndef i32 +# define i32 Int32 +#endif + +#ifndef u16 +# define u16 UInt16 +#endif + +#ifndef u32 +# define u32 UInt32 +#endif + +void read_i16_le (const void *ptr, i16 *buf); +void read_i32_le (const void *ptr, i32 *buf); +i16 peek_i16_le (const void *ptr); +i32 peek_i32_be (const void *ptr); +i32 peek_i32_le (const void *ptr); +void write_i16_le (void *ptr, i16 val); +void write_i32_be (void *ptr, i32 val); +void write_i32_le (void *ptr, i32 val); + diff --git a/src/extract.c b/src/extract.c new file mode 100644 index 0000000..6333039 --- /dev/null +++ b/src/extract.c @@ -0,0 +1,613 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "text.h" +#include "mkwad.h" +#include "texture.h" +#include "ident.h" +#include "color.h" +#include "picture.h" +#include "sound.h" + +/*compile only for DeuTex*/ +#if defined DeuTex + +/************** Begin XTRACT WAD module **************/ +/* +** here we go for some real indecent programming. sorry +*/ + +extern char file[128]; +/* +** try to save entry as BitMap .BMP +*/ +static Bool XTRbmpSave(Int16 *pinsrX,Int16 *pinsrY,struct WADDIR huge *entry, + PICTYPE type,char *DataDir,char *dir,struct WADINFO *info,IMGTYPE Picture,Bool WSafe) +{ Bool res; + Int32 start=entry->start; + Int32 size =entry->size; + char *name=entry->name; + char huge *buffer; + char *extens=NULL; + + if(size<8L) return FALSE; + switch(Picture) + { case PICGIF: extens="GIF";break; + case PICBMP: extens="BMP";break; + case PICPPM: extens="PPM";break; + case PICTGA: extens="TGA";break; + default: Bug("img type"); + } + res = MakeFileName(file,DataDir,dir,"",name,extens); + if((WSafe==TRUE)&&(res==TRUE)) + { Warning("Will not overwrite file %s",file); + return TRUE; + } + buffer=(char huge *)Malloc(size); + WADRseek(info,start); + WADRreadBytes(info,buffer,size); + res = PICsaveInFile(file,type,buffer,size,pinsrX,pinsrY,Picture); + if(res==TRUE)Detail("Saved picture as %s\n",file); + Free(buffer); + return res; +} +/* +** extract entries from a WAD +*/ +void XTRextractWAD(char *doomwad,char *DataDir,char *wadin, char *wadinfo, + IMGTYPE Picture,SNDTYPE Sound,Bool fullSND,NTRYB select, + char trnR, char trnG, char trnB,Bool WSafe) +{ static struct WADINFO pwad; + static struct WADINFO iwad; + static struct WADINFO lwad; + struct WADDIR huge *pdir; + Int16 pnb; + ENTRY huge *piden; + Int16 p; + Int32 ostart,osize; + char huge *buffer; + char huge *Colors=NULL; + Bool res; + Int16 insrX=0,insrY=0; + Bool EntryFound; + /*PNAMES*/ + Int16 pnm;char huge *Pnam;Int32 Pnamsz; + char *extens=NULL; + /*text file to write*/ + static struct TXTFILE *TXT; + Phase("Extracting entries from WAD %s\n",wadin); + /*open iwad,get iwad directory*/ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + + /*find PNAMES*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) ProgError("Can't find PNAMES in main WAD"); + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + /*read WAD*/ + pwad.ok=0; + WADRopenR(&pwad,wadin); + pnb=(Int16)pwad.ntry; + pdir=pwad.dir; + piden=IDENTentriesPWAD(&pwad, Pnam, Pnamsz); + /**/ + Free(Pnam); + /* + ** + ** prepare for graphics + */ + /*find PLAYPAL*/ + pnm=WADRfindEntry(&pwad,"PLAYPAL"); + if(pnm>=0) + Colors=WADRreadEntry(&pwad,pnm,&Pnamsz); + else + { pnm=WADRfindEntry(&iwad,"PLAYPAL"); + if(pnm>=0) + Colors=WADRreadEntry(&iwad,pnm,&Pnamsz); + else ProgError("Can't find PLAYPAL in main WAD"); + } + COLinit(trnR,trnG,trnB,Colors,(Int16)Pnamsz); + Free(Colors); + /* + ** read the PNAMES entry in PWAD + ** or in DOOM.WAD if it does not exist elsewhere + */ + pnm=WADRfindEntry(&pwad,"PNAMES"); + if(pnm>=0) + Pnam=WADRreadEntry(&pwad,pnm,&Pnamsz); + else + { pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm>=0) + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + else ProgError("Can't find PNAMES in main WAD"); + } + PNMinit(Pnam,Pnamsz); + Free(Pnam); + /* + ** iwad not needed anymore + */ + WADRclose(&iwad); + /* + ** output WAD creation directives + ** and save entries depending on their type + */ + + /*check if file exists*/ + TXT=TXTopenW(wadinfo); + TXTaddComment(TXT," DeuTex by Olivier Montanuy"); + TXTaddComment(TXT," PWAD creation directives"); + TXTaddComment(TXT,""); + /* + ** LEVELS + */ + if(select&BLEVEL) + { Phase("Extracting Levels...\n"); + for(EntryFound=FALSE,p=0;p=0) Colors=WADRreadEntry(&iwad,e,&Entrysz); + else ProgError("Can't find PLAYPAL in main WAD"); + WADRclose(&iwad); + pwad.ok=0; + WADRopenR(&pwad,wadin); + e=WADRfindEntry(&pwad,"PLAYPAL"); + if(e>=0) + { Free(Colors); + Colors=WADRreadEntry(&pwad,e,&Entrysz); + } + COLinit(trnR,trnG,trnB,Colors,(Int16)Entrysz); + Free(Colors); + e=WADRfindEntry(&pwad,Name); + if(e<0) ProgError("Can't find entry %.8s in WAD",Name); + Phase("Extracting entry %.8s from WAD %s\n",entry,wadin); + Entry=WADRreadEntry(&pwad,e,&Entrysz); + /*try graphic*/ + if(Found!=TRUE) + if(Entrysz>8) + { switch(Picture) + { case PICGIF: extens="GIF";break; + case PICBMP: extens="BMP";break; + case PICPPM: extens="PPM";break; + case PICTGA: extens="TGA";break; + default: Bug("img type"); + } + MakeFileName(file,DataDir,"","",Name,extens); + if(PICsaveInFile(file,PGRAPH,Entry,Entrysz,&insrX,&insrY,Picture)==TRUE) + { Info("Picture insertion point is (%d,%d)",insrX,insrY); + Found=TRUE; + } + else if((Entrysz==0x1000)||(Entrysz==0x1040)) + { if(PICsaveInFile(file,PFLAT,Entry,Entrysz,&insrX,&insrY,Picture)==TRUE) + { Found=TRUE; + } + } + else if(Entrysz==64000L) + { if(PICsaveInFile(file,PLUMP,Entry,Entrysz,&insrX,&insrY,Picture)==TRUE) + { Found=TRUE; + } + } + } + if (Found!=TRUE) + if (peek_i16_le (Entry) == 3) + if (Entrysz >= 8 + peek_i32_le (Entry + 4)) + { /*save as sound*/ + switch(Sound) + { case SNDAU: extens="AU";break; + case SNDWAV: extens="WAV";break; + case SNDVOC: extens="VOC";break; + default: Bug("snd type"); + } + MakeFileName(file,DataDir,"","",Name,extens); + SNDsaveSound(file,Entry,Entrysz,Sound,fullSND); + Found=TRUE; + } + if(Found!=TRUE) + { /*save as lump*/ + MakeFileName(file,DataDir,"","",Name,"LMP"); + WADRsaveEntry(&pwad,e,file); + } + Free(Entry); + WADRclose(&pwad); +} + + +#endif /*DeuTex*/ + diff --git a/src/extract.h b/src/extract.h new file mode 100644 index 0000000..383a7c6 --- /dev/null +++ b/src/extract.h @@ -0,0 +1,38 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/*extract.c: list dir and extract entries*/ +void XTRextractWAD(char *doomwad,char *DataDir,char *wadin, char *texout, + IMGTYPE Picture,SNDTYPE Sound,Bool fullSND,NTRYB select, + char trnR, char trnG, char trnB,Bool WSafe); +/*extract.c: get a single entry*/ +void XTRgetEntry(char *doomwad,char *DataDir,char *wadin,char *entry, + IMGTYPE Picture,SNDTYPE Sound,Bool fullSND, + char trnR, char trnG, char trnB); + +/*obsolete junk*/ +void XTRtextureList(char *doomwad,char *DataDir); + +void XTRpatchList(char *doomwad,char *DataDir,IMGTYPE Picture, + char trnR, char trnG, char trnB); diff --git a/src/gifcodec.c b/src/gifcodec.c new file mode 100644 index 0000000..0dfbde1 --- /dev/null +++ b/src/gifcodec.c @@ -0,0 +1,511 @@ +/* + The LZW CODEC for GIF is Copyright (c) 1995 David Kaplan + + Alas, This LZW DECODER doesn't work yet. + + In fact this file is not used at all. All the GIF stuff is + really in lzw.c. -- AYM 1999-09-07 +*/ + + +#include "deutex.h" /*for types. equivalent of deu.h*/ + + +#if defined DeuTex /*deutex shit*/ +#if NEWGIFE || NEWGIFD +#include +#include +#include +#include "gifcodec.h" + +/* + local defines +*/ +#define HASHSIZE 5101 +#define TABLESIZE 4096 +#define HASHBITS 4 + +#define OK 0 +#define EMPTY -1 +#define BAD_ALLOC -2 +#define OVERFLOW -3 +#define OUTOFSYNC -4 + + + + + +static void Enc_clear(void); +static void putCode(Int16 code); +static Int16 flush(void); +static Int16 findStr(Int16 pfx, Int16 sfx); +static void putCode(Int16 code); +static Int16 putbyte(Int16 byt); + + +static UInt8 buffer[255]; /* the write buffer */ + + +/* + tables +*/ +static Int16 *codes; /* the code entry column of the table */ +static Int16 *prefix; /* the prefix entry column of the table */ +static Int16 *suffix; /* the suffix entry column of the table */ +/* + codes +*/ +static Int16 clrc; /* the value of the clearcode (the minsize + 1) */ +static Int16 endc; /* the value of the endcode (the minsize + 2) */ +/* + control +*/ +static Int16 nroots; /* how many codes are already in use = bitlength of the pixels*/ + /* 1 << pixelsize */ +static Int16 minsize; /* the minimum size for the first code (the highest value for the bitlength of the pixels*/ +static Int16 cursize; /* the current bitlength being used in the codes */ +static Int16 maxsize; /* the maximum bitlength that can be used (8) */ + +static Int16 curcode; /* the next entry value that is available */ +static Int16 maxcode; /* the maximum entry value of the table */ +static Int16 bytecode; /* last code read or written */ +static Int16 bytemask; /* mask for bytecode */ +static Int16 nbytes; /* COD the number of bytes that have been written */ + /* DEC bytes in buffer */ +static Int16 nbits; /* COD the number of bits being used in the highest empty slot */ + /* DEC current element width */ + +#endif /*NEWGIFE NEWGIFD*/ + + +/* + ENCODER +*/ +#if NEWGIFE +FILE* outfile; /* the file to be written to */ +static Int16 chrc; /* COD the current byte being read */ +static Int16 strc; /* COD the number of the last entry to have a match */ +static Int16 started; /* a boolean variable used to see if this is the first string */ + +/* Initializes all the variables (yup, all them up there!) */ + +Int16 InitEncoder(FILE* out, Int16 bpp) +{ + codes = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); + prefix = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); + suffix = (Int16 *) malloc(sizeof(Int16)*HASHSIZE); + if((codes == NULL) || (prefix == NULL) || (suffix == NULL)) + return BAD_ALLOC; + + outfile = out; + chrc = strc = started = 0; + minsize = bpp + 1; + maxsize = 12; + nroots = 1 << bpp; + clrc = nroots; + endc = clrc + 1; + bytecode = 0; + bytemask = 1; + nbytes = 0; + started = 0; + Enc_clear(); + putCode(clrc); + return OK; +} +Int16 ExitEncoder(void) +{ flush(); + free(codes); + free(prefix); + free(suffix); + return 0; +} +/* Encodes one string of bytes and writes to the current file pointer */ +/* I will comment this part heavily to illustrate the process... */ + +Int16 Encode(UInt8 huge *buf, Int32 size) +{ + Int16 pos = 0, index; + + /* if this is the first table to be used, setup some variables we + need such as the table's first entry: the first byte in the + array */ + + if(!started) + { strc = buf[pos++]; // changed pos+1 to pos++ + started = 1; + } + /* go through the array of bytes */ + while(pos <= size) + { + chrc = buf[pos++]; /* get the next (or first) character */ + /* see if the current string (be it one character or more) + is in the table and return the corresponding entry number. + If not, return the number of the next available entry */ + index = findStr(strc, chrc); + /* if the string IS in the index, we will get a number that + corresponds to a string in the table: it wont be empty */ + if(codes[index] != EMPTY) /* string found! */ + { + /* set the current string to the one-byte + code for the string that was found */ + strc = codes[index]; + } + else /* not found! */ + { + /* set the next entry in the table to + the next available entry number */ + codes[index] = curcode; + prefix[index] = strc; /* set the prefix entry to the strc */ + suffix[index] = chrc; /* set the suffix entry to the chrc */ + putCode(strc); /* put the code into the out file (compression!) */ + strc = chrc; /* set the prefix to the current char */ + curcode++; /* remember that the current entry is now filled */ + /* if the number of bytes in the current code is as big as + possible, we must reset the table! */ + if(curcode > maxcode) + { + cursize++; /* set the currentsize of the code to the next number */ + /* if the current # of bytes being used exceeds the max */ + if(cursize > maxsize) + { + putCode(clrc); /* put a clearcode into the file to tell the decoder */ + Enc_clear(); /* reset the table and start over */ + } + else /* if not */ + { + nbits = cursize; /* set the number of bits to the current size */ + maxcode <<= 1; /* set maxcode to the current char bitshifted once */ + if(cursize == maxsize) /* if we are at the last bit-increase */ + maxcode--; /* make maxcode one less so curcode can be larger than it */ + } + } + } + } + return OK; +} + +/* close the table: */ + +Int16 flush(void) +{ + putCode(endc); /* put an endcode in the file */ + if(bytemask != 1) /* if the last string was less than 256 bytes */ + { + putbyte(bytecode); /* put the last byte into the file */ + bytecode = 0; /* and reset the variables*/ + bytemask = 1; + } + if(nbytes > 0) /* if the last string has anything in it */ + { + fputc(nbytes, outfile); /* write the block out */ + fwrite(buffer, nbytes, 1, outfile); + nbytes = 0; + } + return ferror(outfile) ? BAD_ALLOC : OK; +} + +/* put the code in. This is tricky because we use an int and we might have + a code that is only using 7 or less bits, we must compensate */ + +void putCode(Int16 code) +{ + Int16 mask = 1; + Int16 n = nbits; + while(n-- >0) + { + if(code & mask) bytecode |= bytemask; + if((bytemask <<=1) > 0x80) + { + putbyte(bytecode); + bytecode = 0; + bytemask = 1; + } + mask <<= 1; + } +} + +/* clear the table for a new one to be built */ + +void Enc_clear(void) +{ + Int16 i; + cursize = minsize; + nbits = cursize; + curcode = endc + 1; + maxcode = 1 << cursize; + for(i=0;i 0) && (nb < rwbytes) ) + bytes[nb++] = stack[--stkp]; + + /* loop until a row has been decoded */ + while( nb < rwbytes ) + { /*....... get next code */ + if( (code=getcode()) < 0 ) break; + + /*....... check for a clear code*/ + if( code == clrc ) + { + reset_decoder(); + if( oldc == endc ) break; + bytes[nb++] = oldc; + if( nb == rwbytes ) break; + } + /*....... check for an end code*/ + else if( code == endc ) + { + break; + } + /*....... code is a data code*/ + else + { + if( code == curcode ) + { + code = oldc; + cond = push( newc ); + } + else if( code > curcode ) + { + cond = OUTOFSYNC; + break; + } + while( code > endc ) + { + cond = push( (suffix[code]&0xFF) ); + code = prefix[code]; + } + cond = push( code ); + /* add code to table */ + if( curcode < maxcode ) + { + newc = code; + suffix[curcode] = newc; + prefix[curcode] = oldc; + oldc = bitcode; + curcode++; + } + /* current width exhausted? */ + if( curcode >= maxcode ) + { + if( cursize < maxsize ) + { + cursize++; + nbits = cursize; + maxcode <<= 1; + } + else if( (code=getcode()) == clrc ) + { + reset_decoder(); + if( oldc == endc ) break; + bytes[nb++] = oldc; + if( nb == rwbytes ) break; + } + else + { + cond = OVERFLOW; + break; + } + } + /* transfer string from stack to buffer*/ + while( (stkp > 0) && (nb < rwbytes) ) + bytes[nb++] = stack[--stkp]; + } + } + /*! David + I use fmemcpy not memcpy, because data is FAR (char huge *) + */ + _fmemcpy( buf, bytes, npxls ); + return cond; +} + + +void Dec_clear(void) +{ + Int16 i; + cursize = minsize; + nbits = cursize; + clrc = nroots; + endc = clrc + 1; + curcode = endc + 1; + maxcode = 1 << cursize; + for(i=0; i 0 ) +*/ + for(n=0; n 0x80 ) + { + bytemask = 1; + if( (bytecode = getbyte()) < 0 ) return -1; + } + if( bytecode & bytemask ) bitcode |= bitmask; + bitmask <<= 1; + } return bitcode; +} +/* + get a byte block +*/ +Int16 getbyte( void ) +{ + if( curbyte >= nbytes ) /*need a new block*/ + { + /*! David + the block size is an unsigned char + MODIFIED + if( (nbytes = fgetc( ifile )&) < 1 ) return -1; + */ + for(nbytes=0;nbytes==0;) /*get a non zero block*/ + { if( (nbytes = fgetc( ifile )) == EOF ) return -1; + nbytes &= 0xFF; + } + if(fread( buffer, nbytes, 1, ifile ) != 1 ) return -1; + curbyte = 0; + } + return buffer[curbyte++]; +} + + +void reset_decoder(void) +{ stkp = 0; + Dec_clear(); + while( (oldc=getcode()) == clrc ); + newc = oldc; +} +#endif /*NEWGIFD*/ +#endif /*DeuTex*/ + diff --git a/src/gifcodec.h b/src/gifcodec.h new file mode 100644 index 0000000..432b5fb --- /dev/null +++ b/src/gifcodec.h @@ -0,0 +1,34 @@ +/* + The LZW CODEC for GIF is Copyright (c) 1995 David Kaplan + + The Graphics Interchange Format(c) is the Copyright property of + CompuServe Incorporated. +*/ +/* + initialise encoder. declare the output file +*/ +Int16 InitEncoder(FILE* out, Int16 bpp); /*bpp=8*/ +/* + encode a buffer of 256 characters, + and write it to output file +*/ + +Int16 Encode(UInt8 huge *buf, Int32 size); +/* + last operation to do, when the coding is finished +*/ +Int16 ExitEncoder(void); + +/* + Init decoder + input file, codebits=8, pixelcount=8? +*/ +Int16 InitDecoder( FILE* infile, Int16 codebits, Int16 rowsize); +/* + decode a buffer +*/ +Int16 Decode( UInt8 huge *buf, Int16 npxls ); +/* + last operation +*/ +void ExitDecoder(void); diff --git a/src/ident.c b/src/ident.c new file mode 100644 index 0000000..2611c70 --- /dev/null +++ b/src/ident.c @@ -0,0 +1,658 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "mkwad.h" +#include "texture.h" +#include "ident.h" + +/* +** This file contains all the routines to identify DOOM specific +** entries and structures. Fear the bugs! +*/ + + + +/****************IDENT module ***********************/ +/* identify ExMx or MAPxx entries +** which begin a DOOM level. +** returns -1 if not correct +*/ + + +Int16 IDENTlevelPart(char *name) +{ Int16 n; + static char *Part[]={"name","THINGS","LINEDEFS","SIDEDEFS","VERTEXES", + "SEGS","SSECTORS","NODES","SECTORS","REJECT","BLOCKMAP","BEHAVIOR",NULL}; + for(n=1; Part[n]!=NULL; n++) + { if(strncmp(Part[n],name,8)==0) return n; + } + return -1; +} + + +Int16 IDENTlevel(char *buffer) +{ switch(buffer[0]) + { case 'E': + if(buffer[2]=='M') + if(buffer[4]=='\0') + if((buffer[1]>='1')&&(buffer[1]<='9')) + if((buffer[3]>='1')&&(buffer[3]<='9')) + return (Int16)((buffer[1]&0xF)<<4)+(buffer[3]&0xF); + break; + case 'M': + if(buffer[1]=='A') + if(buffer[2]=='P') + if((buffer[3]>='0')&&(buffer[3]<='9')) + if((buffer[4]>='0')&&(buffer[4]<='9')) + { return (Int16)((buffer[3]&0xF)*10)+(buffer[4]&0xF); + } + break; + default: + break; + } + return -1; +} +/* +** calculate default insertion point +*/ +Int16 IDENTinsrX(PICTYPE type,Int16 insrX,Int16 szx) +{ + if(insrX!=INVALIDINT) + if(insrX > -4096) + if(insrX < 4096) + return insrX; + /* default insertion point */ + switch(type) + { + case PPATCH: /*mid, lower-5 ????*/ + return (Int16)(szx/2); + case PSPRIT: /*mid, lower-5*/ + return (Int16)(szx/2); + case PWEAPN: /*absolute, in 320*200*/ + return (Int16)(-(320-szx)/2); /* -160+X??*/ + case PFLAT: /*no insertion point*/ + return (Int16)0; + case PGRAPH: /*0,0 by default*/ + return (Int16)0; + default: + Bug("idinx (%d)", (int) type); + } + return (Int16)0; +} +Int16 IDENTinsrY(PICTYPE type,Int16 insrY,Int16 szy) +{ + if(insrY!=INVALIDINT) + if(insrY > -4096) + if(insrY < 4096) + return insrY; + /* default insertion point */ + switch(type) + { + case PPATCH: /*mid, lower-5 ????*/ + return (Int16)(szy-5); + case PSPRIT: /*mid, lower-5*/ + return (Int16)(szy-5); + case PWEAPN: /*absolute, in 320*200*/ + return (Int16)(-(200-szy)); + case PFLAT: /*no insertion point*/ + return (Int16)0; + case PGRAPH: /*0,0 by default*/ + return (Int16)0; + default: + Bug("idiny (%d)", (int) type); + } + return 0; +} +/* +** identify a graphic entry +** from a read WAD +*/ + +struct PICHEAD { +Int16 Xsz; /*nb of columns*/ +Int16 Ysz; /*nb of rows*/ +Int16 Xinsr; /*insertion point*/ +Int16 Yinsr; /*insertion point*/ +}; +ENTRY IDENTgraphic(struct WADINFO *info,Int16 n) +{ + Int32 start=info->dir[n].start; + Int32 size=info->dir[n].size; + Int16 x,insrX,insrY,Xsize,Ysize; + Int32 huge *ofscol; + static struct PICHEAD head; + /*check X,Y size and insertion point*/ + if(size<8) return ELUMP; + WADRseek(info,start); + WADRreadBytes(info,(char huge *)&head,sizeof(struct PICHEAD)); + Xsize = peek_i16_le (&head.Xsz); + if((Xsize<1)||(Xsize>320))return ELUMP; + Ysize = peek_i16_le (&head.Ysz); + if((Ysize<1)||(Ysize>200))return ELUMP; + insrX = peek_i16_le (&head.Xinsr); /*insertion point*/ + if((insrX<-4000)||(insrX>4000))return ELUMP; + insrY = peek_i16_le (&head.Yinsr); /*insertion point*/ + if((insrY<-4000)||(insrY>4000))return ELUMP; + /*check picture size*/ + if(size<8+4*Xsize+1*Xsize) return ELUMP; + /*check validity of columns*/ + ofscol=(Int32 huge *)Malloc(Xsize*sizeof(Int32)); + WADRreadBytes(info,(char huge *)ofscol,Xsize*sizeof(Int32)); + for(x=0;x size) /*check against size*/ + { Free(ofscol);return ELUMP;} + } + Free(ofscol); + /*valid...graphic...maybe...*/ + return EGRAPHIC; +} + +/* +** set identity of an entry with known name +** set only the first entry that match this name +*/ +static void IDENTdirSet(ENTRY huge *ids,struct WADINFO *info,char *name,ENTRY ident) +{ Int16 n; + n=WADRfindEntry(info,name); + if(n>=0) /*found it?*/ + if(n<(info->ntry)) + if(ids[n]==EZZZZ) + { ids[n]=ident; + } +} +/* +** identifies sprites from: +** S_START SS_START S_END SS_END delimiters if exist +** S_END SS_END delimiter and crawl back +** +** Precond: ids contains EZZZZ for unidentified entries +*/ +static void IDENTdirSprites(ENTRY huge *ids,struct WADINFO *info,Bool Check) +{ Int16 s_end,s_start; + Int16 n,s; + /* + ** check if there are sprites + */ + s_end=WADRfindEntry(info,"S_END"); + if(s_end<0) s_end=WADRfindEntry(info,"SS_END"); + if(s_end<0) return; + ids[s_end]=EVOID; + /* + ** check if there is a sprites begining + */ + s_start=WADRfindEntry(info,"S_START"); + if(s_start<0) s_start=WADRfindEntry(info,"SS_START"); + /* + ** guess sprite location + */ + if(s_start<0) + { for(n=s_end-1;n>=0;n--) + { if(ids[n]!=EZZZZ) break; /*last sprite*/ + if(info->dir[n].size<8) break; /*last sprite*/ + if(Check==TRUE) + { s=IDENTgraphic(info,n); + if(s==ELUMP) break; + } + ids[n]=ESPRITE; + } + } + /* + ** declare sprites + */ + else + { ids[s_start]=EVOID; + for(n=s_end-1;n>s_start;n--) + { if(info->dir[n].size>8) + { ids[n]=ESPRITE; + } + } + } +} + +/* +** identifies flats from: +** F_START FF_START F_END FF_END delimiters if exist +** F_END FF_END delimiter and crawl back +** +** Precond: ids contains EZZZZ for unidentified entries +*/ +static void IDENTdirFlats(ENTRY huge *ids,struct WADINFO *info) +{ Int16 f_end,f_start; + Int16 n; + /* + ** check if there are flats + */ + f_end=WADRfindEntry(info,"F_END"); + if(f_end<0) f_end=WADRfindEntry(info,"FF_END"); + if(f_end<0) return; + ids[f_end]=EVOID; + + IDENTdirSet(ids,info,"F1_START",EVOID); + IDENTdirSet(ids,info,"F1_END",EVOID); + IDENTdirSet(ids,info,"F2_START",EVOID); + IDENTdirSet(ids,info,"F2_END",EVOID); + IDENTdirSet(ids,info,"F3_START",EVOID); + IDENTdirSet(ids,info,"F3_END",EVOID); + /*F_SKY1 is not a real flat, but it must be among them*/ + IDENTdirSet(ids,info,"F_SKY1",EFLAT); + /* + ** check if there is a flats begining + */ + f_start=WADRfindEntry(info,"F_START"); + if(f_start<0) f_start=WADRfindEntry(info,"FF_START"); + /* + ** guess flat location + */ + if(f_start<0) + { for(n=f_end-1;n>0;n--) + { if(ids[n]!=EZZZZ) + if(ids[n]!=EVOID) + if(ids[n]!=EFLAT) + break; /*last flat*/ + if((info->dir[n].size==0x1000)||(info->dir[n].size==0x2000)||(info->dir[n].size==0x1040)) + { ids[n]=EFLAT; + } + } + } + /* + ** declare flats + */ + else + { ids[f_start]=EVOID; + for(n=f_end-1;n>f_start;n--) + { if((info->dir[n].size==0x1000)||(info->dir[n].size==0x2000)||(info->dir[n].size==0x1040)) + { ids[n]=EFLAT; + } + } + } +} + + +static void IDENTdirLumps(ENTRY huge *ids,struct WADINFO *info) +{ IDENTdirSet(ids,info,"PLAYPAL",ELUMP); + IDENTdirSet(ids,info,"COLORMAP",ELUMP); + IDENTdirSet(ids,info,"ENDOOM",ELUMP); + IDENTdirSet(ids,info,"ENDTEXT",ELUMP); + IDENTdirSet(ids,info,"DEMO1",ELUMP); + IDENTdirSet(ids,info,"DEMO2",ELUMP); + IDENTdirSet(ids,info,"DEMO3",ELUMP); + IDENTdirSet(ids,info,"LOADING",ELUMP); /*loading screen*/ + IDENTdirSet(ids,info,"DMXGUS",ELUMP); + IDENTdirSet(ids,info,"GENMIDI",ELUMP); + IDENTdirSet(ids,info,"TINTTAB",ELUMP); +} + +static void IDENTdirPatches(ENTRY huge *ids,struct WADINFO *info, char huge *Pnam, Int32 Pnamsz,Bool Check) +{ Int16 p_end,p_start; + Int16 n,p; + char huge *Pnames; + /* + ** find texture and pname entries + */ + IDENTdirSet(ids,info,"TEXTURE1",ETEXTUR+1); + IDENTdirSet(ids,info,"TEXTURE2",ETEXTUR+2); + IDENTdirSet(ids,info,"PNAMES",EPNAME); + /* + ** check if there are flats + */ + p_end=WADRfindEntry(info,"P_END"); + if(p_end<0) p_end=WADRfindEntry(info,"PP_END"); + if(p_end>=0) + { ids[p_end]=EVOID; + /* + ** check if there is a patch begining + */ + IDENTdirSet(ids,info,"P1_START",EVOID); + IDENTdirSet(ids,info,"P2_START",EVOID); + IDENTdirSet(ids,info,"P3_START",EVOID); + IDENTdirSet(ids,info,"P1_END",EVOID); + IDENTdirSet(ids,info,"P2_END",EVOID); + IDENTdirSet(ids,info,"P3_END",EVOID); + p_start=WADRfindEntry(info,"P_START"); + if(p_start<0) p_start=WADRfindEntry(info,"PP_START"); + /* + ** declare patches + */ + if(p_start>=0) + { ids[p_start]=EVOID; + for(n=p_end-1;n>p_start;n--) + { if(info->dir[n].size>8) + ids[n]=EPATCH; + } + } + } + /* + ** check for lost patches + ** + */ + if(Check==TRUE) + { /*checkif PNAMES is redefined*/ + n=WADRfindEntry(info,"PNAMES"); + if(n>=0) + { Pnames=(char huge *)Malloc(info->dir[n].size); + WADRseek(info,info->dir[n].start); + WADRreadBytes(info,Pnames,info->dir[n].size); + PNMinit(Pnames,info->dir[n].size); + Free(Pnames); + } + else /*init with default DOOM Pnames*/ + { PNMinit(Pnam,Pnamsz); + } + /*check for lost patches*/ + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + if(info->dir[n].size>8) + { p=PNMindexOfPatch(info->dir[n].name); /*Gcc*/ + if(p>=0) + { p=IDENTgraphic(info,n); + if(p!=ELUMP) ids[n]=EPATCH; + } + } + } + PNMfree(); + } +} + + +/* +** Ident unreferenced graphics +*/ +static void IDENTdirGraphics(ENTRY huge *ids,struct WADINFO *info) +{ Int16 n; + IDENTdirSet(ids,info,"TITLEPIC",EGRAPHIC); +#if 0 + /* not true for heretic*/ + IDENTdirSet(ids,info,"HELP1",EGRAPHIC); + IDENTdirSet(ids,info,"HELP2",EGRAPHIC); + IDENTdirSet(ids,info,"HELP",EGRAPHIC); + IDENTdirSet(ids,info,"CREDIT",EGRAPHIC); + IDENTdirSet(ids,info,"TITLE",EGRAPHIC); +#endif + /*heretic fonts*/ + IDENTdirSet(ids,info,"FONTA_S",ELUMP); + IDENTdirSet(ids,info,"FONTA_E",ELUMP); + IDENTdirSet(ids,info,"FONTB_S",ELUMP); + IDENTdirSet(ids,info,"FONTB_E",ELUMP); + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { if(info->dir[n].size>8) + { if(strncmp(info->dir[n].name,"FONT",4)==0) + { ids[n]=EGRAPHIC; + } + else if(strncmp(info->dir[n].name,"M_",2)==0) + { ids[n]=EGRAPHIC; + } + } + } + } +} +static void IDENTdirGraphics2(ENTRY huge *ids,struct WADINFO *info,Bool Check) +{ Int16 n; + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { if(info->dir[n].size>8) + { if(strncmp(info->dir[n].name,"WI",2)==0) + { ids[n]=EGRAPHIC; + } + else if(strncmp(info->dir[n].name,"ST",2)==0) + { ids[n]=EGRAPHIC; + } + else if(Check==TRUE) + { ids[n]=IDENTgraphic(info,n); + } + else + { ids[n]=EGRAPHIC; + } + } + } + } +} +/* +** Ident PC sounds +*/ +static void IDENTdirPCSounds(ENTRY huge *ids,struct WADINFO *info,Bool Check) +{ Int16 n; + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { if(info->dir[n].size>4) /*works only for DOOM, not HERETIC*/ + if(strncmp(info->dir[n].name,"DP",2)==0) + { if(Check==TRUE) + { WADRseek(info,info->dir[n].start); + if(WADRreadShort(info)==0x0) + ids[n]=ESNDPC; + } + } + } + } +} + +/* +** Ident musics +*/ +static void IDENTdirMusics(ENTRY huge *ids,struct WADINFO *info,Bool Check) +{ Int16 n; + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { if(info->dir[n].size>8) + { /*D_ for DOOM MUS_ for HERETIC*/ + if(strncmp(info->dir[n].name,"D_",2)!=0) + if(strncmp(info->dir[n].name,"MUS_",4)!=0) + continue; + if(Check==TRUE) + { /*check format*/ + WADRseek(info,info->dir[n].start); + if(WADRreadShort(info)==0x554D) + if(WADRreadShort(info)==0x1A53) + ids[n]=EMUSIC; + } + else + ids[n]=EMUSIC; + } + } + } +} +/* +** Ident sounds +*/ +static void IDENTdirSounds(ENTRY huge *ids,struct WADINFO *info, Bool Doom) +{ Int16 n; + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { if(info->dir[n].size>8) + /*works only for DOOM, not HERETIC*/ + if(strncmp(info->dir[n].name,"DS",2)==0) + { ids[n]=ESNDWAV; + } + else if(Doom==FALSE) + { WADRseek(info,info->dir[n].start); + if(WADRreadShort(info)==0x3) + if(WADRreadShort(info)==0x2B11) + ids[n]=ESNDWAV; + } + } + } +} + + +static void IDENTdirLevels(ENTRY huge *ids,struct WADINFO *info) +{ Int16 n,l;Int16 inlvl; + char name[8]; + ENTRY level=EVOID; + for(inlvl=0,n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { Normalise(name,info->dir[n].name); + l=IDENTlevel(name); + if(l>=0) + { level=(name[0]=='M')? EMAP:ELEVEL; + level|=l; + inlvl=10; + ids[n]=level; + } + else if(inlvl>0) + { l=IDENTlevelPart(name); + if(l>=0) /*level continues*/ + { ids[n]=level;inlvl--; + } + else /*level ends*/ + inlvl=0; + } + } + } +} + + + + +/* +** IWAD: we assume all is correct +** if Fast = TRUE then sounds and most graphics are reported as lumps +** (this is for merge. no problem. bad identification only to be feared in PWAD) +*/ +ENTRY huge *IDENTentriesIWAD(struct WADINFO *info,char huge *Pnam, Int32 Pnamsz,Bool Fast) +{ Int16 n; + Bool Doom=FALSE; + ENTRY huge *ids; + Phase("IWAD entry identification..."); + if(info->ok!=TRUE)Bug("IdnOeI"); + ids=(ENTRY huge *)Malloc((info->ntry)*sizeof(ENTRY)); + if(WADRfindEntry(info,"ENDTEXT")<0) /*Not Heretic*/ + if(WADRfindEntry(info,"ENDOOM")>=0) Doom=TRUE; + /* + ** identify for IWAD + */ + for(n=0;nntry;n++) + ids[n]=EZZZZ; + IDENTdirLumps(ids,info); /*fast*/ + IDENTdirSprites(ids,info,FALSE); /*fast*/ + IDENTdirFlats(ids,info); /*fast*/ + IDENTdirLevels(ids,info); /*fast*/ + IDENTdirMusics(ids,info,FALSE); /*fast*/ + IDENTdirPCSounds(ids,info,FALSE);/*fast*/ + IDENTdirPatches(ids,info,Pnam,Pnamsz,FALSE); /*fast*/ + IDENTdirGraphics(ids,info); /*fast*/ + if(Fast!=TRUE) + { IDENTdirSounds(ids,info,Doom); /*slow!*/ + IDENTdirGraphics2(ids,info,TRUE);/*slow!*/ + } + /* unidentified entries are considered LUMPs*/ + for(n=0;nntry;n++) + { + if(ids[n]==EZZZZ) + { + if(info->dir[n].size>=6) + ids[n]=ELUMP; + else + ids[n]=EDATA; + } + } + Phase("done\n"); + /* + ** check registration + */ +/* + switch(check) + { case 1: case 2: break; + default: ProgError("Please register your game."); + } +*/ + + /*the end. WADR is still opened*/ + return ids; + +} + + + +ENTRY huge *IDENTentriesPWAD(struct WADINFO *info,char huge *Pnam, Int32 Pnamsz) +{ Int16 n; + ENTRY huge *ids; + Phase("PWAD entry identification..."); + if(info->ok!=TRUE)Bug("IdnOeP"); + ids=(ENTRY huge *)Malloc((info->ntry)*sizeof(ENTRY)); + /* + ** identify for PWAD + */ + for(n=0;nntry;n++) + ids[n]=EZZZZ; +#ifdef DEBUG + Phase("\nLumps..."); +#endif + IDENTdirLumps(ids,info); +#ifdef DEBUG + Phase("\nSprit..."); +#endif + IDENTdirSprites(ids,info,TRUE); +#ifdef DEBUG + Phase("\nFlat..."); +#endif + IDENTdirFlats(ids,info); +#ifdef DEBUG + Phase("\nLev..."); +#endif + IDENTdirLevels(ids,info); +#ifdef DEBUG + Phase("\nMus..."); +#endif + IDENTdirMusics(ids,info,TRUE); +#ifdef DEBUG + Phase("\nPCsnd..."); +#endif + IDENTdirPCSounds(ids,info,TRUE); +#ifdef DEBUG + Phase("\nPatch..."); +#endif + IDENTdirPatches(ids,info,Pnam,Pnamsz,TRUE); +#ifdef DEBUG + Phase("\nGraph..."); +#endif + IDENTdirGraphics(ids,info); +#ifdef DEBUG + Phase("\nSnd..."); +#endif + IDENTdirSounds(ids,info,FALSE); +#ifdef DEBUG + Phase("\nGraph2..."); +#endif + IDENTdirGraphics2(ids,info,TRUE); + for(n=0;nntry;n++) + { if(ids[n]==EZZZZ) + { + if(info->dir[n].size>16) + ids[n]=ELUMP; + else + ids[n]=EDATA; + } + } + /* + ** unidentified entries are considered LUMPs + */ + Phase("done\n"); + /*the end. WADR is still opened*/ + return ids; +} +/***************end IDENT module *******************/ + diff --git a/src/ident.h b/src/ident.h new file mode 100644 index 0000000..41c8a86 --- /dev/null +++ b/src/ident.h @@ -0,0 +1,35 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* DOOM specifics*/ + +/* Entry Identification */ +ENTRY huge *IDENTentriesIWAD(struct WADINFO *wad,char huge *Pnam,Int32 Pnamsz,Bool Fast); +ENTRY huge *IDENTentriesPWAD(struct WADINFO *wad,char huge *Pnam,Int32 Pnamsz); +Int16 IDENTlevel(char *buffer); +/* Level Part Identification */ +Int16 IDENTlevelPart(char *name); +/* Insertion point determination*/ +Int16 IDENTinsrY(PICTYPE type,Int16 insrY,Int16 szy); +Int16 IDENTinsrX(PICTYPE type,Int16 insrX,Int16 szx); diff --git a/src/listdir.c b/src/listdir.c new file mode 100644 index 0000000..7453ab2 --- /dev/null +++ b/src/listdir.c @@ -0,0 +1,617 @@ + /* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "mkwad.h" +#include "texture.h" +#include "ident.h" + +extern char file[128]; +/* +** list WAD directory and identify entries +*/ +static char *Views[] = {"?","All ", + "Front","FrRgt","Right","RrRgt", + "Rear ","RrLft","Left ","FrLft"}; +static char *IdentView(char view) +{ switch(view) + { case '0': + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': + return Views[1+view-'0']; + } + return Views[0]; +} + +void XTRlistDir(char *doomwad,char *wadin, NTRYB select) +{ Int16 n; + static struct WADINFO pwad; + static struct WADINFO iwad; + static char buffer[128]; + ENTRY huge *iden; + ENTRY type; + Int32 ntry; + struct WADDIR huge *dir; + char *typ; + Int16 pnm;char huge *Pnam;Int32 Pnamsz=0; + + /*open iwad,get iwad directory*/ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) ProgError("Can't find PNAMES in main WAD"); + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + WADRclose(&iwad); + /**/ + if(wadin!=NULL) + { pwad.ok=0; + WADRopenR(&pwad,wadin); + iden=IDENTentriesPWAD(&pwad, Pnam, Pnamsz); + ntry= pwad.ntry; + dir= pwad.dir; + } + else + { iwad.ok=0; + WADRopenR(&iwad,doomwad); + iden=IDENTentriesIWAD(&iwad, Pnam, Pnamsz,FALSE); + ntry= iwad.ntry; + dir= iwad.dir; + } + /**/ + Free(Pnam); + /**/ + Output("\nListing of WAD directory for %s\n\n",wadin); + Output("Entry\t Size\tType\n\n"); + for(n=0;n>4),'0'+(type&0xF)); + typ=buffer; break; + case EMAP: + sprintf(buffer,"Level Map %d",(type&0xFF)); + typ=buffer; break; + case ETEXTUR: typ="List of textures"; break; + case EPNAME: typ="List of wall patches"; break; + case ESOUND: typ="Sound";break; + case EMUSIC: typ="Music";break; + case EGRAPHIC: + if((type&0xFF)==0xFF) + { typ="Graphic"; + } + else + { sprintf(buffer,"Graphic"); + typ=buffer; + } + break; + case ELUMP: typ="Lump of raw data"; break; + case ESPRITE: typ="Sprite"; + if(strncmp(dir[n].name,"ARTI",4)==0) + { sprintf(buffer,"Artifact\t%4.4s",&(dir[n].name[4])); + } + else if(dir[n].name[6]!='\0') + { sprintf(buffer,"Sprite %4.4s\tph:%c %s\tph:%c %s inv.", + dir[n].name,dir[n].name[4],IdentView(dir[n].name[5]),dir[n].name[6],IdentView(dir[n].name[7])); + } + else + { sprintf(buffer,"Sprite %4.4s\tph:%c %s", + dir[n].name,dir[n].name[4],IdentView(dir[n].name[5])); + } + typ = buffer; break; + case EPATCH: typ="Wall patch"; break; + case EFLAT: typ="Flat";break; + case EZZZZ: typ="?";break; + } + switch(type) + { + case EPATCH1: typ="Wall patch 1"; break; + case EPATCH2: typ="Wall patch 2"; break; + case EPATCH3: typ="Wall patch 3"; break; + case EFLAT1: typ="Flat 1"; break; + case EFLAT2: typ="Flat 2"; break; + case EFLAT3: typ="Flat 3"; break; + case ESNDPC: typ = "PC sound"; break; + case ESNDWAV: typ = "WAV sound"; break; + } + Output("%-8.8s %8ld\t%s\n",dir[n].name,dir[n].size,typ); + } + if(wadin!=NULL) + WADRclose(&pwad); + else + WADRclose(&iwad); + Free(iden); +} + + +#if defined(DeuTex) + + +#if DT_OS == 'o' +# if DT_CC = 'b' +int _USERENTRY XTRdirCmp(const void *d1,const void *d2) +# else +int _Optlink XTRdirCmp(const void *d1,const void *d2) +# endif +#else +int XTRdirCmp(const void *d1,const void *d2) +#endif +{ Int32 res; + struct WADDIR *dir1=(struct WADDIR *)d1; + struct WADDIR *dir2=(struct WADDIR *)d2; + res= (dir1->start)-(dir2->start); + if(res<0)return -1; + if(res>0)return 1; + res = (dir1->size)-(dir2->size); + if(res<0)return -1; + if(res>0)return 1; + return 0; +} + +void XTRvoidSpacesInWAD(char *wadin) +{ Int16 n; + static struct WADINFO pwad; + Int32 ntry; + struct WADDIR huge *dir; + Int32 startpos,lastpos,ll,diff,wtotal; + Int32 w3,w20,w100,w1000,w10000,w100000; + wtotal=w3=w20=w100=w1000=w10000=w100000=0; + + pwad.ok=0; + WADRopenR(&pwad,wadin); + ntry= pwad.ntry; + dir= pwad.dir; + qsort(dir,(size_t)ntry,sizeof(struct WADDIR),XTRdirCmp); + Output("\nListing of unused spaces in WAD %s\n",wadin); + lastpos=4+4+4; + for(n=0;n=4) /*suppress word alignement*/ + Output(" At offset 0x%8.8lx, %ld bytes wasted\n",startpos,diff); + } + Output("\nRepartition of wasted bytes:\n"); + Output(" All blocks<=3 \t%ld\n",w3); + Output(" All blocks<=20 \t%ld\n",w20); + Output(" All blocks<=100 \t%ld\n",w100); + Output(" All blocks<=1000 \t%ld\n",w1000); + Output(" All blocks<=10000\t%ld\n",w10000); + Output(" All blocks> 10000\t%ld\n",w100000); + Output(" \t-------\n"); + Output(" Total wasted bytes\t%ld\n",wtotal); + WADRclose(&pwad); +} +#endif + + +struct SIDEDEF +{ Int16 ofsx; /* X offset for texture */ + Int16 ofsy; /* Y offset for texture */ + char Above[8]; /* texture name for the part above */ + char Below[8]; /* texture name for the part below */ + char Center[8]; /* texture name for the regular part */ + Int16 Sector; /* adjacent sector */ +}; +/* +** Check a level +** Assumes TEXTURES are already read somewhere. +*/ +void CheckTexture(char huge *tex,Bool IsDef) +{ int n; + char Name[8]; + for(n=0;n<8;n++) + { Name[n]=tex[n]; + if(tex[n]=='\0')break; + } + Normalise(Name,Name); + switch(Name[0]) + { case '-': case '\0': break; + default: + if(IsDef==TRUE) /*if we only wish to declare the tex*/ + { TXUfakeTex(Name); + } + else + { if(TXUexist(Name)==FALSE) + Output("Warning: Undefined Sidedef %.8s\n",Name); + } + } +} + +/* +**check textures +** IsDef=TRUE if we just wish to declare textures +*/ +void CheckSideDefs(struct WADINFO *pwad,Int32 start,Int32 size,Bool IsDef) +{ struct SIDEDEF huge *sid; + struct SIDEDEF huge *side; + Int32 s; + sid = (struct SIDEDEF huge *)Malloc(size); + WADRseek(pwad,start); + WADRreadBytes(pwad,(char huge *)sid,size); + for(s=0;(s*sizeof(struct SIDEDEF))Above,IsDef); + CheckTexture(side->Below,IsDef); + CheckTexture(side->Center,IsDef); + } + Free(sid); +} +void CheckLevels(struct WADINFO *pwad, Bool IsDef) +{ Int16 lev,lin,id,top; + Int32 ntry=pwad->ntry; + struct WADDIR huge *pdir=pwad->dir; + for(lev=0;lev=0) + { for(lin=lev;lintop) break; + if(strncmp(pdir[lin].name,"SIDEDEFS",8)==0) + { Output("\nChecking LEVEL %.8s\n\n",pdir[lev].name); + CheckSideDefs(pwad,pdir[lin].start,pdir[lin].size,IsDef); + } + } + } + } +} +/* +** Test a PWAD +** +** this is absolutely sub optimal. +*/ +void XTRstructureTest(char *doomwad,char *wadin) +{ static struct WADINFO pwad,iwad; + char huge *Pnames; + Int16 p,pnm,nbPatchs; + Int32 size; + static struct PICH{Int16 Xsz;Int16 Ysz;} pich; + Int16 huge *PszX; + static char name[8]; + char huge *buffer; + Int16 cs,ce; + + /*read PNAME in wad, if defined*/ + Phase("Reading WADs\n"); + iwad.ok=0; + WADRopenR(&iwad,doomwad); + pwad.ok=0; + WADRopenR(&pwad,wadin); + Phase("Reading Patches\n"); + pnm=WADRfindEntry(&pwad,"PNAMES"); + if(pnm>=0) + { size=pwad.dir[pnm].size; + Pnames=(char huge *)Malloc(size); + WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,Pnames,size); + } + else + { pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0)ProgError("PNAMES not found"); + size=iwad.dir[pnm].size; + Pnames=(char huge *)Malloc(size); + WADRseek(&iwad,iwad.dir[pnm].start); + WADRreadBytes(&iwad,Pnames,size); + } + PNMinit(Pnames,size); + Free(Pnames); + /* + ** find each PNAME and identify Xsz Ysz + */ + Phase("Checking Patches\n"); + nbPatchs=PNMgetNbOfPatch(); + PszX=(Int16 huge *)Malloc(nbPatchs*sizeof(Int16)); + for(p=0;p=0) + { WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,(char huge *)&pich,sizeof(struct PICH)); + } + else + { pnm=WADRfindEntry(&iwad,name); + if(pnm<0) + /*ProgError("Patch %.8s not found",name);*/ + Output("Warning: Patch %.8s not found\n",name); + else + { WADRseek(&iwad,iwad.dir[pnm].start); + WADRreadBytes(&iwad,(char huge *)&pich,sizeof(struct PICH)); + } + } + PszX[p] = peek_i16_le (&pich.Xsz); + } + /* + ** read TEXTURES + */ + Phase("Reading Textures\n"); + pnm=WADRfindEntry(&pwad,"TEXTURE1"); + if(pnm>=0) + { /* read texture */ + buffer=(char huge *)Malloc(pwad.dir[pnm].size); + WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,buffer,pwad.dir[pnm].size); + TXUinit(); + TXUreadTEXTURE(buffer,pwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + /*for each textures, check what is covered */ + Phase("Checking TEXTURE1\n"); + TXUcheckTex(nbPatchs,PszX); + TXUfree(); + } + pnm=WADRfindEntry(&pwad,"TEXTURE2"); + if(pnm>=0) + { /* read texture */ + buffer=(char huge *)Malloc(pwad.dir[pnm].size); + WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,buffer,pwad.dir[pnm].size); + TXUinit(); + TXUreadTEXTURE(buffer,pwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + /*for each textures, check what is covered */ + Phase("Checking TEXTURE2\n"); + TXUcheckTex(nbPatchs,PszX); + TXUfree(); + } + Free(PszX); + /* + ** check if all textures composing walls are here + ** + */ + Phase("Checking Level SIDEDEFS for missing textures\n"); + TXUinit(); + pnm=WADRfindEntry(&pwad,"TEXTURE1"); + if(pnm>=0) + { buffer=(char huge *)Malloc(pwad.dir[pnm].size); + WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,buffer,pwad.dir[pnm].size); + TXUreadTEXTURE(buffer,pwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + } + else + { pnm = WADRfindEntry(&iwad,"TEXTURE1"); + if(pnm>=0) + { buffer=(char huge *)Malloc(iwad.dir[pnm].size); + WADRseek(&iwad,iwad.dir[pnm].start); + WADRreadBytes(&iwad,buffer,iwad.dir[pnm].size); + TXUreadTEXTURE(buffer,iwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + } + } + pnm=WADRfindEntry(&pwad,"TEXTURE2"); + if(pnm>=0) + { buffer=(char huge *)Malloc(pwad.dir[pnm].size); + WADRseek(&pwad,pwad.dir[pnm].start); + WADRreadBytes(&pwad,buffer,pwad.dir[pnm].size); + TXUreadTEXTURE(buffer,pwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + } + else + { pnm = WADRfindEntry(&iwad,"TEXTURE2"); + if(pnm>=0) + { buffer=(char huge *)Malloc(iwad.dir[pnm].size); + WADRseek(&iwad,iwad.dir[pnm].start); + WADRreadBytes(&iwad,buffer,iwad.dir[pnm].size); + TXUreadTEXTURE(buffer,iwad.dir[pnm].size,NULL,0,TRUE); + Free(buffer); + } + } + CheckLevels(&pwad,FALSE); + TXUfree(); + PNMfree(); + WADRclose(&iwad); + /* + ** check sprite markers + ** + */ + Phase("Checking Sprites\n"); + for(cs=ce=0,p=0;p1) ProgError("Duplicate S_START"); + if(ce>1) ProgError("Duplicate S_END"); + if((cs>0)&(ce<1)) Output("Warning: S_START but no S_END\n"); + if((cs<1)&(ce<1)) + Info("No need to check SPRITES.\n"); + else + { for(cs=ce=0,p=0;p1) Output("Warning: Duplicate F_START\n"); + if(ce>1) Output("Warning: Duplicate F_END\n"); + if((cs>0)&(ce<1)) Output("Warning: F_START but no F_END\n"); + if((cs<1)&(ce<1))Info("No need to check FLATS.\n"); + WADRclose(&pwad); +} + + + + +#if defined(DeuTex) +/* +** Test a PWAD +** +*/ +void XTRtextureUsed(char *wadin) +{ static struct WADINFO pwad; + /*read PNAME in wad, if defined*/ + Phase("listing texture used in the levels of %s\n",wadin); + pwad.ok=0; + WADRopenR(&pwad,wadin); + /* + ** list all textures composing walls + */ + TXUinit(); + CheckLevels(&pwad,TRUE); + Output("List of textures used in %s\n\n",wadin); + TXUlistTex(); + TXUfree(); + WADRclose(&pwad); +} +#endif + + +#if defined(DeuTex) + +/* +** Detect duplicate entries +** ShowIdx = TRUE if we also output the indexes +** +** Optimise for speed with a CRC-based check +*/ +void XTRcompakWAD(char *DataDir,char *wadin, char *texout,Bool ShowIdx) +{ static struct WADINFO pwad; + struct WADDIR huge *pdir; + Int16 pnb; + Int16 p,bas,tst,ofsx,ofsy; + Int32 size,rsize,sz; + Bool huge *psame; + FILE *out; + char huge *bbas; + char huge *btst; + Phase("Detecting duplicate entries in WAD %s\n",wadin); + pwad.ok=0; + WADRopenR(&pwad,wadin); + pnb=(Int16)pwad.ntry; + pdir=pwad.dir; + psame=(Bool huge *)Malloc(pnb*sizeof(Bool)); + for(p=0;p=8)&&(ShowIdx==TRUE)) + { WADRseek(&pwad,pdir[bas].start); + WADRreadBytes(&pwad,bbas,8); + ofsx=((bbas[5]<<8)&0xFF00)+(bbas[4]&0xFF); + ofsy=((bbas[7]<<8)&0xFF00)+(bbas[6]&0xFF); + fprintf(out,"%-8.8s\t%d\t%d\n",pdir[bas].name,ofsx,ofsy); + } + else + fprintf(out,"%-8.8s\n",pdir[bas].name); + for(tst=bas+1;tstMEMORYCACHE)? MEMORYCACHE : size-rsize; + WADRseek(&pwad,pdir[bas].start+rsize); + WADRreadBytes(&pwad,bbas,sz); + WADRseek(&pwad,pdir[tst].start+rsize); + WADRreadBytes(&pwad,btst,sz); + for(p=0;p=0;l--) + { + if(strncmp(LISspr.Lst[l].name,root,4)==0) + { /*2nd unwanted: replace by 0*/ + if(LISunwantedPhase(&(LISspr.Lst[l].name[6]),phase,view,AllViews)==TRUE) + { LISspr.Lst[l].name[6]='\0'; + LISspr.Lst[l].name[7]='\0'; + Okay=TRUE; + } + /*1st unwanted: replace by second*/ + if(LISunwantedPhase(&(LISspr.Lst[l].name[4]),phase,view,AllViews)==TRUE) + { LISspr.Lst[l].name[4]=LISspr.Lst[l].name[6]; + LISspr.Lst[l].name[5]=LISspr.Lst[l].name[7]; + LISspr.Lst[l].name[6]='\0'; + LISspr.Lst[l].name[7]='\0'; + Okay=TRUE; + } + /*neither 1st nor second wanted: delete*/ + if(LISspr.Lst[l].name[4]=='\0') + { sz=LISspr.Pos-(l+1); + if(sz>0) + Memcpy(&(LISspr.Lst[l]),&(LISspr.Lst[l+1]),(sz)*sizeof(struct WADDIR)); + LISspr.Pos--; + Okay=TRUE; + } + } + } + return Okay; +} +/* +** list management. very basic. no hash table. +*/ +static void LISaddMission(struct WADDIR huge *dir, Int16 found) +{ + Int16 l=0,dummy=0; + /*check*/ + if(LISlmp.Pos>=LISlmp.Top) Bug("LisTsm"); /*level list too small*/ + /*try to locate mission entry at l*/ + for(l=0;lLISlmp.Pos) LISlmp.Pos=dummy; + if(LISlmp.Pos>LISlmp.Top) Bug("LisTsm"); /*level list too small*/ + /*copy new level, or replace existing*/ + Memcpy((&(LISlmp.Lst[l])),(dir),found*sizeof(struct WADDIR)); +} + +static void LISadd(struct ELIST *L,struct WADDIR huge *dir) +{ /*check current position*/ + if((L->Pos)>=L->Top) Bug("LisSml"); /*list count too small*/ + /* ADD in List */ + Memcpy(&(L->Lst[(L->Pos)]),(dir),sizeof(struct WADDIR)); + (L->Pos)++; /*increase pointer in list*/ + return; +} +/* +** Find in list, and replace if exist +** +*/ +static Bool LISfindRplc(struct ELIST *L,struct WADDIR huge *dir) +{ Int16 l; + for(l=0;l<(L->Pos);l++) + if(strncmp(L->Lst[l].name,dir[0].name,8)==0) + { Memcpy(&(L->Lst[l]),&(dir[0]),sizeof(struct WADDIR)); + return TRUE; + } + return FALSE; /*not found*/ +} + /* Substitute In List +** if entry exist, it is substituted, else added at the end of list +** suitable for LUMPS and SPRITES +** but generally those shall not be added: they may not be recognized +*/ +static void LISsubstit(struct ELIST *L,struct WADDIR huge *dir) +{ /* SUBSTIT in List */ + if(LISfindRplc(L,dir)==TRUE) return; + Warning("entry %.8s might be ignored by DOOM.",dir[0].name); + LISadd(L,dir); +} +/* Move In List +** if entry already exist, destroy it, and put at the end +** suitable for PATCH and FLATS (to define new animations) +*/ +static void LISmove(struct ELIST *L,struct WADDIR huge *dir) +{ Int16 l,sz; + for(l=0;l<(L->Pos);l++) + if(strncmp(L->Lst[l].name,dir[0].name,8)==0) + { /*entry already exist. destroy it*/ + sz=(L->Pos)-(l+1); + if(sz>0) Memcpy(&(L->Lst[l]),&(L->Lst[l+1]),(sz)*sizeof(struct WADDIR)); + (L->Pos)--; + } + LISadd(L,dir); +} + /* Put Sprites In List + ** if entry already exist, replace it + ** if entry does not exist, check if it does not obsolete + ** an IWAD sprite entry + ** suitable for SPRITES only + */ /***/ +static void LISaddSprite(struct WADDIR huge *dir,Bool Warn) +{ Bool Okay=FALSE; + /*warn: FALSE= no warning. TRUE = warn.*/ + /* If entry already exists, replace it*/ + if(LISfindRplc(&LISspr,dir)==TRUE) return; + /* Entry does not exist. Check that this sprite + ** viewpoint doesn't obsolete other sprite viewpoints. + */ + if(dir[0].name[4]!='\0') + { Okay|=LISdeleteSprite(dir[0].name,dir[0].name[4],dir[0].name[5]); + if(dir[0].name[6]!='\0') + Okay|=LISdeleteSprite(dir[0].name,dir[0].name[6],dir[0].name[7]); + } + if((Okay==FALSE)&&(Warn==TRUE)) + { Warning("entry %.8s might be ignored by DOOM.",dir[0].name); + } + LISadd(&LISspr,dir); +} +/* +** create a new directory list +** +*/ +static void LISmakeNewDir(struct WADINFO *nwad,Int16 S_END,Int16 P_END,Int16 F_END,Int16 Pn,Int16 Fn) +{ Int16 n; + struct WADDIR huge *dir; + /*levels,lumps, graphics into new dir*/ + if(LISlmp.Pos>0) + { for(n=0;nstart,dir->size,dir->name); + } + } + /*sprites into new dir*/ + if(LISspr.Pos>0) + { WADRdirAddPipo(nwad,0,0,((S_END & X_START)? "S_START":"SS_START")); + for(n=0;nstart,dir->size,dir->name); + } + WADRdirAddPipo(nwad,0,0,((S_END & X_END)? "S_END":"SS_END")); + } + /*patch 1,2,3 into new dir*/ + if(LISpat.Pos>0) + { WADRdirAddPipo(nwad,0,0,((P_END & X_START)?"P_START":"PP_START")); + if((Pn>=1)&&(P_END & X_START)) + WADRdirAddPipo(nwad,0,0,"P1_START"); + for(n=0;nstart,dir->size,dir->name); + } + if((Pn>=1)&&(P_END & X_START)) + { WADRdirAddPipo(nwad,0,0,"P1_END"); + if(Pn>=2) + { WADRdirAddPipo(nwad,0,0,"P2_START"); + WADRdirAddPipo(nwad,0,0,"P2_END"); + if(Pn>=3) + { WADRdirAddPipo(nwad,0,0,"P3_START"); + WADRdirAddPipo(nwad,0,0,"P3_END"); + } + } + } + WADRdirAddPipo(nwad,0,0,((P_END & X_END)?"P_END":"PP_END")); + } + /*flat 1,2,3 into new dir*/ + if(LISflt.Pos>0) + { WADRdirAddPipo(nwad,0,0,((F_END & X_START)?"F_START":"FF_START")); + if((Fn>=1)&&(F_END & X_START)) + WADRdirAddPipo(nwad,0,0,"F1_START"); + for(n=0;nstart,dir->size,dir->name); + } + if((Fn>=1)&&(F_END & X_START)) + { WADRdirAddPipo(nwad,0,0,"F1_END"); + if(Fn>=2) + { WADRdirAddPipo(nwad,0,0,"F2_START"); + WADRdirAddPipo(nwad,0,0,"F2_END"); + if(Fn>=3) + { WADRdirAddPipo(nwad,0,0,"F3_START"); + WADRdirAddPipo(nwad,0,0,"F3_END"); + } + } + } + WADRdirAddPipo(nwad,0,0,((F_END & X_END)?"F_END":"FF_END")); + } +} + + + + +/* +** merge IWAD and PWAD directories +** This function is a good example of COMPLETELY INEFFICIENT CODING. +** but since it's so hard to have it work correctly, +** Optimising was out of question. +** +** +*/ +struct WADDIR huge *LISmergeDir(Int32 *pNtry,Bool Append,Bool Complain,NTRYB select, + struct WADINFO *iwad,ENTRY huge *iiden,Int32 iwadflag, + struct WADINFO *pwad,ENTRY huge *piden,Int32 pwadflag) +{ + struct WADDIR huge *idir; + struct WADDIR huge *pdir; + struct WADINFO nwad; + Int16 inb, pnb; + Int16 i,p,found; + struct WADINFO *refwad; + ENTRY type; + Int16 Pn=0;/*0=nothing 1=P1_ 2=P2_ 3=P3_*/ + Int16 Fn=0;/*0=nothing 1=F1_ 2=F2_ 3=F3_*/ + Bool NoSprite=FALSE; /*no sprites declared. seek in graphics*/ + Int16 S_END=X_NONE; + Int16 F_END=X_NONE; + Int16 P_END=X_NONE; + /* + ** select Sprites markers (tricky hack!) + */ + refwad = ((Append!=TRUE)||(select&BSPRITE))? iwad : pwad; + if(WADRfindEntry(refwad,"S_END")>=0)/*full sprite list is here*/ + { S_END|=X_END; + } + if(WADRfindEntry(refwad,"S_START")>=0)/*full sprite list is here*/ + { S_END|=X_START; + } + if(!(select&BSPRITE)) + { if(S_END & X_END) /*sprites already appended. keep it so.*/ + { Complain=FALSE; + } + } + /* + ** select Patches markers (tricky hack!) + */ + refwad = (Append!=TRUE)? iwad : pwad; + if(WADRfindEntry(refwad,"P_END")>=0)/*full patch list is here*/ + { P_END|=X_END; + if(WADRfindEntry(refwad,"P3_END")>=0) Pn=3; + else if(WADRfindEntry(refwad,"P2_END")>=0) Pn=2; + else if(WADRfindEntry(refwad,"P1_END")>=0) Pn=1; + } + if(WADRfindEntry(refwad,"P_START")>=0)/*full patch list is here*/ + { P_END|=X_START; + } + /* + ** select Flats markers (tricky hack!) + */ + refwad = ((Append!=TRUE)||(select&BFLAT))? iwad : pwad; + if(WADRfindEntry(refwad,"F_END")>=0) /*full flat list is here*/ + { F_END|=X_END; + if(WADRfindEntry(refwad,"F3_END")>=0) Fn=3; + else if(WADRfindEntry(refwad,"F2_END")>=0) Fn=2; + else if(WADRfindEntry(refwad,"F1_END")>=0) Fn=1; + } + if(WADRfindEntry(refwad,"F_START")>=0) /*full flat list is here*/ + { F_END|=X_START; + } + if(!(select&BFLAT)) + { if(F_END & X_END) /*flats already appended. keep it so.*/ + { Complain=FALSE; + } + } + /* + ** make lists of types lists + */ + inb= (Int16)iwad->ntry; + pnb= (Int16)pwad->ntry; + idir=iwad->dir; + pdir=pwad->dir; + /*alloc memory for a fake new wad*/ + nwad.ok=0; + WADRopenPipo(&nwad,(Int32)inb+(Int32)pnb+40); + /*init lists*/ + LISinitLists(); + /*identify the elements and count types*/ + LIScountTypes(iiden,(Int16)iwad->ntry); + LIScountTypes(piden,(Int16)pwad->ntry); + LISallocLists(); + /* distribute IWAD enties*/ + for(i=0;i.A +** Lempel-Zim compression based on "compress". +** +** Copyright (C) 1989 by Jef Poskanzer. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** The Graphics Interchange Format(c) is the Copyright property of +** CompuServe Incorporated. GIF(sm) is a Service Mark property of +** CompuServe Incorporated. +** +** This coder is included in DeuTex only because that of David Kaplan +** didn't work +** +*/ + + +#include "deutex.h" +#include "tools.h" + +/*compile only for DeuTex*/ +#if defined DeuTex + + +#if NEWGIFE && NEWGIFD +/*nothing, for new gif encoder*/ +#else +/* + * General DEFINEs + */ + +#define BITS 12 +#define HSIZE 5003 /* 80% occupancy */ + +typedef char char_type; +typedef Int16 code_int; /* 2**BITS values of type int, and also -1 */ +typedef Int32 count_int; + + + +/*static Int16 table[2][(1< + + +#if NEWGIFE +#else +static Int16 n_bits; /* number of bits/code */ +static Int16 maxbits; /* user settable max # bits/code */ +static code_int maxcode; /* maximum code, given n_bits */ +static code_int maxmaxcode; /* should NEVER generate this code */ +# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) + +#define HashTabOf(i) htab[i] +#define CodeTabOf(i) codetab[i] + +static code_int hsize; /* for dynamic table sizing */ + +static UInt32 cur_accum; +static Int16 cur_bits; + +/* + * To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**BITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) CodeTabOf(i) +#define tab_suffixof(i) ((char_type*)(htab))[i] +#define de_stack ((char_type*)&tab_suffixof((code_int)1< 0 ) goto probe; +nomatch: + output ( (code_int) ent ); + out_count++; + ent = c; + + if ( free_ent < maxmaxcode ) + { CodeTabOf (i) = free_ent++; /* code -> hashtable */ + HashTabOf (i) = fcode; + } + else + cl_block(); + } + /* + * Put out the final code. + */ + output( (code_int)ent ); + ++out_count; + output( (code_int) EOFCode ); +} + +/***************************************************************** + * TAG( output ) + * + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (Int32)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits Int32. + * Algorithm: + * Maintain a BITS character long buffer (so that 8 codes will + * fit in it exactly). Use the VAX insv instruction to insert each + * code in turn. When the buffer fills up empty it and start over. + */ + +static UInt32 masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, + 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, + 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +static void output( code_int code) +{ + cur_accum &= masks[ cur_bits ]; + if( cur_bits > 0 ) + cur_accum |= ((Int32)code << cur_bits); + else + cur_accum = code; + cur_bits += n_bits; + while( cur_bits >= 8 ) + { char_out( (UInt16)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if ( free_ent > maxcode || clear_flg ) + { if( clear_flg ) + { maxcode = (code_int)(MAXCODE (n_bits = g_init_bits)); + clear_flg = 0; + } + else + { n_bits++; + if ( n_bits == maxbits ) + maxcode = maxmaxcode; + else + maxcode = (code_int)(MAXCODE(n_bits)); + } + } + if( code == EOFCode ) + { /* At EOF, write the rest of the buffer.*/ + while( cur_bits > 0 ) + { char_out( (UInt16)(cur_accum & 0xff) ); + cur_accum >>= 8; + cur_bits -= 8; + } + flush_char(); + fflush( g_outfile ); + } +} + +/* + * Clear out the hash table + */ +static void cl_block () /* table clear for block compress */ +{ cl_hash ( (count_int) hsize ); + free_ent = (code_int)(ClearCode + 2); + clear_flg = 1; + output( (code_int)ClearCode ); +} + +static void cl_hash(register count_int hsize) /* reset code table */ +{ count_int *htab_p = htab+(int)hsize; + register Int32 i; + register Int32 m1 = -1; + i = hsize - 16; + do + { /* might use Sys V memset(3) here */ + *(htab_p-16) = m1; + *(htab_p-15) = m1; + *(htab_p-14) = m1; + *(htab_p-13) = m1; + *(htab_p-12) = m1; + *(htab_p-11) = m1; + *(htab_p-10) = m1; + *(htab_p-9) = m1; + *(htab_p-8) = m1; + *(htab_p-7) = m1; + *(htab_p-6) = m1; + *(htab_p-5) = m1; + *(htab_p-4) = m1; + *(htab_p-3) = m1; + *(htab_p-2) = m1; + *(htab_p-1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + + for ( i += 16; i > 0; --i ) + *--htab_p = m1; +} + +/****************************************************************************** + * + * GIF Specific routines + * + ******************************************************************************/ + +/* + * Number of characters so far in this 'packet' + */ +static Int16 a_count; + +/* + * Set up the 'byte output' routine + */ +static void char_init() +{ a_count = 0; +} + +/* + * Define the storage for the packet accumulator + */ +static char accum[ 256 ]; + +/* + * Add a character to the end of the current packet, and if it is 254 + * characters, flush the packet to disk. + */ +static void char_out( Int16 c) +{ accum[ a_count++ ] = (char)c; + if( a_count >= 254 ) + flush_char(); +} + +/* + * Flush the packet to disk, and reset the accumulator + */ +static void flush_char() +{ if( a_count > 0 ) + { fputc( a_count, g_outfile ); + fwrite( accum, 1, a_count, g_outfile ); + a_count = 0; + } +} +#endif /*NEWGIFE*/ +/* The End */ + + + + + +/* +** +** Gif decompression +** +*/ + +#if NEWGIFD +#else +#define TRUE 1 +#define FALSE 0 +#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) == 1) + +static Int16 ZeroDataBlock = FALSE; + +Int16 GetDataBlock(FILE *fd, unsigned char *buf) +{ unsigned char count; + if (! ReadOK(fd,&count,1)) + { /* pm_message("error in getting DataBlock size" ); */ + return -1; + } + ZeroDataBlock = (count == 0)? TRUE :FALSE; + if ((count != 0) && (! ReadOK(fd, buf, count))) + { /* pm_message("error in reading DataBlock" ); */ + return -1; + } + return (Int16)(count&0xFF); +} + +Int16 GetCode(FILE *fd, Int16 code_size, Int16 flag) +{ static unsigned char buf[280]; + static Int16 curbit, lastbit, done, last_byte; + Int16 i, j, ret; + unsigned char count; + + if (flag) + { curbit = 0; + lastbit = 0; + done = FALSE; + return 0; + } + + if ( (curbit+code_size) >= lastbit) + { if (done) + { /*if (curbit >= lastbit)("ran off the end of my bits" );*/ + return -1; + } + buf[0] = buf[last_byte-2]; + buf[1] = buf[last_byte-1]; + if ((count = (unsigned char)GetDataBlock(fd, buf+(2) )) == 0) + done = TRUE; + last_byte = (Int16)(2 + count); + curbit = (Int16)((curbit - lastbit) + 16); + lastbit = (Int16)((2+count)*8) ; + } + + ret = 0; + for (i = curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + curbit += code_size; + return ret; +} + +Int16 LWZReadByte(FILE *fd, Int16 flag, Int16 input_code_size) +{ static Int16 fresh = FALSE; + Int16 code, incode; + register Int16 i; + static Int16 code_size, set_code_size; + static Int16 max_code, max_code_size; + static Int16 firstcode, oldcode; + static Int16 clear_code, end_code; + static Int16 *sp; + if (flag) + { set_code_size = input_code_size; + code_size = (Int16)(set_code_size+1); + clear_code = (Int16)(1 << set_code_size) ; + end_code = (Int16)(clear_code + 1); + max_code_size = (Int16)(2*clear_code); + max_code = (Int16)(clear_code+2); + GetCode(fd, 0, TRUE); + fresh = TRUE; + for (i = 0; i < clear_code; ++i) + { table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1< stack) return *--sp; + + while ((code = GetCode(fd, code_size, FALSE)) >= 0) + { if (code == clear_code) + { for (i = 0; i < clear_code; ++i) + { table[0][i] = 0; + table[1][i] = i; + } + for (; i < (1< 0); + if (count != 0) + { /* pm_message("missing EOD in data stream (common occurence)");*/ + } + return -2; + } + + incode = code; + if (code >= max_code) + { *sp++ = firstcode; + code = oldcode; + } + while (code >= clear_code) + { *sp++ = table[1][code]; + if (code == table[0][code]) + { /*("circular table entry BIG ERROR");*/ + return -1; + } + code = table[0][code]; + } + *sp++ = firstcode = table[1][code]; + if ((code = max_code) <(1<= max_code_size) &&(max_code_size < (1< stack) return *--sp; + } + return code; +} +#endif /*NEWGIFD*/ +#endif /*DeuTex*/ + diff --git a/src/merge.c b/src/merge.c new file mode 100644 index 0000000..237e36f --- /dev/null +++ b/src/merge.c @@ -0,0 +1,605 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "mkwad.h" +#include "texture.h" +#include "ident.h" +#include "lists.h" +#include "merge.h" + +#include + + +/********** HDR fiddling with WAD ******************/ + +/* +** old references +** +*/ +static const Int32 HDRdirSz=5*sizeof(struct WADDIR); +static struct WADDIR HDRdir[6]; +/* +** Take some entries from a WAD +*/ +static void HDRplunderWad(struct WADINFO *rwad,struct WADINFO *ewad) +{ char huge *data; + Int32 wsize,sz=0; + Int32 ostart,osize; + Int16 n; + Int32 oldfilesz; + /* + ** calculate required size + */ + oldfilesz=WADRposition(rwad); /*old file size*/ + /* + ** copy entries from WAD + */ + Phase("Copying entries from Wad (Please wait).\n"); + data = (char huge *)Malloc(MEMORYCACHE); + for(n=0;n<(rwad->ntry);n++) + { + if((n&0x7F)==0) Phase("."); + ostart=rwad->dir[n].start; + osize=rwad->dir[n].size; + /*detect external entries */ + if(ostart&EXTERNAL) + { /*update new directory*/ + WADRalign4(rwad); + rwad->dir[n].start=WADRposition(rwad); + /*get entry size*/ + if(osize>0) + { /*copy old entry */ + WADRseek(ewad,ostart&(~EXTERNAL)); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:osize-wsize; + WADRreadBytes(ewad,data,sz); + if(WADRwriteBytes2(rwad,data,sz)<0) + { WADRchsize(rwad,oldfilesz); + ProgError("Not enough disk space."); + break; + } + + } + } + } + } + Phase("\n"); + Free(data); +} +/* +** Copy a WAD, and link to it's entries +*/ +static Int32 HDRinsertWad(struct WADINFO *rwad,struct WADINFO *ewad,Int32 *pesize) +{ char huge *data; + Int32 wsize,sz=0; + Int32 estart,esize; + Int16 n; + Int32 oldfilesz; + /* + ** calculate required size + */ + oldfilesz=WADRposition(rwad); /*old file size*/ + WADRalign4(rwad); + estart=WADRposition(rwad); + WADRseek(ewad,0); + esize=ewad->maxpos; + Phase("Inserting Wad file into Wad.\n"); + data = (char huge *)Malloc(MEMORYCACHE); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:esize-wsize; + WADRreadBytes(ewad,data,sz); + if(WADRwriteBytes2(rwad,data,sz)<0) + { WADRchsize(rwad,oldfilesz); + ProgError("Not enough disk space."); + break; + } + if((wsize&0xF000)==0) Phase("."); + } + Free(data); + for(n=0;n<(rwad->ntry);n++) + { /*detect external entries */ + if((rwad->dir[n].start)&EXTERNAL) + { /*update new directory*/ + rwad->dir[n].start &= (~EXTERNAL); + rwad->dir[n].start += estart; + } + } + Phase("\n"); + *pesize= esize; + return estart; +} +/*********** End fiddling with WAD ********************/ + + + +/******************* WAD restoration **********************/ +void HDRrestoreWAD(char *wadres) +{ struct WADINFO rwad; + Int32 dirpos,ntry,n; + Int32 rwadstart=0,rwadsize=0; + Int32 ewadstart=0,ewadsize=0; + static char ewadname[8]; + static char ewadfile[40]; + char huge *data; + Int32 size=0,wsize=0,sz=0; + Int32 time; + FILE *fp; + Bool Fail; + Phase("Attempting to restore WAD %s\n",wadres); + /*open DOOM.WAD*/ + rwad.ok=0; + WADRopenR(&rwad,wadres); + + /*get position of fake directory entry, reference to old dir*/ + dirpos = rwad.dirpos - HDRdirSz; + WADRseek(&rwad,dirpos); + WADRreadBytes(&rwad,(char huge *)HDRdir,HDRdirSz); + Fail=FALSE; + if(peek_i32_le (&HDRdir[0].start) != 0x24061968L) Fail=TRUE; + if(peek_i32_le (&HDRdir[0].size) != 666L) Fail=TRUE; + if(strncmp(HDRdir[0].name,"IZNOGOOD",8)!=0) Fail=TRUE; + if(Fail != FALSE) + { if((n=WADRfindEntry(&rwad,"_DEUTEX_"))>=0) + if(rwad.dir[n].size>=HDRdirSz) + { dirpos=rwad.dir[n].start; + WADRseek(&rwad,dirpos); + WADRreadBytes(&rwad,(char huge *)HDRdir,HDRdirSz); + Fail=FALSE; + if(peek_i32_le (&HDRdir[0].start) != 0x24061968L) Fail=TRUE; + if(peek_i32_le (&HDRdir[0].size) != 666L) Fail=TRUE; + if(strncmp(HDRdir[0].name,"IZNOGOOD",8)!=0) Fail=TRUE; + } + } + if(Fail != FALSE) ProgError("Not a modified WAD"); + Phase("Restoration infos seem correct.\n"); + dirpos = peek_i32_le (&HDRdir[1].start); + ntry = peek_i32_le (&HDRdir[1].size); + rwadstart = peek_i32_le (&HDRdir[2].start); + rwadsize = peek_i32_le (&HDRdir[2].size); + ewadstart = peek_i32_le (&HDRdir[3].start); + ewadsize = peek_i32_le (&HDRdir[3].size); + Normalise(ewadname,HDRdir[3].name); /*name of WAD inside*/ + /*original file time*/ + time = peek_i32_le (&HDRdir[4].size); + if(peek_i32_le (&HDRdir[4].start)!=FALSE) + { /*extract the PWAD*/ + sprintf(ewadfile,"%.8s.WAD",ewadname); +#if DT_OS == 'd' +#elif DT_OS == 'o' + ToLowerCase(ewadfile); +#else + ToLowerCase(ewadfile); +#endif + fp=fopen(ewadfile,FOPEN_RB); + if(fp!=NULL) + { fclose(fp); + Info("File %s already exist: internal WAD discarded.\n",ewadfile); + } + else + { Phase("Restoring internal WAD %s\n",ewadfile); + if((fp=fopen(ewadfile,FOPEN_WB))!=NULL) + { data = (char huge *)Malloc( MEMORYCACHE); + size = ewadsize; + WADRseek(&rwad,ewadstart); + fseek(fp,0,SEEK_SET); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE : size-wsize; + WADRreadBytes(&rwad,data,sz); + if(fwrite(data,(size_t)sz,1,fp)!=1) + { Warning("Can't write %s",ewadstart);break; + } + } + Free(data); + fclose(fp); + } + else + Warning("Can't open %s",ewadfile); + } + } + WADRopenA(&rwad,wadres); + /*correct the directory reference of DOOM.WAD*/ + WADRsetDirRef(&rwad,ntry,dirpos); + /*restore original size*/ + WADRchsize(&rwad,rwadstart+rwadsize); + WADRclose(&rwad); + SetFileTime(wadres,time); + Output("Restoration of %s should be successful.\n",wadres); +} +/**************** End WAD restoration **********************/ + + +static void HDRsetDir(struct WADINFO *rwad,Bool IsIwad,Bool Restore, + Int32 time,Int32 dirpos,Int32 ntry,Int32 rsize, + Int32 estart,Int32 esize,char *wadext) +{ static char name[8]; + Int32 pos; + /*Set the old references */ + Phase("Writing new WAD directory\n"); + write_i32_le (&HDRdir[0].start, 0x24061968L); + write_i32_le (&HDRdir[0].size, 666L); + Normalise(HDRdir[0].name,"IZNOGOOD"); + /*Set original WAD DIRECTORY*/ + write_i32_le (&HDRdir[1].start, dirpos); + write_i32_le (&HDRdir[1].size, ntry); + Normalise(HDRdir[1].name,(IsIwad==TRUE)?"DOOM_DIR":"PWAD_DIR"); + /*Store original WAD size and start*/ + write_i32_le (&HDRdir[2].start, 0); + write_i32_le (&HDRdir[2].size, rsize); + Normalise(HDRdir[2].name,"ORIGINAL"); + /*Store external WAD size and start*/ + write_i32_le (&HDRdir[3].start, estart); + write_i32_le (&HDRdir[3].size, esize); + GetNameOfWAD(name,wadext); + Normalise(HDRdir[3].name,name); + /*old file time*/ + write_i32_le (&HDRdir[4].size, time); + write_i32_le (&HDRdir[4].start, Restore); + Normalise(HDRdir[4].name,"TIME"); + /*save position of old ref if no previous _DEUTEX_ */ + WADRalign4(rwad); + pos=(Int32)WADRfindEntry(rwad,"_DEUTEX_"); + if(pos<0) + { pos=WADRposition(rwad);/*BC++ 4.5 bug*/ + WADRdirAddEntry(rwad,pos,HDRdirSz,"_DEUTEX_"); + } + /*write old refs*/ + WADRwriteBytes(rwad,(char huge *)HDRdir,HDRdirSz); + /*write the directory*/ + rwad->dirpos = WADRposition(rwad); + WADRwriteDir(rwad); +} +/************ General services ******************/ + + + + + + + +/**************** Paste PWAD module ***********************/ + + + +/* +** merge WAD +** +*/ + +void PSTmergeWAD(char *doomwad,char *wadin,NTRYB select) +{ + static struct WADINFO iwad; + static struct WADINFO pwad; + ENTRY huge *iiden; /*identify entry in IWAD*/ + ENTRY huge *piden; /*identify entry in PWAD*/ + Int16 pnm;char huge *Pnam;Int32 Pnamsz=0; + Int32 dirpos,ntry,isize,pstart,psize,time; + struct WADDIR huge *NewDir;Int32 NewNtry; + Phase("Attempting to merge IWAD %s and PWAD %s\n",doomwad,wadin); + /*open iwad,get iwad directory*/ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) ProgError("Can't find PNAMES in main WAD"); + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + /* identify iwad*/ + iiden=IDENTentriesIWAD(&iwad, Pnam, Pnamsz,TRUE); + /* get pwad directory, and identify*/ + pwad.ok=0; + WADRopenR(&pwad,wadin); + piden=IDENTentriesPWAD(&pwad, Pnam, Pnamsz); + /**/ + Free(Pnam); + /*where to put pwad? at pwadstart*/ + /* merge the two directories */ + NewDir=LISmergeDir(&NewNtry,FALSE,TRUE,select,&iwad,iiden,0,&pwad,piden,EXTERNAL); + /* prepare for append*/ + time=WADRprepareAppend(doomwad,&iwad,NewDir,NewNtry,&dirpos,&ntry,&isize); + /* complete IWAD with PWAD, restorable*/ + pstart=HDRinsertWad(&iwad,&pwad,&psize); + /* set directory */ + HDRsetDir(&iwad,TRUE,TRUE,time,dirpos,ntry,isize,pstart,psize,wadin); + /* close */ + WADRclose(&pwad); + WADRclose(&iwad); +} + + +/**************** End Paste PWAD module ****************/ + + + + + + + + + + + + + + + + + +/**************** Append IWAD after PWAD module *****************/ +/* +** -app complete a PWAD with DOOM entries +** +*/ +void ADDappendSpriteFloor(char *doomwad,char *wadres,NTRYB select) +{ + struct WADINFO iwad; + struct WADINFO pwad; + ENTRY huge *iiden; /*identify entry in IWAD*/ + ENTRY huge *piden; /*identify entry in PWAD*/ + Int16 pnm;char huge *Pnam;Int32 Pnamsz; + Int32 dirpos,ntry,psize,time; + struct WADDIR huge *NewDir;Int32 NewNtry; + Phase("Appending "); + if(select&BSPRITE) Phase("Sprites "); + if(select&BFLAT) Phase("Flats "); + Phase("from IWAD %s to PWAD %s\n",doomwad,wadres); + /* get iwad directory, and identify */ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) ProgError("Can't find PNAMES in main WAD"); + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + /* identify iwad*/ + iiden=IDENTentriesIWAD(&iwad, Pnam, Pnamsz,TRUE); + /* get pwad directory, and identify*/ + pwad.ok=0; + WADRopenR(&pwad,wadres); + piden=IDENTentriesPWAD(&pwad, Pnam, Pnamsz); + /**/ + Free(Pnam); + /* merge the two directories */ + NewDir=LISmergeDir(&NewNtry,TRUE,TRUE,select,&iwad,iiden,EXTERNAL,&pwad,piden,0); + /* prepare for append*/ + time=WADRprepareAppend(wadres,&pwad,NewDir,NewNtry,&dirpos,&ntry,&psize); + /* append DOOM sprites to PWAD*/ + HDRplunderWad(&pwad,&iwad); + /* set dir */ + HDRsetDir(&pwad,FALSE,FALSE,time,dirpos,ntry,psize,-1,-1,doomwad); + /* close */ + WADRclose(&iwad); + WADRclose(&pwad); +} + + + +/* +** join: complete a PWAD with another PWAD entries +** +*/ +void ADDjoinWads(char *doomwad,char *wadres,char *wadext,NTRYB select) +{ struct WADINFO iwad; /*IWAD*/ + struct WADINFO ewad; /*external Wad*/ + struct WADINFO rwad; + ENTRY huge *eiden; /*identify entry in IWAD*/ + ENTRY huge *riden; /*identify entry in PWAD*/ + Int16 entry;char huge *Entry;Int32 EntrySz; + Int16 pnm;char huge *Patch;Int32 PatchSz; + Int32 start,size; + Int16 etexu,rtexu; + struct WADDIR huge *NewDir;Int32 NewNtry; + Bool TexuMrg = FALSE; + Int32 dirpos,ntry,rsize,estart,esize,time; + Phase("Merging PWAD %s into PWAD %s\n",wadext,wadres); + /* get iwad directory, and identify */ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES*/ + entry=WADRfindEntry(&iwad,"PNAMES"); + if(entry<0) ProgError("Can't find PNAMES in main WAD"); + Entry=WADRreadEntry(&iwad,entry,&EntrySz); + /* get ewad directory, and identify */ + ewad.ok=0; + WADRopenR(&ewad,wadext); + eiden=IDENTentriesPWAD(&ewad, Entry, EntrySz); + /* get rwad directory, and identify*/ + rwad.ok=0; + WADRopenR(&rwad,wadres); + riden=IDENTentriesPWAD(&rwad, Entry, EntrySz); + /**/ + Free(Entry); + /*merge texture1 if needed*/ + etexu=WADRfindEntry(&ewad,"TEXTURE1"); + rtexu=WADRfindEntry(&rwad,"TEXTURE1"); + if((etexu>=0)&&(rtexu>=0)) + { TexuMrg=TRUE; + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES in IWAD and init*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) Bug("JnPnm"); + Entry=WADRreadEntry(&iwad,entry,&EntrySz); + PNMinit(Entry,EntrySz); + Free(Entry); + /*declare TEXTURE1 from IWAD*/ + TXUinit(); + } + WADRclose(&iwad); + if(TexuMrg==TRUE) + { /*add TEXTURE1 from rwad*/ + Phase(" With TEXTURE1 from %s\n",wadres); + PatchSz=0;Patch=NULL; + pnm=WADRfindEntry(&rwad,"PNAMES"); + if(pnm>=0) + { Phase(" Declaring Patches from %s\n",wadres); + riden[pnm]=EVOID; + Patch=WADRreadEntry(&rwad,pnm,&PatchSz); + } + Entry=WADRreadEntry(&rwad,rtexu,&EntrySz); + TXUreadTEXTURE(Entry,EntrySz,Patch,PatchSz,TRUE); + if(PatchSz!=0)Free(Patch); + Free(Entry); + riden[rtexu]=EVOID; /* forget r texu*/ + /*TEXTURE1 from ewad*/ + Phase(" And TEXTURE1 from %s\n",wadext); + PatchSz=0;Patch=NULL; + pnm=WADRfindEntry(&ewad,"PNAMES"); + if(pnm>=0) + { Phase(" Declaring Patches from %s\n",wadext); + eiden[pnm]=EVOID; + Patch=WADRreadEntry(&ewad,pnm,&PatchSz); + } + Entry=WADRreadEntry(&ewad,etexu,&EntrySz); + TXUreadTEXTURE(Entry,EntrySz,Patch,PatchSz,FALSE); + if(PatchSz!=0)Free(Patch); + Free(Entry); + eiden[etexu]=EVOID; /* forget e texu*/ + } + /* merge the two directories, all entries */ + NewDir=LISmergeDir(&NewNtry,FALSE,FALSE,select,&rwad,riden,0,&ewad,eiden,EXTERNAL); + /* prepare for append*/ + time=WADRprepareAppend(wadres,&rwad,NewDir,NewNtry,&dirpos,&ntry,&rsize); + /* append PWAD into PWAD, restorable */ + estart=HDRinsertWad(&rwad,&ewad,&esize); + /* append texu/pname*/ + if(TexuMrg==TRUE) + { WADRalign4(&rwad); + start=WADRposition(&rwad); + size=TXUwriteTEXTUREtoWAD(&rwad); + WADRdirAddEntry(&rwad,start,size,"TEXTURE1"); + TXUfree(); + WADRalign4(&rwad); + start=WADRposition(&rwad); + size=PNMwritePNAMEtoWAD(&rwad); + WADRdirAddEntry(&rwad,start,size,"PNAMES"); + PNMfree(); + } + + /* set directory */ + HDRsetDir(&rwad,FALSE,TRUE,time,dirpos,ntry,rsize,estart,esize,wadext); + /*end*/ + WADRclose(&rwad); + WADRclose(&ewad); +} + + + + + + + + + + + + + + + + + + + +/* +** Add sprites and Floors +** +** must delete void entries (old DMADDS files) +** must select SPRITES of FLOORS +** +*/ +/************** merge PWAD IWAD directory module ****************/ +void ADDallSpriteFloor(char *wadout,char *doomwad,char *wadres,NTRYB select) +{ + struct WADINFO iwad; + struct WADINFO pwad; + struct WADINFO rwad; + Int16 n; + ENTRY huge *iiden; /*identify entry in IWAD*/ + ENTRY huge *piden; /*identify entry in PWAD*/ + Int32 start,size,ostart,osize; + Int16 pnm;char huge *Pnam;Int32 Pnamsz; + struct WADDIR huge *NewDir;Int32 NewNtry; + + Phase("Copying "); + if(select&BSPRITE) Phase("Sprites "); + if(select&BFLAT) Phase("Flats "); + Phase("from IWAD %s and PWAD %s\n",doomwad,wadres); + Phase("Into PWAD %s\n",wadout); + /* get iwad directory, and identify */ + iwad.ok=0; + WADRopenR(&iwad,doomwad); + /*find PNAMES*/ + pnm=WADRfindEntry(&iwad,"PNAMES"); + if(pnm<0) ProgError("Can't find PNAMES in main WAD"); + Pnam=WADRreadEntry(&iwad,pnm,&Pnamsz); + /* identify iwad*/ + iiden=IDENTentriesIWAD(&iwad, Pnam, Pnamsz,TRUE); + /* get pwad directory, and identify*/ + pwad.ok=0; + WADRopenR(&pwad,wadres); + piden=IDENTentriesPWAD(&pwad, Pnam, Pnamsz); + /**/ + Free(Pnam); + /*where to put pwad? at pwadstart*/ + if((iwad.maxpos|pwad.maxpos)&EXTERNAL )Bug("AddExt"); + /* merge the two directories */ + NewDir=LISmergeDir(&NewNtry,TRUE,TRUE,select,&iwad,iiden,EXTERNAL,&pwad,piden,0); + /* create a new PWAD*/ + rwad.ok=0; + WADRopenW(&rwad,wadout,PWAD); + for(n=0;n +/****OS/2****/ +#elif DT_OS == 'o' +# include +# if DT_CC != 'b' +# define filelength _filelength +# endif +/****UNIX****/ +#else +#endif +#include +#include +#include + +#include "tools.h" +#include "mkwad.h" +#include "ident.h" +#include "wadio.h" + +/*************Begin WAD module ********************** +** Open PWAD file. *pcount=global byte counter +** leaves number of entries and directory pointer NULL +*/ + + +/******************End WAD module ******************/ + + + + +const int WADR_READ=1; +const int WADR_WRITE=2; +const int WADR_RDWR=3; +const int WADR_PIPO=8; + + + +/************ begin WAD module ***********/ + +void WADRopenPipo(struct WADINFO *info,Int32 ntry) +{ /*directory */ + if((info->ok&WADR_RDWR)) Bug("WadPpk"); + info->ok=WADR_PIPO; + if(ntry<=0) Bug("WadPpo"); + info->maxdir=ntry; + info->dir=(struct WADDIR huge *)Malloc((info->maxdir)*sizeof(struct WADDIR)); + info->maxpos=ntry*sizeof(struct WADDIR); + info->ntry=0; + info->wposit=info->maxpos; +} +struct WADDIR huge *WADRclosePipo(struct WADINFO *info,Int32 huge *ntry) +{ if((info->ok!=WADR_PIPO)) Bug("WadPpc"); + info->ok=FALSE; + if(info->ntry<0)info->ntry=0; + info->dir=(struct WADDIR huge *) + Realloc(info->dir,(info->ntry)*sizeof(struct WADDIR)); + *ntry=info->ntry; + return info->dir; +} +Int32 WADRdirAddPipo(struct WADINFO *info,Int32 start,Int32 size,char *entry) +{ Int16 n; + if(info->ok!=WADR_PIPO) Bug("WadDaP"); + n=(Int16)info->ntry; /*position of new entry*/ + if(n<0) Bug("WadDa2"); + if(nmaxdir) /*can add to the dir*/ + { info->ntry++; /*new dir size*/ + info->dir[n].size=size; + info->dir[n].start=start; + Normalise(info->dir[n].name,entry); + } + return n; /* nb entries */ +} + +void WADRopenR(struct WADINFO *info,char *wadin) +{ /*directory */ + Int32 ntry,dirpos; + Int16 n; + struct WADDIR dir; + if((info->ok&WADR_RDWR)) Bug("WadOpr"); + info->fd=fopen(wadin,FOPEN_RB); + if((info->fd)==NULL)ProgError("Can't open WAD %s for reading",wadin); + info->ok=WADR_READ; + /*signature*/ + switch(WADRreadShort(info)) + { case PWAD: case IWAD: break; + default: ProgError("WAD %s has a bad header",wadin); + } + if(WADRreadShort(info)!=WADMAGIC) + ProgError("WAD %s has a bad header2",wadin); + /*start of directory*/ + ntry = WADRreadLong(info); + if(ntry<=0) + ProgError("WAD %s is empty",wadin); + if(ntry>=0x2000) + ProgError("WAD has too many entries"); + info->dirpos= dirpos= WADRreadLong(info); + if((dirpos<0)||(dirpos>0x10000000L)) + ProgError("WAD dir references are incorrect"); + /*allocate directory*/ + info->maxdir=ntry; + info->dir=(struct WADDIR huge *)Malloc((info->maxdir)*sizeof(struct WADDIR)); + /*read directory, calculate further byte in wad*/ + info->maxpos=dirpos+(ntry*sizeof(struct WADDIR)); + WADRseek(info,dirpos); + info->ntry=0; + for(n=0;nfd, &dir.start) + || wad_read_i32 (info->fd, &dir.size) + || wad_read_name (info->fd, dir.name)) + ProgError ("Error reading directory of \"%s\"", wadin); + WADRdirAddEntry (info, dir.start, dir.size, dir.name); + } + if(info->ntry!=ntry)Bug("WadOrN"); + info->wposit=info->maxpos; + Phase("Reading WAD %s:\t(%ld entries)\n",wadin,ntry); +} +static char signature[19 + 32]; +void WADRopenW(struct WADINFO *info,char *wadout,WADTYPE type) +{ Phase("Creating %cWAD %s\n",(type==IWAD)?'I':'P',wadout); + if((info->ok&WADR_RDWR)) Bug("WadOpW"); + + /*check file*/ + info->fd = fopen( wadout, FOPEN_RB); + if(info->fd!=NULL) ProgError("Won't overwrite existing file %s", wadout); + /*open file*/ + info->fd = fopen( wadout, FOPEN_WB); + if(info->fd==NULL)ProgError( "Can't create file %s", wadout); + info->ok=WADR_WRITE; + info->wposit=0; + info->ntry =0; + info->maxdir=MAXPWADDIR; + info->dir =(struct WADDIR huge *)Malloc((info->maxdir)*sizeof(struct WADDIR)); + WADRwriteShort(info,type); /* WAD type: PW or IW*/ + WADRwriteShort(info,WADMAGIC); /* WAD type: AD*/ + /* will be fixed when closing the WAD*/ + WADRwriteLong(info,-1); /* no counter of dir entries */ + WADRwriteLong(info,-1); /* no dir pointer */ + /* DeuTex notice*/ + sprintf(signature," DeuTex %.32s %cOJM 94 ",deutex_version,0xB8); + /********----**----**-********/ + WADRwriteBytes(info,signature,strlen(signature)); + WADRalign4(info); +} +/* +** Assumes file already opened write +** if not, open it first +** OPEN READ-WRITE,not APPEND +** because APPEND can't FSEEK to start of file +*/ +void WADRopenA(struct WADINFO *info,char *wadinout) +{ Phase("Modifying WAD %s\n",wadinout); + if((info->ok&WADR_WRITE)) Bug("WadOpA"); + if(!(info->ok&WADR_READ)) + { WADRopenR(info,wadinout); + } + /*reopen for append*/ + fclose(info->fd); + info->fd = fopen( wadinout, FOPEN_RBP); /*rb+ = read/write binary*/ + if(info->fd==NULL)ProgError( "Can't append to file %s", wadinout); + info->ok = WADR_RDWR; + WADRseek(info,info->wposit); +} + + + +/***************** Directory ***************/ +/* +** Add a new entry in the directory +** increase ntry, redim dir +** update maxdir and maxpos +** returns entry ref +*/ +Int32 WADRdirAddEntry(struct WADINFO *info,Int32 start,Int32 size,char *entry) +{ Int16 n; + Int32 sz; + if(!(info->ok&(WADR_RDWR))) Bug("WadDAE"); + n=(Int16)info->ntry; /*position of new entry*/ + if(n>=info->maxdir) /*shall we move the dir?*/ + { info->maxdir+=MAXPWADDIR; + info->dir=(struct WADDIR huge *)Realloc((char huge *)info->dir,(info->maxdir)*sizeof(struct WADDIR)); + } + info->ntry++; /*new dir size*/ + info->dir[n].size=size; + info->dir[n].start=start; + Normalise(info->dir[n].name,entry); + sz=start+size; + if(sz>info->maxpos) + info->maxpos=sz; + return n; /* nb entries */ +} +/* +** write the directory (names, counts, lengths) +** then update the number of entries and dir pointer +*/ +void WADRwriteDir(struct WADINFO *info) +{ Int16 n; + if(!(info->ok&WADR_WRITE)) Bug("WadWD"); + WADRalign4(info); /*align entry on Int32 word*/ + info->dirpos=info->wposit; /*current position*/ + /* write the new WAD directory*/ + for(n=0;nntry;n++) + { + if (wad_write_i32 (info->fd, info->dir[n].start) + || wad_write_i32 (info->fd, info->dir[n].size) + || wad_write_name (info->fd, info->dir[n].name)) + ProgError ("Error writing wad directory"); + } + /* fix up the directory start information */ + WADRsetDirRef(info,info->ntry,info->dirpos); + n=(Int16)( info->dirpos+(sizeof(struct WADDIR)*info->ntry)); + if(n>info->maxpos) info->maxpos=n; + Phase("WAD is complete: size %ld bytes.\n",info->wposit); +} + +/***************** Wad structure *******************/ + +void WADRsetDirRef(struct WADINFO *info,Int32 ntry,Int32 dirpos) +{ +#if 0 + struct { Int32 ntry;Int32 dirpos;} Head; +#endif + if(!(info->ok&WADR_WRITE))Bug("WadSDR"); +#if 0 + Head.ntry=BE_Int32(ntry); + Head.dirpos=BE_Int32(dirpos); +#endif + WADRseek(info,4); + if (wad_write_i32 (info->fd, ntry) + || wad_write_i32 (info->fd, dirpos)) + ProgError ("Error fixing wad header"); +#if 0 + if(fwrite(&Head,sizeof(Head),1,info->fd)!=1) + { Warning("That WAD might not be usable anymore!"); + Warning("Restore bytes 4 to 11 manually if you can."); + ProgError("Failed writing WAD directory References"); + } +#endif + WADRseek(info,info->wposit); + info->ntry=ntry; + info->dirpos=dirpos; +} +void WADRchsize(struct WADINFO *info,Int32 fsize) +{ if(!(info->ok&WADR_WRITE)) Bug("WadcSz"); + if(Chsize(fileno(info->fd),fsize)!=0) + ProgError("Can't change size of WAD."); + info->maxpos=fsize; + info->wposit=fsize; +} +#if 0 +Bool WADRchsize2(struct WADINFO *info,Int32 fsize) +{ if(!(info->ok&WADR_WRITE)) Bug("WadcSz"); + if(Chsize(fileno(info->fd),fsize)!=0) return FALSE; + return TRUE; +} +#endif + + +/****************Read********************/ + + + +void WADRseek(struct WADINFO *info,Int32 position) +{ if(!(info->ok&WADR_RDWR)) Bug("WadSk"); + if(position>info->maxpos) Bug("WadSk>"); + if(fseek(info->fd,position,SEEK_SET)) + ProgError("Can't seek in WAD"); +} + +Int32 WADRreadBytes(struct WADINFO *info,char huge *buffer,Int32 nb) +{ Int32 rsize,sz=0; + if(!(info->ok&WADR_READ)) Bug("WadRdB"); + if(nb<=0) Bug("WadRd<"); + for(rsize=0;rsizeMEMORYCACHE)? MEMORYCACHE:nb-rsize; + if(fread((buffer+(rsize)),(size_t)sz,1,info->fd)!=1)ProgError("Can't read WAD"); + } + return nb; +} + +Int16 WADRreadShort(struct WADINFO *info) +{ Int16 res; + if(!(info->ok&WADR_READ)) Bug("WadRdS"); + if (wad_read_i16 (info->fd, &res)) + ProgError ("Can't read wad"); + return res; +#if 0 + if(fread(&res,sizeof(Int16),1,info->fd)!=1)ProgError("Can't read WAD"); + return BE_Int16(res); +#endif +} + +Int32 WADRreadLong(struct WADINFO *info) +{ Int32 res; + if(!(info->ok&WADR_READ)) Bug("WadRdL"); + if (wad_read_i32 (info->fd, &res)) + ProgError ("Can't read wad"); + return res; +#if 0 + if(fread(&res,sizeof(Int32),1,info->fd)!=1)ProgError("Can't read WAD"); + return BE_Int32(res); +#endif +} + +void WADRclose(struct WADINFO *info) +{ if(!(info->ok&WADR_RDWR)) Bug("WadClo"); + info->ok=FALSE; + Free(info->dir); + fclose(info->fd); +} + +Int16 WADRfindEntry(struct WADINFO *info,char *entry) +{ Int16 i; + static char name[8]; + struct WADDIR huge *dir; + if(!(info->ok&WADR_RDWR)) Bug("WadFE"); + for(i=0,dir=info->dir;intry;i++,dir+=1) + { Normalise(name,dir->name); + if(strncmp(name,entry,8)==0) + return i; + } + return -1; +} + +/* +** load data in buffer +*/ +char huge *WADRreadEntry(struct WADINFO *info,Int16 n,Int32 *psize) +{ char huge *buffer; + Int32 start,size; + if(!(info->ok&WADR_READ)) Bug("WadRE"); + if(n>=(info->ntry))Bug("WadRE>"); + start = info->dir[n].start; + size = info->dir[n].size; + buffer=(char huge *)Malloc(size); + WADRseek(info,start); + WADRreadBytes(info,buffer,size); + *psize=size; + return buffer; +} +#if defined DeuTex +/* +** copy data from WAD to file +*/ +void WADRsaveEntry(struct WADINFO *info,Int16 n, char *file) +{ Int32 wsize,sz=0; + char huge *buffer; + Int32 start,size; + FILE *fd; + if(!(info->ok&WADR_READ)) Bug("WadSE"); + if(n>=(info->ntry))Bug("WadSE>"); + start = info->dir[n].start; + size = info->dir[n].size; + fd=fopen(file,FOPEN_WB); + if(fd==NULL) ProgError("Can't open file %s",file); + buffer = (char huge *)Malloc( MEMORYCACHE); + WADRseek(info,start); + for(wsize=0; wsizeMEMORYCACHE)? MEMORYCACHE : size-wsize; + WADRreadBytes(info,buffer,sz); + if(fwrite(buffer,(size_t)sz,1,fd)!=1) + { Free(buffer); + ProgError("Can't write file %s",file); + } + } /*declare in WAD directory*/ + Free( buffer); + fclose(fd); +} +#endif /*DeuTex*/ + +/******************** Write ************************/ + +void WADRsetLong(struct WADINFO *info,Int32 pos,Int32 val) +{ + if(!(info->ok&WADR_WRITE)) Bug("WadStL"); + if(pos>(info->maxpos)) Bug("WadSL>"); + if(fseek(info->fd, pos, SEEK_SET)) ProgError("Can't seek in wad"); + if(wad_write_i32 (info->fd, val)) ProgError("Can't write in wad"); +#if 0 +if(fwrite(&v,sizeof(Int32),1,info->fd)!=1) ProgError( "Can't write in wad"); +#endif +} + +void WADRsetShort(struct WADINFO *info,Int32 pos,Int16 val) +{ +#if 0 + Int32 v=BE_Int16(val); +#endif + if(!(info->ok&WADR_WRITE)) Bug("WadStS"); + if(pos>(info->maxpos)) Bug("WadSS>"); + if(fseek(info->fd, pos, SEEK_SET)) ProgError("Can't seek in wad"); + if(wad_write_i16 (info->fd, val)) ProgError("Can't write in wad"); +#if 0 + if(fwrite(&v,sizeof(Int16),1,info->fd)!=1) ProgError( "Can't write in wad"); +#endif +} + +/* +** internal functions +** +*/ +static void WADRcheckWritePos(struct WADINFO *info) +{ if(!(info->ok&WADR_WRITE)) Bug("WadCkW"); + if (fseek( info->fd, info->wposit, SEEK_SET)) ProgError( "Can't seek in wad"); +} + +static Int32 WADRwriteBlock(struct WADINFO *info,char huge *data,Int32 sz) +{ if(fwrite(data,(size_t)sz,1,info->fd) != 1) ProgError( "Wad write failed"); + info->wposit += sz; + if(info->maxposwposit)info->maxpos=info->wposit; + return sz; +} + +/* +** align, give position +*/ +void WADRalign4(struct WADINFO *info) +{ Int16 remain; + static char buffer[] ={0,0x24,0x6,0x68}; + WADRcheckWritePos(info); + remain = (Int16)(info->wposit&0x03); /*0 to 3*/ + if(remain>0) WADRwriteBytes(info,buffer,4-remain); +} +/*must be equal to ftell*/ +Int32 WADRposition(struct WADINFO *info) +{ WADRcheckWritePos(info); + return info->wposit; +} +/* +** write +*/ +Int32 WADRwriteLong(struct WADINFO *info,Int32 val) +{ +#if 0 + Int32 v=BE_Int32(val); +#endif + WADRcheckWritePos(info); +#if 0 + return WADRwriteBlock(info,(char huge *)&v,sizeof(Int32)); +#endif + if (wad_write_i32 (info->fd, val)) + ProgError ("Wad write failed"); + info->wposit += sizeof val; + if (info->maxpos < info->wposit) + info->maxpos = info->wposit; + return sizeof val; +} + +Int32 WADRwriteShort(struct WADINFO *info,Int16 val) +{ +#if 0 + Int16 v=BE_Int16(val); +#endif + WADRcheckWritePos(info); +#if 0 + return WADRwriteBlock(info,(char huge *)&v,sizeof(Int16)); +#endif + if (wad_write_i16 (info->fd, val)) + ProgError ("Wad write failed"); + info->wposit += sizeof val; + if (info->maxpos < info->wposit) + info->maxpos = info->wposit; + return sizeof val; +} + +Int32 WADRwriteBytes(struct WADINFO *info,char huge *data,Int32 size) +{ Int32 wsize,sz=0; + WADRcheckWritePos(info); + if(size<=0) Bug("WadWb<"); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE : size-wsize; + wsize+=WADRwriteBlock(info,&data[wsize],sz); + } + return wsize; +} + +static Int32 WADRwriteBlock2(struct WADINFO *info,char huge *data,Int32 sz) +{ if(fwrite(data,(size_t)sz,1,info->fd) != 1)return -1; + info->wposit += sz; + if(info->maxposwposit)info->maxpos=info->wposit; + return sz; +} +Int32 WADRwriteBytes2(struct WADINFO *info,char huge *data,Int32 size) +{ Int32 wsize,sz=0; + WADRcheckWritePos(info); + if(size<=0) Bug("WadWb<"); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE : size-wsize; + sz=WADRwriteBlock2(info,&data[wsize],sz); + if(sz<0) return -1; + wsize+=sz; + } + return wsize; +} +/* +** copy data from SOURCE WAD to WAD +*/ +Int32 WADRwriteWADbytes(struct WADINFO *info,struct WADINFO *src,Int32 start,Int32 size) +{ Int32 wsize,sz=0; + char huge *data; + data = (char huge *)Malloc( MEMORYCACHE); + WADRseek(src,start); + WADRcheckWritePos(info); + for(wsize=0; wsizeMEMORYCACHE)? MEMORYCACHE : size-wsize; + WADRreadBytes(src,data,sz); + wsize+=WADRwriteBlock(info,data,sz); + } /*declare in WAD directory*/ + Free( data); + return wsize; +} + + + +#if defined DeuTex +/* +** copy lump from file into WAD +** returns size +*/ +Int32 WADRwriteLump(struct WADINFO *info,char *file) +{ Int32 size,sz=0; + FILE *fd; + char huge *data; + WADRcheckWritePos(info); + /*Look for entry in master directory */ + fd=fopen(file,FOPEN_RB); + if(fd==NULL) ProgError("Can't read file %s",file); + data = (char huge *)Malloc( MEMORYCACHE); + for(size=0;;) + { sz = fread(data,1,(size_t)MEMORYCACHE,fd); + if(sz<=0)break; + size+=WADRwriteBlock(info,data,sz); + } + Free( data); + fclose(fd); + return size; +} +Int32 WADRwriteWADentry(struct WADINFO *info,struct WADINFO *src,Int16 n) +{ if(n>(src->ntry)) Bug("WadWW>"); + return WADRwriteWADbytes(info,src,src->dir[n].start,src->dir[n].size); +} +/* +** copy level parts +*/ +void WADRwriteWADlevelParts(struct WADINFO *info,struct WADINFO *src,Int16 N) +{ Int32 start,size; + Int16 n,top; + /*set level entries*/ + for(n=N+1;nntry;n++) + { top=N+11; + if(n>top)break; + if(IDENTlevelPart(src->dir[n].name)<0) break; + WADRalign4(info); + start=WADRposition(info); + size=WADRwriteWADentry(info,src,n); + WADRdirAddEntry(info,start,size,src->dir[n].name); + } + top=N+11; + if(n=0)break; + if(N>=src.ntry) ProgError("No level in WAD %s",file); + } + } +/*set level name*/ + WADRalign4(info); + pos=WADRposition(info); /*BC++ 4.5 bug!*/ + WADRdirAddEntry(info,pos,0L,level); + WADRwriteWADlevelParts(info,&src,N); + WADRclose(&src); +} +#endif /*DeuTex*/ + +/* +** replace dir of rwad by dir of newwad +** prepare to write at the end of rwad +** open for append +*/ +Int32 WADRprepareAppend(char *wadres,struct WADINFO *rwad, + struct WADDIR huge *NewDir,Int32 NewNtry, + Int32 *dirpos,Int32 *ntry, Int32 *size) +{ Int32 ewadstart; + Int32 rwadsize; + Int32 time; + time=GetFileTime(wadres); + /* append to the Result WAD*/ + WADRopenA(rwad,wadres); + /*get original size*/ +#if DT_OS == 'd' +# if DT_CC == 'd' + rwadsize=rwad->maxpos; +# else + rwadsize=filelength(fileno(rwad->fd)); +# endif +#elif DT_OS == 'o' + rwadsize=filelength(fileno(rwad->fd)); +#else + rwadsize=rwad->maxpos; +#endif + /*last warning*/ + Output("The WAD file %s will be modified, but it can be restored with:\n",wadres); + Output("%s -res %s\n",COMMANDNAME,wadres); + Output("Restoration may fail if you modified the WAD with another tool.\n"); + Output("In case of failure, you can salvage your WAD by:\n"); + /* Assuming wad is little endian... */ + Output("- setting bytes 4-7 to \t%02Xh %02Xh %02Xh %02Xh\n", + (unsigned short) (rwad->ntry & 0xff), + (unsigned short) ((rwad->ntry >> 8) & 0xff), + (unsigned short) ((rwad->ntry >> 16) & 0xff), + (unsigned short) ((rwad->ntry >> 24) & 0xff)); + Output("- and setting bytes 8-11 to \t%02Xh %02Xh %02Xh %02Xh\n", + (unsigned short) (rwad->dirpos & 0xff), + (unsigned short) ((rwad->dirpos >> 8) & 0xff), + (unsigned short) ((rwad->dirpos >> 16) & 0xff), + (unsigned short) ((rwad->dirpos >> 24) & 0xff)); + Output("If possible, set the file size to %ld bytes.\n",rwadsize); + /*align*/ + ewadstart=((rwadsize+0xF)&(~0xFL)); + if((ewadstart|rwadsize)&EXTERNAL) ProgError("Too big WADs"); + *dirpos=rwad->dirpos; + *ntry=rwad->ntry; + *size=rwadsize; + /*Change size*/ + WADRchsize(rwad,ewadstart); + /*Write will start at file end*/ + rwad->maxpos=ewadstart; + rwad->wposit=ewadstart; + WADRseek(rwad,ewadstart); + /*Change to New directory*/ + Free(rwad->dir); + rwad->dir=NewDir; + rwad->ntry=NewNtry; + rwad->maxdir=NewNtry; + rwad->dirpos=-1; + return time; +} + diff --git a/src/mkwad.h b/src/mkwad.h new file mode 100644 index 0000000..a4232ac --- /dev/null +++ b/src/mkwad.h @@ -0,0 +1,85 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/*for merging directories*/ +void WADRopenPipo(struct WADINFO *info,Int32 ntry); +struct WADDIR huge *WADRclosePipo(struct WADINFO *info,Int32 huge *ntry); +Int32 WADRdirAddPipo(struct WADINFO *info,Int32 start,Int32 size,char *entry); + +/*Open a WAD file for read*/ +void WADRopenR(struct WADINFO *info,char *wadin); +/*Open a WAD file for write*/ +void WADRopenW(struct WADINFO *info,char *wadout, WADTYPE type); +/*Open a WAD file for append*/ +void WADRopenA(struct WADINFO *info,char *wadinout); +/*Close a WAD file*/ +void WADRclose(struct WADINFO *info); + +/*WAD file structure*/ +/*set position of internal WAD directory*/ +void WADRsetDirRef(struct WADINFO *info,Int32 ntry,Int32 dirpos); +/*change size of a WAD*/ +void WADRchsize(struct WADINFO *info,Int32 fsize); +/*increase size of WAD, do not update position*/ +Bool WADRchsize2(struct WADINFO *info,Int32 fsize); + + +/*composition of internal WAD directory*/ +/*add an entry to the directory*/ +Int32 WADRdirAddEntry(struct WADINFO *info,Int32 start,Int32 size,char *name); +/*write the directory (and set it's position)*/ +void WADRwriteDir(struct WADINFO *info); +/*find an entry in the directory*/ +Int16 WADRfindEntry(struct WADINFO *info,char *entry); /*-1 or index of entry in directory*/ + +/*set data in a WAD (write position doesn't change)*/ +void WADRsetLong(struct WADINFO *info,Int32 pos,Int32 val); +void WADRsetShort(struct WADINFO *info,Int32 pos,Int16 val); +/*align on long*/ +void WADRalign4(struct WADINFO *info); /*align on long word, for next entry*/ +/*tell position of pointer*/ +Int32 WADRposition(struct WADINFO *info); /*current position*/ +/*write date (write position increase)*/ +Int32 WADRwriteLong(struct WADINFO *info,Int32 val); +Int32 WADRwriteShort(struct WADINFO *info,Int16 val); +Int32 WADRwriteBytes(struct WADINFO *info,char huge *data,Int32 size); +Int32 WADRwriteBytes2(struct WADINFO *info,char huge *data,Int32 size); +Int32 WADRwriteLump(struct WADINFO *info,char *file); +Int32 WADRwriteWADbytes(struct WADINFO *info,struct WADINFO *src,Int32 start,Int32 size); +Int32 WADRwriteWADentry(struct WADINFO *info,struct WADINFO *src,Int16 n); +void WADRwriteWADlevelParts(struct WADINFO *info,struct WADINFO *src,Int16 n); +void WADRwriteWADlevel(struct WADINFO *info,char *file,char *level); + +/*read data*/ +void WADRseek(struct WADINFO *info,Int32 position); +Int32 WADRreadBytes(struct WADINFO *info,char huge *buffer,Int32 nb); +Int16 WADRreadShort(struct WADINFO *info); +Int32 WADRreadLong(struct WADINFO *info); +char huge *WADRreadEntry(struct WADINFO *info,Int16 N,Int32 *psize); +void WADRsaveEntry(struct WADINFO *info,Int16 N, char *file); + +/*make some preparations before appending data to an existing WAD*/ +/*so that it can be restored later*/ +Int32 WADRprepareAppend(char *wadres,struct WADINFO *rwad,struct WADDIR huge *NewDir,Int32 NewNtry, + Int32 *dirpos,Int32 *ntry, Int32 *size); diff --git a/src/picture.c b/src/picture.c new file mode 100644 index 0000000..704a960 --- /dev/null +++ b/src/picture.c @@ -0,0 +1,1216 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianio.h" +#include "endianm.h" +#include "mkwad.h" +#include "ident.h" +#include "color.h" + +#include + +/*compile only for DeuTex*/ +#if defined DeuTex + +enum { PF_NORMAL, PF_ALPHA } picture_format = PF_NORMAL; + + + +/* BMP,GIF,DoomPIC conversion +** intermediary format: RAW (FLAT= RAW 64x64 or RAW 64x65) +** Int16 Xsz Int16 Ysz +** char idx[Xsz*Ysz] +** colors= those of DOOM palette +** position (x,y) = idx[x+xsz*y] +** insertion point not set +*/ + + + +/* +** +*/ + + +static char huge *PICtoRAW(Int16 *prawX,Int16 *prawY,Int16 *pXinsr,Int16 *pYinsr,char huge *pic,Int32 picsz,char transparent); +static char huge *RAWtoPIC(Int32 *ppicsz, char huge *raw, Int16 rawX, Int16 rawY,Int16 Xinsr,Int16 Yinsr, char transparent); + + +static void RAWtoBMP(char *file,char huge *raw,Int16 rawX, Int16 rawY,struct PIXEL huge *doompal); +static char huge *BMPtoRAW(Int16 *prawX,Int16 *prawY,char *file); + +static void RAWtoPPM(char *file,char huge *raw,Int16 rawX, Int16 rawY,struct PIXEL huge *doompal); +static char huge *PPMtoRAW(Int16 *prawX,Int16 *prawY,char *file); + +static char huge *GIFtoRAW(Int16 *rawX,Int16 *rawY,char *file); +static void RAWtoGIF(char *file,char huge *raw,Int16 rawX,Int16 rawY,struct PIXEL huge *doompal); + +/* +** +** this is only a test example +** COLinit and COLfree must be called before +** BMP->GIF +*/ +#if 0 +void PicDebug(char *file,char *bmpdir,char *name) +{ char huge *raw; + Int16 rawX,rawY; + struct PIXEL huge * doompal; + + Phase("BMP->RAW\n"); + MakeFileName(file,bmpdir,"","",name,"BMP"); + raw =BMPtoRAW(&rawX,&rawY,file); + doompal = COLdoomPalet(); + Phase("RAW->GIF\n"); + MakeFileName(file,bmpdir,"","",name,"GIF"); + RAWtoGIF(file,raw,rawX,rawY,doompal); + + Free(raw); +} +#endif +/* +** this is only a test example +** GIF->BMP +*/ +#if 1 +void PicDebug(char *file,char *bmpdir,char *name) +{ char huge *raw; + Int16 rawX=0,rawY=0; + struct PIXEL huge * doompal; + + Phase("GIF->RAW\n"); + MakeFileName(file,bmpdir,"","",name,"GIF"); + raw =GIFtoRAW(&rawX,&rawY,file); + doompal = COLdoomPalet(); + Phase("RAW->BMP\n"); + MakeFileName(file,bmpdir,"","",name,"BMP"); + RAWtoBMP(file,raw,rawX,rawY,doompal); + + Free(raw); +} +#endif +/* +** end of examples +** +*/ + +/* +** BMP or GIF +** +*/ +Bool PICsaveInFile(char *file,PICTYPE type,char huge *pic,Int32 picsz,Int16 *pXinsr,Int16 *pYinsr,IMGTYPE Picture) + { char huge *raw=NULL; + Int16 rawX,rawY; + struct PIXEL huge * doompal; + char transparent; + + transparent =(char)COLinvisible(); + *pXinsr=INVALIDINT; /*default insertion point X*/ + *pYinsr=INVALIDINT; /*default insertion point Y*/ + switch(type) + { case PGRAPH: case PWEAPN: + case PSPRIT: case PPATCH: + raw = PICtoRAW(&rawX,&rawY,pXinsr,pYinsr,pic,picsz,transparent); + if(raw==NULL) return FALSE; /*was not a valid DoomPic*/ + break; + case PFLAT: + if(picsz==0x1000L) { rawX=64;rawY=64;} + else if(picsz==0x1040) { rawX=64;rawY=65;}/*bug?*/ + else if(picsz==0x2000) { rawX=64;rawY=128;}/*bug?*/ + else return FALSE;/*Wrong size for FLAT. F_SKY1*/ + raw=pic; /*flat IS raw already*/ + break; + case PLUMP: + if(picsz==64000L) + { rawX=320;rawY=200; + } + else return FALSE;/*Wrong size for LUMP. F_SKY1*/ + raw=pic; /*flat IS raw already*/ + break; + default: + Bug("picsv"); + } + /* + ** load doom palette + */ + doompal = COLdoomPalet(); + /* + ** convert to BMP + */ + switch(Picture) + { case PICGIF: + RAWtoGIF(file,raw,rawX,rawY,doompal); + break; + case PICBMP: + RAWtoBMP(file,raw,rawX,rawY,doompal); + break; + case PICPPM: + RAWtoPPM(file,raw,rawX,rawY,doompal); + break; + default: + Bug("psvit (%d)", (int) Picture); + } + switch(type) + { case PGRAPH: case PWEAPN: case PSPRIT: case PPATCH: + Free(raw); + break; + case PFLAT: /*don't free pic!*/ + case PLUMP: + break; + } + return TRUE; +} + + +Int32 PICsaveInWAD(struct WADINFO *info,char *file,PICTYPE type,Int16 Xinsr,Int16 Yinsr,IMGTYPE Picture) +{ + char huge *raw=NULL; + Int16 rawX=0,rawY=0; + char huge *pic=NULL; + Int32 picsz; + char transparent; + + /* + ** convert BMP to RAW + */ + transparent =COLinvisible(); + switch(Picture) + { case PICGIF: + raw = GIFtoRAW(&rawX,&rawY,file); + break; + case PICBMP: + raw = BMPtoRAW(&rawX,&rawY,file); + break; + case PICPPM: + raw = PPMtoRAW(&rawX,&rawY,file); + break; + default: + Bug("pwvit"); + } + if((rawY<1)||(rawX<1))ProgError("Bad picture size"); + // AYM (256 -> 509) + if(rawY>509)ProgError("Picture height can't be more than 509"); + // AYM (512 -> 1024) + if(rawX>1024)ProgError("Picture width can't be more than 1024"); + switch(type) + { case PGRAPH: case PWEAPN: case PSPRIT: case PPATCH: + break; + case PFLAT: /*flats*/ + if(rawX!=64) + ProgError("Width of FLAT %s is not 64",file); + if((rawY!=64)&&(rawY!=65)) + ProgError("Height of FLAT %s is not 64 or 65",file); + break; + case PLUMP: /*special heretic lumps*/ + if(rawX!=320) + ProgError("Width of LUMP %s is not 320",file); + if(rawY!=200) + ProgError("Height of LUMP %s is not 200",file); + break; + default: + Bug("picwt"); + } + /* + ** calculate insertion point + */ + Xinsr=IDENTinsrX(type,Xinsr,rawX); + Yinsr=IDENTinsrY(type,Yinsr,rawY); + /* + ** convert RAW to DoomPic + */ + switch(type) + { case PGRAPH: case PWEAPN: case PSPRIT: case PPATCH: + pic=RAWtoPIC(&picsz,raw,rawX,rawY,Xinsr,Yinsr,transparent); + Free(raw); + WADRwriteBytes(info,pic,picsz); + Free(pic); + break; + case PLUMP: /*LUMP is RAW*/ + case PFLAT: /*FLAT is RAW*/ + picsz= ((Int32)rawX)*((Int32)rawY); + WADRwriteBytes(info,raw,picsz); + Free(raw); + break; + } + /* + ** write DoomPic in WAD + */ + return picsz; +} + + + + +/******************* DoomPic module ************************/ +/* +** doom pic +** +*/ +struct PICHEAD { +Int16 Xsz; /*nb of columns*/ +Int16 Ysz; /*nb of rows*/ +Int16 Xinsr; /*insertion point*/ +Int16 Yinsr; /*insertion point*/ +}; +/* +** RAW to DoomPIC conversion +** +** in: Int16 Xinsr; Int16 Yinsr; +** Int16 rawX; Int16 rawY; char transparent; +** char raw[Xsize*Ysize] +** out: Int32 picsz; size of DoomPIC +** char pic[picsz]; buffer for DoomPIC +*/ +#if DT_OS == 'd' +#define OPTIMEM 1 /*DOS: alloc < 64k if possible*/ +#else +#define OPTIMEM 0 +#endif +char huge *RAWtoPIC(Int32 *ppicsz, char huge *raw, Int16 rawX, Int16 rawY,Int16 Xinsr,Int16 Yinsr, char transparent) +{ Int16 x,y; + char pix,lastpix; /*pixels*/ + /*Doom PIC */ + char huge *pic; /*picture*/ + Int32 picsz,rawpos; + struct PICHEAD huge *pichead; /*header*/ + Int32 huge *ColOfs; /*position of column*/ + /*columns composed of sets */ + char huge *Set=NULL; + Int32 colnbase,colnpos,setpos; + Int16 setcount=0; + + /*offset of first column*/ + colnbase= sizeof(struct PICHEAD)+((Int32)rawX)*sizeof(Int32); + /* worst expansion when converting from PIXEL column to + ** list of sets: (5*Ysize/2)+1, corresponding to a dotted vertical + ** transparent line. Ysize/2 dots, 4overhead+1pix, 1 last FF code. + ** but if too big, allow only a 10 split mean per line + */ + /*this memory optimisation doesn't work for big pics + with many transparent areas. it limits the number of transp slots + to a mean of 10. so a resize could be needed later. + else, the biggest would be 162k + */ + /* AYM 1999-05-09: changed the calculation of picsz. + Previously, it was assumed that the worst case was when + every second pixel was transparent. This is not true for + textures that are only 2-pixel high; in that case, if the + two pixels are opaque, the column uses 7 bytes. The old + code thought that was 6 bytes, and overflowed the buffer + for at least one picture (Strife's STBFN045). */ + /* Highest possible picture : + Post 1 yofs = 0 length = 254 + Post 2 yofs = 254 length = 255 + Max height is 509 pixels. */ + { + /* FIXME */ + int worst_case_1 = 5 * (((long) rawY + 1) / 2) + 1 + 1; /* "+ 1" matters ! */ + int worst_case_2 = 4 + rawY + 1; + int worst_case = worst_case_1 > worst_case_2 ? worst_case_1 : worst_case_2; + picsz= colnbase + ((Int32)rawX) * worst_case; + } +#if OPTIMEM /*optimisation*/ + if(picsz>0x10000L) picsz=0x10000L; +#endif + pic = (char huge *)Malloc(picsz); + ColOfs=(Int32 huge *)&(pic[sizeof(struct PICHEAD)]); + pichead=(struct PICHEAD huge *)pic; + /* + ** convert raw (doom colors) to PIC + */ + write_i16_le (&pichead->Xsz, rawX); + write_i16_le (&pichead->Ysz, rawY); + write_i16_le (&pichead->Xinsr, Xinsr); + write_i16_le (&pichead->Yinsr, Yinsr); + colnpos=colnbase; + for(x=0;x= 509) + { Warning("Column has more than 509 pixels." + " Truncating at (%d,%d).\n", (int) x, (int) y); + break; + } + if(lastpix==transparent) /* begining of post */ + { Set=(char huge *)&(pic[colnpos+setpos]); + setcount=0; + Set[0]=y; /* y position */ + Set[1]=0; /*count (updated later)*/ + Set[2]=pix; /*unused*/ + } + Set[3+setcount]=pix;/*non transparent pixel*/ + setcount++; /*update count of pixel in set*/ + } + else /*pix is transparent*/ + { if(lastpix!=transparent)/*finish the current set*/ + { Set[1]=setcount; + Set[3+setcount]=lastpix; + setpos+= 3+setcount+1;/*1pos,1cnt,1dmy,setcount pixels,1dmy*/ + } + /*else: not in set but in transparent area*/ + } + lastpix=pix; + } + if(lastpix!=transparent) /*finish current set, if any*/ + { Set[1]=setcount; + Set[3+setcount]=lastpix; + setpos+= 3+setcount+1; /*1pos,1count,1dummy,setcount pixels,1dummy*/ + } + pic[colnpos+setpos]=(char)0xFF; /*end of all sets*/ + colnpos+=(Int32)(setpos+1); /*position of next column*/ +#if OPTIMEM /*optimisation*/ + if((colnpos+((Int32)(5*rawY)/2)+1)>=picsz) /*avoid crash during next column*/ + { /*pic size was underestimated. need more pic size*/ + /*Bug("Pic size too small");*/ +#if 1 + picsz= colnpos+0x4000;/*better make it incremental... not 161k!*/ +#else + picsz= colnbase + ((Int32)rawX) * (1+5*(((Int32)rawY+1)/2)); +#endif + pic = (char huge *)Realloc(pic,picsz); + ColOfs=(Int32 huge *)&(pic[sizeof(struct PICHEAD)]); + } +#endif + } + /*picsz was an overestimated size for PIC*/ + pic = (char huge *)Realloc(pic,colnpos); + *ppicsz= colnpos;/*real size of PIC*/; + return pic; +} + +/* +** DoomPIC to RAW +** +** in: Int32 picsz; transparent; +** char pic[picsz]; +** out: Int16 rawX; Int16 rawY; +** char raw[rawX*rawY]; +** NULL if it's not a valid pic +*/ +char huge *PICtoRAW(Int16 *prawX,Int16 *prawY,Int16 *pXinsr,Int16 *pYinsr,char huge *pic,Int32 picsz,char transparent) +{ Int16 rawX,rawY,x,y; /*pixels*/ + struct PICHEAD huge *pichead; + Int32 huge *ColOfs; /*position of column*/ + /*columns composed of sets */ + char huge *Set; + Int32 colnbase,setpos; + Int16 setc,setcount; + /*raw picture*/ + char col,notransp; + char huge *raw; + Int32 rawpos,rawsz; + + notransp=0;/*this is to avoid trouble when the transparent index is used in a picture*/ + pichead = (struct PICHEAD huge *)pic; + read_i16_le (&pichead->Xsz, &rawX); + read_i16_le (&pichead->Ysz, &rawY); + ColOfs = (Int32 huge *)(pic+(sizeof(struct PICHEAD))); + colnbase =sizeof(struct PICHEAD)+((Int32)rawX)*sizeof(Int32); + /* + ** check up + */ + if((rawX<1)||(rawX>320))return NULL; /*illegal height*/ + if((rawY<1)||(rawY>200))return NULL; /*illegal width*/ + for(x=0;x=picsz) return NULL; /*too high*/ + /*BUG: false assumption more rigorous than pix format*/ + /*if(x>0)if(pic[(ColOfs[x]-1)]!=0xFF)return NULL;*/ + } + /* + ** allocate raw. (care: free it if error, before exit) + */ + rawsz=((Int32)rawX)*((Int32)rawY); + raw = (char huge *)Malloc(rawsz); + Memset(raw,transparent,rawsz); + /* + ** + */ + for(x=0;x=picsz) { Free(raw);return NULL;} + Set=(char huge *)(&pic[setpos]); + if(Set[0]==(char)0xFF) break; /*last set*/ + if(setpos+3>=picsz) { Free(raw);return NULL;} + setcount=((Int16)Set[1])&0xFF; + if(setpos+3+setcount+1>=picsz) { Free(raw);return NULL;} + y=((Int16)Set[0])&0xFF; + for(setc=0;setc=rawY) { Free(raw);return NULL;} + col=Set[3+setc]; + if(col==transparent){col=notransp;} + rawpos=((Int32)x)+((Int32)rawX)*((Int32)y); + raw[rawpos]=col; + } + setpos+=3+setcount+1; + } + } + /*return*/ + read_i16_le (&pichead->Xinsr, pXinsr); + read_i16_le (&pichead->Yinsr, pYinsr); + *prawX=rawX; + *prawY=rawY; + return raw; +} +/******************* End DoomPic module ************************/ + + + + + + + + + + + +/* + color index convertion bmp->doom +*/ +static UInt8 Idx2Doom[256]; + + + +/******************* BMP module ************************/ + +struct BMPPALET { UInt8 B; UInt8 G; UInt8 R; UInt8 Zero;}; +struct BMPPIXEL { UInt8 B; UInt8 G; UInt8 R;}; +/* +** bitmap conversion +*/ + +struct BMPHEAD { +Int32 bmplen; /*02 total file length Size*/ +Int32 reserved; /*06 void Reserved1 Reserved2*/ +Int32 startpix; /*0A start of pixels OffBits*/ +/*bitmap core header*/ +Int32 headsz; /*0E Size =nb of bits in bc header*/ +Int32 szx; /*12 X size = width Int16 width*/ +Int32 szy; /*16 Y size = height Int16 height*/ +Int32 planebits; /*1A equal to 1 word planes*/ + /*1C nb of bits word bitcount 1,4,8,24*/ +/**/ +Int32 compress; /*1E Int32 compression = BI_RGB = 0*/ +Int32 pixlen; /*22 Int32 SizeImage size of array necessary for pixels*/ +Int32 XpixRes; /*26 XPelsPerMeter X resolution no one cares*/ +Int32 YpixRes; /*2A YPelPerMeter Y resolution but code1a=code1b*/ +Int32 ColorUsed; /*2C ClrUsed nb of colors in palette*/ +Int32 ColorImp; /*32 ClrImportant nb of important colors in palette*/ +/*palette pos: ((UInt8 *)&headsz) + headsz */ +/*palette size = 4*nb of colors. order is Blue Green Red (Black? always0)*/ +/*bmp line size is xsize*bytes_per_pixel aligned on Int32 */ +/*pixlen = ysize * line size */ +}; +/* +** BMP to RAW conversion +** +** in: UInt8 *bmp; Int32 bmpsize; UInt8 COLindex(R,G,B); +** +** out: UInt8 *raw; Int16 rawX; Int16 rawY; +*/ +char huge *BMPtoRAW(Int16 *prawX,Int16 *prawY,char *file) +{ + struct BMPHEAD huge *head; /*bmp header*/ + struct BMPPALET huge *palet; /*palet. 8 bit*/ + Int32 paletsz; + UInt8 huge *line; /*line of BMP*/ + Int32 startpix,linesz=0; + struct BMPPIXEL huge *pixs; /*pixels. 24 bit*/ + UInt8 huge *bmpidxs; /*color indexs in BMP 8bit*/ + Int16 szx,szy,x,y,p,nbits; + Int32 ncols; + Int32 bmpxy; + char huge *raw; /*point to pixs. 8 bit*/ + Int32 rawpos; + UInt8 col='\0'; + FILE *fd; + char sig[2]; + /* + ** read BMP header for size + */ + + fd=fopen(file,FOPEN_RB); + if(fd==NULL) ProgError("Can't open %s for reading",file); + if(fread(sig,2,1,fd)!=1) + ProgError("Can't read sig of BMP %s",file); + if(strncmp(sig,"BM",2)!=0) ProgError("Bmp: signature incorrect"); + + head=(struct BMPHEAD huge *)Malloc(sizeof(struct BMPHEAD)); + if(fread(head,sizeof(struct BMPHEAD),1,fd)!=1) + ProgError("Bmp: can't read header"); + /* + ** check the BMP header + */ + if (peek_i32_le (&head->compress) != 0) ProgError("Bmp: not RGB"); + read_i32_le (&head->startpix, &startpix); + szx = (Int16) peek_i32_le (&head->szx); + szy = (Int16) peek_i32_le (&head->szy); + if(szx<1) ProgError("Bmp: bad width"); + if(szy<1) ProgError("Bmp: bad height"); + ncols = peek_i32_le (&head->ColorUsed); + /* + ** Allocate memory for raw bytes + */ + raw=(char huge *)Malloc(((Int32)szx)*((Int32)szy)); + /* + ** Determine line size and palet (if needed) + */ + nbits = (Int16) ((peek_i32_le (&head->planebits)>>16)&0xFFFFL); + switch(nbits) + { case 24: + Info("Warning: Color quantisation is slow. Use 8 bit BMP.\n"); + linesz=((((Int32)szx)*sizeof(struct BMPPIXEL))+3L)&~3L; /*RGB, aligned mod 4*/ + break; + case 8: + linesz=(((Int32)szx)+3L)&~3L; /*Idx, aligned mod 4*/ + if(ncols>256) ProgError("Bmp: palette should be 256 color"); + if(ncols<=0) ncols=256; /*Bug of PaintBrush*/ + paletsz=(ncols)*sizeof(struct BMPPALET); + /*set position to palette (a bit hacked)*/ + if(fseek(fd,0xEL+peek_i32_le(&head->headsz),SEEK_SET))ProgError("Bmp: seek failed"); + /*load palette*/ + palet=(struct BMPPALET huge *)Malloc(paletsz); + if(fread(palet,(size_t)paletsz,1,fd)!=1) ProgError("Bmp: can't read palette"); + for(p=0;ppixlenbmplen)<(startpix+bmpxy)) + ProgError("Bmp: size of pixel area incorrect"); + + Free(head); + /* seek start of pixels */ + if(fseek(fd,startpix,SEEK_SET)) ProgError("Bmp: seek failed"); + /* read lines */ + line = (UInt8 huge *)Malloc(linesz); + bmpidxs=(UInt8 huge *)line; + pixs=(struct BMPPIXEL huge *)line; + /*convert bmp pixels/bmp indexs into doom indexs*/ + for(y=szy-1;y>=0;y--) + { if(fread(line,(size_t)linesz,1,fd)!=1) ProgError("Can't read BMP line"); + for(x=0;xbmplen, bmplen); + write_i32_le (&head->reserved, 0); + write_i32_le (&head->startpix, startpix); + write_i32_le (&head->headsz, 0x28); + write_i32_le (&head->szx, rawX); + write_i32_le (&head->szy, rawY); + write_i32_le (&head->planebits, 0x80001);/*1 plane 8bits BMP*/ + write_i32_le (&head->compress, 0); /* RGB */ + write_i32_le (&head->pixlen, pixlen); + write_i32_le (&head->XpixRes, 0); + write_i32_le (&head->YpixRes, 0); + write_i32_le (&head->ColorUsed, ncol); + write_i32_le (&head->ColorImp, ncol); + if(fwrite(head,sizeof(struct BMPHEAD),1,fd)!=1) ProgError("Can't write file %s",file); + Free(head); + /* + ** set palette + ** + */ + palet=(struct BMPPALET huge *)Malloc(paletsz); + for(x=0;x=0;y--) + { for(x=0;x>3)&0xE)+1); + GifScreen.Backgnd = GifHead.backgnd; + GifScreen.AspRatio = GifHead.aspratio; + Memset(GifColor,0,256*sizeof(struct PIXEL)); + /* read Global Color Map */ + if ((GifHead.info)&COLORMAP) + { if(fread(GifColor,sizeof(struct PIXEL),bitPixel,fd)!=bitPixel) + { fclose(fd);ProgError("GIF: read error"); + } + } + /* + ** Read extension, images, etc... + */ + while((c=getc(fd)) !=EOF) + { if(c==';') break; /* GIF terminator */ + /*no need to test imagecount*/ + if(c=='!') /* Extension */ + GIFextens(fd); + else if(c==',') /*valid image start*/ + { if(raw!=NULL) /* only keep first image*/ + { Warning("GIF: Other images discarded."); + break; + } + if (fread_u16_le (fd, &GifImage.ofsx) + || fread_u16_le (fd, &GifImage.ofsy) + || fread_u16_le (fd, &GifImage.xsize) + || fread_u16_le (fd, &GifImage.ysize) + || (chr = fgetc (fd), GifHead.info = chr, chr == EOF)) + { + fclose(fd); + ProgError("GIF: read error"); + } + /* GifImage.ofsx,ofsy X,Y offset ignored */ + bitPixel = 1<<((GifImage.info&0x07)+1); + IntLace= (GifImage.info & INTERLACE)? TRUE:FALSE; + Xsz = GifImage.xsize; + Ysz = GifImage.ysize; + if((Xsz<1)||(Ysz<1)) + { fclose(fd);ProgError("GIF: bad size"); + } + if(GifImage.info & COLORMAP) + { if(fread(GifColor,sizeof(struct PIXEL),bitPixel,fd)!=bitPixel) + { fclose(fd);ProgError("GIF: read error"); + } + } + /*read the GIF. if many pictures, only the last + one is kept. + */ + raw= GIFreadPix(fd, Xsz,Ysz); + } + /*else, not a valid start character, skip to next*/ + } + fclose(fd); + if(raw == NULL) ProgError("GIF: No picture found"); + /*convert colors*/ + for (c=0; c<256; c++) + { Idx2Doom[c]=(UInt8)COLindex((UInt8)GifColor[c].R,(UInt8)GifColor[c].G,(UInt8)GifColor[c].B,(UInt8)c); + } + rawSz=((Int32)Xsz) * ((Int32)Ysz); + for (rawpos=0; rawpos> 2) & 0x7; + Gif89.InputFlag = (Buf[0] >> 1) & 0x1; + Gif89.DelayTime = ((Buf[2]<<8)&0xFF00) + Buf[1]; + if(Buf[0] & 0x1)Gif89.Transparent = Buf[3]; + break; + default: /*Unknown GIF extension*/ + break; + } + while (GIFreadBlock(fd, Buf)>0); +} + +/* +** Read Gif Indexes +*/ +static char huge *GIFreadPix(FILE *fd,Int16 Xsz,Int16 Ysz) +{ char huge *raw=NULL; + Int32 rawSz; +#if NEWGIFD +#else + Int16 v; + Int32 rawpos; + unsigned char c=0; +#endif + + /* + ** get some space + */ + rawSz = ((Int32)Xsz)*((Int32)Ysz); + raw = (char huge *)Malloc(rawSz); +#if NEWGIFD + InitDecoder( fd, 8, Xsz); + Decode((UInt8 huge *)raw, rawSz); + ExitDecoder(); +#else + /* Initialize the Compression routines */ + if (fread(&c,1,1,fd)!=1) ProgError("GIF: read error" ); + if (LWZReadByte(fd, TRUE, c) < 0) ProgError("GIF: bad code in image" ); + /* read the file */ + for(rawpos=0;rawpos=0); /* ignore extra data */ +#endif + return raw; +} + +/* +** Un-Interlace a GIF +*/ +static char huge *GIFintlace(char huge *org,Int16 Xsz,Int16 Ysz) +{ Int32 rawpos,orgpos; + Int16 pass,Ys=0,Y0=0,y; + char huge *raw; + rawpos = ((Int32)Xsz)*((Int32)Ysz); + raw = (char huge *)Malloc(rawpos); + orgpos = 0; + for(pass=0;pass<4;pass++) + { switch(pass) + { case 0: Y0=0; Ys=8; break; + case 1: Y0=4; Ys=8; break; + case 2: Y0=2; Ys=4; break; + case 3: Y0=1; Ys=2; break; + } + rawpos=(Int32)Y0*(Int32)Xsz; + for(y=Y0;y=CountTop) return EOF; + c=Raw[ CountCur]; + CountCur++; + return ((code_int)c &0xFF); +} +#endif + +void RAWtoGIF(char *file,char huge *raw,Int16 rawX,Int16 rawY,struct PIXEL huge*doompal ) +{ FILE *fd; + Int32 rawSz; + + fd=fopen(file,FOPEN_WB); + if(fd==NULL)ProgError("Can't open GIF file %s",file); + rawSz = (Int32)rawX * (Int32)rawY; + /* screen header */ + strncpy(GifIdent,"GIF87a",6); + fwrite(GifIdent, 1, 6, fd ); /*header*/ + fwrite_u16_le (fd, rawX); /* xsize */ + fwrite_u16_le (fd, rawY); /* ysize */ + fputc (COLORMAP | ((8 - 1) << 4) | (8 - 1), fd); /* info */ + /* global colormap, 256 colors, 7 bit per pixel*/ + fputc (0, fd); /* backgnd */ + fputc (0, fd); /* aspratio */ + fwrite(doompal,sizeof(struct PIXEL),256,fd); /*color map*/ + fputc (',',fd); /*Image separator*/ + /* image header */ + fwrite_u16_le (fd, 0); /* ofsx */ + fwrite_u16_le (fd, 0); /* ofsy */ + fwrite_u16_le (fd, rawX); /* xsize*/ + fwrite_u16_le (fd, rawY); /* ysize */ + fputc (0, fd); /* info */ + /* image data */ + fputc(8,fd); /* Write out the initial code size */ +#if NEWGIFE + InitEncoder(fd,8); + Encode((UInt8 huge *)raw,rawSz); + ExitEncoder(); +#else + Raw = raw; /* init */ + CountTop = rawSz; + CountCur = 0; + compressInit(); + compress( 8+1, fd, NextPixel ); /* write picture, InitCodeSize=8 */ + compressFree(); +#endif + /* termination */ + fputc(0,fd); /*0 length packet to end*/ + fputc(';',fd); /*GIF file terminator*/ + fclose(fd); /*the end*/ +} +/******************* End GIF module ************************/ + +#endif /*DeuTex*/ diff --git a/src/picture.h b/src/picture.h new file mode 100644 index 0000000..7161ca0 --- /dev/null +++ b/src/picture.h @@ -0,0 +1,34 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* first call COLinit();*/ +Bool PICsaveInFile(char *file,PICTYPE type,char huge *pic,Int32 picsz,Int16 *pXinsr,Int16 *pYinsr,IMGTYPE Picture); +Int32 PICsaveInWAD(struct WADINFO *info,char *file,PICTYPE type,Int16 Xinsr,Int16 Yinsr,IMGTYPE Picture); +/* last call COLfree();*/ + +extern enum { PF_NORMAL, PF_ALPHA } picture_format; + +/*picture.c: only for test*/ +void GIFtoBMP(char *file,char *bmpdir,char *name); +void BMPtoGIF(char *file,char *bmpdir,char *name); diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..0525575 --- /dev/null +++ b/src/sound.c @@ -0,0 +1,435 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "mkwad.h" +#include "sound.h" +#include "text.h" + +/*compile only for DeuTex*/ +#if defined DeuTex + + +/*********************** WAVE *********************/ + +static struct RIFFHEAD +{ char riff[4]; + Int32 length; + char wave[4]; +} headr; +static struct CHUNK +{ char name[4]; + Int32 size; +} headc; +static struct WAVEFMT/*format*/ +{ char fmt[4]; /* "fmt " */ + Int32 fmtsize; /*0x10*/ + Int16 tag; /*format tag. 1=PCM*/ + Int16 channel; /*1*/ + Int32 smplrate; + Int32 bytescnd; /*average bytes per second*/ + Int16 align; /*block alignment, in bytes*/ + Int16 nbits; /*specific to PCM format*/ +}headf; +static struct WAVEDATA /*data*/ +{ char data[4]; /* "data" */ + Int32 datasize; +}headw; + +static void SNDsaveWave(char *file,char huge *buffer,Int32 size,Int32 speed) +{ + FILE *fp; + Int32 wsize,sz=0; + fp=fopen(file,FOPEN_WB); + if(fp==NULL) + { ProgError("WAV: can't write %s",file); + } + /*header*/ + strncpy(headr.riff,"RIFF",4); + write_i32_le (&headr.length, 4+sizeof(struct WAVEFMT)+sizeof(struct WAVEDATA)+size); + strncpy(headr.wave,"WAVE",4); + fwrite(&headr,sizeof(struct RIFFHEAD),1,fp); + strncpy(headf.fmt, "fmt ",4); + write_i32_le (&headf.fmtsize, sizeof(struct WAVEFMT)-8); + write_i16_le (&headf.tag, 1); + write_i16_le (&headf.channel, 1); + write_i32_le (&headf.smplrate, speed); + write_i32_le (&headf.bytescnd, speed); + write_i16_le (&headf.align, 1); + write_i16_le (&headf.nbits, 8); + fwrite(&headf,sizeof(struct WAVEFMT),1,fp); + strncpy(headw.data,"data",4); + write_i32_le (&headw.datasize, size); + fwrite(&headw,sizeof(struct WAVEDATA),1,fp); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:(size-wsize); + if(fwrite((buffer+(wsize)),(size_t)sz,1,fp)!=1)ProgError("WAV: write error"); + } + fclose(fp); +} + +char huge *SNDloadWaveFile(char *file, Int32 *psize, Int32 *pspeed) +{ FILE *fp; + Int32 wsize,sz=0,smplrate,datasize; + Int32 chunk; + char huge *data; + fp=fopen(file,FOPEN_RB); + if(fp==NULL) ProgError("WAV: can't read file %s",file); + /*read RIFF HEADER*/ + if(fread(&headr,sizeof(struct RIFFHEAD),1,fp)!=1) + ProgError("WAV: can't read header"); + /*check RIFF header*/ + if(strncmp(headr.riff,"RIFF",4)!=0) ProgError("WAV: wrong header"); + if(strncmp(headr.wave,"WAVE",4)!=0) ProgError("WAV: wrong header"); + chunk=sizeof(struct RIFFHEAD); + for(sz=0;;sz++) + { if(sz>256) ProgError("WAV: no fmt"); + fseek(fp,chunk,SEEK_SET); + if(fread(&headc,sizeof(struct CHUNK),1,fp)!=1)ProgError("WAV: no fmt"); + if(strncmp(headc.name,"fmt ",4)==0)break; + /* There used to be a bug here; sizeof (struct CHUNK) had + its bytes swapped too. Reading .wav files on big endian + machines must have been broken. -- AYM 1999-07-04 */ + chunk += sizeof (struct CHUNK) + peek_i32_le (&headc.size); + } + fseek(fp,chunk,SEEK_SET); + fread(&headf,sizeof(struct WAVEFMT),1,fp); + if(peek_i16_le (&headf.tag)!=1) ProgError("WAV: not raw data"); + if(peek_i16_le (&headf.channel)!=1) ProgError("WAV: not one channel"); + smplrate=peek_i32_le(&headf.smplrate); + + for(sz=0;;sz++) + { if(sz>256) ProgError("WAV: no data"); + fseek(fp,chunk,SEEK_SET); + if(fread(&headc,sizeof(struct CHUNK),1,fp)!=1) ProgError("WAV: no data"); + if(strncmp(headc.name,"data",4)==0)break; + /* Same endianness bug as above. */ + chunk += sizeof (struct CHUNK) + peek_i32_le (&headc.size); + } + fseek(fp,chunk,SEEK_SET); + if(fread(&headw,sizeof(struct WAVEDATA),1,fp)!=1) ProgError("WAV: no data"); + datasize = peek_i32_le (&headw.datasize); + /*check WAVE header*/ + if(datasize>0x100000L) ProgError("WAV: sample too long!"); + /*read data*/ + data=(char huge *)Malloc(datasize); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:(datasize-wsize); + if(fread((data+(wsize)),(size_t)sz,1,fp)!=1) ProgError("WAV: can't read data of%s",file); + } + fclose(fp); + *psize=datasize; + *pspeed=smplrate&0xFFFFL; + return data; +} + + +/***************** AU **********************/ +struct AUHEAD +{ char snd[4]; /* ".snd" */ + Int32 dataloc; /* Always big endian */ + Int32 datasize; /* Always big endian */ + Int32 format; /* Always big endian */ + Int32 smplrate; /* Always big endian */ + Int32 channel; /* Always big endian */ + char info[4]; +}; +static struct AUHEAD heada; +/*char data[datasize] as signed char*/ + +static void SNDsaveAu(char *file,char huge *buffer,Int32 size,Int32 speed) +{ FILE *fp; + Int32 i,wsize,sz=0; + fp=fopen(file,FOPEN_WB); + if(fp==NULL)ProgError("WAV: can't write %s",file); + /*header*/ + strncpy(heada.snd,".snd",4); + write_i32_be (&heada.dataloc, sizeof (struct AUHEAD)); + write_i32_be (&heada.datasize, size); + write_i32_be (&heada.format, 2); /*8 bit linear*/ + write_i32_be (&heada.smplrate, speed); + write_i32_be (&heada.channel, 1); + heada.info[0]='\0'; + if(fwrite(&heada,sizeof(struct AUHEAD),1,fp)!=1)ProgError("AU: write error"); + for(i=0;iMEMORYCACHE)? MEMORYCACHE:(size-wsize); + if(fwrite((buffer+(wsize)),(size_t)sz,1,fp)!=1)ProgError("AU: write error"); + } + fclose(fp); +} +char huge *SNDloadAuFile(char *file, Int32 *psize, Int32 *pspeed) +{ FILE *fp; + Int32 wsize,sz=0,i,smplrate,datasize; + char huge *data; + fp=fopen(file,FOPEN_RB); + if(fp==NULL) ProgError("AU: can't read file %s",file); + /*read AU HEADER*/ + if(fread(&heada,sizeof(struct AUHEAD),1,fp)!=1) + + /*check AU header*/ + if(strncmp(heada.snd,".snd",4)!=0) ProgError("AU: not an audio file."); + /*read RIFF HEADER*/ + if(peek_i32_be (&heada.format) != 2) ProgError("AU: not linear 8 bit."); + if(peek_i32_be (&heada.channel)!= 1) ProgError("AU: not one channel."); + + if(fseek(fp,heada.dataloc,SEEK_SET)) ProgError("AU: bad header"); + smplrate = peek_i32_be (&heada.smplrate); + datasize = peek_i32_be (&heada.datasize); + /*check WAVE header*/ + if(smplrate!=11025) + Warning("sample rate of %s is %u instead of 11025",file,smplrate); + if(datasize>0x100000L) + ProgError("AU: sample too long!"); + /*read data*/ + data=(char huge *)Malloc(datasize); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:(datasize-wsize); + if(fread((data+(wsize)),(size_t)sz,1,fp)!=1) ProgError("WAV: can't read data of%s",file); + } + fclose(fp); + /*convert from signed to unsigned char*/ + for(i=0;i>8)&0xFFL); + blockv.sizeU= (char)((sz>>16)&0xFFL); + if(speed<=4000)speed=4000; + blockv.rate=(char)(256-(1000000L/((long)speed))); + blockv.cmprs=0; + fwrite(&blockv,sizeof(struct VOCBLOCK1),1,fp); + /*VOC data*/ + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:(size-wsize); + if(fwrite((buffer+(wsize)),(size_t)sz,1,fp)!=1)ProgError("VOC: write error"); + } + blockv.type=0;/*last block*/ + fwrite(&blockv,1,1,fp); + fclose(fp); +} + +char huge *SNDloadVocFile(char *file, Int32 *psize, Int32 *pspeed) +{ FILE *fp; + Int32 wsize,sz=0,smplrate,datasize; + char huge *data; + fp=fopen(file,FOPEN_RB); + if(fp==NULL) ProgError("VOC: can't read file %s",file); + /*read VOC HEADER*/ + if(fread(&headv,sizeof(struct VOCHEAD),1,fp)!=1) ProgError("VOC: can't read header"); + if(strncmp(VocId,headv.ident,VOCIDLEN)!=0) ProgError("VOC: bad header"); + if(fseek(fp,headv.block1,SEEK_SET)) ProgError("VOC: bad header"); + if(fread(&blockv,sizeof(struct VOCHEAD),1,fp)!=1) ProgError("VOC: can't read block"); + if(blockv.type!=1) ProgError("VOC: first block is not sound"); + datasize= ((blockv.sizeU)<<16)&0xFF0000L; + datasize+=((blockv.sizeM)<<8)&0xFF00L; + datasize+= (blockv.sizeL)&0xFFL; + datasize -=2; + /*check VOC header*/ + if(datasize>0x10000L) ProgError("VOC: sample too long!"); + if(blockv.cmprs!=0) ProgError("VOC: compression not supported."); + smplrate= (1000000L)/(256-(((int)blockv.rate)&0xFF)); + /*read data*/ + data=(char huge *)Malloc(datasize); + for(wsize=0;wsizeMEMORYCACHE)? MEMORYCACHE:(datasize-wsize); + if(fread((data+(wsize)),(size_t)sz,1,fp)!=1) ProgError("VOC: can't read sound"); + } + fclose(fp); + /*should check for more blocks*/ + *psize=datasize; + *pspeed=smplrate&0xFFFFL; + return data; +} + + + + +/**************** generic sound *******************/ +void SNDsaveSound(char *file,char huge *buffer,Int32 size,SNDTYPE Sound,Bool fullSND) +{ char huge *data; + Int32 datasize; + Int16 type,speed,headsize; + headsize = sizeof(Int16)+sizeof(Int16)+sizeof(Int32); + if(size>8; + rate = ((Int32)speed<<8)/11025L; + if(speed>11025) + { Warning("shrinking %ld to 11025 sample/s",speed); + for(s=0;s>8; /* (s*((Int32)speed))/11025;*/ + data[s]= data[d]; + } + data=(char huge *)Realloc(data,soundsize); + } + else if(speed < 11025) + { Warning("expanding %ld to 11025 sample/s",speed); + data=(char huge *)Realloc(data,soundsize); + for(s=soundsize-1;s>=0;s--) + { d= (s*rate)>>8; + data[s]= data[d]; + } + } + else /*11025*/ + { soundsize=datasize; + } + if(soundsize>0) + { size= WADRwriteShort(info,3); + size+=WADRwriteShort(info,11025); + size+=WADRwriteLong(info,soundsize); + size+=WADRwriteBytes(info,data,soundsize); + } + Free(data); + return size; +} +/*********** end soundcard sound effects WAVE ***********/ + + + + +/*********** PC speaker sound effect ***********/ + + +void SNDsavePCSound(char *file,char huge *buffer,Int32 size) +{ FILE *fp; + char huge *data; + Int16 datasize,type,headsize; + Int16 i; + headsize = sizeof(Int16)+sizeof(Int16); + if(size255))ProgError("SND: number out of bounds [0-255]"); + datasize+=sizeof(char); + c=(char)(s&0xFF); + size+=WADRwriteBytes(info,&c,sizeof(c)); + } + WADRsetShort(info,datasizepos,datasize); + TXTcloseR(Txt); + return size; +} + +#endif /*DeuTex*/ + diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000..c44d4a1 --- /dev/null +++ b/src/sound.h @@ -0,0 +1,29 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/********************* sound.c *******************/ +void SNDsaveSound(char *file,char huge *buffer,Int32 size,SNDTYPE Sound,Bool fullSND); +Int32 SNDcopyInWAD(struct WADINFO *info,char *file,SNDTYPE Sound); +void SNDsavePCSound(char *file,char huge *buffer,Int32 size); +Int32 SNDcopyPCSoundInWAD(struct WADINFO *info,char *file); diff --git a/src/substit.c b/src/substit.c new file mode 100644 index 0000000..7504dff --- /dev/null +++ b/src/substit.c @@ -0,0 +1,168 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" + + +/*compile only for DeuTex*/ +#if defined DeuTex + + + +/****** DOOM EXE hacking module *********************/ +/* +Int16 const RAWSIZE = 0x2000; +Int16 const STRMAX = 256; +Int16 const SHOWPRGRS = 0x4000; + +void EXE2list(FILE *out,char *doomexe,Int32 start,Int16 thres) +{ FILE *exe; + char huge *raw; Int16 iraw,remains; + char huge *str; Int16 istr,count; + Int16 c; + Int32 lastpos,posit; + Int32 found=0; + count=0; + lastpos = posit=start; + iraw=0;raw= (char huge *)Malloc(RAWSIZE*sizeof(char)); + istr=0;str= (char huge *)Malloc((STRMAX+2)*sizeof(char)); + exe=fopen(doomexe,FOPEN_RB); + if(exe==NULL)ProgError("Can't open %s",doomexe); + if(fseek(exe,posit,SEEK_SET))ProgError("Can't seek in %s",doomexe); + + TXTinit(); + for(iraw=0,remains=0;;remains--,iraw++) + { if(remains==0) + { remains=fread(raw,1,RAWSIZE,exe); iraw=0;} + if(remains<=0) break; + c=raw[iraw]; + posit++; + switch(TXTvalid(c)) + { case 1: + count++; + str[istr]=c; + istr=(count=thres) + { fprintf(out,"let: #%s#\n be: #%s#\n\n",str,str); + found++; + } + if(posit>lastpos+SHOWPRGRS) + { lastpos=posit; + Phase("Current offset:0x%-6lx\tfound %ld strings\n",posit,found); + } + default: + count=0; + istr=0; + } +#ifdef WinDeuTex + windoze(); +#endif + } + Free(raw); + Free(str); +} + +void EXEsubstit(char *texin,char *doomexe,Int32 start,Int16 thres) +{ FILE *exe; + char huge *raw; Int16 iraw,remains; + char huge *str; Int16 strln,istr; + char huge *anew; Int16 anewln; + Int32 found; + Int16 c; Int16 ref; + Int32 lastpos,posit; + Bool similar,same; + struct TXTFILE *TXT; + TXT=TXTopen(texin); + + iraw=0;raw= (char huge *)Malloc(RAWSIZE*sizeof(char)); + istr=0;str= (char huge *)Malloc((STRMAX+2)*sizeof(char)); + anew = (char huge *)Malloc((STRMAX+2)*sizeof(char)); + exe=fopen(doomexe,FOPEN_RBP); + if(exe==NULL) + ProgError("Can't open %s for writing",doomexe); + + while(1) + { + strln=STRMAX; + anewln=STRMAX; + if(TXTboundStrings(TXT,str,&strln,anew,&anewln)!=TRUE) break; + if(strln=0) + { Warning("String defined twice: #%s#",str); + found=0;break; + } + found=lastpos; + } + } + same=similar=FALSE;istr=0;ref=str[istr]; + } +#ifdef WinDeuTex + windoze(); +#endif + } + + if(found>0) + { Detail("Writing at\t0x%-6lx\t#%s#\n",found,anew); + if(fseek(exe,found,SEEK_SET)) ProgError("Can't seek %s",doomexe); + if(fwrite(anew,1,strln,exe)!=strln) ProgError("Can't write %s correctly",doomexe); + } + else + Warning("Can't insert #%s#",anew); + } + fclose(exe); + Free(raw); + Free(str); + Free(anew); + TXTclose(TXT); +} +*/ +#endif /*DeuTex*/ + diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..a10157b --- /dev/null +++ b/src/text.c @@ -0,0 +1,452 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* +** This code should contain all the tricky O/S related +** functions. If you're porting DeuTex/DeuSF, look here! +*/ + +#include "deutex.h" +#include "tools.h" +#include "text.h" +#include + +/*compile only for DeuTex*/ +#if defined DeuTex + +/*****************************************************/ + +const Int16 SPACE = 0x2; +const Int16 NEWLINE = 0x4; +const Int16 COMMENT = 0x8; +const Int16 SECTION = 0x10; /*ok for SECTION header*/ +const Int16 NAME = 0x20; /*valid as a name identifier*/ +const Int16 NUMBER = 0x40; /*valid for a number*/ +const Int16 STPATCH = 0x80; /*start of patch?*/ +const Int16 EXESTRNG = 0x100; /*valid in #string# */ +const Int16 BOUNDARY = 0x200; /*#*/ +const Int16 STEQUAL = 0x400; /*=*/ +static Int16 TXTval[256]; +static Bool TXTok=FALSE; + + + +void TXTinit(void) +{ Int16 n,val; + for(n=0;n<256;n++) + { val=0; + switch(n) + { case '#': /*comment,string boundary*/ + val |=BOUNDARY+COMMENT;break; + case ';': /*comment*/ + val |=COMMENT+EXESTRNG;break; + case '\0': case '\n': /*newline*/ + val |=NEWLINE;break; + case '_': /*in name*/ + case '\\': /* deal with VILE strange name*/ + val |=NAME+EXESTRNG;break; + case '[': /* deal with VILE strange name*/ + case ']': /* deal with VILE strange name*/ + val |=SECTION+NAME+EXESTRNG;break; + case '-': case '+': /*in integer number*/ + val |=NUMBER+EXESTRNG;break; + case '*': /*start of patch wall*/ + val |= EXESTRNG+STPATCH;break; + case '=': + val |= STEQUAL+EXESTRNG;break; + case '?': case '!': + case '.': case ',': case '\'': + case '&': case '(': case ')': + case '$': case '%': case '@': + case '/': case '<': case '>': + case ' ': case '^': case '\"': + case ':': + val |=EXESTRNG;break; + default: break; + } + if(isdigit(n)) val |= NUMBER+EXESTRNG; + if(isalpha(n)) val |= SECTION+NAME+EXESTRNG; + if(isspace(n)) val |= SPACE; + if (n == '%') // Deal with Strife's "INVFONG%" and "INVFONY%" + val |= NAME; + TXTval[n]=val; + } + TXTok=TRUE; +} +void TXTcloseR(struct TXTFILE *TXT) +{ if(TXTok!=TRUE) Bug("TxtClo"); + fclose(TXT->fp); + Free(TXT); +} +struct TXTFILE *TXTopenR(char *file) +{ struct TXTFILE *TXT; + /*characters*/ + if(TXTok!=TRUE) TXTinit(); + TXT = (struct TXTFILE *)Malloc(sizeof(struct TXTFILE)); + /*some inits */ + TXT->Lines =1;/*start in line 1*/ + TXT->SectionStart=0; + TXT->SectionEnd =0; + TXT->fp = fopen(file,FOPEN_RT); + if(TXT->fp==NULL) ProgError("Could not open file %s for reading",file); + return TXT; +} + +static Bool TXTgetc(struct TXTFILE *TXT,Int16 *c,Int16 *val) +{ Int16 cc=(Int16)getc(TXT->fp ); + TXT->LastChar=cc; + if(cc==EOF) return FALSE; + *c = cc = (cc&0xFF); + *val=TXTval[cc]; + if(TXTval[cc]&NEWLINE) TXT->Lines++; + return TRUE; +} +static void TXTungetc(struct TXTFILE *TXT) +{ Int16 cc=TXT->LastChar; + cc = (cc&0xFF); + ungetc(cc,TXT->fp); + if(TXTval[cc]&NEWLINE) TXT->Lines--; +} +/*skip lines beginning with # or ; */ +Bool TXTskipComment(struct TXTFILE *TXT) +{ Int16 c=0,val=0; Bool comment; + for(comment=FALSE;;) + { if(TXTgetc(TXT,&c,&val)!=TRUE)return FALSE; + if(val & NEWLINE) /*eat newlines*/ + { comment=FALSE; continue;} + if(val & COMMENT) /*eat commentaries*/ + { comment=TRUE; continue;} + if(val & SPACE) /*eat space*/ + { continue;} + if(comment==FALSE) + { TXTungetc(TXT);return TRUE;} + } +} +/* find '*' */ +static Bool TXTcheckStartPatch(struct TXTFILE *TXT) +{ Int16 c=0, val=0; + if(TXTgetc(TXT,&c,&val)!=TRUE) return FALSE; + if(val & STPATCH) return TRUE; + TXTungetc(TXT); return FALSE; +} +/*read string, skip space before, stop space/\n*/ +static Bool TXTread(struct TXTFILE *TXT,char name[8],Int16 valid) +{ Int16 c=0,val=0,n=0; + while(1) + { if(TXTgetc(TXT,&c,&val)!=TRUE)return FALSE; + if(val & NEWLINE) continue; + if(val & SPACE) continue; + if(val & valid) break; + ProgError("Line %d: Illegal char '%c'",TXT->Lines,c); + } + name[0]=(char)c; + for(n=1; n<256; n++ ) + { if(TXTgetc(TXT,&c,&val)!=TRUE) break; + if(val&SPACE) + { TXTungetc(TXT);break;} + if(!(val&valid)) + ProgError("Line %d: Illegal char '%c' in word",TXT->Lines,c); + if(n<8) name[n]=(char)c; + } + if(n<8)name[n]='\0'; + return TRUE; +} +Int16 TXTreadShort(struct TXTFILE *TXT) +{ static char buffer[8]; + TXTread(TXT,buffer,NUMBER); + buffer[8]='\0'; + return (Int16)atoi(buffer); +} +static Bool TXTboundSection(struct TXTFILE *TXT); +static Bool TXTreadIdent(struct TXTFILE *TXT,char name[8]) +{ if(TXTok!=TRUE) Bug("TxtRid"); + if(TXTskipComment(TXT)==FALSE) return FALSE; + /*check end of section*/ + if((TXT->Lines)>(TXT->SectionEnd)) + { if(TXTboundSection(TXT)==FALSE) + return FALSE; /*no other section*/ + } + if(TXTread(TXT,name,NAME|NUMBER)!=TRUE) ProgError("Line %d: Expecting identifier or 'END:'",TXT->Lines); + Normalise(name,name); + return TRUE; +} + +/* +** STPATCH is also used to indicate repetition +*/ +static Bool TXTreadOptionalRepeat(struct TXTFILE *TXT) +{ Int16 c=0,val=0; + while(1) + { if(TXTgetc(TXT,&c,&val)!=TRUE) return FALSE; + if(!(val & NEWLINE)) + { if(val & STPATCH) break; /*look for STPATCH*/ + if(val & SPACE) continue; /*skip space*/ + } + TXTungetc(TXT); + return FALSE; + } + return TRUE; /*found*/ +} +/* +** STEQUAL is used to indicate alternate name +*/ +static void TXTreadOptionalName(struct TXTFILE *TXT,char name[8]) +{ Int16 c=0,val=0; + while(1) + { if(TXTgetc(TXT,&c,&val)!=TRUE) return; + if(!(val & NEWLINE)) + { if(val & STEQUAL) continue; /*skip '='*/ + if(val & SPACE) continue; /*skip space*/ + if(val & (NAME&(~NUMBER))) break; + } + TXTungetc(TXT); + return; /*name is NOT modified*/ + } + TXTungetc(TXT); + if(TXTread(TXT,name,NAME|NUMBER)!=TRUE) + { ProgError("invalid optional name"); + } +} +/* +** Read integer if exist before NEWLINE, +** but don't eat NEWLINE +*/ +static Int16 TXTreadOptionalShort(struct TXTFILE *TXT) +{ static char name[8]; + Int16 n,c=0,val=0; + while(1) + { if(TXTgetc(TXT,&c,&val)!=TRUE)return INVALIDINT; + if(!(val & NEWLINE)) + { if(val & SPACE) continue; /*skip space*/ + if(val & STEQUAL) continue; /*skip '='*/ + if(val & NUMBER) break; /*look for number*/ + } + TXTungetc(TXT); + return INVALIDINT; /*not a number. abort*/ + } + name[0]=(char)c; + for(n=1; n<256; n++ ) + { if(TXTgetc(TXT,&c,&val)!=TRUE) break; + if(val&NEWLINE) {TXTungetc(TXT);break;} + if(val&SPACE)break; + if(!(val&NUMBER)) + ProgError("Line %d: Illegal char '%c' in number",TXT->Lines,c); + if(n<8) name[n]=(char)c; + } + if(n<8)name[n]='\0'; + name[8]='\0'; + return (Int16)atoi(name); +} + +/* read Blocks of the form +** [BLOCKID] +** identifier ... anything ... +** identifier ... anything ... +*/ +static Bool TXTfindSection(struct TXTFILE *TXT,Bool Match) +{ Int16 c=0,val=0,n; + char buffer[8]; + while(1) + { if(TXTskipComment(TXT)!=TRUE) return FALSE; + if(TXTgetc(TXT,&c,&val)!=TRUE)return FALSE; + if(c=='[') + { for(n=0;n<256;n++) + { if(TXTgetc(TXT,&c,&val)!=TRUE) return FALSE; + if(c==']') + { if(n<8)buffer[n]='\0'; + if(Match==FALSE) return TRUE;/*any section is ok*/ + Normalise(buffer,buffer); /*the right section?*/ + if(strncmp(buffer,TXT->Section,8)==0) return TRUE; + break; /*not the right section*/ + } + if(!(val & (NAME|NUMBER))) break; /*not a section*/ + if(n<8) buffer[n]=c; + } + } + while(1) /*look for end of line*/ + { if(TXTgetc(TXT,&c,&val)!=TRUE)return FALSE; + if(val & NEWLINE) break; + } + } +} +/* +** find the section boundaries, from current position in file +*/ +static Bool TXTboundSection(struct TXTFILE *TXT) +{ Int16 c=0,val=0; + if(TXTfindSection(TXT,TRUE)!=TRUE) return FALSE; + TXT->SectionStart=TXT->Lines+1; + /*check that we don't read twice the same section*/ + if(TXT->SectionEnd>TXT->SectionStart) Bug("TxtBdS"); + if(TXTfindSection(TXT,FALSE)==TRUE) + TXT->SectionEnd=TXT->Lines-1; + else + TXT->SectionEnd=TXT->Lines; + /* set pointer to first section line*/ + fseek(TXT->fp,0,SEEK_SET); + TXT->Lines =1;/*start in line 1*/ + while(TXT->LinesSectionStart) + { if(TXTgetc(TXT,&c,&val)!=TRUE)return FALSE; + } + return TRUE; +} +Bool TXTseekSection(struct TXTFILE *TXT,char *section) +{ + if(TXTok!=TRUE) Bug("TxtSks"); + /*seek begin of file*/ + TXT->SectionStart=0; + TXT->SectionEnd =0; + Normalise(TXT->Section,section); + fseek(TXT->fp,0L,SEEK_SET); + TXT->Lines =1;/*start in line 1*/ + /*skipping comments, look for a line with + [section]*/ + return TXTboundSection(TXT); +} + + + +/*read a texture definition*/ +/*return FALSE if read End*/ +Bool TXTreadTexDef(struct TXTFILE *TXT,char name[8],Int16 *szx,Int16 *szy) +{ if(TXTok!=TRUE) Bug("TxtTxd"); + if(TXTskipComment(TXT)==FALSE) return FALSE; /*End*/ + if(TXTread(TXT,name,NAME|NUMBER)!=TRUE) ProgError("Line %d: Expecting identifier",TXT->Lines); + Normalise(name,name); + *szx=TXTreadShort(TXT); + *szy=TXTreadShort(TXT); + return TRUE; +} +/*read a patch def. Return FALSE if could not find '*' */ +Bool TXTreadPatchDef(struct TXTFILE *TXT,char name[8],Int16 *ofsx,Int16 *ofsy) +{ if(TXTok!=TRUE) Bug("TxtRpd"); + if(TXTskipComment(TXT)==FALSE) return FALSE; + if(TXTcheckStartPatch(TXT)!=TRUE) return FALSE; /*not a patch line*/ + if(TXTread(TXT,name,NAME|NUMBER)!=TRUE) + ProgError("Line %d: Expecting identifier",TXT->Lines); + Normalise(name,name); + *ofsx=TXTreadShort(TXT); + *ofsy=TXTreadShort(TXT); + return TRUE; +} +/* +**TXTentryParse(name,filenam,&X,&Y,&Repeat,TXT,TRUE) +*/ +Bool TXTentryParse(char *name,char *filenam,Int16 *x,Int16 *y,Bool *repeat, struct TXTFILE *TXT, Bool XY) +{ Int16 c=0,val=0; Bool comment; + Int16 xx=INVALIDINT,yy=INVALIDINT; + if(TXTreadIdent(TXT,name)!=TRUE) return FALSE; + /* skip the equal*/ + if(TXTgetc(TXT,&c,&val)!=TRUE) return FALSE; + if(c!='=') TXTungetc(TXT); + /* read integer*/ + if(XY==TRUE) + { xx=TXTreadOptionalShort(TXT); + yy=TXTreadOptionalShort(TXT); + } + Normalise(filenam,name); + TXTreadOptionalName(TXT,filenam); + if(XY==TRUE) + { if(xx==INVALIDINT) xx=TXTreadOptionalShort(TXT); + if(yy==INVALIDINT) yy=TXTreadOptionalShort(TXT); + } + *repeat= TXTreadOptionalRepeat(TXT); + *x=xx; + *y=yy; + for(comment=FALSE;;) + { if(TXTgetc(TXT,&c,&val)!=TRUE)break; + if(val & NEWLINE) break; + if(val & COMMENT) /*eat commentaries*/ + { comment=TRUE; continue;} + if(val & SPACE) /*eat space*/ + { continue;} + if(comment==FALSE) + { ProgError("Line %d: bad entry format",TXT->Lines);} + } + return TRUE; +} + + + + + + + + +/* +** For any Writing of text files +*/ +struct TXTFILE *TXTopenW(char *file) /*open, and init if needed*/ +{ struct TXTFILE *TXT; + /*characters*/ + if(TXTok!=TRUE) TXTinit(); + TXT = (struct TXTFILE *)Malloc(sizeof(struct TXTFILE)); + /*some inits */ + TXT->Lines =1;/*start in line 1*/ + TXT->SectionStart=0; + TXT->SectionEnd =0; + TXT->fp = fopen(file,FOPEN_RT); + if(TXT->fp==NULL) + { TXT->fp = fopen(file,FOPEN_WT); + } + else + { fclose(TXT->fp); + TXT->fp = fopen(file,FOPEN_AT); + Warning("Appending to file %s",file); + } + if(TXT->fp==NULL) ProgError("Could not write file %s",file); + return TXT; +} +void TXTcloseW(struct TXTFILE *TXT) +{ if(TXTok!=TRUE) Bug("TxtClo"); + fclose(TXT->fp); + Free(TXT); +} + +/* +** To write entries +*/ +void TXTaddSection(struct TXTFILE *TXT,char *def) +{ if(TXTok!=TRUE) Bug("TxtAdS"); + fprintf(TXT->fp,"[%.8s]\n",def); +} +void TXTaddEntry(struct TXTFILE *TXT,char *name,char *filenam,Int16 x,Int16 y,Bool repeat, Bool XY) +{ if(TXTok!=TRUE) Bug("TxtAdE"); + fprintf(TXT->fp,"%.8s",name); +/* fprintf(TXT->fp,"%.8s=",name);*/ + if(filenam!=NULL) + fprintf(TXT->fp,"\t%.8s",filenam); + if(XY==TRUE) + fprintf(TXT->fp,"\t%d\t%d",x,y); + if(repeat==TRUE) + fprintf(TXT->fp,"\t*"); + fprintf(TXT->fp,"\n"); +} +void TXTaddComment(struct TXTFILE *TXT,char *text) +{ if(TXTok!=TRUE) Bug("TxtAdC"); + fprintf(TXT->fp,";%.256s\n",text); +} + +#endif /*DeuTex*/ + diff --git a/src/text.h b/src/text.h new file mode 100644 index 0000000..6ec1b90 --- /dev/null +++ b/src/text.h @@ -0,0 +1,70 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +/* +** simplified TEXT parsing +*/ +struct TXTFILE +{ FILE *fp; + Int16 Lines; + Int16 LastChar; + Int16 SectionStart; + Int16 SectionEnd; + char Section[8]; +}; +/* +** For any Reading of TEXT files +*/ +void TXTinit(void); +struct TXTFILE *TXTopenR(char *file); /*open, and init if needed*/ +void TXTcloseR(struct TXTFILE *TXT); +/* +** To read entries +*/ +Bool TXTskipComment(struct TXTFILE *TXT); +Bool TXTseekSection(struct TXTFILE *TXT,char *def); +Bool TXTentryParse(char *name,char *filenam,Int16 *x,Int16 *y,Bool *repeat, struct TXTFILE *TXT, Bool XY); +/* +** To read textures +*/ +Bool TXTreadTexDef(struct TXTFILE *TXT,char name[8],Int16 *szx,Int16 *szy); +Bool TXTreadPatchDef(struct TXTFILE *TXT,char name[8],Int16 *ofsx,Int16 *ofsy); +/* +** To read PC sounds +*/ +Int16 TXTreadShort(struct TXTFILE *TXT); + + +/* +** For any Writing of text files +*/ +struct TXTFILE *TXTopenW(char *file); /*open, and init if needed*/ +void TXTcloseW(struct TXTFILE *TXT); +/* +** To write entries +*/ +void TXTaddSection(struct TXTFILE *TXT,char *def); +void TXTaddEntry(struct TXTFILE *TXT,char *name,char *filenam,Int16 x,Int16 y,Bool repeat, Bool XY); +void TXTaddComment(struct TXTFILE *TXT,char *text); + diff --git a/src/texture.c b/src/texture.c new file mode 100644 index 0000000..a7b32d7 --- /dev/null +++ b/src/texture.c @@ -0,0 +1,598 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include "tools.h" +#include "endianm.h" +#include "text.h" +#include "mkwad.h" +#include "texture.h" + +/* add new patchs by cluster of 64 */ +#define NEWPATCHS 0x40 +/* add new textures by cluster of 64 */ +#define NEWTEXTURES 0x40 +/* more than 8000 textures is unreasonable */ +#define MAXTEXTURES 0x2000 +/* no more than 256 patches per cluster */ +#define MAXPATCHPERTEX 0x100 +/* add new patch defs by cluster of 128*/ +#define NEWPATCHESDEF 0x80 + +/* +TEXU + module that stores the textures definitions + +PNM + modules that stores the patch names + +*/ + +/***************Begin PNAME module*****************/ +static struct PNMP{char name[8];} huge *PNMpatchs; +static Int16 PNMtop; +static Int16 PNMmax; +static Int16 PNMknown; +static Bool PNMok = FALSE; + + + +void PNMinit(char huge *buffer,Int32 size) +{ Int16 n,i; + char picname[8]; + Int32 pnames; + /*find the number of entries in PNAME*/ + pnames=0; + if(size>4L) + { pnames = peek_i32_le (buffer); + if(pnames>0x7FFFL) ProgError("Too many patches"); + if(size<(4L+8L*pnames)) ProgError("Wrong size of PNAMES entry"); + } + /*initialise*/ + PNMmax=(Int16)(pnames+NEWPATCHS); + PNMpatchs=(struct PNMP huge *)Malloc(PNMmax*sizeof(struct PNMP)); + PNMtop=(Int16)pnames; + PNMknown=0; + /*Read patches*/ + if(pnames<=0)return; + for(n=0;n=PNMmax) + { PNMmax+=NEWPATCHS; + PNMpatchs=(struct PNMP huge *)Realloc(PNMpatchs,PNMmax*sizeof(struct PNMP)); + } + } + return idx; +} +/* +** get name from index +*/ +void PNMgetPatchName(char name[8],Int16 index) +{ if(PNMok!=TRUE)Bug("PNMok"); + if(index>=PNMtop) Bug("PnmGP>"); + Normalise(name,PNMpatchs[index].name); +} + +/* +** Insert in directory all the entries which are not +** referenced in DOOM.WAD +*/ +Int16 PNMgetNbOfPatch(void) +{ return PNMtop; +} +Bool PNMisNew(Int16 idx) +{ if(PNMok!=TRUE)Bug("PNMok"); + if(idx>=PNMtop)Bug("PnmIN>"); + /*check if patch was added after initial definition*/ + if(idx>PNMknown) return TRUE; + return FALSE; +} +void PNMfree(void) +{ PNMok=FALSE; + Free(PNMpatchs); +} +/********Write PNAME entry in WAD********/ +Int32 PNMwritePNAMEtoWAD(struct WADINFO *info) +{ Int16 idx; Int32 size =0; + char buffer[8]; + if(PNMok!=TRUE)Bug("PNMok"); + /*Write the Number of entries*/ + size+=WADRwriteLong(info,PNMtop); + /*Then write the names , '\0' padded*/ + for(idx=0;idx=TXUtexMax) + { TXUtexMax+=NEWTEXTURES; + TXUtex=(struct TEXTUR *)Realloc(TXUtex,TXUtexMax*sizeof(struct TEXTUR)); + } + Normalise(TXUtex[TXUtexCur].Name,name); /*declare texture*/ + TXUtex[TXUtexCur].szX=X; + TXUtex[TXUtexCur].szY=Y; + TXUtex[TXUtexCur].Npatches=0; + /*check if we redefine other textures, and overide them.*/ + for(t=0;t=TXUpatMax) + { TXUpatMax+=NEWPATCHESDEF; + TXUpat=(struct PATCH *) Realloc(TXUpat,TXUpatMax*sizeof(struct PATCH)); + } + if(TXUtexCur<0) Bug("TXUTxC"); + PNMgetPatchName(pname,pindex); /*check if index correct*/ + TXUtex[TXUtexCur].Npatches+=1; /*increase texture's patch counter*/ + TXUpat[TXUpatTop].Pindex=pindex;/*declare patch*/ + TXUpat[TXUpatTop].ofsX=ofsX; + TXUpat[TXUpatTop].ofsY=ofsY; + TXUpatTop+=1; +} +void TXUfree(void) +{ if(TXUok!=TRUE) Bug("TXUok"); + Free(TXUpat); + Free(TXUtex); + TXUok=FALSE; +} + +Bool TXUexist(char *Name) +{ int t; + if(TXUok!=TRUE) Bug("TXUok"); + for(t=0;t=NbOfTex)Bug("TxuRT"); + WADRsetLong(info,ofsTble+tt*4,size);tt++; + /*write texture*/ + Normalise(texdef.name,TXUtex[t].Name); + write_i16_le (&texdef.dummy0a, 0); + write_i16_le (&texdef.dummy0b, 0); + write_i16_le (&texdef.xsize, TXUtex[t].szX); + write_i16_le (&texdef.ysize, TXUtex[t].szY); + write_i16_le (&texdef.dummy0c, 0); + write_i16_le (&texdef.dummy0d, 0); + write_i16_le (&texdef.numpat, TXUtex[t].Npatches); + /*write the begining of texture definition*/ + size+=WADRwriteBytes(info,(char huge *)&texdef,sizeof(struct TEXDEF)); + for(p=0; p<(TXUtex[t].Npatches); p++) + { if(pat+p>=TXUpatTop) Bug("TxuP>D");/*number of patches exceeds definitions*/ + /*write patch definition*/ + write_i16_le (&patdef.pindex, TXUpat[pat+p].Pindex); + write_i16_le (&patdef.xofs, TXUpat[pat+p].ofsX); + write_i16_le (&patdef.yofs, TXUpat[pat+p].ofsY); + write_i16_le (&patdef.dummy1, 1); + write_i16_le (&patdef.dummy0, 0); + size+=WADRwriteBytes(info,(char huge *)&patdef,sizeof(struct PATDEF)); + } + } + pat+=TXUtex[t].Npatches; + } + return size; +} +/* +** +** convert raw data (as read from wad) into Textures +** Data= texture entry +** if PatchSz>0, Patch defines the patch list +*/ +void TXUreadTEXTURE(char huge *Data,Int32 DataSz,char huge *Patch, Int32 PatchSz,Bool Redefn) +{ Int32 Pos, Numtex, Numpat, dummy; + /* texture data*/ + Int16 t,p,i, Xsize, Ysize; /* size x and y */ + /* nb of wall patches used to build it */ + /* wall patch inside a texture */ + Int16 Xofs, Yofs,Pindex; /* x,y coordinate in texture space*/ + /* patch name index in PNAMES table */ + Int32 MaxPindex; + static char tname[8]; /*texture name*/ + static char pname[8]; /*patch name*/ + struct TEXDEF huge *texdef; + struct PATDEF huge *patdef; + /*si Patch==NULL alors utiliser Pname list*/ + + /*get number of patches*/ + if(PatchSz>0) + { MaxPindex = peek_i32_le (Patch); + dummy=4L+(MaxPindex*8L); + if(dummy>PatchSz) ProgError("Bad PNAMES format"); + } + else + { MaxPindex = PNMgetNbOfPatch(); + } + if((MaxPindex<0)||(MaxPindex>0x7FFF)) ProgError("Bad PNAMES entry"); + /*get number of textures*/ + Numtex = peek_i32_le (Data); + if(Numtex<0) ProgError("Bad TEXTURE entry"); + if(Numtex>MAXTEXTURES) ProgError("Too many TEXTUREs"); + /*read textures*/ + for (t = 0; t DataSz) ProgError("TEXTURE entry too small"); + texdef= (struct TEXDEF huge *)(&Data[Pos]); + Normalise(tname,texdef->name); + Xsize = peek_i16_le (&texdef->xsize); + if((Xsize<0)||(Xsize>4096)) ProgError("texture width out of bound"); + Ysize = peek_i16_le (&texdef->ysize); + if((Ysize<0)||(Ysize>4096)) ProgError("texture height out of bound"); + Numpat = peek_i16_le (&texdef->numpat)&0xFFFF; + if((Numpat<0)||(Numpat>MAXPATCHPERTEX)) + ProgError("Too many patches in texture"); + + /* declare texture */ + TXUdefineCurTex(tname,Xsize,Ysize,Redefn); + /* set Position to start of patches defs*/ + Pos= Pos+sizeof(struct TEXDEF); + dummy=Pos+(Numpat*sizeof(struct PATDEF)); + if(dummy>DataSz) ProgError("TEXTURE entry too small"); + for (p = 0; p < Numpat; p++, Pos+=sizeof(struct PATDEF)) + { patdef=(struct PATDEF huge *)(&Data[Pos]); + Xofs = peek_i16_le (&patdef->xofs); + if((Xofs<-4096)||(Xofs>4096))ProgError("Bad Patch X offset"); + Yofs = peek_i16_le (&patdef->yofs); + if((Yofs<-4096)||(Yofs>4096))ProgError("Bad Patch Y offset"); + Pindex = peek_i16_le (&patdef->pindex); + if((Pindex<0)||(Pindex>MaxPindex))ProgError("Bad Patch index"); + /*if new patch list, recalculate Pindex*/ + if(PatchSz>0) + { for(dummy=(4L+(Pindex*8L)),i=0;i<8;i++) + pname[i]=Patch[dummy+i]; + Pindex=PNMgetPatchIndex(pname); + } + /*declare patch*/ + TXUaddPatchToCurTex(Pindex,Xofs,Yofs); + } + } +} + +Bool TXUcheckTex(Int16 npatch,Int16 huge *PszX) +{ Int16 t,tt,p,pat,col,top,found; + Int16 bit,C,b; /*bit test*/ + Int16 Meduza; + Bool Res=TRUE; + if(TXUok!=TRUE) Bug("TXUok"); + Output("Checking textures\n"); + if(TXUtexTop<1) Bug("TxuNTx"); + if(TXUtexTop<100) Output("Warning: Some textures could be missing! (less than 100 defined)\n"); + for(pat=0, t=0; tTXUpatTop) Bug("TxuP>D"); + /* + ** check width + */ + for(bit=1,C=0,b=0;b<16;b++,bit<<=1) if((TXUtex[t].szX)&bit) C++; + if(C>1) + { Output("Warning: Width of %.8s is not a power of 2\n",TXUtex[t].Name); + Res=FALSE; + } + /* + ** check height + */ + if(TXUtex[t].szY>128) + { Output("Warning: Height of %.8s is more than 128\n",TXUtex[t].Name); + Res=FALSE; + } + /* + ** check patch for: + ** - void columns (crashes the game at boot) + ** - possible meduza effect (if the patch is used on 2S walls) + */ + Meduza=0; + for(col=0;col=npatch) + Bug("~TxuP>D"); + if(col>=TXUpat[pat+p].ofsX) + { top=PszX[TXUpat[pat+p].Pindex]+TXUpat[pat+p].ofsX; + if(col=2) + break; /*two patches on same column. Meduza effect*/ + else + Meduza++; /*keep looking for patches*/ + } + } + } + if(found==FALSE) + { Output("Warning: Empty column %d in texture %.8s\n",col,TXUtex[t].Name); + Res=FALSE; + } + } + if(Meduza>=2) /*there is a colum with two patches*/ + { Output("Warning: Texture %.8s should not be used on a two sided wall.\n",TXUtex[t].Name); + } + pat+=TXUtex[t].Npatches; + } + /* + ** check duplication + */ + for(t=0; t=TXUtexMax) + { TXUtexMax+=NEWTEXTURES; + TXUtex=(struct TEXTUR *)Realloc(TXUtex,TXUtexMax*sizeof(struct TEXTUR)); + } + Normalise(TXUtex[TXUtexCur].Name,Name); /*declare texture*/ + TXUtex[TXUtexCur].szX=0; + TXUtex[TXUtexCur].szY=0; + TXUtex[TXUtexCur].Npatches=0; +} +/* +** list the names of the textures defined +*/ +void TXUlistTex(void) +{ Int16 t; + if(TXUok!=TRUE) Bug("TXUok"); + for (t= 0; t =TXUpatTop) Bug("TxuP>D"); + PNMgetPatchName(pname,TXUpat[pat+p].Pindex); + fprintf(out,"*\t%-8.8s ",pname); + fprintf(out,"\t%d\t%d\n",TXUpat[pat+p].ofsX,TXUpat[pat+p].ofsY); + } + } + pat+=TXUtex[t].Npatches; + } + fprintf(out,";End\n"); + fclose(out); +} +/* +** read texture as text file +** +*/ +void TXUreadTexFile(char *file,Bool Redefn) +{ Int16 Pindex; + Int16 xsize=0,ysize=0,ofsx=0,ofsy=0; + char tname[8]; + char pname[8]; + Int16 t,p,bit,C,b; /*to check Xsize*/ + struct TXTFILE *TXT; + TXT=TXTopenR(file); +/* if(TXTbeginBloc(TXT,"TEXTURES")!=TRUE)ProgError("Invalid texture file format: %s",file); +*/ + for(t=0;t4096)) ProgError("texture width out of bound"); + for(bit=1,C=0,b=0;b<16;b++,bit<<=1) if(xsize&bit) C++; + if(C>1) Warning("Bogus texture %.8s. Width should be a power of 2",tname); + /* check Y size */ + if((ysize<0)||(ysize>4096)) ProgError("texture height out of bound"); + // AYM 1999-05-17 + if(ysize>509) Warning("Bogus texture %.8s. Heights above 509 are ignored",tname); + /* declare texture */ + TXUdefineCurTex(tname,xsize,ysize, Redefn); + for(p=0;p +# include +# include +# include +# elif DT_CC == 'b' /* Borland C for DOS */ +# include +# include +# include +# else /* Other compiler (MSC ?) for DOS */ +# include +# include +# include +# endif +/*OS/2*/ +#elif DT_OS == 'o' +# define SEPARATOR "\\" +# include +# include +# include +/*UNIX*/ +#else +# define SEPARATOR "/" +# include +# include +# include +#endif + +#if DT_OS == 'o' && DT_CC == 'i'\ + || DT_OS == 'd' && DT_CC == 'm' +# include +#else +# include +#endif + +#include +#include +#include +#include +#include + + +/* + * check_types + * Sanity checks on the specified-width types. + * Will help catching porting errors. + */ +typedef struct +{ + const char *name; + size_t mandated_size; + size_t actual_size; +} type_check_t; + +static const type_check_t type_checks[] = +{ + { "Int8", 1, sizeof (Int8) }, + { "Int16", 2, sizeof (Int16) }, + { "Int32", 4, sizeof (Int32) }, + { "UInt8", 1, sizeof (UInt8) }, + { "UInt16", 2, sizeof (UInt16) }, + { "UInt32", 4, sizeof (UInt32) } +}; + +void check_types (void) +{ + const type_check_t *t; + for (t = type_checks; t - type_checks < sizeof type_checks / sizeof *t; t++) + { + if (t->actual_size != t->mandated_size) + ProgError ("Type %s has size %d (should be %d)." + " Fix deutex.h and recompile.", + t->name, (int) t->actual_size, (int) t->mandated_size); + } +} + + +/* +** Resize a file +** returns 0 if okay -1 if failed. +*/ +Int16 Chsize(int handle,Int32 newsize) +{ +#if DT_OS == 'd' +# if DT_CC == 'd' + return (Int16)ftruncate(handle, newsize); +# elif DT_CC == 'b' || DT_CC == 'm' + return (Int16)chsize(handle,newsize); +# else +# error Chsize unimplemented +# endif +#elif DT_OS == 'o' +# if DT_CC == 'b' + return (Int16)chsize(handle,newsize); +# else + return (Int16)_chsize(handle,newsize); +# endif +#else + return (Int16)ftruncate(handle, newsize); +#endif +} + +/* +** Delete a file +*/ +void Unlink(char *file) +{ remove (file); +} + +/* +** Get a file time stamp. (date of last modification) +*/ +Int32 GetFileTime(char *path) +{ Int32 time; + struct stat statbuf; + stat(path,&statbuf); + time =statbuf.st_ctime; + return time; +} +/* +** Set a file time stamp. +*/ +void SetFileTime(char *path, Int32 time) +{ + struct utimbuf stime; + stime.modtime=stime.actime=time; +#if DT_OS == 'o' && DT_CC != 'b' + _utime(path, &stime); +#else + utime(path, &stime); +#endif +} +/* +** Copy memory +*/ +void Memcpy(void huge *dest,const void huge *src, Int32 n) +{ if(n<0) Bug("MovInf"); /*move inf to zero*/ + if(n==0)return; +#if DT_OS == 'd' +# if DT_CC == 'd' + memcpy((char huge *)dest,(char huge *)src,(size_t)n); +# else + if(n>0x10000L) Bug("MovSup"); /*DOS limit: not more than 0x10000*/ + _fmemcpy(dest,src,(size_t)n); +# endif +#elif DT_OS == 'o' + memcpy((char huge *)dest,(char huge *)src,(size_t)n); +#else + memcpy((char huge *)dest,(char huge *)src,(size_t)n); +#endif +} +/* +** Set memory +*/ +void Memset(void huge *dest,char car, Int32 n) +{ if(n<0) Bug("MStInf"); /*set inf to zero*/ + if(n==0)return; +#if DT_OS == 'd' +# if DT_CC == 'd' + memset(dest,car,(size_t)n); +# else + if(n>0x10000L) Bug("MStSup"); /*DOS limit: not more than 0x10000*/ + _fmemset(dest,car,(size_t)n); +# endif +#elif DT_OS == 'o' + memset(dest,car,(size_t)n); +#else + memset(dest,car,(size_t)n); +#endif +} +/* +** Allocate memory +*/ +/*code derived from DEU*/ +#define SIZE_THRESHOLD 0x400L +#define SIZE_OF_BLOCK 0xFFFL +/* actually, this is (size - 1) */ +void huge *Malloc( Int32 size) +{ + void huge *ret; + if(size<1) + { Warning("Attempt to allocate %ld bytes",size); + size=1; + } +#if DT_OS == 'd' && DT_CC == 'b' + ret = farmalloc( size); +#else + if ((size_t) size != size) + ProgError ("Tried to allocate %ld b but couldn't." + " Use another compiler.", size); + ret = malloc((size_t) size); +#endif + if (ret==NULL) + ProgError("Out of memory (Needed %ld bytes)", size); + return ret; +} +/* +** Reallocate memory +*/ +void huge *Realloc( void huge *old, Int32 size) +{ void huge *ret; + + if(size<1) + { Warning("Attempt to allocate %ld bytes",size); + size=1; + } +#if DT_OS == 'd' && DT_CC == 'b' + ret = farrealloc( old, size); +#else + if ((size_t) size != size) + ProgError ("Tried to realloc %ld b but couldn't." + " Use another compiler.", size); + ret = realloc( old, (size_t)size); +#endif + if (ret==NULL) + ProgError( "Out of memory (Needed %ld bytes)", size); + return ret; +} +/* +** Free +*/ +void Free( void huge *ptr) +{ +#if DT_OS == 'd' && DT_CC == 'b' + farfree( ptr); +#else + free( ptr ); +#endif +} +/*****************************************************/ +/* +** Use only lower case file names +*/ +void ToLowerCase(char *file) +{ Int16 i; + for(i=0;(i<128)&&(file[i]!='\0');i++) + file[i]=tolower((((Int16)file[i])&0xFF)); +} +static void NameDir(char file[128], char *path,char *dir,char *sdir) +{ + file[0]='.'; + file[1]='\0'; + if(path!=NULL) if(strlen(path)>0){ strncpy(file,path,80);} + if(dir!=NULL) if(strlen(dir)>0) + { strcat(file,SEPARATOR);strncat(file,dir,12);} + if(sdir!=NULL) if(strlen(sdir)>0) + { strcat(file,SEPARATOR);strncat(file,sdir,12);} + ToLowerCase(file); +} +/* +** Create directory if it does not exists +*/ +void MakeDir(char file[128], char *path,char *dir,char *sdir) +{ NameDir(file,path,dir,sdir); +#if DT_OS == 'd' +# if DT_CC == 'd' + mkdir(file,0); /*2nd argument not used in DOS*/ +# elif DT_CC == 'b' || DT_CC == 'm' + mkdir(file); +# else +# error MakeDir unimplemented +# endif +#elif DT_OS == 'o' +# if DT_CC == 'b' + mkdir(file); +# else + _mkdir(file); +# endif +#else + mkdir(file,(mode_t)S_IRWXU); /*read write exec owner*/ +#endif +} +/* +** Create a file name, by concatenation +** returns TRUE if file exists FALSE otherwise +*/ +Bool MakeFileName(char file[128], char *path,char *dir,char *sdir,char *name,char *extens) +{ FILE *fp; + char name2[8]; /* AYM 1999-01-13: keep checker happy */ + /* deal with VILE strange name + ** replace the VILE[ VILE\ VILE] + ** by VIL@A VIL@B VIL@C + */ + Normalise(name2,name); + + /* FIXME AYM 1999-06-09: Not sure whether it is a good thing + to keep this translation scheme for the Unix version. + However, removing it would make the DOS version and the + Unix version incompatible. */ + switch(name2[4]) + { case '[': name2[4]='$';break; + case '\\': name2[4]='@';break; + case ']': name2[4]='#';break; + } + switch(name2[6]) + { case '[': name2[6]='$';break; + case '\\': name2[6]='@';break; + case ']': name2[6]='#';break; + } + + NameDir(file,path,dir,sdir); + /* + ** file name + */ + strcat(file,SEPARATOR); + strncat(file,name2,8); + strcat(file,"."); + strncat(file,extens,4); + ToLowerCase(file); + /* + ** check if file exists + */ + fp=fopen(file,FOPEN_RB); + if(fp!=NULL) + { fclose(fp); /* AYM 1999-01-??: fclose() used to be called even if + fopen() had returned NULL! It gave beautiful segfaults. */ + return TRUE; + } + return FALSE; +} +/* +** Get the root name of a WAD file +*/ +void GetNameOfWAD(char name[8],char *path) +{ Int16 n, nam,len; + len=(Int16)strlen(path); + /*find end of DOS or Unix path*/ + for(nam=n=0;n4)? 4:level; +} +void PrintExit(void) +{ if(asFile==TRUE) + { fclose(Stdout); + fclose(Stderr); + /*fclose(Stdinfo);*/ + } +} + + +void ActionDummy(void) +{ return; } +static void (*Action)(void)=ActionDummy; +void ProgErrorCancel(void) +{ Action = ActionDummy; +} +void ProgErrorAction(void (*action)(void)) +{ Action = action; +} +void ProgError( char *errstr, ...) +{ + va_list args;va_start( args, errstr); + fprintf(Stderr, "\nError: *** "); + vfprintf(Stderr, errstr, args); + fprintf(Stderr, " ***\n"); + va_end( args); + (*Action)(); /* execute error handler*/ + PrintExit(); + exit( -5); +} +void Bug( char *errstr, ...) +{ va_list args;va_start( args, errstr); + fprintf(Stderr, "\nBug: *** "); + vfprintf(Stderr, errstr, args); + fprintf(Stderr, " ***\n"); + fprintf(Stderr, "Please report that bug.\n"); + va_end( args); /* CloseWadFiles();*/ + PrintExit(); + exit( -10); +} +void Warning( char *str, ...) +{ va_list args;va_start( args, str); + fprintf(Stdwarn, "Warning: ** "); + vfprintf(Stdwarn, str, args); + fprintf(Stdwarn, " **\n"); + va_end( args); +} +void Legal(char *str, ...) +{ va_list args;va_start( args, str); + vfprintf(stdout, str, args); + va_end( args); +} +void Output(char *str, ...) +{ va_list args;va_start( args, str); + vfprintf(Stdout, str, args); + va_end( args); +} +void Info(char *str, ...) +{ va_list args;va_start( args, str); + if(Verbosity>=1) + vfprintf(Stdinfo, str, args); + va_end( args); +} +void Phase(char *str, ...) +{ va_list args;va_start( args, str); + if(Verbosity>=2) + vfprintf(Stdinfo, str, args); + va_end( args); +} +void Detail(char *str, ...) +{ va_list args;va_start( args, str); + if(Verbosity>=3) + vfprintf(Stdinfo, str, args); + va_end( args); +} +#if 0 +Int16 NbP=0; +void Progress(void) +{ NbP++; + if(NbP&0xF==0) fprintf(Stdinfo,"."); + if(NbP>0x400) + { NbP=0; + fprintf(Stdinfo,"\n"); + } +} +void ProgressEnds(void) +{ fprintf(Stdinfo,"\n"); +} +#endif + + + + + + + diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..1e9fc8b --- /dev/null +++ b/src/tools.h @@ -0,0 +1,71 @@ +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +void check_types (void); + +void PrintCopyright(void); +void NoCommandGiven(void); + + +void PrintInit(Bool asFile); +void PrintVerbosity(Int16 level); +void PrintExit(void); + +void ProgErrorCancel(void); +void ProgErrorAction(void (*action)(void)); +void ProgError( char *, ...); /*fatal error. halt.*/ +void Bug( char *, ...); /*fatal bug. halt*/ +void Warning( char *str, ...); /*I'm not happy*/ +void Output(char *str, ...); /*command text output*/ +void Info(char *str, ...); /*useful indications*/ +void Phase(char *str, ...); /*phase of executions*/ +void Detail(char *str, ...); /*technical details*/ +void Legal(char *str, ...); /*legal output*/ + + + + + +/******************tools.c***********************/ + +/** FILE name , for lumps and BMP **/ +void ToLowerCase(char *file); +void MakeDir(char file[128], char *path,char *dir,char *sdir); +Bool MakeFileName(char file[128], char *path,char *dir,char *sdir,char *name,char *extens); +void GetNameOfWAD(char name[8],char *path); +Int16 Chsize(int handle,Int32 newsize); +Int32 GetFileTime(char *path); +void SetFileTime(char *path, Int32 time); +void Unlink(char *file); +void Memcpy(void huge *dest,const void huge *src, Int32 n); +void Memset(void huge *dest,char car, Int32 n); +void huge *Malloc( Int32 size); +void huge *Realloc( void huge *old, Int32 size); +void Free( void huge *); + + +void Normalise(char dest[8], char *src); + +void Progress(void); +void ProgressEnds(void); diff --git a/src/version.c b/src/version.c new file mode 100644 index 0000000..8517787 --- /dev/null +++ b/src/version.c @@ -0,0 +1 @@ +const char deutex_version[] = "4.0.1"; diff --git a/src/wadio.c b/src/wadio.c new file mode 100644 index 0000000..948e9f8 --- /dev/null +++ b/src/wadio.c @@ -0,0 +1,110 @@ +/* + * wadio.c + * Wad low level I/O routines, without error checking. + * AYM 1999-03-06 + */ + + +/* +This file is part of DeuTex. + +DeuTex incorporates code derived from DEU 5.21 that was put in the public +domain in 1994 by Rapha�l Quinet and Brendon Wyber. + +DeuTex is Copyright � 1994-1995 Olivier Montanuy, + Copyright � 1999 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#include "deutex.h" +#include +#include "endianio.h" +#include "wadio.h" + + +/* + * wad_read_i16 + * wad_read_i32 + * wad_write_i16 + * wad_write_i32 + * + * Read and write 16-bit and 32-bit signed integers, with + * the respect to the defined endianness. By default, all + * wad I/O is done in little-endian mode. + * + * Return 0 on success, non-zero on failure. + */ +int (* wad_write_i16) (FILE *, Int16) = fwrite_i16_le; +int (* wad_write_i32) (FILE *, Int32) = fwrite_i32_le; +int (* wad_read_i16) (FILE *, Int16 *) = fread_i16_le; +int (* wad_read_i32) (FILE *, Int32 *) = fread_i32_le; + + +/* + * set_input_wad_endianness + * set_output_wad_endianness + * + * Defined the endianness to use for wad input and output + * respectively. Normally, all wads are little-endian. + */ +void set_output_wad_endianness (int big_endian) +{ + wad_write_i16 = big_endian ? fwrite_i16_be : fwrite_i16_le; + wad_write_i32 = big_endian ? fwrite_i32_be : fwrite_i32_le; +} + +void set_input_wad_endianness (int big_endian) +{ + wad_read_i16 = big_endian ? fread_i16_be : fread_i16_le; + wad_read_i32 = big_endian ? fread_i32_be : fread_i32_le; +} + + +/* + * wad_read_name + * wad_write_name + * + * Read and write a directory name to a wad. The name is + * truncated to 8 characters, upper-cased, terminated and + * padded to 8 with NULs. + * + * Return 0 on success, non-zero on failure. + */ +int wad_read_name (FILE *fd, char name[8]) +{ + size_t n; + int end = 0; + for (n = 0; n < 8; n++) + { + int c = getc (fd); + name[n] = end ? '\0' : toupper (c); + if (c == '\0') + end = 1; + } + return feof (fd) || ferror (fd); +} + +int wad_write_name (FILE *fd, const char *name) +{ + size_t n; + for (n = 0; n < 8 && name[n]; n++) + putc (toupper (name[n]), fd); + for (; n < 8; n++) + putc ('\0', fd); + return ferror (fd); +} + + diff --git a/src/wadio.h b/src/wadio.h new file mode 100644 index 0000000..7d73c99 --- /dev/null +++ b/src/wadio.h @@ -0,0 +1,17 @@ +/* + * wadio.h + * Wad low level I/O routines + * AYM 1999-03-06 + */ + + +void set_output_wad_endianness (int big_endian); +void set_input_wad_endianness (int big_endian); +extern int (* wad_write_i16) (FILE *, Int16); +extern int (* wad_write_i32) (FILE *, Int32); +extern int (* wad_read_i16) (FILE *, Int16 *); +extern int (* wad_read_i32) (FILE *, Int32 *); +int wad_read_name (FILE *fd, char name[8]); +int wad_write_name (FILE *fd, const char *name); + +