Initial commit

This commit is contained in:
Benjamin Rosseaux 2025-01-18 10:58:18 +01:00
commit 405dcfd592
794 changed files with 887052 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.DS_Store
output/
*.wad
*.elf

674
LICENSE Normal file
View file

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. 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
them 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 prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. 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.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey 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;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If 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 convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU 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 that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
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.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
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.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 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, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program 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, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU 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 Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,2 +1,44 @@
# pasriscv_software
This repository contains third-party software, including test cases, guest Linux system build scripts, and other related assets, for the PasRISCV Emulator — a RV64GC RISC-V emulator developed in Object Pascal.
It is based on the work of https://github.com/bane9/rv64gc-emu-software where he has developed a RISC-V emulator in C++. I'm using his work to a starting point for test cases, guest Linux system build scripts, DOOM, and other software that can be used to test the PasRISCV Emulator.
## Getting Started
In order to build the stuff in this repository, you need to have the dependencies. The following dependencies are required:
```bash
sudo apt install -y git build-essential wget cpio unzip rsync bc libncurses5-dev screen bison file flex
```
## Building the Guest Linux System
The guest Linux system is built using the buildroot tool. The buildroot tool is a simple, efficient, and easy-to-use tool to generate embedded Linux systems through cross-compilation. The buildroot tool is used to generate the root filesystem for the guest Linux system.
To build the guest Linux system, you need to run the following commands:
```bash
cd linux
./build.sh
```
The build.sh script will download the buildroot tool, configure the buildroot tool, and build the guest Linux system.
## DOOM
DOOM is a first-person shooter video game developed by id Software. The DOOM game is ported to the RISC-V architecture and can be run on the PasRISCV Emulator under the guest Linux system. You do need a valid DOOM WAD file to build and to run the DOOM game. The DOOM WAD file is not included in this repository due to licensing restrictions.
To build DOOM, you need to run the following commands:
```bash
cd doom
make
```
The make command will build the DOOM game.
## RISC-V Test Cases
The RISC-V test cases are used to test the RISC-V emulator. The RISC-V test cases are taken from the RISC-V Compliance Test Suite. The RISC-V Compliance Test Suite is a comprehensive set of tests that verify the correctness of a RISC-V processor implementation. The RISC-V test cases are used to test the PasRISCV Emulator. This repository contains the RISC-V test cases for the RV64GC RISC-V architecture in precompiled form for fast ready-to-use testing. To build the RISC-V test cases yourself, go to the following repository: https://github.com/riscv/riscv-tests and follow the instructions there.

9
doom/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
build/
doomgeneric
doomgeneric.bin
rv64gc_emu
*.wad
.vscode/
doom_iwad.h
doom_iwad.c
bin_to_c

80
doom/Makefile Normal file
View file

@ -0,0 +1,80 @@
################################################################
#
# $Id:$
#
# $Log:$
#
ifeq ($(V),1)
VB=''
else
VB=@
endif
CCLINUX=riscv64-linux-gnu-gcc
CCBARE=riscv64-unknown-elf-gcc
OBJCOPY=riscv64-unknown-elf-objcopy
CFLAGS+= -O3 -mcmodel=medany -mabi=lp64d -march=rv64gc $(INCLUDES)
CFLAGS+= -Wall
LDFLAGS += -Wl,--no-warn-rwx-segments -flto
HOSTCC=gcc
HOSTCFLAGS = -O3
OBJDIR=build
BIN_TO_C=bin_to_c
SRC_BIN_TO_C=$(BIN_TO_C).c
OUTPUT=doomgeneric
SRC_DOOM = i_main.o dummy.o am_map.o doomdef.o doomstat.o dstrings.o d_event.o d_items.o d_iwad.o d_loop.o d_main.o d_mode.o d_net.o f_finale.o f_wipe.o g_game.o hu_lib.o hu_stuff.o info.o i_cdmus.o i_endoom.o i_joystick.o i_scale.o i_sound.o i_system.o i_timer.o memio.o m_argv.o m_bbox.o m_cheat.o m_config.o m_controls.o m_fixed.o m_menu.o m_misc.o m_random.o p_ceilng.o p_doors.o p_enemy.o p_floor.o p_inter.o p_lights.o p_map.o p_maputl.o p_mobj.o p_plats.o p_pspr.o p_saveg.o p_setup.o p_sight.o p_spec.o p_switch.o p_telept.o p_tick.o p_user.o r_bsp.o r_data.o r_draw.o r_main.o r_plane.o r_segs.o r_sky.o r_things.o sha1.o sounds.o statdump.o st_lib.o st_stuff.o s_sound.o tables.o v_video.o wi_stuff.o w_checksum.o w_file.o w_main.o w_wad.o z_zone.o w_file_stdc.o i_input.o i_video.o doomgeneric.o doomgeneric_pasriscv.o mus2mid.o doom_iwad.o
CC=$(CCLINUX)
CFLAGS += -DLINUX_TARGET=1 -DBAREMETAL_TARGET=0 -lm -lc -lgcc -lc -static
OBJS += $(addprefix $(OBJDIR)/, $(SRC_DOOM))
all: $(OUTPUT)
clean:
-rm -rf $(OBJDIR)
-rm $(OUTPUT)
-rm $(OUTPUT).elf
-rm doom_iwad.h
-rm doom_iwad.c
-rm $(BIN_TO_C)
$(OUTPUT): $(OBJS)
@echo [Linking $@]
$(CCLINUX) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(OUTPUT).elf; \
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: %.c
@echo [Compiling $<]
$(VB)$(CC) $(CFLAGS) -c $< -o $@
print:
@echo OBJS: $(OBJS)
run:
./$(EMULATOR) --bios $(OUTPUT).bin --font $(FONT)
IWAD := $(shell find . -iname '*.wad' | head -n 1 | tr '[:upper:]' '[:lower:]')
$(BIN_TO_C): $(BIN_TO_C).c
@echo [Building $@]
$(HOSTCC) $(HOSTCFLAGS) $(BIN_TO_C).c -o $(BIN_TO_C)
convert_iwad:
./$(BIN_TO_C) $(IWAD) doom_iwad
iwad: $(BIN_TO_C) convert_iwad
makerun: all run
.PHONY: iwad
.PHONY: makerun

1355
doom/am_map.c Normal file

File diff suppressed because it is too large Load diff

49
doom/am_map.h Normal file
View file

@ -0,0 +1,49 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// AutoMap module.
//
#ifndef __AMMAP_H__
#define __AMMAP_H__
#include "d_event.h"
#include "m_cheat.h"
// Used by ST StatusBar stuff.
#define AM_MSGHEADER (('a'<<24)+('m'<<16))
#define AM_MSGENTERED (AM_MSGHEADER | ('e'<<8))
#define AM_MSGEXITED (AM_MSGHEADER | ('x'<<8))
// Called by main loop.
boolean AM_Responder (event_t* ev);
// Called by main loop.
void AM_Ticker (void);
// Called by main loop,
// called instead of view drawer if automap active.
void AM_Drawer (void);
// Called to force the automap to quit
// if the level is completed while it is up.
void AM_Stop (void);
extern cheatseq_t cheat_amap;
#endif

92
doom/baremetal.ld Normal file
View file

@ -0,0 +1,92 @@
OUTPUT_ARCH("riscv")
ENTRY(_start)
_sstack = ORIGIN(RAM) + LENGTH(RAM);
_estack = _sstack - 0xC00000; /*12MiB*/
MEMORY
{
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 256M
}
SECTIONS
{
.text :
{
. = ALIGN(8);
*(.text.init*)
*(.text)
*(.text*)
. = ALIGN(8);
_etext = .;
} >RAM
.rodata : {
*(.rdata)
*(.rodata .rodata.*)
*(.gnu.linkonce.r.*)
. = ALIGN(8);
*(.srodata.cst16)
*(.srodata.cst8)
*(.srodata.cst4)
*(.srodata.cst2)
*(.srodata .srodata.*)
*(.eh_frame)
*(._user_heap_stack)
*(.riscv.attributes)
*(.comment)
} >RAM
.preinit_array :
{
. = ALIGN(8);
PROVIDE_HIDDEN(__preinit_array_start = .);
KEEP(*(.preinit_array*))
PROVIDE_HIDDEN(__preinit_array_end = .);
. = ALIGN(8);
} >RAM
.init_array :
{
. = ALIGN(8);
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array*))
PROVIDE_HIDDEN(__init_array_end = .);
. = ALIGN(8);
} >RAM
.fini_array :
{
. = ALIGN(8);
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array*))
PROVIDE_HIDDEN(__fini_array_end = .);
. = ALIGN(8);
} >RAM
.bss :
{
_sbss = .;
*(.bss)
*(.bss*)
. = ALIGN(8);
_ebss = .;
} >RAM
_sidata = LOADADDR(.data);
.data :
{
. = ALIGN(8);
_sdata = .;
*(.data)
*(.data*)
. = ALIGN(8);
_edata = .;
PROVIDE(__global_pointer$ = . + 0x800);
*(.sdata .sdata.* .sdata2.*)
PROVIDE(_end = .);
} >RAM
}

57
doom/bin_to_c.c Normal file
View file

@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *infile = argv[1];
char *outfile = argv[2];
FILE *fp = fopen(infile, "rb");
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
uint8_t *data = (uint8_t *)malloc(size);
fread(data, 1, size, fp);
fclose(fp);
char *header_filename = (char *)malloc(strlen(outfile) + 3);
sprintf(header_filename, "%s.h", outfile);
char *source_filename = (char *)malloc(strlen(outfile) + 3);
sprintf(source_filename, "%s.c", outfile);
FILE *header_file = fopen(header_filename, "w");
FILE *source_file = fopen(source_filename, "w");
fprintf(header_file, "#ifndef %s_H_\n", outfile);
fprintf(header_file, "#define %s_H_\n", outfile);
fprintf(header_file, "\n#include <stdint.h>\n");
fprintf(header_file, "\n#define DOOM_SIZE %zu\n", size);
fprintf(header_file, "#define DOOM_FILENAME \"%s\"\n", infile);
fprintf(header_file, "\nextern const uint8_t* doom;\n");
fprintf(header_file, "\n#endif\n");
fclose(header_file);
fprintf(source_file, "#include \"%s\"\n\n", header_filename);
fprintf(source_file, "static const uint8_t doom_data[] = {\n");
for (int i = 0; i < size; i++)
{
fprintf(source_file, "0x%02X,", data[i]);
if ((i + 1) % 16 == 0)
{
fprintf(source_file, "\n");
}
}
fprintf(source_file, "};\n\nconst uint8_t* doom = doom_data;\n");
fclose(source_file);
free(data);
free(header_filename);
free(source_filename);
return 0;
}

100
doom/config.h Normal file
View file

@ -0,0 +1,100 @@
/* config.hin. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dev/isa/spkrio.h> header file. */
#undef HAVE_DEV_ISA_SPKRIO_H
/* Define to 1 if you have the <dev/speaker/speaker.h> header file. */
#undef HAVE_DEV_SPEAKER_SPEAKER_H
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `ioperm' function. */
#undef HAVE_IOPERM
/* Define to 1 if you have the `amd64' library (-lamd64). */
#undef HAVE_LIBAMD64
/* Define to 1 if you have the `i386' library (-li386). */
#undef HAVE_LIBI386
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the `png' library (-lpng). */
#undef HAVE_LIBPNG
/* Define to 1 if you have the `samplerate' library (-lsamplerate). */
#undef HAVE_LIBSAMPLERATE
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
/* Define to 1 if you have the <linux/kd.h> header file. */
#undef HAVE_LINUX_KD_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `mmap' function. */
#undef HAVE_MMAP
/* Define to 1 if you have the `sched_setaffinity' function. */
#undef HAVE_SCHED_SETAFFINITY
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#define PACKAGE "Doom"
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#define PACKAGE_NAME "Doom Generic"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Doom Generic 0.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "doomgeneric.tar"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION 0.1
/* Change this when you create your awesome forked version */
#define PROGRAM_PREFIX "doomgeneric"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION 0.1
/* Define to 1 if you want to compile the unmodified code */
#undef ORIGCODE
/* Define to the directory where all game files are located */
#define FILES_DIR "."

693
doom/d_englsh.h Normal file
View file

@ -0,0 +1,693 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Printed strings for translation.
// English language support (default).
//
#ifndef __D_ENGLSH__
#define __D_ENGLSH__
//
// Printed strings for translation
//
//
// D_Main.C
//
#define D_DEVSTR "Development mode ON.\n"
#define D_CDROM "CD-ROM Version: default.cfg from c:\\doomdata\n"
//
// M_Menu.C
//
#define PRESSKEY "press a key."
#define PRESSYN "press y or n."
#define QUITMSG "are you sure you want to\nquit this great game?"
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
#define QLPROMPT "do you want to quickload the game named\n\n'%s'?\n\n"PRESSYN
#define NEWGAME \
"you can't start a new game\n"\
"while in a network game.\n\n"PRESSKEY
#define NIGHTMARE \
"are you sure? this skill level\n"\
"isn't even remotely fair.\n\n"PRESSYN
#define SWSTRING \
"this is the shareware version of doom.\n\n"\
"you need to order the entire trilogy.\n\n"PRESSKEY
#define MSGOFF "Messages OFF"
#define MSGON "Messages ON"
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
#define DOSY "(press y to quit to dos.)"
#define DETAILHI "High detail"
#define DETAILLO "Low detail"
#define GAMMALVL0 "Gamma correction OFF"
#define GAMMALVL1 "Gamma correction level 1"
#define GAMMALVL2 "Gamma correction level 2"
#define GAMMALVL3 "Gamma correction level 3"
#define GAMMALVL4 "Gamma correction level 4"
#define EMPTYSTRING "empty slot"
//
// P_inter.C
//
#define GOTARMOR "Picked up the armor."
#define GOTMEGA "Picked up the MegaArmor!"
#define GOTHTHBONUS "Picked up a health bonus."
#define GOTARMBONUS "Picked up an armor bonus."
#define GOTSTIM "Picked up a stimpack."
#define GOTMEDINEED "Picked up a medikit that you REALLY need!"
#define GOTMEDIKIT "Picked up a medikit."
#define GOTSUPER "Supercharge!"
#define GOTBLUECARD "Picked up a blue keycard."
#define GOTYELWCARD "Picked up a yellow keycard."
#define GOTREDCARD "Picked up a red keycard."
#define GOTBLUESKUL "Picked up a blue skull key."
#define GOTYELWSKUL "Picked up a yellow skull key."
#define GOTREDSKULL "Picked up a red skull key."
#define GOTINVUL "Invulnerability!"
#define GOTBERSERK "Berserk!"
#define GOTINVIS "Partial Invisibility"
#define GOTSUIT "Radiation Shielding Suit"
#define GOTMAP "Computer Area Map"
#define GOTVISOR "Light Amplification Visor"
#define GOTMSPHERE "MegaSphere!"
#define GOTCLIP "Picked up a clip."
#define GOTCLIPBOX "Picked up a box of bullets."
#define GOTROCKET "Picked up a rocket."
#define GOTROCKBOX "Picked up a box of rockets."
#define GOTCELL "Picked up an energy cell."
#define GOTCELLBOX "Picked up an energy cell pack."
#define GOTSHELLS "Picked up 4 shotgun shells."
#define GOTSHELLBOX "Picked up a box of shotgun shells."
#define GOTBACKPACK "Picked up a backpack full of ammo!"
#define GOTBFG9000 "You got the BFG9000! Oh, yes."
#define GOTCHAINGUN "You got the chaingun!"
#define GOTCHAINSAW "A chainsaw! Find some meat!"
#define GOTLAUNCHER "You got the rocket launcher!"
#define GOTPLASMA "You got the plasma gun!"
#define GOTSHOTGUN "You got the shotgun!"
#define GOTSHOTGUN2 "You got the super shotgun!"
//
// P_Doors.C
//
#define PD_BLUEO "You need a blue key to activate this object"
#define PD_REDO "You need a red key to activate this object"
#define PD_YELLOWO "You need a yellow key to activate this object"
#define PD_BLUEK "You need a blue key to open this door"
#define PD_REDK "You need a red key to open this door"
#define PD_YELLOWK "You need a yellow key to open this door"
//
// G_game.C
//
#define GGSAVED "game saved."
//
// HU_stuff.C
//
#define HUSTR_MSGU "[Message unsent]"
#define HUSTR_E1M1 "E1M1: Hangar"
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
#define HUSTR_E1M4 "E1M4: Command Control"
#define HUSTR_E1M5 "E1M5: Phobos Lab"
#define HUSTR_E1M6 "E1M6: Central Processing"
#define HUSTR_E1M7 "E1M7: Computer Station"
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
#define HUSTR_E1M9 "E1M9: Military Base"
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
#define HUSTR_E2M2 "E2M2: Containment Area"
#define HUSTR_E2M3 "E2M3: Refinery"
#define HUSTR_E2M4 "E2M4: Deimos Lab"
#define HUSTR_E2M5 "E2M5: Command Center"
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
#define HUSTR_E2M7 "E2M7: Spawning Vats"
#define HUSTR_E2M8 "E2M8: Tower of Babel"
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
#define HUSTR_E3M1 "E3M1: Hell Keep"
#define HUSTR_E3M2 "E3M2: Slough of Despair"
#define HUSTR_E3M3 "E3M3: Pandemonium"
#define HUSTR_E3M4 "E3M4: House of Pain"
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
#define HUSTR_E3M7 "E3M7: Limbo"
#define HUSTR_E3M8 "E3M8: Dis"
#define HUSTR_E3M9 "E3M9: Warrens"
#define HUSTR_E4M1 "E4M1: Hell Beneath"
#define HUSTR_E4M2 "E4M2: Perfect Hatred"
#define HUSTR_E4M3 "E4M3: Sever The Wicked"
#define HUSTR_E4M4 "E4M4: Unruly Evil"
#define HUSTR_E4M5 "E4M5: They Will Repent"
#define HUSTR_E4M6 "E4M6: Against Thee Wickedly"
#define HUSTR_E4M7 "E4M7: And Hell Followed"
#define HUSTR_E4M8 "E4M8: Unto The Cruel"
#define HUSTR_E4M9 "E4M9: Fear"
#define HUSTR_1 "level 1: entryway"
#define HUSTR_2 "level 2: underhalls"
#define HUSTR_3 "level 3: the gantlet"
#define HUSTR_4 "level 4: the focus"
#define HUSTR_5 "level 5: the waste tunnels"
#define HUSTR_6 "level 6: the crusher"
#define HUSTR_7 "level 7: dead simple"
#define HUSTR_8 "level 8: tricks and traps"
#define HUSTR_9 "level 9: the pit"
#define HUSTR_10 "level 10: refueling base"
#define HUSTR_11 "level 11: 'o' of destruction!"
#define HUSTR_12 "level 12: the factory"
#define HUSTR_13 "level 13: downtown"
#define HUSTR_14 "level 14: the inmost dens"
#define HUSTR_15 "level 15: industrial zone"
#define HUSTR_16 "level 16: suburbs"
#define HUSTR_17 "level 17: tenements"
#define HUSTR_18 "level 18: the courtyard"
#define HUSTR_19 "level 19: the citadel"
#define HUSTR_20 "level 20: gotcha!"
#define HUSTR_21 "level 21: nirvana"
#define HUSTR_22 "level 22: the catacombs"
#define HUSTR_23 "level 23: barrels o' fun"
#define HUSTR_24 "level 24: the chasm"
#define HUSTR_25 "level 25: bloodfalls"
#define HUSTR_26 "level 26: the abandoned mines"
#define HUSTR_27 "level 27: monster condo"
#define HUSTR_28 "level 28: the spirit world"
#define HUSTR_29 "level 29: the living end"
#define HUSTR_30 "level 30: icon of sin"
#define HUSTR_31 "level 31: wolfenstein"
#define HUSTR_32 "level 32: grosse"
#define PHUSTR_1 "level 1: congo"
#define PHUSTR_2 "level 2: well of souls"
#define PHUSTR_3 "level 3: aztec"
#define PHUSTR_4 "level 4: caged"
#define PHUSTR_5 "level 5: ghost town"
#define PHUSTR_6 "level 6: baron's lair"
#define PHUSTR_7 "level 7: caughtyard"
#define PHUSTR_8 "level 8: realm"
#define PHUSTR_9 "level 9: abattoire"
#define PHUSTR_10 "level 10: onslaught"
#define PHUSTR_11 "level 11: hunted"
#define PHUSTR_12 "level 12: speed"
#define PHUSTR_13 "level 13: the crypt"
#define PHUSTR_14 "level 14: genesis"
#define PHUSTR_15 "level 15: the twilight"
#define PHUSTR_16 "level 16: the omen"
#define PHUSTR_17 "level 17: compound"
#define PHUSTR_18 "level 18: neurosphere"
#define PHUSTR_19 "level 19: nme"
#define PHUSTR_20 "level 20: the death domain"
#define PHUSTR_21 "level 21: slayer"
#define PHUSTR_22 "level 22: impossible mission"
#define PHUSTR_23 "level 23: tombstone"
#define PHUSTR_24 "level 24: the final frontier"
#define PHUSTR_25 "level 25: the temple of darkness"
#define PHUSTR_26 "level 26: bunker"
#define PHUSTR_27 "level 27: anti-christ"
#define PHUSTR_28 "level 28: the sewers"
#define PHUSTR_29 "level 29: odyssey of noises"
#define PHUSTR_30 "level 30: the gateway of hell"
#define PHUSTR_31 "level 31: cyberden"
#define PHUSTR_32 "level 32: go 2 it"
#define THUSTR_1 "level 1: system control"
#define THUSTR_2 "level 2: human bbq"
#define THUSTR_3 "level 3: power control"
#define THUSTR_4 "level 4: wormhole"
#define THUSTR_5 "level 5: hanger"
#define THUSTR_6 "level 6: open season"
#define THUSTR_7 "level 7: prison"
#define THUSTR_8 "level 8: metal"
#define THUSTR_9 "level 9: stronghold"
#define THUSTR_10 "level 10: redemption"
#define THUSTR_11 "level 11: storage facility"
#define THUSTR_12 "level 12: crater"
#define THUSTR_13 "level 13: nukage processing"
#define THUSTR_14 "level 14: steel works"
#define THUSTR_15 "level 15: dead zone"
#define THUSTR_16 "level 16: deepest reaches"
#define THUSTR_17 "level 17: processing area"
#define THUSTR_18 "level 18: mill"
#define THUSTR_19 "level 19: shipping/respawning"
#define THUSTR_20 "level 20: central processing"
#define THUSTR_21 "level 21: administration center"
#define THUSTR_22 "level 22: habitat"
#define THUSTR_23 "level 23: lunar mining project"
#define THUSTR_24 "level 24: quarry"
#define THUSTR_25 "level 25: baron's den"
#define THUSTR_26 "level 26: ballistyx"
#define THUSTR_27 "level 27: mount pain"
#define THUSTR_28 "level 28: heck"
#define THUSTR_29 "level 29: river styx"
#define THUSTR_30 "level 30: last call"
#define THUSTR_31 "level 31: pharaoh"
#define THUSTR_32 "level 32: caribbean"
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
#define HUSTR_CHATMACRO2 "I'm OK."
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
#define HUSTR_CHATMACRO4 "Help!"
#define HUSTR_CHATMACRO5 "You suck!"
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
#define HUSTR_CHATMACRO7 "Come here!"
#define HUSTR_CHATMACRO8 "I'll take care of it."
#define HUSTR_CHATMACRO9 "Yes"
#define HUSTR_CHATMACRO0 "No"
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
#define HUSTR_TALKTOSELF2 "Who's there?"
#define HUSTR_TALKTOSELF3 "You scare yourself"
#define HUSTR_TALKTOSELF4 "You start to rave"
#define HUSTR_TALKTOSELF5 "You've lost it..."
#define HUSTR_MESSAGESENT "[Message Sent]"
// The following should NOT be changed unless it seems
// just AWFULLY necessary
#define HUSTR_PLRGREEN "Green: "
#define HUSTR_PLRINDIGO "Indigo: "
#define HUSTR_PLRBROWN "Brown: "
#define HUSTR_PLRRED "Red: "
#define HUSTR_KEYGREEN 'g'
#define HUSTR_KEYINDIGO 'i'
#define HUSTR_KEYBROWN 'b'
#define HUSTR_KEYRED 'r'
//
// AM_map.C
//
#define AMSTR_FOLLOWON "Follow Mode ON"
#define AMSTR_FOLLOWOFF "Follow Mode OFF"
#define AMSTR_GRIDON "Grid ON"
#define AMSTR_GRIDOFF "Grid OFF"
#define AMSTR_MARKEDSPOT "Marked Spot"
#define AMSTR_MARKSCLEARED "All Marks Cleared"
//
// ST_stuff.C
//
#define STSTR_MUS "Music Change"
#define STSTR_NOMUS "IMPOSSIBLE SELECTION"
#define STSTR_DQDON "Degreelessness Mode On"
#define STSTR_DQDOFF "Degreelessness Mode Off"
#define STSTR_KFAADDED "Very Happy Ammo Added"
#define STSTR_FAADDED "Ammo (no keys) Added"
#define STSTR_NCON "No Clipping Mode ON"
#define STSTR_NCOFF "No Clipping Mode OFF"
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
#define STSTR_BEHOLDX "Power-up Toggled"
#define STSTR_CHOPPERS "... doesn't suck - GM"
#define STSTR_CLEV "Changing Level..."
//
// F_Finale.C
//
#define E1TEXT \
"Once you beat the big badasses and\n"\
"clean out the moon base you're supposed\n"\
"to win, aren't you? Aren't you? Where's\n"\
"your fat reward and ticket home? What\n"\
"the hell is this? It's not supposed to\n"\
"end this way!\n"\
"\n" \
"It stinks like rotten meat, but looks\n"\
"like the lost Deimos base. Looks like\n"\
"you're stuck on The Shores of Hell.\n"\
"The only way out is through.\n"\
"\n"\
"To continue the DOOM experience, play\n"\
"The Shores of Hell and its amazing\n"\
"sequel, Inferno!\n"
#define E2TEXT \
"You've done it! The hideous cyber-\n"\
"demon lord that ruled the lost Deimos\n"\
"moon base has been slain and you\n"\
"are triumphant! But ... where are\n"\
"you? You clamber to the edge of the\n"\
"moon and look down to see the awful\n"\
"truth.\n" \
"\n"\
"Deimos floats above Hell itself!\n"\
"You've never heard of anyone escaping\n"\
"from Hell, but you'll make the bastards\n"\
"sorry they ever heard of you! Quickly,\n"\
"you rappel down to the surface of\n"\
"Hell.\n"\
"\n" \
"Now, it's on to the final chapter of\n"\
"DOOM! -- Inferno."
#define E3TEXT \
"The loathsome spiderdemon that\n"\
"masterminded the invasion of the moon\n"\
"bases and caused so much death has had\n"\
"its ass kicked for all time.\n"\
"\n"\
"A hidden doorway opens and you enter.\n"\
"You've proven too tough for Hell to\n"\
"contain, and now Hell at last plays\n"\
"fair -- for you emerge from the door\n"\
"to see the green fields of Earth!\n"\
"Home at last.\n" \
"\n"\
"You wonder what's been happening on\n"\
"Earth while you were battling evil\n"\
"unleashed. It's good that no Hell-\n"\
"spawn could have come through that\n"\
"door with you ..."
#define E4TEXT \
"the spider mastermind must have sent forth\n"\
"its legions of hellspawn before your\n"\
"final confrontation with that terrible\n"\
"beast from hell. but you stepped forward\n"\
"and brought forth eternal damnation and\n"\
"suffering upon the horde as a true hero\n"\
"would in the face of something so evil.\n"\
"\n"\
"besides, someone was gonna pay for what\n"\
"happened to daisy, your pet rabbit.\n"\
"\n"\
"but now, you see spread before you more\n"\
"potential pain and gibbitude as a nation\n"\
"of demons run amok among our cities.\n"\
"\n"\
"next stop, hell on earth!"
// after level 6, put this:
#define C1TEXT \
"YOU HAVE ENTERED DEEPLY INTO THE INFESTED\n" \
"STARPORT. BUT SOMETHING IS WRONG. THE\n" \
"MONSTERS HAVE BROUGHT THEIR OWN REALITY\n" \
"WITH THEM, AND THE STARPORT'S TECHNOLOGY\n" \
"IS BEING SUBVERTED BY THEIR PRESENCE.\n" \
"\n"\
"AHEAD, YOU SEE AN OUTPOST OF HELL, A\n" \
"FORTIFIED ZONE. IF YOU CAN GET PAST IT,\n" \
"YOU CAN PENETRATE INTO THE HAUNTED HEART\n" \
"OF THE STARBASE AND FIND THE CONTROLLING\n" \
"SWITCH WHICH HOLDS EARTH'S POPULATION\n" \
"HOSTAGE."
// After level 11, put this:
#define C2TEXT \
"YOU HAVE WON! YOUR VICTORY HAS ENABLED\n" \
"HUMANKIND TO EVACUATE EARTH AND ESCAPE\n"\
"THE NIGHTMARE. NOW YOU ARE THE ONLY\n"\
"HUMAN LEFT ON THE FACE OF THE PLANET.\n"\
"CANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\n"\
"AND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\n"\
"YOU SIT BACK AND WAIT FOR DEATH, CONTENT\n"\
"THAT YOU HAVE SAVED YOUR SPECIES.\n"\
"\n"\
"BUT THEN, EARTH CONTROL BEAMS DOWN A\n"\
"MESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\n"\
"THE SOURCE OF THE ALIEN INVASION. IF YOU\n"\
"GO THERE, YOU MAY BE ABLE TO BLOCK THEIR\n"\
"ENTRY. THE ALIEN BASE IS IN THE HEART OF\n"\
"YOUR OWN HOME CITY, NOT FAR FROM THE\n"\
"STARPORT.\" SLOWLY AND PAINFULLY YOU GET\n"\
"UP AND RETURN TO THE FRAY."
// After level 20, put this:
#define C3TEXT \
"YOU ARE AT THE CORRUPT HEART OF THE CITY,\n"\
"SURROUNDED BY THE CORPSES OF YOUR ENEMIES.\n"\
"YOU SEE NO WAY TO DESTROY THE CREATURES'\n"\
"ENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\n"\
"TEETH AND PLUNGE THROUGH IT.\n"\
"\n"\
"THERE MUST BE A WAY TO CLOSE IT ON THE\n"\
"OTHER SIDE. WHAT DO YOU CARE IF YOU'VE\n"\
"GOT TO GO THROUGH HELL TO GET TO IT?"
// After level 29, put this:
#define C4TEXT \
"THE HORRENDOUS VISAGE OF THE BIGGEST\n"\
"DEMON YOU'VE EVER SEEN CRUMBLES BEFORE\n"\
"YOU, AFTER YOU PUMP YOUR ROCKETS INTO\n"\
"HIS EXPOSED BRAIN. THE MONSTER SHRIVELS\n"\
"UP AND DIES, ITS THRASHING LIMBS\n"\
"DEVASTATING UNTOLD MILES OF HELL'S\n"\
"SURFACE.\n"\
"\n"\
"YOU'VE DONE IT. THE INVASION IS OVER.\n"\
"EARTH IS SAVED. HELL IS A WRECK. YOU\n"\
"WONDER WHERE BAD FOLKS WILL GO WHEN THEY\n"\
"DIE, NOW. WIPING THE SWEAT FROM YOUR\n"\
"FOREHEAD YOU BEGIN THE LONG TREK BACK\n"\
"HOME. REBUILDING EARTH OUGHT TO BE A\n"\
"LOT MORE FUN THAN RUINING IT WAS.\n"
// Before level 31, put this:
#define C5TEXT \
"CONGRATULATIONS, YOU'VE FOUND THE SECRET\n"\
"LEVEL! LOOKS LIKE IT'S BEEN BUILT BY\n"\
"HUMANS, RATHER THAN DEMONS. YOU WONDER\n"\
"WHO THE INMATES OF THIS CORNER OF HELL\n"\
"WILL BE."
// Before level 32, put this:
#define C6TEXT \
"CONGRATULATIONS, YOU'VE FOUND THE\n"\
"SUPER SECRET LEVEL! YOU'D BETTER\n"\
"BLAZE THROUGH THIS ONE!\n"
// after map 06
#define P1TEXT \
"You gloat over the steaming carcass of the\n"\
"Guardian. With its death, you've wrested\n"\
"the Accelerator from the stinking claws\n"\
"of Hell. You relax and glance around the\n"\
"room. Damn! There was supposed to be at\n"\
"least one working prototype, but you can't\n"\
"see it. The demons must have taken it.\n"\
"\n"\
"You must find the prototype, or all your\n"\
"struggles will have been wasted. Keep\n"\
"moving, keep fighting, keep killing.\n"\
"Oh yes, keep living, too."
// after map 11
#define P2TEXT \
"Even the deadly Arch-Vile labyrinth could\n"\
"not stop you, and you've gotten to the\n"\
"prototype Accelerator which is soon\n"\
"efficiently and permanently deactivated.\n"\
"\n"\
"You're good at that kind of thing."
// after map 20
#define P3TEXT \
"You've bashed and battered your way into\n"\
"the heart of the devil-hive. Time for a\n"\
"Search-and-Destroy mission, aimed at the\n"\
"Gatekeeper, whose foul offspring is\n"\
"cascading to Earth. Yeah, he's bad. But\n"\
"you know who's worse!\n"\
"\n"\
"Grinning evilly, you check your gear, and\n"\
"get ready to give the bastard a little Hell\n"\
"of your own making!"
// after map 30
#define P4TEXT \
"The Gatekeeper's evil face is splattered\n"\
"all over the place. As its tattered corpse\n"\
"collapses, an inverted Gate forms and\n"\
"sucks down the shards of the last\n"\
"prototype Accelerator, not to mention the\n"\
"few remaining demons. You're done. Hell\n"\
"has gone back to pounding bad dead folks \n"\
"instead of good live ones. Remember to\n"\
"tell your grandkids to put a rocket\n"\
"launcher in your coffin. If you go to Hell\n"\
"when you die, you'll need it for some\n"\
"final cleaning-up ..."
// before map 31
#define P5TEXT \
"You've found the second-hardest level we\n"\
"got. Hope you have a saved game a level or\n"\
"two previous. If not, be prepared to die\n"\
"aplenty. For master marines only."
// before map 32
#define P6TEXT \
"Betcha wondered just what WAS the hardest\n"\
"level we had ready for ya? Now you know.\n"\
"No one gets out alive."
#define T1TEXT \
"You've fought your way out of the infested\n"\
"experimental labs. It seems that UAC has\n"\
"once again gulped it down. With their\n"\
"high turnover, it must be hard for poor\n"\
"old UAC to buy corporate health insurance\n"\
"nowadays..\n"\
"\n"\
"Ahead lies the military complex, now\n"\
"swarming with diseased horrors hot to get\n"\
"their teeth into you. With luck, the\n"\
"complex still has some warlike ordnance\n"\
"laying around."
#define T2TEXT \
"You hear the grinding of heavy machinery\n"\
"ahead. You sure hope they're not stamping\n"\
"out new hellspawn, but you're ready to\n"\
"ream out a whole herd if you have to.\n"\
"They might be planning a blood feast, but\n"\
"you feel about as mean as two thousand\n"\
"maniacs packed into one mad killer.\n"\
"\n"\
"You don't plan to go down easy."
#define T3TEXT \
"The vista opening ahead looks real damn\n"\
"familiar. Smells familiar, too -- like\n"\
"fried excrement. You didn't like this\n"\
"place before, and you sure as hell ain't\n"\
"planning to like it now. The more you\n"\
"brood on it, the madder you get.\n"\
"Hefting your gun, an evil grin trickles\n"\
"onto your face. Time to take some names."
#define T4TEXT \
"Suddenly, all is silent, from one horizon\n"\
"to the other. The agonizing echo of Hell\n"\
"fades away, the nightmare sky turns to\n"\
"blue, the heaps of monster corpses start \n"\
"to evaporate along with the evil stench \n"\
"that filled the air. Jeeze, maybe you've\n"\
"done it. Have you really won?\n"\
"\n"\
"Something rumbles in the distance.\n"\
"A blue light begins to glow inside the\n"\
"ruined skull of the demon-spitter."
#define T5TEXT \
"What now? Looks totally different. Kind\n"\
"of like King Tut's condo. Well,\n"\
"whatever's here can't be any worse\n"\
"than usual. Can it? Or maybe it's best\n"\
"to let sleeping gods lie.."
#define T6TEXT \
"Time for a vacation. You've burst the\n"\
"bowels of hell and by golly you're ready\n"\
"for a break. You mutter to yourself,\n"\
"Maybe someone else can kick Hell's ass\n"\
"next time around. Ahead lies a quiet town,\n"\
"with peaceful flowing water, quaint\n"\
"buildings, and presumably no Hellspawn.\n"\
"\n"\
"As you step off the transport, you hear\n"\
"the stomp of a cyberdemon's iron shoe."
//
// Character cast strings F_FINALE.C
//
#define CC_ZOMBIE "ZOMBIEMAN"
#define CC_SHOTGUN "SHOTGUN GUY"
#define CC_HEAVY "HEAVY WEAPON DUDE"
#define CC_IMP "IMP"
#define CC_DEMON "DEMON"
#define CC_LOST "LOST SOUL"
#define CC_CACO "CACODEMON"
#define CC_HELL "HELL KNIGHT"
#define CC_BARON "BARON OF HELL"
#define CC_ARACH "ARACHNOTRON"
#define CC_PAIN "PAIN ELEMENTAL"
#define CC_REVEN "REVENANT"
#define CC_MANCU "MANCUBUS"
#define CC_ARCH "ARCH-VILE"
#define CC_SPIDER "THE SPIDER MASTERMIND"
#define CC_CYBER "THE CYBERDEMON"
#define CC_HERO "OUR HERO"
#endif

63
doom/d_event.c Normal file
View file

@ -0,0 +1,63 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// DESCRIPTION: Event handling.
//
// Events are asynchronous inputs generally generated by the game user.
// Events can be discarded if no responder claims them
//
#include <stdlib.h>
#include "d_event.h"
#define MAXEVENTS 64
static event_t events[MAXEVENTS];
static int eventhead;
static int eventtail;
//
// D_PostEvent
// Called by the I/O functions when input is detected
//
void D_PostEvent (event_t* ev)
{
events[eventhead] = *ev;
eventhead = (eventhead + 1) % MAXEVENTS;
}
// Read an event from the queue.
event_t *D_PopEvent(void)
{
event_t *result;
// No more events waiting.
if (eventtail == eventhead)
{
return NULL;
}
result = &events[eventtail];
// Advance to the next event in the queue.
eventtail = (eventtail + 1) % MAXEVENTS;
return result;
}

137
doom/d_event.h Normal file
View file

@ -0,0 +1,137 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
//
//
#ifndef __D_EVENT__
#define __D_EVENT__
#include "doomtype.h"
//
// Event handling.
//
// Input event types.
typedef enum
{
ev_keydown,
ev_keyup,
ev_mouse,
ev_joystick,
ev_quit
} evtype_t;
// Event structure.
typedef struct
{
evtype_t type;
// Event-related data that depends on the type of event:
//
// ev_keydown/ev_keyup:
// data1: Key code (from doomkeys.h) of the key that was
// pressed or released.
// data2: Ascii text of the character that was pressed,
// shifted appropriately (eg. '$' if 4 was pressed
// while shift was held).
//
// ev_mouse:
// data1: Bitfield of buttons currently held down.
// (bit 0 = left; bit 1 = right; bit 2 = middle).
// data2: X axis mouse movement (turn).
// data3: Y axis mouse movement (forward/backward).
//
// ev_joystick:
// data1: Bitfield of buttons currently pressed.
// data2: X axis mouse movement (turn).
// data3: Y axis mouse movement (forward/backward).
// data4: Third axis mouse movement (strafe).
int data1, data2, data3, data4;
} event_t;
//
// Button/action code definitions.
//
typedef enum
{
// Press "Fire".
BT_ATTACK = 1,
// Use button, to open doors, activate switches.
BT_USE = 2,
// Flag: game events, not really buttons.
BT_SPECIAL = 128,
BT_SPECIALMASK = 3,
// Flag, weapon change pending.
// If true, the next 3 bits hold weapon num.
BT_CHANGE = 4,
// The 3bit weapon mask and shift, convenience.
BT_WEAPONMASK = (8+16+32),
BT_WEAPONSHIFT = 3,
// Pause the game.
BTS_PAUSE = 1,
// Save the game at each console.
BTS_SAVEGAME = 2,
// Savegame slot numbers
// occupy the second byte of buttons.
BTS_SAVEMASK = (4+8+16),
BTS_SAVESHIFT = 2,
} buttoncode_t;
// villsa [STRIFE] Strife specific buttons
// TODO - not finished
typedef enum
{
// Player view look up
BT2_LOOKUP = 1,
// Player view look down
BT2_LOOKDOWN = 2,
// Center player's view
BT2_CENTERVIEW = 4,
// Use inventory item
BT2_INVUSE = 8,
// Drop inventory item
BT2_INVDROP = 16,
// Jump up and down
BT2_JUMP = 32,
// Use medkit
BT2_HEALTH = 128,
} buttoncode2_t;
// Called by IO functions when input is detected.
void D_PostEvent (event_t *ev);
// Read an event from the event queue
event_t *D_PopEvent(void);
#endif

128
doom/d_items.c Normal file
View file

@ -0,0 +1,128 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
//
// We are referring to sprite numbers.
#include "info.h"
#include "d_items.h"
//
// PSPRITE ACTIONS for waepons.
// This struct controls the weapon animations.
//
// Each entry is:
// ammo/amunition type
// upstate
// downstate
// readystate
// atkstate, i.e. attack/fire/hit frame
// flashstate, muzzle flash
//
weaponinfo_t weaponinfo[NUMWEAPONS] =
{
{
// fist
am_noammo,
S_PUNCHUP,
S_PUNCHDOWN,
S_PUNCH,
S_PUNCH1,
S_NULL
},
{
// pistol
am_clip,
S_PISTOLUP,
S_PISTOLDOWN,
S_PISTOL,
S_PISTOL1,
S_PISTOLFLASH
},
{
// shotgun
am_shell,
S_SGUNUP,
S_SGUNDOWN,
S_SGUN,
S_SGUN1,
S_SGUNFLASH1
},
{
// chaingun
am_clip,
S_CHAINUP,
S_CHAINDOWN,
S_CHAIN,
S_CHAIN1,
S_CHAINFLASH1
},
{
// missile launcher
am_misl,
S_MISSILEUP,
S_MISSILEDOWN,
S_MISSILE,
S_MISSILE1,
S_MISSILEFLASH1
},
{
// plasma rifle
am_cell,
S_PLASMAUP,
S_PLASMADOWN,
S_PLASMA,
S_PLASMA1,
S_PLASMAFLASH1
},
{
// bfg 9000
am_cell,
S_BFGUP,
S_BFGDOWN,
S_BFG,
S_BFG1,
S_BFGFLASH1
},
{
// chainsaw
am_noammo,
S_SAWUP,
S_SAWDOWN,
S_SAW,
S_SAW1,
S_NULL
},
{
// super shotgun
am_shell,
S_DSGUNUP,
S_DSGUNDOWN,
S_DSGUN,
S_DSGUN1,
S_DSGUNFLASH1
},
};

41
doom/d_items.h Normal file
View file

@ -0,0 +1,41 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Items: key cards, artifacts, weapon, ammunition.
//
#ifndef __D_ITEMS__
#define __D_ITEMS__
#include "doomdef.h"
// Weapon info: sprite frames, ammunition use.
typedef struct
{
ammotype_t ammo;
int upstate;
int downstate;
int readystate;
int atkstate;
int flashstate;
} weaponinfo_t;
extern weaponinfo_t weaponinfo[NUMWEAPONS];
#endif

848
doom/d_iwad.c Normal file
View file

@ -0,0 +1,848 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Search for and locate an IWAD file, and initialize according
// to the IWAD type.
//
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "config.h"
#include "deh_str.h"
#include "doomkeys.h"
#include "d_iwad.h"
#include "i_system.h"
#include "m_argv.h"
#include "m_config.h"
#include "m_misc.h"
#include "w_wad.h"
#include "z_zone.h"
static const iwad_t iwads[] =
{
{ "doom2.wad", doom2, commercial, "Doom II" },
{ "plutonia.wad", pack_plut, commercial, "Final Doom: Plutonia Experiment" },
{ "tnt.wad", pack_tnt, commercial, "Final Doom: TNT: Evilution" },
{ "doom.wad", doom, retail, "Doom" },
{ "DOOM1.WAD", doom, shareware, "Doom Shareware" },
{ "chex.wad", pack_chex, shareware, "Chex Quest" },
{ "hacx.wad", pack_hacx, commercial, "Hacx" },
{ "freedm.wad", doom2, commercial, "FreeDM" },
{ "freedoom2.wad", doom2, commercial, "Freedoom: Phase 2" },
{ "freedoom1.wad", doom, retail, "Freedoom: Phase 1" },
{ "heretic.wad", heretic, retail, "Heretic" },
{ "heretic1.wad", heretic, shareware, "Heretic Shareware" },
{ "hexen.wad", hexen, commercial, "Hexen" },
//{ "strife0.wad", strife, commercial, "Strife" }, // haleyjd: STRIFE-FIXME
{ "strife1.wad", strife, commercial, "Strife" },
};
// Array of locations to search for IWAD files
//
// "128 IWAD search directories should be enough for anybody".
#define MAX_IWAD_DIRS 128
static boolean iwad_dirs_built = false;
static char *iwad_dirs[MAX_IWAD_DIRS];
static int num_iwad_dirs = 0;
static void AddIWADDir(char *dir)
{
if (num_iwad_dirs < MAX_IWAD_DIRS)
{
iwad_dirs[num_iwad_dirs] = dir;
++num_iwad_dirs;
}
}
// This is Windows-specific code that automatically finds the location
// of installed IWAD files. The registry is inspected to find special
// keys installed by the Windows installers for various CD versions
// of Doom. From these keys we can deduce where to find an IWAD.
#if defined(_WIN32) && !defined(_WIN32_WCE)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef struct
{
HKEY root;
char *path;
char *value;
} registry_value_t;
#define UNINSTALLER_STRING "\\uninstl.exe /S "
// Keys installed by the various CD editions. These are actually the
// commands to invoke the uninstaller and look like this:
//
// C:\Program Files\Path\uninstl.exe /S C:\Program Files\Path
//
// With some munging we can find where Doom was installed.
// [AlexMax] From the persepctive of a 64-bit executable, 32-bit registry
// keys are located in a different spot.
#if _WIN64
#define SOFTWARE_KEY "Software\\Wow6432Node"
#else
#define SOFTWARE_KEY "Software"
#endif
static registry_value_t uninstall_values[] =
{
// Ultimate Doom, CD version (Depths of Doom trilogy)
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\"
"Uninstall\\Ultimate Doom for Windows 95",
"UninstallString",
},
// Doom II, CD version (Depths of Doom trilogy)
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\"
"Uninstall\\Doom II for Windows 95",
"UninstallString",
},
// Final Doom
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\"
"Uninstall\\Final Doom for Windows 95",
"UninstallString",
},
// Shareware version
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Microsoft\\Windows\\CurrentVersion\\"
"Uninstall\\Doom Shareware for Windows 95",
"UninstallString",
},
};
// Value installed by the Collector's Edition when it is installed
static registry_value_t collectors_edition_value =
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Activision\\DOOM Collector's Edition\\v1.0",
"INSTALLPATH",
};
// Subdirectories of the above install path, where IWADs are installed.
static char *collectors_edition_subdirs[] =
{
"Doom2",
"Final Doom",
"Ultimate Doom",
};
// Location where Steam is installed
static registry_value_t steam_install_location =
{
HKEY_LOCAL_MACHINE,
SOFTWARE_KEY "\\Valve\\Steam",
"InstallPath",
};
// Subdirs of the steam install directory where IWADs are found
static char *steam_install_subdirs[] =
{
"steamapps\\common\\doom 2\\base",
"steamapps\\common\\final doom\\base",
"steamapps\\common\\ultimate doom\\base",
"steamapps\\common\\heretic shadow of the serpent riders\\base",
"steamapps\\common\\hexen\\base",
"steamapps\\common\\hexen deathkings of the dark citadel\\base",
// From Doom 3: BFG Edition:
"steamapps\\common\\DOOM 3 BFG Edition\\base\\wads",
};
#define STEAM_BFG_GUS_PATCHES \
"steamapps\\common\\DOOM 3 BFG Edition\\base\\classicmusic\\instruments"
static char *GetRegistryString(registry_value_t *reg_val)
{
HKEY key;
DWORD len;
DWORD valtype;
char *result;
// Open the key (directory where the value is stored)
if (RegOpenKeyEx(reg_val->root, reg_val->path,
0, KEY_READ, &key) != ERROR_SUCCESS)
{
return NULL;
}
result = NULL;
// Find the type and length of the string, and only accept strings.
if (RegQueryValueEx(key, reg_val->value,
NULL, &valtype, NULL, &len) == ERROR_SUCCESS
&& valtype == REG_SZ)
{
// Allocate a buffer for the value and read the value
result = malloc(len);
if (RegQueryValueEx(key, reg_val->value, NULL, &valtype,
(unsigned char *) result, &len) != ERROR_SUCCESS)
{
free(result);
result = NULL;
}
}
// Close the key
RegCloseKey(key);
return result;
}
// Check for the uninstall strings from the CD versions
static void CheckUninstallStrings(void)
{
unsigned int i;
for (i=0; i<arrlen(uninstall_values); ++i)
{
char *val;
char *path;
char *unstr;
val = GetRegistryString(&uninstall_values[i]);
if (val == NULL)
{
continue;
}
unstr = strstr(val, UNINSTALLER_STRING);
if (unstr == NULL)
{
free(val);
}
else
{
path = unstr + strlen(UNINSTALLER_STRING);
AddIWADDir(path);
}
}
}
// Check for Doom: Collector's Edition
static void CheckCollectorsEdition(void)
{
char *install_path;
char *subpath;
unsigned int i;
install_path = GetRegistryString(&collectors_edition_value);
if (install_path == NULL)
{
return;
}
for (i=0; i<arrlen(collectors_edition_subdirs); ++i)
{
subpath = M_StringJoin(install_path, DIR_SEPARATOR_S,
collectors_edition_subdirs[i], NULL);
AddIWADDir(subpath);
}
free(install_path);
}
// Check for Doom downloaded via Steam
static void CheckSteamEdition(void)
{
char *install_path;
char *subpath;
size_t i;
install_path = GetRegistryString(&steam_install_location);
if (install_path == NULL)
{
return;
}
for (i=0; i<arrlen(steam_install_subdirs); ++i)
{
subpath = M_StringJoin(install_path, DIR_SEPARATOR_S,
steam_install_subdirs[i], NULL);
AddIWADDir(subpath);
}
free(install_path);
}
// The BFG edition ships with a full set of GUS patches. If we find them,
// we can autoconfigure to use them.
static void CheckSteamGUSPatches(void)
{
const char *current_path;
char *install_path;
char *patch_path;
int len;
// Already configured? Don't stomp on the user's choices.
current_path = M_GetStrVariable("gus_patch_path");
if (current_path != NULL && strlen(current_path) > 0)
{
return;
}
install_path = GetRegistryString(&steam_install_location);
if (install_path == NULL)
{
return;
}
len = strlen(install_path) + strlen(STEAM_BFG_GUS_PATCHES) + 20;
patch_path = malloc(len);
M_snprintf(patch_path, len, "%s\\%s\\ACBASS.PAT",
install_path, STEAM_BFG_GUS_PATCHES);
// Does acbass.pat exist? If so, then set gus_patch_path.
if (M_FileExists(patch_path))
{
M_snprintf(patch_path, len, "%s\\%s",
install_path, STEAM_BFG_GUS_PATCHES);
M_SetVariable("gus_patch_path", patch_path);
}
free(patch_path);
free(install_path);
}
// Default install directories for DOS Doom
static void CheckDOSDefaults(void)
{
// These are the default install directories used by the deice
// installer program:
AddIWADDir("\\doom2"); // Doom II
AddIWADDir("\\plutonia"); // Final Doom
AddIWADDir("\\tnt");
AddIWADDir("\\doom_se"); // Ultimate Doom
AddIWADDir("\\doom"); // Shareware / Registered Doom
AddIWADDir("\\dooms"); // Shareware versions
AddIWADDir("\\doomsw");
AddIWADDir("\\heretic"); // Heretic
AddIWADDir("\\hrtic_se"); // Heretic Shareware from Quake disc
AddIWADDir("\\hexen"); // Hexen
AddIWADDir("\\hexendk"); // Hexen Deathkings of the Dark Citadel
AddIWADDir("\\strife"); // Strife
}
#endif
// Returns true if the specified path is a path to a file
// of the specified name.
static boolean DirIsFile(char *path, char *filename)
{
size_t path_len;
size_t filename_len;
path_len = strlen(path);
filename_len = strlen(filename);
return path_len >= filename_len + 1
&& path[path_len - filename_len - 1] == DIR_SEPARATOR
&& !strcasecmp(&path[path_len - filename_len], filename);
}
// Check if the specified directory contains the specified IWAD
// file, returning the full path to the IWAD if found, or NULL
// if not found.
static char *CheckDirectoryHasIWAD(char *dir, char *iwadname)
{
char *filename;
// As a special case, the "directory" may refer directly to an
// IWAD file if the path comes from DOOMWADDIR or DOOMWADPATH.
if (DirIsFile(dir, iwadname) && M_FileExists(dir))
{
return strdup(dir);
}
// Construct the full path to the IWAD if it is located in
// this directory, and check if it exists.
if (!strcmp(dir, "."))
{
filename = strdup(iwadname);
}
else
{
filename = M_StringJoin(dir, DIR_SEPARATOR_S, iwadname, NULL);
}
printf("Trying IWAD file:%s\n", filename);
if (M_FileExists(filename))
{
return filename;
}
free(filename);
return NULL;
}
// Search a directory to try to find an IWAD
// Returns the location of the IWAD if found, otherwise NULL.
static char *SearchDirectoryForIWAD(char *dir, int mask, GameMission_t *mission)
{
char *filename;
size_t i;
for (i=0; i<arrlen(iwads); ++i)
{
if (((1 << iwads[i].mission) & mask) == 0)
{
continue;
}
filename = CheckDirectoryHasIWAD(dir, DEH_String(iwads[i].name));
if (filename != NULL)
{
*mission = iwads[i].mission;
return filename;
}
}
return NULL;
}
// When given an IWAD with the '-iwad' parameter,
// attempt to identify it by its name.
static GameMission_t IdentifyIWADByName(char *name, int mask)
{
size_t i;
GameMission_t mission;
char *p;
p = strrchr(name, DIR_SEPARATOR);
if (p != NULL)
{
name = p + 1;
}
mission = none;
for (i=0; i<arrlen(iwads); ++i)
{
// Check if the filename is this IWAD name.
// Only use supported missions:
if (((1 << iwads[i].mission) & mask) == 0)
continue;
// Check if it ends in this IWAD name.
if (!strcasecmp(name, iwads[i].name))
{
mission = iwads[i].mission;
break;
}
}
return mission;
}
#if ORIGCODE
//
// Add directories from the list in the DOOMWADPATH environment variable.
//
static void AddDoomWadPath(void)
{
char *doomwadpath;
char *p;
// Check the DOOMWADPATH environment variable.
doomwadpath = getenv("DOOMWADPATH");
if (doomwadpath == NULL)
{
return;
}
doomwadpath = strdup(doomwadpath);
// Add the initial directory
AddIWADDir(doomwadpath);
// Split into individual dirs within the list.
p = doomwadpath;
for (;;)
{
p = strchr(p, PATH_SEPARATOR);
if (p != NULL)
{
// Break at the separator and store the right hand side
// as another iwad dir
*p = '\0';
p += 1;
AddIWADDir(p);
}
else
{
break;
}
}
}
#endif
//
// Build a list of IWAD files
//
static void BuildIWADDirList(void)
{
#if ORIGCODE
char *doomwaddir;
if (iwad_dirs_built)
{
return;
}
// Look in the current directory. Doom always does this.
AddIWADDir(".");
// Add DOOMWADDIR if it is in the environment
doomwaddir = getenv("DOOMWADDIR");
if (doomwaddir != NULL)
{
AddIWADDir(doomwaddir);
}
// Add dirs from DOOMWADPATH
AddDoomWadPath();
#ifdef _WIN32
// Search the registry and find where IWADs have been installed.
CheckUninstallStrings();
CheckCollectorsEdition();
CheckSteamEdition();
CheckDOSDefaults();
// Check for GUS patches installed with the BFG edition!
CheckSteamGUSPatches();
#else
// Standard places where IWAD files are installed under Unix.
AddIWADDir("/usr/share/games/doom");
AddIWADDir("/usr/local/share/games/doom");
#endif
#else
AddIWADDir (FILES_DIR);
// Don't run this function again.
iwad_dirs_built = true;
#endif
}
//
// Searches WAD search paths for an WAD with a specific filename.
//
char *D_FindWADByName(char *name)
{
char *path;
int i;
// Absolute path?
if (M_FileExists(name))
{
return name;
}
BuildIWADDirList();
// Search through all IWAD paths for a file with the given name.
for (i=0; i<num_iwad_dirs; ++i)
{
// As a special case, if this is in DOOMWADDIR or DOOMWADPATH,
// the "directory" may actually refer directly to an IWAD
// file.
if (DirIsFile(iwad_dirs[i], name) && M_FileExists(iwad_dirs[i]))
{
return strdup(iwad_dirs[i]);
}
// Construct a string for the full path
path = M_StringJoin(iwad_dirs[i], DIR_SEPARATOR_S, name, NULL);
if (M_FileExists(path))
{
return path;
}
free(path);
}
// File not found
return NULL;
}
//
// D_TryWADByName
//
// Searches for a WAD by its filename, or passes through the filename
// if not found.
//
char *D_TryFindWADByName(char *filename)
{
char *result;
result = D_FindWADByName(filename);
if (result != NULL)
{
return result;
}
else
{
return filename;
}
}
//
// FindIWAD
// Checks availability of IWAD files by name,
// to determine whether registered/commercial features
// should be executed (notably loading PWADs).
//
char *D_FindIWAD(int mask, GameMission_t *mission)
{
char *result;
char *iwadfile;
int iwadparm;
int i;
// Check for the -iwad parameter
//!
// Specify an IWAD file to use.
//
// @arg <file>
//
iwadparm = M_CheckParmWithArgs("-iwad", 1);
if (iwadparm)
{
// Search through IWAD dirs for an IWAD with the given name.
iwadfile = myargv[iwadparm + 1];
result = D_FindWADByName(iwadfile);
if (result == NULL)
{
I_Error("IWAD file '%s' not found!", iwadfile);
}
*mission = IdentifyIWADByName(result, mask);
}
else
{
// Search through the list and look for an IWAD
printf("-iwad not specified, trying a few iwad names\n");
result = NULL;
BuildIWADDirList();
for (i=0; result == NULL && i<num_iwad_dirs; ++i)
{
result = SearchDirectoryForIWAD(iwad_dirs[i], mask, mission);
}
}
return result;
}
// Find all IWADs in the IWAD search path matching the given mask.
const iwad_t **D_FindAllIWADs(int mask)
{
const iwad_t **result;
int result_len;
char *filename;
int i;
result = malloc(sizeof(iwad_t *) * (arrlen(iwads) + 1));
result_len = 0;
// Try to find all IWADs
for (i=0; i<arrlen(iwads); ++i)
{
if (((1 << iwads[i].mission) & mask) == 0)
{
continue;
}
filename = D_FindWADByName(iwads[i].name);
if (filename != NULL)
{
result[result_len] = &iwads[i];
++result_len;
}
}
// End of list
result[result_len] = NULL;
return result;
}
//
// Get the IWAD name used for savegames.
//
char *D_SaveGameIWADName(GameMission_t gamemission)
{
size_t i;
// Determine the IWAD name to use for savegames.
// This determines the directory the savegame files get put into.
//
// Note that we match on gamemission rather than on IWAD name.
// This ensures that doom1.wad and doom.wad saves are stored
// in the same place.
for (i=0; i<arrlen(iwads); ++i)
{
if (gamemission == iwads[i].mission)
{
return iwads[i].name;
}
}
// Default fallback:
return "unknown.wad";
}
char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode)
{
int i;
for (i = 0; i < arrlen(iwads); ++i)
{
if (iwads[i].mission == mission && iwads[i].mode == mode)
{
return iwads[i].name;
}
}
return "unknown.wad";
}
char *D_SuggestGameName(GameMission_t mission, GameMode_t mode)
{
int i;
for (i = 0; i < arrlen(iwads); ++i)
{
if (iwads[i].mission == mission
&& (mode == indetermined || iwads[i].mode == mode))
{
return iwads[i].description;
}
}
return "Unknown game?";
}

52
doom/d_iwad.h Normal file
View file

@ -0,0 +1,52 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Find IWAD and initialize according to IWAD type.
//
#ifndef __D_IWAD__
#define __D_IWAD__
#include "d_mode.h"
#define IWAD_MASK_DOOM ((1 << doom) \
| (1 << doom2) \
| (1 << pack_tnt) \
| (1 << pack_plut) \
| (1 << pack_chex) \
| (1 << pack_hacx))
#define IWAD_MASK_HERETIC (1 << heretic)
#define IWAD_MASK_HEXEN (1 << hexen)
#define IWAD_MASK_STRIFE (1 << strife)
typedef struct
{
char *name;
GameMission_t mission;
GameMode_t mode;
char *description;
} iwad_t;
char *D_FindWADByName(char *filename);
char *D_TryFindWADByName(char *filename);
char *D_FindIWAD(int mask, GameMission_t *mission);
const iwad_t **D_FindAllIWADs(int mask);
char *D_SaveGameIWADName(GameMission_t gamemission);
char *D_SuggestIWADName(GameMission_t mission, GameMode_t mode);
char *D_SuggestGameName(GameMission_t mission, GameMode_t mode);
void D_CheckCorrectIWAD(GameMission_t mission);
#endif

826
doom/d_loop.c Normal file
View file

@ -0,0 +1,826 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Main loop code.
//
#include <stdlib.h>
#include <string.h>
#include "doomfeatures.h"
#include "d_event.h"
#include "d_loop.h"
#include "d_ticcmd.h"
#include "i_system.h"
#include "i_timer.h"
#include "i_video.h"
#include "m_argv.h"
#include "m_fixed.h"
#include "net_client.h"
#include "net_gui.h"
#include "net_io.h"
#include "net_query.h"
#include "net_server.h"
#include "net_sdl.h"
#include "net_loop.h"
// The complete set of data for a particular tic.
typedef struct
{
ticcmd_t cmds[NET_MAXPLAYERS];
boolean ingame[NET_MAXPLAYERS];
} ticcmd_set_t;
//
// gametic is the tic about to (or currently being) run
// maketic is the tic that hasn't had control made for it yet
// recvtic is the latest tic received from the server.
//
// a gametic cannot be run until ticcmds are received for it
// from all players.
//
static ticcmd_set_t ticdata[BACKUPTICS];
// The index of the next tic to be made (with a call to BuildTiccmd).
static int maketic;
// The number of complete tics received from the server so far.
static int recvtic;
// The number of tics that have been run (using RunTic) so far.
int gametic;
// When set to true, a single tic is run each time TryRunTics() is called.
// This is used for -timedemo mode.
boolean singletics = false;
// Index of the local player.
static int localplayer;
// Used for original sync code.
static int skiptics = 0;
// Reduce the bandwidth needed by sampling game input less and transmitting
// less. If ticdup is 2, sample half normal, 3 = one third normal, etc.
int ticdup;
// Amount to offset the timer for game sync.
fixed_t offsetms;
// Use new client syncronisation code
static boolean new_sync = true;
// Callback functions for loop code.
static loop_interface_t *loop_interface = NULL;
// Current players in the multiplayer game.
// This is distinct from playeringame[] used by the game code, which may
// modify playeringame[] when playing back multiplayer demos.
static boolean local_playeringame[NET_MAXPLAYERS];
// Requested player class "sent" to the server on connect.
// If we are only doing a single player game then this needs to be remembered
// and saved in the game settings.
static int player_class;
// 35 fps clock adjusted by offsetms milliseconds
static int GetAdjustedTime(void)
{
int time_ms;
time_ms = I_GetTimeMS();
if (new_sync)
{
// Use the adjustments from net_client.c only if we are
// using the new sync mode.
time_ms += (offsetms / FRACUNIT);
}
return (time_ms * TICRATE) / 1000;
}
static boolean BuildNewTic(void)
{
int gameticdiv;
ticcmd_t cmd;
gameticdiv = gametic/ticdup;
I_StartTic ();
loop_interface->ProcessEvents();
// Always run the menu
loop_interface->RunMenu();
if (drone)
{
// In drone mode, do not generate any ticcmds.
return false;
}
if (new_sync)
{
// If playing single player, do not allow tics to buffer
// up very far
if (!net_client_connected && maketic - gameticdiv > 2)
return false;
// Never go more than ~200ms ahead
if (maketic - gameticdiv > 8)
return false;
}
else
{
if (maketic - gameticdiv >= 5)
return false;
}
//printf ("mk:%i ",maketic);
memset(&cmd, 0, sizeof(ticcmd_t));
loop_interface->BuildTiccmd(&cmd, maketic);
#ifdef FEATURE_MULTIPLAYER
if (net_client_connected)
{
NET_CL_SendTiccmd(&cmd, maketic);
}
#endif
ticdata[maketic % BACKUPTICS].cmds[localplayer] = cmd;
ticdata[maketic % BACKUPTICS].ingame[localplayer] = true;
++maketic;
return true;
}
//
// NetUpdate
// Builds ticcmds for console player,
// sends out a packet
//
int lasttime;
void NetUpdate (void)
{
int nowtime;
int newtics;
int i;
// If we are running with singletics (timing a demo), this
// is all done separately.
if (singletics)
return;
#ifdef FEATURE_MULTIPLAYER
// Run network subsystems
NET_CL_Run();
NET_SV_Run();
#endif
// check time
nowtime = GetAdjustedTime() / ticdup;
newtics = nowtime - lasttime;
lasttime = nowtime;
if (skiptics <= newtics)
{
newtics -= skiptics;
skiptics = 0;
}
else
{
skiptics -= newtics;
newtics = 0;
}
// build new ticcmds for console player
for (i=0 ; i<newtics ; i++)
{
if (!BuildNewTic())
{
break;
}
}
}
static void D_Disconnected(void)
{
// In drone mode, the game cannot continue once disconnected.
if (drone)
{
I_Error("Disconnected from server in drone mode.");
}
// disconnected from server
printf("Disconnected from server.\n");
}
//
// Invoked by the network engine when a complete set of ticcmds is
// available.
//
void D_ReceiveTic(ticcmd_t *ticcmds, boolean *players_mask)
{
int i;
// Disconnected from server?
if (ticcmds == NULL && players_mask == NULL)
{
D_Disconnected();
return;
}
for (i = 0; i < NET_MAXPLAYERS; ++i)
{
if (!drone && i == localplayer)
{
// This is us. Don't overwrite it.
}
else
{
ticdata[recvtic % BACKUPTICS].cmds[i] = ticcmds[i];
ticdata[recvtic % BACKUPTICS].ingame[i] = players_mask[i];
}
}
++recvtic;
}
//
// Start game loop
//
// Called after the screen is set but before the game starts running.
//
void D_StartGameLoop(void)
{
lasttime = GetAdjustedTime() / ticdup;
}
#if ORIGCODE
//
// Block until the game start message is received from the server.
//
static void BlockUntilStart(net_gamesettings_t *settings,
netgame_startup_callback_t callback)
{
while (!NET_CL_GetSettings(settings))
{
NET_CL_Run();
NET_SV_Run();
if (!net_client_connected)
{
I_Error("Lost connection to server");
}
if (callback != NULL && !callback(net_client_wait_data.ready_players,
net_client_wait_data.num_players))
{
I_Error("Netgame startup aborted.");
}
I_Sleep(100);
}
}
#endif
void D_StartNetGame(net_gamesettings_t *settings,
netgame_startup_callback_t callback)
{
#if ORIGCODE
int i;
offsetms = 0;
recvtic = 0;
settings->consoleplayer = 0;
settings->num_players = 1;
settings->player_classes[0] = player_class;
//!
// @category net
//
// Use new network client sync code rather than the classic
// sync code. This is currently disabled by default because it
// has some bugs.
//
if (M_CheckParm("-newsync") > 0)
settings->new_sync = 1;
else
settings->new_sync = 0;
// TODO: New sync code is not enabled by default because it's
// currently broken.
//if (M_CheckParm("-oldsync") > 0)
// settings->new_sync = 0;
//else
// settings->new_sync = 1;
//!
// @category net
// @arg <n>
//
// Send n extra tics in every packet as insurance against dropped
// packets.
//
i = M_CheckParmWithArgs("-extratics", 1);
if (i > 0)
settings->extratics = atoi(myargv[i+1]);
else
settings->extratics = 1;
//!
// @category net
// @arg <n>
//
// Reduce the resolution of the game by a factor of n, reducing
// the amount of network bandwidth needed.
//
i = M_CheckParmWithArgs("-dup", 1);
if (i > 0)
settings->ticdup = atoi(myargv[i+1]);
else
settings->ticdup = 1;
if (net_client_connected)
{
// Send our game settings and block until game start is received
// from the server.
NET_CL_StartGame(settings);
BlockUntilStart(settings, callback);
// Read the game settings that were received.
NET_CL_GetSettings(settings);
}
if (drone)
{
settings->consoleplayer = 0;
}
// Set the local player and playeringame[] values.
localplayer = settings->consoleplayer;
for (i = 0; i < NET_MAXPLAYERS; ++i)
{
local_playeringame[i] = i < settings->num_players;
}
// Copy settings to global variables.
ticdup = settings->ticdup;
new_sync = settings->new_sync;
// TODO: Message disabled until we fix new_sync.
//if (!new_sync)
//{
// printf("Syncing netgames like Vanilla Doom.\n");
//}
#else
settings->consoleplayer = 0;
settings->num_players = 1;
settings->player_classes[0] = player_class;
settings->new_sync = 0;
settings->extratics = 1;
settings->ticdup = 1;
ticdup = settings->ticdup;
new_sync = settings->new_sync;
#endif
}
boolean D_InitNetGame(net_connect_data_t *connect_data)
{
boolean result = false;
#ifdef FEATURE_MULTIPLAYER
net_addr_t *addr = NULL;
int i;
#endif
// Call D_QuitNetGame on exit:
I_AtExit(D_QuitNetGame, true);
player_class = connect_data->player_class;
#ifdef FEATURE_MULTIPLAYER
//!
// @category net
//
// Start a multiplayer server, listening for connections.
//
if (M_CheckParm("-server") > 0
|| M_CheckParm("-privateserver") > 0)
{
NET_SV_Init();
NET_SV_AddModule(&net_loop_server_module);
NET_SV_AddModule(&net_sdl_module);
NET_SV_RegisterWithMaster();
net_loop_client_module.InitClient();
addr = net_loop_client_module.ResolveAddress(NULL);
}
else
{
//!
// @category net
//
// Automatically search the local LAN for a multiplayer
// server and join it.
//
i = M_CheckParm("-autojoin");
if (i > 0)
{
addr = NET_FindLANServer();
if (addr == NULL)
{
I_Error("No server found on local LAN");
}
}
//!
// @arg <address>
// @category net
//
// Connect to a multiplayer server running on the given
// address.
//
i = M_CheckParmWithArgs("-connect", 1);
if (i > 0)
{
net_sdl_module.InitClient();
addr = net_sdl_module.ResolveAddress(myargv[i+1]);
if (addr == NULL)
{
I_Error("Unable to resolve '%s'\n", myargv[i+1]);
}
}
}
if (addr != NULL)
{
if (M_CheckParm("-drone") > 0)
{
connect_data->drone = true;
}
if (!NET_CL_Connect(addr, connect_data))
{
I_Error("D_InitNetGame: Failed to connect to %s\n",
NET_AddrToString(addr));
}
printf("D_InitNetGame: Connected to %s\n", NET_AddrToString(addr));
// Wait for launch message received from server.
NET_WaitForLaunch();
result = true;
}
#endif
return result;
}
//
// D_QuitNetGame
// Called before quitting to leave a net game
// without hanging the other players
//
void D_QuitNetGame (void)
{
#ifdef FEATURE_MULTIPLAYER
NET_SV_Shutdown();
NET_CL_Disconnect();
#endif
}
static int GetLowTic(void)
{
int lowtic;
lowtic = maketic;
#ifdef FEATURE_MULTIPLAYER
if (net_client_connected)
{
if (drone || recvtic < lowtic)
{
lowtic = recvtic;
}
}
#endif
return lowtic;
}
static int frameon;
static int frameskip[4];
static int oldnettics;
static void OldNetSync(void)
{
unsigned int i;
int keyplayer = -1;
frameon++;
// ideally maketic should be 1 - 3 tics above lowtic
// if we are consistantly slower, speed up time
for (i=0 ; i<NET_MAXPLAYERS ; i++)
{
if (local_playeringame[i])
{
keyplayer = i;
break;
}
}
if (keyplayer < 0)
{
// If there are no players, we can never advance anyway
return;
}
if (localplayer == keyplayer)
{
// the key player does not adapt
}
else
{
if (maketic <= recvtic)
{
lasttime--;
// printf ("-");
}
frameskip[frameon & 3] = oldnettics > recvtic;
oldnettics = maketic;
if (frameskip[0] && frameskip[1] && frameskip[2] && frameskip[3])
{
skiptics = 1;
// printf ("+");
}
}
}
// Returns true if there are players in the game:
static boolean PlayersInGame(void)
{
boolean result = false;
unsigned int i;
// If we are connected to a server, check if there are any players
// in the game.
if (net_client_connected)
{
for (i = 0; i < NET_MAXPLAYERS; ++i)
{
result = result || local_playeringame[i];
}
}
// Whether single or multi-player, unless we are running as a drone,
// we are in the game.
if (!drone)
{
result = true;
}
return result;
}
// When using ticdup, certain values must be cleared out when running
// the duplicate ticcmds.
static void TicdupSquash(ticcmd_set_t *set)
{
ticcmd_t *cmd;
unsigned int i;
for (i = 0; i < NET_MAXPLAYERS ; ++i)
{
cmd = &set->cmds[i];
cmd->chatchar = 0;
if (cmd->buttons & BT_SPECIAL)
cmd->buttons = 0;
}
}
// When running in single player mode, clear all the ingame[] array
// except the local player.
static void SinglePlayerClear(ticcmd_set_t *set)
{
unsigned int i;
for (i = 0; i < NET_MAXPLAYERS; ++i)
{
if (i != localplayer)
{
set->ingame[i] = false;
}
}
}
//
// TryRunTics
//
void TryRunTics (void)
{
int i;
int lowtic;
int entertic;
static int oldentertics;
int realtics;
int availabletics;
int counts;
// get real tics
entertic = I_GetTime() / ticdup;
realtics = entertic - oldentertics;
oldentertics = entertic;
// in singletics mode, run a single tic every time this function
// is called.
if (singletics)
{
BuildNewTic();
}
else
{
NetUpdate ();
}
lowtic = GetLowTic();
availabletics = lowtic - gametic/ticdup;
// decide how many tics to run
if (new_sync)
{
counts = availabletics;
}
else
{
// decide how many tics to run
if (realtics < availabletics-1)
counts = realtics+1;
else if (realtics < availabletics)
counts = realtics;
else
counts = availabletics;
if (counts < 1)
counts = 1;
if (net_client_connected)
{
OldNetSync();
}
}
if (counts < 1)
counts = 1;
// wait for new tics if needed
while (!PlayersInGame() || lowtic < gametic/ticdup + counts)
{
NetUpdate ();
lowtic = GetLowTic();
if (lowtic < gametic/ticdup)
I_Error ("TryRunTics: lowtic < gametic");
// Don't stay in this loop forever. The menu is still running,
// so return to update the screen
if (I_GetTime() / ticdup - entertic > 0)
{
return;
}
I_Sleep(1);
}
// run the count * ticdup dics
while (counts--)
{
ticcmd_set_t *set;
if (!PlayersInGame())
{
return;
}
set = &ticdata[(gametic / ticdup) % BACKUPTICS];
if (!net_client_connected)
{
SinglePlayerClear(set);
}
for (i=0 ; i<ticdup ; i++)
{
if (gametic/ticdup > lowtic)
I_Error ("gametic>lowtic");
memcpy(local_playeringame, set->ingame, sizeof(local_playeringame));
loop_interface->RunTic(set->cmds, set->ingame);
gametic++;
// modify command for duplicated tics
TicdupSquash(set);
}
NetUpdate (); // check for new console commands
}
}
void D_RegisterLoopCallbacks(loop_interface_t *i)
{
loop_interface = i;
}

81
doom/d_loop.h Normal file
View file

@ -0,0 +1,81 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Main loop stuff.
//
#ifndef __D_LOOP__
#define __D_LOOP__
#include "net_defs.h"
// Callback function invoked while waiting for the netgame to start.
// The callback is invoked when new players are ready. The callback
// should return true, or return false to abort startup.
typedef boolean (*netgame_startup_callback_t)(int ready_players,
int num_players);
typedef struct
{
// Read events from the event queue, and process them.
void (*ProcessEvents)();
// Given the current input state, fill in the fields of the specified
// ticcmd_t structure with data for a new tic.
void (*BuildTiccmd)(ticcmd_t *cmd, int maketic);
// Advance the game forward one tic, using the specified player input.
void (*RunTic)(ticcmd_t *cmds, boolean *ingame);
// Run the menu (runs independently of the game).
void (*RunMenu)();
} loop_interface_t;
// Register callback functions for the main loop code to use.
void D_RegisterLoopCallbacks(loop_interface_t *i);
// Create any new ticcmds and broadcast to other players.
void NetUpdate (void);
// Broadcasts special packets to other players
// to notify of game exit
void D_QuitNetGame (void);
//? how many ticks to run?
void TryRunTics (void);
// Called at start of game loop to initialize timers
void D_StartGameLoop(void);
// Initialize networking code and connect to server.
boolean D_InitNetGame(net_connect_data_t *connect_data);
// Start game with specified settings. The structure will be updated
// with the actual settings for the game.
void D_StartNetGame(net_gamesettings_t *settings,
netgame_startup_callback_t callback);
extern boolean singletics;
extern int gametic, ticdup;
#endif

1815
doom/d_main.c Normal file

File diff suppressed because it is too large Load diff

50
doom/d_main.h Normal file
View file

@ -0,0 +1,50 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// System specific interface stuff.
//
#ifndef __D_MAIN__
#define __D_MAIN__
#include "doomdef.h"
// Read events from all input devices
void D_ProcessEvents (void);
//
// BASE LEVEL
//
void D_PageTicker (void);
void D_PageDrawer (void);
void D_AdvanceDemo (void);
void D_DoAdvanceDemo (void);
void D_StartTitle (void);
//
// GLOBAL VARIABLES
//
extern gameaction_t gameaction;
#endif

209
doom/d_mode.c Normal file
View file

@ -0,0 +1,209 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// DESCRIPTION:
// Functions and definitions relating to the game type and operational
// mode.
//
#include "doomtype.h"
#include "d_mode.h"
// Valid game mode/mission combinations, with the number of
// episodes/maps for each.
static struct
{
GameMission_t mission;
GameMode_t mode;
int episode;
int map;
} valid_modes[] = {
{ pack_chex, shareware, 1, 5 },
{ doom, shareware, 1, 9 },
{ doom, registered, 3, 9 },
{ doom, retail, 4, 9 },
{ doom2, commercial, 1, 32 },
{ pack_tnt, commercial, 1, 32 },
{ pack_plut, commercial, 1, 32 },
{ pack_hacx, commercial, 1, 32 },
{ heretic, shareware, 1, 9 },
{ heretic, registered, 3, 9 },
{ heretic, retail, 5, 9 },
{ hexen, commercial, 1, 60 },
{ strife, commercial, 1, 34 },
};
// Check that a gamemode+gamemission received over the network is valid.
boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode)
{
int i;
for (i=0; i<arrlen(valid_modes); ++i)
{
if (valid_modes[i].mode == mode && valid_modes[i].mission == mission)
{
return true;
}
}
return false;
}
boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
int episode, int map)
{
int i;
// Hacks for Heretic secret episodes
if (mission == heretic)
{
if (mode == retail && episode == 6)
{
return map >= 1 && map <= 3;
}
else if (mode == registered && episode == 4)
{
return map == 1;
}
}
// Find the table entry for this mission/mode combination.
for (i=0; i<arrlen(valid_modes); ++i)
{
if (mission == valid_modes[i].mission
&& mode == valid_modes[i].mode)
{
return episode >= 1 && episode <= valid_modes[i].episode
&& map >= 1 && map <= valid_modes[i].map;
}
}
// Unknown mode/mission combination
return false;
}
// Get the number of valid episodes for the specified mission/mode.
int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode)
{
int episode;
episode = 1;
while (D_ValidEpisodeMap(mission, mode, episode, 1))
{
++episode;
}
return episode - 1;
}
// Table of valid versions
static struct {
GameMission_t mission;
GameVersion_t version;
} valid_versions[] = {
{ doom, exe_doom_1_9 },
{ doom, exe_hacx },
{ doom, exe_ultimate },
{ doom, exe_final },
{ doom, exe_final2 },
{ doom, exe_chex },
{ heretic, exe_heretic_1_3 },
{ hexen, exe_hexen_1_1 },
{ strife, exe_strife_1_2 },
{ strife, exe_strife_1_31 },
};
boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version)
{
int i;
// All Doom variants can use the Doom versions.
if (mission == doom2 || mission == pack_plut || mission == pack_tnt
|| mission == pack_hacx || mission == pack_chex)
{
mission = doom;
}
for (i=0; i<arrlen(valid_versions); ++i)
{
if (valid_versions[i].mission == mission
&& valid_versions[i].version == version)
{
return true;
}
}
return false;
}
// Does this mission type use ExMy form, rather than MAPxy form?
boolean D_IsEpisodeMap(GameMission_t mission)
{
switch (mission)
{
case doom:
case heretic:
case pack_chex:
return true;
case none:
case hexen:
case doom2:
case pack_hacx:
case pack_tnt:
case pack_plut:
case strife:
default:
return false;
}
}
char *D_GameMissionString(GameMission_t mission)
{
switch (mission)
{
case none:
default:
return "none";
case doom:
return "doom";
case doom2:
return "doom2";
case pack_tnt:
return "tnt";
case pack_plut:
return "plutonia";
case pack_hacx:
return "hacx";
case pack_chex:
return "chex";
case heretic:
return "heretic";
case hexen:
return "hexen";
case strife:
return "strife";
}
}

98
doom/d_mode.h Normal file
View file

@ -0,0 +1,98 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Functions and definitions relating to the game type and operational
// mode.
//
#ifndef __D_MODE__
#define __D_MODE__
#include "doomtype.h"
// The "mission" controls what game we are playing.
typedef enum
{
doom, // Doom 1
doom2, // Doom 2
pack_tnt, // Final Doom: TNT: Evilution
pack_plut, // Final Doom: The Plutonia Experiment
pack_chex, // Chex Quest (modded doom)
pack_hacx, // Hacx (modded doom2)
heretic, // Heretic
hexen, // Hexen
strife, // Strife
none
} GameMission_t;
// The "mode" allows more accurate specification of the game mode we are
// in: eg. shareware vs. registered. So doom1.wad and doom.wad are the
// same mission, but a different mode.
typedef enum
{
shareware, // Doom/Heretic shareware
registered, // Doom/Heretic registered
commercial, // Doom II/Hexen
retail, // Ultimate Doom
indetermined // Unknown.
} GameMode_t;
// What version are we emulating?
typedef enum
{
exe_doom_1_2, // Doom 1.2: shareware and registered
exe_doom_1_666, // Doom 1.666: for shareware, registered and commercial
exe_doom_1_7, // Doom 1.7/1.7a: "
exe_doom_1_8, // Doom 1.8: "
exe_doom_1_9, // Doom 1.9: "
exe_hacx, // Hacx
exe_ultimate, // Ultimate Doom (retail)
exe_final, // Final Doom
exe_final2, // Final Doom (alternate exe)
exe_chex, // Chex Quest executable (based on Final Doom)
exe_heretic_1_3, // Heretic 1.3
exe_hexen_1_1, // Hexen 1.1
exe_strife_1_2, // Strife v1.2
exe_strife_1_31 // Strife v1.31
} GameVersion_t;
// Skill level.
typedef enum
{
sk_noitems = -1, // the "-skill 0" hack
sk_baby = 0,
sk_easy,
sk_medium,
sk_hard,
sk_nightmare
} skill_t;
boolean D_ValidGameMode(GameMission_t mission, GameMode_t mode);
boolean D_ValidGameVersion(GameMission_t mission, GameVersion_t version);
boolean D_ValidEpisodeMap(GameMission_t mission, GameMode_t mode,
int episode, int map);
int D_GetNumEpisodes(GameMission_t mission, GameMode_t mode);
boolean D_IsEpisodeMap(GameMission_t mission);
char *D_GameMissionString(GameMission_t mission);
#endif /* #ifndef __D_MODE__ */

281
doom/d_net.c Normal file
View file

@ -0,0 +1,281 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// DOOM Network game communication and protocol,
// all OS independend parts.
//
#include <stdlib.h>
#include "doomfeatures.h"
#include "d_main.h"
#include "m_argv.h"
#include "m_menu.h"
#include "m_misc.h"
#include "i_system.h"
#include "i_timer.h"
#include "i_video.h"
#include "g_game.h"
#include "doomdef.h"
#include "doomstat.h"
#include "w_checksum.h"
#include "w_wad.h"
#include "deh_main.h"
#include "d_loop.h"
ticcmd_t *netcmds;
// Called when a player leaves the game
static void PlayerQuitGame(player_t *player)
{
static char exitmsg[80];
unsigned int player_num;
player_num = player - players;
// Do this the same way as Vanilla Doom does, to allow dehacked
// replacements of this message
M_StringCopy(exitmsg, DEH_String("Player 1 left the game"),
sizeof(exitmsg));
exitmsg[7] += player_num;
playeringame[player_num] = false;
players[consoleplayer].message = exitmsg;
// TODO: check if it is sensible to do this:
if (demorecording)
{
G_CheckDemoStatus ();
}
}
static void RunTic(ticcmd_t *cmds, boolean *ingame)
{
extern boolean advancedemo;
unsigned int i;
// Check for player quits.
for (i = 0; i < MAXPLAYERS; ++i)
{
if (!demoplayback && playeringame[i] && !ingame[i])
{
PlayerQuitGame(&players[i]);
}
}
netcmds = cmds;
// check that there are players in the game. if not, we cannot
// run a tic.
if (advancedemo)
D_DoAdvanceDemo ();
G_Ticker ();
}
static loop_interface_t doom_loop_interface = {
D_ProcessEvents,
G_BuildTiccmd,
RunTic,
M_Ticker
};
// Load game settings from the specified structure and
// set global variables.
static void LoadGameSettings(net_gamesettings_t *settings)
{
unsigned int i;
deathmatch = settings->deathmatch;
startepisode = settings->episode;
startmap = settings->map;
startskill = settings->skill;
startloadgame = settings->loadgame;
lowres_turn = settings->lowres_turn;
nomonsters = settings->nomonsters;
fastparm = settings->fast_monsters;
respawnparm = settings->respawn_monsters;
timelimit = settings->timelimit;
consoleplayer = settings->consoleplayer;
if (lowres_turn)
{
printf("NOTE: Turning resolution is reduced; this is probably "
"because there is a client recording a Vanilla demo.\n");
}
for (i = 0; i < MAXPLAYERS; ++i)
{
playeringame[i] = i < settings->num_players;
}
}
// Save the game settings from global variables to the specified
// game settings structure.
static void SaveGameSettings(net_gamesettings_t *settings)
{
// Fill in game settings structure with appropriate parameters
// for the new game
settings->deathmatch = deathmatch;
settings->episode = startepisode;
settings->map = startmap;
settings->skill = startskill;
settings->loadgame = startloadgame;
settings->gameversion = gameversion;
settings->nomonsters = nomonsters;
settings->fast_monsters = fastparm;
settings->respawn_monsters = respawnparm;
settings->timelimit = timelimit;
settings->lowres_turn = M_CheckParm("-record") > 0
&& M_CheckParm("-longtics") == 0;
}
static void InitConnectData(net_connect_data_t *connect_data)
{
connect_data->max_players = MAXPLAYERS;
connect_data->drone = false;
//!
// @category net
//
// Run as the left screen in three screen mode.
//
if (M_CheckParm("-left") > 0)
{
viewangleoffset = ANG90;
connect_data->drone = true;
}
//!
// @category net
//
// Run as the right screen in three screen mode.
//
if (M_CheckParm("-right") > 0)
{
viewangleoffset = ANG270;
connect_data->drone = true;
}
//
// Connect data
//
// Game type fields:
connect_data->gamemode = gamemode;
connect_data->gamemission = gamemission;
// Are we recording a demo? Possibly set lowres turn mode
connect_data->lowres_turn = M_CheckParm("-record") > 0
&& M_CheckParm("-longtics") == 0;
// Read checksums of our WAD directory and dehacked information
W_Checksum(connect_data->wad_sha1sum);
#if ORIGCODE
DEH_Checksum(connect_data->deh_sha1sum);
#endif
// Are we playing with the Freedoom IWAD?
connect_data->is_freedoom = W_CheckNumForName("FREEDOOM") >= 0;
}
void D_ConnectNetGame(void)
{
net_connect_data_t connect_data;
InitConnectData(&connect_data);
netgame = D_InitNetGame(&connect_data);
//!
// @category net
//
// Start the game playing as though in a netgame with a single
// player. This can also be used to play back single player netgame
// demos.
//
if (M_CheckParm("-solo-net") > 0)
{
netgame = true;
}
}
//
// D_CheckNetGame
// Works out player numbers among the net participants
//
void D_CheckNetGame (void)
{
net_gamesettings_t settings;
if (netgame)
{
autostart = true;
}
D_RegisterLoopCallbacks(&doom_loop_interface);
SaveGameSettings(&settings);
D_StartNetGame(&settings, NULL);
LoadGameSettings(&settings);
DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
startskill, deathmatch, startmap, startepisode);
DEH_printf("player %i of %i (%i nodes)\n",
consoleplayer+1, settings.num_players, settings.num_players);
// Show players here; the server might have specified a time limit
if (timelimit > 0 && deathmatch)
{
// Gross hack to work like Vanilla:
if (timelimit == 20 && M_CheckParm("-avg"))
{
DEH_printf("Austin Virtual Gaming: Levels will end "
"after 20 minutes\n");
}
else
{
DEH_printf("Levels will end after %d minute", timelimit);
if (timelimit > 1)
printf("s");
printf(".\n");
}
}
}

209
doom/d_player.h Normal file
View file

@ -0,0 +1,209 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
//
//
#ifndef __D_PLAYER__
#define __D_PLAYER__
// The player data structure depends on a number
// of other structs: items (internal inventory),
// animation states (closely tied to the sprites
// used to represent them, unfortunately).
#include "d_items.h"
#include "p_pspr.h"
// In addition, the player is just a special
// case of the generic moving object/actor.
#include "p_mobj.h"
// Finally, for odd reasons, the player input
// is buffered within the player data struct,
// as commands per game tick.
#include "d_ticcmd.h"
#include "net_defs.h"
//
// Player states.
//
typedef enum
{
// Playing or camping.
PST_LIVE,
// Dead on the ground, view follows killer.
PST_DEAD,
// Ready to restart/respawn???
PST_REBORN
} playerstate_t;
//
// Player internal flags, for cheats and debug.
//
typedef enum
{
// No clipping, walk through barriers.
CF_NOCLIP = 1,
// No damage, no health loss.
CF_GODMODE = 2,
// Not really a cheat, just a debug aid.
CF_NOMOMENTUM = 4
} cheat_t;
//
// Extended player object info: player_t
//
typedef struct player_s
{
mobj_t* mo;
playerstate_t playerstate;
ticcmd_t cmd;
// Determine POV,
// including viewpoint bobbing during movement.
// Focal origin above r.z
fixed_t viewz;
// Base height above floor for viewz.
fixed_t viewheight;
// Bob/squat speed.
fixed_t deltaviewheight;
// bounded/scaled total momentum.
fixed_t bob;
// This is only used between levels,
// mo->health is used during levels.
int health;
int armorpoints;
// Armor type is 0-2.
int armortype;
// Power ups. invinc and invis are tic counters.
int powers[NUMPOWERS];
boolean cards[NUMCARDS];
boolean backpack;
// Frags, kills of other players.
int frags[MAXPLAYERS];
weapontype_t readyweapon;
// Is wp_nochange if not changing.
weapontype_t pendingweapon;
boolean weaponowned[NUMWEAPONS];
int ammo[NUMAMMO];
int maxammo[NUMAMMO];
// True if button down last tic.
int attackdown;
int usedown;
// Bit flags, for cheats and debug.
// See cheat_t, above.
int cheats;
// Refired shots are less accurate.
int refire;
// For intermission stats.
int killcount;
int itemcount;
int secretcount;
// Hint messages.
char* message;
// For screen flashing (red or bright).
int damagecount;
int bonuscount;
// Who did damage (NULL for floors/ceilings).
mobj_t* attacker;
// So gun flashes light up areas.
int extralight;
// Current PLAYPAL, ???
// can be set to REDCOLORMAP for pain, etc.
int fixedcolormap;
// Player skin colorshift,
// 0-3 for which color to draw player.
int colormap;
// Overlay view sprites (gun, etc).
pspdef_t psprites[NUMPSPRITES];
// True if secret level has been done.
boolean didsecret;
} player_t;
//
// INTERMISSION
// Structure passed e.g. to WI_Start(wb)
//
typedef struct
{
boolean in; // whether the player is in game
// Player stats, kills, collected items etc.
int skills;
int sitems;
int ssecret;
int stime;
int frags[4];
int score; // current score on entry, modified on return
} wbplayerstruct_t;
typedef struct
{
int epsd; // episode # (0-2)
// if true, splash the secret level
boolean didsecret;
// previous and next levels, origin 0
int last;
int next;
int maxkills;
int maxitems;
int maxsecret;
int maxfrags;
// the par time
int partime;
// index of this player in game
int pnum;
wbplayerstruct_t plyr[MAXPLAYERS];
} wbstartstruct_t;
#endif

43
doom/d_textur.h Normal file
View file

@ -0,0 +1,43 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Typedefs related to to textures etc.,
// isolated here to make it easier separating modules.
//
#ifndef __D_TEXTUR__
#define __D_TEXTUR__
#include "doomtype.h"
//
// Flats?
//
// a pic is an unmasked block of pixels
typedef struct
{
byte width;
byte height;
byte data;
} pic_t;
#endif

68
doom/d_think.h Normal file
View file

@ -0,0 +1,68 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// MapObj data. Map Objects or mobjs are actors, entities,
// thinker, take-your-pick... anything that moves, acts, or
// suffers state changes of more or less violent nature.
//
#ifndef __D_THINK__
#define __D_THINK__
//
// Experimental stuff.
// To compile this as "ANSI C with classes"
// we will need to handle the various
// action functions cleanly.
//
typedef void (*actionf_v)();
typedef void (*actionf_p1)( void* );
typedef void (*actionf_p2)( void*, void* );
typedef union
{
actionf_v acv;
actionf_p1 acp1;
actionf_p2 acp2;
} actionf_t;
// Historically, "think_t" is yet another
// function pointer to a routine to handle
// an actor.
typedef actionf_t think_t;
// Doubly linked list of actors.
typedef struct thinker_s
{
struct thinker_s* prev;
struct thinker_s* next;
think_t function;
} thinker_t;
#endif

56
doom/d_ticcmd.h Normal file
View file

@ -0,0 +1,56 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 1993-2008 Raven Software
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// System specific interface stuff.
//
#ifndef __D_TICCMD__
#define __D_TICCMD__
#include "doomtype.h"
// The data sampled per tick (single player)
// and transmitted to other peers (multiplayer).
// Mainly movements/button commands per game tick,
// plus a checksum for internal state consistency.
typedef struct
{
signed char forwardmove; // *2048 for move
signed char sidemove; // *2048 for move
short angleturn; // <<16 for angle delta
byte chatchar;
byte buttons;
// villsa [STRIFE] according to the asm,
// consistancy is a short, not a byte
byte consistancy; // checks for net game
// villsa - Strife specific:
byte buttons2;
int inventory;
// Heretic/Hexen specific:
byte lookfly; // look/fly up/down/centering
byte arti; // artitype_t to use
} ticcmd_t;
#endif

48
doom/deh_main.h Normal file
View file

@ -0,0 +1,48 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// Dehacked entrypoint and common code
//
#ifndef DEH_MAIN_H
#define DEH_MAIN_H
#include "doomtype.h"
#include "doomfeatures.h"
#include "deh_str.h"
#include "sha1.h"
// These are the limits that dehacked uses (from dheinit.h in the dehacked
// source). If these limits are exceeded, it does not generate an error, but
// a warning is displayed.
#define DEH_VANILLA_NUMSTATES 966
#define DEH_VANILLA_NUMSFX 107
void DEH_ParseCommandLine(void);
int DEH_LoadFile(char *filename);
int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error);
int DEH_LoadLumpByName(char *name, boolean allow_long, boolean allow_error);
boolean DEH_ParseAssignment(char *line, char **variable_name, char **value);
void DEH_Checksum(sha1_digest_t digest);
extern boolean deh_allow_extended_strings;
extern boolean deh_allow_long_strings;
extern boolean deh_allow_long_cheats;
extern boolean deh_apply_cheats;
#endif /* #ifndef DEH_MAIN_H */

83
doom/deh_misc.h Normal file
View file

@ -0,0 +1,83 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// Parses "Misc" sections in dehacked files
//
#ifndef DEH_MISC_H
#define DEH_MISC_H
#include "doomfeatures.h"
#define DEH_DEFAULT_INITIAL_HEALTH 100
#define DEH_DEFAULT_INITIAL_BULLETS 50
#define DEH_DEFAULT_MAX_HEALTH 200
#define DEH_DEFAULT_MAX_ARMOR 200
#define DEH_DEFAULT_GREEN_ARMOR_CLASS 1
#define DEH_DEFAULT_BLUE_ARMOR_CLASS 2
#define DEH_DEFAULT_MAX_SOULSPHERE 200
#define DEH_DEFAULT_SOULSPHERE_HEALTH 100
#define DEH_DEFAULT_MEGASPHERE_HEALTH 200
#define DEH_DEFAULT_GOD_MODE_HEALTH 100
#define DEH_DEFAULT_IDFA_ARMOR 200
#define DEH_DEFAULT_IDFA_ARMOR_CLASS 2
#define DEH_DEFAULT_IDKFA_ARMOR 200
#define DEH_DEFAULT_IDKFA_ARMOR_CLASS 2
#define DEH_DEFAULT_BFG_CELLS_PER_SHOT 40
#define DEH_DEFAULT_SPECIES_INFIGHTING 0
#ifdef FEATURE_DEHACKED
extern int deh_initial_health;
extern int deh_initial_bullets;
extern int deh_max_health;
extern int deh_max_armor;
extern int deh_green_armor_class;
extern int deh_blue_armor_class;
extern int deh_max_soulsphere;
extern int deh_soulsphere_health;
extern int deh_megasphere_health;
extern int deh_god_mode_health;
extern int deh_idfa_armor;
extern int deh_idfa_armor_class;
extern int deh_idkfa_armor;
extern int deh_idkfa_armor_class;
extern int deh_bfg_cells_per_shot;
extern int deh_species_infighting;
#else
// If dehacked is disabled, hard coded values
#define deh_initial_health DEH_DEFAULT_INITIAL_HEALTH
#define deh_initial_bullets DEH_DEFAULT_INITIAL_BULLETS
#define deh_max_health DEH_DEFAULT_MAX_HEALTH
#define deh_max_armor DEH_DEFAULT_MAX_ARMOR
#define deh_green_armor_class DEH_DEFAULT_GREEN_ARMOR_CLASS
#define deh_blue_armor_class DEH_DEFAULT_BLUE_ARMOR_CLASS
#define deh_max_soulsphere DEH_DEFAULT_MAX_SOULSPHERE
#define deh_soulsphere_health DEH_DEFAULT_SOULSPHERE_HEALTH
#define deh_megasphere_health DEH_DEFAULT_MEGASPHERE_HEALTH
#define deh_god_mode_health DEH_DEFAULT_GOD_MODE_HEALTH
#define deh_idfa_armor DEH_DEFAULT_IDFA_ARMOR
#define deh_idfa_armor_class DEH_DEFAULT_IDFA_ARMOR_CLASS
#define deh_idkfa_armor DEH_DEFAULT_IDKFA_ARMOR
#define deh_idkfa_armor_class DEH_DEFAULT_IDKFA_ARMOR_CLASS
#define deh_bfg_cells_per_shot DEH_DEFAULT_BFG_CELLS_PER_SHOT
#define deh_species_infighting DEH_DEFAULT_SPECIES_INFIGHTING
#endif
#endif /* #ifndef DEH_MISC_H */

47
doom/deh_str.h Normal file
View file

@ -0,0 +1,47 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// Dehacked string replacements
//
#ifndef DEH_STR_H
#define DEH_STR_H
#include <stdio.h>
#include "doomfeatures.h"
// Used to do dehacked text substitutions throughout the program
#ifdef FEATURE_DEHACKED
char *DEH_String(char *s);
void DEH_printf(char *fmt, ...);
void DEH_fprintf(FILE *fstream, char *fmt, ...);
void DEH_snprintf(char *buffer, size_t len, char *fmt, ...);
void DEH_AddStringReplacement(char *from_text, char *to_text);
#else
#define DEH_String(x) (x)
#define DEH_printf printf
#define DEH_fprintf fprintf
#define DEH_snprintf snprintf
#define DEH_AddStringReplacement(x, y)
#endif
#endif /* #ifndef DEH_STR_H */

42
doom/doom.h Normal file
View file

@ -0,0 +1,42 @@
/*
* doom.h
*
* Created on: 18.02.2015
* Author: Florian
*/
#ifndef SRC_CHOCDOOM_DOOM_H_
#define SRC_CHOCDOOM_DOOM_H_
/*---------------------------------------------------------------------*
* additional includes *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* global definitions *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* type declarations *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* function prototypes *
*---------------------------------------------------------------------*/
void D_DoomMain (void);
/*---------------------------------------------------------------------*
* global data *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* inline functions and function-like macros *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* eof *
*---------------------------------------------------------------------*/
#endif /* SRC_CHOCDOOM_DOOM_H_ */

213
doom/doomdata.h Normal file
View file

@ -0,0 +1,213 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// all external data is defined here
// most of the data is loaded into different structures at run time
// some internal structures shared by many modules are here
//
#ifndef __DOOMDATA__
#define __DOOMDATA__
// The most basic types we use, portability.
#include "doomtype.h"
// Some global defines, that configure the game.
#include "doomdef.h"
//
// Map level types.
// The following data structures define the persistent format
// used in the lumps of the WAD files.
//
// Lump order in a map WAD: each map needs a couple of lumps
// to provide a complete scene geometry description.
enum
{
ML_LABEL, // A separator, name, ExMx or MAPxx
ML_THINGS, // Monsters, items..
ML_LINEDEFS, // LineDefs, from editing
ML_SIDEDEFS, // SideDefs, from editing
ML_VERTEXES, // Vertices, edited and BSP splits generated
ML_SEGS, // LineSegs, from LineDefs split by BSP
ML_SSECTORS, // SubSectors, list of LineSegs
ML_NODES, // BSP nodes
ML_SECTORS, // Sectors, from editing
ML_REJECT, // LUT, sector-sector visibility
ML_BLOCKMAP // LUT, motion clipping, walls/grid element
};
// A single Vertex.
typedef struct
{
short x;
short y;
} PACKEDATTR mapvertex_t;
// A SideDef, defining the visual appearance of a wall,
// by setting textures and offsets.
typedef struct
{
short textureoffset;
short rowoffset;
char toptexture[8];
char bottomtexture[8];
char midtexture[8];
// Front sector, towards viewer.
short sector;
} PACKEDATTR mapsidedef_t;
// A LineDef, as used for editing, and as input
// to the BSP builder.
typedef struct
{
short v1;
short v2;
short flags;
short special;
short tag;
// sidenum[1] will be -1 if one sided
short sidenum[2];
} PACKEDATTR maplinedef_t;
//
// LineDef attributes.
//
// Solid, is an obstacle.
#define ML_BLOCKING 1
// Blocks monsters only.
#define ML_BLOCKMONSTERS 2
// Backside will not be present at all
// if not two sided.
#define ML_TWOSIDED 4
// If a texture is pegged, the texture will have
// the end exposed to air held constant at the
// top or bottom of the texture (stairs or pulled
// down things) and will move with a height change
// of one of the neighbor sectors.
// Unpegged textures allways have the first row of
// the texture at the top pixel of the line for both
// top and bottom textures (use next to windows).
// upper texture unpegged
#define ML_DONTPEGTOP 8
// lower texture unpegged
#define ML_DONTPEGBOTTOM 16
// In AutoMap: don't map as two sided: IT'S A SECRET!
#define ML_SECRET 32
// Sound rendering: don't let sound cross two of these.
#define ML_SOUNDBLOCK 64
// Don't draw on the automap at all.
#define ML_DONTDRAW 128
// Set if already seen, thus drawn in automap.
#define ML_MAPPED 256
// Sector definition, from editing.
typedef struct
{
short floorheight;
short ceilingheight;
char floorpic[8];
char ceilingpic[8];
short lightlevel;
short special;
short tag;
} PACKEDATTR mapsector_t;
// SubSector, as generated by BSP.
typedef struct
{
short numsegs;
// Index of first one, segs are stored sequentially.
short firstseg;
} PACKEDATTR mapsubsector_t;
// LineSeg, generated by splitting LineDefs
// using partition lines selected by BSP builder.
typedef struct
{
short v1;
short v2;
short angle;
short linedef;
short side;
short offset;
} PACKEDATTR mapseg_t;
// BSP node structure.
// Indicate a leaf.
#define NF_SUBSECTOR 0x8000
typedef struct
{
// Partition line from (x,y) to x+dx,y+dy)
short x;
short y;
short dx;
short dy;
// Bounding box for each child,
// clip against view frustum.
short bbox[2][4];
// If NF_SUBSECTOR its a subsector,
// else it's a node of another subtree.
unsigned short children[2];
} PACKEDATTR mapnode_t;
// Thing definition, position, orientation and type,
// plus skill/visibility flags and attributes.
typedef struct
{
short x;
short y;
short angle;
short type;
short options;
} PACKEDATTR mapthing_t;
#endif // __DOOMDATA__

28
doom/doomdef.c Normal file
View file

@ -0,0 +1,28 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// DoomDef - basic defines for DOOM, e.g. Version, game mode
// and skill level, and display parameters.
//
#include "doomdef.h"
// Location for any defines turned variables.
// None.

168
doom/doomdef.h Normal file
View file

@ -0,0 +1,168 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Internally used data structures for virtually everything,
// lots of other stuff.
//
#ifndef __DOOMDEF__
#define __DOOMDEF__
#include <stdio.h>
#include <string.h>
#include "doomtype.h"
#include "i_timer.h"
#include "d_mode.h"
//
// Global parameters/defines.
//
// DOOM version
#define DOOM_VERSION 109
// Version code for cph's longtics hack ("v1.91")
#define DOOM_191_VERSION 111
// If rangecheck is undefined,
// most parameter validation debugging code will not be compiled
#define RANGECHECK
// The maximum number of players, multiplayer/networking.
#define MAXPLAYERS 4
// The current state of the game: whether we are
// playing, gazing at the intermission screen,
// the game final animation, or a demo.
typedef enum
{
GS_LEVEL,
GS_INTERMISSION,
GS_FINALE,
GS_DEMOSCREEN,
} gamestate_t;
typedef enum
{
ga_nothing,
ga_loadlevel,
ga_newgame,
ga_loadgame,
ga_savegame,
ga_playdemo,
ga_completed,
ga_victory,
ga_worlddone,
ga_screenshot
} gameaction_t;
//
// Difficulty/skill settings/filters.
//
// Skill flags.
#define MTF_EASY 1
#define MTF_NORMAL 2
#define MTF_HARD 4
// Deaf monsters/do not react to sound.
#define MTF_AMBUSH 8
//
// Key cards.
//
typedef enum
{
it_bluecard,
it_yellowcard,
it_redcard,
it_blueskull,
it_yellowskull,
it_redskull,
NUMCARDS
} card_t;
// The defined weapons,
// including a marker indicating
// user has not changed weapon.
typedef enum
{
wp_fist,
wp_pistol,
wp_shotgun,
wp_chaingun,
wp_missile,
wp_plasma,
wp_bfg,
wp_chainsaw,
wp_supershotgun,
NUMWEAPONS,
// No pending weapon change.
wp_nochange
} weapontype_t;
// Ammunition types defined.
typedef enum
{
am_clip, // Pistol / chaingun ammo.
am_shell, // Shotgun / double barreled shotgun.
am_cell, // Plasma rifle, BFG.
am_misl, // Missile launcher.
NUMAMMO,
am_noammo // Unlimited for chainsaw / fist.
} ammotype_t;
// Power up artifacts.
typedef enum
{
pw_invulnerability,
pw_strength,
pw_invisibility,
pw_ironfeet,
pw_allmap,
pw_infrared,
NUMPOWERS
} powertype_t;
//
// Power up durations,
// how many seconds till expiration,
// assuming TICRATE is 35 ticks/second.
//
typedef enum
{
INVULNTICS = (30*TICRATE),
INVISTICS = (60*TICRATE),
INFRATICS = (120*TICRATE),
IRONTICS = (60*TICRATE)
} powerduration_t;
#endif // __DOOMDEF__

40
doom/doomfeatures.h Normal file
View file

@ -0,0 +1,40 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// List of features which can be enabled/disabled to slim down the
// program.
//
#ifndef DOOM_FEATURES_H
#define DOOM_FEATURES_H
// Enables wad merging (the '-merge' command line parameter)
#undef FEATURE_WAD_MERGE
// Enables dehacked support ('-deh')
#undef FEATURE_DEHACKED
// Enables multiplayer support (network games)
#undef FEATURE_MULTIPLAYER
// Enables sound output
//#undef FEATURE_SOUND
#endif /* #ifndef DOOM_FEATURES_H */

9
doom/doomgeneric.c Normal file
View file

@ -0,0 +1,9 @@
#include "doomgeneric.h"
#include "pasriscv_config.h"
uint8_t *DG_ScreenBuffer = 0;
void dg_Create()
{
DG_Init();
}

20
doom/doomgeneric.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef DOOM_GENERIC
#define DOOM_GENERIC
#include <stdlib.h>
#include <stdint.h>
extern int DOOMGENERIC_RESX;
extern int DOOMGENERIC_RESY;
extern int DOOMGENERIC_CHANNELS;
extern uint8_t *DG_ScreenBuffer;
void DG_Init();
void DG_DrawFrame();
void DG_SleepMs(uint32_t ms);
uint32_t DG_GetTicksMs();
int DG_GetKey(int *pressed, unsigned char *key);
void DG_SetWindowTitle(const char *title);
#endif // DOOM_GENERIC

487
doom/doomgeneric_pasriscv.c Normal file
View file

@ -0,0 +1,487 @@
#include "doomkeys.h"
#include "m_argv.h"
#include "doomgeneric.h"
#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <stdbool.h>
#include "pasriscv_config.h"
#if LINUX_TARGET
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <termios.h>
static struct termios old_term;
#endif
#define TARGET_RESX 320
#define TARGET_RESY 200
#define TARGET_CHANNELS 3
#define RESET_RESX 640
#define RESET_RESY 400
#define RESET_CHANNELS 3
int DOOMGENERIC_RESX;
int DOOMGENERIC_RESY;
int DOOMGENERIC_CHANNELS;
volatile unsigned char *DOOMGENERIC_FB;
static int old_resx;
static int old_resy;
static volatile unsigned char *fb_active;
static volatile unsigned char *fb_dimensions;
static volatile unsigned char *fb_channels;
//static volatile unsigned char *term_dimensions;
static volatile unsigned char *fb_render;
static volatile unsigned char *uart_read;
static volatile uint32_t *rawkeyboard;
//static int term_cols;
//static int term_rows;
void set_fb_active(uint64_t state){
*(uint32_t *)fb_active = state;
}
void get_fb_info()
{
uint32_t resolution = *(uint32_t *)fb_dimensions;
DOOMGENERIC_RESX = resolution & 0xffff;
DOOMGENERIC_RESY = (resolution >> 16) & 0xffff;
DOOMGENERIC_CHANNELS = *fb_channels;
}
/*
void set_terminal_resolution(uint64_t cols, uint64_t rows)
{
*(uint32_t *)term_dimensions = (rows << 16) | cols;
}
void get_terminal_resolution(void)
{
uint32_t dimensions = *(uint32_t *)term_dimensions;
term_cols = dimensions & 0xffff;
term_rows = (dimensions >> 16) & 0xffff;
}
*/
void set_resolution(uint64_t width, uint64_t height)
{
*(uint32_t *)fb_dimensions = (height << 16) | width;
}
#if LINUX_TARGET
void cleanup(void)
{
tcsetattr(0, TCSAFLUSH, &old_term);
set_resolution(old_resx, old_resy);
//set_terminal_resolution(term_cols, term_rows);
set_fb_active(7);
printf("\033[2J\033[H");
}
#endif
void DG_Init()
{
#if LINUX_TARGET
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd < 0) {
perror("Failed to open /dev/mem");
exit(1);
}
void *fb_render_addr_ptr = (void *)((off_t)(fb_render_addr));
printf("Opened /dev/mem at address %p\n", fb_render_addr_ptr);
fb_render = mmap(NULL, 0x1000 + TARGET_RESX * TARGET_RESY * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ((off_t)(fb_render_addr)));
if (fb_dimensions == MAP_FAILED) {
perror("Failed to mmap fb_dimensions");
exit(1);
}
uart_read = mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ((off_t)(uart_read_addr)));
if (fb_dimensions == MAP_FAILED) {
perror("Failed to mmap uart_read");
exit(1);
}
rawkeyboard = mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ((off_t)(0x10008000)));
if (rawkeyboard == MAP_FAILED) {
perror("Failed to mmap rawkeyboard");
exit(1);
}
fb_active = fb_render + 1 * sizeof(uint32_t);
fb_dimensions = fb_render + 2 * sizeof(uint32_t);
fb_channels = fb_render + 3 * sizeof(uint32_t);
DOOMGENERIC_FB = fb_render + 0x1000;
close(fd);
struct termios term;
tcgetattr(0, &term);
tcgetattr(0, &old_term);
term.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSAFLUSH, &term);
get_fb_info();
old_resx = DOOMGENERIC_RESX;
old_resy = DOOMGENERIC_RESY;
//get_terminal_resolution();
atexit(cleanup);
at_quick_exit(cleanup);
#else
fb_active = fb_active_addr;
fb_dimensions = fb_dimensions_addr;
fb_channels = fb_channels_addr;
fb_render = fb_render_addr;
uart_read = uart_read_addr;
rawkeyboard = (uint32_t *)0x10008000;
DOOMGENERIC_FB = framebuffer_start_addr;
#endif
set_resolution(TARGET_RESX, TARGET_RESY);
get_fb_info();
set_fb_active(1);
//set_terminal_resolution(40, 16);
}
void DG_DrawFrame()
{
*fb_render = 1;
}
void DG_SleepMs(uint32_t ms)
{
uint32_t start = DG_GetTicksMs();
while (DG_GetTicksMs() < start + ms)
{
}
}
uint32_t DG_GetTicksMs()
{
uint64_t result;
asm volatile("rdtime %0;"
: "=r"(result));
return result / 1000;
}
typedef struct
{
int host_key;
int doom_key;
int state;
} key;
key keys[] = {
{.host_key = 302,
.doom_key = KEY_HOME},
{.host_key = 303,
.doom_key = KEY_END},
{.host_key = 304,
.doom_key = KEY_PGUP},
{.host_key = 305,
.doom_key = KEY_PGDN},
{.host_key = 306,
.doom_key = KEY_CAPSLOCK},
{.host_key = 307,
.doom_key = KEY_NUMLOCK},
{.host_key = 308,
.doom_key = KEY_SCRLCK},
{.host_key = 317,
.doom_key = KEY_PRTSCR},
{.host_key = 291,
.doom_key = '/'},
{.host_key = 292,
.doom_key = '*'},
{.host_key = 293,
.doom_key = '-'},
{.host_key = 294,
.doom_key = '+'},
{.host_key = 102,
.doom_key = 'f'},
{.host_key = 109,
.doom_key = 'm'},
{.host_key = 295,
.doom_key = KEY_ENTER},
{.host_key = 296,
.doom_key = KEY_EQUALS},
{.host_key = 61,
.doom_key = KEY_EQUALS},
{.host_key = 43,
.doom_key = '+'},
{.host_key = 45,
.doom_key = '-'},
{.host_key = 9,
.doom_key = KEY_TAB},
{.host_key = 177,
.doom_key = KEY_DEL},
{.host_key = 301,
.doom_key = KEY_INS},
{.host_key = 256,
.doom_key = KEY_F1},
{.host_key = 257,
.doom_key = KEY_F2},
{.host_key = 258,
.doom_key = KEY_F3},
{.host_key = 259,
.doom_key = KEY_F4},
{.host_key = 260,
.doom_key = KEY_F5},
{.host_key = 262,
.doom_key = KEY_F6},
{.host_key = 263,
.doom_key = KEY_F7},
{.host_key = 264,
.doom_key = KEY_F8},
{.host_key = 265,
.doom_key = KEY_F9},
{.host_key = 266,
.doom_key = KEY_F10},
{.host_key = 267,
.doom_key = KEY_F11},
{.host_key = 268,
.doom_key = KEY_F12},
{.host_key = 119,//'W',
.doom_key = KEY_UPARROW},
{.host_key = 297,
.doom_key = KEY_UPARROW},
{.host_key = 97,//'A',
.doom_key = KEY_LEFTARROW},
{.host_key = 300,
.doom_key = KEY_LEFTARROW},
{.host_key = 115,//'S',
.doom_key = KEY_DOWNARROW},
{.host_key = 298,
.doom_key = KEY_DOWNARROW},
{.host_key = 100,//'D',
.doom_key = KEY_RIGHTARROW},
{.host_key = 299,
.doom_key = KEY_RIGHTARROW},
{.host_key = 284, // KP_4
.doom_key = KEY_STRAFE_L},
{ .host_key = 286, // KP_6
.doom_key = KEY_STRAFE_R},
{.host_key = 111,//'O',
.doom_key = KEY_ENTER},
{.host_key = 13,//'O',
.doom_key = KEY_ENTER},
{.host_key = 32,//' ',
.doom_key = KEY_USE},
{.host_key = 311,// CTRL
.doom_key = KEY_FIRE},
{.host_key = 98, // B
.doom_key = KEY_FIRE},
{.host_key = 101,//'E',
.doom_key = KEY_USE},
{.host_key = 113,//'Q',
.doom_key = KEY_ESCAPE},
{.host_key = 27,//'Q',
.doom_key = KEY_ESCAPE},
{.host_key = 121,//'Y',
.doom_key = 'y'},
{.host_key = 110,//'N',
.doom_key = 'n'},
{.host_key = 112, // P
.doom_key = -1},
{.host_key = 19,
.doom_key = -1},
{.host_key = 48, // 0
.doom_key = '0'},
{.host_key = 49, // 1
.doom_key = '1'},
{.host_key = 50, // 2
.doom_key = '2'},
{.host_key = 51, // 3
.doom_key = '3'},
{.host_key = 52, // 4
.doom_key = '4'},
{.host_key = 53, // 5
.doom_key = '5'},
{.host_key = 54, // 6
.doom_key = '6'},
{.host_key = 309,
.doom_key = KEY_RSHIFT},
{.host_key = 310,
.doom_key = KEY_RSHIFT}, // actually LSHIFT, but doom doesn't care
{.host_key = 311,
.doom_key = KEY_RCTRL},
{.host_key = 312,
.doom_key = KEY_RCTRL}, // actually LCTRL, but doom doesn't care
{.host_key = 313,
.doom_key = KEY_RALT},
{.host_key = 314,
.doom_key = KEY_RALT } // actually LALT, but doom doesn't care
};
const int keys_size = sizeof(keys) / sizeof(keys[0]);
int speed_toggle = 0;
int DG_GetKey(int *pressed, unsigned char *doomKey)
{
for (int i = 0; i < keys_size; i++){
uint32_t keyCode = keys[i].host_key;
uint32_t k = rawkeyboard[keyCode >> 5u];
uint32_t mask = 1u << (keyCode & 0x1fu);
if(((k & mask) != 0) && (keys[i].state == 0)){
if (keys[i].doom_key == -1){
speed_toggle = !speed_toggle;
return 0;
}
*doomKey = keys[i].doom_key;
*pressed = 1;
keys[i].state = 1;
return 1;
}else if (((k & mask) == 0) && (keys[i].state == 1)){
if (keys[i].doom_key == -1){
return 0;
}
*doomKey = keys[i].doom_key;
*pressed = 0;
keys[i].state = 0;
return 1;
}
}
/*
char c;
c = *uart_read;
c = toupper(c);
for (int i = 0; i < keys_size; i++)
{
if (keys[i].state == 1)
{
if (keys[i].host_key == c)
{
continue;
}
else
{
keys[i].state = 0;
if (c == 'P')
{
return 0;
}
else
{
*doomKey = keys[i].doom_key;
*pressed = 0;
return 1;
}
}
}
else if (keys[i].host_key == c)
{
keys[i].state = 1;
if (c == 'P')
{
speed_toggle = !speed_toggle;
return 0;
}
else
{
*doomKey = keys[i].doom_key;
*pressed = 1;
return 1;
}
}
}
*/
return 0;
}
void DG_SetWindowTitle(const char *title)
{
}

97
doom/doomkeys.h Normal file
View file

@ -0,0 +1,97 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Key definitions
//
#ifndef __DOOMKEYS__
#define __DOOMKEYS__
//
// DOOM keyboard definition.
// This is the stuff configured by Setup.Exe.
// Most key data are simple ascii (uppercased).
//
#define KEY_RIGHTARROW 0xae
#define KEY_LEFTARROW 0xac
#define KEY_UPARROW 0xad
#define KEY_DOWNARROW 0xaf
#define KEY_STRAFE_L 0xa0
#define KEY_STRAFE_R 0xa1
#define KEY_USE 0xa2
#define KEY_FIRE 0xa3
#define KEY_ESCAPE 27
#define KEY_ENTER 13
#define KEY_TAB 9
#define KEY_F1 (0x80+0x3b)
#define KEY_F2 (0x80+0x3c)
#define KEY_F3 (0x80+0x3d)
#define KEY_F4 (0x80+0x3e)
#define KEY_F5 (0x80+0x3f)
#define KEY_F6 (0x80+0x40)
#define KEY_F7 (0x80+0x41)
#define KEY_F8 (0x80+0x42)
#define KEY_F9 (0x80+0x43)
#define KEY_F10 (0x80+0x44)
#define KEY_F11 (0x80+0x57)
#define KEY_F12 (0x80+0x58)
#define KEY_BACKSPACE 0x7f
#define KEY_PAUSE 0xff
#define KEY_EQUALS 0x3d
#define KEY_MINUS 0x2d
#define KEY_RSHIFT (0x80+0x36)
#define KEY_RCTRL (0x80+0x1d)
#define KEY_RALT (0x80+0x38)
#define KEY_LALT KEY_RALT
// new keys:
#define KEY_CAPSLOCK (0x80+0x3a)
#define KEY_NUMLOCK (0x80+0x45)
#define KEY_SCRLCK (0x80+0x46)
#define KEY_PRTSCR (0x80+0x59)
#define KEY_HOME (0x80+0x47)
#define KEY_END (0x80+0x4f)
#define KEY_PGUP (0x80+0x49)
#define KEY_PGDN (0x80+0x51)
#define KEY_INS (0x80+0x52)
#define KEY_DEL (0x80+0x53)
#define KEYP_0 0
#define KEYP_1 KEY_END
#define KEYP_2 KEY_DOWNARROW
#define KEYP_3 KEY_PGDN
#define KEYP_4 KEY_LEFTARROW
#define KEYP_5 '5'
#define KEYP_6 KEY_RIGHTARROW
#define KEYP_7 KEY_HOME
#define KEYP_8 KEY_UPARROW
#define KEYP_9 KEY_PGUP
#define KEYP_DIVIDE '/'
#define KEYP_PLUS '+'
#define KEYP_MINUS '-'
#define KEYP_MULTIPLY '*'
#define KEYP_PERIOD 0
#define KEYP_EQUALS KEY_EQUALS
#define KEYP_ENTER KEY_ENTER
#endif // __DOOMKEYS__

35
doom/doomstat.c Normal file
View file

@ -0,0 +1,35 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Put all global tate variables here.
//
#include <stdio.h>
#include "doomstat.h"
// Game Mode - identify IWAD as shareware, retail etc.
GameMode_t gamemode = indetermined;
GameMission_t gamemission = doom;
GameVersion_t gameversion = exe_final2;
char *gamedescription;
// Set if homebrew PWAD stuff has been added.
boolean modifiedgame;

281
doom/doomstat.h Normal file
View file

@ -0,0 +1,281 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// All the global variables that store the internal state.
// Theoretically speaking, the internal state of the engine
// should be found by looking at the variables collected
// here, and every relevant module will have to include
// this header file.
// In practice, things are a bit messy.
//
#ifndef __D_STATE__
#define __D_STATE__
// We need globally shared data structures,
// for defining the global state variables.
#include "doomdata.h"
#include "d_loop.h"
// We need the playr data structure as well.
#include "d_player.h"
// Game mode/mission
#include "d_mode.h"
#include "net_defs.h"
// ------------------------
// Command line parameters.
//
extern boolean nomonsters; // checkparm of -nomonsters
extern boolean respawnparm; // checkparm of -respawn
extern boolean fastparm; // checkparm of -fast
extern boolean devparm; // DEBUG: launched with -devparm
// -----------------------------------------------------
// Game Mode - identify IWAD as shareware, retail etc.
//
extern GameMode_t gamemode;
extern GameMission_t gamemission;
extern GameVersion_t gameversion;
extern char *gamedescription;
// If true, we're using one of the mangled BFG edition IWADs.
extern boolean bfgedition;
// Convenience macro.
// 'gamemission' can be equal to pack_chex or pack_hacx, but these are
// just modified versions of doom and doom2, and should be interpreted
// as the same most of the time.
#define logical_gamemission \
(gamemission == pack_chex ? doom : \
gamemission == pack_hacx ? doom2 : gamemission)
// Set if homebrew PWAD stuff has been added.
extern boolean modifiedgame;
// -------------------------------------------
// Selected skill type, map etc.
//
// Defaults for menu, methinks.
extern skill_t startskill;
extern int startepisode;
extern int startmap;
// Savegame slot to load on startup. This is the value provided to
// the -loadgame option. If this has not been provided, this is -1.
extern int startloadgame;
extern boolean autostart;
// Selected by user.
extern skill_t gameskill;
extern int gameepisode;
extern int gamemap;
// If non-zero, exit the level after this number of minutes
extern int timelimit;
// Nightmare mode flag, single player.
extern boolean respawnmonsters;
// Netgame? Only true if >1 player.
extern boolean netgame;
// 0=Cooperative; 1=Deathmatch; 2=Altdeath
extern int deathmatch;
// -------------------------
// Internal parameters for sound rendering.
// These have been taken from the DOS version,
// but are not (yet) supported with Linux
// (e.g. no sound volume adjustment with menu.
// From m_menu.c:
// Sound FX volume has default, 0 - 15
// Music volume has default, 0 - 15
// These are multiplied by 8.
extern int sfxVolume;
extern int musicVolume;
// Current music/sfx card - index useless
// w/o a reference LUT in a sound module.
// Ideally, this would use indices found
// in: /usr/include/linux/soundcard.h
extern int snd_MusicDevice;
extern int snd_SfxDevice;
// Config file? Same disclaimer as above.
extern int snd_DesiredMusicDevice;
extern int snd_DesiredSfxDevice;
// -------------------------
// Status flags for refresh.
//
// Depending on view size - no status bar?
// Note that there is no way to disable the
// status bar explicitely.
extern boolean statusbaractive;
extern boolean automapactive; // In AutoMap mode?
extern boolean menuactive; // Menu overlayed?
extern boolean paused; // Game Pause?
extern boolean viewactive;
extern boolean nodrawers;
extern boolean testcontrols;
extern int testcontrols_mousespeed;
// This one is related to the 3-screen display mode.
// ANG90 = left side, ANG270 = right
extern int viewangleoffset;
// Player taking events, and displaying.
extern int consoleplayer;
extern int displayplayer;
// -------------------------------------
// Scores, rating.
// Statistics on a given map, for intermission.
//
extern int totalkills;
extern int totalitems;
extern int totalsecret;
// Timer, for scores.
extern int levelstarttic; // gametic at level start
extern int leveltime; // tics in game play for par
// --------------------------------------
// DEMO playback/recording related stuff.
// No demo, there is a human player in charge?
// Disable save/end game?
extern boolean usergame;
//?
extern boolean demoplayback;
extern boolean demorecording;
// Round angleturn in ticcmds to the nearest 256. This is used when
// recording Vanilla demos in netgames.
extern boolean lowres_turn;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
//?
extern gamestate_t gamestate;
//-----------------------------
// Internal parameters, fixed.
// These are set by the engine, and not changed
// according to user inputs. Partly load from
// WAD, partly set at startup time.
// Bookkeeping on players - state.
extern player_t players[MAXPLAYERS];
// Alive? Disconnected?
extern boolean playeringame[MAXPLAYERS];
// Player spawn spots for deathmatch.
#define MAX_DM_STARTS 10
extern mapthing_t deathmatchstarts[MAX_DM_STARTS];
extern mapthing_t* deathmatch_p;
// Player spawn spots.
extern mapthing_t playerstarts[MAXPLAYERS];
// Intermission stats.
// Parameters for world map / intermission.
extern wbstartstruct_t wminfo;
//-----------------------------------------
// Internal parameters, used for engine.
//
// File handling stuff.
extern char * savegamedir;
extern char basedefault[1024];
// if true, load all graphics at level load
extern boolean precache;
// wipegamestate can be set to -1
// to force a wipe on the next draw
extern gamestate_t wipegamestate;
extern int mouseSensitivity;
extern int bodyqueslot;
// Needed to store the number of the dummy sky flat.
// Used for rendering,
// as well as tracking projectiles etc.
extern int skyflatnum;
// Netgame stuff (buffers and pointers, i.e. indices).
extern int rndindex;
extern ticcmd_t *netcmds;
#endif

103
doom/doomtype.h Normal file
View file

@ -0,0 +1,103 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Simple basic typedefs, isolated here to make it easier
// separating modules.
//
#ifndef __DOOMTYPE__
#define __DOOMTYPE__
// #define macros to provide functions missing in Windows.
// Outside Windows, we use strings.h for str[n]casecmp.
#ifdef _WIN32
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#else
#include <strings.h>
#endif
//
// The packed attribute forces structures to be packed into the minimum
// space necessary. If this is not done, the compiler may align structure
// fields differently to optimize memory access, inflating the overall
// structure size. It is important to use the packed attribute on certain
// structures where alignment is important, particularly data read/written
// to disk.
//
#ifdef __GNUC__
#define PACKEDATTR __attribute__((packed))
#else
#define PACKEDATTR
#endif
// C99 integer types; with gcc we just use this. Other compilers
// should add conditional statements that define the C99 types.
// What is really wanted here is stdint.h; however, some old versions
// of Solaris don't have stdint.h and only have inttypes.h (the
// pre-standardisation version). inttypes.h is also in the C99
// standard and defined to include stdint.h, so include this.
#include <inttypes.h>
#ifdef __cplusplus
// Use builtin bool type with C++.
typedef bool boolean;
#else
typedef enum
{
false = 0,
true = 1,
undef = 0xFFFFFFFF
} boolean;
#endif
typedef uint8_t byte;
#include <limits.h>
#ifdef _WIN32
#define DIR_SEPARATOR '\\'
#define DIR_SEPARATOR_S "\\"
#define PATH_SEPARATOR ';'
#else
#define DIR_SEPARATOR '/'
#define DIR_SEPARATOR_S "/"
#define PATH_SEPARATOR ':'
#endif
#define arrlen(array) (sizeof(array) / sizeof(*array))
#endif

73
doom/dstrings.c Normal file
View file

@ -0,0 +1,73 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Globally defined strings.
//
#include "dstrings.h"
char *doom1_endmsg[] =
{
"are you sure you want to\nquit this great game?",
"please don't leave, there's more\ndemons to toast!",
"let's beat it -- this is turning\ninto a bloodbath!",
"i wouldn't leave if i were you.\ndos is much worse.",
"you're trying to say you like dos\nbetter than me, right?",
"don't leave yet -- there's a\ndemon around that corner!",
"ya know, next time you come in here\ni'm gonna toast ya.",
"go ahead and leave. see if i care.",
};
char *doom2_endmsg[] =
{
// QuitDOOM II messages
"are you sure you want to\nquit this great game?",
"you want to quit?\nthen, thou hast lost an eighth!",
"don't go now, there's a \ndimensional shambler waiting\nat the dos prompt!",
"get outta here and go back\nto your boring programs.",
"if i were your boss, i'd \n deathmatch ya in a minute!",
"look, bud. you leave now\nand you forfeit your body count!",
"just leave. when you come\nback, i'll be waiting with a bat.",
"you're lucky i don't smack\nyou for thinking about leaving.",
};
#if 0
// UNUSED messages included in the source release
char* endmsg[] =
{
// DOOM1
QUITMSG,
// FinalDOOM?
"fuck you, pussy!\nget the fuck out!",
"you quit and i'll jizz\nin your cystholes!",
"if you leave, i'll make\nthe lord drink my jizz.",
"hey, ron! can we say\n'fuck' in the game?",
"i'd leave: this is just\nmore monsters and levels.\nwhat a load.",
"suck it down, asshole!\nyou're a fucking wimp!",
"don't quit now! we're \nstill spending your money!",
// Internal debug. Different style, too.
"THIS IS NO MESSAGE!\nPage intentionally left blank."
};
#endif

41
doom/dstrings.h Normal file
View file

@ -0,0 +1,41 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
//
// DESCRIPTION:
// DOOM strings, by language.
//
#ifndef __DSTRINGS__
#define __DSTRINGS__
// All important printed strings.
#include "d_englsh.h"
// Misc. other strings.
#define SAVEGAMENAME "doomsav"
// QuitDOOM messages
// 8 per each game type
#define NUM_QUITMESSAGES 8
extern char *doom1_endmsg[];
extern char *doom2_endmsg[];
#endif

53
doom/dummy.c Normal file
View file

@ -0,0 +1,53 @@
/*
* dummy.c
*
* Created on: 16.02.2015
* Author: Florian
*/
/*---------------------------------------------------------------------*
* include files *
*---------------------------------------------------------------------*/
#include "doomtype.h"
/*---------------------------------------------------------------------*
* local definitions *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* external declarations *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* public data *
*---------------------------------------------------------------------*/
boolean net_client_connected = false;
boolean drone = false;
/*---------------------------------------------------------------------*
* private data *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* private functions *
*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*
* public functions *
*---------------------------------------------------------------------*/
#ifndef FEATURE_SOUND
void I_InitTimidityConfig(void)
{
}
#endif
/*---------------------------------------------------------------------*
* eof *
*---------------------------------------------------------------------*/

718
doom/f_finale.c Normal file
View file

@ -0,0 +1,718 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Game completion, final screen animation.
//
#include <stdio.h>
#include <ctype.h>
// Functions.
#include "deh_main.h"
#include "i_system.h"
#include "i_swap.h"
#include "z_zone.h"
#include "v_video.h"
#include "w_wad.h"
#include "s_sound.h"
// Data.
#include "d_main.h"
#include "dstrings.h"
#include "sounds.h"
#include "doomstat.h"
#include "r_state.h"
typedef enum
{
F_STAGE_TEXT,
F_STAGE_ARTSCREEN,
F_STAGE_CAST,
} finalestage_t;
// ?
//#include "doomstat.h"
//#include "r_local.h"
//#include "f_finale.h"
// Stage of animation:
finalestage_t finalestage;
unsigned int finalecount;
#define TEXTSPEED 3
#define TEXTWAIT 250
typedef struct
{
GameMission_t mission;
int episode, level;
char *background;
char *text;
} textscreen_t;
static textscreen_t textscreens[] =
{
{ doom, 1, 8, "FLOOR4_8", E1TEXT},
{ doom, 2, 8, "SFLR6_1", E2TEXT},
{ doom, 3, 8, "MFLR8_4", E3TEXT},
{ doom, 4, 8, "MFLR8_3", E4TEXT},
{ doom2, 1, 6, "SLIME16", C1TEXT},
{ doom2, 1, 11, "RROCK14", C2TEXT},
{ doom2, 1, 20, "RROCK07", C3TEXT},
{ doom2, 1, 30, "RROCK17", C4TEXT},
{ doom2, 1, 15, "RROCK13", C5TEXT},
{ doom2, 1, 31, "RROCK19", C6TEXT},
{ pack_tnt, 1, 6, "SLIME16", T1TEXT},
{ pack_tnt, 1, 11, "RROCK14", T2TEXT},
{ pack_tnt, 1, 20, "RROCK07", T3TEXT},
{ pack_tnt, 1, 30, "RROCK17", T4TEXT},
{ pack_tnt, 1, 15, "RROCK13", T5TEXT},
{ pack_tnt, 1, 31, "RROCK19", T6TEXT},
{ pack_plut, 1, 6, "SLIME16", P1TEXT},
{ pack_plut, 1, 11, "RROCK14", P2TEXT},
{ pack_plut, 1, 20, "RROCK07", P3TEXT},
{ pack_plut, 1, 30, "RROCK17", P4TEXT},
{ pack_plut, 1, 15, "RROCK13", P5TEXT},
{ pack_plut, 1, 31, "RROCK19", P6TEXT},
};
char* finaletext;
char* finaleflat;
void F_StartCast (void);
void F_CastTicker (void);
boolean F_CastResponder (event_t *ev);
void F_CastDrawer (void);
//
// F_StartFinale
//
void F_StartFinale (void)
{
size_t i;
gameaction = ga_nothing;
gamestate = GS_FINALE;
viewactive = false;
automapactive = false;
if (logical_gamemission == doom)
{
S_ChangeMusic(mus_victor, true);
}
else
{
S_ChangeMusic(mus_read_m, true);
}
// Find the right screen and set the text and background
for (i=0; i<arrlen(textscreens); ++i)
{
textscreen_t *screen = &textscreens[i];
// Hack for Chex Quest
if (gameversion == exe_chex && screen->mission == doom)
{
screen->level = 5;
}
if (logical_gamemission == screen->mission
&& (logical_gamemission != doom || gameepisode == screen->episode)
&& gamemap == screen->level)
{
finaletext = screen->text;
finaleflat = screen->background;
}
}
// Do dehacked substitutions of strings
finaletext = DEH_String(finaletext);
finaleflat = DEH_String(finaleflat);
finalestage = F_STAGE_TEXT;
finalecount = 0;
}
boolean F_Responder (event_t *event)
{
if (finalestage == F_STAGE_CAST)
return F_CastResponder (event);
return false;
}
//
// F_Ticker
//
void F_Ticker (void)
{
size_t i;
// check for skipping
if ( (gamemode == commercial)
&& ( finalecount > 50) )
{
// go on to the next level
for (i=0 ; i<MAXPLAYERS ; i++)
if (players[i].cmd.buttons)
break;
if (i < MAXPLAYERS)
{
if (gamemap == 30)
F_StartCast ();
else
gameaction = ga_worlddone;
}
}
// advance animation
finalecount++;
if (finalestage == F_STAGE_CAST)
{
F_CastTicker ();
return;
}
if ( gamemode == commercial)
return;
if (finalestage == F_STAGE_TEXT
&& finalecount>strlen (finaletext)*TEXTSPEED + TEXTWAIT)
{
finalecount = 0;
finalestage = F_STAGE_ARTSCREEN;
wipegamestate = -1; // force a wipe
if (gameepisode == 3)
S_StartMusic (mus_bunny);
}
}
//
// F_TextWrite
//
#include "hu_stuff.h"
extern patch_t *hu_font[HU_FONTSIZE];
void F_TextWrite (void)
{
byte* src;
byte* dest;
int x,y,w;
signed int count;
char* ch;
int c;
int cx;
int cy;
// erase the entire screen to a tiled background
src = W_CacheLumpName ( finaleflat , PU_CACHE);
dest = I_VideoBuffer;
for (y=0 ; y<SCREENHEIGHT ; y++)
{
for (x=0 ; x<SCREENWIDTH/64 ; x++)
{
memcpy (dest, src+((y&63)<<6), 64);
dest += 64;
}
if (SCREENWIDTH&63)
{
memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63);
dest += (SCREENWIDTH&63);
}
}
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
// draw some of the text onto the screen
cx = 10;
cy = 10;
ch = finaletext;
count = ((signed int) finalecount - 10) / TEXTSPEED;
if (count < 0)
count = 0;
for ( ; count ; count-- )
{
c = *ch++;
if (!c)
break;
if (c == '\n')
{
cx = 10;
cy += 11;
continue;
}
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c]->width);
if (cx+w > SCREENWIDTH)
break;
V_DrawPatch(cx, cy, hu_font[c]);
cx+=w;
}
}
//
// Final DOOM 2 animation
// Casting by id Software.
// in order of appearance
//
typedef struct
{
char *name;
mobjtype_t type;
} castinfo_t;
castinfo_t castorder[] = {
{CC_ZOMBIE, MT_POSSESSED},
{CC_SHOTGUN, MT_SHOTGUY},
{CC_HEAVY, MT_CHAINGUY},
{CC_IMP, MT_TROOP},
{CC_DEMON, MT_SERGEANT},
{CC_LOST, MT_SKULL},
{CC_CACO, MT_HEAD},
{CC_HELL, MT_KNIGHT},
{CC_BARON, MT_BRUISER},
{CC_ARACH, MT_BABY},
{CC_PAIN, MT_PAIN},
{CC_REVEN, MT_UNDEAD},
{CC_MANCU, MT_FATSO},
{CC_ARCH, MT_VILE},
{CC_SPIDER, MT_SPIDER},
{CC_CYBER, MT_CYBORG},
{CC_HERO, MT_PLAYER},
{NULL,0}
};
int castnum;
int casttics;
state_t* caststate;
boolean castdeath;
int castframes;
int castonmelee;
boolean castattacking;
//
// F_StartCast
//
void F_StartCast (void)
{
wipegamestate = -1; // force a screen wipe
castnum = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
casttics = caststate->tics;
castdeath = false;
finalestage = F_STAGE_CAST;
castframes = 0;
castonmelee = 0;
castattacking = false;
S_ChangeMusic(mus_evil, true);
}
//
// F_CastTicker
//
void F_CastTicker (void)
{
int st;
int sfx;
if (--casttics > 0)
return; // not time to change state yet
if (caststate->tics == -1 || caststate->nextstate == S_NULL)
{
// switch from deathstate to next monster
castnum++;
castdeath = false;
if (castorder[castnum].name == NULL)
castnum = 0;
if (mobjinfo[castorder[castnum].type].seesound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].seesound);
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
castframes = 0;
}
else
{
// just advance to next state in animation
if (caststate == &states[S_PLAY_ATK1])
goto stopattack; // Oh, gross hack!
st = caststate->nextstate;
caststate = &states[st];
castframes++;
// sound hacks....
switch (st)
{
case S_PLAY_ATK1: sfx = sfx_dshtgn; break;
case S_POSS_ATK2: sfx = sfx_pistol; break;
case S_SPOS_ATK2: sfx = sfx_shotgn; break;
case S_VILE_ATK2: sfx = sfx_vilatk; break;
case S_SKEL_FIST2: sfx = sfx_skeswg; break;
case S_SKEL_FIST4: sfx = sfx_skepch; break;
case S_SKEL_MISS2: sfx = sfx_skeatk; break;
case S_FATT_ATK8:
case S_FATT_ATK5:
case S_FATT_ATK2: sfx = sfx_firsht; break;
case S_CPOS_ATK2:
case S_CPOS_ATK3:
case S_CPOS_ATK4: sfx = sfx_shotgn; break;
case S_TROO_ATK3: sfx = sfx_claw; break;
case S_SARG_ATK2: sfx = sfx_sgtatk; break;
case S_BOSS_ATK2:
case S_BOS2_ATK2:
case S_HEAD_ATK2: sfx = sfx_firsht; break;
case S_SKULL_ATK2: sfx = sfx_sklatk; break;
case S_SPID_ATK2:
case S_SPID_ATK3: sfx = sfx_shotgn; break;
case S_BSPI_ATK2: sfx = sfx_plasma; break;
case S_CYBER_ATK2:
case S_CYBER_ATK4:
case S_CYBER_ATK6: sfx = sfx_rlaunc; break;
case S_PAIN_ATK3: sfx = sfx_sklatk; break;
default: sfx = 0; break;
}
if (sfx)
S_StartSound (NULL, sfx);
}
if (castframes == 12)
{
// go into attack frame
castattacking = true;
if (castonmelee)
caststate=&states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate=&states[mobjinfo[castorder[castnum].type].missilestate];
castonmelee ^= 1;
if (caststate == &states[S_NULL])
{
if (castonmelee)
caststate=
&states[mobjinfo[castorder[castnum].type].meleestate];
else
caststate=
&states[mobjinfo[castorder[castnum].type].missilestate];
}
}
if (castattacking)
{
if (castframes == 24
|| caststate == &states[mobjinfo[castorder[castnum].type].seestate] )
{
stopattack:
castattacking = false;
castframes = 0;
caststate = &states[mobjinfo[castorder[castnum].type].seestate];
}
}
casttics = caststate->tics;
if (casttics == -1)
casttics = 15;
}
//
// F_CastResponder
//
boolean F_CastResponder (event_t* ev)
{
if (ev->type != ev_keydown)
return false;
if (castdeath)
return true; // already in dying frames
// go into death frame
castdeath = true;
caststate = &states[mobjinfo[castorder[castnum].type].deathstate];
casttics = caststate->tics;
castframes = 0;
castattacking = false;
if (mobjinfo[castorder[castnum].type].deathsound)
S_StartSound (NULL, mobjinfo[castorder[castnum].type].deathsound);
return true;
}
void F_CastPrint (char* text)
{
char* ch;
int c;
int cx;
int w;
int width;
// find width
ch = text;
width = 0;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
width += 4;
continue;
}
w = SHORT (hu_font[c]->width);
width += w;
}
// draw it
cx = 160-width/2;
ch = text;
while (ch)
{
c = *ch++;
if (!c)
break;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c> HU_FONTSIZE)
{
cx += 4;
continue;
}
w = SHORT (hu_font[c]->width);
V_DrawPatch(cx, 180, hu_font[c]);
cx+=w;
}
}
//
// F_CastDrawer
//
void F_CastDrawer (void)
{
spritedef_t* sprdef;
spriteframe_t* sprframe;
int lump;
boolean flip;
patch_t* patch;
// erase the entire screen to a background
V_DrawPatch (0, 0, W_CacheLumpName (DEH_String("BOSSBACK"), PU_CACHE));
F_CastPrint (DEH_String(castorder[castnum].name));
// draw the current frame in the middle of the screen
sprdef = &sprites[caststate->sprite];
sprframe = &sprdef->spriteframes[ caststate->frame & FF_FRAMEMASK];
lump = sprframe->lump[0];
flip = (boolean)sprframe->flip[0];
patch = W_CacheLumpNum (lump+firstspritelump, PU_CACHE);
if (flip)
V_DrawPatchFlipped(160, 170, patch);
else
V_DrawPatch(160, 170, patch);
}
//
// F_DrawPatchCol
//
void
F_DrawPatchCol
( int x,
patch_t* patch,
int col )
{
column_t* column;
byte* source;
byte* dest;
byte* desttop;
int count;
column = (column_t *)((byte *)patch + LONG(patch->columnofs[col]));
desttop = I_VideoBuffer + x;
// step through the posts in a column
while (column->topdelta != 0xff )
{
source = (byte *)column + 3;
dest = desttop + column->topdelta*SCREENWIDTH;
count = column->length;
while (count--)
{
*dest = *source++;
dest += SCREENWIDTH;
}
column = (column_t *)( (byte *)column + column->length + 4 );
}
}
//
// F_BunnyScroll
//
void F_BunnyScroll (void)
{
signed int scrolled;
int x;
patch_t* p1;
patch_t* p2;
char name[10];
int stage;
static int laststage;
p1 = W_CacheLumpName (DEH_String("PFUB2"), PU_LEVEL);
p2 = W_CacheLumpName (DEH_String("PFUB1"), PU_LEVEL);
V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT);
scrolled = (320 - ((signed int) finalecount-230)/2);
if (scrolled > 320)
scrolled = 320;
if (scrolled < 0)
scrolled = 0;
for ( x=0 ; x<SCREENWIDTH ; x++)
{
if (x+scrolled < 320)
F_DrawPatchCol (x, p1, x+scrolled);
else
F_DrawPatchCol (x, p2, x+scrolled - 320);
}
if (finalecount < 1130)
return;
if (finalecount < 1180)
{
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
(SCREENHEIGHT - 8 * 8) / 2,
W_CacheLumpName(DEH_String("END0"), PU_CACHE));
laststage = 0;
return;
}
stage = (finalecount-1180) / 5;
if (stage > 6)
stage = 6;
if (stage > laststage)
{
S_StartSound (NULL, sfx_pistol);
laststage = stage;
}
DEH_snprintf(name, 10, "END%i", stage);
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
(SCREENHEIGHT - 8 * 8) / 2,
W_CacheLumpName (name,PU_CACHE));
}
static void F_ArtScreenDrawer(void)
{
char *lumpname;
if (gameepisode == 3)
{
F_BunnyScroll();
}
else
{
switch (gameepisode)
{
case 1:
if (gamemode == retail)
{
lumpname = "CREDIT";
}
else
{
lumpname = "HELP2";
}
break;
case 2:
lumpname = "VICTORY2";
break;
case 4:
lumpname = "ENDPIC";
break;
default:
return;
}
lumpname = DEH_String(lumpname);
V_DrawPatch (0, 0, W_CacheLumpName(lumpname, PU_CACHE));
}
}
//
// F_Drawer
//
void F_Drawer (void)
{
switch (finalestage)
{
case F_STAGE_CAST:
F_CastDrawer();
break;
case F_STAGE_TEXT:
F_TextWrite();
break;
case F_STAGE_ARTSCREEN:
F_ArtScreenDrawer();
break;
}
}

45
doom/f_finale.h Normal file
View file

@ -0,0 +1,45 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
//
//
#ifndef __F_FINALE__
#define __F_FINALE__
#include "doomtype.h"
#include "d_event.h"
//
// FINALE
//
// Called by main loop.
boolean F_Responder (event_t* ev);
// Called by main loop.
void F_Ticker (void);
// Called by main loop.
void F_Drawer (void);
void F_StartFinale (void);
#endif

294
doom/f_wipe.c Normal file
View file

@ -0,0 +1,294 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Mission begin melt/wipe screen special effect.
//
#include <string.h>
#include "z_zone.h"
#include "i_video.h"
#include "v_video.h"
#include "m_random.h"
#include "doomtype.h"
#include "f_wipe.h"
//
// SCREEN WIPE PACKAGE
//
// when zero, stop the wipe
static boolean go = 0;
static byte* wipe_scr_start;
static byte* wipe_scr_end;
static byte* wipe_scr;
void
wipe_shittyColMajorXform
( short* array,
int width,
int height )
{
int x;
int y;
short* dest;
dest = (short*) Z_Malloc(width*height*2, PU_STATIC, 0);
for(y=0;y<height;y++)
for(x=0;x<width;x++)
dest[x*height+y] = array[y*width+x];
memcpy(array, dest, width*height*2);
Z_Free(dest);
}
int
wipe_initColorXForm
( int width,
int height,
int ticks )
{
memcpy(wipe_scr, wipe_scr_start, width*height);
return 0;
}
int
wipe_doColorXForm
( int width,
int height,
int ticks )
{
boolean changed;
byte* w;
byte* e;
int newval;
changed = false;
w = wipe_scr;
e = wipe_scr_end;
while (w!=wipe_scr+width*height)
{
if (*w != *e)
{
if (*w > *e)
{
newval = *w - ticks;
if (newval < *e)
*w = *e;
else
*w = newval;
changed = true;
}
else if (*w < *e)
{
newval = *w + ticks;
if (newval > *e)
*w = *e;
else
*w = newval;
changed = true;
}
}
w++;
e++;
}
return !changed;
}
int
wipe_exitColorXForm
( int width,
int height,
int ticks )
{
return 0;
}
static int* y;
int
wipe_initMelt
( int width,
int height,
int ticks )
{
int i, r;
// copy start screen to main screen
memcpy(wipe_scr, wipe_scr_start, width*height);
// makes this wipe faster (in theory)
// to have stuff in column-major format
wipe_shittyColMajorXform((short*)wipe_scr_start, width/2, height);
wipe_shittyColMajorXform((short*)wipe_scr_end, width/2, height);
// setup initial column positions
// (y<0 => not ready to scroll yet)
y = (int *) Z_Malloc(width*sizeof(int), PU_STATIC, 0);
y[0] = -(M_Random()%16);
for (i=1;i<width;i++)
{
r = (M_Random()%3) - 1;
y[i] = y[i-1] + r;
if (y[i] > 0) y[i] = 0;
else if (y[i] == -16) y[i] = -15;
}
return 0;
}
int
wipe_doMelt
( int width,
int height,
int ticks )
{
int i;
int j;
int dy;
int idx;
short* s;
short* d;
boolean done = true;
width/=2;
while (ticks--)
{
for (i=0;i<width;i++)
{
if (y[i]<0)
{
y[i]++; done = false;
}
else if (y[i] < height)
{
dy = (y[i] < 16) ? y[i]+1 : 8;
if (y[i]+dy >= height) dy = height - y[i];
s = &((short *)wipe_scr_end)[i*height+y[i]];
d = &((short *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=dy;j;j--)
{
d[idx] = *(s++);
idx += width;
}
y[i] += dy;
s = &((short *)wipe_scr_start)[i*height];
d = &((short *)wipe_scr)[y[i]*width+i];
idx = 0;
for (j=height-y[i];j;j--)
{
d[idx] = *(s++);
idx += width;
}
done = false;
}
}
}
return done;
}
int
wipe_exitMelt
( int width,
int height,
int ticks )
{
Z_Free(y);
Z_Free(wipe_scr_start);
Z_Free(wipe_scr_end);
return 0;
}
int
wipe_StartScreen
( int x,
int y,
int width,
int height )
{
wipe_scr_start = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
I_ReadScreen(wipe_scr_start);
return 0;
}
int
wipe_EndScreen
( int x,
int y,
int width,
int height )
{
wipe_scr_end = Z_Malloc(SCREENWIDTH * SCREENHEIGHT, PU_STATIC, NULL);
I_ReadScreen(wipe_scr_end);
V_DrawBlock(x, y, width, height, wipe_scr_start); // restore start scr.
return 0;
}
int
wipe_ScreenWipe
( int wipeno,
int x,
int y,
int width,
int height,
int ticks )
{
int rc;
static int (*wipes[])(int, int, int) =
{
wipe_initColorXForm, wipe_doColorXForm, wipe_exitColorXForm,
wipe_initMelt, wipe_doMelt, wipe_exitMelt
};
// initial stuff
if (!go)
{
go = 1;
// wipe_scr = (byte *) Z_Malloc(width*height, PU_STATIC, 0); // DEBUG
wipe_scr = I_VideoBuffer;
(*wipes[wipeno*3])(width, height, ticks);
}
// do a piece of wipe-in
V_MarkRect(0, 0, width, height);
rc = (*wipes[wipeno*3+1])(width, height, ticks);
// V_DrawBlock(x, y, 0, width, height, wipe_scr); // DEBUG
// final stuff
if (rc)
{
go = 0;
(*wipes[wipeno*3+2])(width, height, ticks);
}
return !go;
}

63
doom/f_wipe.h Normal file
View file

@ -0,0 +1,63 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Mission start screen wipe/melt, special effects.
//
#ifndef __F_WIPE_H__
#define __F_WIPE_H__
//
// SCREEN WIPE PACKAGE
//
enum
{
// simple gradual pixel change for 8-bit only
wipe_ColorXForm,
// weird screen melt
wipe_Melt,
wipe_NUMWIPES
};
int
wipe_StartScreen
( int x,
int y,
int width,
int height );
int
wipe_EndScreen
( int x,
int y,
int width,
int height );
int
wipe_ScreenWipe
( int wipeno,
int x,
int y,
int width,
int height,
int ticks );
#endif

2228
doom/g_game.c Normal file

File diff suppressed because it is too large Load diff

80
doom/g_game.h Normal file
View file

@ -0,0 +1,80 @@
//
// Copyright(C) 1993-1996 Id Software, Inc.
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// Duh.
//
#ifndef __G_GAME__
#define __G_GAME__
#include "doomdef.h"
#include "d_event.h"
#include "d_ticcmd.h"
//
// GAME
//
void G_DeathMatchSpawnPlayer (int playernum);
void G_InitNew (skill_t skill, int episode, int map);
// Can be called by the startup code or M_Responder.
// A normal game starts at map 1,
// but a warp test can start elsewhere
void G_DeferedInitNew (skill_t skill, int episode, int map);
void G_DeferedPlayDemo (char* demo);
// Can be called by the startup code or M_Responder,
// calls P_SetupLevel or W_EnterWorld.
void G_LoadGame (char* name);
void G_DoLoadGame (void);
// Called by M_Responder.
void G_SaveGame (int slot, char* description);
// Only called by startup code.
void G_RecordDemo (char* name);
void G_BeginRecording (void);
void G_PlayDemo (char* name);
void G_TimeDemo (char* name);
boolean G_CheckDemoStatus (void);
void G_ExitLevel (void);
void G_SecretExitLevel (void);
void G_WorldDone (void);
// Read current data from inputs and build a player movement command.
void G_BuildTiccmd (ticcmd_t *cmd, int maketic);
void G_Ticker (void);
boolean G_Responder (event_t* ev);
void G_ScreenShot (void);
void G_DrawMouseSpeedBox(void);
int G_VanillaVersionCode(void);
extern int vanilla_savegame_limit;
extern int vanilla_demo_limit;
#endif

271
doom/gusconf.c Normal file
View file

@ -0,0 +1,271 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// GUS emulation code.
//
// Actually emulating a GUS is far too much work; fortunately
// GUS "emulation" already exists in the form of Timidity, which
// supports GUS patch files. This code therefore converts Doom's
// DMXGUS lump into an equivalent Timidity configuration file.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "w_wad.h"
#include "z_zone.h"
#define MAX_INSTRUMENTS 256
typedef struct
{
char *patch_names[MAX_INSTRUMENTS];
int mapping[MAX_INSTRUMENTS];
} gus_config_t;
char *gus_patch_path = "";
unsigned int gus_ram_kb = 1024;
static unsigned int MappingIndex(void)
{
unsigned int result = gus_ram_kb / 256;
if (result < 1)
{
return 1;
}
else if (result > 4)
{
return 4;
}
else
{
return result;
}
}
static int SplitLine(char *line, char **fields, unsigned int max_fields)
{
unsigned int num_fields;
char *p;
fields[0] = line;
num_fields = 1;
for (p = line; *p != '\0'; ++p)
{
if (*p == ',')
{
*p = '\0';
// Skip spaces following the comma.
do
{
++p;
} while (*p != '\0' && isspace(*p));
fields[num_fields] = p;
++num_fields;
--p;
if (num_fields >= max_fields)
{
break;
}
}
else if (*p == '#')
{
*p = '\0';
break;
}
}
// Strip off trailing whitespace from the end of the line.
p = fields[num_fields - 1] + strlen(fields[num_fields - 1]);
while (p > fields[num_fields - 1] && isspace(*(p - 1)))
{
--p;
*p = '\0';
}
return num_fields;
}
static void ParseLine(gus_config_t *config, char *line)
{
char *fields[6];
unsigned int num_fields;
unsigned int instr_id, mapped_id;
num_fields = SplitLine(line, fields, 6);
if (num_fields < 6)
{
return;
}
instr_id = atoi(fields[0]);
mapped_id = atoi(fields[MappingIndex()]);
free(config->patch_names[instr_id]);
config->patch_names[instr_id] = strdup(fields[5]);
config->mapping[instr_id] = mapped_id;
}
static void ParseDMXConfig(char *dmxconf, gus_config_t *config)
{
char *p, *newline;
unsigned int i;
memset(config, 0, sizeof(gus_config_t));
for (i = 0; i < MAX_INSTRUMENTS; ++i)
{
config->mapping[i] = -1;
}
p = dmxconf;
for (;;)
{
newline = strchr(p, '\n');
if (newline != NULL)
{
*newline = '\0';
}
ParseLine(config, p);
if (newline == NULL)
{
break;
}
else
{
p = newline + 1;
}
}
}
static void FreeDMXConfig(gus_config_t *config)
{
unsigned int i;
for (i = 0; i < MAX_INSTRUMENTS; ++i)
{
free(config->patch_names[i]);
}
}
static char *ReadDMXConfig(void)
{
int lumpnum;
unsigned int len;
char *data;
// TODO: This should be chosen based on gamemode == commercial:
lumpnum = W_CheckNumForName("DMXGUS");
if (lumpnum < 0)
{
lumpnum = W_GetNumForName("DMXGUSC");
}
len = W_LumpLength(lumpnum);
data = Z_Malloc(len + 1, PU_STATIC, NULL);
W_ReadLump(lumpnum, data);
return data;
}
static boolean WriteTimidityConfig(char *path, gus_config_t *config)
{
FILE *fstream;
unsigned int i;
fstream = fopen(path, "w");
if (fstream == NULL)
{
return false;
}
fprintf(fstream, "# Autogenerated Timidity config.\n\n");
fprintf(fstream, "dir %s\n", gus_patch_path);
fprintf(fstream, "\nbank 0\n\n");
for (i = 0; i < 128; ++i)
{
if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS
&& config->patch_names[config->mapping[i]] != NULL)
{
fprintf(fstream, "%i %s\n",
i, config->patch_names[config->mapping[i]]);
}
}
fprintf(fstream, "\ndrumset 0\n\n");
for (i = 128 + 25; i < MAX_INSTRUMENTS; ++i)
{
if (config->mapping[i] >= 0 && config->mapping[i] < MAX_INSTRUMENTS
&& config->patch_names[config->mapping[i]] != NULL)
{
fprintf(fstream, "%i %s\n",
i - 128, config->patch_names[config->mapping[i]]);
}
}
fprintf(fstream, "\n");
fclose(fstream);
return true;
}
boolean GUS_WriteConfig(char *path)
{
boolean result;
char *dmxconf;
gus_config_t config;
if (!strcmp(gus_patch_path, ""))
{
printf("You haven't configured gus_patch_path.\n");
printf("gus_patch_path needs to point to the location of "
"your GUS patch set.\n"
"To get a copy of the \"standard\" GUS patches, "
"download a copy of dgguspat.zip.\n");
return false;
}
dmxconf = ReadDMXConfig();
ParseDMXConfig(dmxconf, &config);
result = WriteTimidityConfig(path, &config);
FreeDMXConfig(&config);
Z_Free(dmxconf);
return result;
}

29
doom/gusconf.h Normal file
View file

@ -0,0 +1,29 @@
//
// Copyright(C) 2005-2014 Simon Howard
//
// 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.
//
// DESCRIPTION:
// GUS emulation code.
//
#ifndef __GUSCONF_H__
#define __GUSCONF_H__
#include "doomtype.h"
extern char *gus_patch_path;
extern unsigned int gus_ram_kb;
boolean GUS_WriteConfig(char *path);
#endif /* #ifndef __GUSCONF_H__ */