Merge from raven-branch.
Subversion-branch: /branches/strife-branch Subversion-revision: 2051
This commit is contained in:
commit
120d90c67b
149 changed files with 13155 additions and 1725 deletions
19
.gitignore
vendored
19
.gitignore
vendored
|
|
@ -1,24 +1,21 @@
|
|||
CMDLINE
|
||||
INSTALL
|
||||
Makefile
|
||||
Makefile.in
|
||||
TAGS
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
Makefile
|
||||
INSTALL
|
||||
CMDLINE
|
||||
autotools
|
||||
bin
|
||||
config.h
|
||||
aclocal.m4
|
||||
configure
|
||||
config.hin
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
lib
|
||||
obj
|
||||
config.h
|
||||
autom4te.cache
|
||||
rpm.spec
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
stamp-h1
|
||||
tags
|
||||
TAGS
|
||||
|
||||
# These are the default patterns globally ignored by Subversion:
|
||||
*.o
|
||||
|
|
|
|||
3
.lvimrc
3
.lvimrc
|
|
@ -16,8 +16,9 @@ set tags+=tags
|
|||
let tagfiles = findfile("tags", ".;", -1)
|
||||
|
||||
" Add tag files for libraries:
|
||||
call add(tagfiles, topdir . "textscreen/tags")
|
||||
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:
|
||||
|
|
|
|||
15
BUGS
15
BUGS
|
|
@ -6,21 +6,6 @@
|
|||
effects are cut off at the wrong distance. This needs further
|
||||
investigation.
|
||||
|
||||
* Music plays back differently.
|
||||
|
||||
Vanilla Doom was typically played with a SoundBlaster (or compatible)
|
||||
card. It programmed the registers for the OPL music chip directly
|
||||
in order to emulate the various General MIDI instruments. However,
|
||||
Chocolate Doom uses the OS's native MIDI playback interfaces to play
|
||||
MIDI sound. As the OPL is programmed differently, the music sounds
|
||||
different to the original, even when using an original SoundBlaster
|
||||
card.
|
||||
|
||||
This can be worked around in the future: OPL emulation code exists that
|
||||
simulates an OPL chip in software. Furthermore, depending on the OS,
|
||||
it may be possible to program the OPL directly in order to get the
|
||||
same sound.
|
||||
|
||||
* A small number of Doom bugs are almost impossible to emulate.
|
||||
|
||||
An example of this can be seen in Ledmeister's "Blackbug" demo which
|
||||
|
|
|
|||
887
ChangeLog
887
ChangeLog
|
|
@ -1,3 +1,890 @@
|
|||
2010-05-30 04:03:44 fraggle
|
||||
|
||||
Add INSTALL to all distribution packages, add note in README.
|
||||
|
||||
2010-05-30 03:56:58 fraggle
|
||||
|
||||
Clarify/update install instructions.
|
||||
|
||||
2010-05-14 19:42:32 fraggle
|
||||
|
||||
Don't grab the mouse when the demo sequence advances.
|
||||
|
||||
2010-05-03 17:47:25 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2010-05-03 16:58:52 fraggle
|
||||
|
||||
Update NEWS.
|
||||
|
||||
2010-05-01 22:47:26 fraggle
|
||||
|
||||
Further sanity checking on use of strcpy() with dehacked string
|
||||
replacements.
|
||||
|
||||
2010-05-01 22:20:30 fraggle
|
||||
|
||||
Silence printf(DEH_String(...)) warnings, by providing a DEH_printf
|
||||
function that checks the format string is a valid replacement. Also
|
||||
add DEH_fprintf and DEH_snprintf functions to use throughout the code
|
||||
to do similar checking.
|
||||
|
||||
2010-05-01 20:22:52 fraggle
|
||||
|
||||
Fix compiler warnings with savegame and response file code.
|
||||
|
||||
2010-04-30 20:58:30 fraggle
|
||||
|
||||
Merge contents of OPL-TODO into TODO file.
|
||||
|
||||
2010-04-30 20:38:24 fraggle
|
||||
|
||||
Add textscreen Doxyfile to dist. Add .desktop file to svn:ignore. Add
|
||||
opl ctags file to localvimrc.
|
||||
|
||||
2010-04-25 00:53:03 fraggle
|
||||
|
||||
Add -reject_pad_with_ff parameter to allow padding value to be
|
||||
specified.
|
||||
|
||||
2010-04-23 21:46:29 fraggle
|
||||
|
||||
Add REJECT buffer overflow emulation, based on code from PrBoom+
|
||||
(thanks entryway). Fixes YDFEAR25.LMP.
|
||||
|
||||
2010-04-22 22:38:51 fraggle
|
||||
|
||||
Disable OPL debugging messages.
|
||||
|
||||
2010-03-08 18:52:59 fraggle
|
||||
|
||||
Add OPL-TODO to dist, set svn:ignore properties.
|
||||
|
||||
2010-03-08 18:50:29 fraggle
|
||||
|
||||
Use native MIDI music by default.
|
||||
|
||||
2010-03-08 01:14:23 fraggle
|
||||
|
||||
Merge opl-branch to trunk.
|
||||
|
||||
OPL support still isn't perfect, and it certainly isn't complete.
|
||||
However, for now, it's good enough.
|
||||
|
||||
2010-02-10 20:21:21 fraggle
|
||||
|
||||
Bump version number, update ChangeLog and NEWS.
|
||||
|
||||
2010-01-31 18:21:50 fraggle
|
||||
|
||||
Change Windows resource file to use PACKAGE_COPYRIGHT and
|
||||
PACKAGE_LICENSE macros.
|
||||
|
||||
2010-01-30 16:14:04 fraggle
|
||||
|
||||
Change directory to home directory before launching the game, so that
|
||||
recorded demos go somewhere sensible.
|
||||
|
||||
2010-01-30 16:04:24 fraggle
|
||||
|
||||
Set launch button as default button, so that it is possible to launch
|
||||
the game by pressing return.
|
||||
|
||||
2010-01-30 00:37:17 fraggle
|
||||
|
||||
Rename mus2mid functions to be consistent with coding standard.
|
||||
|
||||
2010-01-29 23:28:35 fraggle
|
||||
|
||||
Remove unused PACKAGE_LONGDESC.
|
||||
|
||||
2010-01-29 19:17:56 fraggle
|
||||
|
||||
When doing a MUS to MID conversion, allocate MIDI channels so that the
|
||||
lowest-numbered MIDI channels are used before higher-numbered ones.
|
||||
Fixes ear-piercing whistle sound in the MAP05 music when playing with
|
||||
timidity and EAWPATS (thanks entryway / HackNeyed).
|
||||
|
||||
2010-01-29 03:55:20 fraggle
|
||||
|
||||
Fix indentation/style etc. in mus2mid.c.
|
||||
|
||||
2010-01-27 19:16:26 fraggle
|
||||
|
||||
Add tags files to svn:ignore properties.
|
||||
|
||||
2010-01-26 19:21:18 fraggle
|
||||
|
||||
Minor fix of British spelling -> American.
|
||||
|
||||
2010-01-26 19:18:18 fraggle
|
||||
|
||||
Fix glass hack windows where a linedef is flagged as two sided but has
|
||||
only one side. Fixes WADs such as OTTAWAU.WAD (thanks Never_Again).
|
||||
|
||||
2010-01-23 23:06:45 fraggle
|
||||
|
||||
Add menu item to launcher to open a terminal window that can be used
|
||||
to start the game. Add missing 'edit' menu. Set svn:ignore property
|
||||
for osx directory.
|
||||
|
||||
2010-01-18 19:40:50 fraggle
|
||||
|
||||
Fix package source URL.
|
||||
|
||||
2010-01-18 19:29:48 fraggle
|
||||
|
||||
Tweak package description slightly.
|
||||
|
||||
2010-01-18 19:14:54 fraggle
|
||||
|
||||
Define project short description, copyright, maintainer and URL in
|
||||
configure.in. Use these for the Info-gnustep.plist file. Add
|
||||
generated .spec file for building RPM packages.
|
||||
|
||||
2010-01-17 16:58:37 fraggle
|
||||
|
||||
Update NEWS.
|
||||
|
||||
2010-01-17 16:31:03 fraggle
|
||||
|
||||
Restore the original cursor when shutting down video code, this should
|
||||
hopefully fix the problem with the mouse cursor disappearing when
|
||||
exiting on Win9x (thanks Janizdreg).
|
||||
|
||||
2010-01-16 19:20:11 fraggle
|
||||
|
||||
Update TODO file.
|
||||
|
||||
2010-01-15 19:29:28 fraggle
|
||||
|
||||
Don't open the configuration window when the launcher is first run;
|
||||
display an error message if the user tries to launch the game without
|
||||
an IWAD selected.
|
||||
|
||||
2010-01-15 19:14:02 fraggle
|
||||
|
||||
Fix GNUstep info panel.
|
||||
|
||||
2010-01-15 18:51:35 fraggle
|
||||
|
||||
Center the launcher window and config window on startup.
|
||||
|
||||
2010-01-15 18:40:37 fraggle
|
||||
|
||||
Add wadfile.png for GNUstep build.
|
||||
|
||||
2010-01-15 18:13:05 fraggle
|
||||
|
||||
Extend osx makefile to allow building of a working GNUstep
|
||||
application, for testing purposes. Add GNUstep version of Info.plist,
|
||||
remove app-skeleton directory and move contents up.
|
||||
|
||||
2010-01-14 18:47:03 fraggle
|
||||
|
||||
In Chex Quest, use the radiation suit colormap instead of the red
|
||||
colormaps that are usually used when taking damage (or using the
|
||||
berserk pack). This matches the Vanilla chex.exe behavior (thanks
|
||||
Fuzztooth).
|
||||
|
||||
2010-01-12 20:16:25 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2010-01-12 20:15:34 fraggle
|
||||
|
||||
Strip executables when building Windows CE packages.
|
||||
|
||||
2010-01-12 20:14:11 fraggle
|
||||
|
||||
Rearrange order of Makefile generation to alphabetical order.
|
||||
|
||||
2010-01-12 20:12:56 fraggle
|
||||
|
||||
Move Makefile definitions for CC and STRIP into config.make, use
|
||||
versions from autoconf.
|
||||
|
||||
2010-01-12 20:09:54 fraggle
|
||||
|
||||
Set main menu title based on package name, not fixed string.
|
||||
|
||||
2010-01-12 20:09:01 fraggle
|
||||
|
||||
Place commercial level name strings consecutively in the same array,
|
||||
so that overflowing the end of one list accesses the start of the
|
||||
next. This trick is used by pl2.wad for its MAP33 secret level.
|
||||
|
||||
2010-01-12 01:32:24 fraggle
|
||||
|
||||
Add missing connection for plutonia.wad set button.
|
||||
|
||||
2010-01-12 01:20:48 fraggle
|
||||
|
||||
Add document icon file and use for file associations.
|
||||
|
||||
2010-01-11 19:10:42 fraggle
|
||||
|
||||
Insert new files into the command line at the correct location,
|
||||
allowing multiple files to be opened at once.
|
||||
|
||||
2010-01-11 01:35:04 fraggle
|
||||
|
||||
When launching a file from the finder, add the new file into the
|
||||
command line at the appropriate position in the command line string.
|
||||
|
||||
2010-01-10 20:46:15 fraggle
|
||||
|
||||
Change "@executable_path@" to "@executable_path"
|
||||
|
||||
2010-01-10 18:48:21 fraggle
|
||||
|
||||
Install docs with a single cp, rather than using a for loop.
|
||||
|
||||
2010-01-10 18:42:35 fraggle
|
||||
|
||||
Recursively copy library dependencies into destination package.
|
||||
Identify libraries to be installed based on the path in which they are
|
||||
located, rather than whether there is "libSDL" in the name. Use
|
||||
install_name_tool to change the search path so that the system looks
|
||||
for libraries in @executable_path@ rather than their location on the
|
||||
machine upon which the program was built.
|
||||
|
||||
2010-01-09 21:06:31 fraggle
|
||||
|
||||
Clear existing arguments when adding a file.
|
||||
|
||||
2010-01-09 20:42:30 fraggle
|
||||
|
||||
Add file to command line when opened; add link from AppController to
|
||||
LauncherManager.
|
||||
|
||||
2010-01-09 18:54:04 fraggle
|
||||
|
||||
Initial code to identify file type by extension and add file to
|
||||
command line.
|
||||
|
||||
2010-01-09 18:38:48 fraggle
|
||||
|
||||
Hook in AppController as delegate for application, add file
|
||||
associations to property list file.
|
||||
|
||||
2010-01-05 17:20:58 fraggle
|
||||
|
||||
Add "clean" target to package makefiles.
|
||||
|
||||
2010-01-05 15:52:12 fraggle
|
||||
|
||||
Move config.make up to pkg/ directory. Use static makefiles to
|
||||
generate all packages, rather than dynamically generated makefiles.
|
||||
Add pkg/osx to dist. Make OS X staging directory depend on top level
|
||||
documentation files. Generate CMDLINE as part of standard build if it
|
||||
is not already present. Set svn:ignore properties.
|
||||
|
||||
2010-01-04 22:53:44 fraggle
|
||||
|
||||
Fix single space error when listing libraries.
|
||||
|
||||
2010-01-04 22:45:45 fraggle
|
||||
|
||||
Copy binaries into app dir along with libraries.
|
||||
|
||||
2010-01-04 22:24:48 fraggle
|
||||
|
||||
Include documentation files in package.
|
||||
|
||||
2010-01-04 22:19:53 fraggle
|
||||
|
||||
Fix GNUstep build.
|
||||
|
||||
2010-01-04 22:11:11 fraggle
|
||||
|
||||
Generate Info.plist and config.make in configure and remove temporary
|
||||
versions. Include config.h from top level.
|
||||
|
||||
2010-01-04 22:01:32 fraggle
|
||||
|
||||
Import OS X launcher code to trunk.
|
||||
|
||||
2010-01-03 03:49:11 fraggle
|
||||
|
||||
Add quotes around $@ in autogen script (thanks exp[x])
|
||||
|
||||
2009-12-28 20:57:20 fraggle
|
||||
|
||||
When recording low resolution (non-longtics) Vanilla demos, carry
|
||||
forward the error from angleturn caused by the reduced resolution, so
|
||||
that consecutive errors can accumulate, possibly making turning
|
||||
slightly smoother.
|
||||
|
||||
2009-12-27 01:42:13 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2009-12-27 00:11:18 fraggle
|
||||
|
||||
Allow DOOMWADDIR/DOOMWADPATH to contain the complete path to IWAD
|
||||
files, as well as directories in which to search for IWAD files.
|
||||
|
||||
2009-12-18 22:11:06 fraggle
|
||||
|
||||
Fix poor quality application icons seen when the game is running. Add
|
||||
back 8-bit icon files alongside files including both 8-bit and high
|
||||
quality 32-bit versions. Use the high quality icon files for resource
|
||||
files includes, and the low quality ones for in-game SDL.
|
||||
|
||||
2009-12-18 21:11:32 fraggle
|
||||
|
||||
Update generated source files containing icon data.
|
||||
|
||||
2009-12-18 21:10:35 fraggle
|
||||
|
||||
Make ExecuteCommand() under Unix return a failure when the executable
|
||||
cannot be executed.
|
||||
|
||||
2009-12-14 20:57:04 fraggle
|
||||
|
||||
Use GetModuleFileNameW to get the (Unicode) path to the Doom
|
||||
executable. This hopefully fixes problems with Unicode directory
|
||||
names.
|
||||
|
||||
2009-12-14 18:54:25 fraggle
|
||||
|
||||
Add Chocolate Doom/setup icons with scaled versions for various
|
||||
different icon sizes (thanks MikeRS).
|
||||
|
||||
2009-12-12 01:20:49 fraggle
|
||||
|
||||
Fix textscreen black border bug.
|
||||
|
||||
2009-12-09 02:40:39 fraggle
|
||||
|
||||
Fix the setup tool on Windows Vista/7 to not prompt for elevated
|
||||
permissions and to disable the "Program Compatibility Assistant"
|
||||
(thanks hobbs and MikeRS).
|
||||
|
||||
2009-11-29 22:50:17 fraggle
|
||||
|
||||
Add other missing files to dist.
|
||||
|
||||
2009-11-29 22:25:51 fraggle
|
||||
|
||||
Include .lvimrc in dist.
|
||||
|
||||
2009-11-21 03:56:59 fraggle
|
||||
|
||||
Add Makefile to build Win32 packages.
|
||||
|
||||
2009-11-21 02:05:56 fraggle
|
||||
|
||||
Use execvp() rather than execv(), to look up Doom binary in the PATH
|
||||
if necessary.
|
||||
|
||||
2009-11-21 00:40:58 fraggle
|
||||
|
||||
Apply configuration file invalid key setting fix to setup code.
|
||||
|
||||
2009-11-21 00:38:16 fraggle
|
||||
|
||||
Don't crash if key settings are set in a configuration file that are
|
||||
out of range (thanks entryway).
|
||||
|
||||
2009-11-21 00:24:59 fraggle
|
||||
|
||||
Fix crash with chocolate-setup under Windows (thanks Janizdreg).
|
||||
|
||||
2009-11-19 21:49:13 fraggle
|
||||
|
||||
Rework the OS X MIDI disabling code, as SDL_mixer 1.2.11 fixes the
|
||||
crash. Check and disable MIDI by default if using an older version of
|
||||
SDL on OS X.
|
||||
|
||||
2009-11-19 21:07:31 fraggle
|
||||
|
||||
Make chocolate-setup use its own location in the filesystem to find
|
||||
the location of the chocolate-doom executable. Remove INSTALL_DIR
|
||||
define.
|
||||
|
||||
2009-11-05 19:57:55 fraggle
|
||||
|
||||
Perform bounds checking on values passed to TXT_UpdateScreenArea() to
|
||||
avoid crashes.
|
||||
|
||||
2009-10-26 19:28:12 fraggle
|
||||
|
||||
Initial hacks for compiling under SDL 1.3.
|
||||
|
||||
2009-10-17 21:13:54 fraggle
|
||||
|
||||
Fix error in last change.
|
||||
|
||||
2009-10-17 20:39:37 fraggle
|
||||
|
||||
Use M_StrToInt() when processing values passed with -spechit, so that
|
||||
hex values can be specified.
|
||||
|
||||
2009-10-17 20:29:46 fraggle
|
||||
|
||||
Import donut overrun emulation code from PrBoom+ (Thanks entryway).
|
||||
|
||||
2009-10-16 19:10:30 fraggle
|
||||
|
||||
Fix compilation under MSVC (thanks entryway).
|
||||
|
||||
2009-10-10 23:58:25 fraggle
|
||||
|
||||
Rename pkg/wince/Makefile to pkg/wince/GNUmakefile (it uses GNU
|
||||
extensions).
|
||||
|
||||
2009-10-10 22:46:14 fraggle
|
||||
|
||||
Add pkg directory to make dist.
|
||||
|
||||
2009-10-10 02:02:58 fraggle
|
||||
|
||||
Don't crash when using the donut special type and the joining linedef
|
||||
is one sided (thanks Alexander Waldmann).
|
||||
|
||||
2009-10-05 21:25:53 fraggle
|
||||
|
||||
Fix desync in ep1-0500.lmp on 64-bit (thanks exp(x)).
|
||||
|
||||
2009-10-05 00:38:14 fraggle
|
||||
|
||||
Provide pointer to STARTUPINFO structure when calling CreateProcessW,
|
||||
to stop crash under normal Windows (not CE) when launching Doom from
|
||||
the setup tools (thanks Janizdreg).
|
||||
|
||||
2009-10-01 20:08:21 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2009-10-01 02:04:00 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2009-10-01 00:07:03 fraggle
|
||||
|
||||
Change British English spellings to American English, for consistency.
|
||||
|
||||
2009-09-20 16:27:40 fraggle
|
||||
|
||||
Use "const char" in libtextscreen where appropriate (thanks entryway).
|
||||
|
||||
2009-09-11 22:56:47 fraggle
|
||||
|
||||
Add (lack of) copyright notice for SDL workaround.
|
||||
|
||||
2009-09-07 20:43:04 fraggle
|
||||
|
||||
Fix compilation under MacOS X.
|
||||
|
||||
2009-09-06 19:15:52 fraggle
|
||||
|
||||
Fixes for MSVC compile (thanks entryway).
|
||||
|
||||
2009-08-28 00:27:47 fraggle
|
||||
|
||||
Allow PGUP/PGDN to scroll up and down in scroll panes (thanks
|
||||
LionsPhil).
|
||||
|
||||
2009-07-20 23:27:59 fraggle
|
||||
|
||||
Remove redundant variable assignment (thanks Quasar/Yagisan)
|
||||
|
||||
2009-07-20 01:37:41 fraggle
|
||||
|
||||
Save and display the loading disk icon as a fixed 16x16 square, from
|
||||
an image drawn at the bottom right corner of the screen. This seems
|
||||
to be the same as how Vanilla behaves, and fixes chook3.wad, that uses
|
||||
an STDISK replacement with an offset that pushes the image to the
|
||||
left.
|
||||
|
||||
2009-07-13 23:43:06 fraggle
|
||||
|
||||
Add stdio.h include to fix MSVC build (thanks Kaiser)
|
||||
|
||||
2009-07-12 17:47:12 fraggle
|
||||
|
||||
Fix compile with libsamplerate.
|
||||
|
||||
2009-07-12 15:00:50 fraggle
|
||||
|
||||
On Windows CE, use the Windows API to find the amount of available
|
||||
memory, so that at least two megabytes are always left available to
|
||||
the OS.
|
||||
|
||||
2009-07-11 12:15:32 fraggle
|
||||
|
||||
Add missing item to NEWS.
|
||||
|
||||
2009-07-07 20:46:55 fraggle
|
||||
|
||||
Update NEWS.
|
||||
|
||||
2009-07-07 20:38:00 fraggle
|
||||
|
||||
Fix launching of the game from the setup tool in Windows CE.
|
||||
|
||||
2009-06-21 20:33:35 fraggle
|
||||
|
||||
Add Makefile for building CAB files, dependency calculation.
|
||||
|
||||
2009-06-21 20:19:43 fraggle
|
||||
|
||||
Use correct filename for SDL_net DLL.
|
||||
|
||||
2009-06-21 20:03:38 fraggle
|
||||
|
||||
Remove temporary files after generating CAB file.
|
||||
|
||||
2009-06-20 23:13:44 fraggle
|
||||
|
||||
Add script to generate Windows CE install package.
|
||||
|
||||
2009-06-16 20:47:13 fraggle
|
||||
|
||||
Automatically allocate a smaller zone size if it was not possible to
|
||||
allocate the default 16 MiB.
|
||||
|
||||
2009-06-13 18:10:18 fraggle
|
||||
|
||||
Don't post zero key events.
|
||||
|
||||
2009-06-12 20:07:55 fraggle
|
||||
|
||||
On Windows CE systems without a keyboard, patch the default settings
|
||||
to use hardware keys.
|
||||
|
||||
2009-06-12 18:58:42 fraggle
|
||||
|
||||
Remove debug messages.
|
||||
|
||||
2009-06-12 18:35:39 fraggle
|
||||
|
||||
Set the USER environment variable based on the owner information from
|
||||
the registry.
|
||||
|
||||
2009-06-12 18:34:27 fraggle
|
||||
|
||||
Always grab input on Windows CE.
|
||||
|
||||
2009-06-11 22:34:36 fraggle
|
||||
|
||||
Include libc_wince.a in chocolate-server build.
|
||||
|
||||
2009-06-11 20:41:20 fraggle
|
||||
|
||||
Grab the input in setup when reading a new key binding, so that
|
||||
Windows CE buttons are read properly. Map buttons to PC function
|
||||
keys.
|
||||
|
||||
2009-06-11 19:19:05 fraggle
|
||||
|
||||
Include libc_wince.h on Windows CE.
|
||||
|
||||
2009-06-11 19:18:12 fraggle
|
||||
|
||||
Declare getenv/putenv on Windows CE for recent SDL versions that do
|
||||
not declare it.
|
||||
|
||||
2009-06-10 20:03:08 fraggle
|
||||
|
||||
Add key bindings for pause, message refresh.
|
||||
|
||||
2009-06-08 20:26:29 fraggle
|
||||
|
||||
Remove debugging code.
|
||||
|
||||
2009-06-08 19:15:57 fraggle
|
||||
|
||||
Use SDL's getenv/putenv implementation, and populate at startup.
|
||||
|
||||
2009-06-08 00:41:10 fraggle
|
||||
|
||||
Use CreateFileW instead of OpenFile (doesn't exist on Windows CE)
|
||||
|
||||
2009-06-07 20:08:08 fraggle
|
||||
|
||||
Fix header includes (thanks exp[x])
|
||||
|
||||
2009-06-07 19:18:02 fraggle
|
||||
|
||||
Don't add DirectX/Windib selector on Windows CE.
|
||||
|
||||
2009-06-07 18:53:25 fraggle
|
||||
|
||||
Use home dir to store configuration and savegames under Windows CE.
|
||||
|
||||
2009-06-07 18:33:19 fraggle
|
||||
|
||||
Fix setup tool display configuration dialog when fullscreen is not
|
||||
supported.
|
||||
|
||||
2009-06-07 18:10:05 fraggle
|
||||
|
||||
Make auto-adjust code switch to windowed mode if no fullscreen modes
|
||||
are available.
|
||||
|
||||
2009-06-07 17:41:46 fraggle
|
||||
|
||||
Catch errors when initialising SDL. Use the small textscreen font by
|
||||
default on Windows CE if no fullscreen modes are available.
|
||||
|
||||
2009-06-07 17:39:08 fraggle
|
||||
|
||||
Add missing SDL_thread include.
|
||||
|
||||
2009-06-07 17:35:43 fraggle
|
||||
|
||||
Don't try to use the SDL DirectX driver under Windows CE.
|
||||
|
||||
2009-06-07 16:21:41 fraggle
|
||||
|
||||
Fix setup tool compile on Windows CE.
|
||||
|
||||
2009-06-07 16:15:40 fraggle
|
||||
|
||||
Remove call to setbuf.
|
||||
|
||||
2009-06-07 15:35:27 fraggle
|
||||
|
||||
Add IWAD search dirs for Windows CE.
|
||||
|
||||
2009-06-07 15:20:46 fraggle
|
||||
|
||||
Exit with an error on failure to allocate zone memory.
|
||||
|
||||
2009-06-07 03:10:21 fraggle
|
||||
|
||||
Use MessageBoxW instead of MessageBox (doesn't exist on Windows CE)
|
||||
|
||||
2009-06-07 02:59:49 fraggle
|
||||
|
||||
Add README file for Windows CE library.
|
||||
|
||||
2009-06-07 02:56:21 fraggle
|
||||
|
||||
Detect Windows CE target and build/include libc_wince files as
|
||||
necessary.
|
||||
|
||||
2009-06-07 02:50:47 rtc_marine
|
||||
|
||||
- Update textscreen codeblocks project to include txt_scrollpane.* and
|
||||
txt_smallfont.h
|
||||
|
||||
2009-06-07 02:33:58 fraggle
|
||||
|
||||
Include libc_wince.h when on Windows CE.
|
||||
|
||||
2009-06-07 02:32:15 fraggle
|
||||
|
||||
Add CPU affinity function for Windows CE.
|
||||
|
||||
2009-06-07 02:27:58 fraggle
|
||||
|
||||
Add libc_wince.h header, and EISDIR error value.
|
||||
|
||||
2009-06-07 02:27:30 fraggle
|
||||
|
||||
Use GetUserNameExW, not GetUserName (doesn't exist on WinCE)
|
||||
|
||||
2009-06-07 02:26:45 fraggle
|
||||
|
||||
Fix compile with FEATURE_MULTIPLAYER disabled.
|
||||
|
||||
2009-06-07 02:24:40 fraggle
|
||||
|
||||
Fix compile with FEATURE_SOUND disabled.
|
||||
|
||||
2009-06-07 01:56:23 fraggle
|
||||
|
||||
Add Windows CE implementations of some ANSI C functions that are
|
||||
missing.
|
||||
|
||||
2009-06-06 22:13:44 fraggle
|
||||
|
||||
Don't check for Steam/CD installer versions on Windows CE.
|
||||
|
||||
2009-06-05 17:58:48 fraggle
|
||||
|
||||
Add key binding variables for automap and weapon keys.
|
||||
|
||||
2009-06-04 00:37:02 fraggle
|
||||
|
||||
Increase height of menu bindings dialog.
|
||||
|
||||
2009-06-04 00:35:05 fraggle
|
||||
|
||||
Use newer keyboard bindings dialog layout from raven-branch.
|
||||
|
||||
2009-06-04 00:20:37 fraggle
|
||||
|
||||
Add unique key groups for menu navigation and shortcuts.
|
||||
|
||||
2009-06-04 00:20:06 fraggle
|
||||
|
||||
Use key for confirming menu messages, not typed char.
|
||||
|
||||
2009-06-03 21:45:54 fraggle
|
||||
|
||||
Add dialog to setup tool for editing menu shortcuts.
|
||||
|
||||
2009-06-03 21:18:04 fraggle
|
||||
|
||||
Add config file variables to increase/decrease screen size.
|
||||
|
||||
2009-06-03 20:59:26 fraggle
|
||||
|
||||
Fix shortcut keys for menu items.
|
||||
|
||||
2009-06-03 20:55:50 fraggle
|
||||
|
||||
Add configuration file entries for menu key bindings.
|
||||
|
||||
2009-06-03 20:37:19 fraggle
|
||||
|
||||
Add key_ variables for the keys used to control the menu.
|
||||
|
||||
2009-05-26 23:14:24 fraggle
|
||||
|
||||
Fix tags for functions using TXT_UNCAST_ARG.
|
||||
|
||||
2009-05-26 22:13:18 fraggle
|
||||
|
||||
Set appropriate vim 'tags' variable for ctags files.
|
||||
|
||||
2009-05-21 20:18:38 fraggle
|
||||
|
||||
Set display settings window position based on screen dimensions,
|
||||
rather than hard coding position.
|
||||
|
||||
2009-05-19 18:07:49 fraggle
|
||||
|
||||
Fix manpage documentation for DOOMWADPATH (thanks MikeRS)
|
||||
|
||||
2009-05-18 19:30:49 fraggle
|
||||
|
||||
Fix A_BossDeath behavior in v1.9 emulation mode (thanks entryway)
|
||||
|
||||
2009-05-17 14:54:19 fraggle
|
||||
|
||||
Always use an SDL buffer size that is a power of two. Reduce buffer
|
||||
size to 70ms.
|
||||
|
||||
2009-05-12 19:03:20 fraggle
|
||||
|
||||
Add option to "join game" dialog in setup tool to autojoin a LAN game.
|
||||
|
||||
2009-05-12 19:01:27 fraggle
|
||||
|
||||
Make txt_inputboxes emit a "changed" signal when their value is
|
||||
changed.
|
||||
|
||||
2009-05-07 22:59:38 fraggle
|
||||
|
||||
Calculate SDL buffer size automatically based on sample rate.
|
||||
|
||||
2009-05-05 01:00:53 fraggle
|
||||
|
||||
Better ASCII chart.
|
||||
|
||||
2009-05-05 00:46:27 fraggle
|
||||
|
||||
Minor smallfont fixups.
|
||||
|
||||
2009-05-01 22:05:57 fraggle
|
||||
|
||||
Add copyright headers to textscreen examples.
|
||||
|
||||
2009-04-26 17:59:08 fraggle
|
||||
|
||||
More smallfont fixups.
|
||||
|
||||
2009-04-23 20:58:11 fraggle
|
||||
|
||||
Fix up some extended ASCII characters.
|
||||
|
||||
2009-04-23 19:19:52 fraggle
|
||||
|
||||
Oops.
|
||||
|
||||
2009-04-23 19:18:43 fraggle
|
||||
|
||||
Add small textscreen font for low resolution displays, based on the
|
||||
Atari-Small font by Tom Fine.
|
||||
|
||||
2009-03-15 14:44:23 fraggle
|
||||
|
||||
Fix clipped sounds when using libsamplerate (thanks David Flater)
|
||||
|
||||
2009-03-14 15:28:41 fraggle
|
||||
|
||||
Add check to allow sched_setaffinity code to work on older versions of
|
||||
libc.
|
||||
|
||||
2009-03-12 18:55:27 fraggle
|
||||
|
||||
Define INVALID_SET_FILE_POINTER if it is not defined, to fix
|
||||
compilation under MSVC6 (thanks Quasar)
|
||||
|
||||
2009-03-08 22:51:25 fraggle
|
||||
|
||||
Add "make doc" target to run Doxygen, and add a Doxyfile. Add @file
|
||||
tags to start of header files so that Doxygen will process them.
|
||||
|
||||
2009-03-07 00:35:08 fraggle
|
||||
|
||||
Add documentation for high-level txt_desktop.h functions.
|
||||
|
||||
2009-03-07 00:24:45 fraggle
|
||||
|
||||
Add documentation for high-level textscreen functions.
|
||||
|
||||
2009-03-06 20:01:32 fraggle
|
||||
|
||||
Fix signed/unsigned conversion warning.
|
||||
|
||||
2009-03-03 19:26:20 fraggle
|
||||
|
||||
Look up SetProcessAffinityMask function at runtime, so that the
|
||||
program should work under Win9x again.
|
||||
|
||||
2009-01-30 23:53:47 fraggle
|
||||
|
||||
Fix layout of widgets within scroll panes. Scroll scroll panes in
|
||||
response to keyboard events.
|
||||
|
||||
2009-01-29 23:26:03 fraggle
|
||||
|
||||
Shrink text box slightly.
|
||||
|
||||
2009-01-29 23:00:14 fraggle
|
||||
|
||||
Allow clicking within scroll bars to set position.
|
||||
|
||||
2009-01-29 22:54:13 fraggle
|
||||
|
||||
Add scrollable pane widget to textscreen library.
|
||||
|
||||
2009-01-17 14:05:31 fraggle
|
||||
|
||||
Fix '-mmap' command line parameter.
|
||||
|
||||
2009-01-07 22:05:13 fraggle
|
||||
|
||||
Create the ~/.chocolate-doom/savegames directory on startup if it does
|
||||
not exist.
|
||||
|
||||
2009-01-07 21:51:37 fraggle
|
||||
|
||||
Replace -nommap with -mmap; do not use mmap()ed file access by
|
||||
default. Fixes Plutonia 2, and several other minor things.
|
||||
|
||||
2008-12-10 20:25:05 fraggle
|
||||
|
||||
Bump version to 1.2.1, update NEWS and ChangeLog.
|
||||
|
||||
2008-12-10 20:20:10 fraggle
|
||||
|
||||
Fix crash when playing Doom 1 levels.
|
||||
|
|
|
|||
159
INSTALL
159
INSTALL
|
|
@ -2,13 +2,18 @@
|
|||
Chocolate Doom installation
|
||||
===========================
|
||||
|
||||
These are instructions for how to install Chocolate Doom on Unix-like
|
||||
Operating Systems.
|
||||
These are instructions for how to install and set up Chocolate Doom
|
||||
for play.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
Building Chocolate Doom
|
||||
-----------------------
|
||||
|
||||
Chocolate Doom requires the following to be installed:
|
||||
Before you can play Chocolate Doom, you need to compile a binary that
|
||||
you can run. If you are using Windows or Mac OS X, precompiled
|
||||
binaries are available on the website for download, and you can skip
|
||||
this section.
|
||||
|
||||
For compilation, Chocolate Doom requires the following to be installed:
|
||||
|
||||
* A C compiler (gcc is recommended)
|
||||
* make (GNU make is recommended)
|
||||
|
|
@ -17,84 +22,108 @@ Chocolate Doom requires the following to be installed:
|
|||
* SDL_net (see http://www.libsdl.org/projects/SDL_net/)
|
||||
* Python (optional)
|
||||
|
||||
Building Chocolate Doom
|
||||
-----------------------
|
||||
|
||||
On a Unix system, follow the standard instructions for installing an
|
||||
autotools-based package:
|
||||
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.
|
||||
|
||||
Advanced topics such as cross-compilation are beyond the scope of this
|
||||
Advanced topics such as cross-compilation are beyond the scope of this
|
||||
document. Please see the GNU autoconf / automake documentation for more
|
||||
information.
|
||||
|
||||
Installing an IWAD file
|
||||
-----------------------
|
||||
Obtaining an IWAD file
|
||||
----------------------
|
||||
|
||||
To play Doom, an IWAD file is needed. This contains the Doom game data. The
|
||||
file usually has one of the following filenames:
|
||||
To play Doom, you need an IWAD file. This file contains the game data
|
||||
that is used in gameplay (graphics, sounds, etc). The full versions of
|
||||
the Doom games are proprietary and need to be bought. The IWAD file
|
||||
has one of the following names:
|
||||
|
||||
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)
|
||||
|
||||
When you have this file (see the next section, "Obtaining an IWAD file", for
|
||||
how to get this file), install it through one of the following methods:
|
||||
If you don't have a copy of the commercial version, you can download
|
||||
the shareware version (extract the file named doom1.wad):
|
||||
|
||||
* Put the file into the /usr/share/games/doom or
|
||||
/usr/local/share/games/doom directories.
|
||||
* Install it into a directory and set the environment variable DOOMWADDIR to
|
||||
be the path to that directory.
|
||||
* Install multiple IWADs into separate directories and set the environment
|
||||
variable DOOMWADPATH to be a colon-separated list of directories to search
|
||||
(similar to the Unix PATH environment variable).
|
||||
* Run Chocolate Doom with the '-iwad' command line parameter to specify the
|
||||
IWAD file to use, eg.
|
||||
* http://www.doomworld.com/idgames/index.php?id=7053
|
||||
(idstuff/doom/win95/doom95.zip in your nearest /idgames mirror)
|
||||
|
||||
chocolate-doom -iwad /root/doom2.wad
|
||||
If you have a commercial version, obtaining the IWAD file may slightly
|
||||
complicated. The method depends on how you obtained your copy of the
|
||||
game:
|
||||
|
||||
Obtaining an IWAD file
|
||||
----------------------
|
||||
* There have been several CD-based versions of Doom. Generally, the
|
||||
IWAD files can be found on the CD and copied off directly.
|
||||
|
||||
Obtaining the IWAD file may be a complicated process under Unix. The method
|
||||
depends on how you obtained your copy of the game:
|
||||
* The IWAD files might not be directly available on the CD. Look for
|
||||
a program named "deice.exe". In the same directory, there should
|
||||
be a single large file with a numbered extension (eg.
|
||||
"resource.1"); to extract this, follow the same instructions as for
|
||||
the floppy disk version (see below).
|
||||
|
||||
* There have been several CD-based versions of Doom. Generally, the IWAD
|
||||
files can be found on the CD and copied off directly.
|
||||
* If you have the floppy disk version of Doom, first copy the
|
||||
contents of all the floppy disks into a directory together. You
|
||||
will have several large files with numbered extensions.
|
||||
Concatenate these into a single file, eg.
|
||||
|
||||
* The IWAD files may not be directly available on the CD. Look for a program
|
||||
named "deice.exe". In the same directory, there should be a single large
|
||||
file with a numbered extension (eg. "resource.1"); to extract this, follow
|
||||
the same instructions as for the floppy disk version (see below).
|
||||
(Unix instructions)
|
||||
cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.exe
|
||||
|
||||
* If you have the floppy disk version of Doom, first copy the contents of all
|
||||
the floppy disks into a directory together. You will have several large
|
||||
files with numbered extensions. Concatenate these into a single file, eg.
|
||||
(Windows/DOS instructions)
|
||||
copy doom_se.1+doom_se.2+doom_se.3+doom_se.4+doom_se+5 doom_se.exe
|
||||
|
||||
cat doom_se.1 doom_se.2 doom_se.3 doom_se.4 doom_se.5 > doom_se.exe
|
||||
|
||||
The resulting file is self-extracting LHA file. If you have a DOS emulator
|
||||
(such as DOSbox), you can run it to extract the files; alternatively, you
|
||||
can use the Unix LHA tool to extract the archive.
|
||||
The resulting file is self-extracting LHA file. If you have a DOS
|
||||
emulator (such as DOSbox), you can run it to extract the files;
|
||||
alternatively, you can use the Unix LHA tool to extract the
|
||||
archive.
|
||||
|
||||
* The Doom games are also available for download on Steam
|
||||
(http://www.steampowered.com/). To find the IWAD files, look in your Steam
|
||||
directory, under the "steamapps/common" path.
|
||||
(http://www.steampowered.com/). To find the IWAD files, look in
|
||||
your Steam directory, under the "steamapps/common" path.
|
||||
|
||||
Running the game
|
||||
----------------
|
||||
|
||||
When you have an IWAD file, install it through one of the following
|
||||
methods:
|
||||
|
||||
* Under Mac OS X, you can specify the locations of the IWAD files
|
||||
through the graphical launcher program. Click the "Configure..."
|
||||
button, and then click "Set..." for each IWAD location to choose
|
||||
its location.
|
||||
|
||||
* Under Unix, put the file into the /usr/share/games/doom or
|
||||
/usr/local/share/games/doom directories.
|
||||
|
||||
* Place it in a directory and set the environment variable DOOMWADDIR
|
||||
to be the path to that directory.
|
||||
|
||||
* Install multiple IWADs into separate directories and set the
|
||||
environment variable DOOMWADPATH to be a colon-separated list of
|
||||
directories to search (similar to the Unix PATH environment
|
||||
variable).
|
||||
|
||||
* Run Chocolate Doom with the '-iwad' command line parameter to
|
||||
specify the IWAD file to use, eg.
|
||||
|
||||
chocolate-doom -iwad /root/doom2.wad
|
||||
|
||||
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 Chocolate Doom. To do this, the following files are
|
||||
needed:
|
||||
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 Chocolate Doom. 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 in the /idgames
|
||||
repository in utils/exe_edit/patches/chexdeh.zip.
|
||||
|
||||
|
|
@ -106,30 +135,30 @@ line parameter to specify the Chex Quest IWAD file:
|
|||
Installing upgrades
|
||||
-------------------
|
||||
|
||||
Chocolate Doom requires a Doom 1.9 IWAD file. Generally, if you install a
|
||||
recent version of Doom you should automatically have a 1.9 IWAD. However, if
|
||||
you are installing from a very old CD version or from floppy disks, you might
|
||||
find you have an older version.
|
||||
Chocolate Doom requires a Doom 1.9 IWAD file. Generally, if you
|
||||
install a recent version of Doom you should automatically have a 1.9
|
||||
IWAD. 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.
|
||||
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.
|
||||
|
||||
Id Software released upgrade patches that will update your game to 1.9. The
|
||||
following sites have the patches:
|
||||
Id Software released upgrade patches that will update your game to
|
||||
1.9. The following sites have the patches:
|
||||
|
||||
http://www.doomworld.com/files/patches.shtml
|
||||
http://www.doomworld.com/files/patches.shtml
|
||||
http://www.doom2.net/doom2/utils.html
|
||||
ftp://ftp.idsoftware.com/idstuff/doom2
|
||||
|
||||
As the patches are binary patches that run as DOS executables, you will
|
||||
need a DOS emulator (such as DOSBox) to install them.
|
||||
As the patches are binary patches that run as DOS executables, you
|
||||
will need a DOS emulator (such as DOSBox) to install them.
|
||||
|
||||
Music support
|
||||
-------------
|
||||
|
||||
Support for Doom's MIDI music is available through timidity:
|
||||
Support for Doom's MIDI music is available through Timidity:
|
||||
|
||||
http://timidity.sourceforge.net/
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ EXTRA_DIST= \
|
|||
config.h \
|
||||
CMDLINE \
|
||||
HACKING \
|
||||
README.OPL \
|
||||
TODO \
|
||||
BUGS \
|
||||
rpm.spec
|
||||
|
|
@ -57,7 +58,9 @@ EXTRA_DIST= \
|
|||
MAINTAINERCLEANFILES = $(AUX_DIST_GEN)
|
||||
|
||||
docdir=$(prefix)/share/doc/@PACKAGE@
|
||||
SUBDIRS=wince textscreen pcsound src man
|
||||
|
||||
SUBDIRS=wince textscreen opl pcsound src man
|
||||
|
||||
DIST_SUBDIRS=pkg $(SUBDIRS)
|
||||
|
||||
if HAVE_PYTHON
|
||||
|
|
|
|||
66
NEWS
66
NEWS
|
|
@ -1,4 +1,66 @@
|
|||
...
|
||||
1.5.0 (2010-??-??):
|
||||
|
||||
Big changes in this version:
|
||||
* The DOSbox OPL emulator (DBOPL) has been imported to replace
|
||||
the older FMOPL code. The quality of OPL emulation is now
|
||||
therefore much better.
|
||||
* When running in windowed mode, it is now possible to
|
||||
dynamically resize the window by dragging the window borders.
|
||||
* There are now keyboard, mouse and joystick bindings to cycle
|
||||
through available weapons, making play with joypads or mobile
|
||||
devices (ie. without a proper keyboard) much more practical.
|
||||
* There is now a key binding to change the multiplayer spy key
|
||||
(usually F12).
|
||||
* There is now a configuration file parameter to set the OPL I/O
|
||||
port, for cards that don't use port 0x388.
|
||||
* Up to 8 mouse buttons are now supported (including the
|
||||
mousewheel).
|
||||
|
||||
Bugs fixed:
|
||||
* It is now possible to use OPL emulation at 11025Hz sound
|
||||
sampling rate (thanks to the new OPL emulator).
|
||||
* The span renderer function (used for drawing floors and
|
||||
ceilings) now behaves the same as Vanilla Doom, so screenshots
|
||||
are pixel-perfect identical to Vanilla Doom (thanks Porsche
|
||||
Monty).
|
||||
* The zone memory system now aligns allocated memory to 8-byte
|
||||
boundaries on 64-bit systems, which may fix crashes on systems
|
||||
such as sparc64.
|
||||
* The configure script now checks for libm, fixing compile
|
||||
problems on Fedora Linux.
|
||||
|
||||
1.4.0 (2010-07-10):
|
||||
|
||||
The biggest change in this version is the addition of OPL
|
||||
emulation. This emulates Vanilla Doom's MIDI playback when
|
||||
using a Yamaha OPL synthesizer chip, as was found on
|
||||
SoundBlaster compatible cards.
|
||||
|
||||
A software OPL emulator is included as most modern computers do
|
||||
not have a hardware OPL chip any more. If you do have one, you
|
||||
can configure Chocolate Doom to use it; see README.OPL.
|
||||
|
||||
The OPL playback feature is not yet perfect or 100% complete,
|
||||
but is judged to be good enough for general use. If you find
|
||||
music that does not play back properly, please report it as a
|
||||
bug.
|
||||
|
||||
Other changes:
|
||||
* The REJECT overflow emulation code from PrBoom+ has been
|
||||
imported. This fixes demo desync on some demos, although
|
||||
others will still desync.
|
||||
* Warnings are now generated for invalid dehacked replacements of
|
||||
printf format strings. Some potential buffer overflows are
|
||||
also checked.
|
||||
* The installation instructions (INSTALL file) have been
|
||||
clarified and made more platform-agnostic.
|
||||
* The mouse is no longer warped to the center of the screen when
|
||||
the demo sequence advances.
|
||||
* Key bindings can now be changed for the demo recording quit key
|
||||
(normally 'q') and the multiplayer messaging keys (normally
|
||||
't', 'g', 'i', 'b' and 'r').
|
||||
|
||||
1.3.0 (2010-02-10):
|
||||
|
||||
* Chocolate Doom now runs on Windows Mobile/Windows CE!
|
||||
* It is possible to rebind most/all of the keys that control the
|
||||
|
|
@ -35,6 +97,8 @@
|
|||
* When recording shorttics demos, errors caused by the reduced
|
||||
turning resolution are carried forward, possibly making turning
|
||||
smoother.
|
||||
* The source tarball can now be used to build an RPM package:
|
||||
rpmbuild -tb chocolate-doom-VER.tar.gz
|
||||
|
||||
Compatibility:
|
||||
* The A_BossDeath behavior in v1.9 emulation mode was fixed
|
||||
|
|
|
|||
55
README
55
README
|
|
@ -13,33 +13,37 @@ Chocolate Doom aims to:
|
|||
* As far as possible, provide all the same features that are available
|
||||
using the DOS version.
|
||||
|
||||
== 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'.
|
||||
(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 ==
|
||||
|
||||
For a complete list of command-line options, see the CMDLINE
|
||||
file.
|
||||
For a complete list of command-line options, see the CMDLINE file.
|
||||
|
||||
== 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.
|
||||
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
|
||||
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:
|
||||
|
|
@ -53,26 +57,27 @@ Here are some examples:
|
|||
|
||||
== Other information ==
|
||||
|
||||
* More information, including information about how to play various classic
|
||||
TCs, is available on the Chocolate Doom website:
|
||||
* More information, including information about how to play various
|
||||
classic TCs, is available on the Chocolate Doom website:
|
||||
|
||||
http://www.chocolate-doom.org/
|
||||
|
||||
You are encouraged to sign up and contribute any useful information you may
|
||||
have regarding the port!
|
||||
You are encouraged to sign up and contribute any useful information
|
||||
you may have regarding the port!
|
||||
|
||||
* Chocolate Doom is not perfect. See the BUGS file for a list of known
|
||||
issues. New bug reports can be submitted to the Chocolate Doom bug
|
||||
tracker on Sourceforge. See:
|
||||
* Chocolate Doom is not perfect. See the BUGS file for a list of
|
||||
known issues. New bug reports can be submitted to the Chocolate
|
||||
Doom bug tracker on Sourceforge. See:
|
||||
|
||||
http://sourceforge.net/projects/chocolate-doom
|
||||
|
||||
* Source code patches are welcome, but please follow the style guidelines -
|
||||
see the file named HACKING included with the source distribution.
|
||||
* 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.
|
||||
* Chocolate Doom is distributed under the GNU GPL. See the COPYING
|
||||
file for more information.
|
||||
|
||||
* Please send any feedback, questions or suggestions to fraggle@gmail.com.
|
||||
Thanks!
|
||||
* Please send any feedback, questions or suggestions to
|
||||
fraggle@gmail.com. Thanks!
|
||||
|
||||
|
|
|
|||
107
README.OPL
Normal file
107
README.OPL
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
== Chocolate Doom hardware OPL support notes ==
|
||||
|
||||
Chocolate Doom is able to play MIDI music as it sounds in Vanilla Doom
|
||||
with an OPL chip (as found in the Yamaha Adlib card, the Sound Blaster
|
||||
and its clones). Most modern computers do not include an OPL chip any
|
||||
more, as CPUs are fast enough to do decent software MIDI synthesis.
|
||||
For this reason, a software OPL emulator is included as a substitute.
|
||||
|
||||
However, no software emulator sounds exactly like a real (hardware)
|
||||
OPL chip, so if you do have a sound card with hardware OPL, 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.
|
||||
|
||||
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).
|
||||
|
||||
=== Windows 9x ===
|
||||
|
||||
If you're running Windows 95, 98 or Me, there is no need to configure
|
||||
anything. Windows allows direct access to the OPL chip. You can
|
||||
confirm that hardware OPL is working by checking for this message in
|
||||
stdout.txt:
|
||||
|
||||
OPL_Init: Using driver 'Win32'.
|
||||
|
||||
=== Windows NT (including 2000, XP and later) ===
|
||||
|
||||
If you're running an NT-based system, 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:
|
||||
|
||||
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'.
|
||||
|
||||
=== 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 hadware OPL is working by checking for this message
|
||||
on startup:
|
||||
|
||||
OPL_Init: Using driver 'OpenBSD'.
|
||||
|
||||
=== FreeBSD ===
|
||||
|
||||
There is no native OPL backend for FreeBSD yet. Sorry!
|
||||
|
||||
20
TODO
20
TODO
|
|
@ -1,6 +1,5 @@
|
|||
Currently in progress:
|
||||
|
||||
* OPL MIDI playback (see: opl-branch)
|
||||
* Heretic/Hexen support (see: raven-branch)
|
||||
* Strife support (see: strife-branch)
|
||||
|
||||
|
|
@ -36,3 +35,22 @@ Crazy pie in the sky ideas:
|
|||
* DWANGO-like interface for finding players and setting up games.
|
||||
* Video capture mode?
|
||||
|
||||
== OPL TODO list ==
|
||||
|
||||
Needs research:
|
||||
|
||||
* Strategy when no more voices are available is still wrong
|
||||
* Scale levels don't exactly match Vanilla (off-by-one?)
|
||||
|
||||
Bad MIDIs:
|
||||
|
||||
* doom2.wad MAP01
|
||||
* gothicdm MAP05
|
||||
* tnt.wad MAP30
|
||||
* Alien Vendetta (title screen, MAP01, etc)
|
||||
|
||||
Other tasks:
|
||||
|
||||
* Get a better software OPL emulator
|
||||
* DMXOPTIONS opl3/phase option support.
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,19 @@
|
|||
#define PACKAGE_NAME "Chocolate Doom"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "Chocolate Doom 1.2.1"
|
||||
#define PACKAGE_STRING "Chocolate Doom 1.4.0"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "chocolate-doom"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2.1"
|
||||
#define PACKAGE_VERSION "1.4.0"
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.2.1"
|
||||
#define VERSION "1.4.0"
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
1 ICON "../data/doom.ico"
|
||||
|
||||
1 VERSIONINFO
|
||||
PRODUCTVERSION 1,2,1,0
|
||||
FILEVERSION 1,2,1,0
|
||||
PRODUCTVERSION 1,4,0,0
|
||||
FILEVERSION 1,4,0,0
|
||||
FILETYPE 1
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904E4"
|
||||
{
|
||||
VALUE "FileVersion", "1.2.1"
|
||||
VALUE "FileDescription", "1.2.1"
|
||||
VALUE "FileVersion", "1.4.0"
|
||||
VALUE "FileDescription", "1.4.0"
|
||||
VALUE "InternalName", "Chocolate-Doom"
|
||||
VALUE "CompanyName", "Chocolate-Doom"
|
||||
VALUE "LegalCopyright", "GNU General Public License"
|
||||
VALUE "ProductName", "Chocolate-Doom"
|
||||
VALUE "ProductVersion", "1.2.1"
|
||||
VALUE "ProductVersion", "1.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,21 +3,21 @@
|
|||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "setup-manifest.xml"
|
||||
|
||||
1 VERSIONINFO
|
||||
PRODUCTVERSION 1,2,1,0
|
||||
FILEVERSION 1,2,1,0
|
||||
PRODUCTVERSION 1,4,0,0
|
||||
FILEVERSION 1,4,0,0
|
||||
FILETYPE 1
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904E4"
|
||||
{
|
||||
VALUE "FileVersion", "1.2.1"
|
||||
VALUE "FileVersion", "1.4.0"
|
||||
VALUE "FileDescription", "Chocolate-Doom Setup"
|
||||
VALUE "InternalName", "chocolate-setup"
|
||||
VALUE "CompanyName", "fraggle@gmail.com"
|
||||
VALUE "LegalCopyright", "GNU General Public License"
|
||||
VALUE "ProductName", "Chocolate-Doom Setup"
|
||||
VALUE "ProductVersion", "1.2.1"
|
||||
VALUE "ProductVersion", "1.4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
configure.in
13
configure.in
|
|
@ -1,4 +1,4 @@
|
|||
AC_INIT(Chocolate Doom, 1.2.1, fraggle@gmail.com, chocolate-doom)
|
||||
AC_INIT(Chocolate Doom, 1.4.0, fraggle@gmail.com, chocolate-doom)
|
||||
|
||||
PACKAGE_SHORTDESC="Conservative Doom source port"
|
||||
PACKAGE_COPYRIGHT="Copyright (C) 1993-2010"
|
||||
|
|
@ -74,9 +74,16 @@ AC_SDL_MAIN_WORKAROUND([
|
|||
# Check for libsamplerate.
|
||||
|
||||
AC_CHECK_LIB(samplerate, src_new)
|
||||
AC_CHECK_LIB(m, log)
|
||||
|
||||
AC_CHECK_HEADERS([linux/kd.h dev/isa/spkrio.h dev/speaker/speaker.h])
|
||||
AC_CHECK_FUNCS(mmap sched_setaffinity)
|
||||
AC_CHECK_FUNCS(mmap sched_setaffinity ioperm)
|
||||
|
||||
# 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)
|
||||
])
|
||||
|
||||
AC_CHECK_TOOL(WINDRES, windres, )
|
||||
|
|
@ -138,6 +145,8 @@ AC_DEFUN([AC_DATAROOTDIR_CHECKED])
|
|||
AC_OUTPUT([
|
||||
Makefile
|
||||
man/Makefile
|
||||
opl/Makefile
|
||||
opl/examples/Makefile
|
||||
pcsound/Makefile
|
||||
pkg/Makefile
|
||||
pkg/config.make
|
||||
|
|
|
|||
|
|
@ -28,6 +28,17 @@ specifies a PC speaker driver to use for sound effect playback. Valid
|
|||
options are "Linux" for the Linux console mode driver, "BSD" for the
|
||||
NetBSD/OpenBSD PC speaker driver, and "SDL" for SDL-based emulated PC speaker
|
||||
playback (using the digital output).
|
||||
.TP
|
||||
\fBOPL_DRIVER\fR
|
||||
When using OPL MIDI playback, this environment variable specifies an
|
||||
OPL backend driver to use. Valid options are "SDL" for an SDL-based
|
||||
software emulated OPL chip, "Linux" for the Linux hardware OPL driver,
|
||||
and "OpenBSD" for the OpenBSD/NetBSD hardware OPL driver.
|
||||
|
||||
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.
|
||||
.SH FILES
|
||||
.TP
|
||||
\fB$HOME/.chocolate-doom/default.cfg\fR
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@
|
|||
#define PACKAGE_NAME "Chocolate Doom"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "Chocolate Doom 1.2.1"
|
||||
#define PACKAGE_STRING "Chocolate Doom 1.4.0"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "chocolate-doom"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2.1"
|
||||
#define PACKAGE_VERSION "1.4.0"
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.2.1"
|
||||
#define VERSION "1.4.0"
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
|
|
|
|||
|
|
@ -32,21 +32,21 @@
|
|||
#endif
|
||||
|
||||
1 VERSIONINFO
|
||||
PRODUCTVERSION 1,2,1,0
|
||||
FILEVERSION 1,2,1,0
|
||||
PRODUCTVERSION 1,4,0,0
|
||||
FILEVERSION 1,4,0,0
|
||||
FILETYPE 1
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "FileVersion", "1.2.1"
|
||||
VALUE "FileDescription", "Chocolate Doom 1.2.1"
|
||||
VALUE "FileVersion", "1.4.0"
|
||||
VALUE "FileDescription", "Chocolate Doom 1.4.0"
|
||||
VALUE "InternalName", "chocolate-doom"
|
||||
VALUE "CompanyName", "fraggle@gmail.com"
|
||||
VALUE "LegalCopyright", "GNU General Public License"
|
||||
VALUE "ProductName", "Chocolate Doom"
|
||||
VALUE "ProductVersion", "1.2.1"
|
||||
VALUE "ProductVersion", "1.4.0"
|
||||
END
|
||||
END
|
||||
END
|
||||
|
|
|
|||
7
opl/.gitignore
vendored
Normal file
7
opl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
libopl.a
|
||||
*.rc
|
||||
tags
|
||||
TAGS
|
||||
19
opl/Makefile.am
Normal file
19
opl/Makefile.am
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
AM_CFLAGS=@SDLMIXER_CFLAGS@
|
||||
|
||||
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 \
|
||||
dbopl.c dbopl.h
|
||||
|
||||
1602
opl/dbopl.c
Normal file
1602
opl/dbopl.c
Normal file
File diff suppressed because it is too large
Load diff
203
opl/dbopl.h
Normal file
203
opl/dbopl.h
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2010 The DOSBox Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
|
||||
#define WAVE_HANDLER 10
|
||||
//Use a logarithmic wavetable with an exponential table for volume
|
||||
#define WAVE_TABLELOG 11
|
||||
//Use a linear wavetable with a multiply table for volume
|
||||
#define WAVE_TABLEMUL 12
|
||||
|
||||
//Select the type of wave generator routine
|
||||
#define DBOPL_WAVE WAVE_TABLEMUL
|
||||
|
||||
typedef struct _Chip Chip;
|
||||
typedef struct _Operator Operator;
|
||||
typedef struct _Channel Channel;
|
||||
|
||||
typedef uintptr_t Bitu;
|
||||
typedef intptr_t Bits;
|
||||
typedef uint32_t Bit32u;
|
||||
typedef int32_t Bit32s;
|
||||
typedef uint16_t Bit16u;
|
||||
typedef int16_t Bit16s;
|
||||
typedef uint8_t Bit8u;
|
||||
typedef int8_t Bit8s;
|
||||
|
||||
#if (DBOPL_WAVE == WAVE_HANDLER)
|
||||
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
|
||||
#endif
|
||||
|
||||
#define DB_FASTCALL
|
||||
|
||||
typedef Bits (*VolumeHandler)(Operator *self);
|
||||
typedef Channel* (*SynthHandler)(Channel *self, Chip* chip, Bit32u samples, Bit32s* output );
|
||||
|
||||
//Different synth modes that can generate blocks of data
|
||||
typedef enum {
|
||||
sm2AM,
|
||||
sm2FM,
|
||||
sm3AM,
|
||||
sm3FM,
|
||||
sm4Start,
|
||||
sm3FMFM,
|
||||
sm3AMFM,
|
||||
sm3FMAM,
|
||||
sm3AMAM,
|
||||
sm6Start,
|
||||
sm2Percussion,
|
||||
sm3Percussion,
|
||||
} SynthMode;
|
||||
|
||||
//Shifts for the values contained in chandata variable
|
||||
enum {
|
||||
SHIFT_KSLBASE = 16,
|
||||
SHIFT_KEYCODE = 24,
|
||||
};
|
||||
|
||||
//Masks for operator 20 values
|
||||
enum {
|
||||
MASK_KSR = 0x10,
|
||||
MASK_SUSTAIN = 0x20,
|
||||
MASK_VIBRATO = 0x40,
|
||||
MASK_TREMOLO = 0x80,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
OFF,
|
||||
RELEASE,
|
||||
SUSTAIN,
|
||||
DECAY,
|
||||
ATTACK,
|
||||
} OperatorState;
|
||||
|
||||
struct _Operator {
|
||||
VolumeHandler volHandler;
|
||||
|
||||
#if (DBOPL_WAVE == WAVE_HANDLER)
|
||||
WaveHandler waveHandler; //Routine that generate a wave
|
||||
#else
|
||||
Bit16s* waveBase;
|
||||
Bit32u waveMask;
|
||||
Bit32u waveStart;
|
||||
#endif
|
||||
Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
|
||||
Bit32u waveAdd; //The base frequency without vibrato
|
||||
Bit32u waveCurrent; //waveAdd + vibratao
|
||||
|
||||
Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
|
||||
Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
|
||||
Bit32u vibrato; //Scaled up vibrato strength
|
||||
Bit32s sustainLevel; //When stopping at sustain level stop here
|
||||
Bit32s totalLevel; //totalLevel is added to every generated volume
|
||||
Bit32u currentLevel; //totalLevel + tremolo
|
||||
Bit32s volume; //The currently active volume
|
||||
|
||||
Bit32u attackAdd; //Timers for the different states of the envelope
|
||||
Bit32u decayAdd;
|
||||
Bit32u releaseAdd;
|
||||
Bit32u rateIndex; //Current position of the evenlope
|
||||
|
||||
Bit8u rateZero; //Bits for the different states of the envelope having no changes
|
||||
Bit8u keyOn; //Bitmask of different values that can generate keyon
|
||||
//Registers, also used to check for changes
|
||||
Bit8u reg20, reg40, reg60, reg80, regE0;
|
||||
//Active part of the envelope we're in
|
||||
Bit8u state;
|
||||
//0xff when tremolo is enabled
|
||||
Bit8u tremoloMask;
|
||||
//Strength of the vibrato
|
||||
Bit8u vibStrength;
|
||||
//Keep track of the calculated KSR so we can check for changes
|
||||
Bit8u ksr;
|
||||
};
|
||||
|
||||
struct _Channel {
|
||||
Operator op[2];
|
||||
SynthHandler synthHandler;
|
||||
Bit32u chanData; //Frequency/octave and derived values
|
||||
Bit32s old[2]; //Old data for feedback
|
||||
|
||||
Bit8u feedback; //Feedback shift
|
||||
Bit8u regB0; //Register values to check for changes
|
||||
Bit8u regC0;
|
||||
//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
|
||||
Bit8u fourMask;
|
||||
Bit8s maskLeft; //Sign extended values for both channel's panning
|
||||
Bit8s maskRight;
|
||||
|
||||
};
|
||||
|
||||
struct _Chip {
|
||||
//This is used as the base counter for vibrato and tremolo
|
||||
Bit32u lfoCounter;
|
||||
Bit32u lfoAdd;
|
||||
|
||||
|
||||
Bit32u noiseCounter;
|
||||
Bit32u noiseAdd;
|
||||
Bit32u noiseValue;
|
||||
|
||||
//Frequency scales for the different multiplications
|
||||
Bit32u freqMul[16];
|
||||
//Rates for decay and release for rate of this chip
|
||||
Bit32u linearRates[76];
|
||||
//Best match attack rates for the rate of this chip
|
||||
Bit32u attackRates[76];
|
||||
|
||||
//18 channels with 2 operators each
|
||||
Channel chan[18];
|
||||
|
||||
Bit8u reg104;
|
||||
Bit8u reg08;
|
||||
Bit8u reg04;
|
||||
Bit8u regBD;
|
||||
Bit8u vibratoIndex;
|
||||
Bit8u tremoloIndex;
|
||||
Bit8s vibratoSign;
|
||||
Bit8u vibratoShift;
|
||||
Bit8u tremoloValue;
|
||||
Bit8u vibratoStrength;
|
||||
Bit8u tremoloStrength;
|
||||
//Mask for allowed wave forms
|
||||
Bit8u waveFormMask;
|
||||
//0 or -1 when enabled
|
||||
Bit8s opl3Active;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
struct Handler : public Adlib::Handler {
|
||||
DBOPL::Chip chip;
|
||||
virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
|
||||
virtual void WriteReg( Bit32u addr, Bit8u val );
|
||||
virtual void Generate( MixerChannel* chan, Bitu samples );
|
||||
virtual void Init( Bitu rate );
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
void Chip__Setup(Chip *self, Bit32u rate );
|
||||
void DBOPL_InitTables( void );
|
||||
void Chip__Chip(Chip *self);
|
||||
void Chip__WriteReg(Chip *self, Bit32u reg, Bit8u val );
|
||||
void Chip__GenerateBlock2(Chip *self, Bitu total, Bit32s* output );
|
||||
|
||||
|
||||
7
opl/examples/.gitignore
vendored
Normal file
7
opl/examples/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
Makefile.in
|
||||
Makefile
|
||||
.deps
|
||||
droplay
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
8
opl/examples/Makefile.am
Normal file
8
opl/examples/Makefile.am
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
AM_CFLAGS = -I..
|
||||
|
||||
noinst_PROGRAMS=droplay
|
||||
|
||||
droplay_LDADD = ../libopl.a @LDFLAGS@ @SDL_LIBS@ @SDLMIXER_LIBS@
|
||||
droplay_SOURCES = droplay.c
|
||||
|
||||
217
opl/examples/droplay.c
Normal file
217
opl/examples/droplay.c
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Demonstration program for OPL library to play back DRO
|
||||
// format files.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.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, 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);
|
||||
} 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;
|
||||
}
|
||||
|
||||
361
opl/ioperm_sys.c
Normal file
361
opl/ioperm_sys.c
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2002, 2003 Marcel Telka
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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.
|
||||
|
||||
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 */
|
||||
|
||||
36
opl/ioperm_sys.h
Normal file
36
opl/ioperm_sys.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2002, 2003 Marcel Telka
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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 */
|
||||
|
||||
466
opl/opl.c
Normal file
466
opl/opl.c
Normal file
|
|
@ -0,0 +1,466 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// OPL interface.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32_WCE
|
||||
#include "libc_wince.h"
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
|
||||
//#define OPL_DEBUG_TRACE
|
||||
|
||||
#ifdef 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;
|
||||
|
||||
static opl_driver_t *drivers[] =
|
||||
{
|
||||
#ifdef HAVE_IOPERM
|
||||
&opl_linux_driver,
|
||||
#endif
|
||||
#if defined(HAVE_LIBI386) || defined(HAVE_LIBAMD64)
|
||||
&opl_openbsd_driver,
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
&opl_win32_driver,
|
||||
#endif
|
||||
&opl_sdl_driver,
|
||||
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 int InitDriver(opl_driver_t *_driver, unsigned int port_base)
|
||||
{
|
||||
// Initialize the driver.
|
||||
|
||||
if (!_driver->init_func(port_base))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (!OPL_Detect() || !OPL_Detect())
|
||||
{
|
||||
printf("OPL_Init: No OPL detected using '%s' driver.\n", _driver->name);
|
||||
_driver->shutdown_func();
|
||||
driver = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize all registers.
|
||||
|
||||
OPL_InitRegisters();
|
||||
|
||||
init_stage_reg_writes = 0;
|
||||
|
||||
printf("OPL_Init: Using driver '%s'.\n", driver->name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Find a driver automatically by trying each in the list.
|
||||
|
||||
static int AutoSelectDriver(unsigned int port_base)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; drivers[i] != NULL; ++i)
|
||||
{
|
||||
if (InitDriver(drivers[i], port_base))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("OPL_Init: Failed to find a working driver.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Initialize the OPL library. Returns true if initialized
|
||||
// successfully.
|
||||
|
||||
int OPL_Init(unsigned int port_base)
|
||||
{
|
||||
char *driver_name;
|
||||
int i;
|
||||
|
||||
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))
|
||||
{
|
||||
if (InitDriver(drivers[i], port_base))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("OPL_Init: Failed to initialize "
|
||||
"driver: '%s'.\n", driver_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("OPL_Init: unknown driver: '%s'.\n", driver_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
|
||||
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
|
||||
|
||||
int 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);
|
||||
|
||||
// Read status
|
||||
result2 = OPL_ReadStatus();
|
||||
|
||||
// Reset both timers:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x60);
|
||||
|
||||
// Enable interrupts:
|
||||
OPL_WriteRegister(OPL_REG_TIMER_CTRL, 0x80);
|
||||
|
||||
return (result1 & 0xe0) == 0x00
|
||||
&& (result2 & 0xe0) == 0xc0;
|
||||
}
|
||||
|
||||
// Initialize registers on startup
|
||||
|
||||
void OPL_InitRegisters(void)
|
||||
{
|
||||
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);
|
||||
|
||||
// Keyboard split point on (?)
|
||||
OPL_WriteRegister(OPL_REG_FM_MODE, 0x40);
|
||||
}
|
||||
|
||||
//
|
||||
// Timer functions.
|
||||
//
|
||||
|
||||
void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data)
|
||||
{
|
||||
if (driver != NULL)
|
||||
{
|
||||
driver->set_callback_func(ms, 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);
|
||||
}
|
||||
|
||||
void OPL_Delay(unsigned int ms)
|
||||
{
|
||||
delay_data_t delay_data;
|
||||
|
||||
if (driver == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a callback that will signal this thread after the
|
||||
// specified time.
|
||||
|
||||
delay_data.finished = 0;
|
||||
delay_data.mutex = SDL_CreateMutex();
|
||||
delay_data.cond = SDL_CreateCond();
|
||||
|
||||
OPL_SetCallback(ms, 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
137
opl/opl.h
Normal file
137
opl/opl.h
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// OPL interface.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef OPL_OPL_H
|
||||
#define OPL_OPL_H
|
||||
|
||||
typedef void (*opl_callback_t)(void *data);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OPL_REGISTER_PORT = 0,
|
||||
OPL_DATA_PORT = 1
|
||||
} 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
|
||||
|
||||
// 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
|
||||
|
||||
//
|
||||
// Low-level functions.
|
||||
//
|
||||
|
||||
// Initialize the OPL subsystem.
|
||||
|
||||
int 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.
|
||||
|
||||
int OPL_Detect(void);
|
||||
|
||||
// Initialize all registers, performed on startup.
|
||||
|
||||
void OPL_InitRegisters(void);
|
||||
|
||||
//
|
||||
// Timer callback functions.
|
||||
//
|
||||
|
||||
// Set a timer callback. After the specified number of milliseconds
|
||||
// have elapsed, the callback will be invoked.
|
||||
|
||||
void OPL_SetCallback(unsigned int ms, opl_callback_t callback, void *data);
|
||||
|
||||
// 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 milliseconds have elapsed.
|
||||
|
||||
void OPL_Delay(unsigned int ms);
|
||||
|
||||
// Pause the OPL callbacks.
|
||||
|
||||
void OPL_SetPaused(int paused);
|
||||
|
||||
#endif
|
||||
|
||||
64
opl/opl_internal.h
Normal file
64
opl/opl_internal.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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)(unsigned int ms,
|
||||
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 struct
|
||||
{
|
||||
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_driver_t;
|
||||
|
||||
// Sample rate to use when doing software emulation.
|
||||
|
||||
extern unsigned int opl_sample_rate;
|
||||
|
||||
#endif /* #ifndef OPL_INTERNAL_H */
|
||||
|
||||
110
opl/opl_linux.c
Normal file
110
opl/opl_linux.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// OPL Linux interface.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef 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, 2, 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
|
||||
};
|
||||
|
||||
#endif /* #ifdef HAVE_IOPERM */
|
||||
|
||||
125
opl/opl_obsd.c
Normal file
125
opl/opl_obsd.c
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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
|
||||
};
|
||||
|
||||
#endif /* #ifndef NO_OBSD_DRIVER */
|
||||
|
||||
280
opl/opl_queue.c
Normal file
280
opl/opl_queue.c
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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;
|
||||
unsigned int 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,
|
||||
unsigned int 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;
|
||||
}
|
||||
|
||||
unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue)
|
||||
{
|
||||
if (queue->num_entries > 0)
|
||||
{
|
||||
return queue->entries[0].time;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
45
opl/opl_queue.h
Normal file
45
opl/opl_queue.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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,
|
||||
unsigned int time);
|
||||
int OPL_Queue_Pop(opl_callback_queue_t *queue,
|
||||
opl_callback_t *callback, void **data);
|
||||
unsigned int OPL_Queue_Peek(opl_callback_queue_t *queue);
|
||||
|
||||
#endif /* #ifndef OPL_QUEUE_H */
|
||||
|
||||
510
opl/opl_sdl.c
Normal file
510
opl/opl_sdl.c
Normal file
|
|
@ -0,0 +1,510 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// OPL SDL interface.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_mixer.h"
|
||||
|
||||
#include "dbopl.h"
|
||||
|
||||
#include "opl.h"
|
||||
#include "opl_internal.h"
|
||||
|
||||
#include "opl_queue.h"
|
||||
|
||||
#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.
|
||||
unsigned int 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 number of samples since startup:
|
||||
|
||||
static int current_time;
|
||||
|
||||
// If non-zero, playback is currently paused.
|
||||
|
||||
static int opl_sdl_paused;
|
||||
|
||||
// Time offset (in samples) due to the fact that callbacks
|
||||
// were previously paused.
|
||||
|
||||
static unsigned int pause_offset;
|
||||
|
||||
// OPL software emulator structure.
|
||||
|
||||
static Chip opl_chip;
|
||||
|
||||
// Temporary mixing buffer used by the mixing callback.
|
||||
|
||||
static int32_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;
|
||||
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
|
||||
// Advance time.
|
||||
|
||||
current_time += nsamples;
|
||||
|
||||
if (opl_sdl_paused)
|
||||
{
|
||||
pause_offset += nsamples;
|
||||
}
|
||||
|
||||
// Are there callbacks to invoke now? Keep invoking them
|
||||
// until there are none 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(int16_t *buffer, unsigned int nsamples)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
// 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);
|
||||
|
||||
Chip__GenerateBlock2(&opl_chip, nsamples, mix_buffer);
|
||||
|
||||
// Mix into the destination buffer, doubling up into stereo.
|
||||
|
||||
for (i=0; i<nsamples; ++i)
|
||||
{
|
||||
buffer[i * 2] = (int16_t) (mix_buffer[i] * 2);
|
||||
buffer[i * 2 + 1] = (int16_t) (mix_buffer[i] * 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Callback function to fill a new sound buffer:
|
||||
|
||||
static void OPL_Mix_Callback(void *udata,
|
||||
Uint8 *byte_buffer,
|
||||
int buffer_bytes)
|
||||
{
|
||||
int16_t *buffer;
|
||||
unsigned int buffer_len;
|
||||
unsigned int filled = 0;
|
||||
|
||||
// Buffer length in samples (quadrupled, because of 16-bit and stereo)
|
||||
|
||||
buffer = (int16_t *) byte_buffer;
|
||||
buffer_len = buffer_bytes / 4;
|
||||
|
||||
// Repeatedly call the OPL emulator update function until the buffer is
|
||||
// full.
|
||||
|
||||
while (filled < buffer_len)
|
||||
{
|
||||
unsigned int next_callback_time;
|
||||
unsigned int 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_len - filled;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_callback_time = OPL_Queue_Peek(callback_queue) + pause_offset;
|
||||
|
||||
nsamples = next_callback_time - current_time;
|
||||
|
||||
if (nsamples > buffer_len - filled)
|
||||
{
|
||||
nsamples = buffer_len - filled;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(callback_queue_mutex);
|
||||
|
||||
// Add emulator output to buffer.
|
||||
|
||||
FillBuffer(buffer + filled * 2, 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_OpenAudio(opl_sample_rate, AUDIO_S16SYS, 2, GetSliceSize()) < 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:
|
||||
|
||||
mix_buffer = malloc(mixing_freq * sizeof(uint32_t));
|
||||
|
||||
// Create the emulator structure:
|
||||
|
||||
DBOPL_InitTables();
|
||||
Chip__Chip(&opl_chip);
|
||||
Chip__Setup(&opl_chip, mixing_freq);
|
||||
|
||||
callback_mutex = SDL_CreateMutex();
|
||||
callback_queue_mutex = SDL_CreateMutex();
|
||||
|
||||
// TODO: This should be music callback? or-?
|
||||
Mix_HookMusic(OPL_Mix_Callback, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int OPL_SDL_PortRead(opl_port_t port)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
|
||||
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
|
||||
+ (tics * opl_sample_rate) / 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)
|
||||
{
|
||||
timer1.enabled = (value & 0x02) != 0;
|
||||
OPLTimer_CalculateEndTime(&timer2);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Chip__WriteReg(&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_DATA_PORT)
|
||||
{
|
||||
WriteRegister(register_num, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void OPL_SDL_SetCallback(unsigned int ms,
|
||||
opl_callback_t callback,
|
||||
void *data)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Push(callback_queue, callback, data,
|
||||
current_time - pause_offset + (ms * mixing_freq) / 1000);
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
251
opl/opl_timer.c
Normal file
251
opl/opl_timer.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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 int current_time;
|
||||
|
||||
// If non-zero, callbacks are currently paused.
|
||||
|
||||
static int opl_timer_paused;
|
||||
|
||||
// Offset in milliseconds to adjust time due to the fact that playback
|
||||
// was paused.
|
||||
|
||||
static unsigned int 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(unsigned int *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;
|
||||
pause_offset += 50;
|
||||
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;
|
||||
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 unsigned int GetNextTime(void)
|
||||
{
|
||||
opl_callback_t callback;
|
||||
void *callback_data;
|
||||
unsigned int 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)
|
||||
{
|
||||
unsigned int next_time;
|
||||
unsigned int 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();
|
||||
|
||||
if (next_time > now)
|
||||
{
|
||||
SDL_Delay(next_time - now);
|
||||
}
|
||||
|
||||
// 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, 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(unsigned int ms, opl_callback_t callback, void *data)
|
||||
{
|
||||
SDL_LockMutex(callback_queue_mutex);
|
||||
OPL_Queue_Push(callback_queue, callback, data,
|
||||
current_time + ms - 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_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);
|
||||
}
|
||||
|
||||
42
opl/opl_timer.h
Normal file
42
opl/opl_timer.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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(unsigned int ms,
|
||||
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);
|
||||
|
||||
#endif /* #ifndef OPL_TIMER_H */
|
||||
|
||||
172
opl/opl_win32.c
Normal file
172
opl/opl_win32.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2009 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
// 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"
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: MSVC version
|
||||
// #elif defined(_MSC_VER) && defined(_M_IX6) ...
|
||||
|
||||
#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)
|
||||
{
|
||||
#ifndef NO_PORT_RW
|
||||
|
||||
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);
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
#endif /* #ifdef _WIN32 */
|
||||
|
||||
|
|
@ -22,6 +22,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
|
|||
DOC_FILES = README \
|
||||
COPYING \
|
||||
ChangeLog \
|
||||
INSTALL \
|
||||
NEWS \
|
||||
BUGS \
|
||||
CMDLINE \
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
include ../config.make
|
||||
|
||||
# Build so that the package will work on older versions.
|
||||
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.4
|
||||
|
||||
STAGING_DIR=staging
|
||||
DMG=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION).dmg
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ DLL_FILES=$(TOPLEVEL)/src/SDL.dll \
|
|||
$(TOPLEVEL)/src/SDL_mixer.dll \
|
||||
$(TOPLEVEL)/src/SDL_net.dll
|
||||
|
||||
DOC_FILES += README.OPL
|
||||
|
||||
ZIP=$(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-win32.zip
|
||||
|
||||
$(ZIP) : staging
|
||||
|
|
|
|||
|
|
@ -49,9 +49,11 @@ rm -rf $RPM_BUILD_ROOT
|
|||
%files
|
||||
%doc %{_mandir}/man5/*
|
||||
%doc %{_mandir}/man6/*
|
||||
%doc README
|
||||
%doc README.OPL
|
||||
%doc INSTALL
|
||||
%doc NEWS
|
||||
%doc AUTHORS
|
||||
%doc README
|
||||
%doc COPYING
|
||||
%doc CMDLINE
|
||||
%doc BUGS
|
||||
|
|
|
|||
4
src/.gitignore
vendored
4
src/.gitignore
vendored
|
|
@ -3,7 +3,11 @@ Makefile.in
|
|||
.deps
|
||||
*.rc
|
||||
chocolate-doom
|
||||
chocolate-heretic
|
||||
chocolate-hexen
|
||||
chocolate-server
|
||||
chocolate-setup
|
||||
*.exe
|
||||
*.desktop
|
||||
tags
|
||||
TAGS
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ games_PROGRAMS = @PROGRAM_PREFIX@doom \
|
|||
@PROGRAM_PREFIX@setup
|
||||
|
||||
AM_CFLAGS = -I$(top_builddir)/textscreen \
|
||||
-I$(top_builddir)/opl \
|
||||
-I$(top_builddir)/pcsound \
|
||||
@SDLMIXER_CFLAGS@ @SDLNET_CFLAGS@
|
||||
|
||||
|
|
@ -72,6 +73,7 @@ tables.c tables.h \
|
|||
v_video.c v_video.h \
|
||||
v_patch.h \
|
||||
w_checksum.c w_checksum.h \
|
||||
w_main.c w_main.h \
|
||||
w_wad.c w_wad.h \
|
||||
w_file.c w_file.h \
|
||||
w_file_stdc.c \
|
||||
|
|
@ -115,6 +117,8 @@ FEATURE_SOUND_SOURCE_FILES = \
|
|||
i_pcsound.c \
|
||||
i_sdlsound.c \
|
||||
i_sdlmusic.c \
|
||||
i_oplmusic.c \
|
||||
midifile.c midifile.h \
|
||||
mus2mid.c mus2mid.h
|
||||
|
||||
# Some games support dehacked patches, some don't:
|
||||
|
|
@ -131,10 +135,11 @@ EXTRA_LIBS = \
|
|||
$(top_builddir)/wince/libc_wince.a \
|
||||
$(top_builddir)/textscreen/libtextscreen.a \
|
||||
$(top_builddir)/pcsound/libpcsound.a \
|
||||
$(top_builddir)/opl/libopl.a \
|
||||
@LDFLAGS@ \
|
||||
@SDL_LIBS@ \
|
||||
@SDLMIXER_LIBS@ \
|
||||
@SDLNET_LIBS@
|
||||
@SDLNET_LIBS@
|
||||
|
||||
if HAVE_WINDRES
|
||||
@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
|
||||
|
|
@ -145,9 +150,9 @@ endif
|
|||
@PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS)
|
||||
|
||||
if HAVE_WINDRES
|
||||
@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES) resource.rc
|
||||
@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
|
||||
else
|
||||
@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES)
|
||||
@PROGRAM_PREFIX@heretic_SOURCES=$(SOURCE_FILES_WITH_DEH)
|
||||
endif
|
||||
|
||||
@PROGRAM_PREFIX@heretic_LDADD = heretic/libheretic.a $(EXTRA_LIBS)
|
||||
|
|
@ -204,3 +209,6 @@ icon.c : $(top_builddir)/data/doom8.ico
|
|||
|
||||
endif
|
||||
|
||||
midiread : midifile.c
|
||||
$(CC) -DTEST $(CFLAGS) @LDFLAGS@ $^ -o $@
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
extern deh_section_t *deh_section_types[];
|
||||
extern char *deh_signatures[];
|
||||
|
||||
static boolean deh_initialized = false;
|
||||
|
||||
// If true, we can do long string replacements.
|
||||
|
||||
boolean deh_allow_long_strings = false;
|
||||
|
|
@ -322,6 +324,12 @@ int DEH_LoadFile(char *filename)
|
|||
{
|
||||
deh_context_t *context;
|
||||
|
||||
if (!deh_initialized)
|
||||
{
|
||||
InitializeSections();
|
||||
deh_initialized = true;
|
||||
}
|
||||
|
||||
printf(" loading %s\n", filename);
|
||||
|
||||
context = DEH_OpenFile(filename);
|
||||
|
|
@ -346,8 +354,6 @@ void DEH_Init(void)
|
|||
char *filename;
|
||||
int p;
|
||||
|
||||
InitializeSections();
|
||||
|
||||
//!
|
||||
// @category mod
|
||||
//
|
||||
|
|
|
|||
|
|
@ -34,12 +34,9 @@
|
|||
#include "i_system.h"
|
||||
#include "deh_mapping.h"
|
||||
|
||||
//
|
||||
// Set the value of a particular field in a structure by name
|
||||
//
|
||||
|
||||
boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr, char *name, int value)
|
||||
static deh_mapping_entry_t *GetMappingEntryByName(deh_context_t *context,
|
||||
deh_mapping_t *mapping,
|
||||
char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -49,44 +46,121 @@ boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
|
|||
|
||||
if (!strcasecmp(entry->name, name))
|
||||
{
|
||||
void *location;
|
||||
|
||||
if (entry->location == NULL)
|
||||
{
|
||||
DEH_Warning(context, "Field '%s' is unsupported", name);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
|
||||
|
||||
// printf("Setting %p::%s to %i (%i bytes)\n",
|
||||
// structptr, name, value, entry->size);
|
||||
|
||||
switch (entry->size)
|
||||
{
|
||||
case 1:
|
||||
* ((uint8_t *) location) = value;
|
||||
break;
|
||||
case 2:
|
||||
* ((uint16_t *) location) = value;
|
||||
break;
|
||||
case 4:
|
||||
* ((uint32_t *) location) = value;
|
||||
break;
|
||||
default:
|
||||
DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
// field with this name not found
|
||||
// Not found.
|
||||
|
||||
DEH_Warning(context, "Field named '%s' not found", name);
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the location of the specified field in the specified structure.
|
||||
//
|
||||
|
||||
static void *GetStructField(void *structptr,
|
||||
deh_mapping_t *mapping,
|
||||
deh_mapping_entry_t *entry)
|
||||
{
|
||||
unsigned int offset;
|
||||
|
||||
offset = (uint8_t *)entry->location - (uint8_t *)mapping->base;
|
||||
|
||||
return (uint8_t *)structptr + offset;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the value of a particular field in a structure by name
|
||||
//
|
||||
|
||||
boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr, char *name, int value)
|
||||
{
|
||||
deh_mapping_entry_t *entry;
|
||||
void *location;
|
||||
|
||||
entry = GetMappingEntryByName(context, mapping, name);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check:
|
||||
|
||||
if (entry->is_string)
|
||||
{
|
||||
DEH_Error(context, "Tried to set '%s' as integer (BUG)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
location = GetStructField(structptr, mapping, entry);
|
||||
|
||||
// printf("Setting %p::%s to %i (%i bytes)\n",
|
||||
// structptr, name, value, entry->size);
|
||||
|
||||
// Set field content based on its type:
|
||||
|
||||
switch (entry->size)
|
||||
{
|
||||
case 1:
|
||||
* ((uint8_t *) location) = value;
|
||||
break;
|
||||
case 2:
|
||||
* ((uint16_t *) location) = value;
|
||||
break;
|
||||
case 4:
|
||||
* ((uint32_t *) location) = value;
|
||||
break;
|
||||
default:
|
||||
DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the value of a string field in a structure by name
|
||||
//
|
||||
|
||||
boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr, char *name, char *value)
|
||||
{
|
||||
deh_mapping_entry_t *entry;
|
||||
void *location;
|
||||
|
||||
entry = GetMappingEntryByName(context, mapping, name);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check:
|
||||
|
||||
if (!entry->is_string)
|
||||
{
|
||||
DEH_Error(context, "Tried to set '%s' as string (BUG)", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
location = GetStructField(structptr, mapping, entry);
|
||||
|
||||
// Copy value into field:
|
||||
|
||||
strncpy(location, value, entry->size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
|
||||
|
|
|
|||
|
|
@ -42,17 +42,23 @@
|
|||
|
||||
#define DEH_MAPPING(deh_name, fieldname) \
|
||||
{deh_name, &deh_mapping_base.fieldname, \
|
||||
sizeof(deh_mapping_base.fieldname)},
|
||||
sizeof(deh_mapping_base.fieldname), \
|
||||
false},
|
||||
|
||||
#define DEH_MAPPING_STRING(deh_name, fieldname) \
|
||||
{deh_name, &deh_mapping_base.fieldname, \
|
||||
sizeof(deh_mapping_base.fieldname), \
|
||||
true},
|
||||
|
||||
#define DEH_UNSUPPORTED_MAPPING(deh_name) \
|
||||
{deh_name, NULL, -1},
|
||||
|
||||
{deh_name, NULL, -1, false},
|
||||
|
||||
#define DEH_END_MAPPING \
|
||||
{NULL, NULL, -1} \
|
||||
} \
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAX_MAPPING_ENTRIES 32
|
||||
|
||||
|
|
@ -73,6 +79,10 @@ struct deh_mapping_entry_s
|
|||
// field size
|
||||
|
||||
int size;
|
||||
|
||||
// if true, this is a string value.
|
||||
|
||||
boolean is_string;
|
||||
};
|
||||
|
||||
struct deh_mapping_s
|
||||
|
|
@ -81,8 +91,10 @@ struct deh_mapping_s
|
|||
deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES];
|
||||
};
|
||||
|
||||
boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr, char *name, int value);
|
||||
boolean DEH_SetStringMapping(deh_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr, char *name, char *value);
|
||||
void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
|
||||
void *structptr);
|
||||
|
||||
|
|
|
|||
227
src/deh_str.c
227
src/deh_str.c
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "deh_str.h"
|
||||
|
|
@ -179,3 +180,229 @@ void DEH_AddStringReplacement(char *from_text, char *to_text)
|
|||
DEH_AddToHashtable(sub);
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FORMAT_ARG_INVALID,
|
||||
FORMAT_ARG_INT,
|
||||
FORMAT_ARG_FLOAT,
|
||||
FORMAT_ARG_CHAR,
|
||||
FORMAT_ARG_STRING,
|
||||
FORMAT_ARG_PTR,
|
||||
FORMAT_ARG_SAVE_POS
|
||||
} format_arg_t;
|
||||
|
||||
// Get the type of a format argument.
|
||||
// We can mix-and-match different format arguments as long as they
|
||||
// are for the same data type.
|
||||
|
||||
static format_arg_t FormatArgumentType(char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X':
|
||||
return FORMAT_ARG_INT;
|
||||
|
||||
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
|
||||
case 'a': case 'A':
|
||||
return FORMAT_ARG_FLOAT;
|
||||
|
||||
case 'c': case 'C':
|
||||
return FORMAT_ARG_CHAR;
|
||||
|
||||
case 's': case 'S':
|
||||
return FORMAT_ARG_STRING;
|
||||
|
||||
case 'p':
|
||||
return FORMAT_ARG_PTR;
|
||||
|
||||
case 'n':
|
||||
return FORMAT_ARG_SAVE_POS;
|
||||
|
||||
default:
|
||||
return FORMAT_ARG_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
// Given the specified string, get the type of the first format
|
||||
// string encountered.
|
||||
|
||||
static format_arg_t NextFormatArgument(char **str)
|
||||
{
|
||||
format_arg_t argtype;
|
||||
|
||||
// Search for the '%' starting the next string.
|
||||
|
||||
while (**str != '\0')
|
||||
{
|
||||
if (**str == '%')
|
||||
{
|
||||
++*str;
|
||||
|
||||
// Don't stop for double-%s.
|
||||
|
||||
if (**str != '%')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++*str;
|
||||
}
|
||||
|
||||
// Find the type of the format string.
|
||||
|
||||
while (**str != '\0')
|
||||
{
|
||||
argtype = FormatArgumentType(**str);
|
||||
|
||||
if (argtype != FORMAT_ARG_INVALID)
|
||||
{
|
||||
++*str;
|
||||
|
||||
return argtype;
|
||||
}
|
||||
|
||||
++*str;
|
||||
}
|
||||
|
||||
// Stop searching, we have reached the end.
|
||||
|
||||
*str = NULL;
|
||||
|
||||
return FORMAT_ARG_INVALID;
|
||||
}
|
||||
|
||||
// Check if the specified argument type is a valid replacement for
|
||||
// the original.
|
||||
|
||||
static boolean ValidArgumentReplacement(format_arg_t original,
|
||||
format_arg_t replacement)
|
||||
{
|
||||
// In general, the original and replacement types should be
|
||||
// identical. However, there are some cases where the replacement
|
||||
// is valid and the types don't match.
|
||||
|
||||
// Characters can be represented as ints.
|
||||
|
||||
if (original == FORMAT_ARG_CHAR && replacement == FORMAT_ARG_INT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Strings are pointers.
|
||||
|
||||
if (original == FORMAT_ARG_STRING && replacement == FORMAT_ARG_PTR)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return original == replacement;
|
||||
}
|
||||
|
||||
// Return true if the specified string contains no format arguments.
|
||||
|
||||
static boolean ValidFormatReplacement(char *original, char *replacement)
|
||||
{
|
||||
char *rover1;
|
||||
char *rover2;
|
||||
int argtype1, argtype2;
|
||||
|
||||
// Check each argument in turn and compare types.
|
||||
|
||||
rover1 = original; rover2 = replacement;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
argtype1 = NextFormatArgument(&rover1);
|
||||
argtype2 = NextFormatArgument(&rover2);
|
||||
|
||||
if (argtype2 == FORMAT_ARG_INVALID)
|
||||
{
|
||||
// No more arguments left to read from the replacement string.
|
||||
|
||||
break;
|
||||
}
|
||||
else if (argtype1 == FORMAT_ARG_INVALID)
|
||||
{
|
||||
// Replacement string has more arguments than the original.
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (!ValidArgumentReplacement(argtype1, argtype2))
|
||||
{
|
||||
// Not a valid replacement argument.
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get replacement format string, checking arguments.
|
||||
|
||||
static char *FormatStringReplacement(char *s)
|
||||
{
|
||||
char *repl;
|
||||
|
||||
repl = DEH_String(s);
|
||||
|
||||
if (!ValidFormatReplacement(s, repl))
|
||||
{
|
||||
printf("WARNING: Unsafe dehacked replacement provided for "
|
||||
"printf format string: %s\n", s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
return repl;
|
||||
}
|
||||
|
||||
// printf(), performing a replacement on the format string.
|
||||
|
||||
void DEH_printf(char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *repl;
|
||||
|
||||
repl = FormatStringReplacement(fmt);
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vprintf(repl, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// fprintf(), performing a replacement on the format string.
|
||||
|
||||
void DEH_fprintf(FILE *fstream, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *repl;
|
||||
|
||||
repl = FormatStringReplacement(fmt);
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vfprintf(fstream, repl, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// snprintf(), performing a replacement on the format string.
|
||||
|
||||
void DEH_snprintf(char *buffer, size_t len, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *repl;
|
||||
|
||||
repl = FormatStringReplacement(fmt);
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vsnprintf(buffer, len, repl, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#ifndef DEH_STR_H
|
||||
#define DEH_STR_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "doomfeatures.h"
|
||||
|
||||
// Used to do dehacked text substitutions throughout the program
|
||||
|
|
@ -34,11 +36,18 @@
|
|||
#ifdef FEATURE_DEHACKED
|
||||
|
||||
char *DEH_String(char *s);
|
||||
void DEH_printf(char *fmt, ...);
|
||||
void DEH_fprintf(FILE *fstream, char *fmt, ...);
|
||||
void DEH_snprintf(char *buffer, size_t len, char *fmt, ...);
|
||||
void DEH_AddStringReplacement(char *from_text, char *to_text);
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define DEH_String(x) (x)
|
||||
#define DEH_printf printf
|
||||
#define DEH_fprintf fprintf
|
||||
#define DEH_snprintf snprintf
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
4
src/doom/.gitignore
vendored
4
src/doom/.gitignore
vendored
|
|
@ -1,9 +1,5 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
*.rc
|
||||
chocolate-doom
|
||||
chocolate-server
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ void AM_loadPics(void)
|
|||
|
||||
for (i=0;i<10;i++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("AMMNUM%d"), i);
|
||||
DEH_snprintf(namebuf, 9, "AMMNUM%d", i);
|
||||
marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
|
||||
}
|
||||
|
||||
|
|
@ -513,7 +513,7 @@ void AM_unloadPics(void)
|
|||
|
||||
for (i=0;i<10;i++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("AMMNUM%d"), i);
|
||||
DEH_snprintf(namebuf, 9, "AMMNUM%d", i);
|
||||
W_ReleaseLumpName(namebuf);
|
||||
}
|
||||
}
|
||||
|
|
@ -1020,7 +1020,7 @@ AM_drawFline
|
|||
|| fl->b.x < 0 || fl->b.x >= f_w
|
||||
|| fl->b.y < 0 || fl->b.y >= f_h)
|
||||
{
|
||||
fprintf(stderr, DEH_String("fuck %d \r"), fuck++);
|
||||
DEH_fprintf(stderr, "fuck %d \r", fuck++);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@
|
|||
#include "d_iwad.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
#include "w_main.h"
|
||||
#include "w_wad.h"
|
||||
#include "w_merge.h"
|
||||
#include "s_sound.h"
|
||||
#include "v_video.h"
|
||||
|
||||
|
|
@ -358,6 +358,12 @@ void D_BindVariables(void)
|
|||
M_BindWeaponControls();
|
||||
M_BindMapControls();
|
||||
M_BindMenuControls();
|
||||
M_BindChatControls(MAXPLAYERS);
|
||||
|
||||
key_multi_msgplayer[0] = HUSTR_KEYGREEN;
|
||||
key_multi_msgplayer[1] = HUSTR_KEYINDIGO;
|
||||
key_multi_msgplayer[2] = HUSTR_KEYBROWN;
|
||||
key_multi_msgplayer[3] = HUSTR_KEYRED;
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
NET_BindVariables();
|
||||
|
|
@ -827,7 +833,6 @@ static boolean CheckChex(char *iwadname)
|
|||
// print title for every printed line
|
||||
char title[128];
|
||||
|
||||
|
||||
static boolean D_AddFile(char *filename)
|
||||
{
|
||||
wad_file_t *handle;
|
||||
|
|
@ -1069,7 +1074,7 @@ void D_DoomMain (void)
|
|||
|
||||
I_PrintBanner(PACKAGE_STRING);
|
||||
|
||||
printf (DEH_String("Z_Init: Init zone memory allocation daemon. \n"));
|
||||
DEH_printf("Z_Init: Init zone memory allocation daemon. \n");
|
||||
Z_Init ();
|
||||
|
||||
#ifdef FEATURE_MULTIPLAYER
|
||||
|
|
@ -1188,7 +1193,7 @@ void D_DoomMain (void)
|
|||
deathmatch = 2;
|
||||
|
||||
if (devparm)
|
||||
printf(DEH_String(D_DEVSTR));
|
||||
DEH_printf(D_DEVSTR);
|
||||
|
||||
// find which dir to use for config files
|
||||
|
||||
|
|
@ -1236,7 +1241,7 @@ void D_DoomMain (void)
|
|||
scale = 10;
|
||||
if (scale > 400)
|
||||
scale = 400;
|
||||
printf (DEH_String("turbo scale: %i%%\n"),scale);
|
||||
DEH_printf("turbo scale: %i%%\n", scale);
|
||||
forwardmove[0] = forwardmove[0]*scale/100;
|
||||
forwardmove[1] = forwardmove[1]*scale/100;
|
||||
sidemove[0] = sidemove[0]*scale/100;
|
||||
|
|
@ -1244,11 +1249,11 @@ void D_DoomMain (void)
|
|||
}
|
||||
|
||||
// init subsystems
|
||||
printf(DEH_String("V_Init: allocate screens.\n"));
|
||||
V_Init();
|
||||
DEH_printf("V_Init: allocate screens.\n");
|
||||
V_Init ();
|
||||
|
||||
// Load configuration files before initialising other subsystems.
|
||||
printf(DEH_String("M_LoadDefaults: Load system defaults.\n"));
|
||||
DEH_printf("M_LoadDefaults: Load system defaults.\n");
|
||||
M_SetConfigFilenames("default.cfg", PROGRAM_PREFIX "doom.cfg");
|
||||
D_BindVariables();
|
||||
M_LoadDefaults();
|
||||
|
|
@ -1256,160 +1261,9 @@ void D_DoomMain (void)
|
|||
// Save configuration at exit.
|
||||
I_AtExit(M_SaveDefaults, false);
|
||||
|
||||
printf (DEH_String("W_Init: Init WADfiles.\n"));
|
||||
DEH_printf("W_Init: Init WADfiles.\n");
|
||||
D_AddFile(iwadfile);
|
||||
|
||||
#ifdef FEATURE_WAD_MERGE
|
||||
|
||||
// Merged PWADs are loaded first, because they are supposed to be
|
||||
// modified IWADs.
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @category mod
|
||||
//
|
||||
// Simulates the behavior of deutex's -merge option, merging a PWAD
|
||||
// into the main IWAD. Multiple files may be specified.
|
||||
//
|
||||
|
||||
p = M_CheckParm("-merge");
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
printf(" merging %s\n", filename);
|
||||
W_MergeFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
// NWT-style merging:
|
||||
|
||||
// NWT's -merge option:
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @category mod
|
||||
//
|
||||
// Simulates the behavior of NWT's -merge option. Multiple files
|
||||
// may be specified.
|
||||
|
||||
p = M_CheckParm("-nwtmerge");
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
printf(" performing NWT-style merge of %s\n", filename);
|
||||
W_NWTDashMerge(filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Add flats
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @category mod
|
||||
//
|
||||
// Simulates the behavior of NWT's -af option, merging flats into
|
||||
// the main IWAD directory. Multiple files may be specified.
|
||||
//
|
||||
|
||||
p = M_CheckParm("-af");
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
printf(" merging flats from %s\n", filename);
|
||||
W_NWTMergeFile(filename, W_NWT_MERGE_FLATS);
|
||||
}
|
||||
}
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @category mod
|
||||
//
|
||||
// Simulates the behavior of NWT's -as option, merging sprites
|
||||
// into the main IWAD directory. Multiple files may be specified.
|
||||
//
|
||||
|
||||
p = M_CheckParm("-as");
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
printf(" merging sprites from %s\n", filename);
|
||||
W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES);
|
||||
}
|
||||
}
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @category mod
|
||||
//
|
||||
// Equivalent to "-af <files> -as <files>".
|
||||
//
|
||||
|
||||
p = M_CheckParm("-aa");
|
||||
|
||||
if (p > 0)
|
||||
{
|
||||
for (p = p + 1; p<myargc && myargv[p][0] != '-'; ++p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
printf(" merging sprites and flats from %s\n", filename);
|
||||
W_NWTMergeFile(filename, W_NWT_MERGE_SPRITES | W_NWT_MERGE_FLATS);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//!
|
||||
// @arg <files>
|
||||
// @vanilla
|
||||
//
|
||||
// Load the specified PWAD files.
|
||||
//
|
||||
|
||||
p = M_CheckParm ("-file");
|
||||
if (p)
|
||||
{
|
||||
// the parms after p are wadfile/lump names,
|
||||
// until end of parms or another - preceded parm
|
||||
modifiedgame = true; // homebrew levels
|
||||
while (++p != myargc && myargv[p][0] != '-')
|
||||
{
|
||||
char *filename;
|
||||
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
D_AddFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
// Debug:
|
||||
// W_PrintDirectory();
|
||||
modifiedgame = W_ParseCommandLine();
|
||||
|
||||
// add any files specified on the command line with -file wadfile
|
||||
// to the wad list
|
||||
|
|
@ -1603,8 +1457,8 @@ void D_DoomMain (void)
|
|||
|
||||
if (p && p < myargc-1 && deathmatch)
|
||||
{
|
||||
printf(DEH_String("Austin Virtual Gaming: Levels will end "
|
||||
"after 20 minutes\n"));
|
||||
DEH_printf("Austin Virtual Gaming: Levels will end "
|
||||
"after 20 minutes\n");
|
||||
timelimit = 20;
|
||||
}
|
||||
|
||||
|
|
@ -1686,16 +1540,16 @@ void D_DoomMain (void)
|
|||
I_PrintStartupBanner(gamedescription);
|
||||
PrintDehackedBanners();
|
||||
|
||||
printf (DEH_String("M_Init: Init miscellaneous info.\n"));
|
||||
DEH_printf("M_Init: Init miscellaneous info.\n");
|
||||
M_Init ();
|
||||
|
||||
printf (DEH_String("R_Init: Init DOOM refresh daemon - "));
|
||||
DEH_printf("R_Init: Init DOOM refresh daemon - ");
|
||||
R_Init ();
|
||||
|
||||
printf (DEH_String("\nP_Init: Init Playloop state.\n"));
|
||||
DEH_printf("\nP_Init: Init Playloop state.\n");
|
||||
P_Init ();
|
||||
|
||||
printf (DEH_String("I_Init: Setting up machine state.\n"));
|
||||
DEH_printf("I_Init: Setting up machine state.\n");
|
||||
I_CheckIsScreensaver();
|
||||
I_InitTimer();
|
||||
I_InitJoystick();
|
||||
|
|
@ -1705,18 +1559,18 @@ void D_DoomMain (void)
|
|||
NET_Init ();
|
||||
#endif
|
||||
|
||||
printf (DEH_String("S_Init: Setting up sound.\n"));
|
||||
DEH_printf("S_Init: Setting up sound.\n");
|
||||
S_Init (sfxVolume * 8, musicVolume * 8);
|
||||
|
||||
printf (DEH_String("D_CheckNetGame: Checking network game status.\n"));
|
||||
DEH_printf("D_CheckNetGame: Checking network game status.\n");
|
||||
D_CheckNetGame ();
|
||||
|
||||
PrintGameVersion();
|
||||
|
||||
printf (DEH_String("HU_Init: Setting up heads up display.\n"));
|
||||
DEH_printf("HU_Init: Setting up heads up display.\n");
|
||||
HU_Init ();
|
||||
|
||||
printf (DEH_String("ST_Init: Init status bar.\n"));
|
||||
DEH_printf("ST_Init: Init status bar.\n");
|
||||
ST_Init ();
|
||||
|
||||
// If Doom II without a MAP01 lump, this is a store demo.
|
||||
|
|
|
|||
|
|
@ -374,17 +374,17 @@ void D_CheckNetGame (void)
|
|||
++num_players;
|
||||
}
|
||||
|
||||
printf (DEH_String("startskill %i deathmatch: %i startmap: %i startepisode: %i\n"),
|
||||
startskill, deathmatch, startmap, startepisode);
|
||||
DEH_printf("startskill %i deathmatch: %i startmap: %i startepisode: %i\n",
|
||||
startskill, deathmatch, startmap, startepisode);
|
||||
|
||||
printf(DEH_String("player %i of %i (%i nodes)\n"),
|
||||
consoleplayer+1, num_players, num_players);
|
||||
DEH_printf("player %i of %i (%i nodes)\n",
|
||||
consoleplayer+1, num_players, num_players);
|
||||
|
||||
// Show players here; the server might have specified a time limit
|
||||
|
||||
if (timelimit > 0)
|
||||
{
|
||||
printf(DEH_String("Levels will end after %d minute"),timelimit);
|
||||
DEH_printf("Levels will end after %d minute", timelimit);
|
||||
if (timelimit > 1)
|
||||
printf("s");
|
||||
printf(".\n");
|
||||
|
|
|
|||
|
|
@ -663,7 +663,7 @@ void F_BunnyScroll (void)
|
|||
laststage = stage;
|
||||
}
|
||||
|
||||
sprintf (name, DEH_String("END%i"), stage);
|
||||
DEH_snprintf(name, 10, "END%i", stage);
|
||||
V_DrawPatch((SCREENWIDTH - 13 * 8) / 2,
|
||||
(SCREENHEIGHT - 8 * 8) / 2,
|
||||
W_CacheLumpName (name,PU_CACHE));
|
||||
|
|
|
|||
|
|
@ -176,14 +176,37 @@ static int *weapon_keys[] = {
|
|||
&key_weapon8
|
||||
};
|
||||
|
||||
// Set to -1 or +1 to switch to the previous or next weapon.
|
||||
|
||||
static int next_weapon = 0;
|
||||
|
||||
// Used for prev/next weapon keys.
|
||||
|
||||
static const struct
|
||||
{
|
||||
weapontype_t weapon;
|
||||
weapontype_t weapon_num;
|
||||
} weapon_order_table[] = {
|
||||
{ wp_fist, wp_fist },
|
||||
{ wp_chainsaw, wp_fist },
|
||||
{ wp_pistol, wp_pistol },
|
||||
{ wp_shotgun, wp_shotgun },
|
||||
{ wp_supershotgun, wp_shotgun },
|
||||
{ wp_chaingun, wp_chaingun },
|
||||
{ wp_missile, wp_missile },
|
||||
{ wp_plasma, wp_plasma },
|
||||
{ wp_bfg, wp_bfg }
|
||||
};
|
||||
|
||||
#define SLOWTURNTICS 6
|
||||
|
||||
#define NUMKEYS 256
|
||||
#define MAX_JOY_BUTTONS 20
|
||||
|
||||
static boolean gamekeydown[NUMKEYS];
|
||||
static int turnheld; // for accelerative turning
|
||||
|
||||
static boolean mousearray[4];
|
||||
static boolean mousearray[MAX_MOUSE_BUTTONS + 1];
|
||||
static boolean *mousebuttons = &mousearray[1]; // allow [-1]
|
||||
|
||||
// mouse values are used once
|
||||
|
|
@ -197,8 +220,6 @@ static int dclicktime2;
|
|||
static boolean dclickstate2;
|
||||
static int dclicks2;
|
||||
|
||||
#define MAX_JOY_BUTTONS 20
|
||||
|
||||
// joystick values are repeated
|
||||
static int joyxmove;
|
||||
static int joyymove;
|
||||
|
|
@ -337,7 +358,63 @@ int G_CmdChecksum (ticcmd_t* cmd)
|
|||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
static boolean WeaponSelectable(weapontype_t weapon)
|
||||
{
|
||||
// Can't select a weapon if we don't own it.
|
||||
|
||||
if (!players[consoleplayer].weaponowned[weapon])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Can't select the fist if we have the chainsaw, unless
|
||||
// we also have the berserk pack.
|
||||
|
||||
if (weapon == wp_fist
|
||||
&& players[consoleplayer].weaponowned[wp_chainsaw]
|
||||
&& !players[consoleplayer].powers[pw_strength])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int G_NextWeapon(int direction)
|
||||
{
|
||||
weapontype_t weapon;
|
||||
int i;
|
||||
|
||||
// Find index in the table.
|
||||
|
||||
if (players[consoleplayer].pendingweapon == wp_nochange)
|
||||
{
|
||||
weapon = players[consoleplayer].readyweapon;
|
||||
}
|
||||
else
|
||||
{
|
||||
weapon = players[consoleplayer].pendingweapon;
|
||||
}
|
||||
|
||||
for (i=0; i<arrlen(weapon_order_table); ++i)
|
||||
{
|
||||
if (weapon_order_table[i].weapon == weapon)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Switch weapon.
|
||||
|
||||
do
|
||||
{
|
||||
i += direction;
|
||||
i = (i + arrlen(weapon_order_table)) % arrlen(weapon_order_table);
|
||||
} while (!WeaponSelectable(weapon_order_table[i].weapon));
|
||||
|
||||
return weapon_order_table[i].weapon_num;
|
||||
}
|
||||
|
||||
//
|
||||
// G_BuildTiccmd
|
||||
|
|
@ -465,20 +542,34 @@ void G_BuildTiccmd (ticcmd_t* cmd)
|
|||
dclicks = 0;
|
||||
}
|
||||
|
||||
// chainsaw overrides
|
||||
// If the previous or next weapon button is pressed, the
|
||||
// next_weapon variable is set to change weapons when
|
||||
// we generate a ticcmd. Choose a new weapon.
|
||||
|
||||
for (i=0; i<arrlen(weapon_keys); ++i)
|
||||
if (next_weapon != 0)
|
||||
{
|
||||
int key = *weapon_keys[i];
|
||||
i = G_NextWeapon(next_weapon);
|
||||
cmd->buttons |= BT_CHANGE;
|
||||
cmd->buttons |= i << BT_WEAPONSHIFT;
|
||||
next_weapon = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check weapon keys.
|
||||
|
||||
if (gamekeydown[key])
|
||||
for (i=0; i<arrlen(weapon_keys); ++i)
|
||||
{
|
||||
cmd->buttons |= BT_CHANGE;
|
||||
cmd->buttons |= i<<BT_WEAPONSHIFT;
|
||||
break;
|
||||
int key = *weapon_keys[i];
|
||||
|
||||
if (gamekeydown[key])
|
||||
{
|
||||
cmd->buttons |= BT_CHANGE;
|
||||
cmd->buttons |= i<<BT_WEAPONSHIFT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mouse
|
||||
if (mousebuttons[mousebforward])
|
||||
{
|
||||
|
|
@ -657,7 +748,6 @@ void G_DoLoadLevel (void)
|
|||
players[consoleplayer].message = "Press escape to quit.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SetJoyButtons(unsigned int buttons_mask)
|
||||
{
|
||||
|
|
@ -665,10 +755,54 @@ static void SetJoyButtons(unsigned int buttons_mask)
|
|||
|
||||
for (i=0; i<MAX_JOY_BUTTONS; ++i)
|
||||
{
|
||||
joybuttons[i] = (buttons_mask & (1 << i)) != 0;
|
||||
int button_on = (buttons_mask & (1 << i)) != 0;
|
||||
|
||||
// Detect button press:
|
||||
|
||||
if (!joybuttons[i] && button_on)
|
||||
{
|
||||
// Weapon cycling:
|
||||
|
||||
if (i == joybprevweapon)
|
||||
{
|
||||
next_weapon = -1;
|
||||
}
|
||||
else if (i == joybnextweapon)
|
||||
{
|
||||
next_weapon = 1;
|
||||
}
|
||||
}
|
||||
|
||||
joybuttons[i] = button_on;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SetMouseButtons(unsigned int buttons_mask)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_MOUSE_BUTTONS; ++i)
|
||||
{
|
||||
unsigned int button_on = (buttons_mask & (1 << i)) != 0;
|
||||
|
||||
// Detect button press:
|
||||
|
||||
if (!mousebuttons[i] && button_on)
|
||||
{
|
||||
if (i == mousebprevweapon)
|
||||
{
|
||||
next_weapon = -1;
|
||||
}
|
||||
else if (i == mousebnextweapon)
|
||||
{
|
||||
next_weapon = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mousebuttons[i] = button_on;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// G_Responder
|
||||
// Get info needed to make ticcmd_ts for the players.
|
||||
|
|
@ -677,7 +811,7 @@ boolean G_Responder (event_t* ev)
|
|||
{
|
||||
// allow spy mode changes even during the demo
|
||||
if (gamestate == GS_LEVEL && ev->type == ev_keydown
|
||||
&& ev->data1 == KEY_F12 && (singledemo || !deathmatch) )
|
||||
&& ev->data1 == key_spy && (singledemo || !deathmatch) )
|
||||
{
|
||||
// spy mode
|
||||
do
|
||||
|
|
@ -737,6 +871,18 @@ boolean G_Responder (event_t* ev)
|
|||
testcontrols_mousespeed = abs(ev->data2);
|
||||
}
|
||||
|
||||
// If the next/previous weapon keys are pressed, set the next_weapon
|
||||
// variable to change weapons when the next ticcmd is generated.
|
||||
|
||||
if (ev->type == ev_keydown && ev->data1 == key_prevweapon)
|
||||
{
|
||||
next_weapon = -1;
|
||||
}
|
||||
else if (ev->type == ev_keydown && ev->data1 == key_nextweapon)
|
||||
{
|
||||
next_weapon = 1;
|
||||
}
|
||||
|
||||
switch (ev->type)
|
||||
{
|
||||
case ev_keydown:
|
||||
|
|
@ -757,9 +903,7 @@ boolean G_Responder (event_t* ev)
|
|||
return false; // always let key up events filter down
|
||||
|
||||
case ev_mouse:
|
||||
mousebuttons[0] = ev->data1 & 1;
|
||||
mousebuttons[1] = ev->data1 & 2;
|
||||
mousebuttons[2] = ev->data1 & 4;
|
||||
SetMouseButtons(ev->data1);
|
||||
mousex = ev->data2*(mouseSensitivity+5)/10;
|
||||
mousey = ev->data3*(mouseSensitivity+5)/10;
|
||||
return true; // eat events
|
||||
|
|
@ -1428,6 +1572,8 @@ void G_DoLoadGame (void)
|
|||
return;
|
||||
}
|
||||
|
||||
savegame_error = false;
|
||||
|
||||
if (!P_ReadSaveGameHeader())
|
||||
{
|
||||
fclose(save_stream);
|
||||
|
|
@ -1495,6 +1641,8 @@ void G_DoSaveGame (void)
|
|||
return;
|
||||
}
|
||||
|
||||
savegame_error = false;
|
||||
|
||||
P_WriteSaveGameHeader(savedescription);
|
||||
|
||||
P_ArchivePlayers ();
|
||||
|
|
@ -1780,7 +1928,7 @@ void G_WriteDemoTiccmd (ticcmd_t* cmd)
|
|||
{
|
||||
byte *demo_start;
|
||||
|
||||
if (gamekeydown['q']) // press q to end demo recording
|
||||
if (gamekeydown[key_demo_quit]) // press q to end demo recording
|
||||
G_CheckDemoStatus ();
|
||||
|
||||
demo_start = demo_p;
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ void HU_Init(void)
|
|||
j = HU_FONTSTART;
|
||||
for (i=0;i<HU_FONTSIZE;i++)
|
||||
{
|
||||
sprintf(buffer, DEH_String("STCFN%.3d"), j++);
|
||||
DEH_snprintf(buffer, 9, "STCFN%.3d", j++);
|
||||
hu_font[i] = (patch_t *) W_CacheLumpName(buffer, PU_STATIC);
|
||||
}
|
||||
|
||||
|
|
@ -529,14 +529,6 @@ boolean HU_Responder(event_t *ev)
|
|||
int i;
|
||||
int numplayers;
|
||||
|
||||
static char destination_keys[MAXPLAYERS] =
|
||||
{
|
||||
HUSTR_KEYGREEN,
|
||||
HUSTR_KEYINDIGO,
|
||||
HUSTR_KEYBROWN,
|
||||
HUSTR_KEYRED
|
||||
};
|
||||
|
||||
static int num_nobrainers = 0;
|
||||
|
||||
numplayers = 0;
|
||||
|
|
@ -565,7 +557,7 @@ boolean HU_Responder(event_t *ev)
|
|||
message_counter = HU_MSGTIMEOUT;
|
||||
eatkey = true;
|
||||
}
|
||||
else if (netgame && ev->data2 == HU_INPUTTOGGLE)
|
||||
else if (netgame && ev->data2 == key_multi_msg)
|
||||
{
|
||||
eatkey = chat_on = true;
|
||||
HUlib_resetIText(&w_chat);
|
||||
|
|
@ -575,7 +567,7 @@ boolean HU_Responder(event_t *ev)
|
|||
{
|
||||
for (i=0; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
if (ev->data2 == destination_keys[i])
|
||||
if (ev->data2 == key_multi_msgplayer[i])
|
||||
{
|
||||
if (playeringame[i] && i!=consoleplayer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ void M_QuickSave(void)
|
|||
quickSaveSlot = -2; // means to pick a slot now
|
||||
return;
|
||||
}
|
||||
sprintf(tempstring,DEH_String(QSPROMPT),savegamestrings[quickSaveSlot]);
|
||||
DEH_snprintf(tempstring, 80, QSPROMPT, savegamestrings[quickSaveSlot]);
|
||||
M_StartMessage(tempstring,M_QuickSaveResponse,true);
|
||||
}
|
||||
|
||||
|
|
@ -739,7 +739,7 @@ void M_QuickLoad(void)
|
|||
M_StartMessage(DEH_String(QSAVESPOT),NULL,false);
|
||||
return;
|
||||
}
|
||||
sprintf(tempstring,DEH_String(QLPROMPT),savegamestrings[quickSaveSlot]);
|
||||
DEH_snprintf(tempstring, 80, QLPROMPT, savegamestrings[quickSaveSlot]);
|
||||
M_StartMessage(tempstring,M_QuickLoadResponse,true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
FILE *save_stream;
|
||||
int savegamelength;
|
||||
boolean savegame_error;
|
||||
|
||||
// Get the filename of a temporary file to write the savegame to. After
|
||||
// the file has been successfully saved, it will be renamed to the
|
||||
|
|
@ -75,7 +76,7 @@ char *P_SaveGameFile(int slot)
|
|||
filename = malloc(strlen(savegamedir) + 32);
|
||||
}
|
||||
|
||||
sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot);
|
||||
DEH_snprintf(basename, 32, SAVEGAMENAME "%d.dsg", slot);
|
||||
|
||||
sprintf(filename, "%s%s", savegamedir, basename);
|
||||
|
||||
|
|
@ -88,14 +89,31 @@ static byte saveg_read8(void)
|
|||
{
|
||||
byte result;
|
||||
|
||||
fread(&result, 1, 1, save_stream);
|
||||
if (fread(&result, 1, 1, save_stream) < 1)
|
||||
{
|
||||
if (!savegame_error)
|
||||
{
|
||||
fprintf(stderr, "saveg_read8: Unexpected end of file while "
|
||||
"reading save game\n");
|
||||
|
||||
savegame_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void saveg_write8(byte value)
|
||||
{
|
||||
fwrite(&value, 1, 1, save_stream);
|
||||
if (fwrite(&value, 1, 1, save_stream) < 1)
|
||||
{
|
||||
if (!savegame_error)
|
||||
{
|
||||
fprintf(stderr, "saveg_write8: Error while writing save game\n");
|
||||
|
||||
savegame_error = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static short saveg_read16(void)
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ void P_ArchiveSpecials (void);
|
|||
void P_UnArchiveSpecials (void);
|
||||
|
||||
extern FILE *save_stream;
|
||||
extern boolean savegame_error;
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "deh_main.h"
|
||||
#include "i_swap.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_bbox.h"
|
||||
|
||||
#include "g_game.h"
|
||||
|
|
@ -76,6 +77,7 @@ line_t* lines;
|
|||
int numsides;
|
||||
side_t* sides;
|
||||
|
||||
static int totallines;
|
||||
|
||||
// BLOCKMAP
|
||||
// Created from axis aligned bounding box
|
||||
|
|
@ -534,7 +536,6 @@ void P_GroupLines (void)
|
|||
line_t** linebuffer;
|
||||
int i;
|
||||
int j;
|
||||
int total;
|
||||
line_t* li;
|
||||
sector_t* sector;
|
||||
subsector_t* ss;
|
||||
|
|
@ -552,21 +553,21 @@ void P_GroupLines (void)
|
|||
|
||||
// count number of lines in each sector
|
||||
li = lines;
|
||||
total = 0;
|
||||
totallines = 0;
|
||||
for (i=0 ; i<numlines ; i++, li++)
|
||||
{
|
||||
total++;
|
||||
totallines++;
|
||||
li->frontsector->linecount++;
|
||||
|
||||
if (li->backsector && li->backsector != li->frontsector)
|
||||
{
|
||||
li->backsector->linecount++;
|
||||
total++;
|
||||
totallines++;
|
||||
}
|
||||
}
|
||||
|
||||
// build line tables for each sector
|
||||
linebuffer = Z_Malloc (total*sizeof(line_t *), PU_LEVEL, 0);
|
||||
linebuffer = Z_Malloc (totallines*sizeof(line_t *), PU_LEVEL, 0);
|
||||
|
||||
for (i=0; i<numsectors; ++i)
|
||||
{
|
||||
|
|
@ -643,6 +644,87 @@ void P_GroupLines (void)
|
|||
|
||||
}
|
||||
|
||||
// Pad the REJECT lump with extra data when the lump is too small,
|
||||
// to simulate a REJECT buffer overflow in Vanilla Doom.
|
||||
|
||||
static void PadRejectArray(byte *array, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int byte_num;
|
||||
byte *dest;
|
||||
unsigned int padvalue;
|
||||
|
||||
// Values to pad the REJECT array with:
|
||||
|
||||
unsigned int rejectpad[4] =
|
||||
{
|
||||
((totallines * 4 + 3) & ~3) + 24, // Size
|
||||
0, // Part of z_zone block header
|
||||
50, // PU_LEVEL
|
||||
0x1d4a11 // DOOM_CONST_ZONEID
|
||||
};
|
||||
|
||||
// Copy values from rejectpad into the destination array.
|
||||
|
||||
dest = array;
|
||||
|
||||
for (i=0; i<len && i<sizeof(rejectpad); ++i)
|
||||
{
|
||||
byte_num = i % 4;
|
||||
*dest = (rejectpad[i / 4] >> (byte_num * 8)) & 0xff;
|
||||
++dest;
|
||||
}
|
||||
|
||||
// We only have a limited pad size. Print a warning if the
|
||||
// REJECT lump is too small.
|
||||
|
||||
if (len > sizeof(rejectpad))
|
||||
{
|
||||
fprintf(stderr, "PadRejectArray: REJECT lump too short to pad! (%i > %i)\n",
|
||||
len, sizeof(rejectpad));
|
||||
|
||||
// Pad remaining space with 0 (or 0xff, if specified on command line).
|
||||
|
||||
if (M_CheckParm("-reject_pad_with_ff"))
|
||||
{
|
||||
padvalue = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
padvalue = 0xf00;
|
||||
}
|
||||
|
||||
memset(array + sizeof(rejectpad), padvalue, len - sizeof(rejectpad));
|
||||
}
|
||||
}
|
||||
|
||||
static void P_LoadReject(int lumpnum)
|
||||
{
|
||||
int minlength;
|
||||
int lumplen;
|
||||
|
||||
// Calculate the size that the REJECT lump *should* be.
|
||||
|
||||
minlength = (numsectors * numsectors + 7) / 8;
|
||||
|
||||
// If the lump meets the minimum length, it can be loaded directly.
|
||||
// Otherwise, we need to allocate a buffer of the correct size
|
||||
// and pad it with appropriate data.
|
||||
|
||||
lumplen = W_LumpLength(lumpnum);
|
||||
|
||||
if (lumplen >= minlength)
|
||||
{
|
||||
rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
rejectmatrix = Z_Malloc(minlength, PU_LEVEL, &rejectmatrix);
|
||||
W_ReadLump(lumpnum, rejectmatrix);
|
||||
|
||||
PadRejectArray(rejectmatrix + lumplen, minlength - lumplen);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_SetupLevel
|
||||
|
|
@ -692,9 +774,9 @@ P_SetupLevel
|
|||
if ( gamemode == commercial)
|
||||
{
|
||||
if (map<10)
|
||||
sprintf (lumpname, DEH_String("map0%i"), map);
|
||||
DEH_snprintf(lumpname, 9, "map0%i", map);
|
||||
else
|
||||
sprintf (lumpname, DEH_String("map%i"), map);
|
||||
DEH_snprintf(lumpname, 9, "map%i", map);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -719,9 +801,9 @@ P_SetupLevel
|
|||
P_LoadSubsectors (lumpnum+ML_SSECTORS);
|
||||
P_LoadNodes (lumpnum+ML_NODES);
|
||||
P_LoadSegs (lumpnum+ML_SEGS);
|
||||
|
||||
rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
|
||||
|
||||
P_GroupLines ();
|
||||
P_LoadReject (lumpnum+ML_REJECT);
|
||||
|
||||
bodyqueslot = 0;
|
||||
deathmatch_p = deathmatchstarts;
|
||||
|
|
|
|||
|
|
@ -597,48 +597,54 @@ int dscount;
|
|||
// Draws the actual span.
|
||||
void R_DrawSpan (void)
|
||||
{
|
||||
fixed_t xfrac;
|
||||
fixed_t yfrac;
|
||||
byte* dest;
|
||||
int count;
|
||||
int spot;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
unsigned int position, step;
|
||||
byte *dest;
|
||||
int count;
|
||||
int spot;
|
||||
unsigned int xtemp, ytemp;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (ds_x2 < ds_x1
|
||||
|| ds_x1<0
|
||||
|| ds_x2>=SCREENWIDTH
|
||||
|| ds_x2>=SCREENWIDTH
|
||||
|| (unsigned)ds_y>SCREENHEIGHT)
|
||||
{
|
||||
I_Error( "R_DrawSpan: %i to %i at %i",
|
||||
ds_x1,ds_x2,ds_y);
|
||||
}
|
||||
// dscount++;
|
||||
#endif
|
||||
// dscount++;
|
||||
#endif
|
||||
|
||||
// Pack position and step variables into a single 32-bit integer,
|
||||
// with x in the top 16 bits and y in the bottom 16 bits. For
|
||||
// each 16-bit part, the top 6 bits are the integer part and the
|
||||
// bottom 10 bits are the fractional part of the pixel position.
|
||||
|
||||
position = ((ds_xfrac << 10) & 0xffff0000)
|
||||
| ((ds_yfrac >> 6) & 0x0000ffff);
|
||||
step = ((ds_xstep << 10) & 0xffff0000)
|
||||
| ((ds_ystep >> 6) & 0x0000ffff);
|
||||
|
||||
|
||||
xfrac = ds_xfrac;
|
||||
yfrac = ds_yfrac;
|
||||
|
||||
dest = ylookup[ds_y] + columnofs[ds_x1];
|
||||
|
||||
// We do not check for zero spans here?
|
||||
count = ds_x2 - ds_x1;
|
||||
count = ds_x2 - ds_x1;
|
||||
|
||||
do
|
||||
do
|
||||
{
|
||||
// Current texture index in u,v.
|
||||
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
||||
// Calculate current texture index in u,v.
|
||||
ytemp = (position >> 4) & 0x0fc0;
|
||||
xtemp = (position >> 26);
|
||||
spot = xtemp | ytemp;
|
||||
|
||||
// Lookup pixel from flat texture tile,
|
||||
// re-index using light/colormap.
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
|
||||
// Next step in u,v.
|
||||
xfrac += ds_xstep;
|
||||
yfrac += ds_ystep;
|
||||
|
||||
} while (count--);
|
||||
}
|
||||
position += step;
|
||||
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -718,49 +724,54 @@ void R_DrawSpan (void)
|
|||
//
|
||||
// Again..
|
||||
//
|
||||
void R_DrawSpanLow (void)
|
||||
{
|
||||
fixed_t xfrac;
|
||||
fixed_t yfrac;
|
||||
byte* dest;
|
||||
int count;
|
||||
int spot;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
void R_DrawSpanLow (void)
|
||||
{
|
||||
unsigned int position, step;
|
||||
unsigned int xtemp, ytemp;
|
||||
byte *dest;
|
||||
int count;
|
||||
int spot;
|
||||
|
||||
#ifdef RANGECHECK
|
||||
if (ds_x2 < ds_x1
|
||||
|| ds_x1<0
|
||||
|| ds_x2>=SCREENWIDTH
|
||||
|| ds_x2>=SCREENWIDTH
|
||||
|| (unsigned)ds_y>SCREENHEIGHT)
|
||||
{
|
||||
I_Error( "R_DrawSpan: %i to %i at %i",
|
||||
ds_x1,ds_x2,ds_y);
|
||||
}
|
||||
// dscount++;
|
||||
#endif
|
||||
|
||||
xfrac = ds_xfrac;
|
||||
yfrac = ds_yfrac;
|
||||
|
||||
count = (ds_x2 - ds_x1);
|
||||
#endif
|
||||
|
||||
position = ((ds_xfrac << 10) & 0xffff0000)
|
||||
| ((ds_yfrac >> 6) & 0x0000ffff);
|
||||
step = ((ds_xstep << 10) & 0xffff0000)
|
||||
| ((ds_ystep >> 6) & 0x0000ffff);
|
||||
|
||||
count = (ds_x2 - ds_x1);
|
||||
|
||||
// Blocky mode, need to multiply by 2.
|
||||
ds_x1 <<= 1;
|
||||
ds_x2 <<= 1;
|
||||
|
||||
|
||||
dest = ylookup[ds_y] + columnofs[ds_x1];
|
||||
|
||||
do
|
||||
{
|
||||
spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
|
||||
|
||||
do
|
||||
{
|
||||
// Calculate current texture index in u,v.
|
||||
ytemp = (position >> 4) & 0x0fc0;
|
||||
xtemp = (position >> 26);
|
||||
spot = xtemp | ytemp;
|
||||
|
||||
// Lowres/blocky mode does it twice,
|
||||
// while scale is adjusted appropriately.
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
|
||||
xfrac += ds_xstep;
|
||||
yfrac += ds_ystep;
|
||||
*dest++ = ds_colormap[ds_source[spot]];
|
||||
|
||||
} while (count--);
|
||||
position += step;
|
||||
|
||||
} while (count--);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -618,6 +618,15 @@ void S_ChangeMusic(int musicnum, int looping)
|
|||
char namebuf[9];
|
||||
void *handle;
|
||||
|
||||
// The Doom IWAD file has two versions of the intro music: d_intro
|
||||
// and d_introa. The latter is used for OPL playback.
|
||||
|
||||
if (musicnum == mus_intro && (snd_musicdevice == SNDDEVICE_ADLIB
|
||||
|| snd_musicdevice == SNDDEVICE_SB))
|
||||
{
|
||||
musicnum = mus_introa;
|
||||
}
|
||||
|
||||
if (musicnum <= mus_None || musicnum >= NUMMUSIC)
|
||||
{
|
||||
I_Error("Bad music number %d", musicnum);
|
||||
|
|
|
|||
|
|
@ -1085,10 +1085,10 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
|
|||
// Load the numbers, tall and short
|
||||
for (i=0;i<10;i++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("STTNUM%d"), i);
|
||||
DEH_snprintf(namebuf, 9, "STTNUM%d", i);
|
||||
callback(namebuf, &tallnum[i]);
|
||||
|
||||
sprintf(namebuf, DEH_String("STYSNUM%d"), i);
|
||||
DEH_snprintf(namebuf, 9, "STYSNUM%d", i);
|
||||
callback(namebuf, &shortnum[i]);
|
||||
}
|
||||
|
||||
|
|
@ -1100,7 +1100,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
|
|||
// key cards
|
||||
for (i=0;i<NUMCARDS;i++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("STKEYS%d"), i);
|
||||
DEH_snprintf(namebuf, 9, "STKEYS%d", i);
|
||||
callback(namebuf, &keys[i]);
|
||||
}
|
||||
|
||||
|
|
@ -1110,7 +1110,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
|
|||
// arms ownership widgets
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("STGNUM%d"), i+2);
|
||||
DEH_snprintf(namebuf, 9, "STGNUM%d", i+2);
|
||||
|
||||
// gray #
|
||||
callback(namebuf, &arms[i][0]);
|
||||
|
|
@ -1120,7 +1120,7 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
|
|||
}
|
||||
|
||||
// face backgrounds for different color players
|
||||
sprintf(namebuf, DEH_String("STFB%d"), consoleplayer);
|
||||
DEH_snprintf(namebuf, 9, "STFB%d", consoleplayer);
|
||||
callback(namebuf, &faceback);
|
||||
|
||||
// status bar background bits
|
||||
|
|
@ -1132,23 +1132,23 @@ static void ST_loadUnloadGraphics(load_callback_t callback)
|
|||
{
|
||||
for (j=0; j<ST_NUMSTRAIGHTFACES; j++)
|
||||
{
|
||||
sprintf(namebuf, DEH_String("STFST%d%d"), i, j);
|
||||
DEH_snprintf(namebuf, 9, "STFST%d%d", i, j);
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
}
|
||||
sprintf(namebuf, DEH_String("STFTR%d0"), i); // turn right
|
||||
DEH_snprintf(namebuf, 9, "STFTR%d0", i); // turn right
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
sprintf(namebuf, DEH_String("STFTL%d0"), i); // turn left
|
||||
DEH_snprintf(namebuf, 9, "STFTL%d0", i); // turn left
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
sprintf(namebuf, DEH_String("STFOUCH%d"), i); // ouch!
|
||||
DEH_snprintf(namebuf, 9, "STFOUCH%d", i); // ouch!
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
sprintf(namebuf, DEH_String("STFEVL%d"), i); // evil grin ;)
|
||||
DEH_snprintf(namebuf, 9, "STFEVL%d", i); // evil grin ;)
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
sprintf(namebuf, DEH_String("STFKILL%d"), i); // pissed off
|
||||
DEH_snprintf(namebuf, 9, "STFKILL%d", i); // pissed off
|
||||
callback(namebuf, &faces[facenum]);
|
||||
++facenum;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1571,16 +1571,16 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
if (gamemode == commercial)
|
||||
{
|
||||
for (i=0 ; i<NUMCMAPS ; i++)
|
||||
{
|
||||
sprintf(name, DEH_String("CWILV%2.2d"), i);
|
||||
{
|
||||
DEH_snprintf(name, 9, "CWILV%2.2d", i);
|
||||
callback(name, &lnames[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0 ; i<NUMMAPS ; i++)
|
||||
{
|
||||
sprintf(name, DEH_String("WILV%d%d"), wbs->epsd, i);
|
||||
DEH_snprintf(name, 9, "WILV%d%d", wbs->epsd, i);
|
||||
callback(name, &lnames[i]);
|
||||
}
|
||||
|
||||
|
|
@ -1592,7 +1592,7 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
|
||||
// splat
|
||||
callback(DEH_String("WISPLAT"), &splat[0]);
|
||||
|
||||
|
||||
if (wbs->epsd < 3)
|
||||
{
|
||||
for (j=0;j<NUMANIMS[wbs->epsd];j++)
|
||||
|
|
@ -1601,17 +1601,16 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
for (i=0;i<a->nanims;i++)
|
||||
{
|
||||
// MONDO HACK!
|
||||
if (wbs->epsd != 1 || j != 8)
|
||||
if (wbs->epsd != 1 || j != 8)
|
||||
{
|
||||
// animations
|
||||
sprintf(name, DEH_String("WIA%d%.2d%.2d"),
|
||||
wbs->epsd, j, i);
|
||||
DEH_snprintf(name, 9, "WIA%d%.2d%.2d", wbs->epsd, j, i);
|
||||
callback(name, &a->p[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK ALERT!
|
||||
a->p[i] = anims[1][4].p[i];
|
||||
a->p[i] = anims[1][4].p[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1624,7 +1623,7 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
for (i=0;i<10;i++)
|
||||
{
|
||||
// numbers 0-9
|
||||
sprintf(name, DEH_String("WINUM%d"), i);
|
||||
DEH_snprintf(name, 9, "WINUM%d", i);
|
||||
callback(name, &num[i]);
|
||||
}
|
||||
|
||||
|
|
@ -1665,13 +1664,13 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
callback(DEH_String("WICOLON"), &colon);
|
||||
|
||||
// "time"
|
||||
callback(DEH_String("WITIME"), &timepatch);
|
||||
callback(DEH_String("WITIME"), &timepatch);
|
||||
|
||||
// "sucks"
|
||||
callback(DEH_String("WISUCKS"), &sucks);
|
||||
callback(DEH_String("WISUCKS"), &sucks);
|
||||
|
||||
// "par"
|
||||
callback(DEH_String("WIPAR"), &par);
|
||||
callback(DEH_String("WIPAR"), &par);
|
||||
|
||||
// "killers" (vertical)
|
||||
callback(DEH_String("WIKILRS"), &killers);
|
||||
|
|
@ -1680,16 +1679,16 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
callback(DEH_String("WIVCTMS"), &victims);
|
||||
|
||||
// "total"
|
||||
callback(DEH_String("WIMSTT"), &total);
|
||||
callback(DEH_String("WIMSTT"), &total);
|
||||
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
{
|
||||
// "1,2,3,4"
|
||||
sprintf(name, DEH_String("STPB%d"), i);
|
||||
DEH_snprintf(name, 9, "STPB%d", i);
|
||||
callback(name, &p[i]);
|
||||
|
||||
// "1,2,3,4"
|
||||
sprintf(name, DEH_String("WIBP%d"), i+1);
|
||||
DEH_snprintf(name, 9, "WIBP%d", i+1);
|
||||
callback(name, &bp[i]);
|
||||
}
|
||||
|
||||
|
|
@ -1697,19 +1696,21 @@ static void WI_loadUnloadData(load_callback_t callback)
|
|||
|
||||
if (gamemode == commercial)
|
||||
{
|
||||
strcpy(name, DEH_String("INTERPIC"));
|
||||
strncpy(name, DEH_String("INTERPIC"), 9);
|
||||
name[8] = '\0';
|
||||
}
|
||||
else if (gamemode == retail && wbs->epsd == 3)
|
||||
{
|
||||
strcpy(name, DEH_String("INTERPIC"));
|
||||
strncpy(name, DEH_String("INTERPIC"), 9);
|
||||
name[8] = '\0';
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
sprintf(name, DEH_String("WIMAP%d"), wbs->epsd);
|
||||
DEH_snprintf(name, 9, "WIMAP%d", wbs->epsd);
|
||||
}
|
||||
|
||||
|
||||
// Draw backdrop and save to a temporary buffer
|
||||
|
||||
|
||||
callback(name, &background);
|
||||
}
|
||||
|
||||
|
|
@ -1722,7 +1723,7 @@ void WI_loadData(void)
|
|||
{
|
||||
if (gamemode == commercial)
|
||||
{
|
||||
NUMCMAPS = 32;
|
||||
NUMCMAPS = 32;
|
||||
lnames = (patch_t **) Z_Malloc(sizeof(patch_t*) * NUMCMAPS,
|
||||
PU_STATIC, NULL);
|
||||
}
|
||||
|
|
|
|||
7
src/heretic/.gitignore
vendored
7
src/heretic/.gitignore
vendored
|
|
@ -1,7 +1,6 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
*.rc
|
||||
chocolate-doom
|
||||
chocolate-server
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ info.c info.h \
|
|||
in_lude.c \
|
||||
m_random.c m_random.h \
|
||||
mn_menu.c \
|
||||
p_action.h \
|
||||
p_ceilng.c \
|
||||
p_doors.c \
|
||||
p_enemy.c \
|
||||
|
|
@ -55,5 +56,15 @@ EXTRA_DIST= \
|
|||
i_sound.c \
|
||||
i_ibm.c
|
||||
|
||||
libheretic_a_SOURCES=$(SOURCE_FILES)
|
||||
FEATURE_DEHACKED_SOURCE_FILES = \
|
||||
deh_ammo.c \
|
||||
deh_frame.c \
|
||||
deh_htext.c \
|
||||
deh_htic.c \
|
||||
deh_sound.c \
|
||||
deh_thing.c \
|
||||
deh_weapon.c
|
||||
|
||||
libheretic_a_SOURCES=$(SOURCE_FILES) \
|
||||
$(FEATURE_DEHACKED_SOURCE_FILES)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_video.h"
|
||||
#include "m_controls.h"
|
||||
#include "p_local.h"
|
||||
|
|
@ -408,7 +409,7 @@ void AM_loadPics(void)
|
|||
sprintf(namebuf, "AMMNUM%d", i);
|
||||
marknums[i] = W_CacheLumpName(namebuf, PU_STATIC);
|
||||
}*/
|
||||
maplump = W_CacheLumpName("AUTOPAGE", PU_STATIC);
|
||||
maplump = W_CacheLumpName(DEH_String("AUTOPAGE"), PU_STATIC);
|
||||
}
|
||||
|
||||
/*void AM_unloadPics(void)
|
||||
|
|
@ -1473,6 +1474,7 @@ void AM_drawCrosshair(int color)
|
|||
|
||||
void AM_Drawer(void)
|
||||
{
|
||||
char *level_name;
|
||||
int numepisodes;
|
||||
|
||||
if (!automapactive)
|
||||
|
|
@ -1505,7 +1507,8 @@ void AM_Drawer(void)
|
|||
|
||||
if (gameepisode <= numepisodes && gamemap < 10)
|
||||
{
|
||||
MN_DrTextA(LevelNames[(gameepisode - 1) * 9 + gamemap - 1], 20, 145);
|
||||
level_name = LevelNames[(gameepisode - 1) * 9 + gamemap - 1];
|
||||
MN_DrTextA(DEH_String(level_name), 20, 145);
|
||||
}
|
||||
// I_Update();
|
||||
// V_MarkRect(f_x, f_y, f_w, f_h);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <ctype.h>
|
||||
#include "doomdef.h"
|
||||
#include "doomkeys.h"
|
||||
#include "deh_str.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "v_video.h"
|
||||
|
|
@ -115,7 +116,7 @@ void CT_Init(void)
|
|||
memset(plr_lastmsg[i], 0, MESSAGESIZE);
|
||||
memset(chat_msg[i], 0, MESSAGESIZE);
|
||||
}
|
||||
FontABaseLump = W_GetNumForName("FONTA_S") + 1;
|
||||
FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +301,9 @@ void CT_Ticker(void)
|
|||
CT_AddChar(i, 0); // set the end of message character
|
||||
if (numplayers > 2)
|
||||
{
|
||||
strcpy(plr_lastmsg[i], CT_FromPlrText[i]);
|
||||
strncpy(plr_lastmsg[i], DEH_String(CT_FromPlrText[i]),
|
||||
MESSAGESIZE + 9);
|
||||
plr_lastmsg[i][MESSAGESIZE + 8] = '\0';
|
||||
strcat(plr_lastmsg[i], chat_msg[i]);
|
||||
}
|
||||
else
|
||||
|
|
@ -320,13 +323,13 @@ void CT_Ticker(void)
|
|||
if (numplayers > 1)
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer],
|
||||
"-MESSAGE SENT-", true);
|
||||
DEH_String("-MESSAGE SENT-"), true);
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer],
|
||||
"THERE ARE NO OTHER PLAYERS IN THE GAME!",
|
||||
DEH_String("THERE ARE NO OTHER PLAYERS IN THE GAME!"),
|
||||
true);
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
}
|
||||
|
|
@ -376,7 +379,7 @@ void CT_Drawer(void)
|
|||
x += patch->width;
|
||||
}
|
||||
}
|
||||
V_DrawPatch(x, 10, W_CacheLumpName("FONTA59", PU_CACHE));
|
||||
V_DrawPatch(x, 10, W_CacheLumpName(DEH_String("FONTA59"), PU_CACHE));
|
||||
BorderTopRefresh = true;
|
||||
UpdateState |= I_MESSAGES;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "config.h"
|
||||
#include "ct_chat.h"
|
||||
#include "doomdef.h"
|
||||
#include "deh_main.h"
|
||||
#include "d_iwad.h"
|
||||
#include "i_endoom.h"
|
||||
#include "i_joystick.h"
|
||||
|
|
@ -45,6 +46,7 @@
|
|||
#include "m_controls.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "w_main.h"
|
||||
#include "v_video.h"
|
||||
|
||||
#define STARTUP_WINDOW_X 17
|
||||
|
|
@ -184,12 +186,12 @@ void D_Display(void)
|
|||
{
|
||||
if (!netgame)
|
||||
{
|
||||
V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName("PAUSED",
|
||||
V_DrawPatch(160, viewwindowy + 5, W_CacheLumpName(DEH_String("PAUSED"),
|
||||
PU_CACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawPatch(160, 70, W_CacheLumpName("PAUSED", PU_CACHE));
|
||||
V_DrawPatch(160, 70, W_CacheLumpName(DEH_String("PAUSED"), PU_CACHE));
|
||||
}
|
||||
}
|
||||
// Handle player messages
|
||||
|
|
@ -315,7 +317,7 @@ void D_PageDrawer(void)
|
|||
V_DrawRawScreen(W_CacheLumpName(pagename, PU_CACHE));
|
||||
if (demosequence == 1)
|
||||
{
|
||||
V_DrawPatch(4, 160, W_CacheLumpName("ADVISOR", PU_CACHE));
|
||||
V_DrawPatch(4, 160, W_CacheLumpName(DEH_String("ADVISOR"), PU_CACHE));
|
||||
}
|
||||
UpdateState |= I_FULLSCRN;
|
||||
}
|
||||
|
|
@ -347,45 +349,45 @@ void D_DoAdvanceDemo(void)
|
|||
case 0:
|
||||
pagetic = 210;
|
||||
gamestate = GS_DEMOSCREEN;
|
||||
pagename = "TITLE";
|
||||
pagename = DEH_String("TITLE");
|
||||
S_StartSong(mus_titl, false);
|
||||
break;
|
||||
case 1:
|
||||
pagetic = 140;
|
||||
gamestate = GS_DEMOSCREEN;
|
||||
pagename = "TITLE";
|
||||
pagename = DEH_String("TITLE");
|
||||
break;
|
||||
case 2:
|
||||
BorderNeedRefresh = true;
|
||||
UpdateState |= I_FULLSCRN;
|
||||
G_DeferedPlayDemo("demo1");
|
||||
G_DeferedPlayDemo(DEH_String("demo1"));
|
||||
break;
|
||||
case 3:
|
||||
pagetic = 200;
|
||||
gamestate = GS_DEMOSCREEN;
|
||||
pagename = "CREDIT";
|
||||
pagename = DEH_String("CREDIT");
|
||||
break;
|
||||
case 4:
|
||||
BorderNeedRefresh = true;
|
||||
UpdateState |= I_FULLSCRN;
|
||||
G_DeferedPlayDemo("demo2");
|
||||
G_DeferedPlayDemo(DEH_String("demo2"));
|
||||
break;
|
||||
case 5:
|
||||
pagetic = 200;
|
||||
gamestate = GS_DEMOSCREEN;
|
||||
if (gamemode == shareware)
|
||||
{
|
||||
pagename = "ORDER";
|
||||
pagename = DEH_String("ORDER");
|
||||
}
|
||||
else
|
||||
{
|
||||
pagename = "CREDIT";
|
||||
pagename = DEH_String("CREDIT");
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
BorderNeedRefresh = true;
|
||||
UpdateState |= I_FULLSCRN;
|
||||
G_DeferedPlayDemo("demo3");
|
||||
G_DeferedPlayDemo(DEH_String("demo3"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -638,7 +640,7 @@ void initStartup(void)
|
|||
|
||||
// Blit main screen
|
||||
textScreen = TXT_GetScreenData();
|
||||
loading = W_CacheLumpName("LOADING", PU_CACHE);
|
||||
loading = W_CacheLumpName(DEH_String("LOADING"), PU_CACHE);
|
||||
memcpy(textScreen, loading, 4000);
|
||||
|
||||
// Print version string
|
||||
|
|
@ -698,7 +700,7 @@ void tprintf(char *msg, int initflag)
|
|||
// haleyjd: moved up, removed WATCOMC code
|
||||
void CleanExit(void)
|
||||
{
|
||||
printf("Exited from HERETIC.\n");
|
||||
DEH_printf("Exited from HERETIC.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -746,6 +748,7 @@ void D_BindVariables(void)
|
|||
M_BindBaseControls();
|
||||
M_BindHereticControls();
|
||||
M_BindWeaponControls();
|
||||
M_BindChatControls(MAXPLAYERS);
|
||||
|
||||
M_BindMenuControls();
|
||||
M_BindMapControls();
|
||||
|
|
@ -782,7 +785,7 @@ static void D_Endoom(void)
|
|||
return;
|
||||
}
|
||||
|
||||
endoom_data = W_CacheLumpName("ENDTEXT", PU_STATIC);
|
||||
endoom_data = W_CacheLumpName(DEH_String("ENDTEXT"), PU_STATIC);
|
||||
|
||||
I_Endoom(endoom_data);
|
||||
}
|
||||
|
|
@ -847,7 +850,7 @@ void D_DoomMain(void)
|
|||
//
|
||||
// init subsystems
|
||||
//
|
||||
printf("V_Init: allocate screens.\n");
|
||||
DEH_printf("V_Init: allocate screens.\n");
|
||||
V_Init();
|
||||
|
||||
// Check for -CDROM
|
||||
|
|
@ -872,7 +875,7 @@ void D_DoomMain(void)
|
|||
|
||||
if (cdrom)
|
||||
{
|
||||
M_SetConfigDir("c:\\heretic.cd\\");
|
||||
M_SetConfigDir(DEH_String("c:\\heretic.cd"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -880,17 +883,22 @@ void D_DoomMain(void)
|
|||
}
|
||||
|
||||
// Load defaults before initing other systems
|
||||
printf("M_LoadDefaults: Load system defaults.\n");
|
||||
DEH_printf("M_LoadDefaults: Load system defaults.\n");
|
||||
D_BindVariables();
|
||||
M_SetConfigFilenames("heretic.cfg", PROGRAM_PREFIX "heretic.cfg");
|
||||
M_LoadDefaults();
|
||||
|
||||
I_AtExit(M_SaveDefaults, false);
|
||||
|
||||
printf("Z_Init: Init zone memory allocation daemon.\n");
|
||||
DEH_printf("Z_Init: Init zone memory allocation daemon.\n");
|
||||
Z_Init();
|
||||
|
||||
printf("W_Init: Init WADfiles.\n");
|
||||
#ifdef FEATURE_DEHACKED
|
||||
printf("DEH_Init: Init Dehacked support.\n");
|
||||
DEH_Init();
|
||||
#endif
|
||||
|
||||
DEH_printf("W_Init: Init WADfiles.\n");
|
||||
|
||||
iwadfile = D_FindIWAD(IWAD_MASK_HERETIC, &gamemission);
|
||||
|
||||
|
|
@ -901,24 +909,7 @@ void D_DoomMain(void)
|
|||
}
|
||||
|
||||
D_AddFile(iwadfile);
|
||||
|
||||
// -FILE [filename] [filename] ...
|
||||
// Add files to the wad list.
|
||||
p = M_CheckParm("-file");
|
||||
|
||||
if (p)
|
||||
{
|
||||
char *filename;
|
||||
|
||||
// the parms after p are wadfile/lump names, until end of parms
|
||||
// or another - preceded parm
|
||||
|
||||
while (++p != myargc && myargv[p][0] != '-')
|
||||
{
|
||||
filename = D_FindWADByName(myargv[p]);
|
||||
D_AddFile(filename);
|
||||
}
|
||||
}
|
||||
W_ParseCommandLine();
|
||||
|
||||
p = M_CheckParm("-playdemo");
|
||||
if (!p)
|
||||
|
|
@ -927,12 +918,12 @@ void D_DoomMain(void)
|
|||
}
|
||||
if (p && p < myargc - 1)
|
||||
{
|
||||
sprintf(file, "%s.lmp", myargv[p + 1]);
|
||||
DEH_snprintf(file, sizeof(file), "%s.lmp", myargv[p + 1]);
|
||||
D_AddFile(file);
|
||||
printf("Playing demo %s.lmp.\n", myargv[p + 1]);
|
||||
DEH_printf("Playing demo %s.lmp.\n", myargv[p + 1]);
|
||||
}
|
||||
|
||||
if (W_CheckNumForName("E2M1") == -1)
|
||||
if (W_CheckNumForName(DEH_String("E2M1")) == -1)
|
||||
{
|
||||
gamemode = shareware;
|
||||
gamedescription = "Heretic (shareware)";
|
||||
|
|
@ -960,54 +951,55 @@ void D_DoomMain(void)
|
|||
//
|
||||
smsg[0] = 0;
|
||||
if (deathmatch)
|
||||
status("DeathMatch...");
|
||||
status(DEH_String("DeathMatch..."));
|
||||
if (nomonsters)
|
||||
status("No Monsters...");
|
||||
status(DEH_String("No Monsters..."));
|
||||
if (respawnparm)
|
||||
status("Respawning...");
|
||||
status(DEH_String("Respawning..."));
|
||||
if (autostart)
|
||||
{
|
||||
char temp[64];
|
||||
sprintf(temp, "Warp to Episode %d, Map %d, Skill %d ",
|
||||
startepisode, startmap, startskill + 1);
|
||||
DEH_snprintf(temp, sizeof(temp),
|
||||
"Warp to Episode %d, Map %d, Skill %d ",
|
||||
startepisode, startmap, startskill + 1);
|
||||
status(temp);
|
||||
}
|
||||
wadprintf(); // print the added wadfiles
|
||||
|
||||
tprintf("MN_Init: Init menu system.\n", 1);
|
||||
tprintf(DEH_String("MN_Init: Init menu system.\n"), 1);
|
||||
MN_Init();
|
||||
|
||||
CT_Init();
|
||||
|
||||
tprintf("R_Init: Init Heretic refresh daemon.", 1);
|
||||
hprintf("Loading graphics");
|
||||
tprintf(DEH_String("R_Init: Init Heretic refresh daemon."), 1);
|
||||
hprintf(DEH_String("Loading graphics"));
|
||||
R_Init();
|
||||
tprintf("\n", 0);
|
||||
|
||||
tprintf("P_Init: Init Playloop state.\n", 1);
|
||||
hprintf("Init game engine.");
|
||||
tprintf(DEH_String("P_Init: Init Playloop state.\n"), 1);
|
||||
hprintf(DEH_String("Init game engine."));
|
||||
P_Init();
|
||||
IncThermo();
|
||||
|
||||
tprintf("I_Init: Setting up machine state.\n", 1);
|
||||
tprintf(DEH_String("I_Init: Setting up machine state.\n"), 1);
|
||||
I_CheckIsScreensaver();
|
||||
I_InitTimer();
|
||||
I_InitJoystick();
|
||||
IncThermo();
|
||||
|
||||
tprintf("S_Init: Setting up sound.\n", 1);
|
||||
tprintf(DEH_String("S_Init: Setting up sound.\n"), 1);
|
||||
S_Init();
|
||||
//IO_StartupTimer();
|
||||
S_Start();
|
||||
|
||||
tprintf("D_CheckNetGame: Checking network game status.\n", 1);
|
||||
hprintf("Checking network game status.");
|
||||
tprintf(DEH_String("D_CheckNetGame: Checking network game status.\n"), 1);
|
||||
hprintf(DEH_String("Checking network game status."));
|
||||
D_CheckNetGame();
|
||||
IncThermo();
|
||||
|
||||
// haleyjd: removed WATCOMC
|
||||
|
||||
tprintf("SB_Init: Loading patches.\n", 1);
|
||||
tprintf(DEH_String("SB_Init: Loading patches.\n"), 1);
|
||||
SB_Init();
|
||||
IncThermo();
|
||||
|
||||
|
|
|
|||
122
src/heretic/deh_ammo.c
Normal file
122
src/heretic/deh_ammo.c
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses "Ammo" sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "deh_defs.h"
|
||||
#include "deh_io.h"
|
||||
#include "deh_main.h"
|
||||
#include "p_local.h"
|
||||
|
||||
static void *DEH_AmmoStart(deh_context_t *context, char *line)
|
||||
{
|
||||
int ammo_number = 0;
|
||||
|
||||
if (sscanf(line, "Ammo %i", &ammo_number) != 1)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ammo_number < 0 || ammo_number >= NUMAMMO)
|
||||
{
|
||||
DEH_Warning(context, "Invalid ammo number: %i", ammo_number);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &maxammo[ammo_number];
|
||||
}
|
||||
|
||||
static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
char *variable_name, *value;
|
||||
int ivalue;
|
||||
int ammo_number;
|
||||
|
||||
if (tag == NULL)
|
||||
return;
|
||||
|
||||
ammo_number = ((int *) tag) - maxammo;
|
||||
|
||||
// Parse the assignment
|
||||
|
||||
if (!DEH_ParseAssignment(line, &variable_name, &value))
|
||||
{
|
||||
// Failed to parse
|
||||
|
||||
DEH_Warning(context, "Failed to parse assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
ivalue = atoi(value);
|
||||
|
||||
if (!strcasecmp(variable_name, "Per ammo"))
|
||||
{
|
||||
// Heretic doesn't have a "per clip" ammo array, instead
|
||||
// it is per weapon. However, the weapon number lines
|
||||
// up with the ammo number if we add one.
|
||||
|
||||
GetWeaponAmmo[ammo_number + 1] = ivalue;
|
||||
}
|
||||
else if (!strcasecmp(variable_name, "Max ammo"))
|
||||
{
|
||||
maxammo[ammo_number] = ivalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEH_Warning(context, "Field named '%s' not found", variable_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void DEH_AmmoMD5Hash(md5_context_t *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUMAMMO; ++i)
|
||||
{
|
||||
MD5_UpdateInt32(context, maxammo[i]);
|
||||
}
|
||||
|
||||
for (i=0; i<NUMWEAPONS; ++i)
|
||||
{
|
||||
MD5_UpdateInt32(context, GetWeaponAmmo[i]);
|
||||
}
|
||||
}
|
||||
|
||||
deh_section_t deh_section_ammo =
|
||||
{
|
||||
"Ammo",
|
||||
NULL,
|
||||
DEH_AmmoStart,
|
||||
DEH_AmmoParseLine,
|
||||
NULL,
|
||||
DEH_AmmoMD5Hash,
|
||||
};
|
||||
|
||||
344
src/heretic/deh_frame.c
Normal file
344
src/heretic/deh_frame.c
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses "Frame" sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "info.h"
|
||||
|
||||
#include "deh_defs.h"
|
||||
#include "deh_io.h"
|
||||
#include "deh_main.h"
|
||||
#include "deh_mapping.h"
|
||||
#include "deh_htic.h"
|
||||
|
||||
#include "p_action.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int offsets[deh_hhe_num_versions];
|
||||
void (*func)();
|
||||
} hhe_action_pointer_t;
|
||||
|
||||
// Offsets of action pointers within the Heretic executables.
|
||||
// Different versions have different offsets.
|
||||
// (Seriously Greg, was this really necessary? What was wrong with the
|
||||
// "copying action pointer from another frame" technique used in dehacked?)
|
||||
|
||||
// Offset Action function
|
||||
// v1.0 v1.2 v1.3
|
||||
|
||||
static const hhe_action_pointer_t action_pointers[] =
|
||||
{
|
||||
{ { 77680, 80144, 80208 }, A_AccTeleGlitter },
|
||||
{ { 78608, 81104, 81168 }, A_AddPlayerCorpse },
|
||||
{ { 115808, 118000, 118240 }, A_AddPlayerRain },
|
||||
{ { 112272, 114480, 114720 }, A_BeakAttackPL1 },
|
||||
{ { 112448, 114656, 114896 }, A_BeakAttackPL2 },
|
||||
{ { 111856, 114176, 114416 }, A_BeakRaise },
|
||||
{ { 111568, 113888, 114128 }, A_BeakReady },
|
||||
{ { 74640, 77120, 77184 }, A_BeastAttack },
|
||||
{ { 70480, 72992, 73056 }, A_BeastPuff },
|
||||
{ { 73120, 75600, 75664 }, A_BlueSpark },
|
||||
{ { 115456, 117648, 117888 }, A_BoltSpark },
|
||||
{ { 77344, 79808, 79872 }, A_BossDeath },
|
||||
{ { 69328, 71856, 71920 }, A_Chase },
|
||||
{ { 0, 80976, 81040 }, A_CheckBurnGone },
|
||||
{ { 78480, 80944, 81008 }, A_CheckSkullDone },
|
||||
{ { 78448, 80912, 80976 }, A_CheckSkullFloor },
|
||||
{ { 71376, 73888, 73952 }, A_ChicAttack },
|
||||
{ { 71488, 74000, 74064 }, A_ChicChase },
|
||||
{ { 71456, 73968, 74032 }, A_ChicLook },
|
||||
{ { 71520, 74032, 74096 }, A_ChicPain },
|
||||
{ { 75792, 78208, 78272 }, A_ClinkAttack },
|
||||
{ { 108432, 110816, 111056 }, A_ContMobjSound },
|
||||
{ { 114752, 116944, 117184 }, A_DeathBallImpact },
|
||||
{ { 70016, 72528, 72592 }, A_DripBlood },
|
||||
{ { 77472, 79936, 80000 }, A_ESound },
|
||||
{ { 76784, 79248, 79312 }, A_Explode },
|
||||
{ { 69872, 72400, 72464 }, A_FaceTarget },
|
||||
{ { 71568, 74080, 74144 }, A_Feathers },
|
||||
{ { 112928, 115136, 115376 }, A_FireBlasterPL1 },
|
||||
{ { 113072, 115280, 115520 }, A_FireBlasterPL2 },
|
||||
{ { 115232, 117424, 117664 }, A_FireCrossbowPL1 },
|
||||
{ { 115312, 117504, 117744 }, A_FireCrossbowPL2 },
|
||||
{ { 113152, 115360, 115600 }, A_FireGoldWandPL1 },
|
||||
{ { 113296, 115504, 115744 }, A_FireGoldWandPL2 },
|
||||
{ { 113760, 115968, 116208 }, A_FireMacePL1 },
|
||||
{ { 114624, 116816, 117056 }, A_FireMacePL2 },
|
||||
{ { 116368, 118544, 118784 }, A_FirePhoenixPL1 },
|
||||
{ { 116736, 118896, 119136 }, A_FirePhoenixPL2 },
|
||||
{ { 115568, 117760, 118000 }, A_FireSkullRodPL1 },
|
||||
{ { 115648, 117840, 118080 }, A_FireSkullRodPL2 },
|
||||
{ { 117120, 119280, 119520 }, A_FlameEnd },
|
||||
{ { 78704, 81200, 81264 }, A_FlameSnd },
|
||||
{ { 117152, 119312, 119552 }, A_FloatPuff },
|
||||
{ { 78512, 81008, 81072 }, A_FreeTargMobj },
|
||||
{ { 117184, 119344, 119584 }, A_GauntletAttack },
|
||||
{ { 73232, 75712, 75776 }, A_GenWizard },
|
||||
{ { 75872, 78304, 78368 }, A_GhostOff },
|
||||
{ { 74752, 77232, 77296 }, A_HeadAttack },
|
||||
{ { 75488, 77984, 78048 }, A_HeadFireGrow },
|
||||
{ { 75328, 77824, 77888 }, A_HeadIceImpact },
|
||||
{ { 116336, 118512, 118752 }, A_HideInCeiling },
|
||||
{ { 78736, 81232, 81296 }, A_HideThing },
|
||||
{ { 70976, 73488, 73552 }, A_ImpDeath },
|
||||
{ { 70304, 72816, 72880 }, A_ImpExplode },
|
||||
{ { 70592, 73104, 73168 }, A_ImpMeAttack },
|
||||
{ { 70672, 73184, 73248 }, A_ImpMsAttack },
|
||||
{ { 70880, 73392, 73456 }, A_ImpMsAttack2 },
|
||||
{ { 71024, 73536, 73600 }, A_ImpXDeath1 },
|
||||
{ { 71072, 73584, 73648 }, A_ImpXDeath2 },
|
||||
{ { 77728, 80192, 80256 }, A_InitKeyGizmo },
|
||||
{ { 116720, 118880, 119120 }, A_InitPhoenixPL2 },
|
||||
{ { 70160, 72672, 72736 }, A_KnightAttack },
|
||||
{ { 117648, 119824, 120064 }, A_Light0 },
|
||||
{ { 69200, 71728, 71792 }, A_Look },
|
||||
{ { 111760, 114080, 114320 }, A_Lower },
|
||||
{ { 114032, 116224, 116464 }, A_MaceBallImpact },
|
||||
{ { 114192, 116384, 116624 }, A_MaceBallImpact2 },
|
||||
{ { 113904, 116112, 116352 }, A_MacePL1Check },
|
||||
{ { 77104, 79568, 79632 }, A_MakePod },
|
||||
{ { 73648, 76128, 76192 }, A_MinotaurAtk1 },
|
||||
{ { 74112, 76592, 76656 }, A_MinotaurAtk2 },
|
||||
{ { 74352, 76832, 76896 }, A_MinotaurAtk3 },
|
||||
{ { 74032, 76512, 76576 }, A_MinotaurCharge },
|
||||
{ { 73760, 76240, 76304 }, A_MinotaurDecide },
|
||||
{ { 74528, 77008, 77072 }, A_MntrFloorFire },
|
||||
{ { 71808, 74288, 74352 }, A_MummyAttack },
|
||||
{ { 71920, 74400, 74464 }, A_MummyAttack2 },
|
||||
{ { 72016, 74496, 74560 }, A_MummyFX1Seek },
|
||||
{ { 72048, 74528, 74592 }, A_MummySoul },
|
||||
{ { 76400, 78832, 78896 }, A_NoBlocking },
|
||||
{ { 69984, 72496, 72560 }, A_Pain },
|
||||
{ { 116496, 118656, 118896 }, A_PhoenixPuff },
|
||||
{ { 76896, 79360, 79424 }, A_PodPain },
|
||||
{ { 116272, 118448, 118688 }, A_RainImpact },
|
||||
{ { 111920, 114240, 114480 }, A_Raise },
|
||||
{ { 111696, 114016, 114256 }, A_ReFire },
|
||||
{ { 77056, 79520, 79584 }, A_RemovePod },
|
||||
{ { 116480, 0, 0 }, A_RemovedPhoenixFunc },
|
||||
{ { 81952, 84464, 84528 }, A_RestoreArtifact },
|
||||
{ { 82048, 84544, 84608 }, A_RestoreSpecialThing1 },
|
||||
{ { 82128, 84592, 84656 }, A_RestoreSpecialThing2 },
|
||||
{ { 76144, 78576, 78640 }, A_Scream },
|
||||
{ { 117104, 119264, 119504 }, A_ShutdownPhoenixPL2 },
|
||||
{ { 78288, 80752, 80816 }, A_SkullPop },
|
||||
{ { 115776, 117968, 118208 }, A_SkullRodPL2Seek },
|
||||
{ { 115984, 118176, 118416 }, A_SkullRodStorm },
|
||||
{ { 75632, 78048, 78112 }, A_SnakeAttack },
|
||||
{ { 75712, 78128, 78192 }, A_SnakeAttack2 },
|
||||
{ { 72144, 74624, 74688 }, A_Sor1Chase },
|
||||
{ { 72096, 74576, 74640 }, A_Sor1Pain },
|
||||
{ { 73392, 75872, 75936 }, A_Sor2DthInit },
|
||||
{ { 73424, 75904, 75968 }, A_Sor2DthLoop },
|
||||
{ { 73584, 76064, 76128 }, A_SorDBon },
|
||||
{ { 73552, 76032, 76096 }, A_SorDExp },
|
||||
{ { 73520, 76000, 76064 }, A_SorDSph },
|
||||
{ { 73488, 75968, 76032 }, A_SorRise },
|
||||
{ { 73616, 76096, 76160 }, A_SorSightSnd },
|
||||
{ { 73456, 75936, 76000 }, A_SorZap },
|
||||
{ { 72480, 74960, 75024 }, A_SorcererRise },
|
||||
{ { 115088, 117280, 117520 }, A_SpawnRippers },
|
||||
{ { 77520, 79984, 80048 }, A_SpawnTeleGlitter },
|
||||
{ { 77600, 80064, 80128 }, A_SpawnTeleGlitter2 },
|
||||
{ { 72192, 74672, 74736 }, A_Srcr1Attack },
|
||||
{ { 72896, 75376, 75440 }, A_Srcr2Attack },
|
||||
{ { 72816, 75296, 75360 }, A_Srcr2Decide },
|
||||
{ { 112640, 114848, 115088 }, A_StaffAttackPL1 },
|
||||
{ { 112784, 114992, 115232 }, A_StaffAttackPL2 },
|
||||
{ { 78752, 81248, 81312 }, A_UnHideThing },
|
||||
{ { 78080, 80544, 80608 }, A_VolcBallImpact },
|
||||
{ { 77856, 80320, 80384 }, A_VolcanoBlast },
|
||||
{ { 77824, 80288, 80352 }, A_VolcanoSet },
|
||||
{ { 111168, 113488, 113728 }, A_WeaponReady },
|
||||
{ { 75168, 77664, 77728 }, A_WhirlwindSeek },
|
||||
{ { 75888, 78320, 78384 }, A_WizAtk1 },
|
||||
{ { 75920, 78352, 78416 }, A_WizAtk2 },
|
||||
{ { 75952, 78384, 78448 }, A_WizAtk3 },
|
||||
};
|
||||
|
||||
DEH_BEGIN_MAPPING(state_mapping, state_t)
|
||||
DEH_MAPPING("Sprite number", sprite)
|
||||
DEH_MAPPING("Sprite subnumber", frame)
|
||||
DEH_MAPPING("Duration", tics)
|
||||
DEH_MAPPING("Next frame", nextstate)
|
||||
DEH_MAPPING("Unknown 1", misc1)
|
||||
DEH_MAPPING("Unknown 2", misc2)
|
||||
DEH_END_MAPPING
|
||||
|
||||
static void DEH_FrameInit(void)
|
||||
{
|
||||
// Bit of a hack here:
|
||||
DEH_HereticInit();
|
||||
}
|
||||
|
||||
static void *DEH_FrameStart(deh_context_t *context, char *line)
|
||||
{
|
||||
int frame_number = 0;
|
||||
int mapped_frame_number;
|
||||
state_t *state;
|
||||
|
||||
if (sscanf(line, "Frame %i", &frame_number) != 1)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Map the HHE frame number (which assumes a Heretic 1.0 state table)
|
||||
// to the internal frame number (which is is the Heretic 1.3 state table):
|
||||
|
||||
mapped_frame_number = DEH_MapHereticFrameNumber(frame_number);
|
||||
|
||||
if (mapped_frame_number < 0 || mapped_frame_number >= DEH_HERETIC_NUMSTATES)
|
||||
{
|
||||
DEH_Warning(context, "Invalid frame number: %i", frame_number);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = &states[mapped_frame_number];
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static boolean GetActionPointerForOffset(int offset, void **result)
|
||||
{
|
||||
int i;
|
||||
|
||||
// Special case.
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
*result = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i=0; i<arrlen(action_pointers); ++i)
|
||||
{
|
||||
if (action_pointers[i].offsets[deh_hhe_version] == offset)
|
||||
{
|
||||
*result = action_pointers[i].func;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If an invalid action pointer is specified, the patch may be for a
|
||||
// different version from the version we are currently set to. Try to
|
||||
// suggest a different version to use.
|
||||
|
||||
static void SuggestOtherVersions(unsigned int offset)
|
||||
{
|
||||
unsigned int i, v;
|
||||
|
||||
for (i=0; i<arrlen(action_pointers); ++i)
|
||||
{
|
||||
for (v=0; v<deh_hhe_num_versions; ++v)
|
||||
{
|
||||
if (action_pointers[i].offsets[v] == offset)
|
||||
{
|
||||
DEH_SuggestHereticVersion(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
state_t *state;
|
||||
char *variable_name, *value;
|
||||
int ivalue;
|
||||
|
||||
if (tag == NULL)
|
||||
return;
|
||||
|
||||
state = (state_t *) tag;
|
||||
|
||||
// Parse the assignment
|
||||
|
||||
if (!DEH_ParseAssignment(line, &variable_name, &value))
|
||||
{
|
||||
// Failed to parse
|
||||
|
||||
DEH_Warning(context, "Failed to parse assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
// all values are integers
|
||||
|
||||
ivalue = atoi(value);
|
||||
|
||||
// Action pointer field is a special case:
|
||||
|
||||
if (!strcasecmp(variable_name, "Action pointer"))
|
||||
{
|
||||
void *func;
|
||||
|
||||
if (!GetActionPointerForOffset(ivalue, &func))
|
||||
{
|
||||
SuggestOtherVersions(ivalue);
|
||||
DEH_Error(context, "Unknown action pointer: %i", ivalue);
|
||||
return;
|
||||
}
|
||||
|
||||
state->action = func;
|
||||
}
|
||||
else
|
||||
{
|
||||
// "Next frame" numbers need to undergo mapping.
|
||||
|
||||
if (!strcasecmp(variable_name, "Next frame"))
|
||||
{
|
||||
ivalue = DEH_MapHereticFrameNumber(ivalue);
|
||||
}
|
||||
|
||||
DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue);
|
||||
}
|
||||
}
|
||||
|
||||
static void DEH_FrameMD5Sum(md5_context_t *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUMSTATES; ++i)
|
||||
{
|
||||
DEH_StructMD5Sum(context, &state_mapping, &states[i]);
|
||||
}
|
||||
}
|
||||
|
||||
deh_section_t deh_section_frame =
|
||||
{
|
||||
"Frame",
|
||||
DEH_FrameInit,
|
||||
DEH_FrameStart,
|
||||
DEH_FrameParseLine,
|
||||
NULL,
|
||||
DEH_FrameMD5Sum,
|
||||
};
|
||||
|
||||
856
src/heretic/deh_htext.c
Normal file
856
src/heretic/deh_htext.c
Normal file
|
|
@ -0,0 +1,856 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005-2010 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses Text substitution sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "dstrings.h"
|
||||
|
||||
#include "z_zone.h"
|
||||
|
||||
#include "deh_defs.h"
|
||||
#include "deh_io.h"
|
||||
#include "deh_htic.h"
|
||||
#include "deh_main.h"
|
||||
|
||||
//
|
||||
// Ok, Greg, the action pointers thing was bad enough, but this really
|
||||
// takes the biscuit. Why does HHE's text replacement address strings
|
||||
// by offset??!! The dehacked way was much nicer, why change it?
|
||||
//
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int offsets[deh_hhe_num_versions];
|
||||
char *string;
|
||||
} hhe_string_t;
|
||||
|
||||
// Offsets String
|
||||
// v1.0 v1.2 v1.3
|
||||
|
||||
static const hhe_string_t strings[] =
|
||||
{
|
||||
{ { 228, 228, 228 }, "PLAYPAL" },
|
||||
{ { 1240, 1252, 1252 }, "E1M1: THE DOCKS" },
|
||||
{ { 1260, 1272, 1272 }, "E1M2: THE DUNGEONS" },
|
||||
{ { 1280, 1292, 1292 }, "E1M3: THE GATEHOUSE" },
|
||||
{ { 1304, 1316, 1316 }, "E1M4: THE GUARD TOWER" },
|
||||
{ { 1328, 1340, 1340 }, "E1M5: THE CITADEL" },
|
||||
{ { 1348, 1360, 1360 }, "E1M6: THE CATHEDRAL" },
|
||||
{ { 1372, 1384, 1384 }, "E1M7: THE CRYPTS" },
|
||||
{ { 1392, 1404, 1404 }, "E1M8: HELL'S MAW" },
|
||||
{ { 1412, 1424, 1424 }, "E1M9: THE GRAVEYARD" },
|
||||
{ { 1436, 1448, 1448 }, "E2M1: THE CRATER" },
|
||||
{ { 1456, 1468, 1468 }, "E2M2: THE LAVA PITS" },
|
||||
{ { 1480, 1492, 1492 }, "E2M3: THE RIVER OF FIRE" },
|
||||
{ { 1508, 1520, 1520 }, "E2M4: THE ICE GROTTO" },
|
||||
{ { 1532, 1544, 1544 }, "E2M5: THE CATACOMBS" },
|
||||
{ { 1556, 1568, 1568 }, "E2M6: THE LABYRINTH" },
|
||||
{ { 1580, 1592, 1592 }, "E2M7: THE GREAT HALL" },
|
||||
{ { 1604, 1616, 1616 }, "E2M8: THE PORTALS OF CHAOS" },
|
||||
{ { 1632, 1644, 1644 }, "E2M9: THE GLACIER" },
|
||||
{ { 1652, 1664, 1664 }, "E3M1: THE STOREHOUSE" },
|
||||
{ { 1676, 1688, 1688 }, "E3M2: THE CESSPOOL" },
|
||||
{ { 1696, 1708, 1708 }, "E3M3: THE CONFLUENCE" },
|
||||
{ { 1720, 1732, 1732 }, "E3M4: THE AZURE FORTRESS" },
|
||||
{ { 1748, 1760, 1760 }, "E3M5: THE OPHIDIAN LAIR" },
|
||||
{ { 1776, 1788, 1788 }, "E3M6: THE HALLS OF FEAR" },
|
||||
{ { 1804, 1816, 1816 }, "E3M7: THE CHASM" },
|
||||
{ { 1824, 1836, 1836 }, "E3M8: D'SPARIL'S KEEP" },
|
||||
{ { 1848, 1860, 1860 }, "E3M9: THE AQUIFER" },
|
||||
{ { 0, 1880, 1880 }, "E4M1: CATAFALQUE" },
|
||||
{ { 0, 1900, 1900 }, "E4M2: BLOCKHOUSE" },
|
||||
{ { 0, 1920, 1920 }, "E4M3: AMBULATORY" },
|
||||
{ { 0, 1940, 1940 }, "E4M4: SEPULCHER" },
|
||||
{ { 0, 1960, 1960 }, "E4M5: GREAT STAIR" },
|
||||
{ { 0, 1980, 1980 }, "E4M6: HALLS OF THE APOSTATE" },
|
||||
{ { 0, 2012, 2012 }, "E4M7: RAMPARTS OF PERDITION" },
|
||||
{ { 0, 2044, 2044 }, "E4M8: SHATTERED BRIDGE" },
|
||||
{ { 0, 2068, 2068 }, "E4M9: MAUSOLEUM" },
|
||||
{ { 0, 2088, 2088 }, "E5M1: OCHRE CLIFFS" },
|
||||
{ { 0, 2108, 2108 }, "E5M2: RAPIDS" },
|
||||
{ { 0, 2124, 2124 }, "E5M3: QUAY" },
|
||||
{ { 0, 2136, 2136 }, "E5M4: COURTYARD" },
|
||||
{ { 0, 2156, 2156 }, "E5M5: HYDRATYR" },
|
||||
{ { 0, 2172, 2172 }, "E5M6: COLONNADE" },
|
||||
{ { 0, 2192, 2192 }, "E5M7: FOETID MANSE" },
|
||||
{ { 0, 2212, 2212 }, "E5M8: FIELD OF JUDGEMENT" },
|
||||
{ { 0, 2240, 2240 }, "E5M9: SKEIN OF D'SPARIL" },
|
||||
{ { 1868, 2268, 2268 }, "AUTOPAGE" },
|
||||
{ { 1880, 2280, 2280 }, "FOLLOW MODE ON" },
|
||||
{ { 1896, 2296, 2296 }, "FOLLOW MODE OFF" },
|
||||
{ { 1924, 2324, 2324 }, "GREEN: " },
|
||||
{ { 1936, 2336, 2336 }, "YELLOW: " },
|
||||
{ { 1948, 2348, 2348 }, "RED: " },
|
||||
{ { 1956, 2356, 2356 }, "BLUE: " },
|
||||
{ { 1964, 2364, 2364 }, "FONTA_S" },
|
||||
{ { 1972, 2372, 2372 }, "-MESSAGE SENT-" },
|
||||
{ { 1988, 2388, 2388 }, "THERE ARE NO OTHER PLAYERS IN THE GAME!" },
|
||||
{ { 2028, 2428, 2428 }, "FONTA59" },
|
||||
{ { 2036, 2504, 2504 }, "PAUSED" },
|
||||
{ { 2072, 2540, 2540 }, "ADVISOR" },
|
||||
{ { 2080, 2548, 2548 }, "TITLE" },
|
||||
{ { 2088, 2556, 2556 }, "demo1" },
|
||||
{ { 2096, 2564, 2564 }, "CREDIT" },
|
||||
{ { 2104, 2572, 2572 }, "demo2" },
|
||||
{ { 2112, 2580, 2580 }, "ORDER" },
|
||||
{ { 2120, 2588, 2588 }, "demo3" },
|
||||
{ { 2304, 2696, 2696 }, "Exited from HERETIC.\n" },
|
||||
{ { 2412, 2800, 2800 }, "c:\\heretic.cd" },
|
||||
{ { 2528, 2916, 2916 }, "Playing demo %s.lmp.\n" },
|
||||
{ { 2592, 2980, 2980 }, "V_Init: allocate screens.\n" },
|
||||
{ { 2620, 3008, 3008 }, "M_LoadDefaults: Load system defaults.\n" },
|
||||
{ { 2660, 3048, 3048 }, "Z_Init: Init zone memory allocation daemon.\n" },
|
||||
{ { 2708, 3096, 3096 }, "W_Init: Init WADfiles.\n" },
|
||||
{ { 2732, 3120, 3120 }, "E2M1" },
|
||||
{ { 0, 3128, 3128 }, "EXTENDED" },
|
||||
{ { 2740, 3140, 3140 }, "LOADING" },
|
||||
{ { 2748, 3148, 3148 }, "DeathMatch..." },
|
||||
{ { 2764, 3164, 3164 }, "No Monsters..." },
|
||||
{ { 2780, 3180, 3180 }, "Respawning..." },
|
||||
{ { 2796, 3196, 3196 }, "Warp to Episode %d, Map %d, Skill %d " },
|
||||
{ { 2836, 3236, 3236 }, "MN_Init: Init menu system.\n" },
|
||||
{ { 2864, 3264, 3264 }, "R_Init: Init Heretic refresh daemon." },
|
||||
{ { 2904, 3304, 3304 }, "Loading graphics" },
|
||||
{ { 2924, 3324, 3324 }, "P_Init: Init Playloop state." },
|
||||
{ { 2956, 3356, 3356 }, "Init game engine." },
|
||||
{ { 2976, 3376, 3376 }, "I_Init: Setting up machine state.\n" },
|
||||
{ { 3012, 3412, 3412 }, "D_CheckNetGame: Checking network game status.\n" },
|
||||
{ { 3060, 3460, 3460 }, "Checking network game status." },
|
||||
{ { 3092, 3492, 3492 }, "SB_Init: Loading patches.\n" },
|
||||
{ { 0, 3752, 3752 }, "PLAYER 1 LEFT THE GAME" },
|
||||
{ { 3508, 3932, 3932 }, "Network game synchronization aborted." },
|
||||
{ { 0, 3972, 3972 }, "Different DOOM versions cannot play a net game!" },
|
||||
{ { 3908, 4132, 4132 }, "SKY1" },
|
||||
{ { 3916, 4140, 4140 }, "SKY2" },
|
||||
{ { 3924, 4148, 4148 }, "SKY3" },
|
||||
{ { 3736, 4196, 4196 }, "NET GAME" },
|
||||
{ { 3748, 4208, 4208 }, "SAVE GAME" },
|
||||
{ { 3760, 4220, 4220 }, "Only %i deathmatch spots, 4 required" },
|
||||
{ { 3800, 4260, 4260 }, "version %i" },
|
||||
{ { 3828, 4372, 4372 }, "c:\\heretic.cd\\hticsav%d.hsg" },
|
||||
{ { 3856, 4400, 4400 }, "hticsav%d.hsg" },
|
||||
{ { 3896, 4416, 4416 }, "GAME SAVED" },
|
||||
{ { 4016, 4456, 4456 }, E1TEXT },
|
||||
{ { 4536, 4976, 4976 }, E2TEXT },
|
||||
{ { 5068, 5508, 5508 }, E3TEXT },
|
||||
{ { 0, 6072, 6072 }, E4TEXT },
|
||||
{ { 0, 6780, 6780 }, E5TEXT },
|
||||
{ { 5632, 7468, 7468 }, "FLOOR25" },
|
||||
{ { 5640, 7476, 7476 }, "FLATHUH1" },
|
||||
{ { 5652, 7488, 7488 }, "FLTWAWA2" },
|
||||
{ { 0, 7500, 7500 }, "FLOOR28" },
|
||||
{ { 0, 7508, 7508 }, "FLOOR08" },
|
||||
{ { 5664, 7516, 7516 }, "FONTA_S" },
|
||||
{ { 5704, 7524, 7524 }, "PLAYPAL" },
|
||||
{ { 5672, 7532, 7532 }, "FINAL1" },
|
||||
{ { 5680, 7540, 7540 }, "FINAL2" },
|
||||
{ { 5688, 7548, 7548 }, "E2PAL" },
|
||||
{ { 5696, 7556, 7556 }, "E2END" },
|
||||
{ { 7884, 7564, 7564 }, "TITLE" },
|
||||
{ { 5712, 7572, 7572 }, "ORDER" },
|
||||
{ { 0, 7580, 7580 }, "CREDIT" },
|
||||
{ { 5720, 7588, 7588 }, "IMPX" },
|
||||
{ { 5728, 7596, 7596 }, "ACLO" },
|
||||
{ { 5736, 7604, 7604 }, "PTN1" },
|
||||
{ { 5744, 7612, 7612 }, "SHLD" },
|
||||
{ { 5752, 7620, 7620 }, "SHD2" },
|
||||
{ { 5760, 7628, 7628 }, "BAGH" },
|
||||
{ { 5768, 7636, 7636 }, "SPMP" },
|
||||
{ { 5776, 7644, 7644 }, "INVS" },
|
||||
{ { 5784, 7652, 7652 }, "PTN2" },
|
||||
{ { 5792, 7660, 7660 }, "SOAR" },
|
||||
{ { 5800, 7668, 7668 }, "INVU" },
|
||||
{ { 5808, 7676, 7676 }, "PWBK" },
|
||||
{ { 5816, 7684, 7684 }, "EGGC" },
|
||||
{ { 5824, 7692, 7692 }, "EGGM" },
|
||||
{ { 5832, 7700, 7700 }, "FX01" },
|
||||
{ { 5840, 7708, 7708 }, "SPHL" },
|
||||
{ { 5848, 7716, 7716 }, "TRCH" },
|
||||
{ { 5856, 7724, 7724 }, "FBMB" },
|
||||
{ { 5864, 7732, 7732 }, "XPL1" },
|
||||
{ { 5872, 7740, 7740 }, "ATLP" },
|
||||
{ { 5880, 7748, 7748 }, "PPOD" },
|
||||
{ { 5888, 7756, 7756 }, "AMG1" },
|
||||
{ { 5896, 7764, 7764 }, "SPSH" },
|
||||
{ { 5904, 7772, 7772 }, "LVAS" },
|
||||
{ { 5912, 7780, 7780 }, "SLDG" },
|
||||
{ { 5920, 7788, 7788 }, "SKH1" },
|
||||
{ { 5928, 7796, 7796 }, "SKH2" },
|
||||
{ { 5936, 7804, 7804 }, "SKH3" },
|
||||
{ { 5944, 7812, 7812 }, "SKH4" },
|
||||
{ { 5952, 7820, 7820 }, "CHDL" },
|
||||
{ { 5960, 7828, 7828 }, "SRTC" },
|
||||
{ { 5968, 7836, 7836 }, "SMPL" },
|
||||
{ { 5976, 7844, 7844 }, "STGS" },
|
||||
{ { 5984, 7852, 7852 }, "STGL" },
|
||||
{ { 5992, 7860, 7860 }, "STCS" },
|
||||
{ { 6000, 7868, 7868 }, "STCL" },
|
||||
{ { 6008, 7876, 7876 }, "KFR1" },
|
||||
{ { 6016, 7884, 7884 }, "BARL" },
|
||||
{ { 6024, 7892, 7892 }, "BRPL" },
|
||||
{ { 6032, 7900, 7900 }, "MOS1" },
|
||||
{ { 6040, 7908, 7908 }, "MOS2" },
|
||||
{ { 6048, 7916, 7916 }, "WTRH" },
|
||||
{ { 6056, 7924, 7924 }, "HCOR" },
|
||||
{ { 6064, 7932, 7932 }, "KGZ1" },
|
||||
{ { 6072, 7940, 7940 }, "KGZB" },
|
||||
{ { 6080, 7948, 7948 }, "KGZG" },
|
||||
{ { 6088, 7956, 7956 }, "KGZY" },
|
||||
{ { 6096, 7964, 7964 }, "VLCO" },
|
||||
{ { 6104, 7972, 7972 }, "VFBL" },
|
||||
{ { 6112, 7980, 7980 }, "VTFB" },
|
||||
{ { 6120, 7988, 7988 }, "SFFI" },
|
||||
{ { 6128, 7996, 7996 }, "TGLT" },
|
||||
{ { 6136, 8004, 8004 }, "TELE" },
|
||||
{ { 6144, 8012, 8012 }, "STFF" },
|
||||
{ { 6152, 8020, 8020 }, "PUF3" },
|
||||
{ { 6160, 8028, 8028 }, "PUF4" },
|
||||
{ { 6168, 8036, 8036 }, "BEAK" },
|
||||
{ { 6176, 8044, 8044 }, "WGNT" },
|
||||
{ { 6184, 8052, 8052 }, "GAUN" },
|
||||
{ { 6192, 8060, 8060 }, "PUF1" },
|
||||
{ { 6200, 8068, 8068 }, "WBLS" },
|
||||
{ { 6208, 8076, 8076 }, "BLSR" },
|
||||
{ { 6216, 8084, 8084 }, "FX18" },
|
||||
{ { 6224, 8092, 8092 }, "FX17" },
|
||||
{ { 6232, 8100, 8100 }, "WMCE" },
|
||||
{ { 6240, 8108, 8108 }, "MACE" },
|
||||
{ { 6248, 8116, 8116 }, "FX02" },
|
||||
{ { 6256, 8124, 8124 }, "WSKL" },
|
||||
{ { 6264, 8132, 8132 }, "HROD" },
|
||||
{ { 6272, 8140, 8140 }, "FX00" },
|
||||
{ { 6280, 8148, 8148 }, "FX20" },
|
||||
{ { 6288, 8156, 8156 }, "FX21" },
|
||||
{ { 6296, 8164, 8164 }, "FX22" },
|
||||
{ { 6304, 8172, 8172 }, "FX23" },
|
||||
{ { 6312, 8180, 8180 }, "GWND" },
|
||||
{ { 6320, 8188, 8188 }, "PUF2" },
|
||||
{ { 6328, 8196, 8196 }, "WPHX" },
|
||||
{ { 6336, 8204, 8204 }, "PHNX" },
|
||||
{ { 6344, 8212, 8212 }, "FX04" },
|
||||
{ { 6352, 8220, 8220 }, "FX08" },
|
||||
{ { 6360, 8228, 8228 }, "FX09" },
|
||||
{ { 6368, 8236, 8236 }, "WBOW" },
|
||||
{ { 6376, 8244, 8244 }, "CRBW" },
|
||||
{ { 6384, 8252, 8252 }, "FX03" },
|
||||
{ { 6392, 8260, 8260 }, "BLOD" },
|
||||
{ { 6400, 8268, 8268 }, "PLAY" },
|
||||
{ { 6408, 8276, 8276 }, "FDTH" },
|
||||
{ { 6416, 8284, 8284 }, "BSKL" },
|
||||
{ { 6424, 8292, 8292 }, "CHKN" },
|
||||
{ { 6432, 8300, 8300 }, "MUMM" },
|
||||
{ { 6440, 8308, 8308 }, "FX15" },
|
||||
{ { 6448, 8316, 8316 }, "BEAS" },
|
||||
{ { 6456, 8324, 8324 }, "FRB1" },
|
||||
{ { 6464, 8332, 8332 }, "SNKE" },
|
||||
{ { 6472, 8340, 8340 }, "SNFX" },
|
||||
{ { 6480, 8348, 8348 }, "HEAD" },
|
||||
{ { 6488, 8356, 8356 }, "FX05" },
|
||||
{ { 6496, 8364, 8364 }, "FX06" },
|
||||
{ { 6504, 8372, 8372 }, "FX07" },
|
||||
{ { 6512, 8380, 8380 }, "CLNK" },
|
||||
{ { 6520, 8388, 8388 }, "WZRD" },
|
||||
{ { 6528, 8396, 8396 }, "FX11" },
|
||||
{ { 6536, 8404, 8404 }, "FX10" },
|
||||
{ { 6544, 8412, 8412 }, "KNIG" },
|
||||
{ { 6552, 8420, 8420 }, "SPAX" },
|
||||
{ { 6560, 8428, 8428 }, "RAXE" },
|
||||
{ { 6568, 8436, 8436 }, "SRCR" },
|
||||
{ { 6576, 8444, 8444 }, "FX14" },
|
||||
{ { 6584, 8452, 8452 }, "SOR2" },
|
||||
{ { 6592, 8460, 8460 }, "SDTH" },
|
||||
{ { 6600, 8468, 8468 }, "FX16" },
|
||||
{ { 6608, 8476, 8476 }, "MNTR" },
|
||||
{ { 6616, 8484, 8484 }, "FX12" },
|
||||
{ { 6624, 8492, 8492 }, "FX13" },
|
||||
{ { 6632, 8500, 8500 }, "AKYY" },
|
||||
{ { 6640, 8508, 8508 }, "BKYY" },
|
||||
{ { 6648, 8516, 8516 }, "CKYY" },
|
||||
{ { 6656, 8524, 8524 }, "AMG2" },
|
||||
{ { 6664, 8532, 8532 }, "AMM1" },
|
||||
{ { 6672, 8540, 8540 }, "AMM2" },
|
||||
{ { 6680, 8548, 8548 }, "AMC1" },
|
||||
{ { 6688, 8556, 8556 }, "AMC2" },
|
||||
{ { 6696, 8564, 8564 }, "AMS1" },
|
||||
{ { 6704, 8572, 8572 }, "AMS2" },
|
||||
{ { 6712, 8580, 8580 }, "AMP1" },
|
||||
{ { 6720, 8588, 8588 }, "AMP2" },
|
||||
{ { 6728, 8596, 8596 }, "AMB1" },
|
||||
{ { 6736, 8604, 8604 }, "AMB2" },
|
||||
{ { 6744, 8612, 8612 }, "K" },
|
||||
{ { 6748, 8616, 8616 }, "I" },
|
||||
{ { 6752, 8620, 8620 }, "L" },
|
||||
{ { 6756, 8624, 8624 }, "E" },
|
||||
{ { 6760, 8628, 8628 }, "R" },
|
||||
{ { 6764, 8632, 8632 }, "S" },
|
||||
{ { 6768, 8636, 8636 }, "PLAYPAL" },
|
||||
{ { 6776, 8644, 8644 }, "MAPE1" },
|
||||
{ { 6784, 8652, 8652 }, "MAPE2" },
|
||||
{ { 6792, 8660, 8660 }, "MAPE3" },
|
||||
{ { 6800, 8668, 8668 }, "IN_X" },
|
||||
{ { 6808, 8676, 8676 }, "IN_YAH" },
|
||||
{ { 6816, 8684, 8684 }, "FONTB16" },
|
||||
{ { 6824, 8692, 8692 }, "FONTB_S" },
|
||||
{ { 6832, 8700, 8700 }, "FONTB13" },
|
||||
{ { 6840, 8708, 8708 }, "FONTB15" },
|
||||
{ { 6848, 8716, 8716 }, "FONTB05" },
|
||||
{ { 6856, 8724, 8724 }, "FACEA0" },
|
||||
{ { 6864, 8732, 8732 }, "FACEB0" },
|
||||
{ { 6940, 8808, 8808 }, "FLOOR16" },
|
||||
{ { 6948, 8816, 8816 }, "FINISHED" },
|
||||
{ { 6960, 8828, 8828 }, "NOW ENTERING:" },
|
||||
{ { 6976, 8844, 8844 }, "KILLS" },
|
||||
{ { 6984, 8852, 8852 }, "ITEMS" },
|
||||
{ { 6992, 8860, 8860 }, "SECRETS" },
|
||||
{ { 7000, 8868, 8868 }, "TIME" },
|
||||
{ { 7008, 8876, 8876 }, "BONUS" },
|
||||
{ { 7016, 8884, 8884 }, "SECRET" },
|
||||
{ { 7024, 8892, 8892 }, "TOTAL" },
|
||||
{ { 7032, 8900, 8900 }, "VICTIMS" },
|
||||
{ { 7040, 8908, 8908 }, ":" },
|
||||
{ { 7044, 8912, 8912 }, "NEW GAME" },
|
||||
{ { 7056, 8924, 8924 }, "OPTIONS" },
|
||||
{ { 7064, 8932, 8932 }, "GAME FILES" },
|
||||
{ { 7076, 8944, 8944 }, "INFO" },
|
||||
{ { 7084, 8952, 8952 }, "QUIT GAME" },
|
||||
{ { 7096, 8964, 8964 }, "CITY OF THE DAMNED" },
|
||||
{ { 7116, 8984, 8984 }, "HELL'S MAW" },
|
||||
{ { 7128, 8996, 8996 }, "THE DOME OF D'SPARIL" },
|
||||
{ { 0, 9020, 9020 }, "THE OSSUARY" },
|
||||
{ { 0, 9032, 9032 }, "THE STAGNANT DEMESNE" },
|
||||
{ { 7152, 9056, 9056 }, "LOAD GAME" },
|
||||
{ { 7164, 9068, 9068 }, "SAVE GAME" },
|
||||
{ { 7176, 9080, 9080 }, "THOU NEEDETH A WET-NURSE" },
|
||||
{ { 7204, 9108, 9108 }, "YELLOWBELLIES-R-US" },
|
||||
{ { 7224, 9128, 9128 }, "BRINGEST THEM ONETH" },
|
||||
{ { 7244, 9148, 9148 }, "THOU ART A SMITE-MEISTER" },
|
||||
{ { 7272, 9176, 9176 }, "BLACK PLAGUE POSSESSES THEE" },
|
||||
{ { 7300, 9204, 9204 }, "END GAME" },
|
||||
{ { 7312, 9216, 9216 }, "MESSAGES : " },
|
||||
{ { 7324, 9228, 9228 }, "MOUSE SENSITIVITY" },
|
||||
{ { 7344, 9248, 9248 }, "MORE..." },
|
||||
{ { 7352, 9256, 9256 }, "SCREEN SIZE" },
|
||||
{ { 7364, 9268, 9268 }, "SFX VOLUME" },
|
||||
{ { 7376, 9280, 9280 }, "MUSIC VOLUME" },
|
||||
{ { 7416, 9296, 9296 }, "ARE YOU SURE YOU WANT TO QUIT?" },
|
||||
{ { 7448, 9328, 9328 }, "ARE YOU SURE YOU WANT TO END THE GAME?" },
|
||||
{ { 7488, 9368, 9368 }, "DO YOU WANT TO QUICKSAVE THE GAME NAMED" },
|
||||
{ { 7528, 9408, 9408 }, "DO YOU WANT TO QUICKLOAD THE GAME NAMED" },
|
||||
{ { 7392, 9448, 9448 }, "M_SKL00" },
|
||||
{ { 7400, 9456, 9456 }, "FONTA_S" },
|
||||
{ { 7408, 9464, 9464 }, "FONTB_S" },
|
||||
{ { 7568, 9472, 9472 }, "?" },
|
||||
{ { 7572, 9476, 9476 }, "M_SLCTR1" },
|
||||
{ { 7584, 9488, 9488 }, "M_SLCTR2" },
|
||||
{ { 7596, 9500, 9500 }, "M_HTIC" },
|
||||
{ { 7604, 9508, 9508 }, "c:\\heretic.cd\\hticsav%d.hsg" },
|
||||
{ { 7632, 9536, 9536 }, "hticsav%d.hsg" },
|
||||
{ { 7652, 9556, 9556 }, "M_FSLOT" },
|
||||
{ { 7660, 9564, 9564 }, "ON" },
|
||||
{ { 7664, 9568, 9568 }, "OFF" },
|
||||
{ { 0, 9572, 9572 }, "YOU CAN'T START A NEW GAME IN NETPLAY!" },
|
||||
{ { 0, 9612, 9612 }, "YOU CAN'T LOAD A GAME IN NETPLAY!" },
|
||||
{ { 7668, 9648, 9648 }, "MESSAGES ON" },
|
||||
{ { 7680, 9660, 9660 }, "MESSAGES OFF" },
|
||||
{ { 7748, 9676, 9676 }, "ONLY AVAILABLE IN THE REGISTERED VERSION" },
|
||||
{ { 7792, 9720, 9720 }, "PLAYPAL" },
|
||||
{ { 7800, 9728, 9728 }, "QUICKSAVING...." },
|
||||
{ { 7816, 9744, 9744 }, "QUICKLOADING...." },
|
||||
{ { 7836, 9764, 9764 }, "CHOOSE A QUICKSAVE SLOT" },
|
||||
{ { 7860, 9788, 9788 }, "CHOOSE A QUICKLOAD SLOT" },
|
||||
{ { 0, 9812, 9812 }, "TITLE" },
|
||||
{ { 7892, 9820, 9820 }, "M_SLDLT" },
|
||||
{ { 7900, 9828, 9828 }, "M_SLDMD1" },
|
||||
{ { 7912, 9840, 9840 }, "M_SLDMD2" },
|
||||
{ { 7924, 9852, 9852 }, "M_SLDRT" },
|
||||
{ { 7932, 9860, 9860 }, "M_SLDKB" },
|
||||
{ { 9016, 10944, 10944 }, "SCREEN SHOT" },
|
||||
{ { 9028, 10956, 10956 }, "YOU NEED A BLUE KEY TO OPEN THIS DOOR" },
|
||||
{ { 9068, 10996, 10996 }, "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" },
|
||||
{ { 9108, 11036, 11036 }, "YOU NEED A GREEN KEY TO OPEN THIS DOOR" },
|
||||
{ { 9244, 11172, 11172 }, "CRYSTAL VIAL" },
|
||||
{ { 9260, 11188, 11188 }, "SILVER SHIELD" },
|
||||
{ { 9276, 11204, 11204 }, "ENCHANTED SHIELD" },
|
||||
{ { 9296, 11224, 11224 }, "BAG OF HOLDING" },
|
||||
{ { 9312, 11240, 11240 }, "MAP SCROLL" },
|
||||
{ { 9324, 11252, 11252 }, "BLUE KEY" },
|
||||
{ { 9336, 11264, 11264 }, "YELLOW KEY" },
|
||||
{ { 9348, 11276, 11276 }, "GREEN KEY" },
|
||||
{ { 9360, 11288, 11288 }, "QUARTZ FLASK" },
|
||||
{ { 9376, 11304, 11304 }, "WINGS OF WRATH" },
|
||||
{ { 9392, 11320, 11320 }, "RING OF INVINCIBILITY" },
|
||||
{ { 9416, 11344, 11344 }, "TOME OF POWER" },
|
||||
{ { 9432, 11360, 11360 }, "SHADOWSPHERE" },
|
||||
{ { 9448, 11376, 11376 }, "MORPH OVUM" },
|
||||
{ { 9460, 11388, 11388 }, "MYSTIC URN" },
|
||||
{ { 9472, 11400, 11400 }, "TORCH" },
|
||||
{ { 9480, 11408, 11408 }, "TIME BOMB OF THE ANCIENTS" },
|
||||
{ { 9508, 11436, 11436 }, "CHAOS DEVICE" },
|
||||
{ { 9524, 11452, 11452 }, "WAND CRYSTAL" },
|
||||
{ { 9540, 11468, 11468 }, "CRYSTAL GEODE" },
|
||||
{ { 9556, 11484, 11484 }, "MACE SPHERES" },
|
||||
{ { 9572, 11500, 11500 }, "PILE OF MACE SPHERES" },
|
||||
{ { 9596, 11524, 11524 }, "ETHEREAL ARROWS" },
|
||||
{ { 9612, 11540, 11540 }, "QUIVER OF ETHEREAL ARROWS" },
|
||||
{ { 9640, 11568, 11568 }, "CLAW ORB" },
|
||||
{ { 9652, 11580, 11580 }, "ENERGY ORB" },
|
||||
{ { 9664, 11592, 11592 }, "LESSER RUNES" },
|
||||
{ { 9680, 11608, 11608 }, "GREATER RUNES" },
|
||||
{ { 9696, 11624, 11624 }, "FLAME ORB" },
|
||||
{ { 9708, 11636, 11636 }, "INFERNO ORB" },
|
||||
{ { 9720, 11648, 11648 }, "FIREMACE" },
|
||||
{ { 9732, 11660, 11660 }, "ETHEREAL CROSSBOW" },
|
||||
{ { 9752, 11680, 11680 }, "DRAGON CLAW" },
|
||||
{ { 9764, 11692, 11692 }, "HELLSTAFF" },
|
||||
{ { 9776, 11704, 11704 }, "PHOENIX ROD" },
|
||||
{ { 9788, 11716, 11716 }, "GAUNTLETS OF THE NECROMANCER" },
|
||||
{ { 10088, 12016, 12016 }, "FLTWAWA1" },
|
||||
{ { 10100, 12028, 12028 }, "FLTFLWW1" },
|
||||
{ { 10112, 12040, 12040 }, "FLTLAVA1" },
|
||||
{ { 10124, 12052, 12052 }, "FLATHUH1" },
|
||||
{ { 10136, 12064, 12064 }, "FLTSLUD1" },
|
||||
{ { 10148, 12076, 12076 }, "END" },
|
||||
{ { 10236, 12164, 12164 }, "texture2" },
|
||||
{ { 10444, 12372, 12372 }, "PLAYPAL" },
|
||||
{ { 10596, 12488, 12488 }, "PNAMES" },
|
||||
{ { 10604, 12496, 12496 }, "TEXTURE1" },
|
||||
{ { 10616, 12508, 12508 }, "TEXTURE2" },
|
||||
{ { 10628, 12520, 12520 }, "S_END" },
|
||||
{ { 10636, 12528, 12528 }, "S_START" },
|
||||
{ { 10728, 12620, 12620 }, "F_START" },
|
||||
{ { 10736, 12628, 12628 }, "F_END" },
|
||||
{ { 10744, 12636, 12636 }, "COLORMAP" },
|
||||
{ { 10756, 12648, 12648 }, "\nR_InitTextures " },
|
||||
{ { 10776, 12668, 12668 }, "R_InitFlats\n" },
|
||||
{ { 10792, 12684, 12684 }, "R_InitSpriteLumps " },
|
||||
{ { 10948, 12772, 12772 }, "TINTTAB" },
|
||||
{ { 10984, 12780, 12780 }, "FLOOR04" },
|
||||
{ { 10992, 12788, 12788 }, "FLAT513" },
|
||||
{ { 11000, 12796, 12796 }, "bordt" },
|
||||
{ { 11008, 12804, 12804 }, "bordb" },
|
||||
{ { 11016, 12812, 12812 }, "bordl" },
|
||||
{ { 11024, 12820, 12820 }, "bordr" },
|
||||
{ { 11032, 12828, 12828 }, "bordtl" },
|
||||
{ { 11040, 12836, 12836 }, "bordtr" },
|
||||
{ { 11048, 12844, 12844 }, "bordbr" },
|
||||
{ { 11056, 12852, 12852 }, "bordbl" },
|
||||
{ { 11064, 12860, 12860 }, "R_InitData " },
|
||||
{ { 11076, 12872, 12872 }, "R_InitPointToAngle\n" },
|
||||
{ { 11096, 12892, 12892 }, "R_InitTables " },
|
||||
{ { 11112, 12908, 12908 }, "R_InitPlanes\n" },
|
||||
{ { 11128, 12924, 12924 }, "R_InitLightTables " },
|
||||
{ { 11148, 12944, 12944 }, "R_InitSkyMap\n" },
|
||||
{ { 11164, 12960, 12960 }, "F_SKY1" },
|
||||
{ { 12120, 13484, 13484 }, "LTFACE" },
|
||||
{ { 12128, 13492, 13492 }, "RTFACE" },
|
||||
{ { 12136, 13500, 13500 }, "BARBACK" },
|
||||
{ { 12144, 13508, 13508 }, "INVBAR" },
|
||||
{ { 12152, 13516, 13516 }, "CHAIN" },
|
||||
{ { 12160, 13524, 13524 }, "STATBAR" },
|
||||
{ { 12168, 13532, 13532 }, "LIFEBAR" },
|
||||
{ { 12176, 13540, 13540 }, "LIFEGEM2" },
|
||||
{ { 12188, 13552, 13552 }, "LIFEGEM0" },
|
||||
{ { 12200, 13564, 13564 }, "LTFCTOP" },
|
||||
{ { 12208, 13572, 13572 }, "RTFCTOP" },
|
||||
{ { 12224, 13580, 13580 }, "SELECTBOX" },
|
||||
{ { 12236, 13592, 13592 }, "INVGEML1" },
|
||||
{ { 12248, 13604, 13604 }, "INVGEML2" },
|
||||
{ { 12260, 13616, 13616 }, "INVGEMR1" },
|
||||
{ { 12272, 13628, 13628 }, "INVGEMR2" },
|
||||
{ { 12284, 13640, 13640 }, "BLACKSQ" },
|
||||
{ { 12292, 13648, 13648 }, "ARMCLEAR" },
|
||||
{ { 12304, 13660, 13660 }, "CHAINBACK" },
|
||||
{ { 12316, 13672, 13672 }, "IN0" },
|
||||
{ { 12320, 13676, 13676 }, "NEGNUM" },
|
||||
{ { 12328, 13684, 13684 }, "FONTB16" },
|
||||
{ { 12336, 13692, 13692 }, "SMALLIN0" },
|
||||
{ { 12348, 13704, 13704 }, "PLAYPAL" },
|
||||
{ { 12356, 13712, 13712 }, "SPINBK0" },
|
||||
{ { 12364, 13720, 13720 }, "SPFLY0" },
|
||||
{ { 12372, 13728, 13728 }, "LAME" },
|
||||
{ { 12380, 13736, 13736 }, "*** SOUND DEBUG INFO ***" },
|
||||
{ { 12408, 13764, 13764 }, "NAME" },
|
||||
{ { 12416, 13772, 13772 }, "MO.T" },
|
||||
{ { 12424, 13780, 13780 }, "MO.X" },
|
||||
{ { 12432, 13788, 13788 }, "MO.Y" },
|
||||
{ { 12440, 13796, 13796 }, "ID" },
|
||||
{ { 12444, 13800, 13800 }, "PRI" },
|
||||
{ { 12448, 13804, 13804 }, "DIST" },
|
||||
{ { 12456, 13812, 13812 }, "------" },
|
||||
{ { 12464, 13820, 13820 }, "%s" },
|
||||
{ { 12468, 13824, 13824 }, "%d" },
|
||||
{ { 12472, 13828, 13828 }, "GOD1" },
|
||||
{ { 12480, 13836, 13836 }, "GOD2" },
|
||||
{ { 12488, 13844, 13844 }, "useartia" },
|
||||
{ { 12500, 13856, 13856 }, "ykeyicon" },
|
||||
{ { 12512, 13868, 13868 }, "gkeyicon" },
|
||||
{ { 12524, 13880, 13880 }, "bkeyicon" },
|
||||
{ { 12216, 13892, 13892 }, "ARTIBOX" },
|
||||
{ { 12536, 13900, 13900 }, "GOD MODE ON" },
|
||||
{ { 12548, 13912, 13912 }, "GOD MODE OFF" },
|
||||
{ { 12564, 13928, 13928 }, "NO CLIPPING ON" },
|
||||
{ { 12580, 13944, 13944 }, "NO CLIPPING OFF" },
|
||||
{ { 12596, 13960, 13960 }, "ALL WEAPONS" },
|
||||
{ { 12608, 13972, 13972 }, "POWER OFF" },
|
||||
{ { 12620, 13984, 13984 }, "POWER ON" },
|
||||
{ { 12632, 13996, 13996 }, "FULL HEALTH" },
|
||||
{ { 12644, 14008, 14008 }, "ALL KEYS" },
|
||||
{ { 12656, 14020, 14020 }, "SOUND DEBUG ON" },
|
||||
{ { 12672, 14036, 14036 }, "SOUND DEBUG OFF" },
|
||||
{ { 12688, 14052, 14052 }, "TICKER ON" },
|
||||
{ { 12700, 14064, 14064 }, "TICKER OFF" },
|
||||
{ { 12712, 14076, 14076 }, "CHOOSE AN ARTIFACT ( A - J )" },
|
||||
{ { 12744, 14108, 14108 }, "HOW MANY ( 1 - 9 )" },
|
||||
{ { 12764, 14128, 14128 }, "YOU GOT IT" },
|
||||
{ { 12776, 14140, 14140 }, "BAD INPUT" },
|
||||
{ { 12788, 14152, 14152 }, "LEVEL WARP" },
|
||||
{ { 12800, 14164, 14164 }, "CHICKEN OFF" },
|
||||
{ { 12812, 14176, 14176 }, "CHICKEN ON" },
|
||||
{ { 12824, 14188, 14188 }, "MASSACRE" },
|
||||
{ { 12836, 14200, 14200 }, "CHEATER - YOU DON'T DESERVE WEAPONS" },
|
||||
{ { 12872, 14236, 14236 }, "TRYING TO CHEAT, EH? NOW YOU DIE!" },
|
||||
};
|
||||
|
||||
// String offsets that are valid but we don't support.
|
||||
|
||||
static const int unsupported_strings_1_0[] =
|
||||
{
|
||||
0, 4, 64, 104, 160, 200, 220, 236,
|
||||
244, 252, 272, 288, 296, 316, 332, 372,
|
||||
436, 500, 504, 536, 544, 560, 576, 584,
|
||||
592, 612, 640, 664, 708, 712, 744, 764,
|
||||
808, 820, 828, 840, 876, 884, 908, 952,
|
||||
992, 1028, 1036, 1048, 1088, 1128, 1160, 1192,
|
||||
1212, 1912, 2044, 2056, 2068, 2128, 2140, 2168,
|
||||
2184, 2196, 2212, 2228, 2240, 2252, 2260, 2264,
|
||||
2284, 2292, 2296, 2300, 2328, 2340, 2352, 2364,
|
||||
2372, 2384, 2388, 2404, 2428, 2436, 2444, 2464,
|
||||
2496, 2508, 2520, 2552, 2564, 2572, 2584, 3120,
|
||||
3128, 3140, 3184, 3220, 3248, 3252, 3256, 3280,
|
||||
3304, 3320, 3352, 3380, 3400, 3432, 3464, 3548,
|
||||
3600, 3624, 3664, 3696, 3812, 3872, 3932, 3940,
|
||||
3976, 3996, 6872, 6896, 7648, 7696, 7940, 7964,
|
||||
7968, 7992, 8020, 8028, 8052, 8056, 8076, 8088,
|
||||
8104, 8116, 8128, 8136, 8148, 8164, 8180, 8192,
|
||||
8204, 8220, 8232, 8248, 8264, 8276, 8292, 8308,
|
||||
8320, 8328, 8340, 8352, 8364, 8376, 8392, 8408,
|
||||
8424, 8436, 8448, 8460, 8472, 8488, 8504, 8520,
|
||||
8536, 8548, 8560, 8572, 8584, 8596, 8608, 8612,
|
||||
8624, 8648, 8660, 8668, 8680, 8708, 8720, 8728,
|
||||
8740, 8752, 8764, 8788, 8800, 8812, 8824, 8848,
|
||||
8860, 8864, 8868, 8876, 8888, 8896, 8916, 8944,
|
||||
8948, 8960, 8964, 8968, 8980, 9148, 9172, 9212,
|
||||
9216, 9220, 9820, 9860, 9892, 9940, 9972, 10012,
|
||||
10036, 10040, 10052, 10080, 10152, 10192, 10248, 10284,
|
||||
10320, 10360, 10392, 10452, 10488, 10508, 10556, 10644,
|
||||
10684, 10812, 10844, 10880, 10912, 10956, 11172, 11200,
|
||||
11232, 11272, 11312, 11348, 11380, 11404, 11436, 11492,
|
||||
11548, 11616, 11684, 11748, 11792, 11840, 11896, 11936,
|
||||
11980, 12028, 12072, 12908, 12924, 12956, 12960, 12968,
|
||||
12976, 13020, 13048, 13076, 13104, 13136, 13168, 13196,
|
||||
13240, 13272, 13292, 13296, 13308, 13312, 13320, 13324,
|
||||
13364, 13408, 13460, 13492, 13516, 13560, 13612, 13664,
|
||||
13700, 13744, 13796, 13848, 13884, 13940, 13996, 14040,
|
||||
14084, 14140, 14148, 14156, 14164, 14184, 14192, 14204,
|
||||
14208, 14212, 14256, 14272, 14284, 14296, 14300, 14312,
|
||||
14320, 14324, 14348, 14356, 14360, 14372, 14380, 14392,
|
||||
14432, 14440, 14444, 14472, 14496, 14516, 14536, 14548,
|
||||
14560, 14572, 14580, 14588, 14596, 14604, 14612, 14620,
|
||||
14636, 14660, 14704, 14740, 14748, 14756, 14760, 14768,
|
||||
-1,
|
||||
};
|
||||
|
||||
static const int unsupported_strings_1_2[] =
|
||||
{
|
||||
0, 4, 64, 104, 160, 200, 220, 236,
|
||||
244, 252, 272, 288, 296, 316, 332, 372,
|
||||
436, 500, 504, 536, 544, 560, 576, 584,
|
||||
592, 612, 640, 664, 708, 712, 744, 756,
|
||||
776, 820, 832, 840, 852, 888, 896, 920,
|
||||
964, 1004, 1040, 1048, 1060, 1100, 1140, 1172,
|
||||
1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492,
|
||||
2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656,
|
||||
2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764,
|
||||
2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884,
|
||||
2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528,
|
||||
3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704,
|
||||
3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044,
|
||||
4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352,
|
||||
4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900,
|
||||
9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004,
|
||||
10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120,
|
||||
10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220,
|
||||
10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332,
|
||||
10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424,
|
||||
10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540,
|
||||
10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660,
|
||||
10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788,
|
||||
10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876,
|
||||
10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144,
|
||||
11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964,
|
||||
11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248,
|
||||
12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704,
|
||||
12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272,
|
||||
13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332,
|
||||
14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560,
|
||||
14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848,
|
||||
14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216,
|
||||
15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496,
|
||||
15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616,
|
||||
15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692,
|
||||
15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828,
|
||||
15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928,
|
||||
15936, -1,
|
||||
};
|
||||
|
||||
static const int unsupported_strings_1_3[] =
|
||||
{
|
||||
0, 4, 64, 104, 160, 200, 220, 236,
|
||||
244, 252, 272, 288, 296, 316, 332, 372,
|
||||
436, 500, 504, 536, 544, 560, 576, 584,
|
||||
592, 612, 640, 664, 708, 712, 744, 756,
|
||||
776, 820, 832, 840, 852, 888, 896, 920,
|
||||
964, 1004, 1040, 1048, 1060, 1100, 1140, 1172,
|
||||
1204, 1224, 2312, 2436, 2448, 2464, 2480, 2492,
|
||||
2512, 2524, 2536, 2596, 2608, 2636, 2652, 2656,
|
||||
2676, 2684, 2688, 2720, 2732, 2744, 2752, 2764,
|
||||
2772, 2776, 2792, 2816, 2824, 2832, 2852, 2884,
|
||||
2896, 2908, 2940, 2952, 2960, 2972, 3520, 3528,
|
||||
3540, 3584, 3620, 3648, 3652, 3656, 3680, 3704,
|
||||
3720, 3776, 3804, 3824, 3856, 3888, 4020, 4044,
|
||||
4084, 4116, 4156, 4272, 4288, 4296, 4332, 4352,
|
||||
4428, 4432, 8740, 8764, 9552, 9868, 9888, 9900,
|
||||
9916, 9928, 9940, 9948, 9960, 9976, 9992, 10004,
|
||||
10016, 10032, 10044, 10060, 10076, 10088, 10104, 10120,
|
||||
10132, 10140, 10152, 10164, 10176, 10188, 10204, 10220,
|
||||
10236, 10248, 10260, 10272, 10284, 10300, 10316, 10332,
|
||||
10348, 10360, 10372, 10384, 10396, 10408, 10420, 10424,
|
||||
10436, 10460, 10472, 10480, 10492, 10520, 10532, 10540,
|
||||
10552, 10564, 10576, 10600, 10612, 10624, 10636, 10660,
|
||||
10672, 10676, 10700, 10704, 10728, 10756, 10764, 10788,
|
||||
10792, 10796, 10804, 10816, 10824, 10844, 10872, 10876,
|
||||
10888, 10892, 10896, 10908, 11076, 11100, 11140, 11144,
|
||||
11148, 11748, 11788, 11820, 11868, 11900, 11940, 11964,
|
||||
11968, 11980, 12008, 12080, 12120, 12176, 12212, 12248,
|
||||
12288, 12320, 12380, 12400, 12448, 12536, 12576, 12704,
|
||||
12736, 12968, 13000, 13024, 13080, 13136, 13204, 13272,
|
||||
13336, 13380, 13428, 14272, 14288, 14320, 14324, 14332,
|
||||
14340, 14384, 14412, 14440, 14468, 14500, 14532, 14560,
|
||||
14604, 14636, 14656, 14696, 14740, 14792, 14824, 14848,
|
||||
14892, 14944, 14996, 15032, 15076, 15128, 15180, 15216,
|
||||
15272, 15328, 15372, 15416, 15472, 15480, 15488, 15496,
|
||||
15516, 15524, 15536, 15540, 15544, 15588, 15604, 15616,
|
||||
15628, 15632, 15644, 15652, 15656, 15680, 15688, 15692,
|
||||
15704, 15712, 15724, 15764, 15772, 15776, 15804, 15828,
|
||||
15848, 15868, 15880, 15892, 15904, 15912, 15920, 15928,
|
||||
15936, -1,
|
||||
};
|
||||
|
||||
static const int *unsupported_strings[] =
|
||||
{
|
||||
unsupported_strings_1_0,
|
||||
unsupported_strings_1_2,
|
||||
unsupported_strings_1_3,
|
||||
};
|
||||
|
||||
static boolean StringIsUnsupported(unsigned int offset)
|
||||
{
|
||||
const int *string_list;
|
||||
int i;
|
||||
|
||||
string_list = unsupported_strings[deh_hhe_version];
|
||||
|
||||
for (i=0; string_list[i] >= 0; ++i)
|
||||
{
|
||||
if ((unsigned int) string_list[i] == offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean GetStringByOffset(unsigned int offset, char **result)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<arrlen(strings); ++i)
|
||||
{
|
||||
if (strings[i].offsets[deh_hhe_version] == offset)
|
||||
{
|
||||
*result = strings[i].string;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Given a string length, find the maximum length of a
|
||||
// string that can replace it.
|
||||
|
||||
static int MaxStringLength(int len)
|
||||
{
|
||||
// Enough bytes for the string and the NUL terminator
|
||||
|
||||
len += 1;
|
||||
|
||||
// All strings in doom.exe are on 4-byte boundaries, so we may be able
|
||||
// to support a slightly longer string.
|
||||
// Extend up to the next 4-byte boundary
|
||||
|
||||
len += (4 - (len % 4)) % 4;
|
||||
|
||||
// Less one for the NUL terminator.
|
||||
|
||||
return len - 1;
|
||||
}
|
||||
|
||||
// If a string offset does not match any string, it may be because
|
||||
// we are running in the wrong version mode, and the patch was generated
|
||||
// for a different Heretic version. Search the lookup tables to find
|
||||
// versiosn that match.
|
||||
|
||||
static void SuggestOtherVersions(unsigned int offset)
|
||||
{
|
||||
const int *string_list;
|
||||
unsigned int i;
|
||||
unsigned int v;
|
||||
|
||||
// Check main string table.
|
||||
|
||||
for (i=0; i<arrlen(strings); ++i)
|
||||
{
|
||||
for (v=0; v<deh_hhe_num_versions; ++v)
|
||||
{
|
||||
if (strings[i].offsets[v] == offset)
|
||||
{
|
||||
DEH_SuggestHereticVersion(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check unsupported string tables.
|
||||
|
||||
for (v=0; v<deh_hhe_num_versions; ++v)
|
||||
{
|
||||
string_list = unsupported_strings[v];
|
||||
|
||||
for (i=0; string_list[i] >= 0; ++i)
|
||||
{
|
||||
if (string_list[i] == offset)
|
||||
{
|
||||
DEH_SuggestHereticVersion(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *DEH_TextStart(deh_context_t *context, char *line)
|
||||
{
|
||||
char *repl_text;
|
||||
char *orig_text;
|
||||
int orig_offset, repl_len;
|
||||
int i;
|
||||
|
||||
if (sscanf(line, "Text %i %i", &orig_offset, &repl_len) != 2)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
repl_text = Z_Malloc(repl_len + 1, PU_STATIC, NULL);
|
||||
|
||||
// read in the "to" text
|
||||
|
||||
for (i=0; i<repl_len; ++i)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = DEH_GetChar(context);
|
||||
|
||||
repl_text[i] = c;
|
||||
}
|
||||
repl_text[repl_len] = '\0';
|
||||
|
||||
// We don't support all strings, but at least recognise them:
|
||||
|
||||
if (StringIsUnsupported(orig_offset))
|
||||
{
|
||||
DEH_Warning(context, "Unsupported string replacement: %i", orig_offset);
|
||||
}
|
||||
|
||||
// Find the string to replace:
|
||||
|
||||
else if (!GetStringByOffset(orig_offset, &orig_text))
|
||||
{
|
||||
SuggestOtherVersions(orig_offset);
|
||||
DEH_Error(context, "Unknown string offset: %i", orig_offset);
|
||||
}
|
||||
|
||||
// Only allow string replacements that are possible in Vanilla Doom.
|
||||
// Chocolate Doom is unforgiving!
|
||||
|
||||
else if (!deh_allow_long_strings
|
||||
&& repl_len > MaxStringLength(strlen(orig_text)))
|
||||
{
|
||||
DEH_Error(context, "Replacement string is longer than the maximum "
|
||||
"possible in heretic.exe");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Success.
|
||||
|
||||
DEH_AddStringReplacement(orig_text, repl_text);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Failure.
|
||||
|
||||
Z_Free(repl_text);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
// not used
|
||||
}
|
||||
|
||||
deh_section_t deh_section_heretic_text =
|
||||
{
|
||||
"Text",
|
||||
NULL,
|
||||
DEH_TextStart,
|
||||
DEH_TextParseLine,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
186
src/heretic/deh_htic.c
Normal file
186
src/heretic/deh_htic.c
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Top-level dehacked definitions for Heretic dehacked (HHE).
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "deh_defs.h"
|
||||
#include "deh_main.h"
|
||||
#include "deh_htic.h"
|
||||
#include "info.h"
|
||||
#include "m_argv.h"
|
||||
|
||||
char *deh_signatures[] =
|
||||
{
|
||||
"Patch File for HHE v1.0",
|
||||
"Patch File for HHE v1.1",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *hhe_versions[] =
|
||||
{
|
||||
"1.0", "1.2", "1.3"
|
||||
};
|
||||
|
||||
// Version number for patches.
|
||||
|
||||
deh_hhe_version_t deh_hhe_version = deh_hhe_1_0;
|
||||
|
||||
// deh_ammo.c:
|
||||
extern deh_section_t deh_section_ammo;
|
||||
// deh_frame.c:
|
||||
extern deh_section_t deh_section_frame;
|
||||
// deh_ptr.c:
|
||||
extern deh_section_t deh_section_pointer;
|
||||
// deh_sound.c
|
||||
extern deh_section_t deh_section_sound;
|
||||
// deh_htext.c:
|
||||
extern deh_section_t deh_section_heretic_text;
|
||||
// deh_thing.c:
|
||||
extern deh_section_t deh_section_thing;
|
||||
// deh_weapon.c:
|
||||
extern deh_section_t deh_section_weapon;
|
||||
|
||||
//
|
||||
// List of section types:
|
||||
//
|
||||
|
||||
deh_section_t *deh_section_types[] =
|
||||
{
|
||||
&deh_section_ammo,
|
||||
&deh_section_frame,
|
||||
// &deh_section_pointer, TODO
|
||||
&deh_section_sound,
|
||||
&deh_section_heretic_text,
|
||||
&deh_section_thing,
|
||||
&deh_section_weapon,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void SetHHEVersionByName(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<arrlen(hhe_versions); ++i)
|
||||
{
|
||||
if (!strcmp(hhe_versions[i], name))
|
||||
{
|
||||
deh_hhe_version = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown Heretic version: %s\n", name);
|
||||
fprintf(stderr, "Valid versions:\n");
|
||||
|
||||
for (i=0; i<arrlen(hhe_versions); ++i)
|
||||
{
|
||||
fprintf(stderr, "\t%s\n", hhe_versions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Heretic(HHE)-specific dehacked bits.
|
||||
|
||||
void DEH_HereticInit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
//!
|
||||
// @arg <version>
|
||||
//
|
||||
// Select the Heretic version number that was used to generate the
|
||||
// HHE patch to be loaded. Patches for each of the Vanilla
|
||||
// Heretic versions (1.0, 1.2, 1.3) can be loaded, but the correct
|
||||
// version number must be specified.
|
||||
|
||||
i = M_CheckParm("-hhever");
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
SetHHEVersionByName(myargv[i + 1]);
|
||||
}
|
||||
|
||||
// For v1.0 patches, we must apply a slight change to the states[]
|
||||
// table. The table was changed between 1.0 and 1.3 to add two extra
|
||||
// frames to the player "burning death" animation.
|
||||
//
|
||||
// If we are using a v1.0 patch, we must change the table to cut
|
||||
// these out again.
|
||||
|
||||
if (deh_hhe_version < deh_hhe_1_2)
|
||||
{
|
||||
states[S_PLAY_FDTH18].nextstate = S_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int DEH_MapHereticFrameNumber(int frame)
|
||||
{
|
||||
if (deh_hhe_version < deh_hhe_1_2)
|
||||
{
|
||||
// Between Heretic 1.0 and 1.2, two new frames
|
||||
// were added to the "states" table, to extend the "flame death"
|
||||
// animation displayed when the player is killed by fire. Therefore,
|
||||
// we must map Heretic 1.0 frame numbers to corresponding indexes
|
||||
// for our state table.
|
||||
|
||||
if (frame >= S_PLAY_FDTH19)
|
||||
{
|
||||
frame = (frame - S_PLAY_FDTH19) + S_BLOODYSKULL1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// After Heretic 1.2, three unused frames were removed from the
|
||||
// states table, unused phoenix rod frames. Our state table includes
|
||||
// these missing states for backwards compatibility. We must therefore
|
||||
// adjust frame numbers for v1.2/v1.3 to corresponding indexes for
|
||||
// our state table.
|
||||
|
||||
if (frame >= S_PHOENIXFXIX_1)
|
||||
{
|
||||
frame = (frame - S_PHOENIXFXIX_1) + S_PHOENIXPUFF1;
|
||||
}
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void DEH_SuggestHereticVersion(deh_hhe_version_t version)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"This patch may be for version %s. You are currently running in\n"
|
||||
"Heretic %s mode. For %s mode, this mode, add this to your command line:\n"
|
||||
"\n"
|
||||
"\t-hhever %s\n"
|
||||
"\n",
|
||||
hhe_versions[version],
|
||||
hhe_versions[deh_hhe_version],
|
||||
hhe_versions[version],
|
||||
hhe_versions[version]);
|
||||
}
|
||||
|
||||
60
src/heretic/deh_htic.h
Normal file
60
src/heretic/deh_htic.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2010 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Common header for Heretic dehacked (HHE) support.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef DEH_HTIC_H
|
||||
#define DEH_HTIC_H
|
||||
|
||||
#include "info.h"
|
||||
|
||||
// HHE executable version. Loading HHE patches is (unfortunately)
|
||||
// dependent on the version of the Heretic executable used to make them.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
deh_hhe_1_0,
|
||||
deh_hhe_1_2,
|
||||
deh_hhe_1_3,
|
||||
deh_hhe_num_versions
|
||||
} deh_hhe_version_t;
|
||||
|
||||
// HHE doesn't know about the last two states in the state table, so
|
||||
// these are considered invalid.
|
||||
|
||||
#define DEH_HERETIC_NUMSTATES (NUMSTATES - 2)
|
||||
|
||||
// It also doesn't know about the last two things in the mobjinfo table
|
||||
// (which correspond to the states above)
|
||||
|
||||
#define DEH_HERETIC_NUMMOBJTYPES (NUMMOBJTYPES - 2)
|
||||
|
||||
void DEH_HereticInit(void);
|
||||
int DEH_MapHereticFrameNumber(int frame);
|
||||
void DEH_SuggestHereticVersion(deh_hhe_version_t version);
|
||||
|
||||
extern deh_hhe_version_t deh_hhe_version;
|
||||
|
||||
#endif /* #ifndef DEH_HTIC_H */
|
||||
|
||||
118
src/heretic/deh_sound.c
Normal file
118
src/heretic/deh_sound.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses "Sound" sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "doomfeatures.h"
|
||||
#include "doomtype.h"
|
||||
#include "deh_defs.h"
|
||||
#include "deh_main.h"
|
||||
#include "deh_mapping.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "i_sound.h"
|
||||
|
||||
#include "sounds.h"
|
||||
|
||||
DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t)
|
||||
DEH_MAPPING_STRING("Name", name)
|
||||
DEH_UNSUPPORTED_MAPPING("Special")
|
||||
DEH_MAPPING("Value", priority)
|
||||
DEH_MAPPING("Unknown 1", usefulness)
|
||||
DEH_UNSUPPORTED_MAPPING("Unknown 2")
|
||||
DEH_UNSUPPORTED_MAPPING("Unknown 3")
|
||||
DEH_MAPPING("One/Two", numchannels)
|
||||
DEH_END_MAPPING
|
||||
|
||||
static void *DEH_SoundStart(deh_context_t *context, char *line)
|
||||
{
|
||||
int sound_number = 0;
|
||||
|
||||
if (sscanf(line, "Sound %i", &sound_number) != 1)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sound_number < 0 || sound_number >= NUMSFX)
|
||||
{
|
||||
DEH_Warning(context, "Invalid sound number: %i", sound_number);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sound_number >= DEH_VANILLA_NUMSFX)
|
||||
{
|
||||
DEH_Warning(context, "Attempt to modify SFX %i. This will cause "
|
||||
"problems in Vanilla dehacked.", sound_number);
|
||||
}
|
||||
|
||||
return &S_sfx[sound_number];
|
||||
}
|
||||
|
||||
static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
sfxinfo_t *sfx;
|
||||
char *variable_name, *value;
|
||||
|
||||
if (tag == NULL)
|
||||
return;
|
||||
|
||||
sfx = (sfxinfo_t *) tag;
|
||||
|
||||
// Parse the assignment
|
||||
|
||||
if (!DEH_ParseAssignment(line, &variable_name, &value))
|
||||
{
|
||||
// Failed to parse
|
||||
DEH_Warning(context, "Failed to parse assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the field value:
|
||||
|
||||
if (!strcasecmp(variable_name, "Name"))
|
||||
{
|
||||
DEH_SetStringMapping(context, &sound_mapping, sfx,
|
||||
variable_name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEH_SetMapping(context, &sound_mapping, sfx,
|
||||
variable_name, atoi(value));
|
||||
}
|
||||
}
|
||||
|
||||
deh_section_t deh_section_sound =
|
||||
{
|
||||
"Sound",
|
||||
NULL,
|
||||
DEH_SoundStart,
|
||||
DEH_SoundParseLine,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
150
src/heretic/deh_thing.c
Normal file
150
src/heretic/deh_thing.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses "Thing" sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
#include "deh_defs.h"
|
||||
#include "deh_main.h"
|
||||
#include "deh_mapping.h"
|
||||
#include "deh_htic.h"
|
||||
|
||||
#include "info.h"
|
||||
|
||||
DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t)
|
||||
DEH_MAPPING("ID #", doomednum)
|
||||
DEH_MAPPING("Initial frame", spawnstate)
|
||||
DEH_MAPPING("Hit points", spawnhealth)
|
||||
DEH_MAPPING("First moving frame", seestate)
|
||||
DEH_MAPPING("Alert sound", seesound)
|
||||
DEH_MAPPING("Reaction time", reactiontime)
|
||||
DEH_MAPPING("Attack sound", attacksound)
|
||||
DEH_MAPPING("Injury frame", painstate)
|
||||
DEH_MAPPING("Pain chance", painchance)
|
||||
DEH_MAPPING("Pain sound", painsound)
|
||||
DEH_MAPPING("Close attack frame", meleestate)
|
||||
DEH_MAPPING("Far attack frame", missilestate)
|
||||
DEH_MAPPING("Burning frame", crashstate)
|
||||
DEH_MAPPING("Death frame", deathstate)
|
||||
DEH_MAPPING("Exploding frame", xdeathstate)
|
||||
DEH_MAPPING("Death sound", deathsound)
|
||||
DEH_MAPPING("Speed", speed)
|
||||
DEH_MAPPING("Width", radius)
|
||||
DEH_MAPPING("Height", height)
|
||||
DEH_MAPPING("Mass", mass)
|
||||
DEH_MAPPING("Missile damage", damage)
|
||||
DEH_MAPPING("Action sound", activesound)
|
||||
DEH_MAPPING("Bits 1", flags)
|
||||
DEH_MAPPING("Bits 2", flags2)
|
||||
DEH_END_MAPPING
|
||||
|
||||
static void *DEH_ThingStart(deh_context_t *context, char *line)
|
||||
{
|
||||
int thing_number = 0;
|
||||
mobjinfo_t *mobj;
|
||||
|
||||
if (sscanf(line, "Thing %i", &thing_number) != 1)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// HHE thing numbers are indexed from 1
|
||||
--thing_number;
|
||||
|
||||
if (thing_number < 0 || thing_number >= DEH_HERETIC_NUMMOBJTYPES)
|
||||
{
|
||||
DEH_Warning(context, "Invalid thing number: %i", thing_number);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mobj = &mobjinfo[thing_number];
|
||||
|
||||
return mobj;
|
||||
}
|
||||
|
||||
static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
mobjinfo_t *mobj;
|
||||
char *variable_name, *value;
|
||||
int ivalue;
|
||||
|
||||
if (tag == NULL)
|
||||
return;
|
||||
|
||||
mobj = (mobjinfo_t *) tag;
|
||||
|
||||
// Parse the assignment
|
||||
|
||||
if (!DEH_ParseAssignment(line, &variable_name, &value))
|
||||
{
|
||||
// Failed to parse
|
||||
|
||||
DEH_Warning(context, "Failed to parse assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
// all values are integers
|
||||
|
||||
ivalue = atoi(value);
|
||||
|
||||
// If the value to be set is a frame, the frame number must
|
||||
// undergo transformation from a Heretic 1.0 index to a
|
||||
// Heretic 1.3 index.
|
||||
|
||||
if (M_StrCaseStr(variable_name, "frame") != NULL)
|
||||
{
|
||||
ivalue = DEH_MapHereticFrameNumber(ivalue);
|
||||
}
|
||||
|
||||
// Set the field value
|
||||
|
||||
DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue);
|
||||
}
|
||||
|
||||
static void DEH_ThingMD5Sum(md5_context_t *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUMMOBJTYPES; ++i)
|
||||
{
|
||||
DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]);
|
||||
}
|
||||
}
|
||||
|
||||
deh_section_t deh_section_thing =
|
||||
{
|
||||
"Thing",
|
||||
NULL,
|
||||
DEH_ThingStart,
|
||||
DEH_ThingParseLine,
|
||||
NULL,
|
||||
DEH_ThingMD5Sum,
|
||||
};
|
||||
|
||||
131
src/heretic/deh_weapon.c
Normal file
131
src/heretic/deh_weapon.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2005 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Parses "Weapon" sections in dehacked files
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
#include "doomdef.h"
|
||||
|
||||
#include "deh_defs.h"
|
||||
#include "deh_main.h"
|
||||
#include "deh_mapping.h"
|
||||
#include "deh_htic.h"
|
||||
|
||||
DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t)
|
||||
DEH_MAPPING("Ammo type", ammo)
|
||||
DEH_MAPPING("Deselect frame", upstate)
|
||||
DEH_MAPPING("Select frame", downstate)
|
||||
DEH_MAPPING("Bobbing frame", readystate)
|
||||
DEH_MAPPING("Shooting frame", atkstate)
|
||||
DEH_MAPPING("Firing frame", holdatkstate)
|
||||
DEH_MAPPING("Unknown frame", flashstate)
|
||||
DEH_END_MAPPING
|
||||
|
||||
static void *DEH_WeaponStart(deh_context_t *context, char *line)
|
||||
{
|
||||
int weapon_number = 0;
|
||||
|
||||
if (sscanf(line, "Weapon %i", &weapon_number) != 1)
|
||||
{
|
||||
DEH_Warning(context, "Parse error on section start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (weapon_number < 0 || weapon_number >= NUMWEAPONS * 2)
|
||||
{
|
||||
DEH_Warning(context, "Invalid weapon number: %i", weapon_number);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Because of the tome of power, we have two levels of weapons:
|
||||
|
||||
if (weapon_number < NUMWEAPONS)
|
||||
{
|
||||
return &wpnlev1info[weapon_number];
|
||||
}
|
||||
else
|
||||
{
|
||||
return &wpnlev2info[weapon_number - NUMWEAPONS];
|
||||
}
|
||||
}
|
||||
|
||||
static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag)
|
||||
{
|
||||
char *variable_name, *value;
|
||||
weaponinfo_t *weapon;
|
||||
int ivalue;
|
||||
|
||||
if (tag == NULL)
|
||||
return;
|
||||
|
||||
weapon = (weaponinfo_t *) tag;
|
||||
|
||||
if (!DEH_ParseAssignment(line, &variable_name, &value))
|
||||
{
|
||||
// Failed to parse
|
||||
|
||||
DEH_Warning(context, "Failed to parse assignment");
|
||||
return;
|
||||
}
|
||||
|
||||
ivalue = atoi(value);
|
||||
|
||||
// If this is a frame field, we need to map from Heretic 1.0 frame
|
||||
// numbers to Heretic 1.3 frame numbers.
|
||||
|
||||
if (M_StrCaseStr(variable_name, "frame") != NULL)
|
||||
{
|
||||
ivalue = DEH_MapHereticFrameNumber(ivalue);
|
||||
}
|
||||
|
||||
DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue);
|
||||
}
|
||||
|
||||
static void DEH_WeaponMD5Sum(md5_context_t *context)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<NUMWEAPONS ;++i)
|
||||
{
|
||||
DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev1info[i]);
|
||||
DEH_StructMD5Sum(context, &weapon_mapping, &wpnlev2info[i]);
|
||||
}
|
||||
}
|
||||
|
||||
deh_section_t deh_section_weapon =
|
||||
{
|
||||
"Weapon",
|
||||
NULL,
|
||||
DEH_WeaponStart,
|
||||
DEH_WeaponParseLine,
|
||||
NULL,
|
||||
DEH_WeaponMD5Sum,
|
||||
};
|
||||
|
||||
|
|
@ -581,6 +581,7 @@ extern boolean singletics; // debug flag to cancel adaptiveness
|
|||
extern boolean DebugSound; // debug flag for displaying sound info
|
||||
|
||||
extern int maxammo[NUMAMMO];
|
||||
extern int GetWeaponAmmo[NUMWEAPONS];
|
||||
|
||||
extern boolean demoplayback;
|
||||
extern int skytexture;
|
||||
|
|
|
|||
|
|
@ -24,42 +24,6 @@
|
|||
|
||||
// DStrings.h
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// M_menu.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#define PRESSKEY "press a key."
|
||||
#define PRESSYN "press y or n."
|
||||
#define TXT_PAUSED "PAUSED"
|
||||
#define QUITMSG "are you sure you want to\nquit this great game?"
|
||||
#define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY
|
||||
#define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY
|
||||
#define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY
|
||||
#define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY
|
||||
#define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN
|
||||
#define QLPROMPT "do you want to quickload the game named"\
|
||||
"\n\n'%s'?\n\n"PRESSYN
|
||||
#define NEWGAME "you can't start a new game\n"\
|
||||
"while in a network game.\n\n"PRESSKEY
|
||||
#define NIGHTMARE "are you sure? this skill level\n"\
|
||||
"isn't even remotely fair.\n\n"PRESSYN
|
||||
#define SWSTRING "this is the shareware version of doom.\n\n"\
|
||||
"you need to order the entire trilogy.\n\n"PRESSKEY
|
||||
#define MSGOFF "Messages OFF"
|
||||
#define MSGON "Messages ON"
|
||||
#define NETEND "you can't end a netgame!\n\n"PRESSKEY
|
||||
#define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN
|
||||
#define DOSY "(press y to quit to dos.)"
|
||||
#define DETAILHI "High detail"
|
||||
#define DETAILLO "Low detail"
|
||||
#define GAMMALVL0 "Gamma correction OFF"
|
||||
#define GAMMALVL1 "Gamma correction level 1"
|
||||
#define GAMMALVL2 "Gamma correction level 2"
|
||||
#define GAMMALVL3 "Gamma correction level 3"
|
||||
#define GAMMALVL4 "Gamma correction level 4"
|
||||
#define EMPTYSTRING "empty slot"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// P_inter.c
|
||||
|
|
@ -168,74 +132,6 @@
|
|||
|
||||
#define TXT_GAMESAVED "GAME SAVED"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// HU_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define HUSTR_E1M1 "E1M1: Hangar"
|
||||
#define HUSTR_E1M2 "E1M2: Nuclear Plant"
|
||||
#define HUSTR_E1M3 "E1M3: Toxin Refinery"
|
||||
#define HUSTR_E1M4 "E1M4: Command Control"
|
||||
#define HUSTR_E1M5 "E1M5: Phobos Lab"
|
||||
#define HUSTR_E1M6 "E1M6: Central Processing"
|
||||
#define HUSTR_E1M7 "E1M7: Computer Station"
|
||||
#define HUSTR_E1M8 "E1M8: Phobos Anomaly"
|
||||
#define HUSTR_E1M9 "E1M9: Military Base"
|
||||
|
||||
#define HUSTR_E2M1 "E2M1: Deimos Anomaly"
|
||||
#define HUSTR_E2M2 "E2M2: Containment Area"
|
||||
#define HUSTR_E2M3 "E2M3: Refinery"
|
||||
#define HUSTR_E2M4 "E2M4: Deimos Lab"
|
||||
#define HUSTR_E2M5 "E2M5: Command Center"
|
||||
#define HUSTR_E2M6 "E2M6: Halls of the Damned"
|
||||
#define HUSTR_E2M7 "E2M7: Spawning Vats"
|
||||
#define HUSTR_E2M8 "E2M8: Tower of Babel"
|
||||
#define HUSTR_E2M9 "E2M9: Fortress of Mystery"
|
||||
|
||||
#define HUSTR_E3M1 "E3M1: Hell Keep"
|
||||
#define HUSTR_E3M2 "E3M2: Slough of Despair"
|
||||
#define HUSTR_E3M3 "E3M3: Pandemonium"
|
||||
#define HUSTR_E3M4 "E3M4: House of Pain"
|
||||
#define HUSTR_E3M5 "E3M5: Unholy Cathedral"
|
||||
#define HUSTR_E3M6 "E3M6: Mt. Erebus"
|
||||
#define HUSTR_E3M7 "E3M7: Limbo"
|
||||
#define HUSTR_E3M8 "E3M8: Dis"
|
||||
#define HUSTR_E3M9 "E3M9: Warrens"
|
||||
|
||||
#define HUSTR_CHATMACRO1 "I'm ready to kick butt!"
|
||||
#define HUSTR_CHATMACRO2 "I'm OK."
|
||||
#define HUSTR_CHATMACRO3 "I'm not looking too good!"
|
||||
#define HUSTR_CHATMACRO4 "Help!"
|
||||
#define HUSTR_CHATMACRO5 "You suck!"
|
||||
#define HUSTR_CHATMACRO6 "Next time, scumbag..."
|
||||
#define HUSTR_CHATMACRO7 "Come here!"
|
||||
#define HUSTR_CHATMACRO8 "I'll take care of it."
|
||||
#define HUSTR_CHATMACRO9 "Yes"
|
||||
#define HUSTR_CHATMACRO0 "No"
|
||||
|
||||
#define HUSTR_TALKTOSELF1 "You mumble to yourself"
|
||||
#define HUSTR_TALKTOSELF2 "Who's there?"
|
||||
#define HUSTR_TALKTOSELF3 "You scare yourself"
|
||||
#define HUSTR_TALKTOSELF4 "You start to rave"
|
||||
#define HUSTR_TALKTOSELF5 "You've lost it..."
|
||||
|
||||
#define HUSTR_MESSAGESENT "[Message Sent]"
|
||||
|
||||
// The following should NOT be changed unless it seems
|
||||
// just AWFULLY necessary
|
||||
|
||||
#define HUSTR_PLRGREEN "Green: "
|
||||
#define HUSTR_PLRINDIGO "Indigo: "
|
||||
#define HUSTR_PLRBROWN "Brown: "
|
||||
#define HUSTR_PLRRED "Red: "
|
||||
|
||||
#define HUSTR_KEYGREEN 'g'
|
||||
#define HUSTR_KEYINDIGO 'i'
|
||||
#define HUSTR_KEYBROWN 'b'
|
||||
#define HUSTR_KEYRED 'r'
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// AM_map.c
|
||||
|
|
@ -251,26 +147,6 @@
|
|||
#define AMSTR_MARKEDSPOT "Marked Spot"
|
||||
#define AMSTR_MARKSCLEARED "All Marks Cleared"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// ST_stuff.c
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#define STSTR_DQDON "Degreelessness Mode On"
|
||||
#define STSTR_DQDOFF "Degreelessness Mode Off"
|
||||
|
||||
#define STSTR_KFAADDED "Very Happy Ammo Added"
|
||||
|
||||
#define STSTR_NCON "No Clipping Mode ON"
|
||||
#define STSTR_NCOFF "No Clipping Mode OFF"
|
||||
|
||||
#define STSTR_BEHOLD "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"
|
||||
#define STSTR_BEHOLDX "Power-up Toggled"
|
||||
|
||||
#define STSTR_CHOPPERS "... doesn't suck - GM"
|
||||
#define STSTR_CLEV "Changing Level..."
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// F_finale.c
|
||||
|
|
@ -374,56 +250,3 @@
|
|||
"surrender without a fight. eyes\n"\
|
||||
"wide, you go to meet your fate."
|
||||
|
||||
/*
|
||||
#define E1TEXT "Once you beat the big badasses and\n"\
|
||||
"clean out the moon base you're supposed\n"\
|
||||
"to win, aren't you? Aren't you? Where's\n"\
|
||||
"your fat reward and ticket home? What\n"\
|
||||
"the hell is this? It's not supposed to\n"\
|
||||
"end this way!\n"\
|
||||
"\n" \
|
||||
"It stinks like rotten meat, but looks\n"\
|
||||
"like the lost Deimos base. Looks like\n"\
|
||||
"you're stuck on The Shores of Hell.\n"\
|
||||
"The only way out is through.\n"\
|
||||
"\n"\
|
||||
"To continue the DOOM experience, play\n"\
|
||||
"The Shores of Hell and its amazing\n"\
|
||||
"sequel, Inferno!\n"
|
||||
|
||||
#define E2TEXT "You've done it! The hideous cyber-\n"\
|
||||
"demon lord that ruled the lost Deimos\n"\
|
||||
"moon base has been slain and you\n"\
|
||||
"are triumphant! But ... where are\n"\
|
||||
"you? You clamber to the edge of the\n"\
|
||||
"moon and look down to see the awful\n"\
|
||||
"truth.\n" \
|
||||
"\n"\
|
||||
"Deimos floats above Hell itself!\n"\
|
||||
"You've never heard of anyone escaping\n"\
|
||||
"from Hell, but you'll make the bastards\n"\
|
||||
"sorry they ever heard of you! Quickly,\n"\
|
||||
"you rappel down to the surface of\n"\
|
||||
"Hell.\n"\
|
||||
"\n" \
|
||||
"Now, it's on to the final chapter of\n"\
|
||||
"DOOM! -- Inferno."
|
||||
|
||||
#define E3TEXT "The loathsome spiderdemon that\n"\
|
||||
"masterminded the invasion of the moon\n"\
|
||||
"bases and caused so much death has had\n"\
|
||||
"its ass kicked for all time.\n"\
|
||||
"\n"\
|
||||
"A hidden doorway opens and you enter.\n"\
|
||||
"You've proven too tough for Hell to\n"\
|
||||
"contain, and now Hell at last plays\n"\
|
||||
"fair -- for you emerge from the door\n"\
|
||||
"to see the green fields of Earth!\n"\
|
||||
"Home at last.\n" \
|
||||
"\n"\
|
||||
"You wonder what's been happening on\n"\
|
||||
"Earth while you were battling evil\n"\
|
||||
"unleashed. It's good that no Hell-\n"\
|
||||
"spawn could have come through that\n"\
|
||||
"door with you ..."
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_swap.h"
|
||||
#include "i_video.h"
|
||||
#include "s_sound.h"
|
||||
|
|
@ -37,11 +38,6 @@ int finalecount;
|
|||
#define TEXTSPEED 3
|
||||
#define TEXTWAIT 250
|
||||
|
||||
char *e1text = E1TEXT;
|
||||
char *e2text = E2TEXT;
|
||||
char *e3text = E3TEXT;
|
||||
char *e4text = E4TEXT;
|
||||
char *e5text = E5TEXT;
|
||||
char *finaletext;
|
||||
char *finaleflat;
|
||||
|
||||
|
|
@ -72,30 +68,30 @@ void F_StartFinale(void)
|
|||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
finaleflat = "FLOOR25";
|
||||
finaletext = e1text;
|
||||
finaleflat = DEH_String("FLOOR25");
|
||||
finaletext = DEH_String(E1TEXT);
|
||||
break;
|
||||
case 2:
|
||||
finaleflat = "FLATHUH1";
|
||||
finaletext = e2text;
|
||||
finaleflat = DEH_String("FLATHUH1");
|
||||
finaletext = DEH_String(E2TEXT);
|
||||
break;
|
||||
case 3:
|
||||
finaleflat = "FLTWAWA2";
|
||||
finaletext = e3text;
|
||||
finaleflat = DEH_String("FLTWAWA2");
|
||||
finaletext = DEH_String(E3TEXT);
|
||||
break;
|
||||
case 4:
|
||||
finaleflat = "FLOOR28";
|
||||
finaletext = e4text;
|
||||
finaleflat = DEH_String("FLOOR28");
|
||||
finaletext = DEH_String(E4TEXT);
|
||||
break;
|
||||
case 5:
|
||||
finaleflat = "FLOOR08";
|
||||
finaletext = e5text;
|
||||
finaleflat = DEH_String("FLOOR08");
|
||||
finaletext = DEH_String(E5TEXT);
|
||||
break;
|
||||
}
|
||||
|
||||
finalestage = 0;
|
||||
finalecount = 0;
|
||||
FontABaseLump = W_GetNumForName("FONTA_S") + 1;
|
||||
FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1;
|
||||
|
||||
// S_ChangeMusic(mus_victor, true);
|
||||
S_StartSong(mus_cptd, true);
|
||||
|
|
@ -277,8 +273,8 @@ void F_DemonScroll(void)
|
|||
{
|
||||
return;
|
||||
}
|
||||
p1 = W_CacheLumpName("FINAL1", PU_LEVEL);
|
||||
p2 = W_CacheLumpName("FINAL2", PU_LEVEL);
|
||||
p1 = W_CacheLumpName(DEH_String("FINAL1"), PU_LEVEL);
|
||||
p2 = W_CacheLumpName(DEH_String("FINAL2"), PU_LEVEL);
|
||||
if (finalecount < 70)
|
||||
{
|
||||
memcpy(I_VideoBuffer, p1, SCREENHEIGHT * SCREENWIDTH);
|
||||
|
|
@ -319,8 +315,8 @@ void F_DrawUnderwater(void)
|
|||
{
|
||||
underwawa = true;
|
||||
memset((byte *) 0xa0000, 0, SCREENWIDTH * SCREENHEIGHT);
|
||||
I_SetPalette(W_CacheLumpName("E2PAL", PU_CACHE));
|
||||
V_DrawRawScreen(W_CacheLumpName("E2END", PU_CACHE));
|
||||
I_SetPalette(W_CacheLumpName(DEH_String("E2PAL"), PU_CACHE));
|
||||
V_DrawRawScreen(W_CacheLumpName(DEH_String("E2END"), PU_CACHE));
|
||||
}
|
||||
paused = false;
|
||||
MenuActive = false;
|
||||
|
|
@ -328,7 +324,7 @@ void F_DrawUnderwater(void)
|
|||
|
||||
break;
|
||||
case 2:
|
||||
V_DrawRawScreen(W_CacheLumpName("TITLE", PU_CACHE));
|
||||
V_DrawRawScreen(W_CacheLumpName(DEH_String("TITLE"), PU_CACHE));
|
||||
//D_StartTitle(); // go to intro/demo mode.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <string.h>
|
||||
#include "doomdef.h"
|
||||
#include "doomkeys.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_timer.h"
|
||||
#include "i_system.h"
|
||||
#include "m_controls.h"
|
||||
|
|
@ -862,12 +863,16 @@ void G_Ticker(void)
|
|||
{
|
||||
if (netgame)
|
||||
{
|
||||
strcpy(savedescription, "NET GAME");
|
||||
strncpy(savedescription, DEH_String("NET GAME"),
|
||||
sizeof(savedescription));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(savedescription, "SAVE GAME");
|
||||
strncpy(savedescription, DEH_String("SAVE GAME"),
|
||||
sizeof(savedescription));
|
||||
}
|
||||
|
||||
savedescription[sizeof(savedescription) - 1] = '\0';
|
||||
}
|
||||
savegameslot =
|
||||
(players[i].cmd.
|
||||
|
|
@ -1320,7 +1325,9 @@ void G_DoLoadGame(void)
|
|||
save_p = savebuffer + SAVESTRINGSIZE;
|
||||
// Skip the description field
|
||||
memset(vcheck, 0, sizeof(vcheck));
|
||||
sprintf(vcheck, "version %i", HERETIC_VERSION);
|
||||
|
||||
DEH_snprintf(vcheck, VERSIONSIZE, "version %i", HERETIC_VERSION);
|
||||
|
||||
if (strcmp((char *) save_p, vcheck) != 0)
|
||||
{ // Bad version
|
||||
return;
|
||||
|
|
@ -1449,11 +1456,11 @@ void G_InitNew(skill_t skill, int episode, int map)
|
|||
// Set the sky map
|
||||
if (episode > 5)
|
||||
{
|
||||
skytexture = R_TextureNumForName("SKY1");
|
||||
skytexture = R_TextureNumForName(DEH_String("SKY1"));
|
||||
}
|
||||
else
|
||||
{
|
||||
skytexture = R_TextureNumForName(skyLumpNames[episode - 1]);
|
||||
skytexture = R_TextureNumForName(DEH_String(skyLumpNames[episode - 1]));
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1694,7 +1701,7 @@ void G_DoSaveGame(void)
|
|||
SV_Open(name);
|
||||
SV_Write(description, SAVESTRINGSIZE);
|
||||
memset(verString, 0, sizeof(verString));
|
||||
sprintf(verString, "version %i", HERETIC_VERSION);
|
||||
DEH_snprintf(verString, VERSIONSIZE, "version %i", HERETIC_VERSION);
|
||||
SV_Write(verString, VERSIONSIZE);
|
||||
SV_WriteByte(gameskill);
|
||||
SV_WriteByte(gameepisode);
|
||||
|
|
@ -1714,7 +1721,7 @@ void G_DoSaveGame(void)
|
|||
|
||||
gameaction = ga_nothing;
|
||||
savedescription[0] = 0;
|
||||
P_SetMessage(&players[consoleplayer], TXT_GAMESAVED, true);
|
||||
P_SetMessage(&players[consoleplayer], DEH_String(TXT_GAMESAVED), true);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
*/
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
|
|
@ -161,7 +162,7 @@ extern void AM_Stop(void);
|
|||
|
||||
void IN_Start(void)
|
||||
{
|
||||
I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
|
||||
I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE));
|
||||
IN_LoadPics();
|
||||
IN_InitStats();
|
||||
intermission = true;
|
||||
|
|
@ -308,26 +309,26 @@ static void IN_LoadUnloadPics(void (*callback)(char *lumpname,
|
|||
switch (gameepisode)
|
||||
{
|
||||
case 1:
|
||||
callback("MAPE1", 0, &patchINTERPIC);
|
||||
callback(DEH_String("MAPE1"), 0, &patchINTERPIC);
|
||||
break;
|
||||
case 2:
|
||||
callback("MAPE2", 0, &patchINTERPIC);
|
||||
callback(DEH_String("MAPE2"), 0, &patchINTERPIC);
|
||||
break;
|
||||
case 3:
|
||||
callback("MAPE3", 0, &patchINTERPIC);
|
||||
callback(DEH_String("MAPE3"), 0, &patchINTERPIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
callback("IN_X", 0, &patchBEENTHERE);
|
||||
callback("IN_YAH", 0, &patchGOINGTHERE);
|
||||
callback("FONTB13", 0, &FontBNegative);
|
||||
callback(DEH_String("IN_X"), 0, &patchBEENTHERE);
|
||||
callback(DEH_String("IN_YAH"), 0, &patchGOINGTHERE);
|
||||
callback(DEH_String("FONTB13"), 0, &FontBNegative);
|
||||
|
||||
callback("FONTB15", 0, &FontBSlash);
|
||||
callback("FONTB05", 0, &FontBPercent);
|
||||
callback(DEH_String("FONTB15"), 0, &FontBSlash);
|
||||
callback(DEH_String("FONTB05"), 0, &FontBPercent);
|
||||
|
||||
FontBLumpBase = W_GetNumForName("FONTB16");
|
||||
FontBLumpBase = W_GetNumForName(DEH_String("FONTB16"));
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
|
|
@ -355,9 +356,9 @@ static void LoadLumpCallback(char *lumpname, int lumpnum, patch_t **ptr)
|
|||
|
||||
void IN_LoadPics(void)
|
||||
{
|
||||
FontBLump = W_GetNumForName("FONTB_S") + 1;
|
||||
patchFaceOkayBase = W_GetNumForName("FACEA0");
|
||||
patchFaceDeadBase = W_GetNumForName("FACEB0");
|
||||
FontBLump = W_GetNumForName(DEH_String("FONTB_S")) + 1;
|
||||
patchFaceOkayBase = W_GetNumForName(DEH_String("FACEA0"));
|
||||
patchFaceDeadBase = W_GetNumForName(DEH_String("FACEB0"));
|
||||
|
||||
IN_LoadUnloadPics(LoadLumpCallback);
|
||||
}
|
||||
|
|
@ -580,7 +581,7 @@ void IN_DrawStatBack(void)
|
|||
byte *src;
|
||||
byte *dest;
|
||||
|
||||
src = W_CacheLumpName("FLOOR16", PU_CACHE);
|
||||
src = W_CacheLumpName(DEH_String("FLOOR16"), PU_CACHE);
|
||||
dest = I_VideoBuffer;
|
||||
|
||||
for (y = 0; y < SCREENHEIGHT; y++)
|
||||
|
|
@ -612,8 +613,8 @@ void IN_DrawOldLevel(void)
|
|||
x = 160 - MN_TextBWidth(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] +
|
||||
7) / 2;
|
||||
IN_DrTextB(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] + 7, x, 3);
|
||||
x = 160 - MN_TextAWidth("FINISHED") / 2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2;
|
||||
MN_DrTextA(DEH_String("FINISHED"), x, 25);
|
||||
|
||||
if (prevmap == 9)
|
||||
{
|
||||
|
|
@ -660,8 +661,8 @@ void IN_DrawYAH(void)
|
|||
int i;
|
||||
int x;
|
||||
|
||||
x = 160 - MN_TextAWidth("NOW ENTERING:") / 2;
|
||||
MN_DrTextA("NOW ENTERING:", x, 10);
|
||||
x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2;
|
||||
MN_DrTextA(DEH_String("NOW ENTERING:"), x, 10);
|
||||
x = 160 - MN_TextBWidth(LevelNames[(gameepisode - 1) * 9 + gamemap - 1] +
|
||||
7) / 2;
|
||||
IN_DrTextB(LevelNames[(gameepisode - 1) * 9 + gamemap - 1] + 7, x, 20);
|
||||
|
|
@ -698,15 +699,15 @@ void IN_DrawSingleStats(void)
|
|||
int x;
|
||||
static int sounds;
|
||||
|
||||
IN_DrTextB("KILLS", 50, 65);
|
||||
IN_DrTextB("ITEMS", 50, 90);
|
||||
IN_DrTextB("SECRETS", 50, 115);
|
||||
IN_DrTextB(DEH_String("KILLS"), 50, 65);
|
||||
IN_DrTextB(DEH_String("ITEMS"), 50, 90);
|
||||
IN_DrTextB(DEH_String("SECRETS"), 50, 115);
|
||||
|
||||
x = 160 - MN_TextBWidth(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] +
|
||||
7) / 2;
|
||||
IN_DrTextB(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] + 7, x, 3);
|
||||
x = 160 - MN_TextAWidth("FINISHED") / 2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2;
|
||||
MN_DrTextA(DEH_String("FINISHED"), x, 25);
|
||||
|
||||
if (intertime < 30)
|
||||
{
|
||||
|
|
@ -757,13 +758,13 @@ void IN_DrawSingleStats(void)
|
|||
|
||||
if (gamemode != retail || gameepisode <= 3)
|
||||
{
|
||||
IN_DrTextB("TIME", 85, 160);
|
||||
IN_DrTextB(DEH_String("TIME"), 85, 160);
|
||||
IN_DrawTime(155, 160, hours, minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 160 - MN_TextAWidth("NOW ENTERING:") / 2;
|
||||
MN_DrTextA("NOW ENTERING:", x, 160);
|
||||
x = 160 - MN_TextAWidth(DEH_String("NOW ENTERING:")) / 2;
|
||||
MN_DrTextA(DEH_String("NOW ENTERING:"), x, 160);
|
||||
x = 160 -
|
||||
MN_TextBWidth(LevelNames[(gameepisode - 1) * 9 + gamemap - 1] +
|
||||
7) / 2;
|
||||
|
|
@ -787,14 +788,14 @@ void IN_DrawCoopStats(void)
|
|||
|
||||
static int sounds;
|
||||
|
||||
IN_DrTextB("KILLS", 95, 35);
|
||||
IN_DrTextB("BONUS", 155, 35);
|
||||
IN_DrTextB("SECRET", 232, 35);
|
||||
IN_DrTextB(DEH_String("KILLS"), 95, 35);
|
||||
IN_DrTextB(DEH_String("BONUS"), 155, 35);
|
||||
IN_DrTextB(DEH_String("SECRET"), 232, 35);
|
||||
x = 160 - MN_TextBWidth(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] +
|
||||
7) / 2;
|
||||
IN_DrTextB(LevelNames[(gameepisode - 1) * 9 + prevmap - 1] + 7, x, 3);
|
||||
x = 160 - MN_TextAWidth("FINISHED") / 2;
|
||||
MN_DrTextA("FINISHED", x, 25);
|
||||
x = 160 - MN_TextAWidth(DEH_String("FINISHED")) / 2;
|
||||
MN_DrTextA(DEH_String("FINISHED"), x, 25);
|
||||
|
||||
ypos = 50;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
|
|
@ -845,11 +846,11 @@ void IN_DrawDMStats(void)
|
|||
xpos = 90;
|
||||
ypos = 55;
|
||||
|
||||
IN_DrTextB("TOTAL", 265, 30);
|
||||
MN_DrTextA("VICTIMS", 140, 8);
|
||||
IN_DrTextB(DEH_String("TOTAL"), 265, 30);
|
||||
MN_DrTextA(DEH_String("VICTIMS"), 140, 8);
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
MN_DrTextA(KillersText[i], 10, 80 + 9 * i);
|
||||
MN_DrTextA(DEH_String(KillersText[i]), 10, 80 + 9 * i);
|
||||
}
|
||||
if (intertime < 20)
|
||||
{
|
||||
|
|
@ -940,7 +941,7 @@ void IN_DrawTime(int x, int y, int h, int m, int s)
|
|||
if (h)
|
||||
{
|
||||
IN_DrawNumber(h, x, y, 2);
|
||||
IN_DrTextB(":", x + 26, y);
|
||||
IN_DrTextB(DEH_String(":"), x + 26, y);
|
||||
}
|
||||
x += 34;
|
||||
if (m || h)
|
||||
|
|
@ -950,7 +951,7 @@ void IN_DrawTime(int x, int y, int h, int m, int s)
|
|||
x += 34;
|
||||
if (s)
|
||||
{
|
||||
IN_DrTextB(":", x - 8, y);
|
||||
IN_DrTextB(DEH_String(":"), x - 8, y);
|
||||
IN_DrawNumber(s, x, y, 2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "doomdef.h"
|
||||
// generated by multigen
|
||||
#include "p_action.h"
|
||||
|
||||
char *sprnames[] = {
|
||||
"IMPX","ACLO","PTN1","SHLD","SHD2","BAGH","SPMP","INVS","PTN2","SOAR",
|
||||
|
|
@ -41,132 +41,6 @@ char *sprnames[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
void A_FreeTargMobj();
|
||||
void A_RestoreSpecialThing1();
|
||||
void A_RestoreSpecialThing2();
|
||||
void A_HideThing();
|
||||
void A_UnHideThing();
|
||||
void A_RestoreArtifact();
|
||||
void A_Scream();
|
||||
void A_Explode();
|
||||
void A_PodPain();
|
||||
void A_RemovePod();
|
||||
void A_MakePod();
|
||||
void A_InitKeyGizmo();
|
||||
void A_VolcanoSet();
|
||||
void A_VolcanoBlast();
|
||||
void A_BeastPuff();
|
||||
void A_VolcBallImpact();
|
||||
void A_SpawnTeleGlitter();
|
||||
void A_SpawnTeleGlitter2();
|
||||
void A_AccTeleGlitter();
|
||||
void A_Light0();
|
||||
void A_WeaponReady();
|
||||
void A_Lower();
|
||||
void A_Raise();
|
||||
void A_StaffAttackPL1();
|
||||
void A_ReFire();
|
||||
void A_StaffAttackPL2();
|
||||
void A_BeakReady();
|
||||
void A_BeakRaise();
|
||||
void A_BeakAttackPL1();
|
||||
void A_BeakAttackPL2();
|
||||
void A_GauntletAttack();
|
||||
void A_FireBlasterPL1();
|
||||
void A_FireBlasterPL2();
|
||||
void A_SpawnRippers();
|
||||
void A_FireMacePL1();
|
||||
void A_FireMacePL2();
|
||||
void A_MacePL1Check();
|
||||
void A_MaceBallImpact();
|
||||
void A_MaceBallImpact2();
|
||||
void A_DeathBallImpact();
|
||||
void A_FireSkullRodPL1();
|
||||
void A_FireSkullRodPL2();
|
||||
void A_SkullRodPL2Seek();
|
||||
void A_AddPlayerRain();
|
||||
void A_HideInCeiling();
|
||||
void A_SkullRodStorm();
|
||||
void A_RainImpact();
|
||||
void A_FireGoldWandPL1();
|
||||
void A_FireGoldWandPL2();
|
||||
void A_FirePhoenixPL1();
|
||||
void A_InitPhoenixPL2();
|
||||
void A_FirePhoenixPL2();
|
||||
void A_ShutdownPhoenixPL2();
|
||||
void A_PhoenixPuff();
|
||||
void A_FlameEnd();
|
||||
void A_FloatPuff();
|
||||
void A_FireCrossbowPL1();
|
||||
void A_FireCrossbowPL2();
|
||||
void A_BoltSpark();
|
||||
void A_Pain();
|
||||
void A_NoBlocking();
|
||||
void A_AddPlayerCorpse();
|
||||
void A_SkullPop();
|
||||
void A_FlameSnd();
|
||||
void A_CheckBurnGone();
|
||||
void A_CheckSkullFloor();
|
||||
void A_CheckSkullDone();
|
||||
void A_Feathers();
|
||||
void A_ChicLook();
|
||||
void A_ChicChase();
|
||||
void A_ChicPain();
|
||||
void A_FaceTarget();
|
||||
void A_ChicAttack();
|
||||
void A_Look();
|
||||
void A_Chase();
|
||||
void A_MummyAttack();
|
||||
void A_MummyAttack2();
|
||||
void A_MummySoul();
|
||||
void A_ContMobjSound();
|
||||
void A_MummyFX1Seek();
|
||||
void A_BeastAttack();
|
||||
void A_SnakeAttack();
|
||||
void A_SnakeAttack2();
|
||||
void A_HeadAttack();
|
||||
void A_BossDeath();
|
||||
void A_HeadIceImpact();
|
||||
void A_HeadFireGrow();
|
||||
void A_WhirlwindSeek();
|
||||
void A_ClinkAttack();
|
||||
void A_WizAtk1();
|
||||
void A_WizAtk2();
|
||||
void A_WizAtk3();
|
||||
void A_GhostOff();
|
||||
void A_ImpMeAttack();
|
||||
void A_ImpMsAttack();
|
||||
void A_ImpMsAttack2();
|
||||
void A_ImpDeath();
|
||||
void A_ImpXDeath1();
|
||||
void A_ImpXDeath2();
|
||||
void A_ImpExplode();
|
||||
void A_KnightAttack();
|
||||
void A_DripBlood();
|
||||
void A_Sor1Chase();
|
||||
void A_Sor1Pain();
|
||||
void A_Srcr1Attack();
|
||||
void A_SorZap();
|
||||
void A_SorcererRise();
|
||||
void A_SorRise();
|
||||
void A_SorSightSnd();
|
||||
void A_Srcr2Decide();
|
||||
void A_Srcr2Attack();
|
||||
void A_Sor2DthInit();
|
||||
void A_SorDSph();
|
||||
void A_Sor2DthLoop();
|
||||
void A_SorDExp();
|
||||
void A_SorDBon();
|
||||
void A_BlueSpark();
|
||||
void A_GenWizard();
|
||||
void A_MinotaurAtk1();
|
||||
void A_MinotaurDecide();
|
||||
void A_MinotaurAtk2();
|
||||
void A_MinotaurAtk3();
|
||||
void A_MinotaurCharge();
|
||||
void A_MntrFloorFire();
|
||||
void A_ESound();
|
||||
|
||||
state_t states[NUMSTATES] = {
|
||||
{SPR_IMPX, 0, -1, NULL, S_NULL, 0, 0}, // S_NULL
|
||||
{SPR_ACLO, 4, 1050, A_FreeTargMobj, S_NULL, 0, 0}, // S_FREETARGMOBJ
|
||||
|
|
@ -663,6 +537,9 @@ state_t states[NUMSTATES] = {
|
|||
{SPR_FX08, 32773, 4, NULL, S_PHOENIXFXI1_7, 0, 0}, // S_PHOENIXFXI1_6
|
||||
{SPR_FX08, 32774, 4, NULL, S_PHOENIXFXI1_8, 0, 0}, // S_PHOENIXFXI1_7
|
||||
{SPR_FX08, 32775, 4, NULL, S_NULL, 0, 0}, // S_PHOENIXFXI1_8
|
||||
{SPR_FX08, 32776, 8, NULL, S_PHOENIXFXIX_1, 0, 0 }, // S_PHOENIXFXIX_1
|
||||
{SPR_FX08, 32777, 8, A_RemovedPhoenixFunc, S_PHOENIXFXIX_2, 0, 0 }, // S_PHOENIXFXIX_2
|
||||
{SPR_FX08, 32778, 8, NULL, S_NULL, 0, 0 }, // S_PHOENIXFXIX_3
|
||||
{SPR_FX04, 1, 4, NULL, S_PHOENIXPUFF2, 0, 0}, // S_PHOENIXPUFF1
|
||||
{SPR_FX04, 2, 4, NULL, S_PHOENIXPUFF3, 0, 0}, // S_PHOENIXPUFF2
|
||||
{SPR_FX04, 3, 4, NULL, S_PHOENIXPUFF4, 0, 0}, // S_PHOENIXPUFF3
|
||||
|
|
@ -3727,6 +3604,37 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = {
|
|||
MF2_THRUGHOST | MF2_NOTELEPORT // flags2
|
||||
},
|
||||
|
||||
// The following thing is present in the mobjinfo table from Heretic 1.0,
|
||||
// but not in Heretic 1.3 (ie. it was removed). It has been re-inserted
|
||||
// here to support HHE patches.
|
||||
|
||||
{ // MT_PHOENIXFX_REMOVED
|
||||
-1, // doomednum
|
||||
S_PHOENIXFXIX_1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // crashstate
|
||||
S_PHOENIXFXIX_3, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
2 * FRACUNIT, // radius
|
||||
4 * FRACUNIT, // height
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP | MF_MISSILE | MF_DROPOFF | MF_NOGRAVITY, // flags
|
||||
MF2_NOTELEPORT // flags2
|
||||
},
|
||||
|
||||
{ // MT_PHOENIXPUFF
|
||||
-1, // doomednum
|
||||
S_PHOENIXPUFF1, // spawnstate
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// generated by multigen
|
||||
|
||||
#ifndef HERETIC_INFO_H
|
||||
#define HERETIC_INFO_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -653,6 +655,9 @@ typedef enum
|
|||
S_PHOENIXFXI1_6,
|
||||
S_PHOENIXFXI1_7,
|
||||
S_PHOENIXFXI1_8,
|
||||
S_PHOENIXFXIX_1, // [ States in Heretic 1.0 that were removed
|
||||
S_PHOENIXFXIX_2,
|
||||
S_PHOENIXFXIX_3, // ]
|
||||
S_PHOENIXPUFF1,
|
||||
S_PHOENIXPUFF2,
|
||||
S_PHOENIXPUFF3,
|
||||
|
|
@ -773,8 +778,8 @@ typedef enum
|
|||
S_PLAY_FDTH16,
|
||||
S_PLAY_FDTH17,
|
||||
S_PLAY_FDTH18,
|
||||
S_PLAY_FDTH19,
|
||||
S_PLAY_FDTH20,
|
||||
S_PLAY_FDTH19, // < These two frames were not present in the Heretic
|
||||
S_PLAY_FDTH20, // < 1.0 executable (fire death animation was extended)
|
||||
S_BLOODYSKULL1,
|
||||
S_BLOODYSKULL2,
|
||||
S_BLOODYSKULL3,
|
||||
|
|
@ -1470,6 +1475,7 @@ typedef enum
|
|||
MT_GOLDWANDPUFF2,
|
||||
MT_WPHOENIXROD,
|
||||
MT_PHOENIXFX1,
|
||||
MT_PHOENIXFX_REMOVED, // In Heretic 1.0, but removed.
|
||||
MT_PHOENIXPUFF,
|
||||
MT_PHOENIXFX2,
|
||||
MT_MISC15,
|
||||
|
|
@ -1575,3 +1581,6 @@ typedef struct
|
|||
} mobjinfo_t;
|
||||
|
||||
extern mobjinfo_t mobjinfo[NUMMOBJTYPES];
|
||||
|
||||
#endif /* #ifndef HERETIC_INFO_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
// MN_menu.c
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "deh_str.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomkeys.h"
|
||||
#include "i_system.h"
|
||||
|
|
@ -73,7 +75,7 @@ typedef struct
|
|||
{
|
||||
ItemType_t type;
|
||||
char *text;
|
||||
boolean(*func) (int option);
|
||||
boolean(*func) (int option);
|
||||
int option;
|
||||
MenuType_t menu;
|
||||
} MenuItem_t;
|
||||
|
|
@ -305,7 +307,7 @@ void MN_Init(void)
|
|||
InitFonts();
|
||||
MenuActive = false;
|
||||
messageson = true;
|
||||
SkullBaseLump = W_GetNumForName("M_SKL00");
|
||||
SkullBaseLump = W_GetNumForName(DEH_String("M_SKL00"));
|
||||
|
||||
if (gamemode == retail)
|
||||
{ // Add episodes 4 and 5 to the menu
|
||||
|
|
@ -322,8 +324,8 @@ void MN_Init(void)
|
|||
|
||||
static void InitFonts(void)
|
||||
{
|
||||
FontABaseLump = W_GetNumForName("FONTA_S") + 1;
|
||||
FontBBaseLump = W_GetNumForName("FONTB_S") + 1;
|
||||
FontABaseLump = W_GetNumForName(DEH_String("FONTA_S")) + 1;
|
||||
FontBBaseLump = W_GetNumForName(DEH_String("FONTB_S")) + 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -476,26 +478,28 @@ void MN_Drawer(void)
|
|||
int x;
|
||||
int y;
|
||||
MenuItem_t *item;
|
||||
char *message;
|
||||
char *selName;
|
||||
|
||||
if (MenuActive == false)
|
||||
{
|
||||
if (askforquit)
|
||||
{
|
||||
MN_DrTextA(QuitEndMsg[typeofask - 1], 160 -
|
||||
MN_TextAWidth(QuitEndMsg[typeofask - 1]) / 2, 80);
|
||||
message = DEH_String(QuitEndMsg[typeofask - 1]);
|
||||
|
||||
MN_DrTextA(message, 160 - MN_TextAWidth(message) / 2, 80);
|
||||
if (typeofask == 3)
|
||||
{
|
||||
MN_DrTextA(SlotText[quicksave - 1], 160 -
|
||||
MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90);
|
||||
MN_DrTextA("?", 160 +
|
||||
MN_DrTextA(DEH_String("?"), 160 +
|
||||
MN_TextAWidth(SlotText[quicksave - 1]) / 2, 90);
|
||||
}
|
||||
if (typeofask == 4)
|
||||
{
|
||||
MN_DrTextA(SlotText[quickload - 1], 160 -
|
||||
MN_TextAWidth(SlotText[quickload - 1]) / 2, 90);
|
||||
MN_DrTextA("?", 160 +
|
||||
MN_DrTextA(DEH_String("?"), 160 +
|
||||
MN_TextAWidth(SlotText[quickload - 1]) / 2, 90);
|
||||
}
|
||||
UpdateState |= I_FULLSCRN;
|
||||
|
|
@ -525,13 +529,13 @@ void MN_Drawer(void)
|
|||
{
|
||||
if (item->type != ITT_EMPTY && item->text)
|
||||
{
|
||||
MN_DrTextB(item->text, x, y);
|
||||
MN_DrTextB(DEH_String(item->text), x, y);
|
||||
}
|
||||
y += ITEM_HEIGHT;
|
||||
item++;
|
||||
}
|
||||
y = CurrentMenu->y + (CurrentItPos * ITEM_HEIGHT) + SELECTOR_YOFFSET;
|
||||
selName = MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2";
|
||||
selName = DEH_String(MenuTime & 16 ? "M_SLCTR1" : "M_SLCTR2");
|
||||
V_DrawPatch(x + SELECTOR_XOFFSET, y,
|
||||
W_CacheLumpName(selName, PU_CACHE));
|
||||
}
|
||||
|
|
@ -548,7 +552,7 @@ static void DrawMainMenu(void)
|
|||
int frame;
|
||||
|
||||
frame = (MenuTime / 3) % 18;
|
||||
V_DrawPatch(88, 0, W_CacheLumpName("M_HTIC", PU_CACHE));
|
||||
V_DrawPatch(88, 0, W_CacheLumpName(DEH_String("M_HTIC"), PU_CACHE));
|
||||
V_DrawPatch(40, 10, W_CacheLumpNum(SkullBaseLump + (17 - frame),
|
||||
PU_CACHE));
|
||||
V_DrawPatch(232, 10, W_CacheLumpNum(SkullBaseLump + frame, PU_CACHE));
|
||||
|
|
@ -597,7 +601,11 @@ static void DrawFilesMenu(void)
|
|||
|
||||
static void DrawLoadMenu(void)
|
||||
{
|
||||
MN_DrTextB("LOAD GAME", 160 - MN_TextBWidth("LOAD GAME") / 2, 10);
|
||||
char *title;
|
||||
|
||||
title = DEH_String("LOAD GAME");
|
||||
|
||||
MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10);
|
||||
if (!slottextloaded)
|
||||
{
|
||||
MN_LoadSlotText();
|
||||
|
|
@ -613,7 +621,11 @@ static void DrawLoadMenu(void)
|
|||
|
||||
static void DrawSaveMenu(void)
|
||||
{
|
||||
MN_DrTextB("SAVE GAME", 160 - MN_TextBWidth("SAVE GAME") / 2, 10);
|
||||
char *title;
|
||||
|
||||
title = DEH_String("SAVE GAME");
|
||||
|
||||
MN_DrTextB(title, 160 - MN_TextBWidth(title) / 2, 10);
|
||||
if (!slottextloaded)
|
||||
{
|
||||
MN_LoadSlotText();
|
||||
|
|
@ -675,7 +687,7 @@ static void DrawFileSlots(Menu_t * menu)
|
|||
y = menu->y;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
V_DrawPatch(x, y, W_CacheLumpName("M_FSLOT", PU_CACHE));
|
||||
V_DrawPatch(x, y, W_CacheLumpName(DEH_String("M_FSLOT"), PU_CACHE));
|
||||
if (SlotStatus[i])
|
||||
{
|
||||
MN_DrTextA(SlotText[i], x + 5, y + 5);
|
||||
|
|
@ -694,11 +706,11 @@ static void DrawOptionsMenu(void)
|
|||
{
|
||||
if (messageson)
|
||||
{
|
||||
MN_DrTextB("ON", 196, 50);
|
||||
MN_DrTextB(DEH_String("ON"), 196, 50);
|
||||
}
|
||||
else
|
||||
{
|
||||
MN_DrTextB("OFF", 196, 50);
|
||||
MN_DrTextB(DEH_String("OFF"), 196, 50);
|
||||
}
|
||||
DrawSlider(&OptionsMenu, 3, 10, mouseSensitivity);
|
||||
}
|
||||
|
|
@ -796,11 +808,11 @@ static boolean SCMessages(int option)
|
|||
messageson ^= 1;
|
||||
if (messageson)
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer], "MESSAGES ON", true);
|
||||
P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES ON"), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(&players[consoleplayer], "MESSAGES OFF", true);
|
||||
P_SetMessage(&players[consoleplayer], DEH_String("MESSAGES OFF"), true);
|
||||
}
|
||||
S_StartSound(NULL, sfx_chat);
|
||||
return true;
|
||||
|
|
@ -1460,7 +1472,7 @@ boolean MN_Responder(event_t * event)
|
|||
if (CurrentMenu->items[i].text)
|
||||
{
|
||||
if (toupper(charTyped)
|
||||
== toupper(CurrentMenu->items[i].text[0]))
|
||||
== toupper(DEH_String(CurrentMenu->items[i].text)[0]))
|
||||
{
|
||||
CurrentItPos = i;
|
||||
return (true);
|
||||
|
|
@ -1628,13 +1640,13 @@ static void DrawSlider(Menu_t * menu, int item, int width, int slot)
|
|||
|
||||
x = menu->x + 24;
|
||||
y = menu->y + 2 + (item * ITEM_HEIGHT);
|
||||
V_DrawPatch(x - 32, y, W_CacheLumpName("M_SLDLT", PU_CACHE));
|
||||
V_DrawPatch(x - 32, y, W_CacheLumpName(DEH_String("M_SLDLT"), PU_CACHE));
|
||||
for (x2 = x, count = width; count--; x2 += 8)
|
||||
{
|
||||
V_DrawPatch(x2, y, W_CacheLumpName(count & 1 ? "M_SLDMD1"
|
||||
: "M_SLDMD2", PU_CACHE));
|
||||
V_DrawPatch(x2, y, W_CacheLumpName(DEH_String(count & 1 ? "M_SLDMD1"
|
||||
: "M_SLDMD2"), PU_CACHE));
|
||||
}
|
||||
V_DrawPatch(x2, y, W_CacheLumpName("M_SLDRT", PU_CACHE));
|
||||
V_DrawPatch(x2, y, W_CacheLumpName(DEH_String("M_SLDRT"), PU_CACHE));
|
||||
V_DrawPatch(x + 4 + slot * 8, y + 7,
|
||||
W_CacheLumpName("M_SLDKB", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("M_SLDKB"), PU_CACHE));
|
||||
}
|
||||
|
|
|
|||
160
src/heretic/p_action.h
Normal file
160
src/heretic/p_action.h
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 1993-2008 Raven Software
|
||||
// Copyright(C) 2008 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.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
// 02111-1307, USA.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// External definitions for action pointer functions.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef HERETIC_P_ACTION_H
|
||||
#define HERETIC_P_ACTION_H
|
||||
|
||||
void A_FreeTargMobj();
|
||||
void A_RestoreSpecialThing1();
|
||||
void A_RestoreSpecialThing2();
|
||||
void A_HideThing();
|
||||
void A_UnHideThing();
|
||||
void A_RestoreArtifact();
|
||||
void A_Scream();
|
||||
void A_Explode();
|
||||
void A_PodPain();
|
||||
void A_RemovePod();
|
||||
void A_MakePod();
|
||||
void A_InitKeyGizmo();
|
||||
void A_VolcanoSet();
|
||||
void A_VolcanoBlast();
|
||||
void A_BeastPuff();
|
||||
void A_VolcBallImpact();
|
||||
void A_SpawnTeleGlitter();
|
||||
void A_SpawnTeleGlitter2();
|
||||
void A_AccTeleGlitter();
|
||||
void A_Light0();
|
||||
void A_WeaponReady();
|
||||
void A_Lower();
|
||||
void A_Raise();
|
||||
void A_StaffAttackPL1();
|
||||
void A_ReFire();
|
||||
void A_StaffAttackPL2();
|
||||
void A_BeakReady();
|
||||
void A_BeakRaise();
|
||||
void A_BeakAttackPL1();
|
||||
void A_BeakAttackPL2();
|
||||
void A_GauntletAttack();
|
||||
void A_FireBlasterPL1();
|
||||
void A_FireBlasterPL2();
|
||||
void A_SpawnRippers();
|
||||
void A_FireMacePL1();
|
||||
void A_FireMacePL2();
|
||||
void A_MacePL1Check();
|
||||
void A_MaceBallImpact();
|
||||
void A_MaceBallImpact2();
|
||||
void A_DeathBallImpact();
|
||||
void A_FireSkullRodPL1();
|
||||
void A_FireSkullRodPL2();
|
||||
void A_SkullRodPL2Seek();
|
||||
void A_AddPlayerRain();
|
||||
void A_HideInCeiling();
|
||||
void A_SkullRodStorm();
|
||||
void A_RainImpact();
|
||||
void A_FireGoldWandPL1();
|
||||
void A_FireGoldWandPL2();
|
||||
void A_FirePhoenixPL1();
|
||||
void A_InitPhoenixPL2();
|
||||
void A_FirePhoenixPL2();
|
||||
void A_ShutdownPhoenixPL2();
|
||||
void A_PhoenixPuff();
|
||||
void A_RemovedPhoenixFunc();
|
||||
void A_FlameEnd();
|
||||
void A_FloatPuff();
|
||||
void A_FireCrossbowPL1();
|
||||
void A_FireCrossbowPL2();
|
||||
void A_BoltSpark();
|
||||
void A_Pain();
|
||||
void A_NoBlocking();
|
||||
void A_AddPlayerCorpse();
|
||||
void A_SkullPop();
|
||||
void A_FlameSnd();
|
||||
void A_CheckBurnGone();
|
||||
void A_CheckSkullFloor();
|
||||
void A_CheckSkullDone();
|
||||
void A_Feathers();
|
||||
void A_ChicLook();
|
||||
void A_ChicChase();
|
||||
void A_ChicPain();
|
||||
void A_FaceTarget();
|
||||
void A_ChicAttack();
|
||||
void A_Look();
|
||||
void A_Chase();
|
||||
void A_MummyAttack();
|
||||
void A_MummyAttack2();
|
||||
void A_MummySoul();
|
||||
void A_ContMobjSound();
|
||||
void A_MummyFX1Seek();
|
||||
void A_BeastAttack();
|
||||
void A_SnakeAttack();
|
||||
void A_SnakeAttack2();
|
||||
void A_HeadAttack();
|
||||
void A_BossDeath();
|
||||
void A_HeadIceImpact();
|
||||
void A_HeadFireGrow();
|
||||
void A_WhirlwindSeek();
|
||||
void A_ClinkAttack();
|
||||
void A_WizAtk1();
|
||||
void A_WizAtk2();
|
||||
void A_WizAtk3();
|
||||
void A_GhostOff();
|
||||
void A_ImpMeAttack();
|
||||
void A_ImpMsAttack();
|
||||
void A_ImpMsAttack2();
|
||||
void A_ImpDeath();
|
||||
void A_ImpXDeath1();
|
||||
void A_ImpXDeath2();
|
||||
void A_ImpExplode();
|
||||
void A_KnightAttack();
|
||||
void A_DripBlood();
|
||||
void A_Sor1Chase();
|
||||
void A_Sor1Pain();
|
||||
void A_Srcr1Attack();
|
||||
void A_SorZap();
|
||||
void A_SorcererRise();
|
||||
void A_SorRise();
|
||||
void A_SorSightSnd();
|
||||
void A_Srcr2Decide();
|
||||
void A_Srcr2Attack();
|
||||
void A_Sor2DthInit();
|
||||
void A_SorDSph();
|
||||
void A_Sor2DthLoop();
|
||||
void A_SorDExp();
|
||||
void A_SorDBon();
|
||||
void A_BlueSpark();
|
||||
void A_GenWizard();
|
||||
void A_MinotaurAtk1();
|
||||
void A_MinotaurDecide();
|
||||
void A_MinotaurAtk2();
|
||||
void A_MinotaurAtk3();
|
||||
void A_MinotaurCharge();
|
||||
void A_MntrFloorFire();
|
||||
void A_ESound();
|
||||
|
||||
#endif /* #ifndef HERETIC_P_ACTION_H */
|
||||
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
// P_doors.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "v_video.h"
|
||||
|
|
@ -232,7 +233,7 @@ void EV_VerticalDoor(line_t * line, mobj_t * thing)
|
|||
}
|
||||
if (!player->keys[key_blue])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDBLUEKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_NEEDBLUEKEY), false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
|
|
@ -245,7 +246,7 @@ void EV_VerticalDoor(line_t * line, mobj_t * thing)
|
|||
}
|
||||
if (!player->keys[key_yellow])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDYELLOWKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_NEEDYELLOWKEY), false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
|
|
@ -258,7 +259,7 @@ void EV_VerticalDoor(line_t * line, mobj_t * thing)
|
|||
}
|
||||
if (!player->keys[key_green])
|
||||
{
|
||||
P_SetMessage(player, TXT_NEEDGREENKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_NEEDGREENKEY), false);
|
||||
S_StartSound(NULL, sfx_plroof);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
// P_inter.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_system.h"
|
||||
#include "i_timer.h"
|
||||
#include "m_random.h"
|
||||
|
|
@ -54,7 +55,7 @@ int maxammo[NUMAMMO] = {
|
|||
150 // mace
|
||||
};
|
||||
|
||||
static int GetWeaponAmmo[NUMWEAPONS] = {
|
||||
int GetWeaponAmmo[NUMWEAPONS] = {
|
||||
0, // staff
|
||||
25, // gold wand
|
||||
10, // crossbow
|
||||
|
|
@ -580,21 +581,21 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_ITEMHEALTH, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ITEMHEALTH), false);
|
||||
break;
|
||||
case SPR_SHLD: // Item_Shield1
|
||||
if (!P_GiveArmor(player, 1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_ITEMSHIELD1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ITEMSHIELD1), false);
|
||||
break;
|
||||
case SPR_SHD2: // Item_Shield2
|
||||
if (!P_GiveArmor(player, 2))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_ITEMSHIELD2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ITEMSHIELD2), false);
|
||||
break;
|
||||
case SPR_BAGH: // Item_BagOfHolding
|
||||
if (!player->backpack)
|
||||
|
|
@ -610,21 +611,21 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
P_GiveAmmo(player, am_crossbow, AMMO_CBOW_WIMPY);
|
||||
P_GiveAmmo(player, am_skullrod, AMMO_SKRD_WIMPY);
|
||||
P_GiveAmmo(player, am_phoenixrod, AMMO_PHRD_WIMPY);
|
||||
P_SetMessage(player, TXT_ITEMBAGOFHOLDING, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ITEMBAGOFHOLDING), false);
|
||||
break;
|
||||
case SPR_SPMP: // Item_SuperMap
|
||||
if (!P_GivePower(player, pw_allmap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_ITEMSUPERMAP, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ITEMSUPERMAP), false);
|
||||
break;
|
||||
|
||||
// Keys
|
||||
case SPR_BKYY: // Key_Blue
|
||||
if (!player->keys[key_blue])
|
||||
{
|
||||
P_SetMessage(player, TXT_GOTBLUEKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_GOTBLUEKEY), false);
|
||||
}
|
||||
P_GiveKey(player, key_blue);
|
||||
sound = sfx_keyup;
|
||||
|
|
@ -636,7 +637,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
case SPR_CKYY: // Key_Yellow
|
||||
if (!player->keys[key_yellow])
|
||||
{
|
||||
P_SetMessage(player, TXT_GOTYELLOWKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_GOTYELLOWKEY), false);
|
||||
}
|
||||
sound = sfx_keyup;
|
||||
P_GiveKey(player, key_yellow);
|
||||
|
|
@ -648,7 +649,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
case SPR_AKYY: // Key_Green
|
||||
if (!player->keys[key_green])
|
||||
{
|
||||
P_SetMessage(player, TXT_GOTGREENKEY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_GOTGREENKEY), false);
|
||||
}
|
||||
sound = sfx_keyup;
|
||||
P_GiveKey(player, key_green);
|
||||
|
|
@ -662,70 +663,70 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
case SPR_PTN2: // Arti_HealingPotion
|
||||
if (P_GiveArtifact(player, arti_health, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIHEALTH, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIHEALTH), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_SOAR: // Arti_Fly
|
||||
if (P_GiveArtifact(player, arti_fly, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIFLY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIFLY), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_INVU: // Arti_Invulnerability
|
||||
if (P_GiveArtifact(player, arti_invulnerability, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIINVULNERABILITY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIINVULNERABILITY), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_PWBK: // Arti_TomeOfPower
|
||||
if (P_GiveArtifact(player, arti_tomeofpower, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTITOMEOFPOWER, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTITOMEOFPOWER), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_INVS: // Arti_Invisibility
|
||||
if (P_GiveArtifact(player, arti_invisibility, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIINVISIBILITY, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIINVISIBILITY), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_EGGC: // Arti_Egg
|
||||
if (P_GiveArtifact(player, arti_egg, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIEGG, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIEGG), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_SPHL: // Arti_SuperHealth
|
||||
if (P_GiveArtifact(player, arti_superhealth, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTISUPERHEALTH, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTISUPERHEALTH), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_TRCH: // Arti_Torch
|
||||
if (P_GiveArtifact(player, arti_torch, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTITORCH, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTITORCH), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_FBMB: // Arti_FireBomb
|
||||
if (P_GiveArtifact(player, arti_firebomb, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTIFIREBOMB, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTIFIREBOMB), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
case SPR_ATLP: // Arti_Teleport
|
||||
if (P_GiveArtifact(player, arti_teleport, special))
|
||||
{
|
||||
P_SetMessage(player, TXT_ARTITELEPORT, false);
|
||||
P_SetMessage(player, DEH_String(TXT_ARTITELEPORT), false);
|
||||
P_SetDormantArtifact(special);
|
||||
}
|
||||
return;
|
||||
|
|
@ -736,84 +737,84 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOGOLDWAND1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND1), false);
|
||||
break;
|
||||
case SPR_AMG2: // Ammo_GoldWandHefty
|
||||
if (!P_GiveAmmo(player, am_goldwand, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOGOLDWAND2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOGOLDWAND2), false);
|
||||
break;
|
||||
case SPR_AMM1: // Ammo_MaceWimpy
|
||||
if (!P_GiveAmmo(player, am_mace, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOMACE1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOMACE1), false);
|
||||
break;
|
||||
case SPR_AMM2: // Ammo_MaceHefty
|
||||
if (!P_GiveAmmo(player, am_mace, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOMACE2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOMACE2), false);
|
||||
break;
|
||||
case SPR_AMC1: // Ammo_CrossbowWimpy
|
||||
if (!P_GiveAmmo(player, am_crossbow, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOCROSSBOW1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW1), false);
|
||||
break;
|
||||
case SPR_AMC2: // Ammo_CrossbowHefty
|
||||
if (!P_GiveAmmo(player, am_crossbow, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOCROSSBOW2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOCROSSBOW2), false);
|
||||
break;
|
||||
case SPR_AMB1: // Ammo_BlasterWimpy
|
||||
if (!P_GiveAmmo(player, am_blaster, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOBLASTER1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOBLASTER1), false);
|
||||
break;
|
||||
case SPR_AMB2: // Ammo_BlasterHefty
|
||||
if (!P_GiveAmmo(player, am_blaster, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOBLASTER2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOBLASTER2), false);
|
||||
break;
|
||||
case SPR_AMS1: // Ammo_SkullRodWimpy
|
||||
if (!P_GiveAmmo(player, am_skullrod, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOSKULLROD1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD1), false);
|
||||
break;
|
||||
case SPR_AMS2: // Ammo_SkullRodHefty
|
||||
if (!P_GiveAmmo(player, am_skullrod, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOSKULLROD2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOSKULLROD2), false);
|
||||
break;
|
||||
case SPR_AMP1: // Ammo_PhoenixRodWimpy
|
||||
if (!P_GiveAmmo(player, am_phoenixrod, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOPHOENIXROD1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD1), false);
|
||||
break;
|
||||
case SPR_AMP2: // Ammo_PhoenixRodHefty
|
||||
if (!P_GiveAmmo(player, am_phoenixrod, special->health))
|
||||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_AMMOPHOENIXROD2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_AMMOPHOENIXROD2), false);
|
||||
break;
|
||||
|
||||
// Weapons
|
||||
|
|
@ -822,7 +823,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNMACE, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNMACE), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
case SPR_WBOW: // Weapon_Crossbow
|
||||
|
|
@ -830,7 +831,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNCROSSBOW, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNCROSSBOW), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
case SPR_WBLS: // Weapon_Blaster
|
||||
|
|
@ -838,7 +839,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNBLASTER, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNBLASTER), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
case SPR_WSKL: // Weapon_SkullRod
|
||||
|
|
@ -846,7 +847,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNSKULLROD, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNSKULLROD), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
case SPR_WPHX: // Weapon_PhoenixRod
|
||||
|
|
@ -854,7 +855,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNPHOENIXROD, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNPHOENIXROD), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
case SPR_WGNT: // Weapon_Gauntlets
|
||||
|
|
@ -862,7 +863,7 @@ void P_TouchSpecialThing(mobj_t * special, mobj_t * toucher)
|
|||
{
|
||||
return;
|
||||
}
|
||||
P_SetMessage(player, TXT_WPNGAUNTLETS, false);
|
||||
P_SetMessage(player, DEH_String(TXT_WPNGAUNTLETS), false);
|
||||
sound = sfx_wpnup;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1650,6 +1650,17 @@ void A_PhoenixPuff(mobj_t * actor)
|
|||
puff->momz = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// This function was present in the Heretic 1.0 executable for the
|
||||
// removed "secondary phoenix flash" object (MT_PHOENIXFX_REMOVED).
|
||||
// The purpose of this object is unknown, as is this function.
|
||||
//
|
||||
|
||||
void A_RemovedPhoenixFunc(mobj_t *actor)
|
||||
{
|
||||
I_Error("Action function invoked for removed Phoenix action!");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_InitPhoenixPL2
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
// P_Spec.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_system.h"
|
||||
#include "i_timer.h"
|
||||
#include "m_random.h"
|
||||
|
|
@ -204,18 +205,12 @@ struct
|
|||
int type;
|
||||
} TerrainTypeDefs[] =
|
||||
{
|
||||
{
|
||||
"FLTWAWA1", FLOOR_WATER},
|
||||
{
|
||||
"FLTFLWW1", FLOOR_WATER},
|
||||
{
|
||||
"FLTLAVA1", FLOOR_LAVA},
|
||||
{
|
||||
"FLATHUH1", FLOOR_LAVA},
|
||||
{
|
||||
"FLTSLUD1", FLOOR_SLUDGE},
|
||||
{
|
||||
"END", -1}
|
||||
{ "FLTWAWA1", FLOOR_WATER },
|
||||
{ "FLTFLWW1", FLOOR_WATER },
|
||||
{ "FLTLAVA1", FLOOR_LAVA },
|
||||
{ "FLATHUH1", FLOOR_LAVA },
|
||||
{ "FLTSLUD1", FLOOR_SLUDGE },
|
||||
{ "END", -1 }
|
||||
};
|
||||
|
||||
mobj_t LavaInflictor;
|
||||
|
|
@ -266,35 +261,40 @@ void P_InitTerrainTypes(void)
|
|||
|
||||
void P_InitPicAnims(void)
|
||||
{
|
||||
char *startname;
|
||||
char *endname;
|
||||
int i;
|
||||
|
||||
lastanim = anims;
|
||||
for (i = 0; animdefs[i].istexture != -1; i++)
|
||||
{
|
||||
startname = DEH_String(animdefs[i].startname);
|
||||
endname = DEH_String(animdefs[i].endname);
|
||||
|
||||
if (animdefs[i].istexture)
|
||||
{ // Texture animation
|
||||
if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
|
||||
if (R_CheckTextureNumForName(startname) == -1)
|
||||
{ // Texture doesn't exist
|
||||
continue;
|
||||
}
|
||||
lastanim->picnum = R_TextureNumForName(animdefs[i].endname);
|
||||
lastanim->basepic = R_TextureNumForName(animdefs[i].startname);
|
||||
lastanim->picnum = R_TextureNumForName(endname);
|
||||
lastanim->basepic = R_TextureNumForName(startname);
|
||||
}
|
||||
else
|
||||
{ // Flat animation
|
||||
if (W_CheckNumForName(animdefs[i].startname) == -1)
|
||||
if (W_CheckNumForName(startname) == -1)
|
||||
{ // Flat doesn't exist
|
||||
continue;
|
||||
}
|
||||
lastanim->picnum = R_FlatNumForName(animdefs[i].endname);
|
||||
lastanim->basepic = R_FlatNumForName(animdefs[i].startname);
|
||||
lastanim->picnum = R_FlatNumForName(endname);
|
||||
lastanim->basepic = R_FlatNumForName(startname);
|
||||
}
|
||||
lastanim->istexture = animdefs[i].istexture;
|
||||
lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
|
||||
if (lastanim->numpics < 2)
|
||||
{
|
||||
I_Error("P_InitPicAnims: bad cycle from %s to %s",
|
||||
animdefs[i].startname, animdefs[i].endname);
|
||||
startname, endname);
|
||||
}
|
||||
lastanim->speed = animdefs[i].speed;
|
||||
lastanim++;
|
||||
|
|
@ -1132,7 +1132,7 @@ void P_SpawnSpecials(void)
|
|||
int episode;
|
||||
|
||||
episode = 1;
|
||||
if (W_CheckNumForName("texture2") >= 0)
|
||||
if (W_CheckNumForName(DEH_String("texture2")) >= 0)
|
||||
episode = 2;
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_system.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
|
|
@ -129,9 +130,9 @@ void P_InitSwitchList(void)
|
|||
if (alphSwitchList[i].episode <= episode)
|
||||
{
|
||||
switchlist[index++] =
|
||||
R_TextureNumForName(alphSwitchList[i].name1);
|
||||
R_TextureNumForName(DEH_String(alphSwitchList[i].name1));
|
||||
switchlist[index++] =
|
||||
R_TextureNumForName(alphSwitchList[i].name2);
|
||||
R_TextureNumForName(DEH_String(alphSwitchList[i].name2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
|
|
@ -394,7 +395,7 @@ void P_DeathThink(player_t * player)
|
|||
{
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
I_SetPalette((byte *) W_CacheLumpName("PLAYPAL", PU_CACHE));
|
||||
I_SetPalette(W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE));
|
||||
inv_ptr = 0;
|
||||
curpos = 0;
|
||||
newtorch = 0;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
// R_data.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
|
||||
#include "i_swap.h"
|
||||
#include "i_system.h"
|
||||
#include "r_local.h"
|
||||
|
|
@ -316,12 +318,17 @@ void R_InitTextures(void)
|
|||
int offset, maxoff, maxoff2;
|
||||
int numtextures1, numtextures2;
|
||||
int *directory;
|
||||
char *texture1, *texture2, *pnames;
|
||||
|
||||
texture1 = DEH_String("TEXTURE1");
|
||||
texture2 = DEH_String("TEXTURE2");
|
||||
pnames = DEH_String("PNAMES");
|
||||
|
||||
//
|
||||
// load the patch names from pnames.lmp
|
||||
//
|
||||
name[8] = 0;
|
||||
names = W_CacheLumpName("PNAMES", PU_STATIC);
|
||||
names = W_CacheLumpName(pnames, PU_STATIC);
|
||||
nummappatches = LONG(*((int *) names));
|
||||
name_p = names + 4;
|
||||
patchlookup = Z_Malloc(nummappatches * sizeof(*patchlookup), PU_STATIC, NULL);
|
||||
|
|
@ -330,21 +337,21 @@ void R_InitTextures(void)
|
|||
strncpy(name, name_p + i * 8, 8);
|
||||
patchlookup[i] = W_CheckNumForName(name);
|
||||
}
|
||||
W_ReleaseLumpName("PNAMES");
|
||||
W_ReleaseLumpName(pnames);
|
||||
|
||||
//
|
||||
// load the map texture definitions from textures.lmp
|
||||
//
|
||||
maptex = maptex1 = W_CacheLumpName("TEXTURE1", PU_STATIC);
|
||||
maptex = maptex1 = W_CacheLumpName(texture1, PU_STATIC);
|
||||
numtextures1 = LONG(*maptex);
|
||||
maxoff = W_LumpLength(W_GetNumForName("TEXTURE1"));
|
||||
maxoff = W_LumpLength(W_GetNumForName(texture1));
|
||||
directory = maptex + 1;
|
||||
|
||||
if (W_CheckNumForName("TEXTURE2") != -1)
|
||||
if (W_CheckNumForName(texture2) != -1)
|
||||
{
|
||||
maptex2 = W_CacheLumpName("TEXTURE2", PU_STATIC);
|
||||
maptex2 = W_CacheLumpName(texture2, PU_STATIC);
|
||||
numtextures2 = LONG(*maptex2);
|
||||
maxoff2 = W_LumpLength(W_GetNumForName("TEXTURE2"));
|
||||
maxoff2 = W_LumpLength(W_GetNumForName(texture2));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -358,8 +365,11 @@ void R_InitTextures(void)
|
|||
// Init the startup thermometer at this point...
|
||||
//
|
||||
{
|
||||
int start, end;
|
||||
int spramount;
|
||||
spramount = W_GetNumForName("S_END") - W_GetNumForName("S_START") + 1;
|
||||
start = W_GetNumForName(DEH_String("S_START"));
|
||||
end = W_GetNumForName(DEH_String("S_END"));
|
||||
spramount = end - start + 1;
|
||||
InitThermo(spramount + numtextures + 6);
|
||||
}
|
||||
|
||||
|
|
@ -427,10 +437,10 @@ void R_InitTextures(void)
|
|||
|
||||
Z_Free(patchlookup);
|
||||
|
||||
W_ReleaseLumpName("TEXTURE1");
|
||||
W_ReleaseLumpName(texture1);
|
||||
if (maptex2)
|
||||
{
|
||||
W_ReleaseLumpName("TEXTURE2");
|
||||
W_ReleaseLumpName(texture2);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -463,8 +473,8 @@ void R_InitFlats(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
firstflat = W_GetNumForName("F_START") + 1;
|
||||
lastflat = W_GetNumForName("F_END") - 1;
|
||||
firstflat = W_GetNumForName(DEH_String("F_START")) + 1;
|
||||
lastflat = W_GetNumForName(DEH_String("F_END")) - 1;
|
||||
numflats = lastflat - firstflat + 1;
|
||||
|
||||
// translation table for global animation
|
||||
|
|
@ -489,8 +499,8 @@ void R_InitSpriteLumps(void)
|
|||
int i;
|
||||
patch_t *patch;
|
||||
|
||||
firstspritelump = W_GetNumForName("S_START") + 1;
|
||||
lastspritelump = W_GetNumForName("S_END") - 1;
|
||||
firstspritelump = W_GetNumForName(DEH_String("S_START")) + 1;
|
||||
lastspritelump = W_GetNumForName(DEH_String("S_END")) - 1;
|
||||
numspritelumps = lastspritelump - firstspritelump + 1;
|
||||
spritewidth = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0);
|
||||
spriteoffset = Z_Malloc(numspritelumps * sizeof(fixed_t), PU_STATIC, 0);
|
||||
|
|
@ -527,7 +537,7 @@ void R_InitColormaps(void)
|
|||
// load in the light tables
|
||||
// 256 byte align tables
|
||||
//
|
||||
lump = W_GetNumForName("COLORMAP");
|
||||
lump = W_GetNumForName(DEH_String("COLORMAP"));
|
||||
length = W_LumpLength(lump);
|
||||
colormaps = Z_Malloc(length, PU_STATIC, 0);
|
||||
W_ReadLump(lump, colormaps);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
// R_draw.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "r_local.h"
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
|
|
@ -386,11 +387,11 @@ void R_DrawViewBorder(void)
|
|||
|
||||
if (gamemode == shareware)
|
||||
{
|
||||
src = W_CacheLumpName("FLOOR04", PU_CACHE);
|
||||
src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = W_CacheLumpName("FLAT513", PU_CACHE);
|
||||
src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE);
|
||||
}
|
||||
dest = I_VideoBuffer;
|
||||
|
||||
|
|
@ -409,24 +410,26 @@ void R_DrawViewBorder(void)
|
|||
}
|
||||
for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16)
|
||||
{
|
||||
V_DrawPatch(x, viewwindowy - 4, W_CacheLumpName("bordt", PU_CACHE));
|
||||
V_DrawPatch(x, viewwindowy + viewheight, W_CacheLumpName("bordb",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(x, viewwindowy - 4,
|
||||
W_CacheLumpName(DEH_String("bordt"), PU_CACHE));
|
||||
V_DrawPatch(x, viewwindowy + viewheight,
|
||||
W_CacheLumpName(DEH_String("bordb"), PU_CACHE));
|
||||
}
|
||||
for (y = viewwindowy; y < viewwindowy + viewheight; y += 16)
|
||||
{
|
||||
V_DrawPatch(viewwindowx - 4, y, W_CacheLumpName("bordl", PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, y, W_CacheLumpName("bordr",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx - 4, y,
|
||||
W_CacheLumpName(DEH_String("bordl"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, y,
|
||||
W_CacheLumpName(DEH_String("bordr"), PU_CACHE));
|
||||
}
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy - 4, W_CacheLumpName("bordtl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy - 4,
|
||||
W_CacheLumpName(DEH_String("bordtl"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4,
|
||||
W_CacheLumpName("bordtr", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordtr"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight,
|
||||
W_CacheLumpName("bordbr", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordbr"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy + viewheight,
|
||||
W_CacheLumpName("bordbl", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordbl"), PU_CACHE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -450,11 +453,11 @@ void R_DrawTopBorder(void)
|
|||
|
||||
if (gamemode == shareware)
|
||||
{
|
||||
src = W_CacheLumpName("FLOOR04", PU_CACHE);
|
||||
src = W_CacheLumpName(DEH_String("FLOOR04"), PU_CACHE);
|
||||
}
|
||||
else
|
||||
{
|
||||
src = W_CacheLumpName("FLAT513", PU_CACHE);
|
||||
src = W_CacheLumpName(DEH_String("FLAT513"), PU_CACHE);
|
||||
}
|
||||
dest = I_VideoBuffer;
|
||||
|
||||
|
|
@ -476,20 +479,20 @@ void R_DrawTopBorder(void)
|
|||
for (x = viewwindowx; x < viewwindowx + viewwidth; x += 16)
|
||||
{
|
||||
V_DrawPatch(x, viewwindowy - 4,
|
||||
W_CacheLumpName("bordt", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordt"), PU_CACHE));
|
||||
}
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy, W_CacheLumpName("bordl",
|
||||
PU_CACHE));
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy,
|
||||
W_CacheLumpName(DEH_String("bordl"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, viewwindowy,
|
||||
W_CacheLumpName("bordr", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordr"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy + 16,
|
||||
W_CacheLumpName("bordl", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordl"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, viewwindowy + 16,
|
||||
W_CacheLumpName("bordr", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordr"), PU_CACHE));
|
||||
|
||||
V_DrawPatch(viewwindowx - 4, viewwindowy - 4,
|
||||
W_CacheLumpName("bordtl", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordtl"), PU_CACHE));
|
||||
V_DrawPatch(viewwindowx + viewwidth, viewwindowy - 4,
|
||||
W_CacheLumpName("bordtr", PU_CACHE));
|
||||
W_CacheLumpName(DEH_String("bordtr"), PU_CACHE));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_system.h"
|
||||
#include "r_local.h"
|
||||
|
||||
|
|
@ -90,7 +91,7 @@ fixed_t cachedystep[SCREENHEIGHT];
|
|||
|
||||
void R_InitSkyMap(void)
|
||||
{
|
||||
skyflatnum = R_FlatNumForName("F_SKY1");
|
||||
skyflatnum = R_FlatNumForName(DEH_String("F_SKY1"));
|
||||
skytexturemid = 200 * FRACUNIT;
|
||||
skyiscale = FRACUNIT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_swap.h"
|
||||
#include "i_system.h"
|
||||
#include "r_local.h"
|
||||
|
|
@ -154,7 +155,7 @@ void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation,
|
|||
void R_InitSpriteDefs(char **namelist)
|
||||
{
|
||||
char **check;
|
||||
int i, l, intname, frame, rotation;
|
||||
int i, l, frame, rotation;
|
||||
int start, end;
|
||||
|
||||
// count the number of sprite names
|
||||
|
|
@ -176,17 +177,16 @@ void R_InitSpriteDefs(char **namelist)
|
|||
// Just compare 4 characters as ints
|
||||
for (i = 0; i < numsprites; i++)
|
||||
{
|
||||
spritename = namelist[i];
|
||||
spritename = DEH_String(namelist[i]);
|
||||
memset(sprtemp, -1, sizeof(sprtemp));
|
||||
|
||||
maxframe = -1;
|
||||
intname = *(int *) namelist[i];
|
||||
|
||||
//
|
||||
// scan the lumps, filling in the frames for whatever is found
|
||||
//
|
||||
for (l = start + 1; l < end; l++)
|
||||
if (*(int *) lumpinfo[l].name == intname)
|
||||
if (!strncasecmp(lumpinfo[l].name, spritename, 4))
|
||||
{
|
||||
frame = lumpinfo[l].name[4] - 'A';
|
||||
rotation = lumpinfo[l].name[5] - '0';
|
||||
|
|
@ -209,7 +209,7 @@ void R_InitSpriteDefs(char **namelist)
|
|||
if (gamemode == shareware)
|
||||
continue;
|
||||
I_Error("R_InitSprites: No lumps found for sprite %s",
|
||||
namelist[i]);
|
||||
spritename);
|
||||
}
|
||||
|
||||
maxframe++;
|
||||
|
|
@ -219,7 +219,7 @@ void R_InitSpriteDefs(char **namelist)
|
|||
{
|
||||
case -1: // no rotations were found for that frame at all
|
||||
I_Error("R_InitSprites: No patches found for %s frame %c",
|
||||
namelist[i], frame + 'A');
|
||||
spritename, frame + 'A');
|
||||
case 0: // only the first rotation is needed
|
||||
break;
|
||||
|
||||
|
|
@ -228,7 +228,7 @@ void R_InitSpriteDefs(char **namelist)
|
|||
if (sprtemp[frame].lump[rotation] == -1)
|
||||
I_Error
|
||||
("R_InitSprites: Sprite %s frame %c is missing rotations",
|
||||
namelist[i], frame + 'A');
|
||||
spritename, frame + 'A');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "r_local.h"
|
||||
#include "p_local.h"
|
||||
|
||||
#include "sounds.h"
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
|
|
@ -55,9 +57,6 @@ int mus_lumpnum;
|
|||
void *mus_sndptr;
|
||||
byte *soundCurve;
|
||||
|
||||
extern sfxinfo_t S_sfx[];
|
||||
extern musicinfo_t S_music[];
|
||||
|
||||
int snd_MaxVolume = 10;
|
||||
int snd_MusicVolume = 10;
|
||||
int snd_Channels = 16;
|
||||
|
|
@ -529,7 +528,7 @@ void S_Init(void)
|
|||
{
|
||||
snd_Channels = 8;
|
||||
}
|
||||
I_SetMusicVolume(snd_MusicVolume);
|
||||
I_SetMusicVolume(snd_MusicVolume * 8);
|
||||
S_SetMaxVolume(true);
|
||||
|
||||
I_AtExit(S_ShutDown, true);
|
||||
|
|
@ -550,8 +549,16 @@ void S_GetChannelInfo(SoundInfo_t * s)
|
|||
c->priority = channel[i].priority;
|
||||
c->name = S_sfx[c->id].name;
|
||||
c->mo = channel[i].mo;
|
||||
c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy)
|
||||
>> FRACBITS;
|
||||
|
||||
if (c->mo != NULL)
|
||||
{
|
||||
c->distance = P_AproxDistance(c->mo->x - viewx, c->mo->y - viewy)
|
||||
>> FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->distance = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -579,7 +586,7 @@ void S_SetMaxVolume(boolean fullprocess)
|
|||
static boolean musicPaused;
|
||||
void S_SetMusicVolume(void)
|
||||
{
|
||||
I_SetMusicVolume(snd_MusicVolume);
|
||||
I_SetMusicVolume(snd_MusicVolume * 8);
|
||||
if (snd_MusicVolume == 0)
|
||||
{
|
||||
I_PauseSong();
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
// SB_bar.c
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "deh_str.h"
|
||||
#include "i_video.h"
|
||||
#include "m_cheat.h"
|
||||
#include "m_misc.h"
|
||||
|
|
@ -196,53 +197,53 @@ void SB_Init(void)
|
|||
int i;
|
||||
int startLump;
|
||||
|
||||
PatchLTFACE = W_CacheLumpName("LTFACE", PU_STATIC);
|
||||
PatchRTFACE = W_CacheLumpName("RTFACE", PU_STATIC);
|
||||
PatchBARBACK = W_CacheLumpName("BARBACK", PU_STATIC);
|
||||
PatchINVBAR = W_CacheLumpName("INVBAR", PU_STATIC);
|
||||
PatchCHAIN = W_CacheLumpName("CHAIN", PU_STATIC);
|
||||
PatchLTFACE = W_CacheLumpName(DEH_String("LTFACE"), PU_STATIC);
|
||||
PatchRTFACE = W_CacheLumpName(DEH_String("RTFACE"), PU_STATIC);
|
||||
PatchBARBACK = W_CacheLumpName(DEH_String("BARBACK"), PU_STATIC);
|
||||
PatchINVBAR = W_CacheLumpName(DEH_String("INVBAR"), PU_STATIC);
|
||||
PatchCHAIN = W_CacheLumpName(DEH_String("CHAIN"), PU_STATIC);
|
||||
if (deathmatch)
|
||||
{
|
||||
PatchSTATBAR = W_CacheLumpName("STATBAR", PU_STATIC);
|
||||
PatchSTATBAR = W_CacheLumpName(DEH_String("STATBAR"), PU_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
PatchSTATBAR = W_CacheLumpName("LIFEBAR", PU_STATIC);
|
||||
PatchSTATBAR = W_CacheLumpName(DEH_String("LIFEBAR"), PU_STATIC);
|
||||
}
|
||||
if (!netgame)
|
||||
{ // single player game uses red life gem
|
||||
PatchLIFEGEM = W_CacheLumpName("LIFEGEM2", PU_STATIC);
|
||||
PatchLIFEGEM = W_CacheLumpName(DEH_String("LIFEGEM2"), PU_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName("LIFEGEM0")
|
||||
PatchLIFEGEM = W_CacheLumpNum(W_GetNumForName(DEH_String("LIFEGEM0"))
|
||||
+ consoleplayer, PU_STATIC);
|
||||
}
|
||||
PatchLTFCTOP = W_CacheLumpName("LTFCTOP", PU_STATIC);
|
||||
PatchRTFCTOP = W_CacheLumpName("RTFCTOP", PU_STATIC);
|
||||
PatchSELECTBOX = W_CacheLumpName("SELECTBOX", PU_STATIC);
|
||||
PatchINVLFGEM1 = W_CacheLumpName("INVGEML1", PU_STATIC);
|
||||
PatchINVLFGEM2 = W_CacheLumpName("INVGEML2", PU_STATIC);
|
||||
PatchINVRTGEM1 = W_CacheLumpName("INVGEMR1", PU_STATIC);
|
||||
PatchINVRTGEM2 = W_CacheLumpName("INVGEMR2", PU_STATIC);
|
||||
PatchBLACKSQ = W_CacheLumpName("BLACKSQ", PU_STATIC);
|
||||
PatchARMCLEAR = W_CacheLumpName("ARMCLEAR", PU_STATIC);
|
||||
PatchCHAINBACK = W_CacheLumpName("CHAINBACK", PU_STATIC);
|
||||
startLump = W_GetNumForName("IN0");
|
||||
PatchLTFCTOP = W_CacheLumpName(DEH_String("LTFCTOP"), PU_STATIC);
|
||||
PatchRTFCTOP = W_CacheLumpName(DEH_String("RTFCTOP"), PU_STATIC);
|
||||
PatchSELECTBOX = W_CacheLumpName(DEH_String("SELECTBOX"), PU_STATIC);
|
||||
PatchINVLFGEM1 = W_CacheLumpName(DEH_String("INVGEML1"), PU_STATIC);
|
||||
PatchINVLFGEM2 = W_CacheLumpName(DEH_String("INVGEML2"), PU_STATIC);
|
||||
PatchINVRTGEM1 = W_CacheLumpName(DEH_String("INVGEMR1"), PU_STATIC);
|
||||
PatchINVRTGEM2 = W_CacheLumpName(DEH_String("INVGEMR2"), PU_STATIC);
|
||||
PatchBLACKSQ = W_CacheLumpName(DEH_String("BLACKSQ"), PU_STATIC);
|
||||
PatchARMCLEAR = W_CacheLumpName(DEH_String("ARMCLEAR"), PU_STATIC);
|
||||
PatchCHAINBACK = W_CacheLumpName(DEH_String("CHAINBACK"), PU_STATIC);
|
||||
startLump = W_GetNumForName(DEH_String("IN0"));
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
PatchINumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC);
|
||||
}
|
||||
PatchNEGATIVE = W_CacheLumpName("NEGNUM", PU_STATIC);
|
||||
FontBNumBase = W_GetNumForName("FONTB16");
|
||||
startLump = W_GetNumForName("SMALLIN0");
|
||||
PatchNEGATIVE = W_CacheLumpName(DEH_String("NEGNUM"), PU_STATIC);
|
||||
FontBNumBase = W_GetNumForName(DEH_String("FONTB16"));
|
||||
startLump = W_GetNumForName(DEH_String("SMALLIN0"));
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
PatchSmNumbers[i] = W_CacheLumpNum(startLump + i, PU_STATIC);
|
||||
}
|
||||
playpalette = W_GetNumForName("PLAYPAL");
|
||||
spinbooklump = W_GetNumForName("SPINBK0");
|
||||
spinflylump = W_GetNumForName("SPFLY0");
|
||||
playpalette = W_GetNumForName(DEH_String("PLAYPAL"));
|
||||
spinbooklump = W_GetNumForName(DEH_String("SPINBK0"));
|
||||
spinflylump = W_GetNumForName(DEH_String("SPFLY0"));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -311,7 +312,7 @@ static void DrINumber(signed int val, int x, int y)
|
|||
{
|
||||
if (val < -9)
|
||||
{
|
||||
V_DrawPatch(x + 1, y + 1, W_CacheLumpName("LAME", PU_CACHE));
|
||||
V_DrawPatch(x + 1, y + 1, W_CacheLumpName(DEH_String("LAME"), PU_CACHE));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -458,7 +459,7 @@ static void DrawSoundInfo(void)
|
|||
|
||||
if (leveltime & 16)
|
||||
{
|
||||
MN_DrTextA("*** SOUND DEBUG INFO ***", xPos[0], 20);
|
||||
MN_DrTextA(DEH_String("*** SOUND DEBUG INFO ***"), xPos[0], 20);
|
||||
}
|
||||
S_GetChannelInfo(&s);
|
||||
if (s.channelCount == 0)
|
||||
|
|
@ -466,13 +467,13 @@ static void DrawSoundInfo(void)
|
|||
return;
|
||||
}
|
||||
x = 0;
|
||||
MN_DrTextA("NAME", xPos[x++], 30);
|
||||
MN_DrTextA("MO.T", xPos[x++], 30);
|
||||
MN_DrTextA("MO.X", xPos[x++], 30);
|
||||
MN_DrTextA("MO.Y", xPos[x++], 30);
|
||||
MN_DrTextA("ID", xPos[x++], 30);
|
||||
MN_DrTextA("PRI", xPos[x++], 30);
|
||||
MN_DrTextA("DIST", xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("NAME"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("MO.T"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("MO.X"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("MO.Y"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("ID"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("PRI"), xPos[x++], 30);
|
||||
MN_DrTextA(DEH_String("DIST"), xPos[x++], 30);
|
||||
for (i = 0; i < s.channelCount; i++)
|
||||
{
|
||||
c = &s.chan[i];
|
||||
|
|
@ -480,7 +481,7 @@ static void DrawSoundInfo(void)
|
|||
y = 40 + i * 10;
|
||||
if (c->mo == NULL)
|
||||
{ // Channel is unused
|
||||
MN_DrTextA("------", xPos[0], y);
|
||||
MN_DrTextA(DEH_String("------"), xPos[0], y);
|
||||
continue;
|
||||
}
|
||||
sprintf(text, "%s", c->name);
|
||||
|
|
@ -570,8 +571,10 @@ void SB_Drawer(void)
|
|||
V_DrawPatch(0, 158, PatchBARBACK);
|
||||
if (players[consoleplayer].cheats & CF_GODMODE)
|
||||
{
|
||||
V_DrawPatch(16, 167, W_CacheLumpName("GOD1", PU_CACHE));
|
||||
V_DrawPatch(287, 167, W_CacheLumpName("GOD2", PU_CACHE));
|
||||
V_DrawPatch(16, 167,
|
||||
W_CacheLumpName(DEH_String("GOD1"), PU_CACHE));
|
||||
V_DrawPatch(287, 167,
|
||||
W_CacheLumpName(DEH_String("GOD2"), PU_CACHE));
|
||||
}
|
||||
oldhealth = -1;
|
||||
}
|
||||
|
|
@ -776,8 +779,10 @@ void DrawMainBar(void)
|
|||
if (ArtifactFlash)
|
||||
{
|
||||
V_DrawPatch(180, 161, PatchBLACKSQ);
|
||||
V_DrawPatch(182, 161, W_CacheLumpNum(W_GetNumForName("useartia")
|
||||
+ ArtifactFlash - 1, PU_CACHE));
|
||||
|
||||
temp = W_GetNumForName(DEH_String("useartia")) + ArtifactFlash - 1;
|
||||
|
||||
V_DrawPatch(182, 161, W_CacheLumpNum(temp, PU_CACHE));
|
||||
ArtifactFlash--;
|
||||
oldarti = -1; // so that the correct artifact fills in after the flash
|
||||
UpdateState |= I_STATBAR;
|
||||
|
|
@ -789,7 +794,7 @@ void DrawMainBar(void)
|
|||
if (CPlayer->readyArtifact > 0)
|
||||
{
|
||||
V_DrawPatch(179, 160,
|
||||
W_CacheLumpName(patcharti[CPlayer->readyArtifact],
|
||||
W_CacheLumpName(DEH_String(patcharti[CPlayer->readyArtifact]),
|
||||
PU_CACHE));
|
||||
DrSmallNumber(CPlayer->inventory[inv_ptr].count, 201, 182);
|
||||
}
|
||||
|
|
@ -839,15 +844,15 @@ void DrawMainBar(void)
|
|||
{
|
||||
if (CPlayer->keys[key_yellow])
|
||||
{
|
||||
V_DrawPatch(153, 164, W_CacheLumpName("ykeyicon", PU_CACHE));
|
||||
V_DrawPatch(153, 164, W_CacheLumpName(DEH_String("ykeyicon"), PU_CACHE));
|
||||
}
|
||||
if (CPlayer->keys[key_green])
|
||||
{
|
||||
V_DrawPatch(153, 172, W_CacheLumpName("gkeyicon", PU_CACHE));
|
||||
V_DrawPatch(153, 172, W_CacheLumpName(DEH_String("gkeyicon"), PU_CACHE));
|
||||
}
|
||||
if (CPlayer->keys[key_blue])
|
||||
{
|
||||
V_DrawPatch(153, 180, W_CacheLumpName("bkeyicon", PU_CACHE));
|
||||
V_DrawPatch(153, 180, W_CacheLumpName(DEH_String("bkeyicon"), PU_CACHE));
|
||||
}
|
||||
oldkeys = playerkeys;
|
||||
UpdateState |= I_STATBAR;
|
||||
|
|
@ -861,7 +866,7 @@ void DrawMainBar(void)
|
|||
{
|
||||
DrINumber(temp, 109, 162);
|
||||
V_DrawPatch(111, 172,
|
||||
W_CacheLumpName(ammopic[CPlayer->readyweapon - 1],
|
||||
W_CacheLumpName(DEH_String(ammopic[CPlayer->readyweapon - 1]),
|
||||
PU_CACHE));
|
||||
}
|
||||
oldammo = temp;
|
||||
|
|
@ -887,6 +892,7 @@ void DrawMainBar(void)
|
|||
|
||||
void DrawInventoryBar(void)
|
||||
{
|
||||
char *patch;
|
||||
int i;
|
||||
int x;
|
||||
|
||||
|
|
@ -899,10 +905,9 @@ void DrawInventoryBar(void)
|
|||
if (CPlayer->inventorySlotNum > x + i
|
||||
&& CPlayer->inventory[x + i].type != arti_none)
|
||||
{
|
||||
V_DrawPatch(50 + i * 31, 160,
|
||||
W_CacheLumpName(patcharti
|
||||
[CPlayer->inventory[x + i].type],
|
||||
PU_CACHE));
|
||||
patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]);
|
||||
|
||||
V_DrawPatch(50 + i * 31, 160, W_CacheLumpName(patch, PU_CACHE));
|
||||
DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31, 182);
|
||||
}
|
||||
}
|
||||
|
|
@ -921,6 +926,7 @@ void DrawInventoryBar(void)
|
|||
|
||||
void DrawFullScreenStuff(void)
|
||||
{
|
||||
char *patch;
|
||||
int i;
|
||||
int x;
|
||||
int temp;
|
||||
|
|
@ -950,10 +956,9 @@ void DrawFullScreenStuff(void)
|
|||
{
|
||||
if (CPlayer->readyArtifact > 0)
|
||||
{
|
||||
V_DrawTLPatch(286, 170, W_CacheLumpName("ARTIBOX", PU_CACHE));
|
||||
V_DrawPatch(286, 170,
|
||||
W_CacheLumpName(patcharti[CPlayer->readyArtifact],
|
||||
PU_CACHE));
|
||||
patch = DEH_String(patcharti[CPlayer->readyArtifact]);
|
||||
V_DrawTLPatch(286, 170, W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE));
|
||||
V_DrawPatch(286, 170, W_CacheLumpName(patch, PU_CACHE));
|
||||
DrSmallNumber(CPlayer->inventory[inv_ptr].count, 307, 192);
|
||||
}
|
||||
}
|
||||
|
|
@ -962,15 +967,14 @@ void DrawFullScreenStuff(void)
|
|||
x = inv_ptr - curpos;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
V_DrawTLPatch(50 + i * 31, 168, W_CacheLumpName("ARTIBOX",
|
||||
PU_CACHE));
|
||||
V_DrawTLPatch(50 + i * 31, 168,
|
||||
W_CacheLumpName(DEH_String("ARTIBOX"), PU_CACHE));
|
||||
if (CPlayer->inventorySlotNum > x + i
|
||||
&& CPlayer->inventory[x + i].type != arti_none)
|
||||
{
|
||||
patch = DEH_String(patcharti[CPlayer->inventory[x + i].type]);
|
||||
V_DrawPatch(50 + i * 31, 168,
|
||||
W_CacheLumpName(patcharti
|
||||
[CPlayer->inventory[x + i].type],
|
||||
PU_CACHE));
|
||||
W_CacheLumpName(patch, PU_CACHE));
|
||||
DrSmallNumber(CPlayer->inventory[x + i].count, 69 + i * 31,
|
||||
190);
|
||||
}
|
||||
|
|
@ -1051,11 +1055,11 @@ static void CheatGodFunc(player_t * player, Cheat_t * cheat)
|
|||
player->cheats ^= CF_GODMODE;
|
||||
if (player->cheats & CF_GODMODE)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATGODON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATGODON), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATGODOFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATGODOFF), false);
|
||||
}
|
||||
SB_state = -1;
|
||||
}
|
||||
|
|
@ -1065,11 +1069,11 @@ static void CheatNoClipFunc(player_t * player, Cheat_t * cheat)
|
|||
player->cheats ^= CF_NOCLIP;
|
||||
if (player->cheats & CF_NOCLIP)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATNOCLIPON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPON), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATNOCLIPOFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATNOCLIPOFF), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1102,7 +1106,7 @@ static void CheatWeaponsFunc(player_t * player, Cheat_t * cheat)
|
|||
{
|
||||
player->ammo[i] = player->maxammo[i];
|
||||
}
|
||||
P_SetMessage(player, TXT_CHEATWEAPONS, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATWEAPONS), false);
|
||||
}
|
||||
|
||||
static void CheatPowerFunc(player_t * player, Cheat_t * cheat)
|
||||
|
|
@ -1110,12 +1114,12 @@ static void CheatPowerFunc(player_t * player, Cheat_t * cheat)
|
|||
if (player->powers[pw_weaponlevel2])
|
||||
{
|
||||
player->powers[pw_weaponlevel2] = 0;
|
||||
P_SetMessage(player, TXT_CHEATPOWEROFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATPOWEROFF), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_UseArtifact(player, arti_tomeofpower);
|
||||
P_SetMessage(player, TXT_CHEATPOWERON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATPOWERON), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1129,7 +1133,7 @@ static void CheatHealthFunc(player_t * player, Cheat_t * cheat)
|
|||
{
|
||||
player->health = player->mo->health = MAXHEALTH;
|
||||
}
|
||||
P_SetMessage(player, TXT_CHEATHEALTH, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATHEALTH), false);
|
||||
}
|
||||
|
||||
static void CheatKeysFunc(player_t * player, Cheat_t * cheat)
|
||||
|
|
@ -1140,7 +1144,7 @@ static void CheatKeysFunc(player_t * player, Cheat_t * cheat)
|
|||
player->keys[key_green] = true;
|
||||
player->keys[key_blue] = true;
|
||||
playerkeys = 7; // Key refresh flags
|
||||
P_SetMessage(player, TXT_CHEATKEYS, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATKEYS), false);
|
||||
}
|
||||
|
||||
static void CheatSoundFunc(player_t * player, Cheat_t * cheat)
|
||||
|
|
@ -1148,11 +1152,11 @@ static void CheatSoundFunc(player_t * player, Cheat_t * cheat)
|
|||
DebugSound = !DebugSound;
|
||||
if (DebugSound)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATSOUNDON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATSOUNDON), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATSOUNDOFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATSOUNDOFF), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1161,11 +1165,11 @@ static void CheatTickerFunc(player_t * player, Cheat_t * cheat)
|
|||
DisplayTicker = !DisplayTicker;
|
||||
if (DisplayTicker)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATTICKERON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATTICKERON), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATTICKEROFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATTICKEROFF), false);
|
||||
}
|
||||
|
||||
I_DisplayFPSDots(DisplayTicker);
|
||||
|
|
@ -1173,12 +1177,12 @@ static void CheatTickerFunc(player_t * player, Cheat_t * cheat)
|
|||
|
||||
static void CheatArtifact1Func(player_t * player, Cheat_t * cheat)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTS1, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS1), false);
|
||||
}
|
||||
|
||||
static void CheatArtifact2Func(player_t * player, Cheat_t * cheat)
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTS2, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS2), false);
|
||||
}
|
||||
|
||||
static void CheatArtifact3Func(player_t * player, Cheat_t * cheat)
|
||||
|
|
@ -1206,7 +1210,7 @@ static void CheatArtifact3Func(player_t * player, Cheat_t * cheat)
|
|||
P_GiveArtifact(player, i, NULL);
|
||||
}
|
||||
}
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTS3, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false);
|
||||
}
|
||||
else if (type > arti_none && type < NUMARTIFACTS
|
||||
&& count > 0 && count < 10)
|
||||
|
|
@ -1214,18 +1218,18 @@ static void CheatArtifact3Func(player_t * player, Cheat_t * cheat)
|
|||
if (gamemode == shareware
|
||||
&& (type == arti_superhealth || type == arti_teleport))
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTSFAIL, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
P_GiveArtifact(player, type, NULL);
|
||||
}
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTS3, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTS3), false);
|
||||
}
|
||||
else
|
||||
{ // Bad input
|
||||
P_SetMessage(player, TXT_CHEATARTIFACTSFAIL, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATARTIFACTSFAIL), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1242,7 +1246,7 @@ static void CheatWarpFunc(player_t * player, Cheat_t * cheat)
|
|||
if (D_ValidEpisodeMap(gamemission, gamemode, episode, map))
|
||||
{
|
||||
G_DeferedInitNew(gameskill, episode, map);
|
||||
P_SetMessage(player, TXT_CHEATWARP, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATWARP), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1254,19 +1258,19 @@ static void CheatChickenFunc(player_t * player, Cheat_t * cheat)
|
|||
{
|
||||
if (P_UndoPlayerChicken(player))
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATCHICKENOFF, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATCHICKENOFF), false);
|
||||
}
|
||||
}
|
||||
else if (P_ChickenMorphPlayer(player))
|
||||
{
|
||||
P_SetMessage(player, TXT_CHEATCHICKENON, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATCHICKENON), false);
|
||||
}
|
||||
}
|
||||
|
||||
static void CheatMassacreFunc(player_t * player, Cheat_t * cheat)
|
||||
{
|
||||
P_Massacre();
|
||||
P_SetMessage(player, TXT_CHEATMASSACRE, false);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATMASSACRE), false);
|
||||
}
|
||||
|
||||
static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat)
|
||||
|
|
@ -1281,11 +1285,11 @@ static void CheatIDKFAFunc(player_t * player, Cheat_t * cheat)
|
|||
player->weaponowned[i] = false;
|
||||
}
|
||||
player->pendingweapon = wp_staff;
|
||||
P_SetMessage(player, TXT_CHEATIDKFA, true);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATIDKFA), true);
|
||||
}
|
||||
|
||||
static void CheatIDDQDFunc(player_t * player, Cheat_t * cheat)
|
||||
{
|
||||
P_DamageMobj(player->mo, NULL, player->mo, 10000);
|
||||
P_SetMessage(player, TXT_CHEATIDDQD, true);
|
||||
P_SetMessage(player, DEH_String(TXT_CHEATIDDQD), true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#ifndef __SOUNDSH__
|
||||
#define __SOUNDSH__
|
||||
|
||||
#include "i_sound.h"
|
||||
|
||||
#define MAX_SND_DIST 1600
|
||||
#define MAX_CHANNELS 16
|
||||
|
||||
|
|
@ -291,4 +293,7 @@ typedef enum
|
|||
NUMSFX
|
||||
} sfxenum_t;
|
||||
|
||||
extern sfxinfo_t S_sfx[];
|
||||
extern musicinfo_t S_music[];
|
||||
|
||||
#endif
|
||||
|
|
|
|||
6
src/hexen/.gitignore
vendored
6
src/hexen/.gitignore
vendored
|
|
@ -1,7 +1,5 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
*.rc
|
||||
chocolate-doom
|
||||
chocolate-server
|
||||
*.exe
|
||||
tags
|
||||
TAGS
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "m_controls.h"
|
||||
#include "p_local.h"
|
||||
#include "v_video.h"
|
||||
#include "w_main.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
|
@ -88,7 +89,6 @@ static void PageDrawer(void);
|
|||
static void HandleArgs(void);
|
||||
static void CheckRecordFrom(void);
|
||||
static void DrawAndBlit(void);
|
||||
static void ExecOptionFILE(char **args, int tag);
|
||||
static void ExecOptionSCRIPTS(char **args, int tag);
|
||||
static void ExecOptionSKILL(char **args, int tag);
|
||||
static void ExecOptionPLAYDEMO(char **args, int tag);
|
||||
|
|
@ -133,7 +133,6 @@ static int pagetic;
|
|||
static char *pagename;
|
||||
|
||||
static execOpt_t ExecOptions[] = {
|
||||
{"-file", ExecOptionFILE, 1, 0},
|
||||
{"-scripts", ExecOptionSCRIPTS, 1, 0},
|
||||
{"-skill", ExecOptionSKILL, 1, 0},
|
||||
{"-playdemo", ExecOptionPLAYDEMO, 1, 0},
|
||||
|
|
@ -157,6 +156,7 @@ void D_BindVariables(void)
|
|||
M_BindMapControls();
|
||||
M_BindMenuControls();
|
||||
M_BindWeaponControls();
|
||||
M_BindChatControls(MAXPLAYERS);
|
||||
M_BindHereticControls();
|
||||
M_BindHexenControls();
|
||||
|
||||
|
|
@ -422,6 +422,9 @@ static void HandleArgs(void)
|
|||
|
||||
cmdfrag = M_ParmExists("-cmdfrag");
|
||||
|
||||
// Check WAD file command line options
|
||||
W_ParseCommandLine();
|
||||
|
||||
// Process command line options
|
||||
for (opt = ExecOptions; opt->name != NULL; opt++)
|
||||
{
|
||||
|
|
@ -483,27 +486,6 @@ static void ExecOptionSKILL(char **args, int tag)
|
|||
autostart = true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ExecOptionFILE
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ExecOptionFILE(char **args, int tag)
|
||||
{
|
||||
char *filename;
|
||||
int p;
|
||||
|
||||
p = M_CheckParm("-file");
|
||||
while (++p != myargc && myargv[p][0] != '-')
|
||||
{
|
||||
filename = D_TryFindWADByName(myargv[p]);
|
||||
|
||||
D_AddFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ExecOptionPLAYDEMO
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue