================================================================================ Changes since Eternity Engine v3.35.92 ================================================================================ -------------------------------------------------------------------------------- 12/29/09 As an exercise of the new screenshot module, and because doing so requires fewer than 100 lines of code, I added Targa as a supported screenshot format. Targa, although relatively very old, is still in extensive use in the graphics and game industries due to its simplicity of implementation, as well as features it offers that make it useful for display on TV screens (obviously not a factor to EE of course). Hopefully PNG support is not far off :) -------------------------------------------------------------------------------- 12/28/09 I have rewritten the screenshot code into a new mini-screenshot engine that can support multiple formats with minimum addition of code, and also makes use of a new buffered file output module which was initially written as part of my experimental zip file writing code that will eventually become part of our new savegame code, which is still in the planning stages. -------------------------------------------------------------------------------- 12/27/09 EE is now internally consistent with its use of strcasecmp and strncasecmp versus the nonstandard stricmp and strnicmp that Visual Studio expects. This was getting totally out of hand, and our defines were bordering on circularity under GCC. _CRT_SECURE_NO_WARNINGS and _CRT_NONSTDC_NO_WARNINGS have been added to the VS2008 project to prevent 394 some-odd warnings of no consequence. I actually attempted to address the NONSTDC warnings by providing some defines, but Visual Studio predictably threw a fit since its headers contain defines for those function names already which cannot be sorted out in preference for our own without a major bunch of work that is completely not worth it. Thanks, Microsoft, for supporting portable development so well.... psvnsprintf has been hacked up once again to avoid undefined behavior with respect to the passing down of va_list objects to multiple functions, to which GCC 64-bit strongly objects due to some standards-acceptable but highly questionable implementation decisions on that platform. Protip: To avoid breaking 90% of C programs, do not make varargs functions use the AMD64 fastcall convention.... A similarly undefined use of va_list was also eliminated from the E_EDFLoggedErr routine, although doing this imposed a static limit on the error message length that I would have rather avoided. C'est la vie. Linebreak styles have been made consistent in multiple files, as it seems some of our more Linux-minded developers in the past have used tools that are not DOS linebreak-aware, and added Linux linebreaks into their new lines without first converting the existing ones. I have no opinion as to whether the majority of the code should use Linux or DOS linebreaks, so long as the individual files remain self-consistent. To me, that is an absolute must. -------------------------------------------------------------------------------- 12/26/09 A Visual Studio 2008 project has now been added for Eternity, currently supporting 32-bit builds only. I added a tools directory to the SVN project, and wrote up a qbin2c tool that creates C header files from binary files, as part of an attempt to get EE to have an icon on its titlebar. However, SDL's support for this seems to be unacceptably out of date and possibly even glitchy, so for now EE's icon will only display on the taskbar when built with the VS 2008 project. The 6.0 project doesn't currently provide an icon, but I hope to be able to rectify that as well soon. As per a recommendation on MSDN, I have changed the use of GetWindowLong and SetWindowLong used in the code to support disabling of Alt+Space to use GetWindowLongPtr and SetWindowLongPtr instead, as these routines are 64-bit compatible. Sadly, this has caused problems for Visual Studio 6.0, because it is missing these functions from its headers, even though MSDN states that these functions have been supported since Windows 95. This has introduced the need for Eternity to build with the Windows Server 2003 Platform SDK installed and active when using Visual Studio 6.0, something that I had previously hoped to avoid. This is especially unfortunate because the PSDK will no longer install properly due to a bug in either the ridiculous ActiveX installer it uses, or in Internet Explorer 8.0. This requires the enduser to do a run-around the installer by clicking on the proper .msi files that are "hidden" in the setup directory. Doing this precludes any future use of the PSDK update feature, according to Microsoft, so don't do it if you are using a box on which you intend to do active future development with newer SDKs. This would probably be best reserved for that XP box you have over in the corner for a back-up system, or maybe a virtual machine specifically set up for the purpose of supporting VS6.0-based development. -------------------------------------------------------------------------------- 12/22/09 Implemented a MetaSetInt routine to match MetaSetDouble, as it might be useful in the implementation of features such as droptypes and bloodtypes. -------------------------------------------------------------------------------- 11/24/09 I made some important changes to sprite handling so that NUMSPRITES is no longer used as a value to mean "no sprite" or "no next sprite," but instead the value -1 is used for the same purpose. This is required to move sprites toward a fully dynamic model so that they can be implicitly defined in DECORATE states. This will eventually almost entirely obsolete the EDF spritenames array, though it will probably have to be retained for definition of the original DOOM sprites in order to guarantee retention of DeHackEd compatibility. -------------------------------------------------------------------------------- 11/22/09 SoM and I have cooperated to add sprite scaling. -------------------------------------------------------------------------------- 11/21/09 Got around to another long-standing TODO, which was the addition of an r_tlstyle variable which controls the default presentation of thingtypes that were modified by BOOM to be translucent, a change some people object to, and others feel was not radical enough. Under the current system, which is based on a list of EDF thingtype mnemonics and tries to avoid stepping on the toes of any existing mods, you can set r_tlstyle to one of three values, which are explained here: * None - this value makes all BOOM translucent thingtypes opaque again. This is vanilla DOOM's presentation mode. * Boom - pretty obvious I think. The things use BOOM-style translucency. * New - The thingtypes are selectively set to opaque, translucent, or additive blending depending on what I myself, with advice taken from others, believe looks the best. This is Eternity's presentation mode, and is very similar to the behavior of ZDoom in fact. -------------------------------------------------------------------------------- 11/18/09 Applied a long needed compatibility fix: DeHackEd's maxhealth property is only supposed to affect the behavior of health potions, not *ALL* health items as it did in BOOM. This broke HacX, amongst other mods. z_native.c has been extensively cleaned up via the use of some intelligent new macros near the head of the file that get rid of what was previously #ifdef hell (this can still be seen in z_zone.c if you are curious). The code is now infinitely more readable. -------------------------------------------------------------------------------- 11/13/09 EE now expects to build and link against SDL 1.2.14 and SDL_mixer 1.2.10, which may prove to be the final 1.2 versions of SDL if what is written on the website is to be believed. After doing this, I found the need for a new option to disable Alt+Space in Windows, since SDL makes no effort to intercept this event. It causes the window system menu to open, making the game pause and any active keys get stuck in the down state. This is controlled by a new system.cfg option. -------------------------------------------------------------------------------- 11/12/09 I wiped out the last remaining uses of gitextmetric_t objects, which stored metrics for game fonts and mapped their access through the GameModeInfo structure. This was previously replaced by the addition of EDF dynamic fonts, which store the exact same information, but within the font objects instead of a separate global location. After adding the ability to have post-W_InitMultipleFiles adjustments made to GameModeInfo based on the missioninfo object in effect, I added support for the playing of DEMO4 in TNT and Plutonia game modes, contingent upon the presence of an actual DEMO4 lump. TNT and Plutonia were based on Ultimate DOOM instead of DOOM II as one would ordinarily suspect, and because of this they used the Ultimate DOOM demo loop which showed demos for the four episodes. However id evidently forgot about this and only provided 3 demos in each IWAD. This means that watching the demo loops of those games in the vanilla engines would result in a W_CacheLumpNum error upon reaching the fourth demo. Eternity would not error out, because Eternity used the DOOM II demo sequence for these modes, and additionally because Eternity ignores non-existent demo lumps (a message simply appears in the console, and the demo sequence, if it is running, is auto-advanced to the next state). However, Eternity would also not display the fourth demo even if it existed, which was technically incorrect behavior. A DEMO4 lump is provided in the Plutonia 2 mod, which is what prompted this adjustment. A new "open" method has been added to menu objects which allows individual menus to have customized opening behaviors. This was needed to restore support for the defaultskill variable from BOOM, which, although it still existed in the configuration file, was "lost" in SMMU and has been ignored ever since. In an effort to fix bizarre palette issues that are plaguing DirectX modes on startup, I have added an I_SetPaletteDirect routine which ducks under our relatively new palette caching scheme to set the palette to the video surface immediately. This is needed at startup, as we need a palette on the surface before any drawing is done, otherwise SDL decides to do an improper remapping operation once the palette IS set, resulting in a REALLY attractive screen full of what can only properly be described as technicolor puke. Some additional modifications were made that seem to improve the behavior of DirectX modes under older SDL versions. Mainly, blits should be done after any pending palette sets and not before, and second, the screen should always be flipped even if the palette is set, as some types of surfaces violently object to the missing update otherwise. -------------------------------------------------------------------------------- 11/11/09 I eliminated the irritating need for an "index" parameter to the full table iteration method (MetaTableIterator) of the metatable and its corresponding underlying e_hash method, E_HashTableIterator. The index of the current chain being searched is now cached inside the ehash_t structure itself. This does require a search to be primed with the proper value in order to restart from the beginning, of course. Screenshots no longer pop up the console, so that you can actually take a screenshot of the console. The obsolete playersprite variable's processing code has been removed from EDF (it is still syntactically accepted, but is ignored). The only place using it has been rewritten to avoid the need for it. This is a necessary change in preparation for DECORATE state support. -------------------------------------------------------------------------------- 11/10/09 At fraggle's urging I refactored Polyobj_findLines to avoid an unnecessary goto, and to give the algorithm better documentation. I have eliminated the old -debugfile and all code related to it, which was probably added late in id's development cycle while ironing out the network code. The file was nearly useless to us now, and I have not employed it since sometime around 2001, making it dead code. -------------------------------------------------------------------------------- 11/09/09 Kate got a confusing error when trying to play a demo named MAP01.LMP - to my dismay it caused the map it was meant to play with to disappear from visibility, since demos added with the -playdemo command are linked into the wad directory as individual file lumps. I chose to solve this problem (which has existed since vanilla Doom) by placing such demo lumps into their own new namespace, ns_demos. The lump namespace, added by BOOM as part of the fix for allowing sprites and flats in PWADs, is tailor-made to fix this type of problem. I understand that PrBoom has repaired this by simply not adding demo lumps into the wad directory, but that requires significantly more code change in g_game.c than the tweak I came up with, so I am quite happy with it the way it is :) -------------------------------------------------------------------------------- 11/08/09 Unicode input should be supported from ANY key that sends a character within the ASCII range, not just such keys which also have SDL keysym codes in that same range. Adding this tweak allows typing numbers with the numeric keypad so long as the Num Lock key is turned off. This change/fix was requested by SoM ;) Seems GCC 4.4.2 has added a strndup routine, which causes a conflict with libConfuse. I renamed libConfuse's routine to cfg_strndup to avoid this. -------------------------------------------------------------------------------- 11/07/09 Essel found that the codepointers A_FadeIn, A_FadeOut, and A_SetTranslucent were broken due to the argument evaluation rewrite - I accidentally used E_ArgAsInt where I needed to use E_ArgAsFixed, having forgotten that these codepointers accepted floating-point argument values to represent alpha levels. -------------------------------------------------------------------------------- 11/05/09 I reformatted mmus2mid.c in the SDL directory after noticing that it was still a mess from hell. It probably still is even with my changes, but at least it is readable now. -------------------------------------------------------------------------------- 11/04/09 I have migrated many of Eternity's low-level options to system.cfg so that they are now universal amongst all supported games, meaning that they do not have to be set individually for each one. There may be other options which would be best stored here, and I will continue to evaluate all of the settings for the best location in which to put them. I got around to programming a toString method handler function for metadouble objects. I also added an "isinit" field into the metatype_t structure, which allowed me to eliminate a couple dozen checks in the source code that were using "firsttime" guard booleans in order to ensure that metatypes were only initialized once. As a result of that change, non-singleton metatypes are now be treated as an error in MetaRegisterType. SoM fixed slopes so that they light uniformly in all fields of view. -------------------------------------------------------------------------------- 11/03/09 I made the I_Sleep call on video mode sets exclusive to fullscreen, since it was bothering SoM in windowed mode. -------------------------------------------------------------------------------- 11/01/09 I finally got rid of that ridiculous extraneous "eternity" directory inside of our SVN trunk, without managing to screw up the entire repo (I will note it did cause the untimely death of my principal working copy, however :P ) Took the opportunity created by this change to create tags for all of Eternity's releases that have occurred since the SVN repository was established. -------------------------------------------------------------------------------- 10/31/09 Using calloc on vertexes array loaded from the map allows me to get rid of some useless assignments to zero in the dynaseg code when copying vertices from linedefs into dynasegs. I have wiped out all remaining traces of seg_t::angle, which is never used in Cardboard, and a corresponding R_PointToAngle2 call in the dynaseg code which was now a total waste of CPU cycles. The skin viewer now has additional safety code when remapping sprites, due to a bug Kate was able to trigger with an odd barrel skin which caused the skin viewer to begin showing graphics from all over memory before crashing the game. Woops! -------------------------------------------------------------------------------- 10/30/09 Kate seems to believe the crash has to do with the conversion of floats to integers in R_AddLine. Initial testing with a bandaid patch indicates that the crash is indeed stemming from here. Seems conversion of out-of-range floats to integers has undefined results. Once SoM came back, he figured out the problem definitively and worked out the best way to fix it :) No more crashes! I made a minor possible fix to the dynaseg system that will hopefully fix the recently observed problem of automap rendering continuing beyond them. Basically, the backsector of the dynamic seg should not be set to a sector unless the dynamic seg's parent linedef is actually two-sided (it really shouldn't be, but people have found ways to get away with 2S polyobjects in some circumstances ;) -------------------------------------------------------------------------------- 10/29/09 3DMidTex movers have been broken for a very long time evidently, as I missed a break statement in P_ChangeSector3D which caused it to fall through into the default case and malfunction. Eternity has developed a new extremely random and difficult-to-trigger crashing error somewhere in the renderer in the neighborhood of R_RenderSegLoop. Time to call up SoM ;) -------------------------------------------------------------------------------- 10/27/09 Inspired by Chocolate Doom, I added a -noframe command line parameter and a matching "n" flag character for geom resolution-setting strings that allows the creation of Eternity's main graphics window without a window border. Note that frameless windows cannot be moved, at least not in Windows XP. Example of use: eternity -geom 1024x768wn -------------------------------------------------------------------------------- 10/25/09 I decided to finally bite the bullet and revamp portions of Eternity's low-level input system so that we can support the smart Unicode mapping provided by SDL which properly reflects international keyboards. This mapping must be enabled by the end user. The changes made to allow this also allowed me to instantly add support for binding to the numeric keypad and the delete key, as the DOSisms that were holding these features back have either been eliminated entirely or confined to processing of events within the proper ASCII range when using the original shiftxform keyboard mapping. Pipes can also now be typed into the console, even when using the shiftxform mapping. We may never know exactly what prompted the infamous "Oh my GOD does Watcom suck!" comment in hu_stuff.c, but it's pretty irrelevant now, seeing how we have never supported compilation on Watcom ;) -------------------------------------------------------------------------------- 10/24/09 Now that Eternity has sector flags, I removed my previously added wassecret field from sector_t and changed it into a SIF_WASSECRET internal sector flag value. No use having an entire boolean do the job of a single bit! By user request, I have modified the behavior of the BOOM "ammo" cheat so that it gives max ammo if the user is currently not at max, and removes the ammo otherwise. The behavior in BOOM was to take away the ammo if you had any at all, which was obviously somewhat confusing and less useful. -------------------------------------------------------------------------------- 10/23/09 Integration of the new argument evaluation system has been completed, along with a change in the way that EDF keywords are stored and evaluated, and the rewrite of ALL parameterized codepointers to support the new system (this was NOT a trivial undertaking either...) Individual codepointers will require testing to verify that I have not broken anything, as I most certainly have, since it was 4:30 am by the time I finished this. -------------------------------------------------------------------------------- 10/22/09 I have begun work on converting EDF to a runtime evaluation model for the arguments to parameterized codepointers, which will be necessary to properly support some of the advanced features of DECORATE states. This also simultaneously solves Eternity's problem of having a limited number of arguments per state. The argument evaluation engine provides evaluator functions for various data types including int, fixed, double, thing types, states, EDF string objects, etc. Note that there is not currently any support for expressions, but such support should be simple to add once the Aeon scripting system is in place (note that such expressions will then need to be valid ECMAScript, rather than a bespoke expression language like the one currently used by ZDoom). -------------------------------------------------------------------------------- 10/16/09 I added an I_Sleep call to video mode setting to allow the screen to settle when the engine changes into a fullscreen video mode. Out-of-bounds palette changes in ST_Ticker are no longer performed, and P_DamageMobj will no longer allow mobj_t damagecounts to become negative. These together were the cause of the undefined behavior exhibited in vanilla Doom when doing negative damage to the player via DeHackEd patches. This instead crashes in Eternity and other modern ports without these modifications. I also took time to add entryway's new emulation code for the undefined behavior exhibited by donut linedef actions which have no valid model sector. Under vanilla Doom they infact read the target movement height from the interrupt vector as it is stored at memory offset 0. Why does DOS4GW not catch those invalid accesses? I have never figured out why it sucked so badly as a DPMI provider. Of course if it had worked even half-way properly, DOOM would have almost certainly missed its release date by a couple of months ;) -------------------------------------------------------------------------------- 10/12/09 EDF damagefactors are now implemented, using the new multi-valued property syntax. This allows monsters to take different amounts of damage from different types of attacks. Added a new kind of routine to the metatable - MetaSetDouble. This routine will add the field to the metatable if it doesn't exist already, but if it does, it instead changes the value of the existing metadouble object to the new provided value. This is very useful, and I will be adding matching routines for the other basic data types as they are needed. -------------------------------------------------------------------------------- 10/06/09 Added a couple of methods to the qstring pseudoclass: M_QStrReplace M_QStrReplaceNotOf These allow replacement of specific characters inside a qstring with other characters. I have noticed this operation being carried out on some qstrings, so I'll need to find those and replace them with calls to these nicer functions. -------------------------------------------------------------------------------- 10/03/09 I have added separating header comments to distinct sections in d_main.c to outline the different regions of functionality. This module, along with several others in the source code, has become too large and will probably be split up in the future. To my dismay, after essel pointed out some mysterious polyobject issues, I found that I completely failed to define any values for the polyobject flags added previously. This was causing massive malfunctions throughout the entire polyobject system, not limited to the constant addition of more and more dynasegs to the subsector dynaseg lists until the game was running at a grand 1 FPS or less. Woops! -------------------------------------------------------------------------------- 10/01/09 The IWAD picker was firing up when the -game parameter was in use, which prevented the use of normal IWAD searchinig inside of the specified base/game directory. Fixed by turning off the IWAD picker under this circumstance. -------------------------------------------------------------------------------- 09/29/09 I removed A_Look recursion detection entirely because it is too difficult to do in a way that will retain compatibility (Lost Souls can theoretically recurse through A_Look to any possible depth when colliding with something, although due to the way the engine works it typically only recurses 1 or 2 times). However, outside of playing old demos, EE will no longer allow Lost Souls to do this. They will now call the function P_SetMobjStateNF, which does not call the state's action routine, when resetting to their spawnstate upon a collision. This prevents recursion through the non-reentrant P_Move codepath by SKULLFLY objects. The soul will still call A_Look upon its next state transition, so at most it might simply sit there for a couple of tics. -------------------------------------------------------------------------------- 09/28/09 After the rewrite of damagetype pain and death states to utilize the new metastate maintenance code (which stores states into the mobjinfo metatable), several functions were reduced to single lines of code. I eliminated these unnecessary middle-man functions and replaced them with direct calls to the metastate functions. Overall the code still didn't get smaller than it was originally, but the dividends will pay off when metastate management is employed for DECORATE state support. -------------------------------------------------------------------------------- 09/27/09 I had to make an accidental megacommit after the finding of yet another serious issue: 1. I have added the ability to parse "multi-valued properties" to libConfuse. These are properties in this form: field [=] [, ]* The equal sign is optional, as per yesterday's extension, and the list of values is managed by an independent cfg_opt_t array, which functions the same way internally as a libConfuse section. CFG_MVPROP items are basically identical to CFG_SEC items, except that they cannot have titles, may only contain basic options (no sections or lists), and the items must be present in the same order specified in the MVPROP's cfg_opt_t. This matches syntax used by DECORATE for items such as damagefactors. 2. Started addition of meta damagefactors, but this has stalled out for the time being while I worked on other problems. 3. I broke down and reassigned the ownership of metaobject keys to the metaobjects themselves, due to persistant problems with the copying of keys between objects when copying the metatable. My initial design was made under the assumption that metaobject keys would largely be static strings, and that dynamically allocated ones would be the exception. It is increasingly obvious that dynamically allocated key strings are going to be the rule after all, since so many of the features I want to use the metatable for rely on names generated via concatenation of strings derived from EDF definitions which may have arbitrary length. 4. I added another incredibly powerful C++-like mechanism to the metatype system: a toString method. If not defined, the default metatype::toString method prints out a hex dump representation of the object. Otherwise, the toString method may be overridden by passing a function to MetaRegisterTypeEx and it will be called for objects of that type. Metaobjects without a registered metatype will not be printed; instead a message is given that the object is not a registered metatype object. This was added to support the new e_dumpmeta command, which allows me to look at an mobjinfo's metatable in the console. This is a pretty critical thing to have for debugging new metatable-reliant EDF features, which are going to be popping up like weeds for a good while now. 5. Aaaand finally, as alluded to above, a new extremely serious issue abruptly appeared while I was trying to work on the metatable. EE started crashing during P_SetupLevel on Heretic E1M3 with approximately 10% reliability. The crash initially only seemed to work in the release build, so I was forced to try to reconstruct the call stack from the crash reporter output, and I found something extremely disturbing: The game was crashing in P_UpdateThinker. That such reliable, "finished" code that hasn't changed for years would suddenly manifest a segmentation violation was very troubling to me, so I wasn't about to give up on trying to find the root cause of this. I finally got the bug to occur in the debug build by idclev'ing between E1M2 and E1M3 repeatedly, and captured the crash in the debugger, in the exact same locale it had crashed before - P_UpdateThinker as called for the addition of a "strobe light" thinker for a particular sector. For *some strange reason*, it turned out that this strobe light thinker had the function P_MobjThinker in its thinker->function field. Why? Because it turns out that none of the thinker classes were initialized before being sent to P_UpdateThinker. This wasn't a problem before EE, but became such because of the addition of the PrBoom fix to MBF's thinkerclass list corruption bug, which has to test the value of thinker->function. How this managed to survive so long is troubling, but even more troubling is why the Windows debug heap was not doing its job. When memory is freed in a Windows debug program, the system contractually guarantees you that the memory will be overwritten with the value 0xDEADBEEF before being reused. This did not happen, however. Instead, an mobj_t's memory block freed during Z_FreeTags from the previous level was handed back to me during the request for a strobe light thinker. Because both structures have the thinker->function field at the exact same offset, this allowed a "perfect storm" bug to occur that would otherwise be impossible. While I am glad that this enabled me to find the problem, which has been fixed by changing all thinkers to use Z_Calloc instead of Z_Malloc, I am not pleased in learning that I cannot count on the protections afforded by use of the Windows debug heap. -------------------------------------------------------------------------------- 09/26/09 I have introduced a relaxation into the libConfuse grammar/state machine which makes equals signs optional by simply proceeding to the "expect value" state without reading a new token when the token just read is not an '='. This makes EDF a bit more DECORATE-ish in that it now has less unnecessary yet mandatory syntactic sugar. -------------------------------------------------------------------------------- 09/25/09 I defined some additional new flags4 bits: * NODAMAGE prevents objects from taking damage from normal sources, although they still behave as if they take the damage, including being thrust and entering their painstate. I am told that in ZDoom this is completely unconditional, but I have made it inapplicable to telefrag-level damage in EE so that nuke, mdk, and telefragging can still destroy such objects. * LOOKALLAROUND causes a monster to be able to see targets 360 degrees around it in the same manner as AMBUSH monsters after their sectors' soundtargets have been activated. Normal monsters only have a 180 degree field of vision. -------------------------------------------------------------------------------- 09/23/09 Added new thingtype properties respawntime and respawnchance, matching ZDoom, to allow fine-tuned control of Nightmare (or ALWAYSRESPAWN) respawn behavior. Respawn time is in tics, and is the minimum amount of time that a thing must stay still in its death state before it can get a chance to respawn. Respawn chance is a number from 0 to 255 (ideally, at least) representing a chance similar to the pain chance. If a random number is less than respawnchance, then the object will respawn provided that it can fit at the location at which it wants to respawn. Using 0 would mean that it never respawns, whereas using 256 or anything higher would mean that it will always respawn as soon as it gets the first chance. Defaults are 12*35 tics, and 4, respectively. Modified P_RadiusAttack to make it reentrant outside of old demos by adding a bombdata_t structure which is "pushed" and "popped" via the incrementing or decrementing of a pointer over a fixed-size array of objects. The static limit is introduced in order to eliminate the possibility of stack faults when recursive explosions occur. The limit is currently 128, which is actually a lot lower than what can be theoretically allowed, but which is already a very lenient number considering the number of barrels this implies going off in a single event. While in p_map.c I took the long-neglected opportunity to fix blood effects for crushers while the particle system is enabled, by getting rid of the code to draw a particle effect altogether. The effects we have don't even come close to matching the blood spray which is caused by crushers, so we'll just draw blood sprites here unconditionally, for now at least. -------------------------------------------------------------------------------- 09/22/09 I refactored the mess that was P_HitFriend to de-Killoughify it (in other words, to eliminate a single-expression function with tons of side effects in every branch). I then added a check in this function that makes it return false if the object in the way has the NOFRIENDDMG flag, since such objects won't take damage if the caller continues to fire. -------------------------------------------------------------------------------- 09/21/09 Added new flags4 bits NORADIUSDMG and FORCERADIUSDMG (matching ZDoom) to allow more control over explosions. Corrected behavior of the NOFRIENDDMG flag so that objects can still cause damage to themselves if they have this flag. Also tweaked the behavior of the SUPERFRIEND flag so that superfriend objects can *never* acquire friends as attack targets at all, since the checks in A_Chase are evidently insufficient to prevent retaliation in some odd cases. The BOSSIGNORE flag is now officially deprecated, in anticipation of addition of fine-tunable infighting control via the mobjinfo metatable. Do not use this flag, and if you have already used it in an in-progress mod, phase it out now. -------------------------------------------------------------------------------- 09/19/09 The crash report app will no longer be executed for stack faults, since the stack is still trashed during execution of the exception routine. Somehow there is enough space to execute writing of the log file, but not enough for the CreateProcess routine, which apparently generates an exceptionally deep call stack. In case you wonder why EE would have a stack fault, I have been experimenting with the P_RadiusAttack code after finding out that it is both non-reentrant, and can be forced to recurse to an arbitrary depth simply by modifying barrels to call A_Explode during their first death frame. Also added a new A_GenRefire codepointer for Kate, which allows customization of refiring behavior exhibited by monsters like the chaingunner and Spiderdemon. -------------------------------------------------------------------------------- 09/16/09 Defined a new GameModeInfo flag, GIF_SKILL5RESPAWN, which controls whether or not a gamemode's fifth skill level has -respawn behavior enabled by default. This flag is now given to all DOOM gamemodes, but not to Heretic, so that Black Plague skill level no longer has respawning monsters, as expected. Do note that at no point had I forgotten about this - it's been on my 3-mile-long TODO list for an age and half ;) Added another flag, GIF_SKILL5WARNING, which controls the presence of the warning message given when starting a game on skill level 5. Only DOOM games give this message, as apparently Raven felt their games were more fair (I would beg to differ, however, given how much I suck at Black Plague in Heretic despite owning much face in Smite-meister). -------------------------------------------------------------------------------- 09/15/09 I have removed the console-menu interlock and made some fixes that enable the menus to operate over the console with absolute priority, after the scope of problems caused by the interlock was revealed to me by some users. This stuff has been a nagging problem since SMMU, so hopefully it is fixed now. -------------------------------------------------------------------------------- 09/13/09 Adjustments for Catoptromancy: 1. The typedef for ehash_t has to be placed before the ECompFunc_t typedef because apparently GCC cannot understand that "struct foo *" as a function pointer parameter type is not a declaration of the structure type but is just an incomplete type. I don't *think* this is correct behavior out of the compiler, but it wouldn't be the first time I was wrong either. C seems to be getting harder to write every few months... 2. z_zone.h needs to be made visible through metaapi.h due to use of size_t. 3. The temporary TestDSParser function had to be changed from static to extern because apparently you also cannot forward prototype a static function inside a local scope block (this doesn't sound right either but who am I to argue with a bunch of neckbeards). After all that unnecessary annoyance was out of the way, I also found time to work on new features: The flags4 field is now available. After adding an R_TranslationNumForName routine and cleaning up some EDF code to use it, I defined the first new flag for this field, MF4_AUTOTRANSLATE. This flag will kick in if an object using it is spawned in a non-DOOM gamemode. The thing will then have its translation (if it does not have a valid one already, anyway) changed to the gamemode's default palette-conversion translation (for Heretic, this is the TR_DINH lump provided in eternity.wad). This flag has been given to the MBF helper dog, and lets me avoid translating its sprites into the Heretic palette by hand. This flag is only useful for sprites that are in the DOOM palette, and thus may not find a lot of end-user application. I added a double floating-point specialization for metaobjects to the metaapi preemptively, and after observing ZDoom's code a little more closely (note that I did NOT use its implementation as a reference while creating EE's metatable), I made an important alteration to the specialization MetaGet* routines that causes them to take a default value as a parameter. If the metatable does not contain that field, then the default value is returned, instead of the previous behavior of returning 0. metaerrno is still set to META_ERR_NOSUCHOBJECT when this happens, however, in order to enable testing of this if and where it may be needed. -------------------------------------------------------------------------------- 09/11/09 I have added support for the ZDoom 9303 Polyobject spawn spot, which enables polyobjects that do damage simply by touching an object rather than by requiring it to be stuck (ie, crushing damage). -------------------------------------------------------------------------------- 09/10/09 Turns out the oh-so-wonderfully-explicit documentation, if you can call it documentation, of the DECORATE states format that I got from the ZDoom wiki was incomplete in some very important ways. Chiefly, it turns out that consecutive labels are not only allowed, but actually important in some ways. So apparently I will now have to throw labels onto a stack of sorts until I see a state, and then create metastates for that first state for each label that I have put on the stack. A little bit more complicated but certainly nothing I cannot handle. It just would have been nice to know that this was possible before I assumed that it wasn't and ended up having to rewrite a bunch of code and restring portions of my state table. The other feature it so kindly skipped over mentioning was the namespace operator, which is apparently only used for goto targeting of super-class states where the child class has overridden the named state (as this is unnecessary otherwise, since the child class has inherited all the metastates from its parent type already). This required addition of another state to the lexer, since the decision of whether a : is just a : or a :: must be deferred until the next character has been seen. I have slightly modified the way that metatable object copying is carried out through the metatype system in order to reassign responsibility for the copying of the key from the source object to the destination object to the copy method of the metatype. This enables us to get around what would otherwise be an intractible issue for metaobjects with dynamically allocated key strings. I realized this problem while creating the metastate type earlier, but had to give it a lot of thought. -------------------------------------------------------------------------------- 09/09/09 I added a case-sensitive specialization of the ehash_t in order to support a new independent by-type hash within metatables, to fully support hashing and lookups by either field name or type with full efficiency. This did necessitate the creation of an independent metatable_t type, though, which now consists of two ehash_t's - one fixed in size for types, and the other growable for field names. -------------------------------------------------------------------------------- 09/08/09 Custom damagetype pain and death states have now been converted into metaproperties, with the addition of code which will manage the addition and removal of metastates (metaobject wrappers for state_t) to/from mobjinfo. -------------------------------------------------------------------------------- 09/07/09 An initial design of error handling for the DECORATE parser is in place. It will currently always attempt to keep parsing, usually by discarding the remainder of the current line and returning to an appropriate state such as EXPECTLABEL or EXPECTKWORSTATE. We will see how practical this turns out once real-life examples are being turned into state lists. -------------------------------------------------------------------------------- 09/06/09 The DECORATE state parser has now passed its first successful dry run after some minor modifications. -------------------------------------------------------------------------------- 09/04/09 The DECORATE state parser's core loop is now functional, so I am prepared to give it its first dry run. I'm confident that many problems will be revealed, such is the nature of these things. -------------------------------------------------------------------------------- 09/01/09 I had to tweak my fix to the SWITCHES problem a bit - the lump has to actually be named SWITCHES before I can decide whether or not it is a SWITCHES lump. I sort of forgot that the hash chain could have other lumps on it as well ;) I have had to disable particles in low detail mode until the root cause of their bizarre undefined behaviors is rooted out. Any attempts to modify the way they work cause the game to crash hard currently. I also have no idea where exactly the particle system is getting its clipping information from. To me, it seems that it is completely incorrect. An overhaul is apparently overdue. Because they seem to be referenced after return-of-call, and because very large arrays shouldn't be on the stack anyway, I have moved the clipping arrays outside of the R_DrawSprite-style functions and made them into static globals. -------------------------------------------------------------------------------- 08/30/09 I have made an experimental change to R_AddLine to fix a weird Cardboard incompatibility with fiffy5.wad which causes a gigantic HOM in the first room. Seems that DOOM treats at least SOME closed self-referencing lines as solid, so I remove the second side of the line for rendering purposes, in order to force it to be treated like a 1S line for rendering. This smacks of a hack, but to implement it lower down might be messy and a lot more dangerous. Console netcommand variables can now correctly be saved to the configuration file and modified via the menu again. I have changed the way that sky is handled in the engine by creating an internal sector flags field, and creating a handler function that must be called to safely change a sector's ceiling pic. Any time that pic is changed to or from sky, the SIF_SKY flag will be set or cleared on the sector. With this fix, I have finally rewritten and cleaned up the old Hexen lightning engine so that it is savegame safe (lightning strikes are saved and restored properly), and so that it affects ALL sky sectors, not just sectors that had sky at the start of the level. I added some new console commands that can enable lightning and force a lightning strike in order to easily test this code without having to make a dummy EMAPINFO lump. -------------------------------------------------------------------------------- 08/29/09 The use_doom_config variable will also now remap the path to the keys.csc file, which is considered part of the configuration. This was an oversight in the earlier implementation of this feature - one which I noticed a while ago but put off fixing ;) I had to manually repair the VC++ 6.0 project file because I somehow dragged the P_ folder into the M_ folder 9_9 A round of compatibility fixes have been implemented in order to fix some interesting problems in the difficult-to-support spcial1b.wad by Jens Hykkelbjerg, which was a special effects tutorial level. This required a major modification to the BOOM SWITCHES code to cause it to walk down the wad lump hash chain for "SWITCHES" lumps until it finds one that looks valid. This problem was necessitated by spcial1b containing a patch named "SWITCHES". This also required addition of a new compatibility variable, comp_special, to allow toggling of the BOOM change to the behavior of one-time-use line specials at runtime, instead of having it be solely contingent on demo_compatibility. Turns out spcial1b actually exploits the use of a one-time-use gun action line that is tagged to a non-existent sector to enable a blastable shield switch over a switch that is deeper inside. With the BOOM bug fix active, it becomes impossible to activate either switch. With these tweaks, EE has restored 100% support for spcial1b.wad, and is to my knowledge one of the only source ports, along with Choco Doom, that can claim that currently. This thing is a true litmus test for compatibility, and it's pretty amazing IMO that Cardboard is able to replicate all of the special effects with no problems. -------------------------------------------------------------------------------- 08/26/09 Modified the DECORATE state parser to elimiate the difference between "text" and "quoted string" token types, as either can be accepted in any location. This is mainly important for allowing frame strings to contain [\] characters, as when they do, they are required to be contained inside quotation marks. -------------------------------------------------------------------------------- 08/25/09 Added the ability to set the menu background flat and a selection box in which flats can be picked. Catoptromancy pointed out that the old problem of snd_card/mus_card being set to 0 on SDL_mixer initialization failure was still acting up, particularly on Linux, so I have eliminated that behavior entirely. nosfxparm or nomusicparm are now set instead, to cause the game to act as if though -nosfx or -nomusic have been used. Menu and credit screen backgrounds, as well as the console backgroudn, can now be overridden in missioninfo structures in order to give HacX appropriate defaults. Began a new massive round of GCC warning fixes. That thing is utterly impossible to please. -------------------------------------------------------------------------------- 08/23/09 The EDF correct_height field will now be removed from certain classes of thing types when those types are modified by DeHackEd patches, in order to improve the default presentation of multiple wads, including HacX and Aliens TC, which put previously grounded objects on the ceiling using the SPAWNCEILING flag. It was always possible to avoid this by turning on comp_theights, but you won't know it's a problem until you see things hanging in midair. Added an overlooked and sorely needed M_QStrCaseCmp routine to clean up some dodginess in the DECORATE state parser. Added a "runiswalk" configuration and console variable by popular demand that makes the shift key cause you to walk if autorun is enabled. Personally, I can't stand this, since I often hold down shift unnecessarily out of years of ingrained habit, but some people swear by it. Menu help and error messages on the bottom will now be centered, because it looks much better. -------------------------------------------------------------------------------- 08/22/09 A skeletal outline of the DECORATE state parser is now in place, with complete state transition logic (that is to say, the functions will soon be capable of doing a "dry run" on a string so that I can watch the state machine run through the motions without anything important such as state generation happening). ZONE_NATIVE and HAVE_SCHED_SETAFFINITY have been added to the Linux makefiles by user request, so that users no longer have to enable these settings after doing a SVN checkout. If either of them prove to be a problem, users will now need to disable them, but I don't anticipate this. I found an unnecessary conversion of int to float for purposes of doing a comparison against the viewwidth in the core loop of R_DrawMaskedColumn which was causing some major register motion in the generated assembly. Eliminating this provided a small boost to sprite rendering, adding approximately 3 or 4 sprites before a noticeable dip in FPS occurs due to overdraw. -------------------------------------------------------------------------------- 08/20/09 Metatypes are now registered for provided metaobject specializations such as metaint and metastring. I also did an audit of the source for "firsttime" guard booleans that were missing their "static" keyword, which is the only thing that makes them work in the first place, but is painfully easy to forget. While testing HacX 1.2 I also discovered the consequences of an ancient MBF bug relating to support of DEHACKED lumps in WAD files - \r characters must be manually skipped over when reading in DEH-style string values, or the count of characters is messed up completely, causing none of the multiline string matches to work properly. The reason this only matters for deh-in-wad support is, obviously, the fact that WAD file i/o is actually binary, no matter how much the DWFILE system wants to pretend that it is emulating a FILE pointer. Stripping \r's in the DWFILE system is neither practical nor particularly safe, so it is better to have any concerned parsers simply skip over that character. -------------------------------------------------------------------------------- 08/19/09 I have begun work on adding native support for the new HacX 1.2 stand-alone IWAD as a gamemission under the DOOM II gamemode (similar to Final Doom). -------------------------------------------------------------------------------- 08/18/09 The metatype registry has been completed with addition of the supporting E_HashTableIterator, MetaRegisterType(Ex), and MetaCopyTable routines. It works like functional magic, and is almost scary ;) I have converted nukespecials into a native property of mobjinfo, since I see no current value in making them a metaproperty. -------------------------------------------------------------------------------- 08/17/09 Began integration of the metatable with mobjinfo. -fast speedsets are the first code to be rewritten to use them. This rewrite however has revealed the need for a metatable copying mechanism, in order to achieve the desired streamlining of mobjinfo inheritance that was envisioned during my initial conception of the metatable. The only way I can see of enabling objects in the metatable to be copied through a single routine is to establish a secondary cache of type information, which I will call the metatype table. This will be a global hash (a metatable itself, in fact), and types will be registered with it one time each, before the first object of that type is added to any metatable. Only objects with a registered metatype will be capable of being copied between tables in this automated manner. If designed properly, this should approach the power of copy constructors in C++. -------------------------------------------------------------------------------- 08/09/09 I made a long-requested tweak to the A_MissileAttack parameterized codepointer that enables the function to call P_SpawnMissileAngle when the thing does not have a valid target. Missiles will simply be fired from the thing's direction plus or minus the provided offset in this instance. Another critical long-existing bug was uncovered by use of the native heap - player mobj pointers are left dangling after Z_FreeTags, and this could cause a random crash in the sound code. -------------------------------------------------------------------------------- 08/04/09 Building further on top of the generic hash, I have written the previously planned metatable API which will enable EE to associate arbitrary information with particular instances of structures such as mobjinfo without having to add each object as a native structure field. It is already possible to make use of the metatables by converting over certain problematic, pre-existing EDF features such as damagetype states, nukespecs, and fastspeeds to use this instead of their individual list or queue data structures. It will additionally almost certainly prove useful in the implementation of UDMF, and in its subsequent exposure via the Aeon API. A metatable is just an ehash_t which has been sent into MetaInit, initializing it as a case-insensitive string hash which functions on metaobject_t structures. A metaobject_t structure is an mdllistitem_t descendant which additionally provides RTTI and an object pointer which may be either self-referential, or may point to a different address in the case of metaobject_t's which are not contained as the first item in a larger structure, or are not in fact contained within the structure they link to at all. Specializations of metaobject_t are provided for integers and strings as metaint_t and metastring_t. Creating these objects through their respective APIs lets the memory management of these otherwise intrinsic data types become more automated, and the manipulation of such fields is easier. Again, as with the underlying hash table class, specializations can be provided to store any type of structure or data type in the metatable. But unlike the hash by itself, the RTTI and higher-level genericity of the metatable allow objects of multiple types to be in the same table at the same time. RTTI for metaobjects is implemented with string comparison. Types are passed to relevant functions using the METATYPE macro, which simply utilizes the C preprocessor's "stringize" operator, #. An example of basic metatable usage follows: MetaInit(info->meta); MetaAddInt(info->meta, "foo", 10); ... int foo = MetaGetInt(info->meta, "foo"); This is just illustrative, and very basic. It is capable of a lot more, and there are several different ways in which it can be used. -------------------------------------------------------------------------------- 08/02/09 I have completed an awesomely powerful generic hash data structure, previously created for the Experimental Rudimentary Actionscripting system which was abandoned in preference to forging ahead with Aeon based on ECMAScript. This hash table is built on top of the genericity provided by mdllistitem_t, giving it chains which are double-linked lists with **prev pointers, like the majority of EE's currently innumerable private hash implementations that it will eventually replace. Any type of object can be stored inside it via use of callback functions registered with the hash table which retrieve the key, object, and link pointers and return them as void *. Specializations are provided for objects keyed to integers, unsigned integers, and strings. Any other possible specialization imaginable is possible, but those three are all that I can see us needing in the future. The second Two-Week-Bug-style problem in the last two months has suddenly come out of the woodwork. This time it turned out that mobjinfo and states have never been initialized to zero after being allocated. Almost all structs in EE are now allocated using calloc, but these were still using Z_Malloc directly. This suddenly caused E_DisposeDamageTypes to access 0xBAADF00D, the value that the Win32 heap fills freshly allocated memory with. I guess that until now the values in this location were always coincidentally set to zero somehow. I really REALLY hate this kind of stuff, and I hope that it will be the last such error for quite some time. I am glad, however, that this stuff is exploding all over me during development, and not waiting to spring on our users after the next release. It is a pleasant change of pace, I must say :P This is at least in part thanks to our direct use of the Win32 heap, and more importantly, our previous change to eliminate use of the SDLmain library, which allows us to use the the Debug Multithreaded runtime library, which has a heap checking system which puts the one implemented in z_zone to utter shame. -------------------------------------------------------------------------------- 08/01/09 64-bit portability work continues with elimination of almost all instances of the "long" data type in preference to "int" or "int32_t" where appropriate. Exceptions have had to be made in the Small AMX and in the implementation of opendir for Visual C++. The former is not going to be portable to 64-bit, as I have positively identified it writing function pointers into integers, and the latter is meant to return a "long" in order to be POSIX-compliant. Let us hope it doesn't matter ;) Yet another round of GCC warning fixes have been implemented, this time thanks to hobbs. According to CSonicGo, EE has now compiled for the first time under GCC with no meaningful warnings (a few remain about unused functions, but these are being generated by currently unfinished features such as ExtraData sectors, EDF inventory, and the DECORATE states processor...). -------------------------------------------------------------------------------- 07/30/09 - 07/31/09 After severe problems with pstdint.h on GCC (GCC has non-ISO-compliant redundant declarations of inttypes.h types in its sys/types.h file.....), I have been forced to remove that file in preference for a Visual C++-specific stdint.h and inttypes.h. On GCC, we will use the normal inttypes.h which is always available now. However, thanks to the morons in SDL, I must now globally disable VC++ warning 4142, "benign redefinition of type," which is caused by SDL_config_win32.h unconditionally defining ISO integer types with the same types as those used by inttypes.h. Libraries have no business defining standard library types. SDL should be setup to use proper intermediary types rather than defining the ISO names here, and at the very least, it should be possible to disable these by defining a symbol such as HAVE_STDINT_H. But no, that would be good design, and we can't have that! I have completed and committed the initial version of eecrashreport, which is an MFC application that will be launched via the CreateProcess API when Eternity crashes. This dialog app will read crashlog.txt and offer to copy and paste it into a new browser tab or window pointing to the Eternity forum on Doomworld. Do note that simply opening such a dialog from Eternity itself is considered off-limits. Opening dialogs from inside exception handlers is beyond bad practice into the realm of stuff you should never EVER do. Other port authors should take notice... -------------------------------------------------------------------------------- 07/28/09 More 64-bit portability changes, this time in the configuration file. I have rewritten the system entirely to be type-safe, so that string pointers are no longer forced into integer variables. Instead, defaults for various types, which now include support for float and boolean rather than just ints and strings, are all stored in separate variables within the default_t structure. To keep this clean, items are now defined in the defaults array using macros, in a system extremely similar (and in fact entirely redundant) to that used by libConfuse. -------------------------------------------------------------------------------- 07/26/09 "byte" has been changed from a typedef of unsigned char to a typedef of uint8_t. -------------------------------------------------------------------------------- 07/24/09 Began a massive round of changes which will hopefully bring us all the way to 64-bit portability. I have begun by adding a portable implementation of stdint.h so that we can transition to using size-safe integer types everywhere that this is needed. The first victims were the types fixed_t and angle_t, which have become typedefs for int32_t and uint32_t respectively. The latter is especially critical, because the Binary Angle Measure system relies on the behavior of 32-bit integers, but was defined previously as "unsigned long." On x64, long has been promoted to 64-bit, so this would immediately cause a number of severe game- breaking problems. The next victims were the Long64 / ULong64 custom typedefs, which were manually configured to resolve to various system-dependent 64-bit integer types on our supported platforms (__int64 or long long respectively). These two have been eliminated entirely in preference for the standard int64_t. -------------------------------------------------------------------------------- 07/23/09 An incredibly improbably-undetected error which has survived in the code for several years suddenly blew up Two-Week-Bug-style on me today when the skin code started to access a NULL pointer. What should it be other than the fact that the savegame code didn't initialize mo->info until after calling P_SetSkin, which uses the exact same field? I need somebody to explain to me how this never crashed until now, because it makes no sense 6_9 Finished integration of a proper structured exception handler for Windows, to replace the totally useless silent SDL parachute. Crash information is now dumped in to crashlog.txt in the application's directory using routines which are supposed to be safe to call while in an exception handler. -------------------------------------------------------------------------------- 07/22/09 Cleared out some dead code, tweaked an initialization problem in txt_gui.c found by yagisan's analysis in order to match the commit in Choco Doom, and finally, we now clear the channel id in the low-level SDL digital sound channel structs when a sound is stopped, so that the game engine will see an ID mismatch and will not attempt to further update that sound channel. This is just a safety measure, as I've seen nothing to really suggest that this actually causes a problem. I do however believe there is still a subtle problem somewhere in the sound engine, as I swear I am getting occasional phantom cutoffs. We'll see what happens. -------------------------------------------------------------------------------- 07/20/09 Analysis of the game while stress-testing the new native heap implementation revealed extreme allocator noise coming from P_SetPSprite. Found out I need to keep gunaction_t's on a freelist, so that they're not constantly being malloced and freed, sometimes several times per tic. yagisan sent me the output of a static code analyzer (like a special compiler, but it traces through your code and looks for logic errors instead of compiling it into a binary). This found a lot of iffy stuff which I have knocked out. -------------------------------------------------------------------------------- 07/18/09 After some misguided and unsuccessful attempts to stack a fast-fit system on top of the zone heap, I have decided to bite the bullet and provide an optional native heap implementation, which can be enabled by globally defining the symbol ZONE_NATIVE. This #if's out z_zone.c and compiles z_native.c instead. During normal play there is virtually no difference. The zone heap and Win32 heaps have similar overhead, believe it or not. But when the game is under stress, such as during nuts.wad, the difference is unbelievable. The native heap never dumps cachables unless a system out-of-memory event occurs, so there is no constant unloading and reloading of resources, and there is no unnecessary static limit on the amount of memory allocated with a single strategy. The plain fact of the matter is, BOOM's zone block purging stategy is crap, and its extreme-case behavior is pure O(N) garbage. It's a shame because the zone system would otherwise be sustainable. I may in the future do another attempt at a pure fast-fit heap, but as long as the system heap offers superior behavior, I question the need for any futher misadventure. I'd have to be pretty arrogant to believe that I could match the know-how and manpower that have gone into the heaps used by operating systems like Windows and Linux. After attempting to modify one myself, I have nothing but the utmost respect for the people who created and maintain that stuff. They must be geniuses. After a lot of fighting with GCC, it was discovered, again by Russell, that EE's global define values were NOT visible to modules in any directory except the main source directory. This was due to joe not coding any way for those defines to be propagated downward during the build process. This means I am now required to duplicate and maintain the list of global define symbols in every Makefile.am individually. What a bitch. -------------------------------------------------------------------------------- 07/17/09 After being frustrated with the obviously disproportionately bad performance on nuts.wad under a 16MB heap, I have been experimenting with the zone system. My initial idea was to code a load factor over which purgables would stop being dumped and the block list would not be searched, but rather the game would go immediately to using so-called "virtual" memory. This did offer a 2-3 FPS increase, but only once the heap was so saturated with static allocations that the speed of incoming allocations could completely overwhelm the savings offered by dumping cachables. If the rate of allocation could not exceed the rate of reclamation, then the system would see-saw around the load factor, and performance would plummet as usual. This heap stuff is exceptionally difficult. As a result of playing with this stuff, I found not one but TWO places from BOOM where an extra BLOCK_HEADER was not being subtracted from virtual_memory, the variable tracking the amount of virtual allocations for instrumentation purposes. This would cause the program to appear to have a gigantic memory leak, when in fact it was just some bad math. -------------------------------------------------------------------------------- 07/15/09 v_mode has been eliminated entirely. i_videomode now stores the user's video mode in the form of a geom string, and the menus have been recoded to present this string, and the option to set its current value as the default. To support this separate default setting required fixing a well-hidden bug in the console whose behavior I had previously noticed but could not explain. By default the console will not set the default value of a variable when changing its value unless the source of the command doing the setting is the console itself. However, the menu system has always set the command type to c_menu, and yet it was still setting the defaults, which is the expected behavior anyway. Well, the reason this worked was a happy accident. In the console code, the c_typed enumeration value was being compared against the wrong variable - cmdsrc instead of cmdtype. cmdsrc is the player who issued the command, whereas cmdtype represents the game system from which the command emanated. Because in a single player game cmdsrc is always 0, this caused it to always match the enumeration value c_typed - meaning that the entire console system only worked at all because of an ACCIDENT! Fixed by comparing against the proper value, but this in turn then required a change to the menu system - a new menu widget type is supported which sets the command type to c_menu, and default widget types set the command type to c_typed instead so that they cause default values to be set. Otherwise, no changes made via the menu system would stick. Tweaked I_ParseGeom to handle termination of the lexer while in STATE_HEIGHT. If parsing ended here, the height would be set to the default value and you would end up trying to set a strange video mode such as 1024x480. With SoM's completion of the automatic field-of-view adjustment, and my completion of the geom-based video mode setting, widescreen support is now finished. I have raised the rescap to its new value of 2560x1600, which we expect to be sufficient until the next generation of ATi cards is released ;) Turns out dynasegs need to attach to the sector of the subsector in which they reside, rather than referring to the sector of the original linedef's location. Not doing this apparently causes some odd side effects, but only in certain situations. -------------------------------------------------------------------------------- 07/13/09 After getting my butt whipped in a conversation with myk on DWF I fixed the behavior of the iwadhandle variable in EE's wad system so that it is only ever set to the FIRST IWAD to pass through W_AddFile, and not to every subsequent IWAD. This keeps things like loading DOOM over DOOM II working the way you would expect, rather than having DOOM II's maps mysteriously start to call themselves "New Level" even though they exist in the IWAD. This was indeed a bug, inherited from SMMU, but amplified by EE's further application of the feature. -------------------------------------------------------------------------------- 07/11/09 Empty-string filenames provided to the -file command will now be ignored, to help abate problems with Doom Builder and other utilities which can sometimes accidentally insert empty filenames into command lines when they invoke other programs. This is kind of a bug on their end, but it's also a design issue on ours, and so I think correcting it is fine. -------------------------------------------------------------------------------- 07/10/09 Thanks to Russell Rice for helping me eliminate further instances of undefined sprintf behavior in the console. I eliminated them in this case by employing qstring_t, which also simultaneously makes this code vastly more secure and robust. It's still a fuckin' mess though. Removed support for comments in console scripts, because they conflicted with the ability to use ; as a command separator and as a literal character inside strings. I then additionally repaired the keybinding save code to surround ; in quotation marks when it occurs as the name of a key. Due to these two problems together, it was impossible to have any action bound to ; to survive from one play session to the next. Added graceful handling of errors to I_ParseGeom, in preparation for making it Eternity's primary means of setting the screen resolution. Any error in parsing will cause the routine to set the resolution info to a reasonable default, which is 640x480w. Added a new deathmatch flag on a whim: INSTAGIB! Try using this in single player for an entirely new sort of challenge - the honest no-damage run. You could play DOOM in a no-damage run previously, but you had to watch your health very carefully. Sometimes it's easy to ignore minor damage in DOOM and not even realize it happened. With instagib, if you take damage, you die. After initial testing, I did remove instant death for NULL damage sources, however, since this makes it impossible to cross nukage sectors or survive minor fall damage, things that some maps require you to suffer in order for them to be playable. SoM noted that the Boss Brain object had accidentally been given a correct height field in EDF. EE's policy on adoption of the correct height data from the abandoned BOOM OVER_UNDER implementation was to apply it only to decorative objects - nothing shootable except barrels. As a result of this error, it was possible for your aim to become distracted by the Boss Brain object on DOOM II MAP30, and your rockets would strike the Baphomet in the face instead of going into his brain. Don't ask me how this went unnoticed for so long. I guess nobody has ever played MAP30 with comp_overunder off :/ -------------------------------------------------------------------------------- 07/07/09 The old legacy -vwidth / -vheight parameters needed to use MAX_SCREENWIDTH and MAX_SCREENHEIGHT for bounds checking rather than using hardcoded constants. -------------------------------------------------------------------------------- 07/06/09 Added long-overdue save and restore code for acsthinker_t. As a result I had to change the location of the call to ACS_RunDeferredScripts, because deferred scripts cannot run from G_DoLoadLevel when loading a savegame. This needs a serious fix when the level transfer crap is rewritten for hub support later. I changed the way that video.screens[4] is allocated. It is now a full-sized screen buffer allocated with Z_SysAlloc, even though only a status-bar-sized buffer is actually required. This is just the simplest and safest way to ensure that the buffer is the appropriate size. If we eliminate buffering of the status bar later, screens[4] can be eliminated entirely. This change helps open the way for the impending change to Eternity's resolution system that will enable widescreen support. Rescap raising has been undertaken: the new cap for testing purposes is 1280x800, which is the fullscreen resolution of my laptop. -------------------------------------------------------------------------------- 07/05/09 Added save and restore code for floorwaggle_t thinkers. -------------------------------------------------------------------------------- 07/03/09 - 07/04/09 Continuing the effort to move more data into GameModeInfo, I have defined a GIF_HASEXITSOUNDS flag, and broke up the quitsounds array and mapped it through GameModeInfo. Added a GIF_WOLFHACK flag, which indicates that the gamemode needs the DOOM II hack to check for the presence of secret levels. This is technically silly, but I am being rigorous about not branching on the value of GameModeInfo->id wherever it is practical to avoid it. Level exit rules, previously implemented as hard coded functions called through an array indexed by GameModeInfo->type, are now tablified into arrays of rules that function in a cascading manner. Each rule is checked until a match is found, and the last rule in the table is always a catch-all which determines the default exit destination behavior for that gamemode. The arrays are, of course, attached to GameModeInfo. Added a GIF_SETENDGAME flag and teleEndGameFinale field which control the behavior of the Teleport_EndGame special through GameModeInfo. Added a GIF_CLASSICMENUS flag which indicates support for the classic menu emulation feature. There is no current plan to support emulated menus for any gamemodes except DOOM-based ones, so this flag is considered part of the flags that define the "DOOM" game type. Fixed a bug as a result of testing this that resulted in the value of mn_classic_menus being ignored by the menu system until its value had changed at least once during runtime. Tablified finale defaults in the same manner as level exit rules, applying the same design of cascading rule sets. Fixed another bug: don't try to go to a non-existant E4M2 when exiting E4M1 in Heretic registered version. Dunno what was up with this, it was probably just a typo or an off-by-one error caused by the annoying fact that level numbers sent into the finale code are off-by-one (ROMERO!!!!!!!! >_<) Music selection routines are now mapped through GameModeInfo, though due to the complexity of music selection, these are not tablified but instead handled with a function pointer. The music selection methods are completely different for each gamemode, so trying to handle them with rulesets would be overly complex. The particle blood effect has yet again been significantly improved. The particles are smaller, do not accelerate on the x-y plane, spawn higher up, fall faster, are more voluminous, can be given greater positive z momentum, live longer, and most importantly, can use any color between the two normal blood colors if those colors are separated in the palette by fewer than 16 indices. -------------------------------------------------------------------------------- 07/02/09 I fixed the cast call caused in DOOM 2 by a call to Teleport_EndGame so that the cast call actually occurs ;) If you summon boss brain spots via the console, the list of boss brain spots will now be reinitialized, so that any already active cube spitters will begin spitting cubes to that spot. Previously, any such spots added would simply be ignored. I'll admit I mainly did this just so that I could see the Seven Portals fill up with 5000 DOOM monsters :) What's the point of writing this program if I'm not allowed to have fun? :P After worrying some more about the fact that all the special linedefs in Hexen seemed to give off switch sounds, even when this was totally inappropriate, I decided to find out what the deal was. Turns out this was actually a bug in Eternity in general, and a result of the change to R_TextureNumForName which allows the game to keep running in event of missing textures. Under the BOOM switches system, if a non-existant texture is resolved in the table, then any texture will start to match the entry for that switch, and thus a switch sound will be given off inappropriately. This was fixed by ignoring texture number 0 in the switch finding routine. I have begun another massive effort to remap static data in the executable through the GameModeInfo structure, and to eliminate as many uses of the gamemode and gamemission id's to branch or select behaviors directly. This starts with the breakup of the demostates table in d_main.c. Lee previously assembled this into one table, but with the way we do things now, it makes more sense to have one self-contained table per gamemode, and to select them by accessing GameModeInfo->demostates. I think it's actually a lot cleaner now, since the tables no longer have to be padded out with NULL pointers so that they're all the same length. -------------------------------------------------------------------------------- 07/01/09 I implemented script wait notification in the ACS interpreter, so that scripts waiting on other scripts can resume execution. Yet more Hexen areas have come to life. I also implemented a "puke" console command (in reference to the Hexen cheat code of the same name) which can run ACS levelscripts. This has proven useful, since missing linedef specials keep some of the more interesting scripts in Hexen from executing currently. Thing_SpawnNoFog and Teleport_EndGame are now implemented. -------------------------------------------------------------------------------- 06/30/09 I have added a system for specification of gamemode-dependent default overrides, which alter the values of defaults stored in the configuration file system. This enables Heretic to specify its proper default values for, amongst other things, automap and HUD widget colors. OPEN scripts in the ACS interpreter were being executed too early, leading to undefined behavior. Repaired by deferring the call until initialization of the virtual machine is complete. Floor_Waggle (Hexen line type 138, ED type 397) is now implemented. Added Thing_Spawn for ACS. Zombiemen now warp in all over Hexen maps. -------------------------------------------------------------------------------- 06/29/09 I finally got around to fixing one of my longest-standing pet peeves left over from SMMU, and that's the fact that the automap timer was attached to a redundant variable named levelTime, which is not saved in savegames, instead of using the normal leveltime variable that has always existed and is savegame and demo safe. levelTime no longer exists at all, as the automap was the only thing using it. -------------------------------------------------------------------------------- 06/27/09 I cleaned up a hack in the IWAD picker subsystem which was written to avoid a double-free due to two of the IWADs using the same titlescreen resource by creating a W_FreeDirectoryLumps routine in w_wad.c. This routine goes down the wad directory and frees all loaded lumps, in preparation for the destruction of a private directory. -------------------------------------------------------------------------------- 06/23/09 While looking over the zone heap I noticed that if a malloc or free occurs on a gametic ending with the LSB zero, the memory ends up getting memset to 0. This is exceptionally harmful for catching errors, as zero is the general default value for intialized pointers as well as most other variables and structures. I modified this by OR'ing 1 with gametic & 0xff, so that at least one bit is always set. It's still not fool-proof of course, but it's an improvement. -------------------------------------------------------------------------------- 06/21/09 I have added a "parent" field to mobjinfo_t which will permanently remember EDF thingtype inheritance, which will be necessary to support the virtual behavior of the A_Jump pointer defined in DECORATE. EE has never had any such concept of runtime inheritance behaviors, but with this addition they will now be possible. -------------------------------------------------------------------------------- 06/19/09 It are my birfday! I have defined a formal grammar for parsing DECORATE states, and have done additional work on the parser for them based on it. I have also modified EDF heredocs once again to require matching opening and closing delimiters (either @" "@ or @' '@ respectively). This was originally intended, and was to be documented as a requirement, but now it is a formal fact in the code as well. This enables heredocs to ignore only the specific type of delimiter with which they are started. -------------------------------------------------------------------------------- 06/18/09 states is now finally declared as an array of state_t *, so this opens the door for making states fully dynamic and allowing them to be declared outside of the root EDF, as most other EDF entities now function. This leaves thingtypes and sprites as the remaining critical definitions which are still runtime-static. -------------------------------------------------------------------------------- 06/17/09 Work continues on the DECORATE state parser. -------------------------------------------------------------------------------- 06/16/09 I added a call to the I_Sleep routine inside the dedicated screenwipe loop used when wipewait is set to "always" or "demos". This should make the screenwipe significantly more friendly toward fraps. As it was, fraps' recording would lag horribly during any wipe, regardless of the routine being used (though the melt wipe was by far the worst, as it's already a CPU muncher on its own). I have begun tenative work on DECORATE state parsing, laying out an enumeration based on my initial draw-up of the FSA required to parse them. This stuff is very likely to change as I get deeper into it, though. -------------------------------------------------------------------------------- 06/15/09 I have eliminated all uses of pointer math on the states array in further preparation for DECORATE states. All such statements like state - states, states + foo, etc. now either access states directly or use the new state->index field as is appropriate. Added static keywords to all private automap routines. Dave Taylor never used that keyword apparently ;) -------------------------------------------------------------------------------- 06/13/09 The Wu line drawer has been completed, with some modifications demonstrated to me by SoM - if sine and cosine lookups are used on the amount of error in the pixel and its inverse, for some interesting reason which probably has a deep geometric explanation that escapes my grasp, the antialiasing effect becomes significantly smoother and somewhat brighter than the normal linear treatment of these numbers used in the stock Wu algorithm. I have titled this modification the Wu-McGranahan line drawing algorithm, since I cannot find any literature or hits referring to it, though it seems certain somebody else would have thought of this before. TODO is making Wu antialiasing optional. The Bresenham line drawer is still present, since it must be used for special cases in Wu line drawing (horizontal, vertical, and perfectly diagonal all collapse to Bresenham), so it should be possible to use it directly, for those ultrapurists out there who object to having a better looking automap... -------------------------------------------------------------------------------- 06/12/09 There was a tornado warning, so I threw in a quick commit just in case my house ended up somewhere in Oz. I have started work on a Wu line drawing routine for the automap which uses the ZDoom-style translucency table rather than the traditional method of precalculated color ramps, which wouldn't work efficiently for EE since we allow customization of automap colors. I have also added an "index" field to state_t, in preparation for support of DECORATE state syntax within EDF heredocs. This will require turning states into an array of state_t pointers rather than an array of state_t objects as it currently is, and when that modification is made, it will be necessary to get the index of a state in states[] using state->index, rather than the current hackish method of doing state - states. state_t::index is filled in sequentially by E_ProcessStates. -------------------------------------------------------------------------------- 06/10/09 The automap boundary calculation is now sensitive to portal overlays, and thus the edges of the map will be consistent with the map when overlays are turned on. Previously, the normal map boundaries were always in effect, and this often lead to not being able to scroll the map far enough to even see your own location. -------------------------------------------------------------------------------- 06/09/09 Although it is probably largely pointless now, I have repaired a long-standing issue with the BOOM (or is it MBF?) tranmap.dat caching code which creates the tranmap.dat file in EE's base/game folders. Lee was accidentally saving the 8-bit 256-color palette, which is 768 bytes long, into a 256-byte buffer - a clear and simple logic error. This meant that if a palette was identical to the palette used to calculate the tranmap within the first 256 bytes (or the first third of the palette, in other words), it would fail to detect any change and would use the cached tranmap with an incorrect palette, resulting in weird and ugly colors showing up on translucent sprites. Thanks to esselfortium for catching this in his vapor project, or it probably would have gone unnoticed forever. I took the opportunity to add versioning information to the header of the cached tranmap, so that if we ever need to change its format again, EE will know to discard files in earlier formats rather than trying to use them. This was critical for making sure that the next release doesn't cause a bevy of complaints about supposedly broken translucency. After a complaint was registered on the Doomworld forums and an email was sent to me personally by the same person about the little-known fact that BOOM generalized walk-over crusher line types are no-ops, I repaired them for demo_version >= 335. It is evident enough that the lines are intended to work if they have been placed in a map. Jim Flynn must have left the case for them out of the switch in P_CrossSpecialLine, and this is not very surprising since they were apparently the very last generalized line category implemented by the BOOM team. God rest your soul, Jim. -------------------------------------------------------------------------------- 06/08/09 I have finally gotten around to my long-planned rewrite of the automap to use floating-point arithmetic. This brings it up to par with Cardboard for numeric stability, so that we can now map overly large levels or overly long linedefs with the same precision and unerring grace which we have previously had only when rendering them. Plus on modern architectures, floating point is just as fast and in some cases (believe it or not) faster than fixed point. In the process of testing this rewrite, I discovered a hitherto little-known vanilla DOOM bug - automap grid lines are lost near the left and bottom edges of the map due to some faulty math - a minimum amount (MAPBLOCKUNITS) is added in which causes the drawing loop to start beyond the position of a line that is closer to the edge of the screen than that amount. The proper thing to do is to start at the closest line to the edge of the screen by subtracting the remainder, even if that line is offscreen as a result - an offscreen line will be efficiently rejected by the Cohen-Sutherland clipping algorithm and won't be drawn. At most one line can be offscreen on a given edge with this method. -------------------------------------------------------------------------------- 06/07/09 Another round of GCC warning fixes. Ever since the thread-safety rewrite of the SDL digital sound update loop in 3.35.92, I had been hearing sample loss, as if the update loop were being barred from modifying sounds for an unacceptable amount of time. After thinking about it for a while, I realized that this must have been coming from the positional sound update code called via the main loop, which modifies the volume lookup ramps for each channel to keep them in sync with changes in the player's relative position. I realized that a critical section is not needed around this code, since changing the volume ramp pointers should not in fact affect the sound update loop in any serious way - at worst, the two stereo channels' volume ramps might become out of sync with each other for an unnoticably short amount of time. Removing the semaphore acquisition around the volume ramp modfication code alleviated all of the sample loss and made the sound engine run smoothly once again. -------------------------------------------------------------------------------- 06/04/09 Modified EDF heredocs so that they do not require a linebreak immediately before the terminating sequence. I don't feel this is a good or necessary restriction. After having followed a similar course with my experimental but ultimately abandoned "ERA" parser, I rewrote the libConfuse lexer to use a state table. This reduces the core lexer loop to 3 lines of code, whereas it was previously several hundred. Each state is now handled on its own, and everything is much cleaner as a result. SoM has completed the core integration of slopes. -------------------------------------------------------------------------------- 06/02/09 I completed two new gun codepointers for esselfortium, EjectCasing and CasingThrust. These are fairly standard object spawn and thrust pointers, except that they behave in a way that attempts to keep them consistent with the position of the player's gun psprite on screen, and their parameters allow extremely fine-tuned adjustment in 32nds of a unit. These pointers look great in first-person perspective in a single player game, but they look pretty ridiculous in multiplayer or with the chasecam active. This is what essel wanted though, so who am I to complain? :P Dynasegs got another smaller optimization. I do not need to calculate the sidedness of the polyobject origin point *unless* both of the vertices of the seg are within epsilon distance of the partition line, since the calculated value is otherwise unused. This was a silly thing just caused by wanting to get the code over and done with. While wrapping up essel's codepointers I also noticed that my previous modification to allow copying of arguments into the player mobj state from the player gun state during P_SetPSprite calls was unsafe if P_SetPSprite became reentrant. In order to safely operate in this manner, I must store the states and their original argument values on a stack, pushing one gunaction_t struct for every call, and popping one off the stack afterward. This makes it properly recursive. -------------------------------------------------------------------------------- 05/30/09 I added the "smart" background drawer routine which I had been thinking about implementing for a very long time. V_DrawFSBackground will, when given the pointer to a cached lump and the lump's size, determine if the lump should be drawn as a tiled 64x64 flat, a 320x200 linear graphic, or a screen patch. Patch vs. linear determination is not "smart" here - the linear graphic must be exactly 64000 bytes, which is not a valid size for 320x200 fullscreen patch graphics (they must be larger than that, or else they contain erroneous transparent areas and are not really fullscreen graphics). I rewrote several functions to call this new routine instead of doing their own private determination of resource types. This added support for some of the formats where it did not exist before, as well as cutting down on duplicated code. -------------------------------------------------------------------------------- 05/16/09 Line IDs and line tags are now effectively the same thing as far as DOOM-format maps are concerned in Eternity now, in order to bring us into compliance with UDMF semantics and to fix what could have actually become quite an awful mess. It is good, although humbling, to admit when you've made a design error. -------------------------------------------------------------------------------- 05/13/09 I applied yet another round of GCC warning fixes today. I also found a massive optimization opportunity in R_IntersectPoint in the dynaseg code. The expressions I used to calculate the (a2,b2,c2) values for the node line at the beginning of the function turned out to be, under some minor mathematical analysis, exactly equivalent to the negation of the node line's A,B,C general line equation coefficients. So instead of calucating these values again, I now just read them out of the node and negate them. Should provide a good speed boost to dynaseg splitting, since R_IntersectPoint is called every time a seg crosses a node line. I also added a seg length calculation to dynaseg attachment, to satisfy SoM's new Cardboard optimization that caches seg lengths instead of computing them every frame. -------------------------------------------------------------------------------- 05/12/09 Randomized sounds are now supported via EDF sound definitions. A new random block inside the sound serves to alias that sound definition to any one of the sounds listed by name within the block. Random and alias resolution are performed simultaneously, so that random sounds can both refer to sound aliases, and sounds referred to by random sound lists can both be random sounds, or aliases of normal sounds, or aliases of random sounds, etc. Yeah, it's kind of complicated. There's rarely any need to actually mix the two features, though. -------------------------------------------------------------------------------- 05/06/09 I changed the behavior of the Heretic deathmatch intermission somewhat from how it worked in vanilla because it seemed backward to me. In vanilla Heretic, if there was a frag leader, the "wpnup" laughing sound would play and the player(s)' frag count(s) would then flash. However, at the top, all the players' pics except your own would then fade out to indicate who you were. I have changed this so that your own row of frag counts is instead indicated by a pulsing translucent yellow color block beneath the numbers, and when there is one or more "slaughterboy," the players who were defeated by him or them will have their pictures fade out to indicate their loserly status. To me this makes more sense, and looks awesome. -------------------------------------------------------------------------------- 04/26/09 Finished the deathmatch intermission, and added a definition for the Heretic wpnup sound effect. -------------------------------------------------------------------------------- 04/25/09 Completed the cooperative-mode intermission statistics for Heretic, and started work on the deathmatch-mode frags table. -------------------------------------------------------------------------------- 04/19/09 I discovered that a subtle problem still existed with my new approach to button_t sound-playing for switches which could result in the switch sounds jumping to global position (0,0) - this was due to the fact that button_t's would be immediately cleared, even while the sound they just started was still playing. To fix this, I went ahead and implemented my previous idea of linedef sound origins, which consist of a degenmobj_t which is positioned at the center point of every linedef at startup (and yes, polyobjects drag this around too, keeping it consistent with the linedef's location). This may open the door in the future for some new linedef-based features, an area of DOOM-editing which I do not think has been exploited to even a fraction of its potential by any port so far. -------------------------------------------------------------------------------- 04/17/09 Esselfortium found that Eternity could crash when less than 17 members were a part of the cast call sequence. A small logical error lead to some very selective trashing of memory near the castinfo array. This was due to use of OLDCASTMAX without checking if numcastinfo was less than that value when populating cast members with the default names defined via BEX strings. Also, the screen clear routine in the IWAD picker module was always resolving RGB (0,0,0) to a surface-format color value on every call because I forgot the keyword "static" before the firsttime variable's declaration. I fixed that up. -------------------------------------------------------------------------------- 03/31/09 While trying to play an interesting PrBoom 2.02 demo posted on Doomworld where a Pain Elemental is fooled into killing a Boss Brain whilst trying to attack a Revenant while the player is dead, ending the level, I discovered that a simple logic error in MBF's comp vector handling prevented such demos from synching artificially. Basically, if the demo was recorded with "compatibility," the old BOOM setting, disabled, then MBF's logic would set the entire comp vector to "false," including any comp vars that didn't exist as of 2.02. This was just plain wrong. The proper action is to set all the comp vector values that were included as part of "compatibility" originally to the state of that variable, and to set any newer ones to true unconditionally. Eternity should have excellent PrBoom 2.02 demo compatibility so long as the demos in question are not for maps that use certain BOOM features - friction, mainly. ================================================================================ EOF ================================================================================