games/NXDoom: Initial port of Chocolate DOOM to NuttX.
This commit includes a (highly) modified version of Chocolate DOOM which can run on NuttX. The majority of the modifications were made to pass the NuttX style check. Some small modifications have been added to support keyboard input, render graphics to frame buffers and directly use the POSIX interfaces NuttX supplies, stripping out Windows/Mac stuff and any references to SDL. NOTE: Sound is currently not supported in any capacity, nor is the networking stuff. A lot of Chocolate DOOM code was stripped out since it was unused. If there is a need/desire to add it back later, the original Chocolate DOOM source can be used as a reference. WARNING: The NuttX keyboard codec is incredibly non-standard and so there are problems translating from X11 keys to NuttX ones to play DOOM. Right now, the CTRL key for firing doesn't work because the NuttX codec has no concept of it. The NuttX codec should be modified (and other input devices supported), but at the time of this port I am not sufficiently comfortable doing so since I am afraid of breaking other things in the kernel. NOTE: This port (and likely the original DOOM) seems to be written with 32-bit computers in mind. As such, most things are given the type of natural `int`, even when a single byte might do. There are significant size optimizations that could be made to make this more suited to embedded devices that NuttX typically runs on. Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
4
games/NXDoom/.devcontainer/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
|||
*.xauth
|
||||
wads/
|
||||
prefs/
|
||||
share/
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
// 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)
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#!/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
|
|
@ -1,101 +0,0 @@
|
|||
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
|
|
@ -1,28 +0,0 @@
|
|||
<!--
|
||||
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
|
|
@ -1,54 +0,0 @@
|
|||
# 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
|
|
@ -1,23 +0,0 @@
|
|||
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
|
|
@ -1,152 +0,0 @@
|
|||
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 }}
|
||||
7
games/NXDoom/.gitignore
vendored
|
|
@ -1,13 +1,12 @@
|
|||
CMDLINE
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
Make.dep
|
||||
TAGS
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
autotools
|
||||
bin
|
||||
config.h
|
||||
config.hin
|
||||
config.log
|
||||
config.status
|
||||
|
|
@ -36,7 +35,11 @@ STRIFE*.pcx
|
|||
/out
|
||||
|
||||
# These are the default patterns globally ignored by Subversion:
|
||||
.depend
|
||||
.built
|
||||
*.o
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.lo
|
||||
*.la
|
||||
*.al
|
||||
|
|
|
|||
3
games/NXDoom/.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "quickcheck"]
|
||||
path = quickcheck
|
||||
url = https://github.com/chocolate-doom/quickcheck.git
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
" 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
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
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()
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# 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/
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
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
|
||||
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
# 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*
|
||||
//
|
||||
```
|
||||
187
games/NXDoom/Kconfig
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config GAMES_NXDOOM
|
||||
bool "NXDoom"
|
||||
default n
|
||||
depends on ALLOW_GPL_COMPONENTS
|
||||
depends on VIDEO_FB
|
||||
depends on CRYPTO
|
||||
---help---
|
||||
Play DOOM on NuttX!
|
||||
|
||||
if GAMES_NXDOOM
|
||||
|
||||
comment "Program options"
|
||||
|
||||
config GAMES_NXDOOM_PRIORITY
|
||||
int "Priority"
|
||||
default 100
|
||||
---help---
|
||||
The task priority for the NXDoom application.
|
||||
|
||||
config GAMES_NXDOOM_STACKSIZE
|
||||
int "Stack size"
|
||||
default 4096
|
||||
---help---
|
||||
The stack size for the NXDoom application.
|
||||
|
||||
comment "General game options"
|
||||
|
||||
choice # Language
|
||||
prompt "Game language"
|
||||
default GAMES_NXDOOM_LANG_EN
|
||||
|
||||
config GAMES_NXDOOM_LANG_EN
|
||||
bool "English"
|
||||
---help---
|
||||
English language support (original).
|
||||
|
||||
config GAMES_NXDOOM_LANG_FR
|
||||
bool "French"
|
||||
---help---
|
||||
French language support.
|
||||
endchoice # Language
|
||||
|
||||
config GAMES_NXDOOM_PREFDIR
|
||||
string "DOOM data directory"
|
||||
default "/data"
|
||||
---help---
|
||||
Directory where DOOM WAD files are stored.
|
||||
|
||||
config GAMES_NXDOOM_ENDOOM
|
||||
bool "Show ENDOOM"
|
||||
default n
|
||||
---help---
|
||||
Show the ENDOOM screen (https://www.doomwiki.org/wiki/ENDOOM).
|
||||
|
||||
comment "Networking options"
|
||||
|
||||
config GAMES_NXDOOM_NET
|
||||
bool "Enable network features"
|
||||
default n
|
||||
---help---
|
||||
Not ported! Will not work.
|
||||
|
||||
if GAMES_NXDOOM_NET
|
||||
|
||||
config GAMES_NXDOOM_NET_LOGS
|
||||
bool "Enable network logging"
|
||||
default n
|
||||
---help---
|
||||
Enables log information from the network features.
|
||||
|
||||
config GAMES_NXDOOM_NET_MAXPLAYERS
|
||||
int "Maximum number of players"
|
||||
default 6
|
||||
---help---
|
||||
The maximum number of players, multiplayer/networking.
|
||||
This is the maximum supported by the networking code; individual games
|
||||
have their own values for MAXPLAYERS that can be smaller.
|
||||
ChocolateDOOM default was 8.
|
||||
|
||||
config GAMES_NXDOOM_NET_BACKUPTICS
|
||||
int "Maximum number of backup tics"
|
||||
default 32
|
||||
---help---
|
||||
The maximum number of backup tics to store locally during a net game.
|
||||
ChocalateDOOM default was 128.
|
||||
|
||||
config GAMES_NXDOOM_NET_MAXPLAYERNAME
|
||||
int "Maximum player name length"
|
||||
default 16
|
||||
---help---
|
||||
The maximum number of characters in a player name for netgames.
|
||||
ChocalateDOOM default was 30.
|
||||
|
||||
endif # GAMES_NXDOOM_NET
|
||||
|
||||
comment "Sound options"
|
||||
|
||||
config GAMES_NXDOOM_SOUND
|
||||
bool "Enable sound features"
|
||||
default n
|
||||
---help---
|
||||
Not ported! Will not work.
|
||||
|
||||
comment "Graphics options"
|
||||
|
||||
config GAMES_NXDOOM_FBPATH
|
||||
string "Framebuffer path"
|
||||
default "/dev/fb0"
|
||||
---help---
|
||||
Path to the framebuffer character driver to use for rendering.
|
||||
|
||||
comment "Input options"
|
||||
|
||||
choice # Input method
|
||||
prompt "NXDoom input method"
|
||||
default GAMES_NXDOOM_KEYBOARD
|
||||
|
||||
config GAMES_NXDOOM_KEYBOARD
|
||||
bool "Keyboard"
|
||||
---help---
|
||||
Use a NuttX keyboard character driver.
|
||||
|
||||
endchoice # Input method
|
||||
|
||||
if GAMES_NXDOOM_KEYBOARD
|
||||
|
||||
config GAMES_NXDOOM_KBDPATH
|
||||
string "Keyboard device path"
|
||||
default "/dev/kbd0"
|
||||
---help---
|
||||
Path to the keyboard device to use as input.
|
||||
|
||||
endif # GAMES_NXDOOM_KEYBOARD
|
||||
|
||||
comment "Optimizations"
|
||||
|
||||
config GAMES_NXDOOM_MAXVISPLANES
|
||||
int "Maximum number of visplanes"
|
||||
default 96
|
||||
---help---
|
||||
DOOM allocates a static number of 'visplanes' to use for gameplay. The
|
||||
original ChocolateDOOM source uses 128 of these. They take a significant
|
||||
amount of memory, so you may reduce the number. However, too few planes
|
||||
may cause 'visplane overflow' errors, which is more common in complex
|
||||
levels.
|
||||
|
||||
config GAMES_NXDOOM_MAXOPENINGS
|
||||
int "Maximum number of openings"
|
||||
default 32
|
||||
---help---
|
||||
DOOM allocates a static number of 'openings' to use for gameplay. These
|
||||
are defined as multiples of the SCREENWIDTH (320). The original
|
||||
ChocolateDOOM source uses 64 as the multiplier. They take a significant
|
||||
amount of memory, so you may reduce the number. However, too few
|
||||
openings will cause 'opening overflow' errors.
|
||||
|
||||
config GAMES_NXDOOM_MAXVISSPRITES
|
||||
int "Maximum number of visible sprites"
|
||||
default 96
|
||||
---help---
|
||||
DOOM allocates a static number of 'vissprites' to use for gameplay. The
|
||||
original ChocolateDOOM source uses 128. They take a significant amount
|
||||
of memory, so you may reduce the number. However, too few will cause
|
||||
overflow errors.
|
||||
|
||||
config GAMES_NXDOOM_MAXDRAWSEGS
|
||||
int "Maximum number of drawsegs"
|
||||
default 192
|
||||
---help---
|
||||
DOOM allocates a static number of 'drawsegs' to use for gameplay. The
|
||||
original ChocolateDOOM source uses 256. They take a significant amount of
|
||||
memory, so you may reduce the number. However, too few will cause
|
||||
rendering issues (overflow is checked to avoid crashes).
|
||||
|
||||
config GAMES_NXDOOM_RANGECHECK
|
||||
bool "Perform range checks"
|
||||
default y
|
||||
---help---
|
||||
The ChocolateDOOM source includes the ability to optionally exclude
|
||||
range checking on some array operations.
|
||||
|
||||
endif # GAMES_NXDOOM
|
||||
3
games/NXDoom/Make.defs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ifneq ($(CONFIG_GAMES_NXDOOM),)
|
||||
CONFIGURED_APPS += $(APPDIR)/games/NXDoom
|
||||
endif
|
||||
203
games/NXDoom/Makefile
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
include $(APPDIR)/Make.defs
|
||||
|
||||
# Program options
|
||||
|
||||
MODULE = $(CONFIG_GAMES_NXDOOM)
|
||||
PRIORITY = $(CONFIG_GAMES_NXDOOM_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_GAMES_NXDOOM_STACKSIZE)
|
||||
PROGNAME = nxdoom
|
||||
|
||||
# Source files
|
||||
|
||||
COMMONSRCDIR = src
|
||||
TEXTSCREENSRCDIR = textscreen
|
||||
DOOMSRCDIR = $(COMMONSRCDIR)/doom
|
||||
PCSOUNDSRCDIR = pcsound
|
||||
|
||||
# Includes
|
||||
|
||||
CFLAGS += -I$(COMMONSRCDIR) -I$(DOOMSRCDIR) -I$(TEXTSCREENSRCDIR)
|
||||
CFLAGS += -I$(PCSOUNDSRCDIR)
|
||||
|
||||
# Source files
|
||||
|
||||
COMMONSRCS = i_system.c m_argv.c m_misc.c # Excluding i_main.c
|
||||
COMMONSRCS += z_native.c # Native memory allocation
|
||||
|
||||
DEHACKEDSRCS = deh_io.c deh_main.c deh_mapping.c deh_text.c
|
||||
|
||||
BASESRCS = \
|
||||
aes_prng.c \
|
||||
d_event.c \
|
||||
d_iwad.c \
|
||||
d_loop.c \
|
||||
d_mode.c \
|
||||
deh_str.c \
|
||||
gusconf.c \
|
||||
i_glob.c \
|
||||
i_input.c \
|
||||
i_joystick.c \
|
||||
i_timer.c \
|
||||
i_video.c \
|
||||
m_bbox.c \
|
||||
m_cheat.c \
|
||||
m_config.c \
|
||||
m_controls.c \
|
||||
m_fixed.c \
|
||||
p_rejectpad.c \
|
||||
memio.c \
|
||||
tables.c \
|
||||
v_diskicon.c \
|
||||
v_video.c \
|
||||
w_checksum.c \
|
||||
w_main.c \
|
||||
w_wad.c \
|
||||
w_file.c \
|
||||
w_file_stdc.c \
|
||||
w_merge.c \
|
||||
|
||||
# Only add ENDOOM stuff if the user wants it
|
||||
|
||||
ifeq ($(CONFIG_GAMES_NXDOOM_ENDOOM),y)
|
||||
BASESRCS += i_endoom.c
|
||||
endif
|
||||
|
||||
NETSRCS = \
|
||||
net_client.c \
|
||||
net_common.c \
|
||||
net_dedicated.c \
|
||||
net_gui.c \
|
||||
net_io.c \
|
||||
net_loop.c \
|
||||
net_packet.c \
|
||||
net_query.c \
|
||||
net_sdl.c \
|
||||
net_server.c \
|
||||
net_structrw.c \
|
||||
|
||||
DOOMSRCS = \
|
||||
am_map.c \
|
||||
deh_ammo.c \
|
||||
deh_bexstr.c \
|
||||
deh_cheat.c \
|
||||
deh_doom.c \
|
||||
deh_frame.c \
|
||||
deh_misc.c \
|
||||
deh_ptr.c \
|
||||
deh_thing.c \
|
||||
deh_weapon.c \
|
||||
d_items.c \
|
||||
d_main.c \
|
||||
d_net.c \
|
||||
doomdef.c \
|
||||
doomstat.c \
|
||||
dstrings.c \
|
||||
f_finale.c \
|
||||
f_wipe.c \
|
||||
g_game.c \
|
||||
hu_lib.c \
|
||||
hu_stuff.c \
|
||||
info.c \
|
||||
m_menu.c \
|
||||
m_random.c \
|
||||
p_ceilng.c \
|
||||
p_doors.c \
|
||||
p_enemy.c \
|
||||
p_floor.c \
|
||||
p_inter.c \
|
||||
p_lights.c \
|
||||
p_map.c \
|
||||
p_maputl.c \
|
||||
p_mobj.c \
|
||||
p_plats.c \
|
||||
p_pspr.c \
|
||||
p_saveg.c \
|
||||
p_setup.c \
|
||||
p_sight.c \
|
||||
p_spec.c \
|
||||
p_switch.c \
|
||||
p_telept.c \
|
||||
p_tick.c \
|
||||
p_user.c \
|
||||
r_bsp.c \
|
||||
r_data.c \
|
||||
r_draw.c \
|
||||
r_main.c \
|
||||
r_plane.c \
|
||||
r_segs.c \
|
||||
r_sky.c \
|
||||
r_things.c \
|
||||
statdump.c \
|
||||
st_lib.c \
|
||||
st_stuff.c \
|
||||
wi_stuff.c
|
||||
|
||||
TXTSCREENSRCS = \
|
||||
txt_conditional.c \
|
||||
txt_checkbox.c \
|
||||
txt_desktop.c \
|
||||
txt_dropdown.c \
|
||||
txt_fileselect.c \
|
||||
txt_gui.c \
|
||||
txt_inputbox.c \
|
||||
txt_io.c \
|
||||
txt_button.c \
|
||||
txt_label.c \
|
||||
txt_radiobutton.c \
|
||||
txt_scrollpane.c \
|
||||
txt_separator.c \
|
||||
txt_spinctrl.c \
|
||||
txt_sdl.c \
|
||||
txt_strut.c \
|
||||
txt_table.c \
|
||||
txt_utf8.c \
|
||||
txt_widget.c \
|
||||
txt_window.c \
|
||||
txt_window_action.c
|
||||
|
||||
CSRCS += $(patsubst %,$(COMMONSRCDIR)/%,$(COMMONSRCS))
|
||||
CSRCS += $(patsubst %,$(COMMONSRCDIR)/%,$(DEHACKEDSRCS))
|
||||
CSRCS += $(patsubst %,$(COMMONSRCDIR)/%,$(BASESRCS))
|
||||
CSRCS += $(patsubst %,$(DOOMSRCDIR)/%,$(DOOMSRCS))
|
||||
|
||||
# Textscreen stuff only needs to be included for networking stuff
|
||||
# or if the user wants to see ENDOOM
|
||||
|
||||
ifeq ($(CONFIG_GAMES_NXDOOM_ENDOOM),y)
|
||||
ADDTXTSCREEN = y
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_GAMES_NXDOOM_NET),y)
|
||||
ADDTXTSCREEN = y
|
||||
endif
|
||||
|
||||
# Only include textscreen code if needed
|
||||
|
||||
ifeq ($(ADDTXTSCREEN),y)
|
||||
CSRCS += $(patsubst %,$(TEXTSCREENSRCDIR)/%,$(TXTSCREENSRCS))
|
||||
endif
|
||||
|
||||
# Only include networking logic if enabled
|
||||
|
||||
ifeq ($(CONFIG_GAMES_NXDOOM_NET),y)
|
||||
CSRCS += $(patsubst %,$(COMMONSRCDIR)/%,$(NETSRCS))
|
||||
endif
|
||||
|
||||
# Only include sound logic if enabled
|
||||
|
||||
ifeq ($(CONFIG_GAMES_NXDOOM_SOUND),y)
|
||||
CSRCS += $(COMMONSRCDIR)/i_musicpack.c
|
||||
CSRCS += $(COMMONSRCDIR)/i_pcsound.c
|
||||
CSRCS += $(COMMONSRCDIR)/i_sdlmusic.c
|
||||
CSRCS += $(COMMONSRCDIR)/i_sound.c
|
||||
CSRCS += $(COMMONSRCDIR)/midifile.c
|
||||
CSRCS += $(COMMONSRCDIR)/mus2mid.c
|
||||
|
||||
CSRCS += $(DOOMSRCDIR)/sounds.c
|
||||
CSRCS += $(DOOMSRCDIR)/s_sound.c
|
||||
CSRCS += $(DOOMSRCDIR)/deh_sound.c
|
||||
endif
|
||||
|
||||
MAINSRC = $(COMMONSRCDIR)/i_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
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
|
|
@ -1,149 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,214 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
````````````````````````````````````````````````````````````````````````
|
||||
|
||||
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.
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
# 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.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
## 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).
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
autoreconf -fi
|
||||
./configure "$@"
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/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
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# 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()
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#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
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
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
|
|
@ -1,7 +0,0 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
*-doom.png
|
||||
*-heretic.png
|
||||
*-hexen.png
|
||||
*-setup.png
|
||||
*-strife.png
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
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)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
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.
|
||||
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#!/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])
|
||||
|
||||
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
16
games/NXDoom/man/.gitignore
vendored
|
|
@ -1,16 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
== 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
|
||||
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# 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
|
||||
|
||||
|
|
@ -1,316 +0,0 @@
|
|||
#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
|
||||
|
|
@ -1,226 +0,0 @@
|
|||
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
|
|
@ -1,5 +0,0 @@
|
|||
*doom
|
||||
*heretic
|
||||
*hexen
|
||||
*strife
|
||||
*.template
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
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
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# 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
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
.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)
|
||||
|
|
@ -1,624 +0,0 @@
|
|||
#!/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)
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
.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)
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
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.
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
#!/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)
|
||||
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
.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.
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
# 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
|
|
@ -1,7 +0,0 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
libopl.a
|
||||
*.rc
|
||||
tags
|
||||
TAGS
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
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()
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
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
|
|
@ -1,7 +0,0 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
droplay
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
AM_CFLAGS = -I$(top_srcdir)/opl
|
||||
|
||||
noinst_PROGRAMS=droplay
|
||||
|
||||
droplay_LDADD = ../libopl.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@
|
||||
droplay_SOURCES = droplay.c
|
||||
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
@ -1,355 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,530 +0,0 @@
|
|||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// 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) */
|
||||
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,521 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -1,250 +0,0 @@
|
|||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
//
|
||||
// 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 */
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
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()
|
||||