apps/games/NXDoom: Original Chocolate DOOM source
This commit adds the original Chocolate DOOM source which forms a basis for the NuttX port of DOOM. Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
4
games/NXDoom/.devcontainer/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
*.xauth
|
||||
wads/
|
||||
prefs/
|
||||
share/
|
||||
39
games/NXDoom/.devcontainer/Dockerfile
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
FROM ubuntu
|
||||
|
||||
######### Apt dependencies
|
||||
|
||||
ARG system_apt_dependencies="build-essential gdb automake autoconf libtool git pkg-config python3 python3-pip sudo"
|
||||
ARG choco_apt_dependencies="gcc make libsdl2-dev libsdl2-net-dev libsdl2-mixer-dev"
|
||||
ARG choco_apt_dependencies_optional="libflac-dev libfluidsynth-dev libpng-dev libsamplerate-dev libvorbis-dev"
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -qq $system_apt_dependencies $choco_apt_dependencies $choco_apt_dependencies_optional
|
||||
|
||||
########## Install Pillow (PIL) via pip, not apt
|
||||
|
||||
ARG choco_pip_dependencies="pillow"
|
||||
RUN pip install $choco_pip_dependencies
|
||||
|
||||
########## Container user setup
|
||||
|
||||
ARG USERNAME=chocodev
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=$USER_UID
|
||||
RUN groupadd --gid $USER_GID $USERNAME \
|
||||
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME
|
||||
|
||||
# Add sudo support
|
||||
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
|
||||
&& chmod 0440 /etc/sudoers.d/$USERNAME
|
||||
|
||||
# Add the user to the audio group, to have ALSA sound access
|
||||
# TODO: pulseaudio, so this isn't necessary?
|
||||
RUN addgroup $USERNAME audio
|
||||
|
||||
# Use bash, not sh. Yuck.
|
||||
RUN chsh $USERNAME -s /bin/bash
|
||||
|
||||
USER $USERNAME
|
||||
|
||||
# Make sure we actually own our own local share stuff
|
||||
RUN mkdir -p /home/$USERNAME/.local/share && \
|
||||
chown -R $USERNAME:$USERNAME /home/$USERNAME/.local
|
||||
45
games/NXDoom/.devcontainer/devcontainer.json
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/docker-existing-dockerfile
|
||||
{
|
||||
"name": "Doom Dev Container",
|
||||
"context": "..",
|
||||
"dockerFile": "./Dockerfile",
|
||||
|
||||
"extensions": [
|
||||
"yzhang.markdown-all-in-one",
|
||||
"bierner.markdown-preview-github-styles",
|
||||
"dotjoshjohnson.xml",
|
||||
|
||||
"eamodio.gitlens",
|
||||
"npxms.hide-gitignored", // Note: need to run its command manually
|
||||
|
||||
// Build tooling
|
||||
"ms-vscode.cpptools",
|
||||
"cschlosser.doxdocgen",
|
||||
"austin.code-gnu-global",
|
||||
"jeff-hykin.better-cpp-syntax", // Note: runs locally
|
||||
"ms-vscode.cpptools-themes", // Note: runs locally
|
||||
],
|
||||
|
||||
// Required to not bleed "root" permission files into the host volume
|
||||
"containerUser": "chocodev",
|
||||
|
||||
// VSCode on Linux specific, for creating X11 and sound forwarding
|
||||
// Comment out manually if working on non-Linux
|
||||
"initializeCommand": "${localWorkspaceFolder}/.devcontainer/initialize-linux.sh",
|
||||
"mounts": [
|
||||
"source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind",
|
||||
"source=${localWorkspaceFolder}/.devcontainer/prefs,target=/home/chocodev/.local/share/chocolate-doom,type=bind",
|
||||
],
|
||||
"containerEnv": {
|
||||
"DISPLAY": "${localEnv:DISPLAY}",
|
||||
"XAUTHORITY": "${containerWorkspaceFolder}/.devcontainer/share/devcontainer.xauth",
|
||||
},
|
||||
"runArgs": [
|
||||
// "--gpus", "all", // Uncomment for GPU support
|
||||
"--device", "/dev/snd",
|
||||
// TODO: pulseaudio? https://github.com/mviereck/x11docker/wiki/Container-sound:-ALSA-or-Pulseaudio
|
||||
]
|
||||
|
||||
// TODO: X11/sound forwarding configs for MacOS (XQuartz) and Windows (Xming)
|
||||
}
|
||||
9
games/NXDoom/.devcontainer/initialize-linux.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
HERE=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
|
||||
|
||||
### Create the xauth file allowing the container to interact with a forwarded X11
|
||||
XAUTH="$HERE/share/devcontainer.xauth";
|
||||
touch "$XAUTH"
|
||||
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
|
||||
|
||||
### TODO: pulseaudio pasthrough
|
||||
101
games/NXDoom/.github/CONTRIBUTING.md
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
Thanks for contributing to Chocolate Doom! Whatever your contribution,
|
||||
whether it's code or just a bug report, it's greatly appreciated.
|
||||
|
||||
The project is governed by the
|
||||
[Contributor Covenant](http://contributor-covenant.org/version/1/4/)
|
||||
version 1.4. By contributing to the project you agree to abide by its
|
||||
terms. To report violations, please send an email to fraggle@gmail.com.
|
||||
|
||||
### Reporting bugs
|
||||
|
||||
Before reporting a bug, it's worth checking if this really is a bug.
|
||||
Chocolate Doom's mission is to reproduce the Vanilla (DOS) versions of
|
||||
the Doom engine games, bugs and all. Check out the
|
||||
[NOT-BUGS](../NOT-BUGS.md) file for a list of common issues which aren't
|
||||
really bugs at all. You might also try searching [the GitHub issues
|
||||
list](https://github.com/chocolate-doom/chocolate-doom/issues) to see
|
||||
if your bug has already been reported.
|
||||
|
||||
If you're confident that you've found a real bug (or even if you're
|
||||
not sure!) please go ahead and [file an issue on
|
||||
GitHub](https://github.com/chocolate-doom/chocolate-doom/issues/new).
|
||||
You'll need a GitHub account, but it's pretty easy to sign up.
|
||||
|
||||
Please try to give as much information as possible:
|
||||
|
||||
* What version of Chocolate Doom are you using? Check the title bar of
|
||||
the window for the version number.
|
||||
|
||||
* Chocolate Doom runs on many different operating systems (not just
|
||||
Windows!). Please say which operating system and what version of it
|
||||
you're using.
|
||||
|
||||
* Please say which game you're playing (Doom 1, Doom 2, Heretic,
|
||||
Hexen, Strife, etc.) and if you're using any fan-made WADs or mods,
|
||||
please say which mods (and where they can be downloaded!). It helps
|
||||
to give the full command line you're using to start the game.
|
||||
|
||||
* Please mention if you have any special configuration you think may be
|
||||
relevant, too.
|
||||
|
||||
### Feature requests
|
||||
|
||||
Chocolate Doom is always open to new feature requests; however, please
|
||||
be aware that the project is designed around a deliberately limited
|
||||
[philosophy](../PHILOSOPHY.md), and many features common in other source
|
||||
ports will not be accepted. Here are a few common requests which are
|
||||
often rejected:
|
||||
|
||||
* "High resolution" rendering (greater than 320x200 display).
|
||||
|
||||
* An option to disable Vanilla limits, such as the visplane rendering
|
||||
limit.
|
||||
|
||||
* Ability to play "No Rest For The Living", the expansion pack which
|
||||
comes with the XBLA / BFG Edition of Doom.
|
||||
|
||||
If you're not sure whether your feature is in line with the project
|
||||
philosophy, don't worry - just ask anyway!
|
||||
To make a feature request, [file an issue on
|
||||
GitHub](https://github.com/chocolate-doom/chocolate-doom/issues/new).
|
||||
|
||||
### Bug fixes / code submission
|
||||
|
||||
Thank you for contributing code to Chocolate Doom! Please check the
|
||||
following guidelines before opening a pull request:
|
||||
|
||||
* All code must be licensed under [the GNU General Public License,
|
||||
version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html).
|
||||
Please don't reuse code that isn't GPL, or that is GPLv3 licensed.
|
||||
Be aware that by submitting your code to the project, you're agreeing
|
||||
to license it under the GPL.
|
||||
|
||||
* Please follow the coding style guidelines described in the
|
||||
[HACKING](../HACKING.md) file.
|
||||
|
||||
* Please don't make unnecessary changes which just change formatting
|
||||
without any actual change to program logic. While being consistent
|
||||
is nice, such changes destroy the ability to use the `git blame`
|
||||
command to see when code was last changed.
|
||||
|
||||
* The guidelines given above in the "feature requests" section also
|
||||
apply here. New features which aren't in line with the project
|
||||
philosophy are likely to be rejected. If you're not sure, open a
|
||||
feature request first and ask before you start implementing your
|
||||
feature.
|
||||
|
||||
* Follow the guidelines for [how to write a Git commit
|
||||
message](http://chris.beams.io/posts/git-commit/). In short: the
|
||||
first line should be a short summary; keep to an 80 column limit;
|
||||
use the imperative mood ("fix bug X", rather than "fixed bug X" or
|
||||
"fixing bug X"). If your change fixes a particular subsystem,
|
||||
prefix the summary with that subsystem: eg. "doom: Fix bug X" or
|
||||
"textscreen: Change size of X".
|
||||
|
||||
* If you're making a change related to a bug, reference the GitHub
|
||||
issue number in the commit message, eg. "This is a partial fix
|
||||
for #646". This will link your commit into the issue comments. If
|
||||
your change is a fix for the bug, put the word "fixes" before the
|
||||
issue number to automatically close the issue once your change
|
||||
is merged.
|
||||
|
||||
28
games/NXDoom/.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<!--
|
||||
Thank you for reporting a bug in Chocolate Doom. Please complete
|
||||
the following template so that we can better diagnose the source
|
||||
of your problem.
|
||||
|
||||
To save yourself some time, you may want to check the FAQ and the
|
||||
NOT-BUGS list for solutions to some common problems:
|
||||
|
||||
https://www.chocolate-doom.org/wiki/index.php/FAQ
|
||||
https://www.chocolate-doom.org/not-bugs
|
||||
-->
|
||||
|
||||
### Background
|
||||
|
||||
Version of Chocolate Doom:
|
||||
|
||||
Operating System and version:
|
||||
|
||||
Game: (Doom/Heretic/Hexen/Strife/other)
|
||||
|
||||
Any loaded WADs and mods (please include full command line):
|
||||
|
||||
### Bug description
|
||||
|
||||
Observed behavior:
|
||||
|
||||
Expected behavior:
|
||||
|
||||
54
games/NXDoom/.github/workflows/cpp-linter.yml
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Workflow syntax:
|
||||
# https://help.github.com/en/articles/workflow-syntax-for-github-actions
|
||||
name: cpp-linter
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
cpp-linter:
|
||||
strategy:
|
||||
matrix:
|
||||
compiler: [clang]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install libfluidsynth-dev libpng-dev libsamplerate0-dev libsdl2-dev libsdl2-mixer-dev libsdl2-net-dev ninja-build
|
||||
- name: Run cmake to generate compilation database
|
||||
run: cmake -S . -B . -G Ninja -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||
- uses: cpp-linter/cpp-linter-action@v2
|
||||
id: linter
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
style: file
|
||||
lines-changed-only: true
|
||||
version: 16
|
||||
tidy-checks: >-
|
||||
boost-*
|
||||
,bugprone-*
|
||||
,performance-*
|
||||
,readability-*
|
||||
,portability-*
|
||||
,modernize-*
|
||||
,clang-analyzer-*
|
||||
,cppcoreguidelines-*
|
||||
,-cppcoreguidelines-avoid-magic-numbers
|
||||
,-cppcoreguidelines-init-variables
|
||||
,-readability-identifier-length
|
||||
,-readability-isolate-declaration
|
||||
,-readability-magic-numbers
|
||||
|
||||
- name: Fail fast?!
|
||||
if: steps.linter.outputs.checks-failed > 0
|
||||
run: |
|
||||
echo "Some files failed the linting checks! Fail fast disabled until false positive issue is fixed"
|
||||
|
||||
- name: Check no extern used in .c files
|
||||
run: |
|
||||
./check-extern.sh
|
||||
23
games/NXDoom/.github/workflows/cppcheck.yml
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
name: cppcheck
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize]
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
cppcheck:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt-get install cppcheck
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Run cppcheck
|
||||
env:
|
||||
ANALYZE: true
|
||||
run: $GITHUB_WORKSPACE/.travis.sh
|
||||
152
games/NXDoom/.github/workflows/main.yml
vendored
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
tags:
|
||||
- "*"
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.config.name }}
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.config.shell }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- name: Linux GCC
|
||||
os: ubuntu-latest
|
||||
compiler: gcc
|
||||
shell: bash
|
||||
|
||||
- name: macOS Clang
|
||||
os: macos-latest
|
||||
compiler: clang
|
||||
shell: bash
|
||||
|
||||
- name: macOS x86 Clang
|
||||
os: macos-15-intel
|
||||
compiler: clang
|
||||
shell: bash
|
||||
|
||||
- name: MSYS2 UCRT64
|
||||
os: windows-latest
|
||||
compiler: gcc
|
||||
shell: 'msys2 {0}'
|
||||
msystem: ucrt64
|
||||
msys-env: mingw-w64-ucrt-x86_64
|
||||
artifacts: true
|
||||
pkg-path: pkg/win32/*.zip
|
||||
pkg-dir: pkg/win32
|
||||
|
||||
steps:
|
||||
- name: Install pandoc
|
||||
if: runner.os == 'Windows'
|
||||
shell: cmd
|
||||
run: choco install pandoc
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
libsdl2-dev \
|
||||
libsdl2-mixer-dev \
|
||||
libsdl2-net-dev \
|
||||
libpng-dev \
|
||||
libsamplerate0-dev \
|
||||
libfluidsynth-dev
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install \
|
||||
automake \
|
||||
sdl2 \
|
||||
sdl2_mixer \
|
||||
sdl2_net \
|
||||
libpng \
|
||||
libsamplerate \
|
||||
fluid-synth
|
||||
|
||||
- name: Install dependencies (MSYS2)
|
||||
if: runner.os == 'Windows'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.config.msystem }}
|
||||
update: true
|
||||
path-type: inherit
|
||||
install: >-
|
||||
autotools
|
||||
zip
|
||||
${{ matrix.config.msys-env }}-python-pip
|
||||
${{ matrix.config.msys-env }}-gcc
|
||||
${{ matrix.config.msys-env }}-SDL2
|
||||
${{ matrix.config.msys-env }}-SDL2_mixer
|
||||
${{ matrix.config.msys-env }}-SDL2_net
|
||||
${{ matrix.config.msys-env }}-libpng
|
||||
${{ matrix.config.msys-env }}-libsamplerate
|
||||
${{ matrix.config.msys-env }}-fluidsynth
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Configure
|
||||
env:
|
||||
CC: ${{ matrix.config.compiler }}
|
||||
run: |
|
||||
./autogen.sh
|
||||
|
||||
- name: Build
|
||||
run: make -j4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
pip install pyyaml
|
||||
PREFIX=`sed -n '/PROGRAM_PREFIX/p' ${PWD}/config.h | cut -d '"' -f 2`
|
||||
make -j4 -C quickcheck check SOURCE_PORT=$PWD/src/${PREFIX}doom
|
||||
|
||||
- name: Package
|
||||
if: ${{ matrix.config.artifacts }}
|
||||
run: |
|
||||
cd ${{ matrix.config.pkg-dir }}
|
||||
make
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ matrix.config.artifacts }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.config.name }}
|
||||
path: ${{ matrix.config.pkg-path }}
|
||||
|
||||
- name: Extract Package String
|
||||
if: ${{ contains(github.ref, 'tags') }}
|
||||
run: |
|
||||
PACKAGE_STRING=`sed -n '/PACKAGE_STRING/p' ${PWD}/config.h | cut -d '"' -f 2`
|
||||
echo "PACKAGE_STRING=${PACKAGE_STRING}" >> $GITHUB_ENV
|
||||
|
||||
- name: Release
|
||||
if: ${{ contains(github.ref, 'tags') && matrix.config.artifacts }}
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
name: ${{ env.PACKAGE_STRING }}
|
||||
bodyFile: RELEASE_NOTES.md
|
||||
allowUpdates: true
|
||||
artifacts: ${{ matrix.config.pkg-path }}
|
||||
67
games/NXDoom/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
CMDLINE
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
TAGS
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
autotools
|
||||
bin
|
||||
config.h
|
||||
config.hin
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
lib
|
||||
obj
|
||||
rpm.spec
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
tags
|
||||
\#*\#
|
||||
DOOM*.png
|
||||
HTIC*.png
|
||||
HEXEN*.png
|
||||
STRIFE*.png
|
||||
DOOM*.pcx
|
||||
HTIC*.pcx
|
||||
HEXEN*.pcx
|
||||
STRIFE*.pcx
|
||||
|
||||
# CMake-specific ignores
|
||||
/.vs
|
||||
/build*
|
||||
/CMakeSettings.json
|
||||
/out
|
||||
|
||||
# These are the default patterns globally ignored by Subversion:
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.al
|
||||
.libs
|
||||
*.so
|
||||
*.so.[0-9]*
|
||||
*.a
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.rej
|
||||
*~
|
||||
.#*
|
||||
.*.swp
|
||||
.DS_store
|
||||
|
||||
# Ignore GNU Global tags and html files
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
/HTML/
|
||||
|
||||
# VSCode settings
|
||||
|
||||
/.vscode/
|
||||
|
||||
# clangd settings
|
||||
/.cache/clangd
|
||||
compile_commands.json
|
||||
3
games/NXDoom/.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "quickcheck"]
|
||||
path = quickcheck
|
||||
url = https://github.com/chocolate-doom/quickcheck.git
|
||||
32
games/NXDoom/.lvimrc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
" Local vimrc configuration file. Install the localvimrc.vim vim script.
|
||||
set expandtab
|
||||
set tabstop=8
|
||||
set softtabstop=4
|
||||
set shiftwidth=4
|
||||
|
||||
" Add all tag files to tags path.
|
||||
|
||||
let topdir = findfile("configure.ac", ".;")
|
||||
let topdir = substitute(topdir, "configure.ac", "", "")
|
||||
|
||||
" Check tags file in current dir:
|
||||
set tags+=tags
|
||||
|
||||
" Add tag files in parent directories:
|
||||
let tagfiles = findfile("tags", ".;", -1)
|
||||
|
||||
" Add tag files for libraries:
|
||||
call add(tagfiles, topdir . "opl/tags")
|
||||
call add(tagfiles, topdir . "pcsound/tags")
|
||||
call add(tagfiles, topdir . "textscreen/tags")
|
||||
|
||||
for tagfile in tagfiles
|
||||
" Don't go beyond the project top level when adding parent dirs:
|
||||
if stridx(tagfile, topdir) >= 0
|
||||
exec "set tags+=" . tagfile
|
||||
endif
|
||||
endfor
|
||||
|
||||
unlet topdir
|
||||
unlet tagfiles
|
||||
|
||||
19
games/NXDoom/.travis.sh
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/sh
|
||||
if [ "$ANALYZE" = "true" ] ; then
|
||||
# -D__GNUC__ is required for cppcheck to know about noreturn functions
|
||||
cppcheck --error-exitcode=1 -j2 -UTESTING -D__GNUC__ -Iopl -Isrc -Isrc/setup opl pcsound src textscreen 2> stderr.txt
|
||||
RET=$?
|
||||
if [ -s stderr.txt ]
|
||||
then
|
||||
cat stderr.txt
|
||||
fi
|
||||
exit $RET
|
||||
else
|
||||
set -e
|
||||
./autogen.sh --enable-werror
|
||||
make -j4
|
||||
make install DESTDIR=/tmp/whatever
|
||||
make dist
|
||||
PREFIX=`sed -n '/PROGRAM_PREFIX/p' ${PWD}/config.h | cut -d '"' -f 2`
|
||||
make -j4 -C quickcheck check SOURCE_PORT=$PWD/src/${PREFIX}doom
|
||||
fi
|
||||
7
games/NXDoom/AUTHORS
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Simon Howard <fraggle@gmail.com>
|
||||
James Haley <haleyjd@hotmail.com>
|
||||
Samuel Villarreal <svkaiser@gmail.com>
|
||||
Fabian Greffrath <fabian@greffrath.com>
|
||||
Jonathan Dowland <jon@dow.land>
|
||||
Alexey Khokholov <alexeytf2@gmail.com>
|
||||
Turo Lamminen <turol@iki.fi>
|
||||
105
games/NXDoom/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
project("Chocolate Doom" VERSION 3.1.1 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
# Autotools variables
|
||||
set(top_srcdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(top_builddir ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# AC_INIT variables
|
||||
set(PACKAGE_NAME "${PROJECT_NAME}")
|
||||
set(PACKAGE_TARNAME "chocolate-doom")
|
||||
set(PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
set(PACKAGE_STRING "${PROJECT_NAME} ${PROJECT_VERSION}")
|
||||
set(PACKAGE_BUGREPORT "chocolate-doom-dev-list@chocolate-doom.org")
|
||||
|
||||
string(REGEX REPLACE " Doom$" "" PACKAGE_SHORTNAME "${PACKAGE_NAME}")
|
||||
set(PACKAGE_COPYRIGHT "Copyright (C) 1993-2025")
|
||||
set(PACKAGE_LICENSE "GNU General Public License, version 2")
|
||||
|
||||
# Any settings that should apply to all targets in this directory and all
|
||||
# subdirectories should go here. Use judiciously.
|
||||
if(MSVC)
|
||||
add_definitions("/D_CRT_SECURE_NO_WARNINGS" "/D_CRT_SECURE_NO_DEPRECATE"
|
||||
"/D_CRT_NONSTDC_NO_DEPRECATE")
|
||||
else()
|
||||
add_compile_options("-Wall" "-Wdeclaration-after-statement"
|
||||
"-Wredundant-decls")
|
||||
endif()
|
||||
|
||||
option(CMAKE_FIND_PACKAGE_PREFER_CONFIG
|
||||
"Lookup package config files before using find modules" On)
|
||||
|
||||
option(ENABLE_SDL2_NET "Enable SDL2_net" On)
|
||||
option(ENABLE_SDL2_MIXER "Enable SDL2_mixer" On)
|
||||
|
||||
if (NOT DEFINED EMSCRIPTEN)
|
||||
find_package(SDL2 2.0.14)
|
||||
endif()
|
||||
if(ENABLE_SDL2_MIXER)
|
||||
if (NOT DEFINED EMSCRIPTEN)
|
||||
find_package(SDL2_mixer 2.0.2)
|
||||
endif()
|
||||
else()
|
||||
add_compile_definitions(DISABLE_SDL2MIXER=1)
|
||||
endif()
|
||||
|
||||
if(ENABLE_SDL2_NET)
|
||||
if (NOT DEFINED EMSCRIPTEN)
|
||||
find_package(SDL2_net 2.0.0)
|
||||
endif()
|
||||
else()
|
||||
add_compile_definitions(DISABLE_SDL2NET=1)
|
||||
endif()
|
||||
|
||||
|
||||
# Check for libsamplerate.
|
||||
find_package(SampleRate)
|
||||
if(SampleRate_FOUND)
|
||||
set(HAVE_LIBSAMPLERATE TRUE)
|
||||
endif()
|
||||
|
||||
# Check for libpng.
|
||||
find_package(PNG)
|
||||
if(PNG_FOUND)
|
||||
set(HAVE_LIBPNG TRUE)
|
||||
endif()
|
||||
|
||||
# Check for FluidSynth.
|
||||
find_package(FluidSynth 2.2.0)
|
||||
if(FluidSynth_FOUND AND ENABLE_SDL2_MIXER)
|
||||
set(HAVE_FLUIDSYNTH TRUE)
|
||||
endif()
|
||||
|
||||
find_package(m)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
include(CheckIncludeFile)
|
||||
check_symbol_exists(strcasecmp "strings.h" HAVE_DECL_STRCASECMP)
|
||||
check_symbol_exists(strncasecmp "strings.h" HAVE_DECL_STRNCASECMP)
|
||||
check_include_file("dirent.h" HAVE_DIRENT_H)
|
||||
|
||||
string(CONCAT WINDOWS_RC_VERSION "${PROJECT_VERSION_MAJOR}, "
|
||||
"${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH}, 0")
|
||||
|
||||
# Without a hyphen. This is used for the bash-completion scripts.
|
||||
string(TOLOWER "${PACKAGE_SHORTNAME}" PROGRAM_SPREFIX)
|
||||
|
||||
# With a hyphen, used almost everywhere else.
|
||||
set(PROGRAM_PREFIX "${PROGRAM_SPREFIX}-")
|
||||
|
||||
configure_file(cmake/config.h.cin config.h)
|
||||
|
||||
configure_file(src/doom-res.rc.in src/doom-res.rc)
|
||||
configure_file(src/heretic-res.rc.in src/heretic-res.rc)
|
||||
configure_file(src/hexen-res.rc.in src/hexen-res.rc)
|
||||
configure_file(src/setup-res.rc.in src/setup-res.rc)
|
||||
configure_file(src/setup/setup-manifest.xml.in src/setup/setup-manifest.xml)
|
||||
configure_file(src/strife-res.rc.in src/strife-res.rc)
|
||||
|
||||
foreach(SUBDIR textscreen opl pcsound src)
|
||||
add_subdirectory("${SUBDIR}")
|
||||
endforeach()
|
||||
74
games/NXDoom/CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at fraggle@gmail.com. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
361
games/NXDoom/COPYING.md
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
### GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
### Preamble
|
||||
|
||||
The licenses for most software are designed to take away your freedom
|
||||
to share and change it. By contrast, the GNU General Public License is
|
||||
intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on,
|
||||
we want its recipients to know that what they have is not the
|
||||
original, so that any problems introduced by others will not reflect
|
||||
on the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at
|
||||
all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
**0.** This License applies to any program or other work which
|
||||
contains a notice placed by the copyright holder saying it may be
|
||||
distributed under the terms of this General Public License. The
|
||||
"Program", below, refers to any such program or work, and a "work
|
||||
based on the Program" means either the Program or any derivative work
|
||||
under copyright law: that is to say, a work containing the Program or
|
||||
a portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".) Each licensee
|
||||
is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the Program
|
||||
(independent of having been made by running the Program). Whether that
|
||||
is true depends on what the Program does.
|
||||
|
||||
**1.** You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
**2.** You may modify your copy or copies of the Program or any
|
||||
portion of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
|
||||
**a)** You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
|
||||
**b)** You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any part
|
||||
thereof, to be licensed as a whole at no charge to all third parties
|
||||
under the terms of this License.
|
||||
|
||||
|
||||
**c)** If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such interactive
|
||||
use in the most ordinary way, to print or display an announcement
|
||||
including an appropriate copyright notice and a notice that there is
|
||||
no warranty (or else, saying that you provide a warranty) and that
|
||||
users may redistribute the program under these conditions, and telling
|
||||
the user how to view a copy of this License. (Exception: if the
|
||||
Program itself is interactive but does not normally print such an
|
||||
announcement, your work based on the Program is not required to print
|
||||
an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
**3.** You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
|
||||
**a)** Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections 1
|
||||
and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
|
||||
**b)** Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your cost of
|
||||
physically performing source distribution, a complete machine-readable
|
||||
copy of the corresponding source code, to be distributed under the
|
||||
terms of Sections 1 and 2 above on a medium customarily used for
|
||||
software interchange; or,
|
||||
|
||||
|
||||
**c)** Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is allowed
|
||||
only for noncommercial distribution and only if you received the
|
||||
program in object code or executable form with such an offer, in
|
||||
accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
**4.** You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt otherwise
|
||||
to copy, modify, sublicense or distribute the Program is void, and
|
||||
will automatically terminate your rights under this License. However,
|
||||
parties who have received copies, or rights, from you under this
|
||||
License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
**5.** You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
**6.** Each time you redistribute the Program (or any work based on
|
||||
the Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
**7.** If, as a consequence of a court judgment or allegation of
|
||||
patent infringement or for any other reason (not limited to patent
|
||||
issues), conditions are imposed on you (whether by court order,
|
||||
agreement or otherwise) that contradict the conditions of this
|
||||
License, they do not excuse you from the conditions of this License.
|
||||
If you cannot distribute so as to satisfy simultaneously your
|
||||
obligations under this License and any other pertinent obligations,
|
||||
then as a consequence you may not distribute the Program at all. For
|
||||
example, if a patent license would not permit royalty-free
|
||||
redistribution of the Program by all those who receive copies directly
|
||||
or indirectly through you, then the only way you could satisfy both it
|
||||
and this License would be to refrain entirely from distribution of the
|
||||
Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
**8.** If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
**9.** The Free Software Foundation may publish revised and/or new
|
||||
versions of the General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Program does not specify a
|
||||
version number of this License, you may choose any version ever
|
||||
published by the Free Software Foundation.
|
||||
|
||||
**10.** If you wish to incorporate parts of the Program into other
|
||||
free programs whose distribution conditions are different, write to
|
||||
the author to ask for permission. For software which is copyrighted by
|
||||
the Free Software Foundation, write to the Free Software Foundation;
|
||||
we sometimes make exceptions for this. Our decision will be guided by
|
||||
the two goals of preserving the free status of all derivatives of our
|
||||
free software and of promoting the sharing and reuse of software
|
||||
generally.
|
||||
|
||||
**NO WARRANTY**
|
||||
|
||||
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
**12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
### END OF TERMS AND CONDITIONS
|
||||
|
||||
### How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
one line to give the program's name and an idea of what it does.
|
||||
Copyright (C) yyyy name of author
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper
|
||||
mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
|
||||
type `show w'. This is free software, and you are welcome
|
||||
to redistribute it under certain conditions; type `show c'
|
||||
for details.
|
||||
|
||||
The hypothetical commands \`show w' and \`show c' should show the
|
||||
appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than \`show w' and
|
||||
\`show c'; they could even be mouse-clicks or menu items--whatever
|
||||
suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or
|
||||
your school, if any, to sign a "copyright disclaimer" for the program,
|
||||
if necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright
|
||||
interest in the program `Gnomovision'
|
||||
(which makes passes at compilers) written
|
||||
by James Hacker.
|
||||
|
||||
signature of Ty Coon, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library,
|
||||
you may consider it more useful to permit linking proprietary
|
||||
applications with the library. If this is what you want to do, use the
|
||||
[GNU Lesser General Public
|
||||
License](https://www.gnu.org/licenses/lgpl.html) instead of this
|
||||
License.
|
||||
5
games/NXDoom/ChangeLog
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
Chocolate Doom's version history is stored in Git. For a full
|
||||
change log, clone the repository on Github:
|
||||
|
||||
https://github.com/chocolate-doom/chocolate-doom
|
||||
|
||||
256
games/NXDoom/HACKING.md
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
# Coding style guidelines
|
||||
|
||||
The coding style guidelines for Chocolate Doom are designed to keep the
|
||||
style of the original source code. This maintains consistency throughout
|
||||
the program, and does not require the original code to be changed. Some
|
||||
of these guidelines are stricter than what was done in the original
|
||||
source; follow these when writing new code only: there is no need to
|
||||
change existing code to fit them.
|
||||
|
||||
You should set tabs to *display* as eight spaces, not four. However,
|
||||
*indentation* should be four spaces. If possible, do not use tab
|
||||
characters at all. There is a utility called “expand” which will remove
|
||||
tab characters. For the reasoning behind this, see:
|
||||
http://www.jwz.org/doc/tabs-vs-spaces.html
|
||||
|
||||
Please write code to an 80 column limit so that it fits within a standard
|
||||
80 column terminal. Do not leave trailing whitespace at the end of lines.
|
||||
|
||||
Functions should be named like this: `AB_FunctionName`. The `AB` prefix
|
||||
denotes the subsystem (`AM_` for automap, `G_` for game, etc). If a
|
||||
function is static, you can omit the prefix and just name it like
|
||||
`FunctionName`. Functions and global variables should always be made
|
||||
static if possible.
|
||||
|
||||
Put `_t` on the end of types created with typedef. Type names like this
|
||||
should be all lowercase and have the subsystem name at the start. An
|
||||
example of this is `txt_window_t`. When creating structures, always
|
||||
typedef them.
|
||||
|
||||
Do not use Hungarian notation.
|
||||
|
||||
Do not use the goto statement.
|
||||
|
||||
Use C++-style comments, ie. `//` comments, not `/* ... */` comments.
|
||||
I don’t care that this isn’t standard ANSI C.
|
||||
|
||||
Variables should be named like this: `my_variable_name`, not like this:
|
||||
`MyVariableName`. In pointer variable declarations, place the `*` next
|
||||
to the variable name, not the type.
|
||||
|
||||
When casting variables from one type to another, put a space after the
|
||||
last closing brace.
|
||||
|
||||
When using an if, do, while, or for statement, always use the { } braces
|
||||
even when they are not necessary. For example, do this:
|
||||
|
||||
```c
|
||||
if (condition)
|
||||
{
|
||||
body;
|
||||
}
|
||||
```
|
||||
|
||||
Not this:
|
||||
|
||||
```c
|
||||
if (condition) // NO
|
||||
body;
|
||||
```
|
||||
|
||||
Write code like this:
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
int member1;
|
||||
char *member2;
|
||||
} my_structure_t;
|
||||
|
||||
void FunctionName(int argument, int arg2, int arg3, int arg4, int arg5,
|
||||
int arg6, int arg7)
|
||||
{
|
||||
int assign_var;
|
||||
|
||||
assign_var = arg2 + arg3 * arg4 * (arg5 + arg6);
|
||||
|
||||
if (foo && !bar || baz && qux || !(foo && bar && baz))
|
||||
{
|
||||
body;
|
||||
}
|
||||
else if (xyz + 4 < abc * 4 + 3)
|
||||
{
|
||||
body;
|
||||
}
|
||||
else
|
||||
{
|
||||
body;
|
||||
}
|
||||
|
||||
if (very_long_condition_like_this_one_that_forces_a_line_break
|
||||
&& other_condition)
|
||||
{
|
||||
body;
|
||||
}
|
||||
|
||||
switch (argument)
|
||||
{
|
||||
case FIRST:
|
||||
code;
|
||||
break;
|
||||
|
||||
case SECOND:
|
||||
code;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (a = 0; a < 10; ++a)
|
||||
{
|
||||
FunctionCall(arg1, arg2, arg3, arg4,
|
||||
arg_split_onto_second_line);
|
||||
}
|
||||
|
||||
while (a < 10)
|
||||
{
|
||||
loop_body;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
} while (condition);
|
||||
}
|
||||
```
|
||||
|
||||
## Editor-specific default settings
|
||||
|
||||
If you use vim, you can put this into your `.vimrc` (or install the
|
||||
`localvimrc` script):
|
||||
|
||||
```
|
||||
set expandtab
|
||||
set tabstop=8
|
||||
set softtabstop=4
|
||||
set shiftwidth=4
|
||||
```
|
||||
|
||||
Or, if you use Emacs, put this in your `.emacs`:
|
||||
|
||||
```lisp
|
||||
(add-hook 'c-mode-hook (lambda ()
|
||||
(when (and buffer-file-name
|
||||
(string-match "chocolate-doom" buffer-file-name))
|
||||
(c-set-style "bsd")
|
||||
(setq indent-tabs-mode nil)
|
||||
(setq tab-width 8)
|
||||
(setq c-basic-offset 4))))
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
The C standard library has a number of unsafe functions that should be
|
||||
avoided when writing code for Chocolate Doom. These are:
|
||||
|
||||
Unsafe function | Safer alternative
|
||||
------------------|------------------------
|
||||
`gets()` | `fgets(.., stdin)`
|
||||
`sprintf` | `M_snprintf()`
|
||||
`snprintf` | `M_snprintf()`
|
||||
`vsprintf` | `M_vsnprintf()`
|
||||
`vsnprintf` | `M_vsnprintf()`
|
||||
`strcpy()` | `M_StringCopy()`
|
||||
`strncpy()` | `M_StringCopy()`
|
||||
`strcat()` | `M_StringConcat()`
|
||||
`strncat()` | `M_StringConcat()`
|
||||
`strdup()` | `M_StringDuplicate()`
|
||||
`realloc()` | `I_Realloc()`
|
||||
|
||||
Lots of the code includes calls to DEH_String() to simulate string
|
||||
replacement by the Dehacked tool. Be careful when using Dehacked
|
||||
replacements of printf format strings. For example, do not do this:
|
||||
|
||||
```c
|
||||
printf(DEH_String("foo %s"), s);
|
||||
sprintf(mybuf, DEH_String("bar %s"), t);
|
||||
```
|
||||
|
||||
Instead do this:
|
||||
|
||||
```c
|
||||
DEH_printf("foo %s", s);
|
||||
DEH_snprintf(mybuf, sizeof(mybuf), "bar %s", t);
|
||||
```
|
||||
|
||||
This does the format string replacement safely in a way that checks
|
||||
the arguments securely.
|
||||
|
||||
## Portability
|
||||
|
||||
Chocolate Doom is designed to be cross-platform and work on different
|
||||
Operating Systems and processors. Bear this in mind when writing code.
|
||||
|
||||
Do not use the `long` type (its size differs across platforms; use
|
||||
`int` or `int64_t` depending on which you want).
|
||||
|
||||
Use Doom’s byte data type for byte data. `int` is assumed to be a
|
||||
32-bit integer, and `short` is a 16-bit integer. You can also use the
|
||||
ISO C99 data types: `intN_t` and `uintN_t` where N is 8, 16, 32, 64.
|
||||
|
||||
Be careful with platform dependencies: do not use Windows API
|
||||
functions, for example. Use SDL where possible.
|
||||
|
||||
Preprocessor `#defines` are set that can be used to identify the OS
|
||||
if necessary: `_WIN32` for Windows and `__MACOSX__` for Mac OS X. Others
|
||||
are set through SDL. Try to avoid this if possible.
|
||||
|
||||
Be careful of endianness! Doom has `SHORT()` and `LONG()` macros that
|
||||
do endianness conversion. Never assume that integer types have a
|
||||
particular byte ordering. Similarly, never assume that fields
|
||||
inside a structure are aligned in a particular way. This is most
|
||||
relevant when reading or writing data to a file or a network pipe.
|
||||
|
||||
For signed integers, you shouldn’t assume that `(i >> n)` is the same as
|
||||
`(i / (1 << n))`. However, most processors handle bitshifts of signed
|
||||
integers properly, so it’s not a huge problem.
|
||||
|
||||
Due to Microsoft implementation of the Unicode support in C standard
|
||||
library you should use these wrappers to support non-latin paths and
|
||||
filenames on Windows.
|
||||
|
||||
C library function | Wrapper
|
||||
-------------------|-------------------
|
||||
`fopen()` | `M_fopen()`
|
||||
`remove()` | `M_remove()`
|
||||
`rename()` | `M_rename()`
|
||||
`stat()` | `M_stat()`
|
||||
`mkdir()` | `M_MakeDirectory()`
|
||||
`getenv()` | `M_getenv()`
|
||||
|
||||
## GNU GPL and licensing
|
||||
|
||||
All code submitted to the project must be licensed under the GNU GPLv2 or a
|
||||
compatible license. If you use code that you haven’t 100% written
|
||||
yourself, say so. Add a copyright header to the start of every file. Use
|
||||
this template:
|
||||
|
||||
```
|
||||
//
|
||||
// Copyright(C) YEAR Author's name
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// *File description goes here*
|
||||
//
|
||||
```
|
||||
62
games/NXDoom/Makefile.am
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
AUX_DIST_GEN = \
|
||||
$(ac_aux_dir)/install-sh \
|
||||
$(ac_aux_dir)/missing
|
||||
|
||||
CMAKE_FILES= \
|
||||
CMakeLists.txt \
|
||||
cmake/FindSDL2.cmake \
|
||||
cmake/FindSDL2_mixer.cmake \
|
||||
cmake/FindSDL2_net.cmake \
|
||||
cmake/FindFluidSynth.cmake \
|
||||
cmake/Findm.cmake \
|
||||
cmake/FindSampleRate.cmake \
|
||||
cmake/config.h.cin
|
||||
|
||||
DOC_FILES= \
|
||||
COPYING.md \
|
||||
README.md \
|
||||
README.Music.md \
|
||||
NEWS.md \
|
||||
PHILOSOPHY.md \
|
||||
ChangeLog
|
||||
|
||||
EXTRA_DIST= \
|
||||
$(AUX_DIST_GEN) \
|
||||
$(CMAKE_FILES) \
|
||||
$(DOC_FILES) \
|
||||
NOT-BUGS.md \
|
||||
README.Strife.md \
|
||||
.lvimrc \
|
||||
HACKING.md \
|
||||
TODO.md \
|
||||
rpm.spec \
|
||||
win32/win_opendir.c \
|
||||
win32/win_opendir.h
|
||||
|
||||
doomdocsdir = ${docdir}/../${PROGRAM_PREFIX}doom
|
||||
doomdocs_DATA = $(DOC_FILES) NOT-BUGS.md
|
||||
|
||||
hereticdocsdir = ${docdir}/../${PROGRAM_PREFIX}heretic
|
||||
hereticdocs_DATA = $(DOC_FILES)
|
||||
|
||||
hexendocsdir = ${docdir}/../${PROGRAM_PREFIX}hexen
|
||||
hexendocs_DATA = $(DOC_FILES)
|
||||
|
||||
strifedocsdir = ${docdir}/../${PROGRAM_PREFIX}strife
|
||||
strifedocs_DATA = $(DOC_FILES) README.Strife.md
|
||||
|
||||
MAINTAINERCLEANFILES = $(AUX_DIST_GEN)
|
||||
|
||||
SUBDIRS=textscreen opl pcsound data src man
|
||||
|
||||
DIST_SUBDIRS=pkg $(SUBDIRS)
|
||||
|
||||
if HAVE_DOC
|
||||
|
||||
INSTALL : man/INSTALL.template man/simplecpp
|
||||
$(srcdir)/man/simplecpp -DDOOM -DHERETIC -DHEXEN -DSTRIFE \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \
|
||||
< $(srcdir)/man/INSTALL.template > $@
|
||||
|
||||
endif
|
||||
1492
games/NXDoom/NEWS.md
Normal file
149
games/NXDoom/NOT-BUGS.md
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
The aim of Chocolate Doom is to behave as closely to Vanilla Doom as
|
||||
possible. As a result, you may experience problems that you would
|
||||
also experience when using Vanilla Doom. These are not “bugs” as
|
||||
Chocolate Doom is behaving as intended.
|
||||
|
||||
This is not intended to be a comprehensive list of Vanilla Doom bugs.
|
||||
For more information, consult the “engine bugs” page of the Doom Wiki.
|
||||
|
||||
## Game exits after title screen with message about game version
|
||||
|
||||
The game may exit after the title screen is shown, with a message like
|
||||
the following:
|
||||
|
||||
Demo is from a different game version!
|
||||
(read 2, should be 109)
|
||||
|
||||
*** You may need to upgrade your version of Doom to v1.9. ***
|
||||
See: https://www.doomworld.com/classicdoom/info/patches.php
|
||||
This appears to be v1.0/v1.1/v1.2.
|
||||
|
||||
This usually indicates that your IWAD file that you are using to play
|
||||
the game (usually named doom.wad or doom2.wad) is out of date.
|
||||
Chocolate Doom only supports versions 1.666 through 1.9.
|
||||
|
||||
To fix the problem, you must upgrade your IWAD file, preferably
|
||||
to 1.9. The URL in the message has downloadable upgrade patches that
|
||||
you can use to upgrade.
|
||||
|
||||
## Game exits in demo loop when playing Final Doom
|
||||
|
||||
When playing with the Final Doom IWAD files (tnt.wad, plutonia.wad),
|
||||
if you leave the game at the title screen to play through the demo
|
||||
loop, it will eventually exit with the following error message:
|
||||
|
||||
W_GetNumForName: demo4 not found!
|
||||
|
||||
This is the same behavior as the Vanilla executables that were
|
||||
bundled with Final Doom. When Ultimate Doom was developed, a fourth
|
||||
demo was added to the demo loop, and this change was retained in the
|
||||
Final Doom version of the executable. However, the Final Doom IWADs
|
||||
do not include a fourth demo, so the game crashes.
|
||||
|
||||
An alternate version of Final Doom was included in the Id Anthology
|
||||
boxed set, and this version of the game fixed this bug. However, this
|
||||
version also changes the teleport behavior, so the default is to
|
||||
emulate the most commonly distributed version of the game. To use
|
||||
the alternate version, run with:
|
||||
|
||||
chocolate-doom -gameversion final2
|
||||
|
||||
## Game exits when accessing the options menu
|
||||
|
||||
The game may exit with the message “Bad V_DrawPatch” when accessing
|
||||
the options menu, if you have your mouse sensitivity set high.
|
||||
|
||||
The Doom options menu has a slider that allows the mouse sensitivity
|
||||
to be controlled; however, it has only a very limited range. It is
|
||||
common for experienced players to set a mouse sensitivity that is much
|
||||
higher than what can be set via the options menu. The setup program
|
||||
allows a larger range of values to be set.
|
||||
|
||||
However, setting very high sensitivity values causes the game to exit
|
||||
when accessing the options menu under Vanilla Doom. Because Chocolate
|
||||
Doom aims to emulate Vanilla Doom as closely as possible, it does the
|
||||
same thing.
|
||||
|
||||
One solution to the problem is to set a lower mouse sensitivity.
|
||||
Alternatively, all of the settings in the options menu can be
|
||||
controlled through Doom’s key bindings anyway:
|
||||
|
||||
Option | Key
|
||||
---------------------------|-----
|
||||
End game | F7
|
||||
Messages on/off | F8
|
||||
Graphic detail high/low | F5
|
||||
Screen size smaller/larger | -/+
|
||||
Sound volume menu | F4
|
||||
|
||||
## Game exits with “Savegame buffer overrun” when saving the game
|
||||
|
||||
If you are playing on a particularly large level, it is possible that
|
||||
when you save the game, the game will quit with the message “Savegame
|
||||
buffer overrun”.
|
||||
|
||||
Vanilla Doom has a limited size memory buffer that it uses for saving
|
||||
games. If you are playing on a large level, the buffer may be too
|
||||
small for the entire savegame to fit. Chocolate Doom allows the limit
|
||||
to be disabled: in the setup tool, go to the “compatibility” menu and
|
||||
disable the “Vanilla savegame limit” option.
|
||||
|
||||
If this error happens to you, your game has not been lost! A file
|
||||
named temp.dsg is saved; rename this to doomsav0.dsg to make it appear
|
||||
in the first slot in the “load game” menu. (On Unix systems, you will
|
||||
need to look in the .chocolate-doom/savegames directory in your home
|
||||
directory)
|
||||
|
||||
## Game ends suddenly when recording a demo
|
||||
|
||||
If you are recording a very long demo, the game may exit suddenly.
|
||||
Vanilla Doom has a limited size memory buffer that it uses to save the
|
||||
demo into. When the buffer is full, the game exits. You can tell if
|
||||
this happens, as the demo file will be around 131,072 bytes in size.
|
||||
|
||||
You can work around this by using the -maxdemo command line parameter
|
||||
to specify a larger buffer size. Alternatively, the limit can be
|
||||
disabled: in the setup tool, go to the compatibility menu and disable
|
||||
the “Vanilla demo limit” option.
|
||||
|
||||
## Game exits with a message about “visplanes”
|
||||
|
||||
The game may exit with one of these messages:
|
||||
|
||||
R_FindPlane: no more visplanes
|
||||
R_DrawPlanes: visplane overflow (129)
|
||||
|
||||
This is known as the “visplane overflow” limit and is one of the most
|
||||
well-known Vanilla Doom engine limits. You should only ever experience
|
||||
this when trying to play an add-on level. The level you are trying to
|
||||
play is too complex; it was most likely designed to work with a limit
|
||||
removing source port.
|
||||
|
||||
More information can be found here (archived link): https://archive.is/s6h7V
|
||||
|
||||
## IDMUS## cheat doesn’t work with shareware/registered Doom IWADs
|
||||
|
||||
The IDMUS cheat allows the in-game music to be changed. However, in
|
||||
the original v1.9 this cheat didn’t work properly when playing with
|
||||
the Doom 1 (shareware and registered) IWADs. This bug was fixed in
|
||||
the Ultimate Doom and Final Doom executables.
|
||||
|
||||
Chocolate Doom emulates this bug. When playing with the shareware or
|
||||
registered Doom IWADs, the IDMUS cheat therefore does not work
|
||||
properly. If you are playing with the Ultimate Doom IWAD, the
|
||||
Ultimate Doom executable is emulated by default, so the cheat works
|
||||
properly.
|
||||
|
||||
## Some graphics are wrong when playing with BFG Edition IWADs
|
||||
|
||||
If you are playing using the IWAD files from Doom 3: BFG Edition, you
|
||||
may notice that certain graphics appear strange or wrong. This
|
||||
includes the title screen, and parts of the options menu.
|
||||
|
||||
The IWAD files in the new BFG Edition have had some significant
|
||||
changes from the IWAD files in older releases. Some of the graphics
|
||||
lumps have been removed or changed, and the Doom 2 secret levels are
|
||||
also censored. Chocolate Doom includes some small workarounds that
|
||||
allow the game to run, but for the best experience, it’s best to get a
|
||||
copy of the classic versions of the IWADs. These are still available
|
||||
to buy from Steam or GOG.com.
|
||||
214
games/NXDoom/PHILOSOPHY.md
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
Chocolate Doom has been designed around a careful and deliberate
|
||||
philosophy that attempts to recreate the original (“Vanilla”) DOS
|
||||
executables for Doom, Heretic, Hexen and Strife. This document
|
||||
describes some of that philosophy and the reasoning behind it.
|
||||
|
||||
This document is descriptive, not proscriptive.
|
||||
|
||||
# Vanilla behavior
|
||||
|
||||
Ideally Chocolate Doom aims to recreate the behavior of the Vanilla
|
||||
binaries, but different aspects of Vanilla behavior are held to
|
||||
varying degrees of importance. It can be imagined as different “tiers”
|
||||
of compatibility:
|
||||
|
||||
* The game and gameplay itself is of central importance. Here, the
|
||||
Vanilla behavior ought to be maintained as accurately as possible.
|
||||
This includes the look, feel and sound, and things like demo
|
||||
compatibility.
|
||||
* The surrounding aspects of the game that aren’t part of the central
|
||||
gameplay experience can be extended as long as there’s a good
|
||||
reason and Vanilla behavior is respected.
|
||||
* The setup tool is not required to reproduce the behavior of the
|
||||
Vanilla setup tool, even though it reproduces its look and feel.
|
||||
|
||||
“Vanilla” is defined as:
|
||||
|
||||
* DOS Doom 1.9 (although there are actually multiple “1.9”s).
|
||||
* DOS Heretic 1.3.
|
||||
* DOS Hexen 1.1 (although there are actually two known “1.1”s).
|
||||
* DOS Strife 1.31.
|
||||
* DOS Chex Quest.
|
||||
|
||||
Compatibility with older versions of the DOS binaries is also a
|
||||
secondary goal (though not pre-release versions). Other ports (either
|
||||
official or unofficial) are out of scope: this includes console ports,
|
||||
non-DOS ports, Doom 95 and Doom 3: BFG Edition.
|
||||
|
||||
# Compatibility
|
||||
|
||||
Chocolate Doom aims to be compatible with Vanilla Doom in several
|
||||
different ways. Examples are:
|
||||
|
||||
* Bug compatibility: the aim is to emulate compatibility of the
|
||||
original game down to bugs that were present in the DOS
|
||||
executables. This includes maintaining the limitations of the
|
||||
original engine: for example, the infamous “visplane overflow” bug
|
||||
is intentionally still present, where other source ports have
|
||||
removed it; this allows mappers targeting Vanilla Doom to use
|
||||
Chocolate Doom as a faithful substitute.
|
||||
* Demo compatibility: Doom was one of the first games to develop a
|
||||
‘speedrunning’ community, and thousands of recordings of Doom
|
||||
gameplay (`.lmp` demo files) exist in the Compet-N archive. Chocolate
|
||||
Doom aims for the highest standard of demo compatibility with
|
||||
Vanilla Doom, a goal that is often complicated by obscure behavior
|
||||
that can be difficult to reproduce.
|
||||
* Configuration file compatibility: Chocolate Doom uses the same
|
||||
configuration file format as Vanilla Doom, such that a user should
|
||||
be able to reuse their existing Vanilla configuration file without
|
||||
making any changes. Extra non-Vanilla options are stored in a
|
||||
separate configuration file.
|
||||
* Savegame file compatibility: Chocolate Doom uses the same savegame
|
||||
file format as Vanilla, such that it should be possible to import
|
||||
and use existing savegame files.
|
||||
|
||||
# DOS tools
|
||||
|
||||
Chocolate Doom includes some features that aren’t part of Vanilla Doom
|
||||
but exist for compatibility with DOS tools that interact with it.
|
||||
These are considered part of the Vanilla experience and ought to be
|
||||
treated as such. Some examples are:
|
||||
|
||||
* The novert setting, which reproduces the functionality of
|
||||
`novert.exe`.
|
||||
* The `-deh` parameter, which loads Dehacked patches like dehacked.exe
|
||||
does under DOS. Chocolate Doom imposes the same limitations that
|
||||
Vanilla Dehacked does.
|
||||
|
||||
# Exceptions
|
||||
|
||||
Chocolate Doom differs from Vanilla Doom in a number of ways. In most
|
||||
cases these are subtle, minor differences. Nonetheless they deserve
|
||||
some explanation and justification. Here are some examples of
|
||||
situations where changes are considered acceptable:
|
||||
|
||||
1. Vanilla behavior can be broken that is harmful, eg. can damage the
|
||||
player’s computer, or is just outright misleading. For example:
|
||||
|
||||
- Vanilla uses unbounded sprintf and strcpy (security issue).
|
||||
- Vanilla has crashes that force the user to reboot the machine.
|
||||
- Vanilla has an out of memory message that recommends tweaking
|
||||
CONFIG.SYS. As Chocolate Doom doesn’t run under DOS, reproducing
|
||||
this message would not be helpful.
|
||||
|
||||
2. Subtly extending behavior is okay where it’s not clear what the
|
||||
Vanilla behavior is anyway. For example:
|
||||
|
||||
- Opening the menu releases mouse grab in Chocolate Doom.
|
||||
- Chocolate Hexen’s graphical startup screen runs in a window.
|
||||
|
||||
3. Supporting obsolete technology is not a goal: it’s considered
|
||||
acceptable that Chocolate Doom does not support every type of
|
||||
hardware from 1993. However, Chocolate Doom should aim to recreate
|
||||
the functionality in a modern way. Examples of technologies that
|
||||
aren’t supported are:
|
||||
|
||||
- No support for IPX networks, but TCP/IP is supported instead.
|
||||
- No support for dial-up/serial connections; modern operating
|
||||
systems have features that do that for you.
|
||||
- No MS-DOS version.
|
||||
|
||||
4. Changes are acceptable that allow the player to be able play the
|
||||
game. For example:
|
||||
|
||||
- There are new key bindings for actions that can’t be rebound with
|
||||
Vanilla Doom, because it’s useful for portability to machines
|
||||
that don’t have a full keyboard.
|
||||
- There are additional mouse and joystick button bindings that let
|
||||
you perform actions with them that can only be done with the
|
||||
keyboard in Vanilla Doom.
|
||||
- Chocolate Doom includes some hacks to support the Doom 3: BFG
|
||||
Edition IWAD files. The assumption is that being able to at least
|
||||
play is better than nothing, even if it’s not Vanilla behavior.
|
||||
- Chocolate Strife does not emulate the save bug from
|
||||
Vanilla 1.31, which could corrupt saves when overwriting a slot,
|
||||
if the old slot was not part of the current game’s progression.
|
||||
Vanilla behavior is unexpected and potentially devastating.
|
||||
|
||||
5. Adding extra options to Vanilla functionality is acceptable as long
|
||||
as the defaults match Vanilla, it doesn’t change gameplay and
|
||||
there’s a good reason for it. For example:
|
||||
|
||||
- PNG screenshots are supported because PCX is an obsolete format.
|
||||
- Chocolate Doom has the vanilla_keyboard_mapping option that
|
||||
allows the user to use the native keyboard mapping for their
|
||||
computer, rather than always assuming a US layout.
|
||||
|
||||
6. Changing configuration file defaults is acceptable where there’s a
|
||||
very good reason. For example:
|
||||
|
||||
- Vanilla Doom defaults to no sound or music if a configuration
|
||||
file is not found. Chocolate Doom defaults to having sound
|
||||
effects and music turned on by default, because modern computers
|
||||
support these; there’s no need to configure hardware IRQ settings
|
||||
to get sound working.
|
||||
|
||||
7. Things can be changed if they’re really just inconsequential. For
|
||||
example:
|
||||
|
||||
- The startup messages in Chocolate Doom are not identical to
|
||||
Vanilla Doom and are not necessarily in the same order.
|
||||
- Vanilla Doom has command line options named `-comdev`, `-shdev`
|
||||
and `-regdev` used by id internally for development; these have
|
||||
been removed.
|
||||
|
||||
8. Expansions to the vanilla demo formats are allowed, to make
|
||||
recording and playback of vanilla gameplay more convenient, with
|
||||
the following restrictions:
|
||||
|
||||
- Such expansions are not supported in WAD files (they are not
|
||||
an editing feature for WAD authors to use).
|
||||
- Support for these features can be completely disabled using the
|
||||
`-strictdemos` command line argument.
|
||||
- A warning is shown to the user on the console (stdout) when a
|
||||
demo using one of these features is recorded or played back.
|
||||
|
||||
A good litmus test of when it’s acceptable to break from Vanilla
|
||||
behavior is to ask the question: “Although this is Vanilla behavior,
|
||||
is there anyone who would want this?”
|
||||
|
||||
For example, emulating Vanilla bugs like the visplane overflow bug is
|
||||
something that is useful for people making Vanilla format maps. On the
|
||||
other hand, painstakingly emulating Vanilla Doom by starting with no
|
||||
sound or music by default is not helpful to anyone.
|
||||
|
||||
# Minimalism
|
||||
|
||||
Chocolate Doom aims to be minimalist and straightforward to configure;
|
||||
in particular, the setup tool should have a sane interface. Part of
|
||||
the inspiration for Chocolate Doom came from Boom’s complicated maze
|
||||
of options menus (and a desire to avoid them). Too many preferences
|
||||
lead to a bad user interface; see Havoc Pennington’s essay on Free
|
||||
Software UI:
|
||||
|
||||
http://ometer.com/free-software-ui.html
|
||||
|
||||
Chocolate Doom has some options that are quite obscure and only really
|
||||
of interest to a small number of people. In these cases, the options
|
||||
are hidden away in configuration files and deliberately not exposed in
|
||||
the setup tool. The assumption is that if you care enough about those
|
||||
obscure features, editing a configuration file by hand should not be a
|
||||
huge problem for you.
|
||||
|
||||
Also inspirational was the README file from Havoc’s Metacity window
|
||||
manager, where the list of features begins:
|
||||
|
||||
> Boring window manager for the adult in you. Many window managers
|
||||
> are like Marshmallow Froot Loops; Metacity is like Cheerios.
|
||||
|
||||
I’d like to think that Chocolate Doom’s philosophy towards features is
|
||||
similar. The idea is for a source port that is boring. I find the best
|
||||
software - both proprietary and open source - is software that is
|
||||
“egoless”: it does a job well without pretentions about its importance
|
||||
or delusions of grandeur. A couple of other notable examples of
|
||||
software that I feel embody this spirit of design in a beautiful way
|
||||
are Marco Pesenti Gritti’s Epiphany web browser and Evince PDF viewer.
|
||||
|
||||
# Other philosophical aspects
|
||||
|
||||
Chocolate Doom aims for maximal portability. That includes running on
|
||||
many different CPUs, different operating systems and different devices
|
||||
(ie. not just a desktop machine with a keyboard and mouse).
|
||||
|
||||
Chocolate Doom is and will always remain Free Software. It will never
|
||||
include code that is not compatible with the GNU GPL.
|
||||
173
games/NXDoom/README.Music.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
Doom has a memorable and atmospheric soundtrack. Like many games of
|
||||
the era, it is MIDI-based. Chocolate Doom includes a number of
|
||||
different options for music playback, detailed below.
|
||||
|
||||
# Native MIDI playback
|
||||
|
||||
Most modern operating systems have some kind of built-in support for
|
||||
MIDI playback; some have very good quality MIDI playback (Mac OS X for
|
||||
example). To use this, choose “Native MIDI” in the sound configuration
|
||||
dialog in the setup tool.
|
||||
|
||||
# Timidity
|
||||
|
||||
Timidity is a software-based MIDI synthesizer, and a version of it is
|
||||
included in the SDL2_mixer library used by Chocolate Doom. To use
|
||||
Timidity for MIDI playback, first download a sound font. An example of
|
||||
a good quality sound font is the eawpats font, which can be downloaded
|
||||
from the idgames archive as sounds/eawpats.zip:
|
||||
|
||||
https://www.doomworld.com/idgames/sounds/eawpats
|
||||
|
||||
Having installed a sound font, select “Native MIDI” in the sound
|
||||
configuration dialog in the setup tool, and use the “Timidity
|
||||
configuration file” widget below to enter the path to the Timidity
|
||||
configuration file (normally named timidity.cfg).
|
||||
|
||||
# Gravis Ultrasound (GUS)
|
||||
|
||||
The Gravis Ultrasound (GUS) was a PC sound card popular in the ’90s,
|
||||
notable for having wavetable synthesis that provided MIDI playback
|
||||
that was superior to most other cards of the era. Chocolate Doom
|
||||
includes a “pseudo-GUS emulation” feature that simulates the GUS
|
||||
(using Timidity, under the hood).
|
||||
|
||||
To use this feature you need a copy of the GUS patch files that were
|
||||
distributed with the original GUS patches. If you have Doom 3: BFG
|
||||
Edition, these patches are included with its version of classic Doom,
|
||||
and are automatically detected. Otherwise, they can be downloaded
|
||||
from the idgames archive as music/dgguspat.zip:
|
||||
|
||||
https://www.doomworld.com/idgames/music/dgguspat
|
||||
|
||||
Having downloaded the patches, select “GUS (emulated)” in the sound
|
||||
configuration dialog in the setup tool, and use the “GUS patch path”
|
||||
widget to enter the path to the directory containing the patch files.
|
||||
|
||||
For the music not to sound weird, you will almost certainly want to
|
||||
load gusgonna.wad (sounds/gusgonna.zip in the idgames archive) when
|
||||
you run the game, to work around a bug in vanilla Doom's instrument
|
||||
mappings parser:
|
||||
|
||||
https://www.doomworld.com/idgames/sounds/gusgonna
|
||||
|
||||
By default a GUS card with 1024KB is simulated; to simulate a 256KB,
|
||||
512KB or 768KB card instead, change the gus_ram_kb option in
|
||||
chocolate-doom.cfg.
|
||||
|
||||
# OPL (Soundblaster / Adlib)
|
||||
|
||||
Most people playing Doom in the ’90s had Soundblaster-compatible sound
|
||||
cards, which used the Yamaha OPL series of chips for FM-based MIDI
|
||||
synthesis. Chocolate Doom includes the ability to emulate these chips
|
||||
for a retro experience. OPL emulation is the default MIDI playback,
|
||||
but can be selected in the setup tool as “OPL (Adlib/SB)”.
|
||||
|
||||
Most modern computers do not include an OPL chip any more, as CPUs are
|
||||
fast enough to do decent software MIDI synthesis. However, no software
|
||||
emulator sounds exactly like a real (hardware) OPL chip, and a few
|
||||
cards do have real hardware OPL. If you have such a card, here’s how
|
||||
to configure Chocolate Doom to use it.
|
||||
|
||||
## Sound cards with OPL chips
|
||||
|
||||
If you have an ISA sound card, it almost certainly includes an OPL
|
||||
chip. Modern computers don’t have slots for ISA cards though, so you
|
||||
must be running a pretty old machine.
|
||||
|
||||
If you have a PCI sound card, you probably don’t have an OPL chip.
|
||||
However, there are some exceptions to this. The following cards are
|
||||
known to include “legacy” OPL support:
|
||||
|
||||
* C-Media CMI8738 (*)
|
||||
* Forte Media FM801
|
||||
* Cards based on the Yamaha YMF724 (*)
|
||||
|
||||
Other cards that apparently have OPL support but have not been tested:
|
||||
|
||||
* S3 SonicVibes
|
||||
* AZTech PCI 168 (AZT 3328 chipset)
|
||||
* ESS Solo-1 sound cards (ES1938, ES1946, ES1969 chipset)
|
||||
* Conexant Riptide Audio/Modem combo cards
|
||||
* Cards based on the Crystal Semiconductors CS4281
|
||||
* Cards based on the Avance Logic ALS300
|
||||
* Cards based on the Avance Logic ALS4000
|
||||
|
||||
If you desperately want hardware OPL music, you may be able to find
|
||||
one of these cards for sale cheap on eBay.
|
||||
|
||||
For the cards listed above with (\*) next to them, OPL support is
|
||||
disabled by default and must be explictly enabled in software. See
|
||||
sections below for operating system-specific instructions on how you
|
||||
may be able to do this.
|
||||
|
||||
If your machine is not a PC, you don’t have an OPL chip, and you will
|
||||
have to use the software OPL.
|
||||
|
||||
## Operating System support
|
||||
|
||||
If you’re certain that you have a sound card with hardware OPL, you
|
||||
may need to take extra steps to configure your operating system to
|
||||
allow access to it. To do hardware OPL, Chocolate Doom must access
|
||||
the chip directly, which is usually not possible in modern operating
|
||||
systems unless you are running as the superuser (root/Administrator).
|
||||
|
||||
### Microsoft Windows
|
||||
|
||||
On modern Windows systems it is not possible to directly access the
|
||||
OPL chip, even when running as Administrator. Fortunately, it is
|
||||
possible to use the “ioperm.sys” driver developed for Cygwin (look for
|
||||
iopermsys-0.2.1.tar.bz2):
|
||||
|
||||
http://openwince.sourceforge.net/ioperm/
|
||||
|
||||
It is not necessary to have Cygwin installed to use this. Copy the
|
||||
ioperm.sys file into the same directory as the Chocolate Doom
|
||||
executable and it should be automatically loaded.
|
||||
|
||||
You can confirm that hardware OPL is working by checking for this
|
||||
message in stdout.txt:
|
||||
|
||||
OPL_Init: Using driver 'Win32'.
|
||||
|
||||
If you have a C-Media CMI8738, you may need to enable the `FM_EN`
|
||||
flag in Windows Device Manager to access hardware OPL output. See
|
||||
[this](http://www.vogons.org/viewtopic.php?f=46&t=36445) thread on
|
||||
vogons.org for some more information.
|
||||
|
||||
### Linux
|
||||
|
||||
If you are using a system based on the Linux kernel, you can access
|
||||
the OPL chip directly, but you must be running as root. You can
|
||||
confirm that hardware OPL is working, by checking for this message on
|
||||
startup:
|
||||
|
||||
OPL_Init: Using driver 'Linux'.
|
||||
|
||||
If you are using one of the PCI cards in the list above with a (*)
|
||||
next to it, you may need to manually enable FM legacy support. Add
|
||||
the following to your /etc/modprobe.conf file to do this:
|
||||
|
||||
options snd-ymfpci fm_port=0x388
|
||||
options snd-cmipci fm_port=0x388
|
||||
|
||||
### OpenBSD/NetBSD
|
||||
|
||||
You must be running as root to access the hardware OPL directly. You
|
||||
can confirm that hardware OPL is working by checking for this message
|
||||
on startup:
|
||||
|
||||
OPL_Init: Using driver 'OpenBSD'.
|
||||
|
||||
There is no native OPL backend for FreeBSD yet. Sorry!
|
||||
|
||||
# Other options
|
||||
|
||||
If you have some other favorite MIDI playback option that isn’t
|
||||
listed above, you can set a hook to invoke an external command for
|
||||
MIDI playback using the ‘snd_musiccmd’ configuration file option. For
|
||||
example, set:
|
||||
|
||||
snd_musiccmd "aplaymidi -p 128:0"
|
||||
|
||||
in your chocolate-doom.cfg file.
|
||||
124
games/NXDoom/README.Strife.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
````````````````````````````````````````````````````````````````````````
|
||||
|
||||
Samuel ‘Kaiser’ Villarreal and James ‘Quasar’ Haley Present
|
||||
|
||||
C H O C O L A T E
|
||||
______________________________._________________________
|
||||
/ _____/\__ ___/\______ \ \_ _____/\_ _____/
|
||||
\_____ \ | | | _/ || __) | __)_
|
||||
/ \ | | | | \ || \ | \
|
||||
/_______ / |____| |____|_ /___|\___ / /_______ /
|
||||
\/ \/ \/ \/
|
||||
|
||||
````````````````````````````````````````````````````````````````````````
|
||||
|
||||
## What is it?
|
||||
|
||||
Chocolate Strife is the most accurate and complete recreation of Rogue
|
||||
Entertainment’s “Strife: Quest for the Sigil.” It was created through more
|
||||
than four years of reverse engineering effort with the blessings of the
|
||||
original programmers of the game.
|
||||
|
||||
|
||||
## Why?
|
||||
|
||||
The source code for Strife was lost, which means, unlike the code for all the
|
||||
other commercial DOOM-engine games, it cannot be released. The only access we
|
||||
have to the code is the binary executable file. Tools such as IDA Pro have
|
||||
been employed to disassemble and decompile the executable, which was cross-
|
||||
referenced against the Linux DOOM and DOS Heretic sources and painstakingly
|
||||
combed over multiple times, instruction-by-instruction, to ensure that the
|
||||
resulting Chocolate Doom-based executable is as close as possible to the
|
||||
original.
|
||||
|
||||
|
||||
## Is it Legal?
|
||||
|
||||
Chocolate Strife was originally reverse-engineered from the DOS Strife
|
||||
binaries. Although reverse engineering is legally a protected activity, this
|
||||
nonetheless left some open questions about its legal status.
|
||||
|
||||
In 2014, a new commercial release of Strife was published (Strife: Veteran
|
||||
Edition) based on the Chocolate Strife code, and developed by the authors of
|
||||
Chocolate Strife under commercial license. The release of Strife: Veteran
|
||||
Edition, along with its GPL-licensed source code, constitutes tacit approval
|
||||
for the legal status of Chocolate Strife by its current copyright holder.
|
||||
|
||||
|
||||
## Is it Perfect?
|
||||
|
||||
Almost, but not entirely! That’s where you come in. Help us by reporting any
|
||||
discrepancies you may notice between this executable and the vanilla DOS
|
||||
program!
|
||||
|
||||
However, do *not* report any glitch that you can replicate in the vanilla EXE
|
||||
as a bug. The point of Chocolate Strife, like Chocolate Doom before it, is to
|
||||
be as bug-compatible with the original game as possible. Also be aware that
|
||||
some glitches are impossible to compatibly recreate, and wherever this is the
|
||||
case, Chocolate Strife has erred on the side of not crashing the program,
|
||||
for example by initializing pointers to NULL rather than using them without
|
||||
setting a value first.
|
||||
|
||||
|
||||
## What are some known problems?
|
||||
|
||||
The demo version is *not* supported, and there are not any current plans to
|
||||
support it in the future, due to the vast number of differences (the demo
|
||||
version of Strife is based on an earlier version of Rogue’s
|
||||
codebase).
|
||||
|
||||
The commercial Strife IWAD version 1.1 may run, but also exhibit issues. Like
|
||||
the demo version, there are no current plans to fully support it. Make sure
|
||||
your copy is updated to at least 1.2. Strife: Veteran Edition already
|
||||
includes the required version.
|
||||
|
||||
|
||||
## How do I use it?
|
||||
|
||||
From the Run box or a command line, issue a command to Chocolate Strife just
|
||||
like you would run Chocolate Doom. Most of the same command line parameters
|
||||
are supported.
|
||||
|
||||
voices.wad will be read from the same directory as the IWAD, if it can be
|
||||
found. If it is not found, then voices will be disabled just as would happen
|
||||
with the vanilla executable. Do not add voices.wad using -file, as that is
|
||||
redundant and unnecessary.
|
||||
|
||||
Some new command-line parameters in Chocolate Strife include the following:
|
||||
|
||||
- -nograph
|
||||
- Disables the graphical introduction sequence. -devparm implies this.
|
||||
|
||||
- -novoice
|
||||
- Disables voices even if voices.wad can be found.
|
||||
|
||||
- -work
|
||||
- Enables Rogue’s playtesting mode. Automatic godmode, and pressing the
|
||||
inventory drop key will toggle noclipping.
|
||||
|
||||
- -flip
|
||||
- Flips player gun graphics. This is buggy, however, because it does not
|
||||
reverse the graphics’ x offsets (this is an accurate emulation of the
|
||||
vanilla engine’s behavior).
|
||||
|
||||
- -random
|
||||
- Randomizes the timing and location of item respawns in deathmatch, when
|
||||
item respawning is enabled.
|
||||
|
||||
|
||||
## Copyright
|
||||
|
||||
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.
|
||||
|
||||
See the “COPYING” file for the full license text. The source code for this
|
||||
program is available from the same location where you downloaded this package.
|
||||
|
||||
Aside from Chocolate Doom, portions of the code are derived from the Eternity
|
||||
Engine, Copyright 2011 Team Eternity, as published under the GNU GPL.
|
||||
102
games/NXDoom/README.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
# Chocolate Doom
|
||||
|
||||
Chocolate Doom aims to accurately reproduce the original DOS version of
|
||||
Doom and other games based on the Doom engine in a form that can be
|
||||
run on modern computers.
|
||||
|
||||
Originally, Chocolate Doom was only a Doom source port. The project
|
||||
now includes ports of Heretic and Hexen, and Strife.
|
||||
|
||||
Chocolate Doom’s aims are:
|
||||
|
||||
* To always be 100% Free and Open Source software.
|
||||
* Portability to as many different operating systems as possible.
|
||||
* Accurate reproduction of the original DOS versions of the games,
|
||||
including bugs.
|
||||
* Compatibility with the DOS demo, configuration and savegame files.
|
||||
* To provide an accurate retro “feel” (display and input should
|
||||
behave the same).
|
||||
|
||||
More information about the philosophy and design behind Chocolate Doom
|
||||
can be found in the PHILOSOPHY file distributed with the source code.
|
||||
|
||||
## Setting up gameplay
|
||||
|
||||
For instructions on how to set up Chocolate Doom for play, see the
|
||||
INSTALL file.
|
||||
|
||||
## Configuration File
|
||||
|
||||
Chocolate Doom is compatible with the DOS Doom configuration file
|
||||
(normally named `default.cfg`). Existing configuration files for DOS
|
||||
Doom should therefore simply work out of the box. However, Chocolate
|
||||
Doom also provides some extra settings. These are stored in a
|
||||
separate file named `chocolate-doom.cfg`.
|
||||
|
||||
The configuration can be edited using the chocolate-setup tool.
|
||||
|
||||
## Command line options
|
||||
|
||||
Chocolate Doom supports a number of command line parameters, including
|
||||
some extras that were not originally suported by the DOS versions. For
|
||||
binary distributions, see the CMDLINE file included with your
|
||||
download; more information is also available on the Chocolate Doom
|
||||
website.
|
||||
|
||||
## Playing TCs
|
||||
|
||||
With Vanilla Doom there is no way to include sprites in PWAD files.
|
||||
Chocolate Doom’s ‘-file’ command line option behaves exactly the same
|
||||
as Vanilla Doom, and trying to play TCs by adding the WAD files using
|
||||
‘-file’ will not work.
|
||||
|
||||
Many Total Conversions (TCs) are distributed as a PWAD file which must
|
||||
be merged into the main IWAD. Typically a copy of DEUSF.EXE is
|
||||
included which performs this merge. Chocolate Doom includes a new
|
||||
option, ‘-merge’, which will simulate this merge. Essentially, the
|
||||
WAD directory is merged in memory, removing the need to modify the
|
||||
IWAD on disk.
|
||||
|
||||
To play TCs using Chocolate Doom, run like this:
|
||||
|
||||
```
|
||||
chocolate-doom -merge thetc.wad
|
||||
```
|
||||
|
||||
Here are some examples:
|
||||
|
||||
```
|
||||
chocolate-doom -merge batman.wad -deh batman.deh vbatman.deh (Batman Doom)
|
||||
chocolate-doom -merge aoddoom1.wad -deh aoddoom1.deh (Army of Darkness Doom)
|
||||
```
|
||||
|
||||
## Other information
|
||||
|
||||
* Chocolate Doom includes a number of different options for music
|
||||
playback. See the README.Music file for more details.
|
||||
|
||||
* More information, including information about how to play various
|
||||
classic TCs, is available on the Chocolate Doom website:
|
||||
|
||||
https://www.chocolate-doom.org/
|
||||
|
||||
You are encouraged to sign up and contribute any useful information
|
||||
you may have regarding the port!
|
||||
|
||||
* Chocolate Doom is not perfect. Although it aims to accurately
|
||||
emulate and reproduce the DOS executables, some behavior can be very
|
||||
difficult to reproduce. Because of the nature of the project, you
|
||||
may also encounter Vanilla Doom bugs; these are intentionally
|
||||
present; see the NOT-BUGS file for more information.
|
||||
|
||||
New bug reports, feedback, questions or suggestions can be submitted
|
||||
to the issue tracker on Github:
|
||||
|
||||
https://github.com/chocolate-doom/chocolate-doom/issues
|
||||
|
||||
* Source code patches are welcome, but please follow the style
|
||||
guidelines - see the file named HACKING included with the source
|
||||
distribution.
|
||||
|
||||
* Chocolate Doom is distributed under the GNU GPL. See the COPYING
|
||||
file for more information.
|
||||
35
games/NXDoom/RELEASE_NOTES.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
## 3.1.1 (2025-08-14)
|
||||
|
||||
### General
|
||||
* Fix compilation on GCC 15 (thanks Fabian).
|
||||
* Hide public IP addresses for privacy.
|
||||
* Use native OpenGL texture format for better performance (thanks Fabian).
|
||||
* Improved directory handling on Windows (thank Roman Fomin):
|
||||
* Fixes problems with postfix "." for non-relative paths.
|
||||
* Support for long NTFS paths (up to 32768 characters).
|
||||
* Fixed metainfo files for latest AppStream spec compliance (thanks Fabian).
|
||||
* Add option to enable or disable smooth pixel scaling (thanks StevenSYS).
|
||||
* Allow spaces in GUS patch folder path (thanks Michael Day).
|
||||
* Add support for non-US backslash key (thanks Michael Day).
|
||||
* Never let SDL Mixer use native midi on Windows (thanks Michael Day).
|
||||
* Use $TMPDIR to find tempdir on Unix (thanks Mr. Myth).
|
||||
* Improve man page formatting (thanks g-branden-robinson).
|
||||
|
||||
### Build systems
|
||||
* Can now be built with Emscripten (thanks James Baicoianu).
|
||||
* Misc. improvements (thanks suve, Emmanuel Ferdman, Gabriele Simoni, et al.)
|
||||
|
||||
### Setup
|
||||
* Use correct EGA palette colors (thanks Henrique Jorge).
|
||||
|
||||
### Doom
|
||||
* Initial support for Doom version 1.5 (thanks Michael Francis).
|
||||
|
||||
### Heretic
|
||||
* Fix crash after loading too many saved games (thanks Noseey).
|
||||
|
||||
### Hexen
|
||||
* Fix crash with Heresiarch fireballs if player has never touched a wall (thank Noseey).
|
||||
|
||||
### Strife
|
||||
* Initialize floor->type and floor->crush fields in EV_BuildStairs() (thanks Fabian).
|
||||
36
games/NXDoom/TODO.md
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
This is Chocolate Doom’s “to do” list. Note that this is kind of an arbitrary
|
||||
and unstructured wish list of features and improvements. The bug tracker
|
||||
(http://chocolate-doom.org/bugs) has more feature requests.
|
||||
|
||||
* Multiplayer:
|
||||
- Use UPnP to automatically configure port forwarding for NATed
|
||||
networks.
|
||||
- Multiplayer options and configuration file (server name, etc)
|
||||
* Improve multiplayer startup:
|
||||
- Select an IWAD automatically from the server’s game type rather than
|
||||
all players having to specify -iwad.
|
||||
- Send list of WADs to load instead of all clients having to specify -file.
|
||||
- Same applies to dehacked patches and wad merging parameters.
|
||||
* Portability improvements:
|
||||
- Test on and fix for architectures where `((-2) >> 1) != -1`
|
||||
- Use size-specific types (eg. `int32_t` instead of int)
|
||||
- Don’t make structure packing assumptions when loading levels.
|
||||
- Port to every OS and architecture under the sun
|
||||
- Port to Emscripten and release a web-based version.
|
||||
* Video capture mode
|
||||
- Real-time recording of gameplay
|
||||
- Batch conversion of demos into videos
|
||||
* Heretic/Hexen/Strife:
|
||||
- Merge r_draw.c to common version and delete duplicates
|
||||
- Heretic v1.2 emulation (if possible)
|
||||
- Hexen v1.0 emulation (if possible/necessary)
|
||||
- Strife v1.1 emulation (for demo IWAD support)
|
||||
- Screensaver mode
|
||||
|
||||
Crazy pie in the sky ideas:
|
||||
|
||||
* Automatic WAD installer - download and run TCs from a list automatically
|
||||
(automating the current “instructions on wiki” system).
|
||||
* Textscreen interface to the Compet-N database: menu driven system to
|
||||
automatically download and play speedruns.
|
||||
* DWANGO-like interface for finding players and setting up games.
|
||||
4
games/NXDoom/autogen.sh
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
autoreconf -fi
|
||||
./configure "$@"
|
||||
6
games/NXDoom/check-extern.sh
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
EXTERN="$(grep -e 'extern[^A-Za-z0-9_]' $(find . -name *.c))"
|
||||
if [ -n "$EXTERN" ] ; then
|
||||
echo "extern found in .c files:\n${EXTERN}"
|
||||
exit 1
|
||||
fi
|
||||
106
games/NXDoom/cmake/FindFluidSynth.cmake
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# FindFluidSynth
|
||||
# ---------
|
||||
#
|
||||
# Try to find the FluidSynth library.
|
||||
#
|
||||
# This will define the following variables:
|
||||
#
|
||||
# ``FluidSynth_FOUND``
|
||||
# System has FluidSynth.
|
||||
#
|
||||
# ``FluidSynth_VERSION``
|
||||
# The version of FluidSynth.
|
||||
#
|
||||
# ``FluidSynth_INCLUDE_DIRS``
|
||||
# This should be passed to target_include_directories() if
|
||||
# the target is not used for linking.
|
||||
#
|
||||
# ``FluidSynth_LIBRARIES``
|
||||
# The FluidSynth library.
|
||||
# This can be passed to target_link_libraries() instead of
|
||||
# the ``FluidSynth::libfluidsynth`` target
|
||||
#
|
||||
# If ``FluidSynth_FOUND`` is TRUE, the following imported target
|
||||
# will be available:
|
||||
#
|
||||
# ``FluidSynth::libfluidsynth``
|
||||
# The FluidSynth library
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright 2018 Christophe Giboudeaux <christophe@krop.fr>
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#=============================================================================
|
||||
|
||||
# Cache variable that allows you to point CMake at a directory containing
|
||||
# an extracted development library.
|
||||
set(FluidSynth_DIR "${FluidSynth_DIR}"
|
||||
CACHE PATH "Location of FluidSynth library directory")
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_FluidSynth QUIET fluidsynth>=${FluidSynth_FIND_VERSION})
|
||||
|
||||
find_library(FluidSynth_LIBRARIES
|
||||
NAMES fluidsynth
|
||||
HINTS
|
||||
"${FluidSynth_DIR}/lib"
|
||||
${PC_FluidSynth_LIBDIR}
|
||||
)
|
||||
|
||||
find_path(FluidSynth_INCLUDE_DIRS
|
||||
NAMES fluidsynth.h
|
||||
HINTS
|
||||
"${FluidSynth_DIR}/include"
|
||||
${PC_FluidSynth_INCLUDEDIR}
|
||||
)
|
||||
|
||||
if(NOT FluidSynth_VERSION)
|
||||
if(EXISTS "${FluidSynth_INCLUDE_DIRS}/fluidsynth/version.h")
|
||||
file(STRINGS "${FluidSynth_INCLUDE_DIRS}/fluidsynth/version.h" _FLUIDSYNTH_VERSION_H
|
||||
REGEX "^#define[ ]+FLUIDSYNTH_VERSION[ ]+\"[0-9].[0-9].[0-9]\"")
|
||||
string(REGEX REPLACE "^#define[ ]+FLUIDSYNTH_VERSION[ ]+\"([0-9].[0-9].[0-9])\".*" "\\1" FluidSynth_VERSION "${_FLUIDSYNTH_VERSION_H}")
|
||||
unset(_FLUIDSYNTH_VERSION_H)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FluidSynth
|
||||
FOUND_VAR FluidSynth_FOUND
|
||||
REQUIRED_VARS FluidSynth_LIBRARIES FluidSynth_INCLUDE_DIRS
|
||||
VERSION_VAR FluidSynth_VERSION
|
||||
)
|
||||
|
||||
if(FluidSynth_FOUND AND NOT TARGET FluidSynth::libfluidsynth)
|
||||
add_library(FluidSynth::libfluidsynth UNKNOWN IMPORTED)
|
||||
set_target_properties(FluidSynth::libfluidsynth PROPERTIES
|
||||
IMPORTED_LOCATION "${FluidSynth_LIBRARIES}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${FluidSynth_INCLUDE_DIRS}"
|
||||
)
|
||||
if(WIN32 AND FluidSynth_DIR)
|
||||
# On Windows, we need to figure out the location of our library files
|
||||
# so we can copy and package them.
|
||||
set(FluidSynth_DLL_DIR "${FluidSynth_DIR}/bin" CACHE INTERNAL "")
|
||||
endif()
|
||||
endif()
|
||||
114
games/NXDoom/cmake/FindSDL2.cmake
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# FindSDL2.cmake
|
||||
#
|
||||
# Copyright (c) 2018, Alex Mayfield <alexmax2742@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Currently works with the following generators:
|
||||
# - Unix Makefiles (Linux, MSYS2)
|
||||
# - Ninja (Linux, MSYS2)
|
||||
# - Visual Studio
|
||||
|
||||
# Cache variable that allows you to point CMake at a directory containing
|
||||
# an extracted development library.
|
||||
set(SDL2_DIR "${SDL2_DIR}" CACHE PATH "Location of SDL2 library directory")
|
||||
|
||||
# Use pkg-config to find library locations in *NIX environments.
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PC_SDL2 QUIET sdl2)
|
||||
endif()
|
||||
|
||||
# Find the include directory.
|
||||
find_path(SDL2_INCLUDE_DIR "SDL_version.h"
|
||||
HINTS "${SDL2_DIR}/include" ${PC_SDL2_INCLUDE_DIRS})
|
||||
|
||||
# Find the version. Taken and modified from CMake's FindSDL.cmake.
|
||||
if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL_version.h")
|
||||
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}")
|
||||
set(SDL2_VERSION "${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH}")
|
||||
unset(SDL2_VERSION_MAJOR_LINE)
|
||||
unset(SDL2_VERSION_MINOR_LINE)
|
||||
unset(SDL2_VERSION_PATCH_LINE)
|
||||
unset(SDL2_VERSION_MAJOR)
|
||||
unset(SDL2_VERSION_MINOR)
|
||||
unset(SDL2_VERSION_PATCH)
|
||||
endif()
|
||||
|
||||
# Find the SDL2 and SDL2main libraries
|
||||
if(CMAKE_SIZEOF_VOID_P STREQUAL 8)
|
||||
find_library(SDL2_LIBRARY "SDL2"
|
||||
HINTS "${SDL2_DIR}/lib/x64" ${PC_SDL2_LIBRARY_DIRS})
|
||||
find_library(SDL2_MAIN_LIBRARY "SDL2main"
|
||||
HINTS "${SDL2_DIR}/lib/x64" ${PC_SDL2_LIBRARY_DIRS})
|
||||
else()
|
||||
find_library(SDL2_LIBRARY "SDL2"
|
||||
HINTS "${SDL2_DIR}/lib/x86" ${PC_SDL2_LIBRARY_DIRS})
|
||||
find_library(SDL2_MAIN_LIBRARY "SDL2main"
|
||||
HINTS "${SDL2_DIR}/lib/x86" ${PC_SDL2_LIBRARY_DIRS})
|
||||
endif()
|
||||
set(SDL2_LIBRARIES "${SDL2_MAIN_LIBRARY}" "${SDL2_LIBRARY}")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SDL2
|
||||
FOUND_VAR SDL2_FOUND
|
||||
REQUIRED_VARS SDL2_INCLUDE_DIR SDL2_LIBRARIES
|
||||
VERSION_VAR SDL2_VERSION
|
||||
)
|
||||
|
||||
if(SDL2_FOUND)
|
||||
# SDL2 imported target.
|
||||
add_library(SDL2::SDL2 UNKNOWN IMPORTED)
|
||||
set_target_properties(SDL2::SDL2 PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_SDL2_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIR}"
|
||||
IMPORTED_LOCATION "${SDL2_LIBRARY}")
|
||||
|
||||
# SDL2main imported target.
|
||||
if(MINGW)
|
||||
# Gross hack to get mingw32 first in the linker order.
|
||||
add_library(SDL2::_SDL2main_detail UNKNOWN IMPORTED)
|
||||
set_target_properties(SDL2::_SDL2main_detail PROPERTIES
|
||||
IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}")
|
||||
|
||||
# Ensure that SDL2main comes before SDL2 in the linker order. CMake
|
||||
# isn't smart enough to keep proper ordering for indirect dependencies
|
||||
# so we have to spell it out here.
|
||||
target_link_libraries(SDL2::_SDL2main_detail INTERFACE SDL2::SDL2)
|
||||
|
||||
add_library(SDL2::SDL2main INTERFACE IMPORTED)
|
||||
set_target_properties(SDL2::SDL2main PROPERTIES
|
||||
IMPORTED_LIBNAME mingw32)
|
||||
target_link_libraries(SDL2::SDL2main INTERFACE SDL2::_SDL2main_detail)
|
||||
else()
|
||||
add_library(SDL2::SDL2main UNKNOWN IMPORTED)
|
||||
set_target_properties(SDL2::SDL2main PROPERTIES
|
||||
IMPORTED_LOCATION "${SDL2_MAIN_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
88
games/NXDoom/cmake/FindSDL2_mixer.cmake
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# FindSDL2_mixer.cmake
|
||||
#
|
||||
# Copyright (c) 2018, Alex Mayfield <alexmax2742@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Currently works with the following generators:
|
||||
# - Unix Makefiles (Linux, MSYS2)
|
||||
# - Ninja (Linux, MSYS2)
|
||||
# - Visual Studio
|
||||
|
||||
# Cache variable that allows you to point CMake at a directory containing
|
||||
# an extracted development library.
|
||||
set(SDL2_MIXER_DIR "${SDL2_MIXER_DIR}" CACHE PATH "Location of SDL2_mixer library directory")
|
||||
|
||||
# Use pkg-config to find library locations in *NIX environments.
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PC_SDL2_MIXER QUIET SDL2_mixer)
|
||||
endif()
|
||||
|
||||
# Find the include directory.
|
||||
find_path(SDL2_MIXER_INCLUDE_DIR "SDL_mixer.h"
|
||||
HINTS "${SDL2_MIXER_DIR}/include" ${PC_SDL2_MIXER_INCLUDE_DIRS})
|
||||
|
||||
# Find the version. Taken and modified from CMake's FindSDL.cmake.
|
||||
if(SDL2_MIXER_INCLUDE_DIR AND EXISTS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h")
|
||||
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_MIXER_INCLUDE_DIR}/SDL_mixer.h" SDL2_MIXER_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+[0-9]+$")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MAJOR "${SDL2_MIXER_VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_MINOR "${SDL2_MIXER_VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_MIXER_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_MIXER_VERSION_PATCH "${SDL2_MIXER_VERSION_PATCH_LINE}")
|
||||
set(SDL2_MIXER_VERSION "${SDL2_MIXER_VERSION_MAJOR}.${SDL2_MIXER_VERSION_MINOR}.${SDL2_MIXER_VERSION_PATCH}")
|
||||
unset(SDL2_MIXER_VERSION_MAJOR_LINE)
|
||||
unset(SDL2_MIXER_VERSION_MINOR_LINE)
|
||||
unset(SDL2_MIXER_VERSION_PATCH_LINE)
|
||||
unset(SDL2_MIXER_VERSION_MAJOR)
|
||||
unset(SDL2_MIXER_VERSION_MINOR)
|
||||
unset(SDL2_MIXER_VERSION_PATCH)
|
||||
endif()
|
||||
|
||||
# Find the library.
|
||||
if(CMAKE_SIZEOF_VOID_P STREQUAL 8)
|
||||
find_library(SDL2_MIXER_LIBRARY "SDL2_mixer"
|
||||
HINTS "${SDL2_MIXER_DIR}/lib/x64" ${PC_SDL2_MIXER_LIBRARY_DIRS})
|
||||
else()
|
||||
find_library(SDL2_MIXER_LIBRARY "SDL2_mixer"
|
||||
HINTS "${SDL2_MIXER_DIR}/lib/x86" ${PC_SDL2_MIXER_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SDL2_mixer
|
||||
FOUND_VAR SDL2_MIXER_FOUND
|
||||
REQUIRED_VARS SDL2_MIXER_INCLUDE_DIR SDL2_MIXER_LIBRARY
|
||||
VERSION_VAR SDL2_MIXER_VERSION
|
||||
)
|
||||
|
||||
if(SDL2_MIXER_FOUND)
|
||||
# Imported target.
|
||||
add_library(SDL2_mixer::SDL2_mixer UNKNOWN IMPORTED)
|
||||
set_target_properties(SDL2_mixer::SDL2_mixer PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_SDL2_MIXER_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_MIXER_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES SDL2::SDL2
|
||||
IMPORTED_LOCATION "${SDL2_MIXER_LIBRARY}")
|
||||
endif()
|
||||
88
games/NXDoom/cmake/FindSDL2_net.cmake
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# FindSDL2_net.cmake
|
||||
#
|
||||
# Copyright (c) 2018, Alex Mayfield <alexmax2742@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Currently works with the following generators:
|
||||
# - Unix Makefiles (Linux, MSYS2)
|
||||
# - Ninja (Linux, MSYS2)
|
||||
# - Visual Studio
|
||||
|
||||
# Cache variable that allows you to point CMake at a directory containing
|
||||
# an extracted development library.
|
||||
set(SDL2_NET_DIR "${SDL2_NET_DIR}" CACHE PATH "Location of SDL2_net library directory")
|
||||
|
||||
# Use pkg-config to find library locations in *NIX environments.
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PC_SDL2_NET QUIET SDL2_net)
|
||||
endif()
|
||||
|
||||
# Find the include directory.
|
||||
find_path(SDL2_NET_INCLUDE_DIR "SDL_net.h"
|
||||
HINTS "${SDL2_NET_DIR}/include" ${PC_SDL2_NET_INCLUDE_DIRS})
|
||||
|
||||
# Find the version. Taken and modified from CMake's FindSDL.cmake.
|
||||
if(SDL2_NET_INCLUDE_DIR AND EXISTS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h")
|
||||
file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+[0-9]+$")
|
||||
file(STRINGS "${SDL2_NET_INCLUDE_DIR}/SDL_net.h" SDL2_NET_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+[0-9]+$")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_NET_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MAJOR "${SDL2_NET_VERSION_MAJOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_NET_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_MINOR "${SDL2_NET_VERSION_MINOR_LINE}")
|
||||
string(REGEX REPLACE "^#define[ \t]+SDL_NET_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_NET_VERSION_PATCH "${SDL2_NET_VERSION_PATCH_LINE}")
|
||||
set(SDL2_NET_VERSION "${SDL2_NET_VERSION_MAJOR}.${SDL2_NET_VERSION_MINOR}.${SDL2_NET_VERSION_PATCH}")
|
||||
unset(SDL2_NET_VERSION_MAJOR_LINE)
|
||||
unset(SDL2_NET_VERSION_MINOR_LINE)
|
||||
unset(SDL2_NET_VERSION_PATCH_LINE)
|
||||
unset(SDL2_NET_VERSION_MAJOR)
|
||||
unset(SDL2_NET_VERSION_MINOR)
|
||||
unset(SDL2_NET_VERSION_PATCH)
|
||||
endif()
|
||||
|
||||
# Find the library.
|
||||
if(CMAKE_SIZEOF_VOID_P STREQUAL 8)
|
||||
find_library(SDL2_NET_LIBRARY "SDL2_net"
|
||||
HINTS "${SDL2_NET_DIR}/lib/x64" ${PC_SDL2_NET_LIBRARY_DIRS})
|
||||
else()
|
||||
find_library(SDL2_NET_LIBRARY "SDL2_net"
|
||||
HINTS "${SDL2_NET_DIR}/lib/x86" ${PC_SDL2_NET_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SDL2_net
|
||||
FOUND_VAR SDL2_NET_FOUND
|
||||
REQUIRED_VARS SDL2_NET_INCLUDE_DIR SDL2_NET_LIBRARY
|
||||
VERSION_VAR SDL2_NET_VERSION
|
||||
)
|
||||
|
||||
if(SDL2_NET_FOUND)
|
||||
# Imported target.
|
||||
add_library(SDL2_net::SDL2_net UNKNOWN IMPORTED)
|
||||
set_target_properties(SDL2_net::SDL2_net PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_SDL2_NET_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SDL2_NET_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES SDL2::SDL2
|
||||
IMPORTED_LOCATION "${SDL2_NET_LIBRARY}")
|
||||
endif()
|
||||
67
games/NXDoom/cmake/FindSampleRate.cmake
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Findsamplerate.cmake
|
||||
#
|
||||
# Copyright (c) 2018, Alex Mayfield <alexmax2742@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Currently works with the following generators:
|
||||
# - Unix Makefiles (Linux, MSYS2)
|
||||
# - Ninja (Linux, MSYS2)
|
||||
# - Visual Studio
|
||||
|
||||
# Use pkg-config to find library locations in *NIX environments.
|
||||
find_package(PkgConfig QUIET)
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_search_module(PC_SAMPLERATE QUIET samplerate)
|
||||
endif()
|
||||
|
||||
# Find the include directory.
|
||||
find_path(SAMPLERATE_INCLUDE_DIR "samplerate.h"
|
||||
HINTS ${PC_SAMPLERATE_INCLUDE_DIRS})
|
||||
|
||||
# Find the version. I don't know if there is a correct way to find this on
|
||||
# Windows - the config.h in the tarball is wrong for 0.1.19.
|
||||
if(PC_SAMPLERATE_VERSION)
|
||||
set(SAMPLERATE_VERSION "${PC_SAMPLERATE_VERSION}")
|
||||
endif()
|
||||
|
||||
# Find the library.
|
||||
find_library(SAMPLERATE_LIBRARY "samplerate"
|
||||
HINTS ${PC_SAMPLERATE_LIBRARY_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SampleRate
|
||||
FOUND_VAR SampleRate_FOUND
|
||||
REQUIRED_VARS SAMPLERATE_INCLUDE_DIR SAMPLERATE_LIBRARY
|
||||
VERSION_VAR SAMPLERATE_VERSION
|
||||
)
|
||||
|
||||
if(SampleRate_FOUND)
|
||||
# Imported target.
|
||||
add_library(SampleRate::samplerate UNKNOWN IMPORTED)
|
||||
set_target_properties(SampleRate::samplerate PROPERTIES
|
||||
INTERFACE_COMPILE_OPTIONS "${PC_SAMPLERATE_CFLAGS_OTHER}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${SAMPLERATE_INCLUDE_DIR}"
|
||||
IMPORTED_LOCATION "${SAMPLERATE_LIBRARY}")
|
||||
endif()
|
||||
36
games/NXDoom/cmake/Findm.cmake
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Findm.cmake
|
||||
#
|
||||
# Copyright (c) 2018, Alex Mayfield <alexmax2742@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the <organization> nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Finds libm, so we can link against it for math functions. If libm doesn't
|
||||
# exist, linking against the m target will have no effect.
|
||||
|
||||
find_library(M_LIBRARY m)
|
||||
|
||||
add_library(m INTERFACE)
|
||||
if(M_LIBRARY)
|
||||
target_link_libraries(m INTERFACE "${M_LIBRARY}")
|
||||
endif()
|
||||
12
games/NXDoom/cmake/config.h.cin
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
|
||||
#cmakedefine PACKAGE_TARNAME "@PACKAGE_TARNAME@"
|
||||
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
|
||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||
#cmakedefine PROGRAM_PREFIX "@PROGRAM_PREFIX@"
|
||||
|
||||
#cmakedefine HAVE_FLUIDSYNTH
|
||||
#cmakedefine HAVE_LIBSAMPLERATE
|
||||
#cmakedefine HAVE_LIBPNG
|
||||
#cmakedefine HAVE_DIRENT_H
|
||||
#cmakedefine01 HAVE_DECL_STRCASECMP
|
||||
#cmakedefine01 HAVE_DECL_STRNCASECMP
|
||||
335
games/NXDoom/configure.ac
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
AC_INIT(Chocolate Doom, 3.1.1,
|
||||
chocolate-doom-dev-list@chocolate-doom.org, chocolate-doom)
|
||||
|
||||
PACKAGE_SHORTNAME=${PACKAGE_NAME% Doom}
|
||||
PACKAGE_SHORTDESC="Conservative source port"
|
||||
PACKAGE_COPYRIGHT="Copyright (C) 1993-2025"
|
||||
PACKAGE_LICENSE="GNU General Public License, version 2"
|
||||
PACKAGE_MAINTAINER="Simon Howard"
|
||||
PACKAGE_URL="https://www.chocolate-doom.org/"
|
||||
PACKAGE_RDNS="org.chocolate_doom"
|
||||
PACKAGE_BUGREPORT="https://github.com/chocolate-doom/chocolate-doom/issues"
|
||||
|
||||
dnl Check for Emscripten environment so we can set necessary environment variables
|
||||
AC_ARG_ENABLE(
|
||||
[emscripten],
|
||||
[AS_HELP_STRING([--enable-emscripten=@<:@no/yes@:>@],[compile to JavaScript using Emscripten])],,
|
||||
[AS_CASE([$CC],
|
||||
[*emcc.py], [enable_emscripten="yes"],
|
||||
[*emcc], [enable_emscripten="yes"],
|
||||
[enable_emscripten="no"]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
AS_IF([test "x$enable_emscripten" = "xyes"],
|
||||
AC_MSG_NOTICE([auto-detected use of Emscripten])
|
||||
SDL_CFLAGS="-s USE_SDL=2"
|
||||
SDL_LIBS="-s USE_SDL=2"
|
||||
SDLMIXER_CFLAGS="-s USE_SDL=2 -s USE_SDL_MIXER=2"
|
||||
SDLMIXER_LIBS="-s USE_SDL=2 -s USE_SDL_MIXER=2"
|
||||
SDLNET_CFLAGS="-s USE_SDL=2 -s USE_SDL_NET=2"
|
||||
SDLNET_LIBS="-s USE_SDL=2 -s USE_SDL_NET=2"
|
||||
EM_LDFLAGS="-s ALLOW_MEMORY_GROWTH=1 -s ASYNCIFY=1 -s EXPORTED_RUNTIME_METHODS=[ccall,cwrap,FS,ENV,PATH,ERRNO_CODES] -s FORCE_FILESYSTEM"
|
||||
)
|
||||
|
||||
AC_CONFIG_AUX_DIR(autotools)
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
orig_CFLAGS="$CFLAGS"
|
||||
|
||||
AM_PROG_AR
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_RANLIB
|
||||
AC_CHECK_PROG(HAVE_PYTHON, python3, true, false)
|
||||
|
||||
OPT_LEVEL=2
|
||||
|
||||
# If this is gcc, we have some options we'd like to turn on. Turn on
|
||||
# optimisation and debugging symbols.
|
||||
|
||||
if test "$GCC" = "yes"
|
||||
then
|
||||
WARNINGS="-Wall -Wdeclaration-after-statement -Wredundant-decls"
|
||||
CFLAGS="-O$OPT_LEVEL -g $WARNINGS $orig_CFLAGS"
|
||||
fi
|
||||
|
||||
AC_CANONICAL_TARGET
|
||||
TARGET_OS=""
|
||||
AS_CASE([$target_cpu],
|
||||
[x86_64],
|
||||
[
|
||||
TARGET_OS="x64"
|
||||
],
|
||||
[aarch64*|arm*],
|
||||
[
|
||||
TARGET_OS="arm"
|
||||
],
|
||||
[i?86|arm*],
|
||||
[
|
||||
TARGET_OS="32"
|
||||
])
|
||||
AC_SUBST([TARGET_OS])
|
||||
|
||||
PKG_CHECK_MODULES(SDL, [sdl2 >= 2.0.14])
|
||||
# Check for SDL2_mixer
|
||||
AC_ARG_ENABLE([sdl2mixer],
|
||||
AS_HELP_STRING([--disable-sdl2mixer], [Disable SDL2_mixer support])
|
||||
)
|
||||
AS_IF([test "x$enable_sdl2mixer" != xno], [
|
||||
PKG_CHECK_MODULES(SDLMIXER, [SDL2_mixer >= 2.0.2])], [
|
||||
AC_DEFINE([DISABLE_SDL2MIXER], [1], [SDL2_mixer disabled])
|
||||
])
|
||||
|
||||
# Check for networking
|
||||
AC_ARG_ENABLE([sdl2net],
|
||||
AS_HELP_STRING([--disable-sdl2net], [Disable SDL2_net support])
|
||||
)
|
||||
AS_IF([test "x$enable_sdl2net" != xno], [
|
||||
PKG_CHECK_MODULES(SDLNET, [SDL2_net >= 2.0.0])], [
|
||||
AC_DEFINE([DISABLE_SDL2NET], [1], [SDL2_net disabled])
|
||||
])
|
||||
|
||||
# Check for bash-completion.
|
||||
AC_ARG_ENABLE([bash-completion],
|
||||
AS_HELP_STRING([--disable-bash-completion], [Disable bash-completion])
|
||||
)
|
||||
AS_IF([test "x$enable_bash_completion" != xno], [
|
||||
AS_IF([test "x$HAVE_PYTHON" = xfalse], [
|
||||
AC_MSG_WARN([Building bash-completion requires Python, but Python not found])
|
||||
enable_bash_completion=no
|
||||
])
|
||||
])
|
||||
|
||||
# Check for doc.
|
||||
AC_ARG_ENABLE([doc],
|
||||
AS_HELP_STRING([--disable-doc], [Disable documentation])
|
||||
)
|
||||
AS_IF([test "x$enable_doc" != xno], [
|
||||
AS_IF([test "x$HAVE_PYTHON" = xfalse], [
|
||||
AC_MSG_WARN([Building documentation requires Python, but Python not found])
|
||||
enable_doc=no
|
||||
])
|
||||
])
|
||||
|
||||
# Check for fonts.
|
||||
AC_ARG_ENABLE([fonts],
|
||||
AS_HELP_STRING([--disable-fonts], [Disable fonts])
|
||||
)
|
||||
AS_IF([test "x$enable_fonts" != xno], [
|
||||
AS_IF([test "x$HAVE_PYTHON" = xfalse], [
|
||||
AC_MSG_WARN([Building fonts require Python, but Python not found])
|
||||
enable_fonts=no
|
||||
])
|
||||
])
|
||||
|
||||
# Check for icons.
|
||||
AC_ARG_ENABLE([icons],
|
||||
AS_HELP_STRING([--disable-icons], [Disable icons])
|
||||
)
|
||||
AS_IF([test "x$enable_icons" != xno], [
|
||||
AS_IF([test "x$HAVE_PYTHON" = xfalse], [
|
||||
AC_MSG_WARN([Building icons require Python, but Python not found])
|
||||
enable_icons=no
|
||||
])
|
||||
])
|
||||
|
||||
# Check for memory pool debugging.
|
||||
AC_ARG_ENABLE([zpool],
|
||||
AS_HELP_STRING([--disable-zpool], [Disable memory pools for debugging])
|
||||
)
|
||||
AS_IF([test "x$enable_zpool" != xno], [], [
|
||||
AC_DEFINE([DISABLE_ZPOOL], [1], [Memory pooling disabled])
|
||||
])
|
||||
|
||||
# Check for libsamplerate.
|
||||
AC_ARG_WITH([libsamplerate],
|
||||
AS_HELP_STRING([--without-libsamplerate],
|
||||
[Build without libsamplerate @<:@default=check@:>@]),
|
||||
[],
|
||||
[
|
||||
[with_libsamplerate=check]
|
||||
])
|
||||
AS_IF([test "x$with_libsamplerate" != xno], [
|
||||
PKG_CHECK_MODULES(SAMPLERATE, samplerate >= 0.1.8, [
|
||||
AC_DEFINE([HAVE_LIBSAMPLERATE], [1], [libsamplerate installed])
|
||||
], [
|
||||
AS_IF([test "x$with_libsamplerate" != xcheck], [AC_MSG_FAILURE(
|
||||
[--with-libsamplerate was given, but test for libsamplerate failed])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
# Check for libpng.
|
||||
AC_ARG_WITH([libpng],
|
||||
AS_HELP_STRING([--without-libpng],
|
||||
[Build without libpng @<:@default=check@:>@]),
|
||||
[],
|
||||
[
|
||||
[with_libpng=check]
|
||||
])
|
||||
AS_IF([test "x$with_libpng" != xno], [
|
||||
PKG_CHECK_MODULES(PNG, libpng >= 1.2.50, [
|
||||
AC_DEFINE([HAVE_LIBPNG], [1], [libpng installed])
|
||||
], [
|
||||
AS_IF([test "x$with_libpng" != xcheck], [AC_MSG_FAILURE(
|
||||
[--with-libpng was given, but test for libpng failed])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
# Check for fluidsynth.
|
||||
AC_ARG_WITH([fluidsynth],
|
||||
AS_HELP_STRING([--without-fluidsynth],
|
||||
[Build without fluidsynth @<:@default=check@:>@]),
|
||||
[],
|
||||
[
|
||||
[with_fluidsynth=check]
|
||||
])
|
||||
AS_IF([test "x$with_fluidsynth" != xno] && [test "x$enable_sdl2mixer" != xno], [
|
||||
PKG_CHECK_MODULES(FLUIDSYNTH, fluidsynth >= 2.2.0, [
|
||||
AC_DEFINE([HAVE_FLUIDSYNTH], [1], [fluidsynth installed])
|
||||
], [
|
||||
AS_IF([test "x$with_fluidsynth" != xcheck], [AC_MSG_FAILURE(
|
||||
[--with-fluidsynth was given, but test for fluidsynth failed])
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
# TODO: We currently link everything against libraries that don't need it.
|
||||
# Use the specific library CFLAGS/LIBS variables instead of setting them here.
|
||||
CFLAGS="$CFLAGS $SDL_CFLAGS ${SAMPLERATE_CFLAGS:-} ${PNG_CFLAGS:-} ${FLUIDSYNTH_CFLAGS:-}"
|
||||
LDFLAGS="$LDFLAGS $SDL_LIBS ${SAMPLERATE_LIBS:-} ${PNG_LIBS:-} ${FLUIDSYNTH_LIBS:-}"
|
||||
case "$host" in
|
||||
*-*-mingw* | *-*-cygwin* | *-*-msvc* )
|
||||
LDFLAGS="$LDFLAGS -lwinmm -lshlwapi"
|
||||
;;
|
||||
*)
|
||||
esac
|
||||
|
||||
AC_CHECK_LIB(m, log)
|
||||
|
||||
AC_CHECK_HEADERS([dirent.h linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
|
||||
AC_CHECK_FUNCS(mmap ioperm)
|
||||
AC_CHECK_DECLS([strcasecmp, strncasecmp], [], [], [[#include <strings.h>]])
|
||||
|
||||
# OpenBSD I/O i386 library for I/O port access.
|
||||
# (64 bit has the same thing with a different name!)
|
||||
|
||||
AC_CHECK_LIB(i386, i386_iopl)
|
||||
AC_CHECK_LIB(amd64, amd64_iopl)
|
||||
|
||||
case "$host" in
|
||||
*-*-mingw* | *-*-cygwin* | *-*-msvc* )
|
||||
AC_CHECK_TOOL(WINDRES, windres, )
|
||||
;;
|
||||
*)
|
||||
WINDRES=
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CHECK_TOOL(OBJDUMP, objdump, )
|
||||
AC_CHECK_TOOL(STRIP, strip, )
|
||||
|
||||
AC_ARG_ENABLE([werror], AS_HELP_STRING([--enable-werror], [Treat warnings as errors]))
|
||||
|
||||
AS_IF([test "x$enable_werror" = "xyes"], [
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
])
|
||||
|
||||
AM_CONDITIONAL(HAVE_WINDRES, test "$WINDRES" != "")
|
||||
AM_CONDITIONAL(HAVE_BASH_COMPLETION, [test "x$enable_bash_completion" != xno])
|
||||
AM_CONDITIONAL(HAVE_DOC, [test "x$enable_doc" != xno])
|
||||
AM_CONDITIONAL(HAVE_FONTS, [test "x$enable_fonts" != xno])
|
||||
AM_CONDITIONAL(HAVE_ICONS, [test "x$enable_icons" != xno])
|
||||
AM_CONDITIONAL(HAVE_ZPOOL, [test "x$enable_zpool" != xno])
|
||||
|
||||
dnl Automake v1.8.0 is required, please upgrade!
|
||||
|
||||
AM_INIT_AUTOMAKE([1.8.0 foreign])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
WINDOWS_RC_VERSION=`echo $PACKAGE_VERSION | sed 's/-.*//; s/\./, /g; s/$/, 0/'`
|
||||
|
||||
dnl Without a hyphen. This is used for the bash-completion scripts.
|
||||
PROGRAM_SPREFIX=$(echo $PACKAGE_SHORTNAME | tr A-Z a-z)
|
||||
|
||||
dnl With a hyphen, used almost everywhere else.
|
||||
PROGRAM_PREFIX=${PROGRAM_SPREFIX}-
|
||||
|
||||
AC_SUBST(PROGRAM_PREFIX)
|
||||
AC_DEFINE_UNQUOTED(PROGRAM_PREFIX, "$PROGRAM_PREFIX",
|
||||
Change this when you create your awesome forked version)
|
||||
AC_SUBST(PROGRAM_SPREFIX)
|
||||
|
||||
AC_CONFIG_HEADERS(config.h:config.hin)
|
||||
|
||||
AC_SUBST(WINDOWS_RC_VERSION)
|
||||
AC_SUBST(SDLMIXER_CFLAGS)
|
||||
AC_SUBST(SDLMIXER_LIBS)
|
||||
AC_SUBST(EM_LDFLAGS)
|
||||
|
||||
AC_SUBST(SDLNET_CFLAGS)
|
||||
AC_SUBST(SDLNET_LIBS)
|
||||
|
||||
AC_SUBST(ac_aux_dir)
|
||||
|
||||
AC_SUBST(PACKAGE_SHORTNAME)
|
||||
AC_SUBST(PACKAGE_SHORTDESC)
|
||||
AC_SUBST(PACKAGE_COPYRIGHT)
|
||||
AC_SUBST(PACKAGE_LICENSE)
|
||||
AC_SUBST(PACKAGE_MAINTAINER)
|
||||
AC_SUBST(PACKAGE_URL)
|
||||
AC_SUBST(PACKAGE_RDNS)
|
||||
AC_SUBST(PACKAGE_BUGREPORT)
|
||||
|
||||
dnl Shut up the datarootdir warnings.
|
||||
AC_DEFUN([AC_DATAROOTDIR_CHECKED])
|
||||
|
||||
AS_IF([test "x$enable_emscripten" = "xyes"],
|
||||
EXEEXT=".html"
|
||||
)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
man/Makefile
|
||||
man/bash-completion/Makefile
|
||||
man/bash-completion/doom.template
|
||||
man/bash-completion/heretic.template
|
||||
man/bash-completion/hexen.template
|
||||
man/bash-completion/strife.template
|
||||
opl/Makefile
|
||||
opl/examples/Makefile
|
||||
pcsound/Makefile
|
||||
pkg/Makefile
|
||||
pkg/config.make
|
||||
pkg/osx/Info.plist
|
||||
rpm.spec
|
||||
data/Makefile
|
||||
src/Makefile
|
||||
src/doom-res.rc
|
||||
src/Doom.metainfo.xml
|
||||
src/Doom.desktop
|
||||
src/Doom_Screensaver.desktop
|
||||
src/doom/Makefile
|
||||
src/heretic-res.rc
|
||||
src/Heretic.metainfo.xml
|
||||
src/Heretic.desktop
|
||||
src/heretic/Makefile
|
||||
src/hexen-res.rc
|
||||
src/Hexen.metainfo.xml
|
||||
src/Hexen.desktop
|
||||
src/hexen/Makefile
|
||||
src/setup-res.rc
|
||||
src/setup/Makefile
|
||||
src/setup/Setup.desktop
|
||||
src/setup/setup-manifest.xml
|
||||
src/strife-res.rc
|
||||
src/Strife.metainfo.xml
|
||||
src/Strife.desktop
|
||||
src/strife/Makefile
|
||||
textscreen/Makefile
|
||||
textscreen/examples/Makefile
|
||||
textscreen/fonts/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
7
games/NXDoom/data/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
*-doom.png
|
||||
*-heretic.png
|
||||
*-hexen.png
|
||||
*-setup.png
|
||||
*-strife.png
|
||||
39
games/NXDoom/data/Makefile.am
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
EXTRA_DIST= \
|
||||
README \
|
||||
doom.ico \
|
||||
doom.png \
|
||||
heretic.ico \
|
||||
heretic.png \
|
||||
hexen.ico \
|
||||
hexen.png \
|
||||
setup.ico \
|
||||
setup.png \
|
||||
strife.ico \
|
||||
strife.png \
|
||||
wadfile.png \
|
||||
convert-icon
|
||||
|
||||
iconsdir = $(prefix)/share/icons/hicolor/128x128/apps
|
||||
icons_DATA = @PROGRAM_PREFIX@doom.png \
|
||||
@PROGRAM_PREFIX@heretic.png \
|
||||
@PROGRAM_PREFIX@hexen.png \
|
||||
@PROGRAM_PREFIX@setup.png \
|
||||
@PROGRAM_PREFIX@strife.png
|
||||
|
||||
@PROGRAM_PREFIX@doom.png : doom.png
|
||||
cp $(top_srcdir)/data/doom.png $@
|
||||
|
||||
@PROGRAM_PREFIX@heretic.png : heretic.png
|
||||
cp $(top_srcdir)/data/heretic.png $@
|
||||
|
||||
@PROGRAM_PREFIX@hexen.png : hexen.png
|
||||
cp $(top_srcdir)/data/hexen.png $@
|
||||
|
||||
@PROGRAM_PREFIX@setup.png : setup.png
|
||||
cp $(top_srcdir)/data/setup.png $@
|
||||
|
||||
@PROGRAM_PREFIX@strife.png : strife.png
|
||||
cp $(top_srcdir)/data/strife.png $@
|
||||
|
||||
CLEANFILES = $(icons_DATA)
|
||||
16
games/NXDoom/data/README
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
The Chocolate Doom icon is based on an image by Chris Metcalf
|
||||
(http://www.chrismetcalf.org/) which is copyrighted to him:
|
||||
|
||||
http://www.flickr.com/photos/laffy4k/448920776/
|
||||
|
||||
Chris has kindly agreed that the Chocolate Doom icon may be used under
|
||||
the GNU GPL, so the copyright status of the icon is the same as that of
|
||||
the rest of the project.
|
||||
|
||||
The "foo8.ico" files are 8-bit depth only, while the "foo.ico" files
|
||||
contain full 32-bit versions, scaled to different sizes and with proper
|
||||
alpha masks (as well as the 8-bit versions). The 8-bit versions are
|
||||
used when setting the icon within SDL, as SDL under Windows displays
|
||||
full color icons in a very poor quality. The full-color versions are
|
||||
used in the resource files.
|
||||
|
||||
72
games/NXDoom/data/convert-icon
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
# Converts images into C structures to be inserted in programs
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
try:
|
||||
import Image
|
||||
except ImportError:
|
||||
try:
|
||||
from PIL import Image
|
||||
except ImportError:
|
||||
print("WARNING: Could not update %s. "
|
||||
"Please install the Python Imaging library or Pillow."
|
||||
% sys.argv[2])
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def convert_image(filename, output_filename):
|
||||
|
||||
im = Image.open(filename)
|
||||
|
||||
outfile = open(output_filename, "w")
|
||||
|
||||
size = im.size
|
||||
|
||||
struct_name = os.path.basename(output_filename)
|
||||
struct_name = re.sub(re.compile("\\..*$"), "", struct_name)
|
||||
struct_name = re.sub(re.compile("\W"), "_", struct_name)
|
||||
|
||||
outfile.write("static int %s_w = %i;\n" % (struct_name, size[0]))
|
||||
outfile.write("static int %s_h = %i;\n" % (struct_name, size[1]))
|
||||
|
||||
outfile.write("\n")
|
||||
outfile.write("static const unsigned int %s_data[] = {\n" % (struct_name))
|
||||
|
||||
elements_on_line = 0
|
||||
|
||||
outfile.write(" ")
|
||||
|
||||
for y in range(size[1]):
|
||||
for x in range(size[0]):
|
||||
val = im.getpixel((x, y))
|
||||
outfile.write("0x%02x%02x%02x%02x, " % val)
|
||||
elements_on_line += 1
|
||||
|
||||
if elements_on_line >= 6:
|
||||
elements_on_line = 0
|
||||
outfile.write("\n")
|
||||
outfile.write(" ")
|
||||
|
||||
outfile.write("\n")
|
||||
outfile.write("};\n")
|
||||
|
||||
convert_image(sys.argv[1], sys.argv[2])
|
||||
|
||||
BIN
games/NXDoom/data/doom.ico
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
games/NXDoom/data/doom.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
games/NXDoom/data/heretic.ico
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
games/NXDoom/data/heretic.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
BIN
games/NXDoom/data/hexen.ico
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
games/NXDoom/data/hexen.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
games/NXDoom/data/setup.ico
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
games/NXDoom/data/setup.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
games/NXDoom/data/strife.ico
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
games/NXDoom/data/strife.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
games/NXDoom/data/wadfile.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
16
games/NXDoom/man/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
CMDLINE.doom
|
||||
CMDLINE.doom.md
|
||||
CMDLINE.heretic
|
||||
CMDLINE.heretic.md
|
||||
CMDLINE.hexen
|
||||
CMDLINE.hexen.md
|
||||
CMDLINE.strife
|
||||
CMDLINE.strife.md
|
||||
INSTALL.doom
|
||||
INSTALL.heretic
|
||||
INSTALL.hexen
|
||||
INSTALL.strife
|
||||
Makefile.in
|
||||
Makefile
|
||||
*.6
|
||||
*.5
|
||||
8
games/NXDoom/man/CMDLINE.template
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
== Command line parameters ==
|
||||
|
||||
This is a full list of the supported command line parameters. A number of
|
||||
additional parameters are supported in addition to those present in the DOS
|
||||
version.
|
||||
|
||||
@content
|
||||
|
||||
8
games/NXDoom/man/CMDLINE.template.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Command line parameters
|
||||
|
||||
This is a full list of the supported command line parameters. A number of
|
||||
additional parameters are supported in addition to those present in the DOS
|
||||
version.
|
||||
|
||||
@content
|
||||
|
||||
316
games/NXDoom/man/INSTALL.template
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
#ifdef DOOM
|
||||
#define DEFAULT_IWAD doom2.wad
|
||||
#elif HERETIC
|
||||
#define DEFAULT_IWAD heretic.wad
|
||||
#elif HEXEN
|
||||
#define DEFAULT_IWAD hexen.wad
|
||||
#elif STRIFE
|
||||
#define DEFAULT_IWAD strife1.wad
|
||||
#endif
|
||||
# LONG_GAME_NAME installation
|
||||
|
||||
These are instructions for how to install and set up LONG_GAME_NAME
|
||||
for play.
|
||||
|
||||
#if !PRECOMPILED
|
||||
# Building LONG_GAME_NAME
|
||||
|
||||
Before you can play LONG_GAME_NAME, you need to compile a binary that
|
||||
you can run. For compilation, LONG_GAME_NAME requires the following
|
||||
to be installed:
|
||||
|
||||
* A C compiler (gcc is recommended)
|
||||
* make (GNU make is recommended)
|
||||
* SDL2 (see https://www.libsdl.org/)
|
||||
* SDL2_mixer (see https://www.libsdl.org/projects/SDL_mixer/)
|
||||
* SDL2_net (see https://www.libsdl.org/projects/SDL_net/)
|
||||
* Python (optional)
|
||||
|
||||
Follow the standard instructions for installing an autotools-based
|
||||
package:
|
||||
|
||||
1. Run `./configure` to initialize the package.
|
||||
2. Run `make` to compile the package.
|
||||
3. Run `make install` to install the package.
|
||||
|
||||
An automated build script is available that installs the necessary
|
||||
dependencies and builds the source code automatically. See the build
|
||||
instructions on the website.
|
||||
|
||||
Advanced topics such as cross-compilation are beyond the scope of this
|
||||
document. Please see the GNU autoconf / automake documentation for more
|
||||
information.
|
||||
|
||||
#endif
|
||||
# Obtaining an IWAD file
|
||||
|
||||
To play, you need an IWAD file. This file contains the game data
|
||||
(graphics, sounds, etc). The full versions of the games are
|
||||
proprietary and need to be bought. The IWAD file has one of the
|
||||
following names:
|
||||
|
||||
| IWAD | Game |
|
||||
| -------------------------- | ------------------------------- |
|
||||
#if DOOM
|
||||
| doom1.wad | Shareware Doom |
|
||||
| doom.wad | Registered / Ultimate Doom |
|
||||
| doom2.wad | Doom 2 |
|
||||
| tnt.wad | Final Doom: TNT: Evilution |
|
||||
| plutonia.wad | Final Doom: Plutonia Experiment |
|
||||
| chex.wad | Chex Quest |
|
||||
| freedoom1.wad | Freedoom: Phase 1 |
|
||||
| freedoom2.wad | Freedoom: Phase 2 |
|
||||
| freedm.wad | FreeDM |
|
||||
#endif
|
||||
#if HERETIC
|
||||
| heretic1.wad | Shareware Heretic |
|
||||
| heretic.wad | Registered / Commercial Heretic |
|
||||
#endif
|
||||
#if HEXEN
|
||||
| hexen.wad | Hexen |
|
||||
#endif
|
||||
#if STRIFE
|
||||
| strife1.wad (+voices.wad) | Strife |
|
||||
#endif
|
||||
|
||||
#if DOOM
|
||||
If you don’t have a copy of a commercial version, you can download
|
||||
the shareware version of Doom (extract the file named doom1.wad):
|
||||
|
||||
* https://www.doomworld.com/idgames/idstuff/doom/win95/doom95
|
||||
(idstuff/doom/win95/doom95.zip in your nearest /idgames mirror)
|
||||
|
||||
#endif
|
||||
If you have a commercial version on a CD-ROM, obtaining the IWAD
|
||||
file is usually straightforward. Simply locate the IWAD file on the
|
||||
disc and copy it off.
|
||||
|
||||
#if !__MACOSX__
|
||||
#if DOOM
|
||||
The Doom games are available to purchase for download on Steam
|
||||
(https://store.steampowered.com/), all releases containing the classic
|
||||
games including Doom 3: BFG Edition are supported.
|
||||
#endif
|
||||
#if HERETIC
|
||||
Heretic is available to purchase for download on Steam
|
||||
(https://store.steampowered.com/).
|
||||
#endif
|
||||
#if HEXEN
|
||||
Hexen and its expansion pack are available to purchase for download on
|
||||
Steam (https://store.steampowered.com/).
|
||||
#endif
|
||||
#if STRIFE
|
||||
Strife: Veteran Edition is available to purchase for download on Steam
|
||||
(https://store.steampowered.com/).
|
||||
#endif
|
||||
#if !_WIN32
|
||||
For Steam on Linux, you need to enable “Steam Play” for all titles in
|
||||
order to install the games. You may do this from the Steam menu,
|
||||
Setup, and the Steam Play tab.
|
||||
#endif
|
||||
LONG_GAME_NAME will autodetect IWADs installed by Steam and you do not
|
||||
need to do anything.
|
||||
#else
|
||||
The Doom, Heretic, Hexen, and Strife games are available to purchase
|
||||
for download on Steam (https://store.steampowered.com/), but are only
|
||||
available for Windows. To find the IWAD files on a Windows or Wine
|
||||
system, look in the Steam directory (usually within “Program Files”),
|
||||
under the “steamapps/common” path.
|
||||
#endif
|
||||
|
||||
#if DOOM || STRIFE
|
||||
The Doom and Strife: Veteran Edition games are available for purchase
|
||||
on GOG.com (https://www.gog.com/).
|
||||
#if _WIN32
|
||||
LONG_GAME_NAME will autodetect IWADs from the standalone or GOG Galaxy
|
||||
installers and you do not need to do anything.
|
||||
#else
|
||||
The games are only available for Windows, but you may find the IWAD
|
||||
files on a Windows or Wine system, typically within the “C:\GOG Games”
|
||||
or “C:\Program Files\GOG Galaxy” directories.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#if DOOM || HERETIC
|
||||
Older floppy disk versions are harder to deal with. The easiest way
|
||||
to install from floppies is to run the original installer program
|
||||
inside an emulator such as DOSbox (https://www.dosbox.com/).
|
||||
As an alternative to using an emulator, it is possible to extract the
|
||||
files manually. On the install disk(s), you will find several files
|
||||
with numbered extensions (eg. “doom_se.1”).
|
||||
|
||||
From the command line it is possible to combine these files into a
|
||||
single large file, using a command similar to the following:
|
||||
|
||||
#if _WIN32
|
||||
copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se.5 doom_se.lzh
|
||||
#else
|
||||
cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.lzh
|
||||
#endif
|
||||
|
||||
The resulting file is an LHA archive file, and it can be extracted
|
||||
using an LHA archive tool (there is one available for almost every
|
||||
operating system).
|
||||
|
||||
#endif
|
||||
# Running the game
|
||||
|
||||
#if __MACOSX__
|
||||
Once you have an IWAD file, you can specify its location within the
|
||||
graphical launcher program. Click the “Configure...” button, and then
|
||||
click “Set...” for each IWAD to choose its location. From the main
|
||||
launcher dialog you can then choose which game you want to play and
|
||||
click the “Launch” button to start the game.
|
||||
|
||||
If you are an advanced user and like to run Doom from the command
|
||||
line, you can use the “Command Prompt...” menu item to open a Terminal
|
||||
window. The DOOMWADPATH environment variable is preconfigured
|
||||
to point to the locations of the IWAD files set within the launcher.
|
||||
You can launch the game with a specific IWAD file by typing, for
|
||||
example:
|
||||
|
||||
LONG_EXE_NAME -iwad tnt.wad
|
||||
#else
|
||||
LONG_GAME_NAME needs to know where to find your IWAD file. To do this,
|
||||
do one of the following:
|
||||
|
||||
#if _WIN32
|
||||
* Within Explorer, simply place the IWAD file in the same folder as
|
||||
the LONG_GAME_NAME files, and double-click `LONG_EXE_NAME.exe`.
|
||||
|
||||
* Run LONG_GAME_NAME from the command prompt with the `-iwad` command
|
||||
line parameter to specify the IWAD file to use, eg.
|
||||
|
||||
LONG_EXE_NAME -iwad c:\games\DEFAULT_IWAD
|
||||
|
||||
* Set the environment variable DOOMWADDIR to the location of a
|
||||
directory containing your IWAD files.
|
||||
|
||||
* If you have multiple IWADs in different directories, set the
|
||||
environment variable DOOMWADPATH to be a semicolon-separated list
|
||||
of directories to search (similar to the PATH environment
|
||||
variable).
|
||||
#else
|
||||
* Run LONG_GAME_NAME from the Unix console with the `-iwad` command
|
||||
line parameter to specify the IWAD file to use, eg.
|
||||
|
||||
LONG_EXE_NAME -iwad /root/DEFAULT_IWAD
|
||||
|
||||
* Put the file into one of the following directories:
|
||||
|
||||
$HOME/.local/share/games/doom
|
||||
/usr/share/doom
|
||||
/usr/share/games/doom
|
||||
/usr/local/share/doom
|
||||
/usr/local/share/games/doom
|
||||
|
||||
* Set the environment variable DOOMWADDIR to specify the path to a
|
||||
directory containing your IWAD files.
|
||||
|
||||
* If you have multiple IWADs in different directories, set the
|
||||
environment variable DOOMWADPATH to be a colon-separated list of
|
||||
directories to search (similar to the Unix PATH environment
|
||||
variable).
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if DOOM
|
||||
# Playing with Freedoom
|
||||
|
||||
Freedoom is an open content project to create a Doom engine-based game
|
||||
that is entirely free software. The website can be found here:
|
||||
|
||||
https://freedoom.github.io/
|
||||
|
||||
Check out the [Chocolate Doom wiki’s page on
|
||||
Freedoom](https://www.chocolate-doom.org/wiki/index.php/Freedoom)
|
||||
for more information.
|
||||
|
||||
# Playing with Chex Quest
|
||||
|
||||
Chex Quest is a game based on Doom with some minor modifications that
|
||||
was distributed with boxes of Chex cereal in 1997. It is possible to
|
||||
play Chex Quest using LONG_GAME_NAME. To do this, the following files
|
||||
are needed:
|
||||
|
||||
* The IWAD file “chex.wad”, from the Chex Quest CD.
|
||||
|
||||
* The dehacked patch “chex.deh”, which can be found here:
|
||||
https://www.doomworld.com/idgames/themes/chex/chexdeh
|
||||
(themes/chex/chexdeh.zip in your nearest /idgames mirror)
|
||||
|
||||
Copy these files into a directory together and use the `-iwad` command
|
||||
line parameter to specify the Chex Quest IWAD file:
|
||||
|
||||
LONG_EXE_NAME -iwad chex.wad
|
||||
|
||||
#endif
|
||||
# Installing upgrades
|
||||
|
||||
#if DOOM
|
||||
LONG_GAME_NAME requires a version 1.9 IWAD file. Generally, if you
|
||||
install a recent version of Doom you should have a version 1.9 IWAD.
|
||||
#elif HERETIC
|
||||
LONG_GAME_NAME requires a version 1.2 (Shareware) or version 1.3
|
||||
(Shadow of the Serpent Riders) IWAD file. Generally, if you install a
|
||||
recent version of Heretic you should have a version 1.2 or 1.3 IWAD.
|
||||
#elif HEXEN
|
||||
LONG_GAME_NAME requires a version 1.1 IWAD file. Generally, if you
|
||||
install a recent version of Hexen you should have a version 1.1 IWAD.
|
||||
#elif STRIFE
|
||||
LONG_GAME_NAME requires a version 1.2 IWAD file. Generally, if you
|
||||
install a recent version of Strife you should have a version 1.2 IWAD.
|
||||
Please note that Strife version 1.3 does not update the IWAD, if your
|
||||
version.txt file says “STRIFE(TM) VERSION 1.3”, you are still good.
|
||||
#endif
|
||||
However, if you are installing from a very old CD version or from
|
||||
floppy disks, you might find you have an older version.
|
||||
|
||||
The most obvious symptom of an out of date IWAD file is that the game
|
||||
will exit at the title screen before the demo starts, with the message
|
||||
“Demo is from a different game version!”. If this happens, your IWAD
|
||||
file is out of date and you need to upgrade.
|
||||
|
||||
Upgrade patches are available that will update your game to the latest
|
||||
version, the following sites have the patches:
|
||||
|
||||
#if DOOM
|
||||
* http://www.doom2.net/doom2/utils.html
|
||||
* http://www.gamers.org/pub/idgames/idstuff/doom
|
||||
* http://www.gamers.org/pub/idgames/idstuff/doom2
|
||||
#elif HERETIC
|
||||
* http://www.gamers.org/pub/idgames/idstuff/heretic
|
||||
#elif HEXEN
|
||||
* http://www.gamers.org/pub/idgames/idstuff/hexen
|
||||
#elif STRIFE
|
||||
* http://www.gamers.org/pub/idgames/roguestuff
|
||||
#endif
|
||||
|
||||
Please see the
|
||||
[Doom Wiki’s page on game patches](https://doomwiki.org/wiki/Game_patch)
|
||||
for more information.
|
||||
|
||||
#if _WIN32
|
||||
As the patches are binary patches that run as DOS executables, on
|
||||
recent 64-bit versions of Windows you will need to use a DOS emulator
|
||||
(such as DOSBox) to run them.
|
||||
#else
|
||||
As the patches are binary patches that run as DOS executables, you
|
||||
will need to use a DOS emulator (such as DOSBox) to run them.
|
||||
#endif
|
||||
|
||||
# Music support
|
||||
|
||||
LONG_GAME_NAME includes OPL emulation code that accurately reproduces
|
||||
the way that the in-game music sounded under DOS when using an
|
||||
Adlib/Soundblaster card. This is, however, not to everyone’s taste.
|
||||
|
||||
LONG_GAME_NAME includes a number of different options for better
|
||||
quality MIDI playback; see the file README.Music for more details of
|
||||
how to set these up.
|
||||
|
||||
#if !PRECOMPILED
|
||||
When compiling from source, be sure to compile and install Timidity
|
||||
before installing SDL2_mixer.
|
||||
|
||||
#endif
|
||||
226
games/NXDoom/man/Makefile.am
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
SUBDIRS = bash-completion
|
||||
|
||||
MANPAGE_GEN_FILES = environ.man \
|
||||
iwad_paths.man \
|
||||
doom.template \
|
||||
heretic.template \
|
||||
hexen.template \
|
||||
strife.template \
|
||||
docgen \
|
||||
default.cfg.template \
|
||||
extra.cfg.template \
|
||||
server.template \
|
||||
setup.template
|
||||
|
||||
doomdocsdir = ${docdir}/../${PROGRAM_PREFIX}doom
|
||||
hereticdocsdir = ${docdir}/../${PROGRAM_PREFIX}heretic
|
||||
hexendocsdir = ${docdir}/../${PROGRAM_PREFIX}hexen
|
||||
strifedocsdir = ${docdir}/../${PROGRAM_PREFIX}strife
|
||||
|
||||
if HAVE_DOC
|
||||
|
||||
GENERATED_MAN_PAGES = \
|
||||
@PROGRAM_PREFIX@doom.6 \
|
||||
default.cfg.5 \
|
||||
@PROGRAM_PREFIX@doom.cfg.5 \
|
||||
@PROGRAM_PREFIX@heretic.6 \
|
||||
heretic.cfg.5 \
|
||||
@PROGRAM_PREFIX@heretic.cfg.5 \
|
||||
@PROGRAM_PREFIX@hexen.6 \
|
||||
hexen.cfg.5 \
|
||||
@PROGRAM_PREFIX@hexen.cfg.5 \
|
||||
@PROGRAM_PREFIX@strife.6 \
|
||||
strife.cfg.5 \
|
||||
@PROGRAM_PREFIX@strife.cfg.5 \
|
||||
@PROGRAM_PREFIX@server.6
|
||||
|
||||
SETUP_MAN_PAGES = \
|
||||
@PROGRAM_PREFIX@doom-setup.6 \
|
||||
@PROGRAM_PREFIX@heretic-setup.6 \
|
||||
@PROGRAM_PREFIX@hexen-setup.6 \
|
||||
@PROGRAM_PREFIX@strife-setup.6
|
||||
|
||||
man_MANS = $(GENERATED_MAN_PAGES) \
|
||||
$(SETUP_MAN_PAGES)
|
||||
|
||||
doomdocs_DATA = INSTALL.doom CMDLINE.doom
|
||||
hereticdocs_DATA = INSTALL.heretic CMDLINE.heretic
|
||||
hexendocs_DATA = INSTALL.hexen CMDLINE.hexen
|
||||
strifedocs_DATA = INSTALL.strife CMDLINE.strife
|
||||
|
||||
if HAVE_WINDRES
|
||||
|
||||
WIN32=-D_WIN32
|
||||
|
||||
doomdocs_DATA += CMDLINE.doom.md
|
||||
hereticdocs_DATA += CMDLINE.heretic.md
|
||||
hexendocs_DATA += CMDLINE.hexen.md
|
||||
strifedocs_DATA += CMDLINE.strife.md
|
||||
|
||||
endif
|
||||
|
||||
CLEANFILES = $(GENERATED_MAN_PAGES) $(SETUP_MAN_PAGES) \
|
||||
$(doomdocs_DATA) $(hereticdocs_DATA) \
|
||||
$(hexendocs_DATA) $(strifedocs_DATA)
|
||||
DOCGEN = $(srcdir)/docgen
|
||||
DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" \
|
||||
-s "@PACKAGE_NAME@" \
|
||||
-z "@PACKAGE_SHORTNAME@" \
|
||||
-v "@VERSION@"
|
||||
|
||||
@PROGRAM_PREFIX@doom.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g doom -m $(srcdir)/doom.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/doom > $@
|
||||
|
||||
default.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g doom -m $(srcdir)/default.cfg.template \
|
||||
-c default $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
@PROGRAM_PREFIX@doom.cfg.5: $(top_srcdir)/src extra.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g doom -m $(srcdir)/extra.cfg.template \
|
||||
-c extended $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
CMDLINE.doom : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/doom
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-p $(srcdir)/CMDLINE.template \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@
|
||||
|
||||
CMDLINE.doom.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/doom
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-M $(srcdir)/CMDLINE.template.md \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@
|
||||
|
||||
CMDLINE.doom.wikitext : $(top_srcdir)/src $(top_srcdir)/src/doom
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-w $(top_srcdir)/src/ $(top_srcdir)/src/doom/ > $@
|
||||
|
||||
INSTALL.doom: INSTALL.template
|
||||
$(srcdir)/simplecpp -DDOOM $(WIN32) \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \
|
||||
-DPRECOMPILED < $(srcdir)/INSTALL.template > $@
|
||||
|
||||
@PROGRAM_PREFIX@heretic.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES) heretic.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g heretic -m $(srcdir)/heretic.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/heretic > $@
|
||||
|
||||
heretic.cfg.5: $(top_srcdir)/src $(srcdir)/default.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g heretic -m $(srcdir)/default.cfg.template \
|
||||
-c default $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
@PROGRAM_PREFIX@heretic.cfg.5: $(top_srcdir)/src extra.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g heretic -m $(srcdir)/extra.cfg.template \
|
||||
-c extended $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
CMDLINE.heretic : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/heretic
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-p $(srcdir)/CMDLINE.template \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@
|
||||
|
||||
CMDLINE.heretic.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/heretic
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-M $(srcdir)/CMDLINE.template.md \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/heretic/ > $@
|
||||
|
||||
INSTALL.heretic: INSTALL.template
|
||||
$(srcdir)/simplecpp -DHERETIC $(WIN32) \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Heretic" \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@heretic" \
|
||||
-DPRECOMPILED < $(srcdir)/INSTALL.template > $@
|
||||
|
||||
|
||||
@PROGRAM_PREFIX@hexen.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g hexen -m $(srcdir)/hexen.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/hexen > $@
|
||||
|
||||
hexen.cfg.5: $(top_srcdir)/src default.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g hexen -m $(srcdir)/default.cfg.template \
|
||||
-c default $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
@PROGRAM_PREFIX@hexen.cfg.5: $(top_srcdir)/src extra.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g hexen -m $(srcdir)/extra.cfg.template \
|
||||
-c extended $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
CMDLINE.hexen : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/hexen
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-p $(srcdir)/CMDLINE.template \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@
|
||||
|
||||
CMDLINE.hexen.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/hexen
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-M $(srcdir)/CMDLINE.template.md \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/hexen/ > $@
|
||||
|
||||
INSTALL.hexen: INSTALL.template
|
||||
$(srcdir)/simplecpp -DHEXEN $(WIN32) \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Hexen" \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@hexen" \
|
||||
-DPRECOMPILED < $(srcdir)/INSTALL.template > $@
|
||||
|
||||
@PROGRAM_PREFIX@strife.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g strife -m $(srcdir)/strife.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/strife > $@
|
||||
|
||||
@PROGRAM_PREFIX@server.6: $(top_srcdir)/src $(MANPAGE_GEN_FILES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g server -m $(srcdir)/server.template \
|
||||
$(top_srcdir)/src > $@
|
||||
|
||||
$(SETUP_MAN_PAGES): $(top_srcdir)/src $(MANPAGE_GEN_FILES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g $(patsubst @PROGRAM_PREFIX@%-setup.6,%,$@) \
|
||||
-m $(srcdir)/setup.template \
|
||||
$(top_srcdir)/src > $@
|
||||
|
||||
strife.cfg.5: $(top_srcdir)/src default.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g strife -m $(srcdir)/default.cfg.template \
|
||||
-c default $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
@PROGRAM_PREFIX@strife.cfg.5: $(top_srcdir)/src extra.cfg.template
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g strife -m $(srcdir)/extra.cfg.template \
|
||||
-c extended $(top_srcdir)/src/m_config.c > $@
|
||||
|
||||
CMDLINE.strife : CMDLINE.template $(top_srcdir)/src $(top_srcdir)/src/strife
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-p $(srcdir)/CMDLINE.template \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@
|
||||
|
||||
CMDLINE.strife.md : CMDLINE.template.md $(top_srcdir)/src $(top_srcdir)/src/strife
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-M $(srcdir)/CMDLINE.template.md \
|
||||
$(top_srcdir)/src/ $(top_srcdir)/src/strife/ > $@
|
||||
|
||||
INSTALL.strife: INSTALL.template
|
||||
$(srcdir)/simplecpp -DSTRIFE $(WIN32) \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@strife" \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Strife" \
|
||||
-DPRECOMPILED < $(srcdir)/INSTALL.template > $@
|
||||
|
||||
|
||||
INSTALL: INSTALL.template
|
||||
$(srcdir)//simplecpp -DDOOM -DHERETIC -DHEXEN -DSTRIFE \
|
||||
-DLONG_GAME_NAME="@PACKAGE_SHORTNAME@ Doom" \
|
||||
-DLONG_EXE_NAME="@PROGRAM_PREFIX@doom" \
|
||||
-DPRECOMPILED < $(srcdir)/INSTALL.template > $@
|
||||
|
||||
endif
|
||||
|
||||
EXTRA_DIST = $(man_MANS) $(MANPAGE_GEN_FILES) \
|
||||
wikipages \
|
||||
CMDLINE.template \
|
||||
CMDLINE.template.md \
|
||||
INSTALL.template \
|
||||
simplecpp
|
||||
|
||||
5
games/NXDoom/man/bash-completion/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
*doom
|
||||
*heretic
|
||||
*hexen
|
||||
*strife
|
||||
*.template
|
||||
52
games/NXDoom/man/bash-completion/Makefile.am
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
bashcompletiondir=@datadir@/bash-completion/completions
|
||||
|
||||
BASH_COMPLETION_TEMPLATES = \
|
||||
doom.template \
|
||||
heretic.template \
|
||||
hexen.template \
|
||||
strife.template
|
||||
|
||||
if HAVE_BASH_COMPLETION
|
||||
|
||||
BASH_COMPLETION_SCRIPTLETS = \
|
||||
@PROGRAM_PREFIX@doom \
|
||||
@PROGRAM_PREFIX@heretic \
|
||||
@PROGRAM_PREFIX@hexen \
|
||||
@PROGRAM_PREFIX@strife
|
||||
|
||||
bashcompletion_DATA = $(BASH_COMPLETION_SCRIPTLETS)
|
||||
CLEANFILES = $(BASH_COMPLETION_SCRIPTLETS)
|
||||
|
||||
DOCGEN = $(top_srcdir)/man/docgen
|
||||
DOCGEN_COMMON_ARGS = -n "@PROGRAM_SPREFIX@" -s "@PACKAGE_NAME@" -z "@PACKAGE_SHORTNAME@"
|
||||
|
||||
@PROGRAM_PREFIX@doom: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g doom -b doom.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/doom > $@
|
||||
|
||||
@PROGRAM_PREFIX@heretic: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g heretic -b heretic.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/heretic > $@
|
||||
|
||||
@PROGRAM_PREFIX@hexen: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g hexen -b hexen.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/hexen > $@
|
||||
|
||||
@PROGRAM_PREFIX@strife: $(top_srcdir)/src $(DOCGEN) $(BASH_COMPLETION_TEMPLATES)
|
||||
$(DOCGEN) $(DOCGEN_COMMON_ARGS) \
|
||||
-g strife -b strife.template \
|
||||
$(top_srcdir)/src $(top_srcdir)/src/strife > $@
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(BASH_COMPLETION_TEMPLATES) \
|
||||
$(BASH_COMPLETION_SCRIPTLETS)
|
||||
|
||||
else
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(BASH_COMPLETION_TEMPLATES)
|
||||
|
||||
endif
|
||||
51
games/NXDoom/man/bash-completion/doom.template.in
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# bash completion for @PACKAGE_SHORTNAME@ Doom -*- shell-script -*-
|
||||
|
||||
_@PROGRAM_SPREFIX@_doom()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
# Save the previous switch on the command line in the prevsw variable
|
||||
local i prevsw=""
|
||||
for (( i=1; $cword > 1 && i <= $cword; i++ )); do
|
||||
if [[ ${words[i]} == -* ]]; then
|
||||
prevsw=${words[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
# Allow adding more than one file with the same extension to the same switch
|
||||
case $prevsw in
|
||||
-config|-extraconfig)
|
||||
_filedir cfg
|
||||
;;
|
||||
-file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
|
||||
_filedir wad
|
||||
;;
|
||||
-playdemo|-timedemo)
|
||||
_filedir lmp
|
||||
;;
|
||||
-deh)
|
||||
_filedir '@(bex|deh)'
|
||||
;;
|
||||
esac
|
||||
|
||||
case $prev in
|
||||
-pack)
|
||||
COMPREPLY=(doom2 tnt plutonia)
|
||||
;;
|
||||
-gameversion)
|
||||
COMPREPLY=(1.666 1.7 1.8 1.9 ultimate final final2 hacx chex)
|
||||
;;
|
||||
-setmem)
|
||||
COMPREPLY=(dos622 dos71 dosbox)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
|
||||
fi
|
||||
} &&
|
||||
|
||||
complete -F _@PROGRAM_SPREFIX@_doom @PROGRAM_PREFIX@doom
|
||||
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
48
games/NXDoom/man/bash-completion/heretic.template.in
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# bash completion for @PACKAGE_SHORTNAME@ Heretic -*- shell-script -*-
|
||||
|
||||
_@PROGRAM_SPREFIX@_heretic()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
# Save the previous switch on the command line in the prevsw variable
|
||||
local i prevsw=""
|
||||
for (( i=1; $cword > 1 && i <= $cword; i++ )); do
|
||||
if [[ ${words[i]} == -* ]]; then
|
||||
prevsw=${words[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
# Allow adding more than one file with the same extension to the same switch
|
||||
case $prevsw in
|
||||
-config|-extraconfig)
|
||||
_filedir cfg
|
||||
;;
|
||||
-file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
|
||||
_filedir wad
|
||||
;;
|
||||
-playdemo|-timedemo)
|
||||
_filedir lmp
|
||||
;;
|
||||
-deh)
|
||||
_filedir hhe
|
||||
;;
|
||||
esac
|
||||
|
||||
case $prev in
|
||||
-hhever)
|
||||
COMPREPLY=(1.0 1.2 1.3)
|
||||
;;
|
||||
-setmem)
|
||||
COMPREPLY=(dos622 dos71 dosbox)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
|
||||
fi
|
||||
} &&
|
||||
|
||||
complete -F _@PROGRAM_SPREFIX@_heretic @PROGRAM_PREFIX@heretic
|
||||
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
45
games/NXDoom/man/bash-completion/hexen.template.in
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# bash completion for @PACKAGE_SHORTNAME@ Hexen -*- shell-script -*-
|
||||
|
||||
_@PROGRAM_SPREFIX@_hexen()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
# Save the previous switch on the command line in the prevsw variable
|
||||
local i prevsw=""
|
||||
for (( i=1; $cword > 1 && i <= $cword; i++ )); do
|
||||
if [[ ${words[i]} == -* ]]; then
|
||||
prevsw=${words[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
# Allow adding more than one file with the same extension to the same switch
|
||||
case $prevsw in
|
||||
-config|-extraconfig)
|
||||
_filedir cfg
|
||||
;;
|
||||
-file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
|
||||
_filedir wad
|
||||
;;
|
||||
-playdemo|-timedemo)
|
||||
_filedir lmp
|
||||
;;
|
||||
esac
|
||||
|
||||
case $prev in
|
||||
-gameversion)
|
||||
COMPREPLY=(1.1 1.1r2)
|
||||
;;
|
||||
-setmem)
|
||||
COMPREPLY=(dos622 dos71 dosbox)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
|
||||
fi
|
||||
} &&
|
||||
|
||||
complete -F _@PROGRAM_SPREFIX@_hexen @PROGRAM_PREFIX@hexen
|
||||
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
48
games/NXDoom/man/bash-completion/strife.template.in
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# bash completion for @PACKAGE_SHORTNAME@ Strife -*- shell-script -*-
|
||||
|
||||
_@PROGRAM_SPREFIX@_strife()
|
||||
{
|
||||
local cur prev words cword
|
||||
_init_completion || return
|
||||
|
||||
# Save the previous switch on the command line in the prevsw variable
|
||||
local i prevsw=""
|
||||
for (( i=1; $cword > 1 && i <= $cword; i++ )); do
|
||||
if [[ ${words[i]} == -* ]]; then
|
||||
prevsw=${words[i]}
|
||||
fi
|
||||
done
|
||||
|
||||
# Allow adding more than one file with the same extension to the same switch
|
||||
case $prevsw in
|
||||
-config|-extraconfig)
|
||||
_filedir cfg
|
||||
;;
|
||||
-file|-iwad|-aa|-af|-as|-merge|-nwtmerge)
|
||||
_filedir wad
|
||||
;;
|
||||
-playdemo|-timedemo)
|
||||
_filedir lmp
|
||||
;;
|
||||
-deh)
|
||||
_filedir seh
|
||||
;;
|
||||
esac
|
||||
|
||||
case $prev in
|
||||
-gameversion)
|
||||
COMPREPLY=(1.2 1.31)
|
||||
;;
|
||||
-setmem)
|
||||
COMPREPLY=(dos622 dos71 dosbox)
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ $cur == -* ]]; then
|
||||
COMPREPLY=( $( compgen -W '@content' -- "$cur" ) )
|
||||
fi
|
||||
} &&
|
||||
|
||||
complete -F _@PROGRAM_SPREFIX@_strife @PROGRAM_PREFIX@strife
|
||||
|
||||
# ex: ts=4 sw=4 et filetype=sh
|
||||
50
games/NXDoom/man/default.cfg.template
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
.TH @CFGFILE@ 5 2017-11-30 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@CFGFILE@ \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fI@CFGFILE@\fR
|
||||
is the configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). The configuration
|
||||
options stored in the file are the same as those stored in the
|
||||
original DOS Vanilla @GAME_UPPER@.
|
||||
Extra @PACKAGE_SHORTNAME@ @GAME_UPPER@-specific options are stored in a separate
|
||||
configuration file, \fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR.
|
||||
.PP
|
||||
\fI@CFGFILE@\fR is normally stored in the user's home directory,
|
||||
as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@CFGFILE@\fR. The path can be
|
||||
overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG
|
||||
Base Directory Specification).
|
||||
.PP
|
||||
The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end
|
||||
for editing \fI@CFGFILE@\fR.
|
||||
.SH FILE FORMAT
|
||||
The file is a plain-text file, consisting of a list of configuration
|
||||
options and their values, separated by whitespace. Each option is stored
|
||||
on a separate line. Options have different types; an option may have
|
||||
either an integer, floating point or string value. If the option is
|
||||
of a string type, the value is surrounded by quotes (").
|
||||
.PP
|
||||
For example:
|
||||
.RS
|
||||
.PP
|
||||
.EX
|
||||
integer_value 1
|
||||
integer_value2 1
|
||||
floating_point_value 4.2
|
||||
string_value "hello world"
|
||||
.EE
|
||||
.RE
|
||||
.PP
|
||||
Invalid lines or comments in the file will be ignored, but it is advisable
|
||||
not to put them in the file; the file is rewritten from scratch every time
|
||||
the game exits, so any invalid lines or comments will be lost.
|
||||
.PP
|
||||
Some options are used for keyboard key bindings; these are stored as
|
||||
integer values containing the keyboard scan code of the key to be bound to.
|
||||
Boolean values are also stored as integers, with a value of zero usually
|
||||
indicating "false" and a non-zero value indicating "true".
|
||||
@content
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5),
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6)
|
||||
624
games/NXDoom/man/docgen
Executable file
|
|
@ -0,0 +1,624 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Chocolate Doom self-documentation tool. This works similar to javadoc
|
||||
# or doxygen, but documents command line parameters and configuration
|
||||
# file values, generating documentation in Unix manpage, wikitext and
|
||||
# plain text forms.
|
||||
#
|
||||
# Comments are read from the source code in the following form:
|
||||
#
|
||||
# //!
|
||||
# // @arg <extra arguments>
|
||||
# // @category Category
|
||||
# // @platform <some platform that the parameter is specific to>
|
||||
# //
|
||||
# // Long description of the parameter
|
||||
# //
|
||||
#
|
||||
# something_involving = M_CheckParm("-param");
|
||||
#
|
||||
# For configuration file values:
|
||||
#
|
||||
# //! @begin_config_file myconfig
|
||||
#
|
||||
# //!
|
||||
# // Description of the configuration file value.
|
||||
# //
|
||||
#
|
||||
# CONFIG_VARIABLE_INT(my_variable, c_variable),
|
||||
#
|
||||
|
||||
import io
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import glob
|
||||
import getopt
|
||||
|
||||
TEXT_WRAP_WIDTH = 78
|
||||
INCLUDE_STATEMENT_RE = re.compile(r"@include\s+(\S+)")
|
||||
|
||||
# Use appropriate stdout function for Python 2 or 3
|
||||
|
||||
def stdout(buf):
|
||||
if sys.version_info.major < 3:
|
||||
sys.stdout.write(buf)
|
||||
else:
|
||||
sys.stdout.buffer.write(buf)
|
||||
|
||||
# Find the maximum width of a list of parameters (for plain text output)
|
||||
|
||||
def parameter_list_width(params):
|
||||
w = 0
|
||||
|
||||
for p in params:
|
||||
pw = len(p.name) + 5
|
||||
|
||||
if p.args:
|
||||
pw += len(p.args)
|
||||
|
||||
if pw > w:
|
||||
w = pw
|
||||
|
||||
return w
|
||||
|
||||
class ConfigFile:
|
||||
def __init__(self, filename):
|
||||
self.filename = filename
|
||||
self.variables = []
|
||||
|
||||
def add_variable(self, variable):
|
||||
self.variables.append(variable)
|
||||
|
||||
def manpage_output(self):
|
||||
result = ".SH CONFIGURATION VARIABLES\n"
|
||||
|
||||
for v in self.variables:
|
||||
result += ".TP\n"
|
||||
result += v.manpage_output()
|
||||
|
||||
return result
|
||||
|
||||
def plaintext_output(self):
|
||||
result = ""
|
||||
|
||||
w = parameter_list_width(self.variables)
|
||||
|
||||
for p in self.variables:
|
||||
result += p.plaintext_output(w)
|
||||
|
||||
result = result.rstrip() + "\n"
|
||||
|
||||
return result
|
||||
|
||||
class Category:
|
||||
def __init__(self, description):
|
||||
self.description = description
|
||||
self.params = []
|
||||
|
||||
def add_param(self, param):
|
||||
self.params.append(param)
|
||||
|
||||
# Plain text output
|
||||
|
||||
def plaintext_output(self):
|
||||
result = "=== %s ===\n\n" % self.description
|
||||
|
||||
self.params.sort()
|
||||
|
||||
w = parameter_list_width(self.params)
|
||||
|
||||
for p in self.params:
|
||||
if p.should_show():
|
||||
result += p.plaintext_output(w)
|
||||
|
||||
result = result.rstrip() + "\n"
|
||||
|
||||
return result
|
||||
|
||||
def markdown_output(self):
|
||||
result = "## %s\n\n| Parameter | Description |\n| - | - |\n" % self.description
|
||||
|
||||
self.params.sort()
|
||||
|
||||
for p in self.params:
|
||||
if p.should_show():
|
||||
result += p.markdown_output()
|
||||
|
||||
result = result.rstrip() + "\n"
|
||||
|
||||
return result
|
||||
|
||||
def completion_output(self):
|
||||
result = ""
|
||||
|
||||
self.params.sort()
|
||||
|
||||
for p in self.params:
|
||||
if p.should_show():
|
||||
result += p.completion_output(0)
|
||||
|
||||
result = result.rstrip()
|
||||
|
||||
return result
|
||||
|
||||
def manpage_output(self):
|
||||
result = ".SH " + self.description.upper() + "\n"
|
||||
|
||||
self.params.sort()
|
||||
|
||||
for p in self.params:
|
||||
if p.should_show():
|
||||
result += ".TP\n"
|
||||
result += p.manpage_output()
|
||||
|
||||
return result
|
||||
|
||||
def wiki_output(self):
|
||||
result = "=== %s ===\n" % self.description
|
||||
|
||||
self.params.sort()
|
||||
|
||||
for p in self.params:
|
||||
if p.should_show():
|
||||
result += "; " + p.wiki_output() + "\n"
|
||||
|
||||
# Escape special HTML characters
|
||||
|
||||
result = result.replace("&", "&")
|
||||
result = result.replace("<", "<")
|
||||
result = result.replace(">", ">")
|
||||
|
||||
return result
|
||||
|
||||
categories = (
|
||||
(None, Category("General options")),
|
||||
("game", Category("Game start options")),
|
||||
("video", Category("Display options")),
|
||||
("net", Category("Networking options")),
|
||||
("mod", Category("Dehacked and WAD merging")),
|
||||
("demo", Category("Demo options")),
|
||||
("compat", Category("Compatibility")),
|
||||
("obscure", Category("Obscure and less-used options")),
|
||||
)
|
||||
|
||||
wikipages = []
|
||||
config_files = {}
|
||||
|
||||
# Show options that are in Vanilla Doom? Or only new options?
|
||||
|
||||
show_vanilla_options = True
|
||||
|
||||
class Parameter:
|
||||
def __lt__(self, other):
|
||||
return self.name < other.name
|
||||
|
||||
def __init__(self):
|
||||
self.text = ""
|
||||
self.name = ""
|
||||
self.args = None
|
||||
self.platform = None
|
||||
self.category = None
|
||||
self.vanilla_option = False
|
||||
self.games = None
|
||||
|
||||
def should_show(self):
|
||||
return not self.vanilla_option or show_vanilla_options
|
||||
|
||||
def add_text(self, text):
|
||||
if len(text) <= 0:
|
||||
pass
|
||||
elif text[0] == "@":
|
||||
match = re.match(r'@(\S+)\s*(.*)', text)
|
||||
|
||||
if not match:
|
||||
raise "Malformed option line: %s" % text
|
||||
|
||||
option_type = match.group(1)
|
||||
data = match.group(2)
|
||||
|
||||
if option_type == "arg":
|
||||
self.args = data
|
||||
elif option_type == "platform":
|
||||
self.platform = data
|
||||
elif option_type == "category":
|
||||
self.category = data
|
||||
elif option_type == "vanilla":
|
||||
self.vanilla_option = True
|
||||
elif option_type == "game":
|
||||
self.games = re.split(r'\s+', data.strip())
|
||||
else:
|
||||
raise "Unknown option type '%s'" % option_type
|
||||
|
||||
else:
|
||||
self.text += text + " "
|
||||
|
||||
def _games_only_text(self, pattern="(%s only)"):
|
||||
if not match_game and self.games:
|
||||
games_list = ", ".join(map(str.capitalize, self.games))
|
||||
return " " + (pattern % games_list)
|
||||
else:
|
||||
return ""
|
||||
|
||||
def manpage_output(self):
|
||||
if self.args:
|
||||
# Special cases -- GBR is not proud.
|
||||
if self.args == "[<x> <y> | <xy>]":
|
||||
result = ".BR " + self.name + " \\~\\c\n" \
|
||||
+ ".RI [ x\\~y | xy ]\n"
|
||||
elif self.args == "<WxH>":
|
||||
result = ".BI " + self.name + "\\~ W x H\n"
|
||||
elif self.args == "<x> <y>":
|
||||
result = ".BI " + self.name + "\\~ \"x y\"\n"
|
||||
elif self.args == "<files>":
|
||||
result = ".BI " + self.name + "\\~ \"file\\~\\c\n" \
|
||||
+ "\\&.\\|.\\|.\n"
|
||||
elif self.args == "<save-num> <demo-name>":
|
||||
result = ".BI " + self.name \
|
||||
+ "\\~ \"save-num demo-name\"\n"
|
||||
else:
|
||||
self.args = re.sub(r'[<>]', '', self.args)
|
||||
result = ".BI " + self.name + "\\~ " + self.args + "\n"
|
||||
else:
|
||||
result = ".B " + self.name + "\n"
|
||||
|
||||
if self.platform:
|
||||
result += "[%s only] " % self.platform
|
||||
|
||||
escaped = re.sub(r'\\', r'\\\\', self.text)
|
||||
|
||||
result += escaped + self._games_only_text() + "\n"
|
||||
|
||||
return result
|
||||
|
||||
def wiki_output(self):
|
||||
result = self.name
|
||||
|
||||
if self.args:
|
||||
result += " " + self.args
|
||||
|
||||
result += ": "
|
||||
|
||||
result += add_wiki_links(self.text)
|
||||
|
||||
if self.platform:
|
||||
result += "'''(%s only)'''" % self.platform
|
||||
result += self._games_only_text("'''(%s only)'''")
|
||||
|
||||
return result
|
||||
|
||||
def markdown_output(self):
|
||||
if self.args:
|
||||
name = "%s %s" % (self.name, self.args)
|
||||
else:
|
||||
name = "%s" % self.name
|
||||
|
||||
name = name.replace("|", "\\|")
|
||||
|
||||
text = self.text
|
||||
if self.platform:
|
||||
text += " (%s only)" % self.platform
|
||||
|
||||
text = text.replace("|", "\\|")
|
||||
|
||||
result = "| %s | %s |\n" % (name, text)
|
||||
|
||||
# html escape
|
||||
result = result.replace("<", "<")
|
||||
result = result.replace(">", ">")
|
||||
|
||||
return result
|
||||
|
||||
def plaintext_output(self, indent):
|
||||
# Build the first line, with the argument on
|
||||
start = " " + self.name
|
||||
if self.args:
|
||||
start += " " + self.args
|
||||
|
||||
# pad up to the plaintext width
|
||||
start += " " * (indent - len(start))
|
||||
|
||||
# Build the description text
|
||||
description = self.text
|
||||
if self.platform:
|
||||
description += " (%s only)" % self.platform
|
||||
description += self._games_only_text()
|
||||
|
||||
# Build the complete text for the argument
|
||||
# Split the description into words and add a word at a time
|
||||
result = ""
|
||||
words = [word for word in re.split(r'\s+', description) if word]
|
||||
maxlen = TEXT_WRAP_WIDTH - indent
|
||||
outlines = [[]]
|
||||
for word in words:
|
||||
linelen = sum(len(w) + 1 for w in outlines[-1])
|
||||
if linelen + len(word) > maxlen:
|
||||
outlines.append([])
|
||||
outlines[-1].append(word)
|
||||
|
||||
linesep = "\n" + " " * indent
|
||||
|
||||
return (start +
|
||||
linesep.join(" ".join(line) for line in outlines) +
|
||||
"\n\n")
|
||||
|
||||
def completion_output(self, w):
|
||||
|
||||
result = self.name + " "
|
||||
|
||||
return result
|
||||
|
||||
# Read list of wiki pages
|
||||
|
||||
def read_wikipages():
|
||||
f = io.open("wikipages", encoding='UTF-8')
|
||||
|
||||
try:
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
|
||||
line = re.sub(r'\#.*$', '', line)
|
||||
|
||||
if not re.match(r'^\s*$', line):
|
||||
wikipages.append(line)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
# Add wiki page links
|
||||
|
||||
def add_wiki_links(text):
|
||||
def replace_name(m):
|
||||
linktext = m.group(1)
|
||||
if linktext == pagename:
|
||||
return '[[%s]]' % pagename
|
||||
else:
|
||||
return '[[%s|%s]]' % (pagename, linktext)
|
||||
|
||||
for pagename in wikipages:
|
||||
text = re.sub(r'\b(%s)\b' % re.escape(pagename), replace_name,
|
||||
text, count=0, flags=re.IGNORECASE)
|
||||
|
||||
return text
|
||||
|
||||
def add_parameter(param, line, config_file):
|
||||
|
||||
# If we're only targeting a particular game, check this is one of
|
||||
# the ones we're targeting.
|
||||
|
||||
if match_game and param.games and match_game not in param.games:
|
||||
return
|
||||
|
||||
# Is this documenting a command line parameter?
|
||||
|
||||
match = re.search(r'(M_CheckParm(WithArgs)|M_ParmExists)?\s*\(\s*"(.*?)"',
|
||||
line)
|
||||
|
||||
if match:
|
||||
param.name = match.group(3)
|
||||
category = dict(categories)[param.category]
|
||||
category.add_param(param)
|
||||
return
|
||||
|
||||
# Documenting a configuration file variable?
|
||||
|
||||
match = re.search(r'CONFIG_VARIABLE_\S+\s*\(\s*(\S+?)\),', line)
|
||||
|
||||
if match:
|
||||
param.name = match.group(1)
|
||||
config_file.add_variable(param)
|
||||
return
|
||||
|
||||
raise Exception(param.text)
|
||||
|
||||
def process_file(filename):
|
||||
|
||||
current_config_file = None
|
||||
|
||||
f = io.open(filename, encoding='UTF-8')
|
||||
|
||||
try:
|
||||
param = None
|
||||
waiting_for_checkparm = False
|
||||
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
|
||||
# Ignore empty lines
|
||||
|
||||
if re.match(r'\s*$', line):
|
||||
continue
|
||||
|
||||
# Currently reading a doc comment?
|
||||
|
||||
if param:
|
||||
# End of doc comment
|
||||
|
||||
if not re.match(r'\s*//', line):
|
||||
waiting_for_checkparm = True
|
||||
|
||||
# The first non-empty line after the documentation comment
|
||||
# ends must contain the thing being documented.
|
||||
|
||||
if waiting_for_checkparm:
|
||||
add_parameter(param, line, current_config_file)
|
||||
param = None
|
||||
else:
|
||||
# More documentation text
|
||||
|
||||
munged_line = re.sub(r'\s*\/\/\s*', '', line, count=1)
|
||||
munged_line = re.sub(r'\s*$', '', munged_line)
|
||||
param.add_text(munged_line)
|
||||
|
||||
# Check for start of a doc comment
|
||||
|
||||
if re.search("//!", line):
|
||||
match = re.search(r"@begin_config_file\s*(\S+)", line)
|
||||
|
||||
if match:
|
||||
# Beginning a configuration file
|
||||
tagname = match.group(1)
|
||||
current_config_file = ConfigFile(tagname)
|
||||
config_files[tagname] = current_config_file
|
||||
else:
|
||||
# Start of a normal comment
|
||||
param = Parameter()
|
||||
waiting_for_checkparm = False
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def process_files(path):
|
||||
# Process all C source files.
|
||||
|
||||
if os.path.isdir(path):
|
||||
files = glob.glob(path + "/*.c")
|
||||
|
||||
for filename in files:
|
||||
process_file(filename)
|
||||
else:
|
||||
# Special case to allow a single file to be specified as a target
|
||||
|
||||
process_file(path)
|
||||
|
||||
def print_template(template_file, substs, content):
|
||||
f = io.open(template_file, encoding='UTF-8')
|
||||
|
||||
try:
|
||||
for line in f:
|
||||
match = INCLUDE_STATEMENT_RE.search(line)
|
||||
if match:
|
||||
filename = match.group(1)
|
||||
filename = os.path.join(os.path.dirname(template_file),
|
||||
filename)
|
||||
print_template(filename, substs, content)
|
||||
else:
|
||||
line = line.replace("@content", content)
|
||||
for k,v in substs.items():
|
||||
line = line.replace(k,v)
|
||||
stdout(line.rstrip().encode('UTF-8') + b'\n')
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def manpage_output(targets, substs, template_file):
|
||||
|
||||
content = ""
|
||||
|
||||
for t in targets:
|
||||
content += t.manpage_output()
|
||||
|
||||
content = content.replace("-", "\\-")
|
||||
|
||||
print_template(template_file, substs, content)
|
||||
|
||||
def wiki_output(targets, _, template):
|
||||
read_wikipages()
|
||||
|
||||
for t in targets:
|
||||
stdout(t.wiki_output().encode('UTF-8') + b'\n')
|
||||
|
||||
def markdown_output(targets, substs, template_file):
|
||||
content = ""
|
||||
|
||||
for t in targets:
|
||||
content += t.markdown_output() + "\n"
|
||||
|
||||
print_template(template_file, substs, content)
|
||||
|
||||
def plaintext_output(targets, substs, template_file):
|
||||
|
||||
content = ""
|
||||
|
||||
for t in targets:
|
||||
content += t.plaintext_output() + "\n"
|
||||
|
||||
print_template(template_file, substs, content)
|
||||
|
||||
def completion_output(targets, substs, template_file):
|
||||
|
||||
content = ""
|
||||
|
||||
for t in targets:
|
||||
content += t.completion_output() + "\n"
|
||||
|
||||
print_template(template_file, substs, content)
|
||||
|
||||
def usage():
|
||||
print("Usage: %s [-V] [-c tag] [-g game] -n program_name -s package_name [ -z shortname ] ( -M | -m | -w | -p ) <dir>..." \
|
||||
% sys.argv[0])
|
||||
print(" -c : Provide documentation for the specified configuration file")
|
||||
print(" (matches the given tag name in the source file)")
|
||||
print(" -s : Package name, e.g. Chocolate Doom (for substitution)")
|
||||
print(" -z : Package short-name, e.g. Chocolate (for substitution)")
|
||||
print(" -v : Package version, e.g. 7.0 (for substitution)")
|
||||
print(" -n : Program name, e.g. chocolate (for substitution)")
|
||||
print(" -M : Markdown output")
|
||||
print(" -m : Manpage output")
|
||||
print(" -w : Wikitext output")
|
||||
print(" -p : Plaintext output")
|
||||
print(" -b : Bash-Completion output")
|
||||
print(" -V : Don't show Vanilla Doom options")
|
||||
print(" -g : Only document options for specified game.")
|
||||
sys.exit(0)
|
||||
|
||||
# Parse command line
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], "n:s:z:v:M:m:wp:b:c:g:V")
|
||||
|
||||
output_function = None
|
||||
template = None
|
||||
doc_config_file = None
|
||||
match_game = None
|
||||
substs = {}
|
||||
|
||||
for opt in opts:
|
||||
if opt[0] == "-n":
|
||||
substs["@PROGRAM_SPREFIX@"] = opt[1]
|
||||
if opt[0] == "-s":
|
||||
substs["@PACKAGE_NAME@"] = opt[1]
|
||||
if opt[0] == "-z":
|
||||
substs["@PACKAGE_SHORTNAME@"] = opt[1]
|
||||
if opt[0] == "-v":
|
||||
substs["@VERSION@"] = opt[1]
|
||||
if opt[0] == "-m":
|
||||
output_function = manpage_output
|
||||
template = opt[1]
|
||||
elif opt[0] == "-M":
|
||||
output_function = markdown_output
|
||||
template = opt[1]
|
||||
elif opt[0] == "-w":
|
||||
output_function = wiki_output
|
||||
elif opt[0] == "-p":
|
||||
output_function = plaintext_output
|
||||
template = opt[1]
|
||||
elif opt[0] == "-b":
|
||||
output_function = completion_output
|
||||
template = opt[1]
|
||||
elif opt[0] == "-V":
|
||||
show_vanilla_options = False
|
||||
elif opt[0] == "-c":
|
||||
doc_config_file = opt[1]
|
||||
elif opt[0] == "-g":
|
||||
match_game = opt[1]
|
||||
substs["@GAME@"] = opt[1]
|
||||
substs["@GAME_UPPER@"] = opt[1].title()
|
||||
if "doom" == opt[1]:
|
||||
substs["@CFGFILE@"] = "default.cfg"
|
||||
else:
|
||||
substs["@CFGFILE@"] = opt[1] + ".cfg"
|
||||
|
||||
if output_function == None or len(args) < 1:
|
||||
usage()
|
||||
else:
|
||||
# Process specified files
|
||||
|
||||
for path in args:
|
||||
process_files(path)
|
||||
|
||||
# Build a list of things to document
|
||||
if doc_config_file:
|
||||
documentation_targets = [config_files[doc_config_file]]
|
||||
else:
|
||||
documentation_targets = [c for _, c in categories]
|
||||
|
||||
# Generate the output
|
||||
output_function(documentation_targets, substs, template)
|
||||
|
||||
45
games/NXDoom/man/doom.template
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
.TH @PROGRAM_SPREFIX@\-doom 6 2018-01-09 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-doom \- historically compatible Doom engine
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-doom
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_SHORTNAME@ Doom is a port of Id Software's 1993 game
|
||||
.I Doom
|
||||
that is designed to behave as similarly to the original DOS version of
|
||||
Doom as is possible.
|
||||
@content
|
||||
.SH IWAD SEARCH PATHS
|
||||
@include iwad_paths.man
|
||||
.SH ENVIRONMENT
|
||||
This section describes environment variables that control
|
||||
@PACKAGE_SHORTNAME@ Doom's behavior.
|
||||
@include environ.man
|
||||
.SH FILES
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/default.cfg
|
||||
The main configuration file for @PACKAGE_NAME@.
|
||||
See \fBdefault.cfg\fR(5).
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-doom.cfg
|
||||
Extra configuration values that are specific to @PACKAGE_NAME@ and not
|
||||
present in Vanilla Doom.
|
||||
See \fB@PROGRAM_SPREFIX@\-doom.cfg\fR(5).
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-server\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-setup\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-heretic\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-hexen\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-strife\fR(6)
|
||||
.SH AUTHOR
|
||||
Chocolate Doom is written and maintained by Simon Howard.
|
||||
It is based on the LinuxDoom source code, released by Id Software.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co 2005-2016 Simon Howard.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
34
games/NXDoom/man/environ.man
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
.TP
|
||||
.I DOOMWADDIR
|
||||
.TQ
|
||||
.I DOOMWADPATH
|
||||
See section \(lqIWAD SEARCH PATHS\(rq above.
|
||||
.TP
|
||||
.I PCSOUND_DRIVER
|
||||
When running in PC speaker sound effect mode, this environment variable
|
||||
specifies a PC speaker driver to use for sound effect playback.
|
||||
Valid options are
|
||||
.RB \(lq Linux \(rq
|
||||
for the Linux console mode driver,
|
||||
.RB \(lq BSD \(rq
|
||||
for the NetBSD/OpenBSD PC speaker driver,
|
||||
and
|
||||
.RB \(lq SDL \(rq
|
||||
for SDL-based emulated PC speaker playback (using the digital output).
|
||||
.TP
|
||||
.I OPL_DRIVER
|
||||
When using OPL MIDI playback, this environment variable specifies an
|
||||
OPL backend driver to use.
|
||||
Valid options are
|
||||
.RB \(lq SDL \(rq
|
||||
for an SDL-based software emulated OPL chip,
|
||||
.RB \(lq Linux \(rq
|
||||
for the Linux hardware OPL driver,
|
||||
and
|
||||
.RB \(lq OpenBSD \(rq
|
||||
for the OpenBSD/NetBSD hardware OPL driver.
|
||||
.IP
|
||||
Generally speaking, a real hardware OPL chip sounds better than software
|
||||
emulation; however, modern machines do not often include one.
|
||||
If present, it may still require extra work to set up and elevated
|
||||
security privileges to access.
|
||||
28
games/NXDoom/man/extra.cfg.template
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.TH @PROGRAM_SPREFIX@\-@GAME@.cfg 5 2024-01-23 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-@GAME@.cfg \- @PACKAGE_SHORTNAME@ @GAME_UPPER@ configuration file
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR
|
||||
is a configuration file for \fB@PROGRAM_SPREFIX@\-@GAME@\fR(6). This file acts
|
||||
as an auxiliary configuration file; the main configuration options
|
||||
are stored in \fB@CFGFILE@\fR, which contains the same configuration
|
||||
options as Vanilla @GAME_UPPER@ (for compatibility). \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR
|
||||
contains configuration options that are specific to @PACKAGE_SHORTNAME@\-@GAME_UPPER@
|
||||
only.
|
||||
.PP
|
||||
\fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR is normally stored in the user's home directory,
|
||||
as \fI~/.local/share/@PROGRAM_SPREFIX@\-@GAME@/@PROGRAM_SPREFIX@\-@GAME@.cfg\fR. The path can be
|
||||
overridden using the \fBXDG_DATA_HOME\fR environment variable (see the XDG
|
||||
Base Directory Specification).
|
||||
.PP
|
||||
The \fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6) tool provides a simple to use front-end
|
||||
for editing \fI@PROGRAM_SPREFIX@\-@GAME@.cfg\fR.
|
||||
.SH FILE FORMAT
|
||||
.PP
|
||||
The file format is the same as that used for \fB@CFGFILE@\fR(5).
|
||||
@content
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6),
|
||||
\fB@CFGFILE@\fR(5),
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@\-setup\fR(6)
|
||||
47
games/NXDoom/man/heretic.template
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
.TH @PROGRAM_SPREFIX@\-heretic 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-heretic \- historically compatible Heretic engine
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-heretic
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_SHORTNAME@ Heretic is a port of Raven Software's 1994 game
|
||||
.I Heretic
|
||||
that aims to behave as similar to the original DOS version of Heretic as
|
||||
possible.
|
||||
@content
|
||||
.SH IWAD SEARCH PATHS
|
||||
@include iwad_paths.man
|
||||
.SH ENVIRONMENT
|
||||
This section describes environment variables that control
|
||||
@PACKAGE_SHORTNAME@ Heretic's behavior.
|
||||
@include environ.man
|
||||
.SH FILES
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/heretic.cfg
|
||||
The main configuration file for @PACKAGE_SHORTNAME@ Heretic.
|
||||
See \fBheretic.cfg\fR(5).
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-heretic.cfg
|
||||
Extra configuration values that are specific to @PACKAGE_SHORTNAME@ Heretic and not
|
||||
present in Vanilla Heretic.
|
||||
See \fB@PROGRAM_SPREFIX@\-heretic.cfg\fR(5).
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-doom\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-hexen\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-server\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-setup\fR(6)
|
||||
.SH AUTHOR
|
||||
Chocolate Heretic is part of the Chocolate Doom project, written and
|
||||
maintained by Simon Howard.
|
||||
It is based on the Heretic source code,
|
||||
released by Raven Software.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co Raven Software Inc.
|
||||
Copyright \(co 2005-2013 Simon Howard.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
47
games/NXDoom/man/hexen.template
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
.TH @PROGRAM_SPREFIX@\-hexen 6 2017-11-27 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-hexen \- historically compatible Hexen engine
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-hexen
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_SHORTNAME@ Hexen is a port of Raven Software's 1995 game
|
||||
.I Hexen
|
||||
that aims to behave as similar to the original DOS version of Hexen as
|
||||
possible.
|
||||
@content
|
||||
.SH IWAD SEARCH PATHS
|
||||
@include iwad_paths.man
|
||||
.SH ENVIRONMENT
|
||||
This section describes environment variables that control
|
||||
@PACKAGE_SHORTNAME@ Hexen's behavior.
|
||||
@include environ.man
|
||||
.SH FILES
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/hexen.cfg
|
||||
The main configuration file for @PACKAGE_SHORTNAME@ Hexen.
|
||||
See \fBhexen.cfg\fR(5).
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-hexen.cfg
|
||||
Extra configuration values that are specific to @PACKAGE_SHORTNAME@
|
||||
Hexen and not present in Vanilla Hexen.
|
||||
See \fB@PROGRAM_SPREFIX@\-hexen.cfg\fR(5).
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-doom\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-heretic\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-server\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-setup\fR(6)
|
||||
.SH AUTHOR
|
||||
Chocolate Hexen is part of the Chocolate Doom project, written and
|
||||
maintained by Simon Howard.
|
||||
It is based on the Hexen source code,
|
||||
released by Raven Software.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co Raven Software Inc.
|
||||
Copyright \(co 2005-2013 Simon Howard.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
73
games/NXDoom/man/iwad_paths.man
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
To play, an IWAD file is needed.
|
||||
This is a large file containing all of the levels, graphics,
|
||||
sound effects, music and other material that make up the game.
|
||||
IWAD files are named according to the game; the standard names are:
|
||||
.TP
|
||||
.IR doom.wad ,\~\c
|
||||
.IR doom1.wad ,\~\c
|
||||
.IR doom2.wad ,\~\c
|
||||
.IR tnt.wad ,\~\c
|
||||
.I plutonia.wad
|
||||
Doom, Doom II, Final Doom
|
||||
.TP
|
||||
.IR heretic.wad ,\~\c
|
||||
.IR hexen.wad ,\~\c
|
||||
.I strife.wad
|
||||
Heretic, Hexen and Strife (commercial Doom engine games).
|
||||
.TP
|
||||
.IR hacx.wad ,\~\c
|
||||
.I chex.wad
|
||||
Hacx and Chex Quest - more obscure games based on the Doom engine.
|
||||
.TP
|
||||
.IR freedm.wad ,\~\c
|
||||
.IR freedoom1.wad ,\~\c
|
||||
.I freedoom2.wad
|
||||
The Freedoom open content IWAD files.
|
||||
.LP
|
||||
The following directory paths are searched in order to find an IWAD:
|
||||
.TP
|
||||
Current working directory
|
||||
Any IWAD files found in the current working directory will be used in
|
||||
preference to IWADs found in any other directories.
|
||||
.TP
|
||||
.I DOOMWADDIR
|
||||
This environment variable can be set to contain a path to a single
|
||||
directory in which to look for IWAD files.
|
||||
This environment variable is supported by most Doom source ports.
|
||||
.TP
|
||||
.I DOOMWADPATH
|
||||
This environment variable, if set, can contain a colon-separated list of
|
||||
directories in which to look for IWAD files, or alternatively full paths to
|
||||
specific IWAD files.
|
||||
.TP
|
||||
.I $HOME/.local/share/games/doom
|
||||
Writeable directory in the user's home directory.
|
||||
The path can be overridden using the
|
||||
.I \%XDG_DATA_HOME
|
||||
environment variable (see the XDG Base Directory Specification).
|
||||
.TP
|
||||
.I /usr/local/share/doom
|
||||
.TQ
|
||||
.I /usr/local/share/games/doom
|
||||
.TQ
|
||||
.I /usr/share/doom
|
||||
.TQ
|
||||
.I /usr/share/games/doom
|
||||
System-wide locations that can be accessed by all users.
|
||||
The path
|
||||
.I /usr/share/games/doom
|
||||
is a standard path that is supported by most Doom source ports.
|
||||
These paths can be overridden using the
|
||||
.I \%XDG_DATA_DIRS
|
||||
environment variable (see the XDG Base Directory Specification).
|
||||
.LP
|
||||
The above can be overridden on a one-time basis by using the
|
||||
.B \-iwad
|
||||
command line parameter to provide the path to an IWAD file to use.This
|
||||
parameter can also be used to specify the name of a particular IWAD to use
|
||||
from one of the above paths.
|
||||
For example,
|
||||
.RB \(lq "\-iwad doom.wad" \(rq
|
||||
will search the above paths for the file
|
||||
.I doom.wad
|
||||
to use.
|
||||
55
games/NXDoom/man/server.template
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
.TH @PROGRAM_SPREFIX@\-server 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-server \- dedicated server for @PROGRAM_SPREFIX@\-doom
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-server
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_NAME@ is a modern Doom engine designed to behave
|
||||
as similarly to the original Doom game as is possible.
|
||||
.PP
|
||||
.I \%@PROGRAM_SPREFIX@\-server
|
||||
is a dedicated server for @PACKAGE_SHORTNAME@.
|
||||
It is equivalent to running
|
||||
\fB@PROGRAM_SPREFIX@-doom\fR(6)
|
||||
with the
|
||||
.B \%\-dedicated
|
||||
option.
|
||||
.PP
|
||||
Game options are not specified to the server, which merely acts to
|
||||
retransmit data between players in the game; parameters for the
|
||||
game should be specified by the first player to connect to the server,
|
||||
who is designated the controlling player.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-ignoreversion
|
||||
Ignore version mismatches between the server and the client.
|
||||
Using this option may cause game desyncs to occur,
|
||||
or differences in protocol may mean the netgame will simply not function
|
||||
at all.
|
||||
.TP
|
||||
.BI \-port\~ n
|
||||
Use UDP port
|
||||
.I n
|
||||
for communications instead of the default (2342).
|
||||
.TP
|
||||
.B \-privateserver
|
||||
Don't register with the global master server.
|
||||
.TP
|
||||
.BI \-servername\~ name
|
||||
Specify a name for the server.
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@-doom\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@-setup\fR(6)
|
||||
.SH AUTHOR
|
||||
Chocolate Doom is written and maintained by Simon Howard.
|
||||
.PP
|
||||
This manual was written by Jonathan Dowland.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co 2005-8 Simon Howard.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
46
games/NXDoom/man/setup.template
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
.TH @PROGRAM_SPREFIX@\-@GAME@-setup 6 2017-11-30 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-@GAME@-setup \- configuration tool for @PROGRAM_SPREFIX@\-@GAME@
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-@GAME@-setup
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_SHORTNAME@ @GAME_UPPER@ is a modern @GAME_UPPER@ engine
|
||||
designed to behave as similarly to the original @GAME_UPPER@ game as is
|
||||
possible.
|
||||
.PP
|
||||
.I @PROGRAM_SPREFIX@\-@GAME@-setup
|
||||
is a tool for configuring @PACKAGE_SHORTNAME@ @GAME_UPPER@.
|
||||
It provides a menu-based interface for the display, joystick, keyboard,
|
||||
mouse, sound and compatibility settings.
|
||||
.PP
|
||||
.I @PROGRAM_SPREFIX@\-@GAME@-setup
|
||||
can also be used to start and join network games.
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \-config\~ file
|
||||
Load configuration from the specified file,
|
||||
instead of
|
||||
.IR @CFGFILE@ .
|
||||
.TP
|
||||
.BI \-extraconfig\~ file
|
||||
Load extra configuration from the specified file,
|
||||
instead of
|
||||
.IR @PROGRAM_SPREFIX@\-@GAME@.cfg .
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@\fR(6),
|
||||
\fBdefault.cfg\fR(5),
|
||||
\fB@PROGRAM_SPREFIX@\-@GAME@.cfg\fR(5)
|
||||
.SH AUTHOR
|
||||
Chocolate Doom is written and maintained by Simon Howard.
|
||||
.PP
|
||||
This manual was written by Jonathan Dowland.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co 2005-8 Simon Howard.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
228
games/NXDoom/man/simplecpp
Executable file
|
|
@ -0,0 +1,228 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Contributors to the Freedoom project. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the freedoom project nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
#
|
||||
# simple cpp-style preprocessor
|
||||
#
|
||||
# Understands most features of the C preprocessor, including:
|
||||
# #if .. #elif .. #else .. #endif
|
||||
# - with expressions
|
||||
# #ifdef
|
||||
# #define
|
||||
# #include
|
||||
#
|
||||
|
||||
import collections
|
||||
import io
|
||||
import sys
|
||||
import re
|
||||
|
||||
debug = False
|
||||
defines = collections.defaultdict(lambda: False)
|
||||
|
||||
command_re = re.compile(r"\#(\w+)(\s+(.*))?")
|
||||
include_re = re.compile(r"\s*\"(.*)\"\s*")
|
||||
define_re = re.compile(r"\s*(\S+)\s*(.*?)\s*$")
|
||||
|
||||
def debug_msg(message):
|
||||
if debug:
|
||||
sys.stderr.write(message)
|
||||
|
||||
# Parse command line options
|
||||
|
||||
def parse_cmdline():
|
||||
for arg in sys.argv[1:]:
|
||||
if not arg.startswith("-D"):
|
||||
continue
|
||||
|
||||
name = arg[2:]
|
||||
if '=' in name:
|
||||
name, value = name.split('=', 1)
|
||||
else:
|
||||
value = True
|
||||
|
||||
defines[name] = value
|
||||
|
||||
def parse_stream(stream):
|
||||
result = read_block(stream, False)
|
||||
|
||||
if result is not None:
|
||||
raise Exception("Mismatched #if in '%s'" % stream.name)
|
||||
|
||||
def parse_file(filename):
|
||||
f = io.open(filename, encoding='UTF-8')
|
||||
|
||||
try:
|
||||
parse_stream(f)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
# Evaluate an expression using Python's eval() function.
|
||||
|
||||
def eval_expr(expr):
|
||||
expr = expr.replace("||", " or ") \
|
||||
.replace("&&", " and ") \
|
||||
.replace("!", "not ")
|
||||
|
||||
code = compile(expr, "", "eval")
|
||||
result = eval(code, {}, defines)
|
||||
return result
|
||||
|
||||
# #include
|
||||
|
||||
def cmd_include(arg):
|
||||
# Extract the filename
|
||||
|
||||
match = include_re.match(arg)
|
||||
|
||||
if not match:
|
||||
raise Exception("Invalid 'include' command")
|
||||
|
||||
filename = match.group(1)
|
||||
|
||||
# Open the file and process it
|
||||
|
||||
parse_file(filename)
|
||||
|
||||
# #define
|
||||
|
||||
def cmd_define(arg):
|
||||
match = define_re.match(arg)
|
||||
name = match.group(1)
|
||||
value = match.group(2)
|
||||
if value == '':
|
||||
value = True
|
||||
|
||||
defines[name] = value
|
||||
|
||||
# #undef
|
||||
|
||||
def cmd_undef(arg):
|
||||
if arg in defines:
|
||||
del defines[arg]
|
||||
|
||||
# #ifdef/#ifndef
|
||||
|
||||
def cmd_ifdef(arg, command, stream, ignore):
|
||||
|
||||
# Get the define name
|
||||
|
||||
debug_msg("%s %s >\n" % (command, arg))
|
||||
|
||||
# Should we ignore the contents of this block?
|
||||
|
||||
sub_ignore = not eval_expr(arg)
|
||||
|
||||
if "n" in command:
|
||||
sub_ignore = not sub_ignore
|
||||
|
||||
# Parse the block
|
||||
|
||||
result, newarg = read_block(stream, ignore or sub_ignore)
|
||||
|
||||
debug_msg("%s %s < (%s)\n" % (command, arg, result))
|
||||
|
||||
# There may be a second "else" block to parse:
|
||||
|
||||
if result == "else":
|
||||
debug_msg("%s %s else >\n" % (command, arg))
|
||||
result, arg = read_block(stream, ignore or (not sub_ignore))
|
||||
debug_msg("%s %s else < (%s)\n" % (command, arg, result))
|
||||
|
||||
if result == "elif":
|
||||
debug_msg("%s %s elif %s>\n" % (command, arg, newarg))
|
||||
cmd_ifdef(newarg, "if", stream, ignore or (not sub_ignore))
|
||||
result = "endif"
|
||||
|
||||
# Should end in an endif:
|
||||
|
||||
if result != "endif":
|
||||
raise Exception("'if' block did not end in an 'endif'")
|
||||
|
||||
commands = {
|
||||
"include" : cmd_include,
|
||||
"define" : cmd_define,
|
||||
"undef" : cmd_undef,
|
||||
"if" : cmd_ifdef,
|
||||
"ifdef" : cmd_ifdef,
|
||||
"ifn" : cmd_ifdef,
|
||||
"ifndef" : cmd_ifdef,
|
||||
}
|
||||
|
||||
# Recursive block reading function
|
||||
# if 'ignore' argument is 1, contents are ignored
|
||||
|
||||
def read_block(stream, ignore):
|
||||
|
||||
for line in stream:
|
||||
|
||||
# Remove newline
|
||||
|
||||
line = line[0:-1]
|
||||
|
||||
# Check if this line has a command
|
||||
|
||||
match = command_re.match(line)
|
||||
|
||||
if match:
|
||||
command = match.group(1)
|
||||
arg = match.group(3)
|
||||
|
||||
if command in ("else", "elif", "endif"):
|
||||
return (command, arg)
|
||||
elif command not in commands:
|
||||
raise Exception("Unknown command: '%s'" % \
|
||||
command)
|
||||
|
||||
# Get the callback function.
|
||||
|
||||
func = commands[command]
|
||||
|
||||
# Invoke the callback function. #ifdef commands
|
||||
# are a special case and need extra arguments.
|
||||
# Other commands are only executed if we are not
|
||||
# ignoring this block.
|
||||
|
||||
if func == cmd_ifdef:
|
||||
cmd_ifdef(arg, command=command,
|
||||
stream=stream,
|
||||
ignore=ignore)
|
||||
elif not ignore:
|
||||
func(arg)
|
||||
else:
|
||||
if not ignore:
|
||||
for key, value in defines.items():
|
||||
if isinstance(value, str):
|
||||
line = line.replace(key, value)
|
||||
print(line)
|
||||
|
||||
parse_cmdline()
|
||||
parse_stream(sys.stdin)
|
||||
|
||||
91
games/NXDoom/man/strife.template
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
.TH @PROGRAM_SPREFIX@\-strife 6 2018-01-15 "@PACKAGE_NAME@ @VERSION@"
|
||||
.SH NAME
|
||||
@PROGRAM_SPREFIX@\-strife \- historically compatible Strife engine
|
||||
.SH SYNOPSIS
|
||||
.B @PROGRAM_SPREFIX@\-strife
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@PACKAGE_SHORTNAME@ Strife is an accurate and complete recreation of
|
||||
Rogue Entertainment's
|
||||
.IR "Strife: Quest for the Sigil" .
|
||||
It was created through
|
||||
more than two years of reverse engineering effort with the blessings
|
||||
of the original programmers of the game;
|
||||
see section \(lqHISTORY\(rq below.
|
||||
@content
|
||||
.SH IWAD SEARCH PATHS
|
||||
@include iwad_paths.man
|
||||
.SH ENVIRONMENT
|
||||
This section describes environment variables that control
|
||||
@PACKAGE_SHORTNAME@ Strife's behavior.
|
||||
@include environ.man
|
||||
.SH FILES
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/strife.cfg
|
||||
The main configuration file for @PACKAGE_SHORTNAME@ Strife.
|
||||
See \fBstrife.cfg\fR(5).
|
||||
.TP
|
||||
.I $HOME/.local/share/@PROGRAM_SPREFIX@\-doom/@PROGRAM_SPREFIX@\-strife.cfg
|
||||
Extra configuration values that are specific to @PACKAGE_SHORTNAME@
|
||||
Strife and not present in Vanilla Strife.
|
||||
See \fB@PROGRAM_SPREFIX@\-strife.cfg\fR(5).
|
||||
.SH SEE ALSO
|
||||
\fB@PROGRAM_SPREFIX@\-doom\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-server\fR(6),
|
||||
\fB@PROGRAM_SPREFIX@\-setup\fR(6)
|
||||
.SH HISTORY
|
||||
The source code for Strife was lost, which means, unlike the code for
|
||||
all the other commercial games using the Doom engine, it cannot be
|
||||
released.
|
||||
The only access we have to the code is the binary executable file.
|
||||
Reverse engineering tools were employed to disassemble and decompile the
|
||||
executables, which were cross-referenced against the Linux Doom and
|
||||
DOS Heretic sources and painstakingly combed over multiple times,
|
||||
instruction by instruction, to ensure that the resulting
|
||||
Chocolate-Doom-based executable is as close as possible to the original.
|
||||
.SH LEGALITY
|
||||
Reverse engineering is a protected activity so long as the original code
|
||||
is not used directly in the product.
|
||||
Due to the vast amount of information lost through the process of
|
||||
compilation, and the need to refactor large portions of code in order to
|
||||
eliminate non-portable idioms or to adapt them properly to Chocolate
|
||||
Doom's framework, the resulting code behaves the same, but is not the
|
||||
.I same
|
||||
code.
|
||||
.PP
|
||||
In addition, James Monroe and John Carmack have both stated that they
|
||||
have no objections to the project.
|
||||
Because they are the original authors of the code, and neither Rogue nor
|
||||
their publisher, Velocity, Inc., exist any longer as legal entities,
|
||||
this is effectively legal permission.
|
||||
.SH BUGS
|
||||
@PACKAGE_SHORTNAME@ Strife is almost, but not entirely perfect, in
|
||||
recreating the behavior of Vanilla Strife.
|
||||
Help us by reporting any discrepancies you might notice between this
|
||||
executable and the vanilla DOS program.
|
||||
.PP
|
||||
However, do
|
||||
.I not
|
||||
report any glitch that you can replicate in the vanilla EXE as a bug.
|
||||
The point of @PACKAGE_SHORTNAME@ Strife, like Chocolate Doom before it,
|
||||
is to be as bug-compatible with the original game as possible.
|
||||
Also be aware that some glitches are impossible to compatibly recreate,
|
||||
and wherever this is the case, @PACKAGE_SHORTNAME@ Strife has erred on
|
||||
the side of not crashing the program, for example by initializing
|
||||
pointers to
|
||||
.I NULL
|
||||
rather than using them without setting a value first.
|
||||
.SH AUTHORS
|
||||
Chocolate Strife is part of the Chocolate Doom project.
|
||||
It was reverse engineered from the DOS versions of Strife by James Haley
|
||||
and Samuel Villarreal.
|
||||
Chocolate Doom was written and maintained by Simon Howard, and is based
|
||||
on the LinuxDoom source code released by Id Software.
|
||||
.SH COPYRIGHT
|
||||
Copyright \(co id Software Inc.
|
||||
Copyright \(co 2005-2013 Simon Howard, James Haley, Samuel Villarreal.
|
||||
.PP
|
||||
This is free software. You may redistribute copies of it under the terms of
|
||||
the GNU General Public License <http://www.gnu.org/licenses/gpl.html>.
|
||||
There is NO WARRANTY, to the extent permitted by law.
|
||||
7
games/NXDoom/man/wikipages
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# This is a list of wiki pages to automatically link to when generating
|
||||
# wikitext output.
|
||||
Dehacked
|
||||
Doom 1.91
|
||||
Merging
|
||||
Multiplayer
|
||||
Three screen mode
|
||||
7
games/NXDoom/opl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
libopl.a
|
||||
*.rc
|
||||
tags
|
||||
TAGS
|
||||
28
games/NXDoom/opl/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
add_library(opl STATIC
|
||||
opl_internal.h
|
||||
opl.c opl.h
|
||||
opl_linux.c
|
||||
opl_obsd.c
|
||||
opl_queue.c opl_queue.h
|
||||
opl_sdl.c
|
||||
opl_timer.c opl_timer.h
|
||||
opl_win32.c
|
||||
ioperm_sys.c ioperm_sys.h
|
||||
opl3.c opl3.h)
|
||||
target_include_directories(opl
|
||||
INTERFACE "."
|
||||
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../")
|
||||
if (DEFINED EMSCRIPTEN)
|
||||
if(ENABLE_SDL2_MIXER)
|
||||
set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2")
|
||||
set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2")
|
||||
else()
|
||||
set_target_properties(opl PROPERTIES COMPILE_FLAGS "-s USE_SDL=2")
|
||||
set_target_properties(opl PROPERTIES LINK_FLAGS "-s USE_SDL=2")
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(opl SDL2::SDL2)
|
||||
if(ENABLE_SDL2_MIXER)
|
||||
target_link_libraries(opl SDL2_mixer::SDL2_mixer)
|
||||
endif()
|
||||
endif()
|
||||
21
games/NXDoom/opl/Makefile.am
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
AM_CFLAGS=@SDLMIXER_CFLAGS@
|
||||
|
||||
EXTRA_DIST=CMakeLists.txt
|
||||
|
||||
SUBDIRS = . examples
|
||||
|
||||
noinst_LIBRARIES=libopl.a
|
||||
|
||||
libopl_a_SOURCES = \
|
||||
opl_internal.h \
|
||||
opl.c opl.h \
|
||||
opl_linux.c \
|
||||
opl_obsd.c \
|
||||
opl_queue.c opl_queue.h \
|
||||
opl_sdl.c \
|
||||
opl_timer.c opl_timer.h \
|
||||
opl_win32.c \
|
||||
ioperm_sys.c ioperm_sys.h \
|
||||
opl3.c opl3.h
|
||||
|
||||
7
games/NXDoom/opl/examples/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
droplay
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
8
games/NXDoom/opl/examples/Makefile.am
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
AM_CFLAGS = -I$(top_srcdir)/opl
|
||||
|
||||
noinst_PROGRAMS=droplay
|
||||
|
||||
droplay_LDADD = ../libopl.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@
|
||||
droplay_SOURCES = droplay.c
|
||||
|
||||
210
games/NXDoom/opl/examples/droplay.c
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
//
|
||||
// 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:
|
||||
// Demonstration program for OPL library to play back DRO
|
||||
// format files.
|
||||
//
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#include "opl.h"
|
||||
|
||||
#define HEADER_STRING "DBRAWOPL"
|
||||
#define ADLIB_PORT 0x388
|
||||
|
||||
void WriteReg(unsigned int reg, unsigned int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
// This was recorded from an OPL2, but we are probably playing
|
||||
// back on an OPL3, so we need to enable the original OPL2
|
||||
// channels. Doom does this already, but other games don't.
|
||||
|
||||
if ((reg & 0xf0) == OPL_REGS_FEEDBACK)
|
||||
{
|
||||
val |= 0x30;
|
||||
}
|
||||
|
||||
OPL_WritePort(OPL_REGISTER_PORT, reg);
|
||||
|
||||
for (i=0; i<6; ++i)
|
||||
{
|
||||
OPL_ReadPort(OPL_REGISTER_PORT);
|
||||
}
|
||||
|
||||
OPL_WritePort(OPL_DATA_PORT, val);
|
||||
|
||||
for (i=0; i<35; ++i)
|
||||
{
|
||||
OPL_ReadPort(OPL_REGISTER_PORT);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearAllRegs(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<=0xff; ++i)
|
||||
{
|
||||
WriteReg(i, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void Init(void)
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_TIMER) < 0)
|
||||
{
|
||||
fprintf(stderr, "Unable to initialise SDL timer\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!OPL_Init(ADLIB_PORT))
|
||||
{
|
||||
fprintf(stderr, "Unable to initialise OPL layer\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
OPL_Shutdown();
|
||||
}
|
||||
|
||||
struct timer_data
|
||||
{
|
||||
int running;
|
||||
FILE *fstream;
|
||||
};
|
||||
|
||||
void TimerCallback(void *data)
|
||||
{
|
||||
struct timer_data *timer_data = data;
|
||||
int delay;
|
||||
|
||||
if (!timer_data->running)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Read data until we must make a delay.
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int reg, val;
|
||||
|
||||
// End of file?
|
||||
|
||||
if (feof(timer_data->fstream))
|
||||
{
|
||||
timer_data->running = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
reg = fgetc(timer_data->fstream);
|
||||
val = fgetc(timer_data->fstream);
|
||||
|
||||
// Register value of 0 or 1 indicates a delay.
|
||||
|
||||
if (reg == 0x00)
|
||||
{
|
||||
delay = val;
|
||||
break;
|
||||
}
|
||||
else if (reg == 0x01)
|
||||
{
|
||||
val |= (fgetc(timer_data->fstream) << 8);
|
||||
delay = val;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteReg(reg, val);
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule the next timer callback.
|
||||
|
||||
OPL_SetCallback(delay * OPL_MS, TimerCallback, timer_data);
|
||||
}
|
||||
|
||||
void PlayFile(char *filename)
|
||||
{
|
||||
struct timer_data timer_data;
|
||||
int running;
|
||||
char buf[8];
|
||||
|
||||
timer_data.fstream = fopen(filename, "rb");
|
||||
|
||||
if (timer_data.fstream == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to open %s\n", filename);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (fread(buf, 1, 8, timer_data.fstream) < 8)
|
||||
{
|
||||
fprintf(stderr, "failed to read raw OPL header\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncmp(buf, HEADER_STRING, 8) != 0)
|
||||
{
|
||||
fprintf(stderr, "Raw OPL header not found\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fseek(timer_data.fstream, 28, SEEK_SET);
|
||||
timer_data.running = 1;
|
||||
|
||||
// Start callback loop sequence.
|
||||
|
||||
OPL_SetCallback(0, TimerCallback, &timer_data);
|
||||
|
||||
// Sleep until the playback finishes.
|
||||
|
||||
do
|
||||
{
|
||||
OPL_Lock();
|
||||
running = timer_data.running;
|
||||
OPL_Unlock();
|
||||
|
||||
SDL_Delay(100 * OPL_MS);
|
||||
} while (running);
|
||||
|
||||
fclose(timer_data.fstream);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <filename>\n", argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
Init();
|
||||
|
||||
PlayFile(argv[1]);
|
||||
|
||||
ClearAllRegs();
|
||||
Shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
355
games/NXDoom/opl/ioperm_sys.c
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
//
|
||||
// Copyright(C) 2002, 2003 Marcel Telka
|
||||
// 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:
|
||||
// Interface to the ioperm.sys driver, based on code from the
|
||||
// Cygwin ioperm library.
|
||||
//
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "ioperm_sys.h"
|
||||
|
||||
#define IOPERM_FILE L"\\\\.\\ioperm"
|
||||
|
||||
#define IOCTL_IOPERM \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0xA00, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
struct ioperm_data
|
||||
{
|
||||
unsigned long from;
|
||||
unsigned long num;
|
||||
int turn_on;
|
||||
};
|
||||
|
||||
// Function pointers for advapi32.dll. This DLL does not exist on
|
||||
// Windows 9x, so they are dynamically loaded from the DLL at runtime.
|
||||
|
||||
// haleyjd 09/09/10: Moved calling conventions into ()'s
|
||||
|
||||
static SC_HANDLE (WINAPI *MyOpenSCManagerW)(wchar_t *lpMachineName,
|
||||
wchar_t *lpDatabaseName,
|
||||
DWORD dwDesiredAccess) = NULL;
|
||||
static SC_HANDLE (WINAPI *MyCreateServiceW)(SC_HANDLE hSCManager,
|
||||
wchar_t *lpServiceName,
|
||||
wchar_t *lpDisplayName,
|
||||
DWORD dwDesiredAccess,
|
||||
DWORD dwServiceType,
|
||||
DWORD dwStartType,
|
||||
DWORD dwErrorControl,
|
||||
wchar_t *lpBinaryPathName,
|
||||
wchar_t *lpLoadOrderGroup,
|
||||
LPDWORD lpdwTagId,
|
||||
wchar_t *lpDependencies,
|
||||
wchar_t *lpServiceStartName,
|
||||
wchar_t *lpPassword);
|
||||
static SC_HANDLE (WINAPI *MyOpenServiceW)(SC_HANDLE hSCManager,
|
||||
wchar_t *lpServiceName,
|
||||
DWORD dwDesiredAccess);
|
||||
static BOOL (WINAPI *MyStartServiceW)(SC_HANDLE hService,
|
||||
DWORD dwNumServiceArgs,
|
||||
wchar_t **lpServiceArgVectors);
|
||||
static BOOL (WINAPI *MyControlService)(SC_HANDLE hService,
|
||||
DWORD dwControl,
|
||||
LPSERVICE_STATUS lpServiceStatus);
|
||||
static BOOL (WINAPI *MyCloseServiceHandle)(SC_HANDLE hSCObject);
|
||||
static BOOL (WINAPI *MyDeleteService)(SC_HANDLE hService);
|
||||
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
void **fn;
|
||||
} dll_functions[] = {
|
||||
{ "OpenSCManagerW", (void **) &MyOpenSCManagerW },
|
||||
{ "CreateServiceW", (void **) &MyCreateServiceW },
|
||||
{ "OpenServiceW", (void **) &MyOpenServiceW },
|
||||
{ "StartServiceW", (void **) &MyStartServiceW },
|
||||
{ "ControlService", (void **) &MyControlService },
|
||||
{ "CloseServiceHandle", (void **) &MyCloseServiceHandle },
|
||||
{ "DeleteService", (void **) &MyDeleteService },
|
||||
};
|
||||
|
||||
// Globals
|
||||
|
||||
static SC_HANDLE scm = NULL;
|
||||
static SC_HANDLE svc = NULL;
|
||||
static int service_was_created = 0;
|
||||
static int service_was_started = 0;
|
||||
|
||||
static int LoadLibraryPointers(void)
|
||||
{
|
||||
HMODULE dll;
|
||||
int i;
|
||||
|
||||
// Already loaded?
|
||||
|
||||
if (MyOpenSCManagerW != NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
dll = LoadLibraryW(L"advapi32.dll");
|
||||
|
||||
if (dll == NULL)
|
||||
{
|
||||
fprintf(stderr, "LoadLibraryPointers: Failed to open advapi32.dll\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(dll_functions) / sizeof(*dll_functions); ++i)
|
||||
{
|
||||
*dll_functions[i].fn = GetProcAddress(dll, dll_functions[i].name);
|
||||
|
||||
if (*dll_functions[i].fn == NULL)
|
||||
{
|
||||
fprintf(stderr, "LoadLibraryPointers: Failed to get address "
|
||||
"for '%s'\n", dll_functions[i].name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on)
|
||||
{
|
||||
HANDLE h;
|
||||
struct ioperm_data ioperm_data;
|
||||
DWORD BytesReturned;
|
||||
BOOL r;
|
||||
|
||||
h = CreateFileW(IOPERM_FILE, GENERIC_READ, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
errno = ENODEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ioperm_data.from = from;
|
||||
ioperm_data.num = num;
|
||||
ioperm_data.turn_on = turn_on;
|
||||
|
||||
r = DeviceIoControl(h, IOCTL_IOPERM,
|
||||
&ioperm_data, sizeof ioperm_data,
|
||||
NULL, 0,
|
||||
&BytesReturned, NULL);
|
||||
|
||||
if (!r)
|
||||
{
|
||||
errno = EPERM;
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return r != 0;
|
||||
}
|
||||
|
||||
// Load ioperm.sys driver.
|
||||
// Returns 1 for success, 0 for failure.
|
||||
// Remember to call IOperm_UninstallDriver to uninstall the driver later.
|
||||
|
||||
int IOperm_InstallDriver(void)
|
||||
{
|
||||
wchar_t driver_path[MAX_PATH];
|
||||
int error;
|
||||
int result = 1;
|
||||
|
||||
if (!LoadLibraryPointers())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
scm = MyOpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
|
||||
if (scm == NULL)
|
||||
{
|
||||
error = GetLastError();
|
||||
fprintf(stderr, "IOperm_InstallDriver: OpenSCManager failed (%i).\n",
|
||||
error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the full path to the driver file.
|
||||
|
||||
GetFullPathNameW(L"ioperm.sys", MAX_PATH, driver_path, NULL);
|
||||
|
||||
// Create the service.
|
||||
|
||||
svc = MyCreateServiceW(scm,
|
||||
L"ioperm",
|
||||
L"ioperm support for Cygwin driver",
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_KERNEL_DRIVER,
|
||||
SERVICE_AUTO_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
driver_path,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (svc == NULL)
|
||||
{
|
||||
error = GetLastError();
|
||||
|
||||
if (error != ERROR_SERVICE_EXISTS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"IOperm_InstallDriver: Failed to create service (%i).\n",
|
||||
error);
|
||||
}
|
||||
else
|
||||
{
|
||||
svc = MyOpenServiceW(scm, L"ioperm", SERVICE_ALL_ACCESS);
|
||||
|
||||
if (svc == NULL)
|
||||
{
|
||||
error = GetLastError();
|
||||
|
||||
fprintf(stderr,
|
||||
"IOperm_InstallDriver: Failed to open service (%i).\n",
|
||||
error);
|
||||
}
|
||||
}
|
||||
|
||||
if (svc == NULL)
|
||||
{
|
||||
MyCloseServiceHandle(scm);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
service_was_created = 1;
|
||||
}
|
||||
|
||||
// Start the service. If the service already existed, it might have
|
||||
// already been running as well.
|
||||
|
||||
if (!MyStartServiceW(svc, 0, NULL))
|
||||
{
|
||||
error = GetLastError();
|
||||
|
||||
if (error != ERROR_SERVICE_ALREADY_RUNNING)
|
||||
{
|
||||
fprintf(stderr, "IOperm_InstallDriver: Failed to start service (%i).\n",
|
||||
error);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("IOperm_InstallDriver: ioperm driver already running.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("IOperm_InstallDriver: ioperm driver installed.\n");
|
||||
service_was_started = 1;
|
||||
}
|
||||
|
||||
// If we failed to start the driver running, we need to clean up
|
||||
// before finishing.
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
IOperm_UninstallDriver();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int IOperm_UninstallDriver(void)
|
||||
{
|
||||
SERVICE_STATUS stat;
|
||||
int result = 1;
|
||||
int error;
|
||||
|
||||
// If we started the service, stop it.
|
||||
|
||||
if (service_was_started)
|
||||
{
|
||||
if (!MyControlService(svc, SERVICE_CONTROL_STOP, &stat))
|
||||
{
|
||||
error = GetLastError();
|
||||
|
||||
if (error == ERROR_SERVICE_NOT_ACTIVE)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"IOperm_UninstallDriver: Service not active? (%i)\n",
|
||||
error);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr,
|
||||
"IOperm_UninstallDriver: Failed to stop service (%i).\n",
|
||||
error);
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we created the service, delete it.
|
||||
|
||||
if (service_was_created)
|
||||
{
|
||||
if (!MyDeleteService(svc))
|
||||
{
|
||||
error = GetLastError();
|
||||
|
||||
fprintf(stderr,
|
||||
"IOperm_UninstallDriver: DeleteService failed (%i).\n",
|
||||
error);
|
||||
|
||||
result = 0;
|
||||
}
|
||||
else if (service_was_started)
|
||||
{
|
||||
printf("IOperm_UnInstallDriver: ioperm driver uninstalled.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Close handles.
|
||||
|
||||
if (svc != NULL)
|
||||
{
|
||||
MyCloseServiceHandle(svc);
|
||||
svc = NULL;
|
||||
}
|
||||
|
||||
if (scm != NULL)
|
||||
{
|
||||
MyCloseServiceHandle(scm);
|
||||
scm = NULL;
|
||||
}
|
||||
|
||||
service_was_created = 0;
|
||||
service_was_started = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* #ifndef _WIN32 */
|
||||
|
||||
28
games/NXDoom/opl/ioperm_sys.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Copyright(C) 2002, 2003 Marcel Telka
|
||||
// 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:
|
||||
// Interface to the ioperm.sys driver, based on code from the
|
||||
// Cygwin ioperm library.
|
||||
//
|
||||
|
||||
#ifndef IOPERM_SYS_H
|
||||
#define IOPERM_SYS_H
|
||||
|
||||
int IOperm_EnablePortRange(unsigned int from, unsigned int num, int turn_on);
|
||||
int IOperm_InstallDriver(void);
|
||||
int IOperm_UninstallDriver(void);
|
||||
|
||||
#endif /* #ifndef IOPERM_SYS_H */
|
||||
|
||||
530
games/NXDoom/opl/opl.c
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL interface.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
|
||||
//#define OPL_DEBUG_TRACE
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
|
||||
static opl_driver_t *drivers[] =
|
||||
{
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
|
||||
&opl_linux_driver,
|
||||
#endif
|
||||
#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64)
|
||||
&opl_openbsd_driver,
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
&opl_win32_driver,
|
||||
#endif
|
||||
#ifndef DISABLE_SDL2MIXER
|
||||
&opl_sdl_driver,
|
||||
#endif // DISABLE_SDL2MIXER
|
||||
NULL
|
||||
};
|
||||
|
||||
static opl_driver_t *driver = NULL;
|
||||
static int init_stage_reg_writes = 1;
|
||||
|
||||
unsigned int opl_sample_rate = 22050;
|
||||
|
||||
//
|
||||
// Init/shutdown code.
|
||||
//
|
||||
|
||||
// Initialize the specified driver and detect an OPL chip. Returns
|
||||
// true if an OPL is detected.
|
||||
|
||||
static opl_init_result_t InitDriver(opl_driver_t *_driver,
|
||||
unsigned int port_base)
|
||||
{
|
||||
opl_init_result_t result1, result2;
|
||||
|
||||
// Initialize the driver.
|
||||
|
||||
if (!_driver->init_func(port_base))
|
||||
{
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
|
||||
// The driver was initialized okay, so we now have somewhere
|
||||
// to write to. It doesn't mean there's an OPL chip there,
|
||||
// though. Perform the detection sequence to make sure.
|
||||
// (it's done twice, like how Doom does it).
|
||||
|
||||
driver = _driver;
|
||||
init_stage_reg_writes = 1;
|
||||
|
||||
result1 = OPL_Detect();
|
||||
result2 = OPL_Detect();
|
||||
if (result1 == OPL_INIT_NONE || result2 == OPL_INIT_NONE)
|
||||
{
|
||||
printf("OPL_Init: No OPL detected using '%s' driver.\n", _driver->name);
|
||||
_driver->shutdown_func();
|
||||
driver = NULL;
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
|
||||
init_stage_reg_writes = 0;
|
||||
|
||||
printf("OPL_Init: Using driver '%s'.\n", driver->name);
|
||||
|
||||
return result2;
|
||||
}
|
||||
|
||||
// Find a driver automatically by trying each in the list.
|
||||
|
||||
static opl_init_result_t AutoSelectDriver(unsigned int port_base)
|
||||
{
|
||||
int i;
|
||||
opl_init_result_t result;
|
||||
|
||||
for (i = 0; drivers[i] != NULL; ++i)
|
||||
{
|
||||
result = InitDriver(drivers[i], port_base);
|
||||
if (result != OPL_INIT_NONE)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
printf("OPL_Init: Failed to find a working driver.\n");
|
||||
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
|
||||
// Initialize the OPL library. Return value indicates type of OPL chip
|
||||
// detected, if any.
|
||||
|
||||
opl_init_result_t OPL_Init(unsigned int port_base)
|
||||
{
|
||||
char *driver_name;
|
||||
int i;
|
||||
int result;
|
||||
|
||||
driver_name = getenv("OPL_DRIVER");
|
||||
|
||||
if (driver_name != NULL)
|
||||
{
|
||||
// Search the list until we find the driver with this name.
|
||||
|
||||
for (i=0; drivers[i] != NULL; ++i)
|
||||
{
|
||||
if (!strcmp(driver_name, drivers[i]->name))
|
||||
{
|
||||
result = InitDriver(drivers[i], port_base);
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OPL_Init: Failed to initialize "
|
||||
"driver: '%s'.\n", driver_name);
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("OPL_Init: unknown driver: '%s'.\n", driver_name);
|
||||
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AutoSelectDriver(port_base);
|
||||
}
|
||||
}
|
||||
|
||||
// Shut down the OPL library.
|
||||
|
||||
void OPL_Shutdown(void)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->shutdown_func();
|
||||
driver = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the sample rate used for software OPL emulation.
|
||||
|
||||
void OPL_SetSampleRate(unsigned int rate)
|
||||
{
|
||||
opl_sample_rate = rate;
|
||||
}
|
||||
|
||||
void OPL_WritePort(opl_port_t port, unsigned int value)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
#ifdef OPL_DEBUG_TRACE
|
||||
printf("OPL_write: %i, %x\n", port, value);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
driver->write_port_func(port, value);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int OPL_ReadPort(opl_port_t port)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
unsigned int result;
|
||||
|
||||
#ifdef OPL_DEBUG_TRACE
|
||||
printf("OPL_read: %i...\n", port);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
result = driver->read_port_func(port);
|
||||
|
||||
#ifdef OPL_DEBUG_TRACE
|
||||
printf("OPL_read: %i -> %x\n", port, result);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Higher-level functions, based on the lower-level functions above
|
||||
// (register write, etc).
|
||||
//
|
||||
|
||||
unsigned int OPL_ReadStatus(void)
|
||||
{
|
||||
return OPL_ReadPort(OPL_REGISTER_PORT);
|
||||
}
|
||||
|
||||
// Write an OPL register value
|
||||
|
||||
void OPL_WriteRegister(int reg, int value)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (reg & 0x100)
|
||||
{
|
||||
OPL_WritePort(OPL_REGISTER_PORT_OPL3, reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPL_WritePort(OPL_REGISTER_PORT, reg);
|
||||
}
|
||||
|
||||
// For timing, read the register port six times after writing the
|
||||
// register number to cause the appropriate delay
|
||||
|
||||
for (i=0; i<6; ++i)
|
||||
{
|
||||
// An oddity of the Doom OPL code: at startup initialization,
|
||||
// the spacing here is performed by reading from the register
|
||||
// port; after initialization, the data port is read, instead.
|
||||
|
||||
if (init_stage_reg_writes)
|
||||
{
|
||||
OPL_ReadPort(OPL_REGISTER_PORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPL_ReadPort(OPL_DATA_PORT);
|
||||
}
|
||||
}
|
||||
|
||||
OPL_WritePort(OPL_DATA_PORT, value);
|
||||
|
||||
// Read the register port 24 times after writing the value to
|
||||
// cause the appropriate delay
|
||||
|
||||
for (i=0; i<24; ++i)
|
||||
{
|
||||
OPL_ReadStatus();
|
||||
}
|
||||
}
|
||||
|
||||
// Detect the presence of an OPL chip
|
||||
|
||||
opl_init_result_t OPL_Detect(void)
|
||||
{
|
||||
int result1, result2;
|
||||
int i;
|
||||
|
||||
// Reset both timers:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);
|
||||
|
||||
// Enable interrupts:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);
|
||||
|
||||
// Read status
|
||||
result1 = OPL_ReadStatus();
|
||||
|
||||
// Set timer:
|
||||
OPL_WriteRegister(OPL_REG_TIMER1, 0xff);
|
||||
|
||||
// Start timer 1:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x21);
|
||||
|
||||
// Wait for 80 microseconds
|
||||
// This is how Doom does it:
|
||||
|
||||
for (i=0; i<200; ++i)
|
||||
{
|
||||
OPL_ReadStatus();
|
||||
}
|
||||
|
||||
OPL_Delay(1 * OPL_MS);
|
||||
|
||||
// Read status
|
||||
result2 = OPL_ReadStatus();
|
||||
|
||||
// Reset both timers:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);
|
||||
|
||||
// Enable interrupts:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);
|
||||
|
||||
if ((result1 & 0xe0) == 0x00 && (result2 & 0xe0) == 0xc0)
|
||||
{
|
||||
result1 = OPL_ReadPort(OPL_REGISTER_PORT);
|
||||
result2 = OPL_ReadPort(OPL_REGISTER_PORT_OPL3);
|
||||
if (result1 == 0x00)
|
||||
{
|
||||
return OPL_INIT_OPL3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPL_INIT_OPL2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPL_INIT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize registers on startup
|
||||
|
||||
void OPL_InitRegisters(int opl3)
|
||||
{
|
||||
int r;
|
||||
|
||||
// Initialize level registers
|
||||
|
||||
for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r, 0x3f);
|
||||
}
|
||||
|
||||
// Initialize other registers
|
||||
// These two loops write to registers that actually don't exist,
|
||||
// but this is what Doom does ...
|
||||
// Similarly, the <= is also intenational.
|
||||
|
||||
for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r, 0x00);
|
||||
}
|
||||
|
||||
// More registers ...
|
||||
|
||||
for (r=1; r < OPL_REGS_LEVEL; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r, 0x00);
|
||||
}
|
||||
|
||||
// Re-initialize the low registers:
|
||||
|
||||
// Reset both timers and enable interrupts:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);
|
||||
|
||||
// "Allow FM chips to control the waveform of each operator":
|
||||
OPL_WriteRegister(OPL_REG_WAVEFORM_ENABLE, 0x20);
|
||||
|
||||
if (opl3)
|
||||
{
|
||||
OPL_WriteRegister(OPL_REG_NEW, 0x01);
|
||||
|
||||
// Initialize level registers
|
||||
|
||||
for (r=OPL_REGS_LEVEL; r <= OPL_REGS_LEVEL + OPL_NUM_OPERATORS; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r | 0x100, 0x3f);
|
||||
}
|
||||
|
||||
// Initialize other registers
|
||||
// These two loops write to registers that actually don't exist,
|
||||
// but this is what Doom does ...
|
||||
// Similarly, the <= is also intenational.
|
||||
|
||||
for (r=OPL_REGS_ATTACK; r <= OPL_REGS_WAVEFORM + OPL_NUM_OPERATORS; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r | 0x100, 0x00);
|
||||
}
|
||||
|
||||
// More registers ...
|
||||
|
||||
for (r=1; r < OPL_REGS_LEVEL; ++r)
|
||||
{
|
||||
OPL_WriteRegister(r | 0x100, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard split point on (?)
|
||||
OPL_WriteRegister(OPL_REG_FM_MODE, 0x40);
|
||||
|
||||
if (opl3)
|
||||
{
|
||||
OPL_WriteRegister(OPL_REG_NEW, 0x01);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Timer functions.
|
||||
//
|
||||
|
||||
void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->set_callback_func(us, callback, data);
|
||||
}
|
||||
}
|
||||
|
||||
void OPL_ClearCallbacks(void)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->clear_callbacks_func();
|
||||
}
|
||||
}
|
||||
|
||||
void OPL_Lock(void)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->lock_func();
|
||||
}
|
||||
}
|
||||
|
||||
void OPL_Unlock(void)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->unlock_func();
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int finished;
|
||||
|
||||
SDL_mutex *mutex;
|
||||
SDL_cond *cond;
|
||||
} delay_data_t;
|
||||
|
||||
static void DelayCallback(void *_delay_data)
|
||||
{
|
||||
delay_data_t *delay_data = _delay_data;
|
||||
|
||||
SDL_LockMutex(delay_data->mutex);
|
||||
delay_data->finished = 1;
|
||||
|
||||
SDL_CondSignal(delay_data->cond);
|
||||
|
||||
SDL_UnlockMutex(delay_data->mutex);
|
||||
}
|
||||
|
||||
// Delay for specified number of microseconds after OPL subsystem is initialized
|
||||
|
||||
void OPL_Delay(uint64_t us)
|
||||
{
|
||||
delay_data_t delay_data;
|
||||
|
||||
if (driver == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a callback that will signal this thread after the
|
||||
// specified time.
|
||||
|
||||
// Note that this is not just a simple time-based delay, it will ensure
|
||||
// that the OPL system is initialized and the queue has begun processing
|
||||
// before releasing the mutex lock
|
||||
|
||||
delay_data.finished = 0;
|
||||
delay_data.mutex = SDL_CreateMutex();
|
||||
delay_data.cond = SDL_CreateCond();
|
||||
|
||||
OPL_SetCallback(us, DelayCallback, &delay_data);
|
||||
|
||||
// Wait until the callback is invoked.
|
||||
|
||||
SDL_LockMutex(delay_data.mutex);
|
||||
|
||||
while (!delay_data.finished)
|
||||
{
|
||||
SDL_CondWait(delay_data.cond, delay_data.mutex);
|
||||
#ifdef EMSCRIPTEN
|
||||
// Use async sleep to avoid locking browser main thread
|
||||
emscripten_sleep(us / 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(delay_data.mutex);
|
||||
|
||||
// Clean up.
|
||||
|
||||
SDL_DestroyMutex(delay_data.mutex);
|
||||
SDL_DestroyCond(delay_data.cond);
|
||||
}
|
||||
|
||||
void OPL_SetPaused(int paused)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->set_paused_func(paused);
|
||||
}
|
||||
}
|
||||
|
||||
void OPL_AdjustCallbacks(float value)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->adjust_callbacks_func(value);
|
||||
}
|
||||
}
|
||||
|
||||
153
games/NXDoom/opl/opl.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL interface.
|
||||
//
|
||||
|
||||
|
||||
#ifndef OPL_OPL_H
|
||||
#define OPL_OPL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef void (*opl_callback_t)(void *data);
|
||||
|
||||
// Result from OPL_Init(), indicating what type of OPL chip was detected,
|
||||
// if any.
|
||||
typedef enum
|
||||
{
|
||||
OPL_INIT_NONE,
|
||||
OPL_INIT_OPL2,
|
||||
OPL_INIT_OPL3,
|
||||
} opl_init_result_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OPL_REGISTER_PORT = 0,
|
||||
OPL_DATA_PORT = 1,
|
||||
OPL_REGISTER_PORT_OPL3 = 2
|
||||
} opl_port_t;
|
||||
|
||||
#define OPL_NUM_OPERATORS 21
|
||||
#define OPL_NUM_VOICES 9
|
||||
|
||||
#define OPL_REG_WAVEFORM_ENABLE 0x01
|
||||
#define OPL_REG_TIMER1 0x02
|
||||
#define OPL_REG_TIMER2 0x03
|
||||
#define OPL_REG_TIMER_CTRL 0x04
|
||||
#define OPL_REG_FM_MODE 0x08
|
||||
#define OPL_REG_NEW 0x105
|
||||
|
||||
// Operator registers (21 of each):
|
||||
|
||||
#define OPL_REGS_TREMOLO 0x20
|
||||
#define OPL_REGS_LEVEL 0x40
|
||||
#define OPL_REGS_ATTACK 0x60
|
||||
#define OPL_REGS_SUSTAIN 0x80
|
||||
#define OPL_REGS_WAVEFORM 0xE0
|
||||
|
||||
// Voice registers (9 of each):
|
||||
|
||||
#define OPL_REGS_FREQ_1 0xA0
|
||||
#define OPL_REGS_FREQ_2 0xB0
|
||||
#define OPL_REGS_FEEDBACK 0xC0
|
||||
|
||||
// Times
|
||||
|
||||
#define OPL_SECOND ((uint64_t) 1000 * 1000)
|
||||
#define OPL_MS ((uint64_t) 1000)
|
||||
#define OPL_US ((uint64_t) 1)
|
||||
|
||||
//
|
||||
// Low-level functions.
|
||||
//
|
||||
|
||||
// Initialize the OPL subsystem.
|
||||
|
||||
opl_init_result_t OPL_Init(unsigned int port_base);
|
||||
|
||||
// Shut down the OPL subsystem.
|
||||
|
||||
void OPL_Shutdown(void);
|
||||
|
||||
// Set the sample rate used for software emulation.
|
||||
|
||||
void OPL_SetSampleRate(unsigned int rate);
|
||||
|
||||
// Write to one of the OPL I/O ports:
|
||||
|
||||
void OPL_WritePort(opl_port_t port, unsigned int value);
|
||||
|
||||
// Read from one of the OPL I/O ports:
|
||||
|
||||
unsigned int OPL_ReadPort(opl_port_t port);
|
||||
|
||||
//
|
||||
// Higher-level functions.
|
||||
//
|
||||
|
||||
// Read the cuurrent status byte of the OPL chip.
|
||||
|
||||
unsigned int OPL_ReadStatus(void);
|
||||
|
||||
// Write to an OPL register.
|
||||
|
||||
void OPL_WriteRegister(int reg, int value);
|
||||
|
||||
// Perform a detection sequence to determine that an
|
||||
// OPL chip is present.
|
||||
|
||||
opl_init_result_t OPL_Detect(void);
|
||||
|
||||
// Initialize all registers, performed on startup.
|
||||
|
||||
void OPL_InitRegisters(int opl3);
|
||||
|
||||
//
|
||||
// Timer callback functions.
|
||||
//
|
||||
|
||||
// Set a timer callback. After the specified number of microseconds
|
||||
// have elapsed, the callback will be invoked.
|
||||
|
||||
void OPL_SetCallback(uint64_t us, opl_callback_t callback, void *data);
|
||||
|
||||
// Adjust callback times by the specified factor. For example, a value of
|
||||
// 0.5 will halve all remaining times.
|
||||
|
||||
void OPL_AdjustCallbacks(float factor);
|
||||
|
||||
// Clear all OPL callbacks that have been set.
|
||||
|
||||
void OPL_ClearCallbacks(void);
|
||||
|
||||
// Begin critical section, during which, OPL callbacks will not be
|
||||
// invoked.
|
||||
|
||||
void OPL_Lock(void);
|
||||
|
||||
// End critical section.
|
||||
|
||||
void OPL_Unlock(void);
|
||||
|
||||
// Block until the specified number of microseconds have elapsed.
|
||||
|
||||
void OPL_Delay(uint64_t us);
|
||||
|
||||
// Pause the OPL callbacks.
|
||||
|
||||
void OPL_SetPaused(int paused);
|
||||
|
||||
#endif
|
||||
|
||||
1377
games/NXDoom/opl/opl3.c
Normal file
150
games/NXDoom/opl/opl3.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
//
|
||||
// Copyright (C) 2013-2018 Alexey Khokholov (Nuke.YKT)
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
// Nuked OPL3 emulator.
|
||||
// Thanks:
|
||||
// MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
|
||||
// Feedback and Rhythm part calculation information.
|
||||
// forums.submarine.org.uk(carbon14, opl3):
|
||||
// Tremolo and phase generator calculation information.
|
||||
// OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
||||
// OPL2 ROMs.
|
||||
// siliconpr0n.org(John McMaster, digshadow):
|
||||
// YMF262 and VRC VII decaps and die shots.
|
||||
//
|
||||
// version: 1.8
|
||||
//
|
||||
|
||||
#ifndef OPL_OPL3_H
|
||||
#define OPL_OPL3_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define OPL_WRITEBUF_SIZE 1024
|
||||
#define OPL_WRITEBUF_DELAY 2
|
||||
|
||||
typedef uintptr_t Bitu;
|
||||
typedef intptr_t Bits;
|
||||
typedef uint64_t Bit64u;
|
||||
typedef int64_t Bit64s;
|
||||
typedef uint32_t Bit32u;
|
||||
typedef int32_t Bit32s;
|
||||
typedef uint16_t Bit16u;
|
||||
typedef int16_t Bit16s;
|
||||
typedef uint8_t Bit8u;
|
||||
typedef int8_t Bit8s;
|
||||
|
||||
typedef struct _opl3_slot opl3_slot;
|
||||
typedef struct _opl3_channel opl3_channel;
|
||||
typedef struct _opl3_chip opl3_chip;
|
||||
|
||||
struct _opl3_slot {
|
||||
opl3_channel *channel;
|
||||
opl3_chip *chip;
|
||||
Bit16s out;
|
||||
Bit16s fbmod;
|
||||
Bit16s *mod;
|
||||
Bit16s prout;
|
||||
Bit16s eg_rout;
|
||||
Bit16s eg_out;
|
||||
Bit8u eg_inc;
|
||||
Bit8u eg_gen;
|
||||
Bit8u eg_rate;
|
||||
Bit8u eg_ksl;
|
||||
Bit8u *trem;
|
||||
Bit8u reg_vib;
|
||||
Bit8u reg_type;
|
||||
Bit8u reg_ksr;
|
||||
Bit8u reg_mult;
|
||||
Bit8u reg_ksl;
|
||||
Bit8u reg_tl;
|
||||
Bit8u reg_ar;
|
||||
Bit8u reg_dr;
|
||||
Bit8u reg_sl;
|
||||
Bit8u reg_rr;
|
||||
Bit8u reg_wf;
|
||||
Bit8u key;
|
||||
Bit32u pg_reset;
|
||||
Bit32u pg_phase;
|
||||
Bit16u pg_phase_out;
|
||||
Bit8u slot_num;
|
||||
};
|
||||
|
||||
struct _opl3_channel {
|
||||
opl3_slot *slots[2];
|
||||
opl3_channel *pair;
|
||||
opl3_chip *chip;
|
||||
Bit16s *out[4];
|
||||
Bit8u chtype;
|
||||
Bit16u f_num;
|
||||
Bit8u block;
|
||||
Bit8u fb;
|
||||
Bit8u con;
|
||||
Bit8u alg;
|
||||
Bit8u ksv;
|
||||
Bit16u cha, chb;
|
||||
Bit8u ch_num;
|
||||
};
|
||||
|
||||
typedef struct _opl3_writebuf {
|
||||
Bit64u time;
|
||||
Bit16u reg;
|
||||
Bit8u data;
|
||||
} opl3_writebuf;
|
||||
|
||||
struct _opl3_chip {
|
||||
opl3_channel channel[18];
|
||||
opl3_slot slot[36];
|
||||
Bit16u timer;
|
||||
Bit64u eg_timer;
|
||||
Bit8u eg_timerrem;
|
||||
Bit8u eg_state;
|
||||
Bit8u eg_add;
|
||||
Bit8u newm;
|
||||
Bit8u nts;
|
||||
Bit8u rhy;
|
||||
Bit8u vibpos;
|
||||
Bit8u vibshift;
|
||||
Bit8u tremolo;
|
||||
Bit8u tremolopos;
|
||||
Bit8u tremoloshift;
|
||||
Bit32u noise;
|
||||
Bit16s zeromod;
|
||||
Bit32s mixbuff[2];
|
||||
Bit8u rm_hh_bit2;
|
||||
Bit8u rm_hh_bit3;
|
||||
Bit8u rm_hh_bit7;
|
||||
Bit8u rm_hh_bit8;
|
||||
Bit8u rm_tc_bit3;
|
||||
Bit8u rm_tc_bit5;
|
||||
//OPL3L
|
||||
Bit32s rateratio;
|
||||
Bit32s samplecnt;
|
||||
Bit16s oldsamples[2];
|
||||
Bit16s samples[2];
|
||||
|
||||
Bit64u writebuf_samplecnt;
|
||||
Bit32u writebuf_cur;
|
||||
Bit32u writebuf_last;
|
||||
Bit64u writebuf_lasttime;
|
||||
opl3_writebuf writebuf[OPL_WRITEBUF_SIZE];
|
||||
};
|
||||
|
||||
void OPL3_Generate(opl3_chip *chip, Bit16s *buf);
|
||||
void OPL3_GenerateResampled(opl3_chip *chip, Bit16s *buf);
|
||||
void OPL3_Reset(opl3_chip *chip, Bit32u samplerate);
|
||||
void OPL3_WriteReg(opl3_chip *chip, Bit16u reg, Bit8u v);
|
||||
void OPL3_WriteRegBuffered(opl3_chip *chip, Bit16u reg, Bit8u v);
|
||||
void OPL3_GenerateStream(opl3_chip *chip, Bit16s *sndptr, Bit32u numsamples);
|
||||
#endif
|
||||
71
games/NXDoom/opl/opl_internal.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL internal interface.
|
||||
//
|
||||
|
||||
|
||||
#ifndef OPL_INTERNAL_H
|
||||
#define OPL_INTERNAL_H
|
||||
|
||||
#include "opl.h"
|
||||
|
||||
typedef int (*opl_init_func)(unsigned int port_base);
|
||||
typedef void (*opl_shutdown_func)(void);
|
||||
typedef unsigned int (*opl_read_port_func)(opl_port_t port);
|
||||
typedef void (*opl_write_port_func)(opl_port_t port, unsigned int value);
|
||||
typedef void (*opl_set_callback_func)(uint64_t us,
|
||||
opl_callback_t callback,
|
||||
void *data);
|
||||
typedef void (*opl_clear_callbacks_func)(void);
|
||||
typedef void (*opl_lock_func)(void);
|
||||
typedef void (*opl_unlock_func)(void);
|
||||
typedef void (*opl_set_paused_func)(int paused);
|
||||
typedef void (*opl_adjust_callbacks_func)(float value);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
|
||||
opl_init_func init_func;
|
||||
opl_shutdown_func shutdown_func;
|
||||
opl_read_port_func read_port_func;
|
||||
opl_write_port_func write_port_func;
|
||||
opl_set_callback_func set_callback_func;
|
||||
opl_clear_callbacks_func clear_callbacks_func;
|
||||
opl_lock_func lock_func;
|
||||
opl_unlock_func unlock_func;
|
||||
opl_set_paused_func set_paused_func;
|
||||
opl_adjust_callbacks_func adjust_callbacks_func;
|
||||
} opl_driver_t;
|
||||
|
||||
// Sample rate to use when doing software emulation.
|
||||
|
||||
extern unsigned int opl_sample_rate;
|
||||
|
||||
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
|
||||
extern opl_driver_t opl_linux_driver;
|
||||
#endif
|
||||
#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64)
|
||||
extern opl_driver_t opl_openbsd_driver;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
extern opl_driver_t opl_win32_driver;
|
||||
#endif
|
||||
extern opl_driver_t opl_sdl_driver;
|
||||
|
||||
|
||||
#endif /* #ifndef OPL_INTERNAL_H */
|
||||
|
||||
103
games/NXDoom/opl/opl_linux.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL Linux interface.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/io.h>
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
#include "opl_timer.h"
|
||||
|
||||
static unsigned int opl_port_base;
|
||||
|
||||
static int OPL_Linux_Init(unsigned int port_base)
|
||||
{
|
||||
// Try to get permissions:
|
||||
|
||||
if (ioperm(port_base, 3, 1) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to get I/O port permissions for 0x%x: %s\n",
|
||||
port_base, strerror(errno));
|
||||
|
||||
if (errno == EPERM)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\tYou may need to run the program as root in order\n"
|
||||
"\tto acquire I/O port permissions for OPL MIDI playback.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
opl_port_base = port_base;
|
||||
|
||||
// Start callback thread
|
||||
|
||||
if (!OPL_Timer_StartThread())
|
||||
{
|
||||
ioperm(port_base, 2, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void OPL_Linux_Shutdown(void)
|
||||
{
|
||||
// Stop callback thread
|
||||
|
||||
OPL_Timer_StopThread();
|
||||
|
||||
// Release permissions
|
||||
|
||||
ioperm(opl_port_base, 2, 0);
|
||||
}
|
||||
|
||||
static unsigned int OPL_Linux_PortRead(opl_port_t port)
|
||||
{
|
||||
return inb(opl_port_base + port);
|
||||
}
|
||||
|
||||
static void OPL_Linux_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
outb(value, opl_port_base + port);
|
||||
}
|
||||
|
||||
opl_driver_t opl_linux_driver =
|
||||
{
|
||||
"Linux",
|
||||
OPL_Linux_Init,
|
||||
OPL_Linux_Shutdown,
|
||||
OPL_Linux_PortRead,
|
||||
OPL_Linux_PortWrite,
|
||||
OPL_Timer_SetCallback,
|
||||
OPL_Timer_ClearCallbacks,
|
||||
OPL_Timer_Lock,
|
||||
OPL_Timer_Unlock,
|
||||
OPL_Timer_SetPaused,
|
||||
OPL_Timer_AdjustCallbacks,
|
||||
};
|
||||
|
||||
#endif /* #if (defined(__i386__) || defined(__x86_64__)) && defined(HAVE_IOPERM) */
|
||||
|
||||
118
games/NXDoom/opl/opl_obsd.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL OpenBSD interface (also NetBSD)
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
// OpenBSD has a i386_iopl on i386 and amd64_iopl on x86_64,
|
||||
// even though they do the same thing. Take care of this
|
||||
// here, and map set_iopl to point to the appropriate name.
|
||||
|
||||
#if defined(HAVE_LIBI386)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <i386/pio.h>
|
||||
#define set_iopl i386_iopl
|
||||
|
||||
#elif defined(HAVE_LIBAMD64)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <amd64/pio.h>
|
||||
#define set_iopl amd64_iopl
|
||||
|
||||
#else
|
||||
#define NO_OBSD_DRIVER
|
||||
#endif
|
||||
|
||||
// If the above succeeded, proceed with the rest.
|
||||
|
||||
#ifndef NO_OBSD_DRIVER
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
#include "opl_timer.h"
|
||||
|
||||
static unsigned int opl_port_base;
|
||||
|
||||
static int OPL_OpenBSD_Init(unsigned int port_base)
|
||||
{
|
||||
// Try to get permissions:
|
||||
|
||||
if (set_iopl(3) < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to get raise I/O privilege level: "
|
||||
"check that you are running as root.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
opl_port_base = port_base;
|
||||
|
||||
// Start callback thread
|
||||
|
||||
if (!OPL_Timer_StartThread())
|
||||
{
|
||||
set_iopl(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void OPL_OpenBSD_Shutdown(void)
|
||||
{
|
||||
// Stop callback thread
|
||||
|
||||
OPL_Timer_StopThread();
|
||||
|
||||
// Release I/O port permissions:
|
||||
|
||||
set_iopl(0);
|
||||
}
|
||||
|
||||
static unsigned int OPL_OpenBSD_PortRead(opl_port_t port)
|
||||
{
|
||||
return inb(opl_port_base + port);
|
||||
}
|
||||
|
||||
static void OPL_OpenBSD_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
outb(opl_port_base + port, value);
|
||||
}
|
||||
|
||||
opl_driver_t opl_openbsd_driver =
|
||||
{
|
||||
"OpenBSD",
|
||||
OPL_OpenBSD_Init,
|
||||
OPL_OpenBSD_Shutdown,
|
||||
OPL_OpenBSD_PortRead,
|
||||
OPL_OpenBSD_PortWrite,
|
||||
OPL_Timer_SetCallback,
|
||||
OPL_Timer_ClearCallbacks,
|
||||
OPL_Timer_Lock,
|
||||
OPL_Timer_Unlock,
|
||||
OPL_Timer_SetPaused,
|
||||
OPL_Timer_AdjustCallbacks,
|
||||
};
|
||||
|
||||
#endif /* #ifndef NO_OBSD_DRIVER */
|
||||
|
||||
285
games/NXDoom/opl/opl_queue.c
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
//
|
||||
// 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:
|
||||
// Queue of waiting callbacks, stored in a binary min heap, so that we
|
||||
// can always get the first callback.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "opl_queue.h"
|
||||
|
||||
#define MAX_OPL_QUEUE 64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
opl_callback_t callback;
|
||||
void *data;
|
||||
uint64_t time;
|
||||
} opl_queue_entry_t;
|
||||
|
||||
struct opl_callback_queue_s
|
||||
{
|
||||
opl_queue_entry_t entries[MAX_OPL_QUEUE];
|
||||
unsigned int num_entries;
|
||||
};
|
||||
|
||||
opl_callback_queue_t *OPL_Queue_Create(void)
|
||||
{
|
||||
opl_callback_queue_t *queue;
|
||||
|
||||
queue = malloc(sizeof(opl_callback_queue_t));
|
||||
queue->num_entries = 0;
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
void OPL_Queue_Destroy(opl_callback_queue_t *queue)
|
||||
{
|
||||
free(queue);
|
||||
}
|
||||
|
||||
int OPL_Queue_IsEmpty(opl_callback_queue_t *queue)
|
||||
{
|
||||
return queue->num_entries == 0;
|
||||
}
|
||||
|
||||
void OPL_Queue_Clear(opl_callback_queue_t *queue)
|
||||
{
|
||||
queue->num_entries = 0;
|
||||
}
|
||||
|
||||
void OPL_Queue_Push(opl_callback_queue_t *queue,
|
||||
opl_callback_t callback, void *data,
|
||||
uint64_t time)
|
||||
{
|
||||
int entry_id;
|
||||
int parent_id;
|
||||
|
||||
if (queue->num_entries >= MAX_OPL_QUEUE)
|
||||
{
|
||||
fprintf(stderr, "OPL_Queue_Push: Exceeded maximum callbacks\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to last queue entry.
|
||||
|
||||
entry_id = queue->num_entries;
|
||||
++queue->num_entries;
|
||||
|
||||
// Shift existing entries down in the heap.
|
||||
|
||||
while (entry_id > 0)
|
||||
{
|
||||
parent_id = (entry_id - 1) / 2;
|
||||
|
||||
// Is the heap condition satisfied?
|
||||
|
||||
if (time >= queue->entries[parent_id].time)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Move the existing entry down in the heap.
|
||||
|
||||
memcpy(&queue->entries[entry_id],
|
||||
&queue->entries[parent_id],
|
||||
sizeof(opl_queue_entry_t));
|
||||
|
||||
// Advance to the parent.
|
||||
|
||||
entry_id = parent_id;
|
||||
}
|
||||
|
||||
// Insert new callback data.
|
||||
|
||||
queue->entries[entry_id].callback = callback;
|
||||
queue->entries[entry_id].data = data;
|
||||
queue->entries[entry_id].time = time;
|
||||
}
|
||||
|
||||
int OPL_Queue_Pop(opl_callback_queue_t *queue,
|
||||
opl_callback_t *callback, void **data)
|
||||
{
|
||||
opl_queue_entry_t *entry;
|
||||
int child1, child2;
|
||||
int i, next_i;
|
||||
|
||||
// Empty?
|
||||
|
||||
if (queue->num_entries <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Store the result:
|
||||
|
||||
*callback = queue->entries[0].callback;
|
||||
*data = queue->entries[0].data;
|
||||
|
||||
// Decrease the heap size, and keep pointer to the last entry in
|
||||
// the heap, which must now be percolated down from the top.
|
||||
|
||||
--queue->num_entries;
|
||||
entry = &queue->entries[queue->num_entries];
|
||||
|
||||
// Percolate down.
|
||||
|
||||
i = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
child1 = i * 2 + 1;
|
||||
child2 = i * 2 + 2;
|
||||
|
||||
if (child1 < queue->num_entries
|
||||
&& queue->entries[child1].time < entry->time)
|
||||
{
|
||||
// Left child is less than entry.
|
||||
// Use the minimum of left and right children.
|
||||
|
||||
if (child2 < queue->num_entries
|
||||
&& queue->entries[child2].time < queue->entries[child1].time)
|
||||
{
|
||||
next_i = child2;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_i = child1;
|
||||
}
|
||||
}
|
||||
else if (child2 < queue->num_entries
|
||||
&& queue->entries[child2].time < entry->time)
|
||||
{
|
||||
// Right child is less than entry. Go down the right side.
|
||||
|
||||
next_i = child2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Finished percolating.
|
||||
break;
|
||||
}
|
||||
|
||||
// Percolate the next value up and advance.
|
||||
|
||||
memcpy(&queue->entries[i],
|
||||
&queue->entries[next_i],
|
||||
sizeof(opl_queue_entry_t));
|
||||
i = next_i;
|
||||
}
|
||||
|
||||
// Store the old last-entry at its new position.
|
||||
|
||||
memcpy(&queue->entries[i], entry, sizeof(opl_queue_entry_t));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue)
|
||||
{
|
||||
if (queue->num_entries > 0)
|
||||
{
|
||||
return queue->entries[0].time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
|
||||
uint64_t time, float factor)
|
||||
{
|
||||
int64_t offset;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < queue->num_entries; ++i)
|
||||
{
|
||||
offset = queue->entries[i].time - time;
|
||||
queue->entries[i].time = time + (uint64_t) (offset / factor);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static void PrintQueueNode(opl_callback_queue_t *queue, int node, int depth)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (node >= queue->num_entries)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<depth * 3; ++i)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("%i\n", queue->entries[node].time);
|
||||
|
||||
PrintQueueNode(queue, node * 2 + 1, depth + 1);
|
||||
PrintQueueNode(queue, node * 2 + 2, depth + 1);
|
||||
}
|
||||
|
||||
static void PrintQueue(opl_callback_queue_t *queue)
|
||||
{
|
||||
PrintQueueNode(queue, 0, 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
opl_callback_queue_t *queue;
|
||||
int iteration;
|
||||
|
||||
queue = OPL_Queue_Create();
|
||||
|
||||
for (iteration=0; iteration<5000; ++iteration)
|
||||
{
|
||||
opl_callback_t callback;
|
||||
void *data;
|
||||
unsigned int time;
|
||||
unsigned int newtime;
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_OPL_QUEUE; ++i)
|
||||
{
|
||||
time = rand() % 0x10000;
|
||||
OPL_Queue_Push(queue, NULL, NULL, time);
|
||||
}
|
||||
|
||||
time = 0;
|
||||
|
||||
for (i=0; i<MAX_OPL_QUEUE; ++i)
|
||||
{
|
||||
assert(!OPL_Queue_IsEmpty(queue));
|
||||
newtime = OPL_Queue_Peek(queue);
|
||||
assert(OPL_Queue_Pop(queue, &callback, &data));
|
||||
|
||||
assert(newtime >= time);
|
||||
time = newtime;
|
||||
}
|
||||
|
||||
assert(OPL_Queue_IsEmpty(queue));
|
||||
assert(!OPL_Queue_Pop(queue, &callback, &data));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
39
games/NXDoom/opl/opl_queue.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL callback queue.
|
||||
//
|
||||
|
||||
#ifndef OPL_QUEUE_H
|
||||
#define OPL_QUEUE_H
|
||||
|
||||
#include "opl.h"
|
||||
|
||||
typedef struct opl_callback_queue_s opl_callback_queue_t;
|
||||
|
||||
opl_callback_queue_t *OPL_Queue_Create(void);
|
||||
int OPL_Queue_IsEmpty(opl_callback_queue_t *queue);
|
||||
void OPL_Queue_Clear(opl_callback_queue_t *queue);
|
||||
void OPL_Queue_Destroy(opl_callback_queue_t *queue);
|
||||
void OPL_Queue_Push(opl_callback_queue_t *queue,
|
||||
opl_callback_t callback, void *data,
|
||||
uint64_t time);
|
||||
int OPL_Queue_Pop(opl_callback_queue_t *queue,
|
||||
opl_callback_t *callback, void **data);
|
||||
uint64_t OPL_Queue_Peek(opl_callback_queue_t *queue);
|
||||
void OPL_Queue_AdjustCallbacks(opl_callback_queue_t *queue,
|
||||
uint64_t time, float factor);
|
||||
|
||||
#endif /* #ifndef OPL_QUEUE_H */
|
||||
|
||||
521
games/NXDoom/opl/opl_sdl.c
Normal file
|
|
@ -0,0 +1,521 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL SDL interface.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#ifndef DISABLE_SDL2MIXER
|
||||
#include "SDL_mixer.h"
|
||||
#endif // DISABLE_SDL2MIXER
|
||||
|
||||
#include "opl3.h"
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
|
||||
#include "opl_queue.h"
|
||||
|
||||
|
||||
#ifndef DISABLE_SDL2MIXER
|
||||
|
||||
|
||||
#define MAX_SOUND_SLICE_TIME 100 /* ms */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int rate; // Number of times the timer is advanced per sec.
|
||||
unsigned int enabled; // Non-zero if timer is enabled.
|
||||
unsigned int value; // Last value that was set.
|
||||
uint64_t expire_time; // Calculated time that timer will expire.
|
||||
} opl_timer_t;
|
||||
|
||||
// When the callback mutex is locked using OPL_Lock, callback functions
|
||||
// are not invoked.
|
||||
|
||||
static SDL_mutex *callback_mutex = NULL;
|
||||
|
||||
// Queue of callbacks waiting to be invoked.
|
||||
|
||||
static opl_callback_queue_t *callback_queue;
|
||||
|
||||
// Mutex used to control access to the callback queue.
|
||||
|
||||
static SDL_mutex *callback_queue_mutex = NULL;
|
||||
|
||||
// Current time, in us since startup:
|
||||
|
||||
static uint64_t current_time;
|
||||
|
||||
// If non-zero, playback is currently paused.
|
||||
|
||||
static int opl_sdl_paused;
|
||||
|
||||
// Time offset (in us) due to the fact that callbacks
|
||||
// were previously paused.
|
||||
|
||||
static uint64_t pause_offset;
|
||||
|
||||
// OPL software emulator structure.
|
||||
|
||||
static opl3_chip opl_chip;
|
||||
static int opl_opl3mode;
|
||||
|
||||
// Temporary mixing buffer used by the mixing callback.
|
||||
|
||||
static uint8_t *mix_buffer = NULL;
|
||||
|
||||
// Register number that was written.
|
||||
|
||||
static int register_num = 0;
|
||||
|
||||
// Timers; DBOPL does not do timer stuff itself.
|
||||
|
||||
static opl_timer_t timer1 = { 12500, 0, 0, 0 };
|
||||
static opl_timer_t timer2 = { 3125, 0, 0, 0 };
|
||||
|
||||
// SDL parameters.
|
||||
|
||||
static int sdl_was_initialized = 0;
|
||||
static int mixing_freq, mixing_channels;
|
||||
static Uint16 mixing_format;
|
||||
|
||||
static int SDLIsInitialized(void)
|
||||
{
|
||||
int freq, channels;
|
||||
Uint16 format;
|
||||
|
||||
return Mix_QuerySpec(&freq, &format, &channels);
|
||||
}
|
||||
|
||||
// Advance time by the specified number of samples, invoking any
|
||||
// callback functions as appropriate.
|
||||
|
||||
static void AdvanceTime(unsigned int nsamples)
|
||||
{
|
||||
opl_callback_t callback;
|
||||
void *callback_data;
|
||||
uint64_t us;
|
||||
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
|
||||
// Advance time.
|
||||
|
||||
us = ((uint64_t) nsamples * OPL_SECOND) / mixing_freq;
|
||||
current_time += us;
|
||||
|
||||
if (opl_sdl_paused)
|
||||
{
|
||||
pause_offset += us;
|
||||
}
|
||||
|
||||
// Are there callbacks to invoke now? Keep invoking them
|
||||
// until there are no more left.
|
||||
|
||||
while (!OPL_Queue_IsEmpty(callback_queue)
|
||||
&& current_time >= OPL_Queue_Peek(callback_queue) + pause_offset)
|
||||
{
|
||||
// Pop the callback from the queue to invoke it.
|
||||
|
||||
if (!OPL_Queue_Pop(callback_queue, &callback, &callback_data))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The mutex stuff here is a bit complicated. We must
|
||||
// hold callback_mutex when we invoke the callback (so that
|
||||
// the control thread can use OPL_Lock() to prevent callbacks
|
||||
// from being invoked), but we must not be holding
|
||||
// callback_queue_mutex, as the callback must be able to
|
||||
// call OPL_SetCallback to schedule new callbacks.
|
||||
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
|
||||
SDL_LockMutex(callback_mutex);
|
||||
callback(callback_data);
|
||||
SDL_UnlockMutex(callback_mutex);
|
||||
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
// Call the OPL emulator code to fill the specified buffer.
|
||||
|
||||
static void FillBuffer(uint8_t *buffer, unsigned int nsamples)
|
||||
{
|
||||
// This seems like a reasonable assumption. mix_buffer is
|
||||
// 1 second long, which should always be much longer than the
|
||||
// SDL mix buffer.
|
||||
assert(nsamples < mixing_freq);
|
||||
|
||||
// OPL output is generated into temporary buffer and then mixed
|
||||
// (to avoid overflows etc.)
|
||||
OPL3_GenerateStream(&opl_chip, (Bit16s *) mix_buffer, nsamples);
|
||||
SDL_MixAudioFormat(buffer, mix_buffer, AUDIO_S16SYS, nsamples * 4,
|
||||
SDL_MIX_MAXVOLUME);
|
||||
}
|
||||
|
||||
// Callback function to fill a new sound buffer:
|
||||
|
||||
static void OPL_Mix_Callback(int chan, void *stream, int len, void *udata)
|
||||
{
|
||||
unsigned int filled, buffer_samples;
|
||||
Uint8 *buffer = (Uint8*)stream;
|
||||
|
||||
// Repeatedly call the OPL emulator update function until the buffer is
|
||||
// full.
|
||||
filled = 0;
|
||||
buffer_samples = len / 4;
|
||||
|
||||
while (filled < buffer_samples)
|
||||
{
|
||||
uint64_t next_callback_time;
|
||||
uint64_t nsamples;
|
||||
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
|
||||
// Work out the time until the next callback waiting in
|
||||
// the callback queue must be invoked. We can then fill the
|
||||
// buffer with this many samples.
|
||||
|
||||
if (opl_sdl_paused || OPL_Queue_IsEmpty(callback_queue))
|
||||
{
|
||||
nsamples = buffer_samples - filled;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset;
|
||||
|
||||
nsamples = (next_callback_time - current_time) * mixing_freq;
|
||||
nsamples = (nsamples + OPL_SECOND - 1) / OPL_SECOND;
|
||||
|
||||
if (nsamples > buffer_samples - filled)
|
||||
{
|
||||
nsamples = buffer_samples - filled;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
|
||||
// Add emulator output to buffer.
|
||||
|
||||
FillBuffer(buffer + filled * 4, nsamples);
|
||||
filled += nsamples;
|
||||
|
||||
// Invoke callbacks for this point in time.
|
||||
|
||||
AdvanceTime(nsamples);
|
||||
}
|
||||
}
|
||||
|
||||
static void OPL_SDL_Shutdown(void)
|
||||
{
|
||||
Mix_HookMusic(NULL, NULL);
|
||||
|
||||
if (sdl_was_initialized)
|
||||
{
|
||||
Mix_CloseAudio();
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
OPL_Queue_Destroy(callback_queue);
|
||||
free(mix_buffer);
|
||||
sdl_was_initialized = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
if (opl_chip != NULL)
|
||||
{
|
||||
OPLDestroy(opl_chip);
|
||||
opl_chip = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if (callback_mutex != NULL)
|
||||
{
|
||||
SDL_DestroyMutex(callback_mutex);
|
||||
callback_mutex = NULL;
|
||||
}
|
||||
|
||||
if (callback_queue_mutex != NULL)
|
||||
{
|
||||
SDL_DestroyMutex(callback_queue_mutex);
|
||||
callback_queue_mutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int GetSliceSize(void)
|
||||
{
|
||||
int limit;
|
||||
int n;
|
||||
|
||||
limit = (opl_sample_rate * MAX_SOUND_SLICE_TIME) / 1000;
|
||||
|
||||
// Try all powers of two, not exceeding the limit.
|
||||
|
||||
for (n=0;; ++n)
|
||||
{
|
||||
// 2^n <= limit < 2^n+1 ?
|
||||
|
||||
if ((1 << (n + 1)) > limit)
|
||||
{
|
||||
return (1 << n);
|
||||
}
|
||||
}
|
||||
|
||||
// Should never happen?
|
||||
|
||||
return 1024;
|
||||
}
|
||||
|
||||
static int OPL_SDL_Init(unsigned int port_base)
|
||||
{
|
||||
// Check if SDL_mixer has been opened already
|
||||
// If not, we must initialize it now
|
||||
|
||||
if (!SDLIsInitialized())
|
||||
{
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
fprintf(stderr, "Unable to set up sound.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Mix_OpenAudioDevice(opl_sample_rate, AUDIO_S16SYS, 2, GetSliceSize(), NULL, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error initialising SDL_mixer: %s\n", Mix_GetError());
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
// When this module shuts down, it has the responsibility to
|
||||
// shut down SDL.
|
||||
|
||||
sdl_was_initialized = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sdl_was_initialized = 0;
|
||||
}
|
||||
|
||||
opl_sdl_paused = 0;
|
||||
pause_offset = 0;
|
||||
|
||||
// Queue structure of callbacks to invoke.
|
||||
|
||||
callback_queue = OPL_Queue_Create();
|
||||
current_time = 0;
|
||||
|
||||
// Get the mixer frequency, format and number of channels.
|
||||
|
||||
Mix_QuerySpec(&mixing_freq, &mixing_format, &mixing_channels);
|
||||
|
||||
// Only supports AUDIO_S16SYS
|
||||
|
||||
if (mixing_format != AUDIO_S16SYS || mixing_channels != 2)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"OPL_SDL only supports native signed 16-bit LSB, "
|
||||
"stereo format!\n");
|
||||
|
||||
OPL_SDL_Shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Mix buffer: four bytes per sample (16 bits * 2 channels):
|
||||
mix_buffer = malloc(mixing_freq * 4);
|
||||
|
||||
// Create the emulator structure:
|
||||
|
||||
OPL3_Reset(&opl_chip, mixing_freq);
|
||||
opl_opl3mode = 0;
|
||||
|
||||
callback_mutex = SDL_CreateMutex();
|
||||
callback_queue_mutex = SDL_CreateMutex();
|
||||
|
||||
// Set postmix that adds the OPL music. This is deliberately done
|
||||
// as a postmix and not using Mix_HookMusic() as the latter disables
|
||||
// normal SDL_mixer music mixing.
|
||||
Mix_RegisterEffect(MIX_CHANNEL_POST, OPL_Mix_Callback, NULL, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int OPL_SDL_PortRead(opl_port_t port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
if (port == OPL_REGISTER_PORT_OPL3)
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
if (timer1.enabled && current_time > timer1.expire_time)
|
||||
{
|
||||
result |= 0x80; // Either have expired
|
||||
result |= 0x40; // Timer 1 has expired
|
||||
}
|
||||
|
||||
if (timer2.enabled && current_time > timer2.expire_time)
|
||||
{
|
||||
result |= 0x80; // Either have expired
|
||||
result |= 0x20; // Timer 2 has expired
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void OPLTimer_CalculateEndTime(opl_timer_t *timer)
|
||||
{
|
||||
int tics;
|
||||
|
||||
// If the timer is enabled, calculate the time when the timer
|
||||
// will expire.
|
||||
|
||||
if (timer->enabled)
|
||||
{
|
||||
tics = 0x100 - timer->value;
|
||||
timer->expire_time = current_time
|
||||
+ ((uint64_t) tics * OPL_SECOND) / timer->rate;
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteRegister(unsigned int reg_num, unsigned int value)
|
||||
{
|
||||
switch (reg_num)
|
||||
{
|
||||
case OPL_REG_TIMER1:
|
||||
timer1.value = value;
|
||||
OPLTimer_CalculateEndTime(&timer1);
|
||||
break;
|
||||
|
||||
case OPL_REG_TIMER2:
|
||||
timer2.value = value;
|
||||
OPLTimer_CalculateEndTime(&timer2);
|
||||
break;
|
||||
|
||||
case OPL_REG_TIMER_CTRL:
|
||||
if (value & 0x80)
|
||||
{
|
||||
timer1.enabled = 0;
|
||||
timer2.enabled = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((value & 0x40) == 0)
|
||||
{
|
||||
timer1.enabled = (value & 0x01) != 0;
|
||||
OPLTimer_CalculateEndTime(&timer1);
|
||||
}
|
||||
|
||||
if ((value & 0x20) == 0)
|
||||
{
|
||||
timer2.enabled = (value & 0x02) != 0;
|
||||
OPLTimer_CalculateEndTime(&timer2);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OPL_REG_NEW:
|
||||
opl_opl3mode = value & 0x01;
|
||||
|
||||
default:
|
||||
OPL3_WriteRegBuffered(&opl_chip, reg_num, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void OPL_SDL_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
if (port == OPL_REGISTER_PORT)
|
||||
{
|
||||
register_num = value;
|
||||
}
|
||||
else if (port == OPL_REGISTER_PORT_OPL3)
|
||||
{
|
||||
register_num = value | 0x100;
|
||||
}
|
||||
else if (port == OPL_DATA_PORT)
|
||||
{
|
||||
WriteRegister(register_num, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void OPL_SDL_SetCallback(uint64_t us, opl_callback_t callback,
|
||||
void *data)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Push(callback_queue, callback, data,
|
||||
current_time - pause_offset + us);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
static void OPL_SDL_ClearCallbacks(void)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Clear(callback_queue);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
static void OPL_SDL_Lock(void)
|
||||
{
|
||||
SDL_LockMutex(callback_mutex);
|
||||
}
|
||||
|
||||
static void OPL_SDL_Unlock(void)
|
||||
{
|
||||
SDL_UnlockMutex(callback_mutex);
|
||||
}
|
||||
|
||||
static void OPL_SDL_SetPaused(int paused)
|
||||
{
|
||||
opl_sdl_paused = paused;
|
||||
}
|
||||
|
||||
static void OPL_SDL_AdjustCallbacks(float factor)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
opl_driver_t opl_sdl_driver =
|
||||
{
|
||||
"SDL",
|
||||
OPL_SDL_Init,
|
||||
OPL_SDL_Shutdown,
|
||||
OPL_SDL_PortRead,
|
||||
OPL_SDL_PortWrite,
|
||||
OPL_SDL_SetCallback,
|
||||
OPL_SDL_ClearCallbacks,
|
||||
OPL_SDL_Lock,
|
||||
OPL_SDL_Unlock,
|
||||
OPL_SDL_SetPaused,
|
||||
OPL_SDL_AdjustCallbacks,
|
||||
};
|
||||
|
||||
|
||||
#endif // DISABLE_SDL2MIXER
|
||||
250
games/NXDoom/opl/opl_timer.c
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL timer thread.
|
||||
// Once started using OPL_Timer_StartThread, the thread sleeps,
|
||||
// waking up to invoke callbacks set using OPL_Timer_SetCallback.
|
||||
//
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#include "opl_timer.h"
|
||||
#include "opl_queue.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
THREAD_STATE_STOPPED,
|
||||
THREAD_STATE_RUNNING,
|
||||
THREAD_STATE_STOPPING,
|
||||
} thread_state_t;
|
||||
|
||||
static SDL_Thread *timer_thread = NULL;
|
||||
static thread_state_t timer_thread_state;
|
||||
static uint64_t current_time;
|
||||
|
||||
// If non-zero, callbacks are currently paused.
|
||||
|
||||
static int opl_timer_paused;
|
||||
|
||||
// Offset in microseconds to adjust time due to the fact that playback
|
||||
// was paused.
|
||||
|
||||
static uint64_t pause_offset = 0;
|
||||
|
||||
// Queue of callbacks waiting to be invoked.
|
||||
// The callback queue mutex is held while the callback queue structure
|
||||
// or current_time is being accessed.
|
||||
|
||||
static opl_callback_queue_t *callback_queue;
|
||||
static SDL_mutex *callback_queue_mutex;
|
||||
|
||||
// The timer mutex is held while timer callback functions are being
|
||||
// invoked, so that the calling code can prevent clashes.
|
||||
|
||||
static SDL_mutex *timer_mutex;
|
||||
|
||||
// Returns true if there is a callback at the head of the queue ready
|
||||
// to be invoked. Otherwise, next_time is set to the time when the
|
||||
// timer thread must wake up again to check.
|
||||
|
||||
static int CallbackWaiting(uint64_t *next_time)
|
||||
{
|
||||
// If paused, just wait in 50ms increments until unpaused.
|
||||
// Update pause_offset so after we unpause, the callback
|
||||
// times will be right.
|
||||
|
||||
if (opl_timer_paused)
|
||||
{
|
||||
*next_time = current_time + 50 * OPL_MS;
|
||||
pause_offset += 50 * OPL_MS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If there are no queued callbacks, sleep for 50ms at a time
|
||||
// until a callback is added.
|
||||
|
||||
if (OPL_Queue_IsEmpty(callback_queue))
|
||||
{
|
||||
*next_time = current_time + 50 * OPL_MS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the time of the first callback in the queue.
|
||||
// If the time for the callback has not yet arrived,
|
||||
// we must sleep until the callback time.
|
||||
|
||||
*next_time = OPL_Queue_Peek(callback_queue) + pause_offset;
|
||||
|
||||
return *next_time <= current_time;
|
||||
}
|
||||
|
||||
static uint64_t GetNextTime(void)
|
||||
{
|
||||
opl_callback_t callback;
|
||||
void *callback_data;
|
||||
uint64_t next_time;
|
||||
int have_callback;
|
||||
|
||||
// Keep running through callbacks until there are none ready to
|
||||
// run. When we run out of callbacks, next_time will be set.
|
||||
|
||||
do
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
|
||||
// Check if the callback at the head of the list is ready to
|
||||
// be invoked. If so, pop from the head of the queue.
|
||||
|
||||
have_callback = CallbackWaiting(&next_time);
|
||||
|
||||
if (have_callback)
|
||||
{
|
||||
OPL_Queue_Pop(callback_queue, &callback, &callback_data);
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
|
||||
// Now invoke the callback, if we have one.
|
||||
// The timer mutex is held while the callback is invoked.
|
||||
|
||||
if (have_callback)
|
||||
{
|
||||
SDL_LockMutex(timer_mutex);
|
||||
callback(callback_data);
|
||||
SDL_UnlockMutex(timer_mutex);
|
||||
}
|
||||
} while (have_callback);
|
||||
|
||||
return next_time;
|
||||
}
|
||||
|
||||
static int ThreadFunction(void *unused)
|
||||
{
|
||||
uint64_t next_time;
|
||||
uint64_t now;
|
||||
|
||||
// Keep running until OPL_Timer_StopThread is called.
|
||||
|
||||
while (timer_thread_state == THREAD_STATE_RUNNING)
|
||||
{
|
||||
// Get the next time that we must sleep until, and
|
||||
// wait until that time.
|
||||
|
||||
next_time = GetNextTime();
|
||||
now = SDL_GetTicks() * OPL_MS;
|
||||
|
||||
if (next_time > now)
|
||||
{
|
||||
SDL_Delay((next_time - now) / OPL_MS);
|
||||
}
|
||||
|
||||
// Update the current time.
|
||||
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
current_time = next_time;
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
timer_thread_state = THREAD_STATE_STOPPED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void InitResources(void)
|
||||
{
|
||||
callback_queue = OPL_Queue_Create();
|
||||
timer_mutex = SDL_CreateMutex();
|
||||
callback_queue_mutex = SDL_CreateMutex();
|
||||
}
|
||||
|
||||
static void FreeResources(void)
|
||||
{
|
||||
OPL_Queue_Destroy(callback_queue);
|
||||
SDL_DestroyMutex(callback_queue_mutex);
|
||||
SDL_DestroyMutex(timer_mutex);
|
||||
}
|
||||
|
||||
int OPL_Timer_StartThread(void)
|
||||
{
|
||||
InitResources();
|
||||
|
||||
timer_thread_state = THREAD_STATE_RUNNING;
|
||||
current_time = SDL_GetTicks();
|
||||
opl_timer_paused = 0;
|
||||
pause_offset = 0;
|
||||
|
||||
timer_thread = SDL_CreateThread(ThreadFunction, "OPL timer thread", NULL);
|
||||
|
||||
if (timer_thread == NULL)
|
||||
{
|
||||
timer_thread_state = THREAD_STATE_STOPPED;
|
||||
FreeResources();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void OPL_Timer_StopThread(void)
|
||||
{
|
||||
timer_thread_state = THREAD_STATE_STOPPING;
|
||||
|
||||
while (timer_thread_state != THREAD_STATE_STOPPED)
|
||||
{
|
||||
SDL_Delay(1);
|
||||
}
|
||||
|
||||
FreeResources();
|
||||
}
|
||||
|
||||
void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Push(callback_queue, callback, data,
|
||||
current_time + us - pause_offset);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
void OPL_Timer_ClearCallbacks(void)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Clear(callback_queue);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
void OPL_Timer_AdjustCallbacks(float factor)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_AdjustCallbacks(callback_queue, current_time, factor);
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
void OPL_Timer_Lock(void)
|
||||
{
|
||||
SDL_LockMutex(timer_mutex);
|
||||
}
|
||||
|
||||
void OPL_Timer_Unlock(void)
|
||||
{
|
||||
SDL_UnlockMutex(timer_mutex);
|
||||
}
|
||||
|
||||
void OPL_Timer_SetPaused(int paused)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
opl_timer_paused = paused;
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
}
|
||||
|
||||
33
games/NXDoom/opl/opl_timer.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL timer thread.
|
||||
//
|
||||
|
||||
#ifndef OPL_TIMER_H
|
||||
#define OPL_TIMER_H
|
||||
|
||||
#include "opl.h"
|
||||
|
||||
int OPL_Timer_StartThread(void);
|
||||
void OPL_Timer_StopThread(void);
|
||||
void OPL_Timer_SetCallback(uint64_t us, opl_callback_t callback, void *data);
|
||||
void OPL_Timer_ClearCallbacks(void);
|
||||
void OPL_Timer_Lock(void);
|
||||
void OPL_Timer_Unlock(void);
|
||||
void OPL_Timer_SetPaused(int paused);
|
||||
void OPL_Timer_AdjustCallbacks(float factor);
|
||||
|
||||
#endif /* #ifndef OPL_TIMER_H */
|
||||
|
||||
192
games/NXDoom/opl/opl_win32.c
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
//
|
||||
// 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:
|
||||
// OPL Win32 native interface.
|
||||
//
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
#include "opl_timer.h"
|
||||
|
||||
#include "ioperm_sys.h"
|
||||
|
||||
static unsigned int opl_port_base;
|
||||
|
||||
// MingW?
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
static unsigned int OPL_Win32_PortRead(opl_port_t port)
|
||||
{
|
||||
unsigned char result;
|
||||
|
||||
__asm__ volatile (
|
||||
"movl %1, %%edx\n"
|
||||
"inb %%dx, %%al\n"
|
||||
"movb %%al, %0"
|
||||
: "=m" (result)
|
||||
: "r" (opl_port_base + port)
|
||||
: "edx", "al", "memory"
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
__asm__ volatile (
|
||||
"movl %0, %%edx\n"
|
||||
"movb %1, %%al\n"
|
||||
"outb %%al, %%dx"
|
||||
:
|
||||
: "r" (opl_port_base + port), "r" ((unsigned char) value)
|
||||
: "edx", "al"
|
||||
);
|
||||
}
|
||||
|
||||
// haleyjd 20110417: MSVC version
|
||||
#elif defined(_MSC_VER) && defined(_M_IX86)
|
||||
|
||||
static unsigned int OPL_Win32_PortRead(opl_port_t port)
|
||||
{
|
||||
unsigned char result;
|
||||
opl_port_t dst_port = opl_port_base + port;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov edx, dword ptr [dst_port]
|
||||
in al, dx
|
||||
mov byte ptr [result], al
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
opl_port_t dst_port = opl_port_base + port;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov edx, dword ptr [dst_port]
|
||||
mov al, byte ptr [value]
|
||||
out dx, al
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Not x86, or don't know how to do port R/W on this compiler.
|
||||
|
||||
#define NO_PORT_RW
|
||||
|
||||
static unsigned int OPL_Win32_PortRead(opl_port_t port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void OPL_Win32_PortWrite(opl_port_t port, unsigned int value)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int OPL_Win32_Init(unsigned int port_base)
|
||||
{
|
||||
|
||||
OSVERSIONINFO version_info;
|
||||
|
||||
opl_port_base = port_base;
|
||||
|
||||
// Check the OS version.
|
||||
|
||||
memset(&version_info, 0, sizeof(version_info));
|
||||
version_info.dwOSVersionInfoSize = sizeof(version_info);
|
||||
|
||||
GetVersionEx(&version_info);
|
||||
|
||||
#ifndef NO_PORT_RW
|
||||
// On NT-based systems, we must acquire I/O port permissions
|
||||
// using the ioperm.sys driver.
|
||||
|
||||
if (version_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
// Install driver.
|
||||
|
||||
if (!IOperm_InstallDriver())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Open port range.
|
||||
|
||||
if (!IOperm_EnablePortRange(opl_port_base, 2, 1))
|
||||
{
|
||||
IOperm_UninstallDriver();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Start callback thread
|
||||
|
||||
if (!OPL_Timer_StartThread())
|
||||
{
|
||||
IOperm_UninstallDriver();
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void OPL_Win32_Shutdown(void)
|
||||
{
|
||||
// Stop callback thread
|
||||
|
||||
OPL_Timer_StopThread();
|
||||
|
||||
// Unload IOperm library.
|
||||
|
||||
IOperm_UninstallDriver();
|
||||
}
|
||||
|
||||
opl_driver_t opl_win32_driver =
|
||||
{
|
||||
"Win32",
|
||||
OPL_Win32_Init,
|
||||
OPL_Win32_Shutdown,
|
||||
OPL_Win32_PortRead,
|
||||
OPL_Win32_PortWrite,
|
||||
OPL_Timer_SetCallback,
|
||||
OPL_Timer_ClearCallbacks,
|
||||
OPL_Timer_Lock,
|
||||
OPL_Timer_Unlock,
|
||||
OPL_Timer_SetPaused,
|
||||
OPL_Timer_AdjustCallbacks,
|
||||
};
|
||||
|
||||
#endif /* #ifdef _WIN32 */
|
||||
|
||||
8
games/NXDoom/pcsound/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
libpcsound.a
|
||||
*.rc
|
||||
tags
|
||||
TAGS
|
||||
|
||||
24
games/NXDoom/pcsound/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
add_library(pcsound STATIC
|
||||
pcsound.c pcsound.h
|
||||
pcsound_bsd.c
|
||||
pcsound_sdl.c
|
||||
pcsound_linux.c
|
||||
pcsound_win32.c
|
||||
pcsound_internal.h)
|
||||
target_include_directories(pcsound
|
||||
INTERFACE "."
|
||||
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/../")
|
||||
if (DEFINED EMSCRIPTEN)
|
||||
if(ENABLE_SDL2_MIXER)
|
||||
set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2")
|
||||
set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2 -s USE_SDL_MIXER=2")
|
||||
else()
|
||||
set_target_properties(pcsound PROPERTIES COMPILE_FLAGS "-s USE_SDL=2")
|
||||
set_target_properties(pcsound PROPERTIES LINK_FLAGS "-s USE_SDL=2")
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(pcsound SDL2::SDL2)
|
||||
if(ENABLE_SDL2_MIXER)
|
||||
target_link_libraries(pcsound SDL2_mixer::SDL2_mixer)
|
||||
endif()
|
||||
endif()
|
||||