Coder Social home page Coder Social logo

reflectionhle's Introduction

ReflectionHLE

ReflectionHLE, known for years as Reflection Keen, is a project consisting of source ports of DOS games, all being inspired by the Chocolate Doom port. These ports use a common codebase, consisting of the ReflectionHLE backend and third-party code.

The source ports in question are:

  • Reflection Keen Dreams (KDreams), a Keen Dreams port.
  • Reflection Catacomb 3-D (Cat3D), which includes ports of Catacomb 3-D (The Descent) and The Catacomb Adventure Series.
  • Reflection Wolfenstein 3D (Wolf3D), covering ports of Wolfenstein 3D, Spear of Destiny and Super 3-D Noah's Ark (DOS version).

Terms of use

All corresponding license documents should be found under LICENSES.

Since the covered ports are based on multiple codebases with varying licenses, the terms are described for each source port as a whole, as well as the differing components.

Note that these terms do not cover any original game data, which should be obtained separately.

The terms applying to the source ports (i.e., the executables):

  • Reflection KDreams, Reflection Cat3D and Reflection Wolf3D are all released under the GNU GPLv2+. See gpl-2.0.txt for more details.

The terms applying to each component separately:

  • The ported Keen Dreams, Catacomb 3-D, The Catacomb Adventures Series and Wolfenstein 3D codebases are released under the GNU GPLv2+. See gpl-2.0.txt.

  • The ported Wolfenstein 3D code is also available under the original terms for the Wolfenstein 3D sources from 1995. See id-wolf3d.txt.

  • The ReflectionHLE backend is released under the 3-Clause BSD License. See bsd-3-clause-template.txt for a general license template. For the exact contents you should consult the top of any relevant file from the source code, although the template's form was originally used as a base.

  • Nuked OPL3 is released under the GNU LGPLv2.1+. See lgpl-2.1.txt.

  • The included depklite implementation, a modification of ExeUnpacker, is released under the MIT License. See mit-opentesarena.txt for details.

  • The included CRC-32 implementation is in the public domain. The same applies to the modified unlzexe source (based on UNLZEXE.DOC from v0.4).

How to run a game

Note that ReflectionHLE does not include game data, which you'll have to obtain separately.

Depending on the environment (e.g., operating system) in which ReflectionHLE is used, you might be able to use the ReflectionHLE launcher and/or a command-line interface. Even if you prefer to skip the launcher, it may assist you when you want to tell ReflectionHLE where to locate compatible game data.

ReflectionHLE may autodetect existing game installations in specific locations which are internally scanned. You can also use the launcher to add other locations with game installations.

Using an application icon or executable

If you start ReflectionHLE by pressing on an application icon or executable, the ReflectionHLE launcher should appear. Here, you can see which game versions are supported, and which game files are required for each such version.

In addition to autodetected game installations, you can use the launcher to select a directory with compatible game data. Once it's confirmed such data is found, it'll be remembered for later uses.

Note that if you use an external launcher or shortcut which adds additional command-line arguments, this may change the behaviors. More details are given under following instructions for using a command-line interface.

Using a command-line interface

You can also start ReflectionHLE from a command-line interface, like Windows' Command Prompt. Doing so without passing additional arguments should generally be the same as using an application icon, albeit there can be differences that vary by the environment.

If you pass at least one additional argument, a game can be started without going through the launcher, unless you use -fulllauncher or -softlauncher.

If -passorigargs is used, the arguments that follow it are passed to the game as-is. The exact meanings of them can vary by the game.

You can use -gamever for selecting a specific game version. To show a list of supported game versions, use -listgamevers as the only command-line argument.

To read about more options, you can use -? as the sole command-line argument.

Skipping the launcher

If you simply want to start a game while skipping the launcher, you can use the command-line arguments -gamever , or alternatively, use -passorigargs with no other argument.

Note that you should first make sure that ReflectionHLE knows where to find compatible game data. See above for locating data via the launcher.

How to build from the source code

See COMPILING.md.

Acknowledgements

See AUTHORS.md.

reflectionhle's People

Contributors

blzut3 avatar keendreams avatar ny00123 avatar rdmandel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

reflectionhle's Issues

[Suggestion] Save directory option

I was looking for an option to do this within the executable, but I don't think it's implemented. Basically it's a suggestion to implement something akin to Chocolate Doom's optional -savedir parameter, which lets the user specify their own desired folder where save games are stored at their own discretion. I think it would be useful for people wanting to keep all their vanilla-compatible saves in one folder.

Broken mouse button overrides: Function keys, scrolls

If a mouse button is bound to "Scrolls" (Catacomb 3-D / Abyss) or "Function keys", no appropriate UI will appear upon use, unless a supported game controller is detected.
The UI in question was initially added to be used for game controllers, and later, was also extended for usage with touch input.

This bug might be rare in practice, since if such mouse binding is desired, there are maybe greater chances that a game controller is also used, but it's still a bug.

Note that unlike the examples in this bug report, debug keys will appear on request even if controller and touch input aren't used at all.

[Feature request] Uncapped framerate

Hi @NY00123

How feasible would it be to have uncapped framerate + movement interpolation on those? Since they are 70Hz games originally, they seem to tick the screen refresh at 35Hz, which looks pretty bad on modern screens, which are ~60Hz.

User input improvements

This issue was opened for tracking the status of user input support, and also for writing details specific to supported games.

Unlike Vanilla/Chocolate Doom, a few of the covered games let you change keyboard/joystick settings from the in-game menus, while Wolf3D also covers the mouse. Additionally, there isn't necessarily a single function for processing input which impacts gameplay.

Game-specific details are following.

Keen Dreams and the Catacombs use IN_ReadControl for getting user input and translating it into data impacting gameplay. Wolfenstein 3D is only using IN_ReadControl in the menus, via wl_menu.c:ReadAnyControl.

IN_ReadControl fills a ControlInfo (CursorInfo) struct with the following fields: button0 & button1, x & y, xaxis & yaxis, dir. In the case of Wolf3D (or at least the sole uses from the menu), there are also button2 & button3.

The button fields are used for specifying actions like shooting, jumping and strafing. xaxis and yaxis encode two direction values, with the valid values being -1, 0 and 1. dir encodes both directions in a single enum value. x and y encode not just the directions themselves, but also their magnitudes. These fields are always 0 or +-127 for a keyboard, while they may have more values for mouse and joystick inputs.

With the exception of the Catacomb Adventure Series, ID_ReadControl only gets data from one device at a time, a keyboard or a joystick.

  • A mouse could theoretically be used in Keen Dreams after appropriately hex editing the config file, albeit USL_TearDownCtlPanel would effectively change this to ctrl_Joystick2 instead.
  • If such a hex edit is done for Catacomb 3-D, only the mouse will be usable for moving, strafing and the basic shooting action. It'll feel closer to its usage in the Catacomb Adventure Series. An explanation related to the series is given later.
  • For Wolfenstein 3D, the device type set for ID_ReadControl will always be a keyboard.

Keen Dreams never makes use of the aforementioned 'x' or 'y' values, so it's only the direction which matters. The data that impacts core gameplay arrives from IN_ReadControl. It may still check for other pressed keys in CheckKeys, say for debug keys or displaying the status screen.

For Catacomb 3-D:

  • c3_play.c:PollControls is used as a wrapper over IN_ReadControl. In addition to processing keyboard/joystick input via IN_ReadControl, it separately checks for mouse input, taking two mouse buttons into account and storing mouse motion in separate global variables, mousexmove and mouseymove. If a joystick is used, the (calibrated) distance of the stick from the center determines if the player is running. Otherwise, the right shift key is used as a toggle for this.
  • c3_wiz.c:ControlMovement uses the aforementioned input to pick movement and rotation speeds. Data based on mousexmove and mouseymove is accumulated with keyboard/joystick input. For the same magnitude of mouse delta, the player will move forward for a greater distance than backwards.
  • This is not all that impacts gameplay, though. In addition to the call to ControlMovement, c3_wiz.c:T_Player also checks for specific hardcoded keys representing special actions, like drinking potions or casting bolts.
  • The x and y fields of the struct returned from IN_ReadControl are used just for the aforementioned joystick "running" toggle. Mouse motion updates via mousexmove and mouseymove are the only other way for impacting the speed, on top of the keyboard's "running" toggle.

The Catacomb Adventure Series differs from Catacomb 3-D in the following manners, at the least:

  • id_in.c:IN_ReadControl may check for input from any of the supported devices, in the following order of priorities: Mouse (if present/detected), joystick (if calibrated), keyboard. It'll exclusively use input from just one of these.
  • As a side-effect, if the mouse is used in a way which impacts gameplay, then keyboard/joystick input will be ignored by IN_ReadControl. This differs from Catacomb 3-D. Other keyboard actions (say for drinking a potion) will still be functional, outside of IN_ReadControl.
  • Also, unlike Catacomb 3-D, there's no "running" toggle for moving, just for turning. Additionally, how far the joystick is moved will not impact it at all, so just a keyboard toggle will do it, using the 'V' or 'Tab' key.
  • If fast turning is enabled via the keyboard, the impact on the turning speed will be greater than in Catacomb 3-D.
  • While ControlMovement still fills mousexmove and mouseymove, most chances are they'll be set to 0, due to being done right after a call to IN_ReadControl, which reads pending mouse motion earlier.
  • Therefore, in the Catacomb Adventure Series, it's practically just IN_ReadControl which tells how mouse motion impacts movement and rotations in gameplay. This is similar to running Catacomb 3-D with the mouse as the selected input device (by hex editing CONFIG.C3D).
  • The x and y fields of the struct returned from IN_ReadControl are not used at all, except for checks in DisplayStatus that could also be done with the xaxis and yaxis fields.
  • Furthermore, DisplayStatus separately checks for hardcoded keys in order to pick a status message, say for using a zapper. In the case of a missile, it also checks the control key, not just the button0 field returned from IN_ReadControl. Since you can't change the shooting key without hex editing the config file, it generally doesn't matter, but this is still the case.

To finish, as written earlier, Wolfenstein 3D doesn't use IN_ReadControl during gameplay. wl_play.c:PollControls is used as a full replacement, including demo recording/playback. Outside of demo playback, it may accumulate input from keyboard, mouse and joystick/gamepad.

[Wolf3d/Cat3d] Strafe Buttons?

Could we perhaps get a launcher-based option to enable dedicated strafe keys in Wolfenstein 3D and the Catacomb 3D games?

wolf3d: Sound timing problem in the intermission screen

The code under LevelCompleted may repeatedly start playback of sound ENDBONUS1SND or D_INCSND with SD_PlaySound.

Originally, this was done by waiting for SD_SoundPlaying() to return false in Wolf3D, or by waiting for the variable TimeCount to change in S3DNA (via RollDelay). With the DOS versions from the 90s, this generally works well, given that the timer interrupt is in charge, but the same tends to not hold for the port.

This is especially noticeable while VSync is toggled on, but it may still be observed even without it.

Handle transitions to levels 19-22 in The Catacomb Abyss

Originally reported by Arno for level 19: https://www.doomworld.com/forum/topic/117084-reflection-keen-now-supporting-wolfenstein-3d/?tab=comments#comment-2194909

This one is a bit tricky to properly handle. The following posts of mine have an analysis of the behaviors, which is repeated here:
https://www.doomworld.com/forum/topic/117084-reflection-keen-now-supporting-wolfenstein-3d/?tab=comments#comment-2195973
https://www.doomworld.com/forum/topic/117084-reflection-keen-now-supporting-wolfenstein-3d/?tab=comments#comment-2196379

There is more than one problem to take care of.

levelnames buffer overread

First of all, for levels 19-22, DrawEnterScreen will overread the levelnames array. For versions 1.13 and 1.24 of the game, due to the layouts of the DOS EXEs, this will translate to an attempt to read a C string literal from the grsegs segment pointers array.

In the case of level 19, it will end with what should be a pointer to a 16x16 tile. Since there are no 16x16 tiles - at least with the original game data - the corresponding grsegs element won't be filled with a nonzero segment pointer from CA_CacheGrChunk (via LoadLatchMem). Thus, the buffer overread will practically translate to an empty string.

I haven't fully investigated what occurs with levels 20-22. However, while DrawEnterScreen generally returned, in spite of the aforementioned overruns, the situation was different in an attempt of mine to load level 21 from v1.13. Here, the string buffer overrun done via levelnames[21] ended with a string made out of the following sequence of bytes: 2F 06 15 07 73 33 00
For printing the string, ShiftPropChar from ID_VW_AE.ASM should be called for every string character. When it's called with the value of bx == 6, [es:charwidth+bx] (i.e., currfont->width[charnum] in Reflection Catacomb) is 0, so the si register is also set to 0. It remains set to 0 even after a few more manipulations on it. Eventually, an attempt to jump is done as follows:

jmp [ss:shiftdrawtable+si]

However, because si set to 0, and shiftdrawtable further begins with 0, this effectively jumps to some arbitrary address.

In that case, it turns out to be exactly the location where VW_Vlin is called from VWB_Vlin, which must be the explanation for the vertical lines shown in the screenshot.

catabyss_000

Of course, the return from VWB_Vlin leads to a more-or-less undefined location.

Loading level 19

Ignoring the levelnames buffer overread, there are still more problems to come. For level 19, we reach CA_CacheMap, which attempts to access mapheaderseg[19]. This leads to another out-of-bounds array access.
For the EXEs from versions 1.13 and 1.24, mapheaderseg[19] basically overlaps textstarts[0].

Generally, textstarts[0] should be set to 0 (on exe load and via ScanText).
If we enter level 19 from another level, then CA_CacheMap will simply use mapheaderseg[19] i.e., textstarts[0] to store a pointer to newly allocated data.
SetupGameLevel will later reference the map width and height from this pointer.

Later, ScanText will be called from CacheScaleds, thus resetting textstarts[0] i.e., mapheaderseg[19] to 0.
What this effectively leads to is a memory leak.

When leaving level 19 (or possibly even just restarting level 19), CA_CacheMap will not free the memory previously referenced by mapheaderseg[19], because this pointer variable, which is actually textstarts[0], has already been set to 0.
One possible way to handle this in a port is as follows. The mapheaderseg array length can be increased by 1, and then mapheaderseg[19] (i.e., mapheaderseg[NUMMAPS+1]) can be reset to 0 right after being used in SetupGameLevel.

Attempting to load any of levels 20-22

Let's ignore issues with levelnames again. Just like mapheaderseg[19] refers to textstarts[0], mapheaderseg[20], mapheaderseg[21] and mapheaderseg[22] refer to the following 3 locations in the textstarts array. Main difference is that these offsets are generally nonzero when CA_CacheMap is called. Thus, it'll try to set their purge levels with MM_SetPurge.

Because these aren't properly allocated memory addresses (at least not in my tests), this will simply end with the following error message: "MM_SetPurge: Block not found!"

Wolf3D: Handle pressing on a pushwall right after beginning to push it

This is possibly another instance of an out-of-bounds memory access, for which emulating the original behaviors can be a bit tricky.

Basically, depending on the wall tile, you might open/close a door with an arbitrary door number, just by pressing on a pushwall right after beginning to push it. If this number is >= MAXDOORS, you get an overflow. One possible side-effect is a change to some tile in the map, say by turning it into a blocking tile.

Detecting multiple game versions from selected dir

When a location is picked for game data, only one matching game version can be added at a time.
A separate txt file is currently created for each game version, filled with a description of the location, and with an internal description of the version in question being used in the file name.

Detection of multiple versions can still be done, simply be trying one after the other. Alternatively, a separate file with multiple locations can be maintained as an alternative to multiple scattered txt files, which are already one-liners, anyway.

Android Version: Unify all APK's into one single launcher?

It's been several years since the Reflection Keen APK's were released; would it be possible to combine it all into one single launcher, instead of splitting each plugin across several, separate APK's, as was the case with the Catacomb releases?

Keen Dreams can quickly run out of memory with the 2015 edition

To reproduce, start a new game, and then use F10+W to warp to the following levels in the given order: 1-6.

For a bit of a background, the memory management code as used for other versions of Keen Dreams isn't suitable for the 2015 one, because it uses recorded sound effects with too large chunk sizes to fit in memory (as originally done under DOS).

A bit of patching was done to make the code behave a little bit different for the 2015 release, but it's not sufficient.

fail to compile on Pi4

i thought i would give this a shot and see if i can get it to run on my Pi4

it starts to compile and then ends up failing quickly

/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:125:1: error: narrowing conversion of ‘-1’ from ‘int’ to ‘sodac14::id0_char_t’ {aka ‘char’} inside { } [-Wnarrowing]
 };
 ^
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:125:1: error: narrowing conversion of ‘-1’ from ‘int’ to ‘sodac14::id0_char_t’ {aka ‘char’} inside { } [-Wnarrowing]
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:125:1: error: narrowing conversion of ‘-1’ from ‘int’ to ‘sodac14::id0_char_t’ {aka ‘char’} inside { } [-Wnarrowing]
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:125:1: error: narrowing conversion of ‘-1’ from ‘int’ to ‘sodac14::id0_char_t’ {aka ‘char’} inside { } [-Wnarrowing]
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c: In function ‘void sodac14::T_Attack(sodac14::objtype*)’:
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:2173:3: warningcase label value is less than minimum value for type
   case -1:
   ^~~~
/home/pi/RetroPie-Setup/tmp/build/refkeen/src/wolf3d/wl_agent.c:2174:14: warning: statement will never be executed [-Wswitch-unreachable]
    ob->state = &s_player;
    ~~~~~~~~~~^~~~~~~~~~~
make[2]: *** [CMakeFiles/reflection-sodac14.dir/build.make:342: CMakeFiles/reflection-sodac14.dir/src/wolf3d/wl_agent.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:217: CMakeFiles/reflection-sodac14.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

any pointers would be great

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.