ANDY BAKER'S LOG DATE: 2006/02/15 Patched the configure.ac to look for glbsp in the detect the header in the root include directory (glbsp.h instead of glbsp/glbsp.h). Implemented two patches from Darren Salt to make FLTK optional (plus a bugfix that stopped linux/i_system.cpp compiling) and detection of an external lzo lib. DATE: 2005/12/28 Refitted 'nosound' back into the engine sound system. DATE: 2005/12/02 Implemented epi::path GetDir() & GetBasename(), GetExtension(), GetFilename() and stripped out M_CheckExtension(). Removed the unused M_ReadFile() and M_Writefile(). The wad handling now uses the file_c object for file access. This means I can remove the far from standard includes and EDGE's config.h won't have to balloon in size. IWAD directory is no longer defaulted to the game directory as I felt that custom games are unlikely to contain IWADs. This may need to refinement to check IWAD, GAME and current directory. See how we go here I think. Oh yeah, almost forgot. Best to hold the front page: I've done something remotely constructive. The cache directory has been implemented. Combining that with edge.log being written to the edge home directory and we have an engine that can be installed globally on a linux box, but write to user specific areas when needs be. Use of DOOMWADDIR environment var is recommended to access global data, but any GWA file creation is done in the users cache directory. RC4 just moved that bit closer. The focus is completing the work required for release: 1) Handle 'nosound' in sound system properly. 2) Video depth switching notice. 3) C++ Exceptions. DATE: 2005/11/29 Moved the EPI path methods from the filesystem class and into the path namespace. Shortened the names since path is stated in the namespace part. So IsAbsolutePath() has become IsAbsolute(). Looking forward to do something productive as opposed to this continuing battle of refactoring :). DATE: 2005/11/28 Replaced I_PreparePath(), I_PathIsAbsolute and I_PathIsDirectory() with EPI filesystem methods. I_PreparePath() doesn't have a direct replacement, instead we use JoinPath to append directory and filename where appropriate. DATE: 2005/11/25 We did only use I_TmpMalloc/I_TmpFree in one instance - in rad_trig.cpp - for string allocation. As a result I replaced it with an epi::string_c class and removed the definitions for i_defs.h. DATE: 2005/11/24 Commited fixes (inclusion of correct headers) to linux code. Added automake Makefile for lzo library. It was my intention to use the lzo library, but since its required for win32, I added it back into the linux configure build. DATE: 2005/11/23 Refactored the directory setup code. Added a cache directory to be used for cached gwa and hwa files. Made the raw_filenames table in w_wad.cpp a epi::array_c. Very tempting to go on a spring clean and continue to strip out the Z_ code, but that can be a further iteration of 1.29 after the initial release. DATE: 2005/11/19 Added win32 headers with configure conditionals to the engine code and the epi. Footnote to self: Handle C++ standard exceptions in e_main.cpp. Also run ww-cash.wad on EDGE through the debugger. DATE: 2005/11/13 Added a dummy config.h in CVS and made the move away from including the world+dog mentality. This step is needed for us to implement a proper configure script. It is also helpful in respect of compile times. Have to plead guilty on being the original architect to a now clearly suspect idea. Added the w_image_gl header. I didn't want to include i_defs_gl.h in places where it wasn't needed and only in source files, as opposed to header files. A good example of this is am_map.cpp which has no need to know anything about OpenGL, but it did require something else in the w_image.h header. A quick grep shows that only the rgl_* source files only use the methods in question. DATE: 2005/11/10 Purged CVS of old directories. EPI now considered seperate project. Mus2Midi extracted from EPI since it has no purposes beyond that of the engine. Implemented system specific GL header. Stripped out the include world+dog in the epi headers. This is to allow for quicker compilation and ultimately support the config.h which will be generated by the configure script. Completed a first pass configure script with checks for glBSP, humidity, epi & fltk checks as m4 macros. Produced glBSP, humidity & epi configure scripts which no longer require any change of structure to the respective projects as they stand. DATE: 2005/10/23 Removed turkish translation as it was clearly suspect. Implemented a basic NSIS install script for EDGE. It installs the engine executable, ogg vorbis dlls, changelog, readme and an option to install the standard DDFs zip. It creates short-cuts and an uninstaller which work fine. Need to add: * Display GPL Dialog. * IWAD Location Dialog. * Option to run the OpenAL Installer. * DDF/RTS Online Install Option. * Example WADs Install Option. Sync'd the win32 makefile with the changes made to its linux counterpart. DATE: 2005/10/22 Starting committing the minor changes implemented for RC#3 Compiler Config builds. It appears that an assertion is raised in the M$ libs if isdigit() is called with a negative value. This occured in FontParseCharacter() where an extended character gets read. Fixed by verifying a value is greater than zero before calling isdigit(). Used a epi::string_c to handle in the filename building contained in M_ScreenShot. The sole benefit of this is cleaner code and is not as efficent, but since screen shot taking is hardly the fastest process in the world I left the change in. Originally, this was implemented in an effort to track down an issue with screen shot generation. This "bug" actually turned out to be an incompatibility with the runtime DLL libraries between Visual Studio 6 and dotNET. I should note at this point the solution is rebuilding the offending libraries in dotNET; one would hope for a better fix but the dotNET build is for testing purposes only, therefore it goes on the end of a very long TODO list. Reimplemented the standard memory handlers for the engine. The custom malloc has had its use, but seems a reasonable stab-in-the-dark to resolve the random crashes that people have reported, but I have never been able to reproduce at all. Judging by debug output generated by one suspect machine - cheers Lobo - the crash seems always to follow a delete[] call. Removed the USE_DL_PREFIX define: this was a custom malloc directive. Renamed SDL/i_system.cpp to SDL/i_loop.cpp. Neither GNU Automake or Visual Studio are happy with a source filename being used in multiple different directories. Removed -fno-rtti (debugging move) for Mingw and stripped out generated include directives that where a hangover from the dev-c++ generated Makefile. We now link against SDL 1.2.9 instead of SDL 1.2.8. This seems to fix a crash on exit that we were experiencing on Win32. The "Why" is unclear. Fixed a bugette in ChangeToExeDir() - Win32's i_main.cpp - where a buffer was a character too small. Tidied using the epi::string_c for the buffer. Test for __func__ preprocessor keyword now: #If __GNUC__. Added missing M_PI define to M$ Win32 section in epi_win32.h. Made sure the latest version of deh_edge is being used for win32 builds. Modified the code to use the epi, glbsp & humidity as if they were in the global name space. So instead of "epi/someheader.h". A prelude to supporting 'configure'. Treat deh_edge as if they are a subdir of the engine tree and no longer specify a version number. The config.h will detect version numbers and enforce that contract if needs be. Defined USE_HUMID in i_music.cpp as opposed to the Makefile, another configure option that will go in config.h. DATE: 2005/10/19 Having provided a release containing three engine executables (RC#3 Compiler Config) for people who might have had previous random CTD issues for testing. I set my mind to the ten remaining tasks for the project's 1.29 release: 1) glBSP Configure Script - Needed as an EDGE configure script prerequisite. 2) Humidity Configure Script - Needed as an EDGE configure script prerequisite. 3) Sync codebase with changes made for compiler-config builds 4) Handle 'nosound' in sound system properly. 5) Video depth switching notice. 6) EDGE configure script. 7) Sync codebase with changes made for configure builds 8) Build Win32 Installer. 9) Release candidate #4 - Win32 Binary. 10) Release candidate #4 - Linux Sources. Asssuming that all goes smoothly we'll ready for a christmas release. In the meanwhile I have to make changes to our website for when the old sourceforge mysql database is taken offline. DATE: 2005/10/08 Fixed a small code oversight in image_jpeg.cpp. DATE: 2005/09/19 Introduced a defaults header file so we have only one place to configure the default config setting. The screen size defaults have been added to this. Applied the voodoo doll patch supplied by dsalt. Implemented a configuraton option for the screenshots (with regards to my solution for bug #1222174) in the video menu. It is now possible to select either JPEG or PNG as your preferred choice for screenshot output. Prepared EDGE 1.29 for release. DATE: 2005/09/17 Implemented an FXFLAG_IGNORELOOP flag. This overrides the effect definition and is used by the StopLoopingFX code to handing pending effects correctly. Previous they were just stopped which resulted in some platform effects not being played. Added a '-bestaudio' parameter for win32. This replaces '-forceds'. Due to the number of issues with regards to dodgy 3d audio drivers, I thought it best to force the use of "DirectSound" as the driver. The '-bestaudio' will make OpenAL select what it considers to be the best audio drivers. Win32 Icon added to CVS and removed the obsolete resource files. Implemented a fix so that the Win32 MessageBox is now displayed on exit when required. Implemented a quick fix to stop the sound playback of platform planes in stasis. The crusher on MAP06 which can be stopped by walking over linedef previous did not stop the crusher effect. DATE: 2005/09/08 Fixed a few sound effect generation issues: 1) The call to StartFX() is given a valid origin but a NULL sound prior to refactoring would cause any effect linked to the origin to be stopped. This behaviour has been replicated and the related issues (plane moving effects not been stopped) have been fixed. 2) Sector ambient effects not ceasing on level exit. Its noteworthy that previously the looping and distance calculation was handled within the sector playsim code. It is also noteworthy that these effects always loop regardless at a rate of 7 times a second. We retain this behaviour unless the effect is flagged as looping (the sound system does proper looping) and we now ensure that all ambient effects are stopped on level exit. A new P_StopLevel() method calls P_StopAmbientSectorSfx() which handles the required behaviour. P_StopLevel() exists to perform any required cleanup without deleting any allocated resources. Not bad for a right-handed person with a broken right hand. DATE: 2005/08/08 Fixed a bug in SetAllocatedSize() which resulted in the sound system referencing uninitialised data. DATE: 2005/07/24 Added code for persistent effects (reserved fx) channels. Its a bit hacky in places but does its job of allowing the music effects to work. Reinstated the basic distance calculation and set a category limitation func in place. DDF Priorities are no longer supported. DATE: 2005/07/10 Implemented category prioritisation. Very simple and very effective. The actual calculation of the category limits still remains: currently each category will have a minimum of 3 effects playing. Need to introduce code that will allow allocation of a fx structure inbetween Ticker() calls. This is required for music playback channels. DATE: 2005/07/02 Retrofitted the Win32 code with the SDL library. I had previously resisted the need to use the SDL because it was my opinion that our finely grained code was more suited to EDGE. Since the testing of the see-through-walls bug (#1180553) seems to indicate an initialisation problem. It was felt that the SDL would be a useful comparison. Having to implement the SDL highlighted that it does provide all the necessary hooks to win32 data (main window handle etc..), so as a result it has been decided to use the SDL for Video and Control routines. Noteworthy changes in regards to SDL: i_ctrl.cpp now handles whether the application is active or not and what happens when the application has gained/lost focus. An i_system.cpp has been added which holds the I_Loop() method. This now calls I_ControlGetEvents() each loop to ensure that application activation event is caught. The engine namespace now has an 'idle' function. This is called when the application has lost focus. E_ReleaseAllKeys() has been added to e_input.cpp. The purpose of the function is to generate keyboard events to release all keys that the engine thinks are down. This is called by engine::Idle() to ensure that keys are not left down. This can occur when an ALT+TAB combination is used, since when the engine is given back control, it does not get an event to say the ALT key has been released and in the default key config will result in the playing strafing when then intended to turn. The handling of application switching does work in gnome (tested by hacking in an iconify on ALT+TAB), however getting it to ALT+TAB (or whatever the WM manager uses) will need some work. DATE: 2005/05/30 Implemented a effective but nasty singularity handling. I've preferred to over-engineer this bit of code in order to keep the initial start effect code to a bare minimum. Considering the number of effects it will process with the sinularity test, I don't think it _that_ wasteful. Although I do accept that it is somewhat sub-optimal, as is all the sound system at the present time. DATE: 2005/05/13 Implemented Pause/Resume functionality. Have introduced a flags field on the pending effect (pending_fx_t) and effect (fx_t) structure. The purpose of the flags field is currently limited to effect which do not get paused. This is required since Effects are now paused by the ticker function in response to a pending_state variable being set to pause). An aside relating to OpenGL window rendering in Win32. It would appear that the main window will need to be destroyed and recreated for resolution depth changes to be properly restarted. I had played with the used of either an 'owned' window or a 'child' window to be used for rendering, but this appears to rather fiddly. DATE: 2005/05/09 Reimplemented proper positional data and volume control. DATE: 2005/05/08 Spent the last couple of days constructing a queue system for pending sound effects; this has effective become a rewrite of the entire sound system for the engine, since it includes merging in the OpenAL code. The mechanism for builting up a list of pending sounding, producing a combined list of pending/playing effects and then evaluating those effects to determine those which should remain playing and those would should cease is complete. Although the exact logic for picking the effects has yet to be finalised. The system specific startup/shutdown code has been temporarily reimplemented in AL/i_sound.cpp (should a version in each system specific directory) and a sound caching system reimplemented. I have know reach a point where I have merged the playback/stop/stoplooping OpenAL into the engine and this appears to work fine. DATE: 2005/04/11 Added the category type to the S_StartSound() call. This is prelude to biasing of the limited number of sound channel/sources code. DATE: 2005/04/08 Implemented a fix for bug #1176231. This is where the depth of the desktop (and hence the window) was not being changed when requested. This needs testing as I have a problem with my main windows PC where a series of res changes will result in nothing been drawn apart from the mouse. DATE: 2005/04/05 DDFinWAD 1.3 packaged and released. DATE: 2005/04/04 Fixed an outstanding bug with the teleport spawner (thing 7101), the final frame remains on screen and doesn't disappear. The last frame is now NULL and gives the effect of the teleport flash disappearing. DATE: 2005/04/03 Footnote of two bugs to document: Plutonia MAP16 (Raising -> Falling Platform) and both raising stairs in TNT MAP30. Both issues prevent completion of their respective maps. DATE: 2005/04/02 Stripped out the TRANSLUCENCY flag for global/levels. This did not actually do anything in the GL Renderer. Picked an issue with the lines.ddf file, it contains a '/* ... */' style comment (C style). Its interesting thats in the file since this comment format is not supported. This problem was detected when I had a brief chance to review my pending parser code which will currently reject the comment start characters. DATE: 2005/03/26 Added three parameters for the use with audio: -audiodev - Forces OpenAL to select device -forceds - Forces OpenAL to select "DirectSound" device -maxaudiochan - Sets the maximum number of playing audio channels at once These have been created as possible workarounds for buggy drivers in the Win32 environment. Although only '-forceds' is win32 only. Fixed an issue where only the first mixer in Win32 was being tested; hence MUS playback not occuring on these devices. DATE: 2005/03/18 Fixed a possible infinite loop condition. The win32 mixer detection code was not incrementing the loop if the mixerGetDevCaps() failed. DATE: 2005/03/14 Restructed the Win32 OpenGL startup/setscreensize/shutdown code. Apparently SetPixelFormat() is only allowed to be called once on each window. Since our choice of pixel format doesn't change I felt it appropriate to set it once on startup as opposed to every call to I_SetScreenSize(). DATE: 2005/03/07 Implemented the screen mode list object (scrmodelist_c). This replaces the old scrmodes/numscrmodes combination and now deals with the various find, next & prev routines that would scattered about the code. It greatly simplifies the logic in m_option.c. A noteworthy change to the code has been the removal of the "changeresneeded" boolean and srcmode struct. This combination has been replaced by a "newres_idx" var which when non-negative is an index in the scrmodelist object. Updated the copyright headers for all source files. DATE: 2005/03/06 Started to look at the resolution selection code with an aim of fixing various issues. Primarily, it is to add the actual system depth value in the screen mode structure: the hope is that this will resolve the issue of depth value being listed as available, but the opsys will not switch because a different actual depth is used. For example the case of 15 bit colour is given by the system, but 16 bit colour is send back by the engine and is failed. Along the way I plan to fix problems with the V_FindClosestResolution() not resolving back to the same res that was selected: I plan to sort and cleanup the list of resolutions as each one is added to the list on startup. Relying on V_FindClosestResolution() when an exact match exists is somewhat lazy. DATE: 2005/02/21 Fixed the window positioning issue on Win32. The code was not resetting the position of the window for fullscreen display modes. DATE: 2005/02/19 Since crc and md5 are both math-type functions, they now have a math_ prefix. This follows a request for this from Andrew Apted. DATE: 2005/02/18 Normalised the naming of source files in the epi lib. Where the change of name could come into conflict with standard headers, it was decided that the best case was normal to go with the plural version of the name if possible. This is the full list of renames: epiarchive -> archive epiarray -> arrays epiassert -> asserts epibasicimage -> basicimage epibytearray -> bytearray epicrc -> crc epiendian -> endianess epierror -> errors epifile -> files epifilesystem -> filesystem epimacro -> macros epimalloc -> memalloc epimd5 -> md5 epimemorymanager -> memmanager episound -> soundsystem epistack -> stacks epistring -> strings epitimestamp -> timestamp epitype -> types epiutil -> utility linux_epi -> epi_linux linux_epifile -> files_linux linux_epifilesystem -> filesystem_linux macosx_epi -> epi_macosx win32_epi -> epi_win32 win32_epifile -> files_win32 win32_epifilesystem -> filesystem_win32 DATE: 2005/02/16 Hacked together a fix for bug #1123377. An issue I picked up on a play through TNT MAP16 where stairs were not raised, but created by dropping sector heights. The code for stairs is something of a hack: the moving plane's destination height is adjusted according to the movement of the first step regardless of what the subsequent calls to P_SetupSectorAction() determine. This actually worked fine where the first step was calculated to move in same direction as the following steps; however the set of stairs triggered off by linedef #2116 on this map did not. The solution is an improvement on the original hack where a function is called to set direction and speed based off a new start and destination. Nasty, hacky, horrible; but it works. Story of my week in development. Explicitly set the linedef types to a speed of zero in lines.ddf to override any defaults in the code and force compliant behaviour. Must really finish that elevator code some time.... DATE: 2005/02/10 Tweaked the EDGE Makefiles for mingw + gnuwin32 binutils compile. DATE: 2005/02/06 Had a play with numbers to support EDGE's volume scale and "Attenuation By Distance". This is approximate; but appears to work for my configuration. Testing in the field is going to ensure that I have to revisit this one. The previous distance calc has been removed from the EDGE sound code and we now rely upon the underlying audio library. As such the sound interface has been modified accordingly. Noteworthy are: * I_SoundPlayback() no longer takes a parameter for panning as this was required for the engine's old distance/volume/pan. * I_SoundAlter() has been renamed to I_SoundSetVolume(); it now longer has a panning setting as described above. * I_SoundSetListenerOrient() Created. Takes two floating point vectors which are the at and up positions of the listener. * I_SoundSetListenerPos() Created. Sets the listener position. * I_SoundSetPos() Created. Sets the sound position of a given "source". * I_SoundSetRelative() Created. Sets whether the sound position is given to be relative to listener or not. The primary use is effects that sit directly on the usage. * AdjustSoundParams() Removed (s_sound.cpp). This handled the offseting of the panning and volume for the old distance calc. These functions are unashamedly OpenAL-centric, but I suspect further tweaking will involved the creation for a class for audio playback or not use system specific functions at all and stick with OpenAL calls in code, the same way OpenGL calls are embedded. Couple things for the TODO: * Change to 'up' vector in regards to mouse-look. * Validate usage on 5.1 sound; the stereo headphones don't cut it. * Check the soundvolume calc setting is correct. DATE: 2005/02/02 Generated Makefile's for the Dev-C++ 4.9.8.0 environment. The reasoning is simply that Makefiles are easier for crossplatform developers to maintain compared to project files for either Microsoft C++ (be in VC6 or .NET) or the Dev-C++ environment. DATE: 2005/02/01 Implemented 3D Positioning to the audio system. The positioning code works itself, however the volume adjustment needs to be completed. DATE: 2005/01/05 This marks the 6th year on my involvement with EDGE (Obsessed? Perhaps). I'm happy that OGGs are OK stored as external files. People who don't like that can like it or lump it. Quite literally in fact: The OGG player now supports lumps :). In addition I found that using ov_read() on win32 generated some obscure errors related to file opening. This was fixed by setting up the fread/fseek/ftell/fclose handlers explicitly. This should probably use the epi::file_c object in future. DATE: 2004/10/29 Implement the #define storage method in my lexer class. The only remaining hash directives work is the version checking. DATE: 2004/09/17 Began implemented hash directive processing in demo. DATE: 2004/09/15 Began writing the C++ version of the lexer prototype. The output remains the same however the internals will be modified to use the more coder-friendly top-down approach. This is where the parser will read a token and the call a function to parse through the rest of the token until it requires to revert. This is different to a state driven read mechanism (the bottom-up method) of "I'm reading this token and I'm in this mode therefore I do this", which is somewhat more primitive and more complex to manage. The handling of hash directives will be run in the lines->chunk processing, but will not alter chunk output. Although it possible to handle chunks in this manner, this would break backward-compat with the existing DDF Parser. Instead a table will be created that may be referenced at a later stage by the objects derived from the lexer if they so wish. DATE: 2004/09/02 Decided that since RTS is heading for a more involved scripting role that it was better to make it a little more complex. The initial phase - splitting into lines and then chunks (i.e. minus remarks and whitespace of no consequence) needs to be enhanced to pick up hash directives. I believe this to be correct behaviour since #defines are normally dealt with prior to any other parsing. Any C compiler will direct its output via a preprocessor prior to any actual processing it does itself. DATE: 2004/08/31 Continued the prototype of the tokeniser for DDF. Going well since DDF is quite nicely a primitive language. Although it does suffer a few problems with characters being reused. The best sample is the hash - used for redirection in states and hash defines. It does not look too complex to work around this round though. Have decided against replacing all the Z_Zone code for our next release since the a lot of the code that I'm having the rewrite will be rewritten with the introduction of the new WAD system. I don't have that much free time :(. DATE: 2004/08/27 Began prototyping a tokeniser for DDF in python. DATE: 2004/08/26 Stripped out any Z_Zone headers that could be extracted. Completed the implementation of ddf_base_c which includes use of the epi crc class and the epi strent (string entity) class. Started looking at building a tokeniser for the DDF stuff since the parser as a whole appears to be a bench mark test for the use of memory allocators. A tokeniser will enable more efficent use of memory and a faster processing time. DATE: 2004/08/25 Continued to replace Z_New() / Z_Free() combos with new/delete. As part of this I've began replacing the ddf_base_s struct with a class. This may seem a little bit of sidetracking from replacing the Z_Resize() stuff, but having looked at the WAD stuff and the amount of work it will entail to fix it, I felt that more time needs to be taken to produce a more OO-based solution. DATE: 2004/08/24 Removed the win32 console window. DATE: 2004/08/23 Removed deleted headers previously used by the software renderer. DATE: 2004/08/20 The OGG Player now works in Linux. After handling some underrun - restarting a stopped buffer when data was availble - it now works. The issue detailed below was caused by underrun at the beginning of the level. Fixed an issue where the Close() on the player didn't update the status and therefore was causing an error when trying to Play() another ogg. Muppet. Special mention to Erik Sandberg's contribution to EDGE. Its worth a note he did a shedload of quality work for and made a special effort to make sure we were GPL legal - something we maintain now - I do this since because we have recently removed the software renderer, we removed about 90% of the work he put into EDGE. DATE: 2004/08/19 Continued the stripping out of the software renderer. This is helpful since I can remove a few things from my list that use Z_Resize(). DATE: 2004/08/18 Implemented an OGG Music Player via OpenAL. This seems to work without problem on Windows. Reading from memory (a lump from a WAD) appears to be a simple modification, this is the only work outstanding apart for volume which is also an easy job. Note: Ogg Vorbis Precompiled Win32 libs only work statically linked and even that has to use a multithreaded debug DLL. There appears to be a problem with OpenAL on linux with either alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed) or alSourceQueueBuffers();. Since the update seems to work only once. oggplayer.cpp/.h got added to the AL directory simply because it is AL specific. Ideally this will be moved into the main source tree when OpenAL becomes the only sound handler. DATE: 2004/08/17 Implemented a binary-tree + linked-list solution to handle the drawthings array. No array object was used since I wanted to avoid doing any alloc(s) altogether in the routine. DATE: 2004/08/16 Implemented the deathmatchstarts (now dm_starts) as an epi::array_c (spawnpointarray_c). Could do the same for the playerstarts. DATE: 2004/08/15 Implemented the buttonlist as an epi::array_c. Wouldn't this be better called switchlist? DATE: 2004/08/14 Turns out that alcMakeContextCurrent() with a NULL parameter is the cause of our lockup for OpenAL. Had a look ath alutExit() function for Linux and it doesn't call it. This is done for windows however. Took out the call for linux - probably should use alutInit() & alutExit() and emulate it where missing. The I_SoundStopLooping for OpenAL now works. I need to look into why the chainsaw effect does not appear to be playing correctly. Implemented an epi::array_c for the storedsfx in the OpenAL code. Tided up the m_menu.cpp string handling. Dynamically allocated input and message strings replaced a host of statically allocated fixed buffers. Note to self: need to start implementing epi::error_c for the throwing mechanisms in the epi::string_c. DATE: 2004/08/13 Implemented the removeque in p_mobj.cpp as an epi::array_c; this is start of stripped out the Z_Resize() calls. M_ComposeFilename() and G_FileNameFromSlot() now take a epi::string_c instead of returning a string that requires de-allocations. Seems a tidy short term solution. I think this conversion process will learn to some addition directories for holding classes and containers since leaving them in just inserted into code is not the tidiest solution. We can do that once we've finally removed Z_Zone. DATE: 2004/08/11 Started picking through the allocations used for strings only and replacing them with epi::strent_c. DATE: 2004/08/10 My concern with OpenAL on win32 boiled down to library support for MinGW (minimalist GNU for windows). As it happens there are libraries for the compiler (via the DEV-C++ interface) and as such it compiles without problem. The current test implementation seems to work without issue although I need to preform more extensive testing. DATE: 2004/08/09 Completed the list of required changes related to Z_Resize(). I will effect the things I'm certain of to start with. Those that require work will work to the epi will be altered towards the end of this series of changes. DATE: 2004/08/06 Compiled a list of required changes for data that uses Z_Resize(). This operation itself is somewhat inefficent and indicates that data should be built as a container. There are going to be instances where a resize() is an apt action, but we need to look at other options first. con_*.cpp: Rewrite. Break up into seperate parts: console_history, console_executor (does the work when the console command is passed), console_renderer (takes history and prompt to render) and console_prompt. Sounds like a lot of work, but the EDGE console does very little at present and writing one is a simple action especially with the new epi::string_c & epi::strent_c now in active use. ddf_main.cpp: defines/numDefines - Build variable epi::strtable_c class. ddf_stat.cpp: redirection_names - Use epi::strlist_c class states - Form from an epi::array_c class e_net.cpp: Remark out and start again! r_data.cpp: R_InitFlats - F_lumps - use i32array_c class r_layers.cpp: solid_rects - Form from an epi::array_c class r_things.cpp: sprites - Form from an epi::array_c class rgl_unit.cpp: RGL_DoSplitQuadHoriz() - quad->verts & AddPolyDynPoint() - poly->verts: Need to refer to Andrew Apted on these. I think that we should consider removing the need to realloc() here since the golden rule of not malloc()ing each frame and I would hazard a guess that this is happening here. However without a firm understanding of how the rendering works in full I'm not best positioned to deal with it. I could realloc() in the short term. sv_chunk.cpp: SV_PutByte() - cur->start - Use realloc(). v_colour.cpp: LoadColourmap - cache->baseptr - Use realloc() v_res.cpp: V_AddAvailableResolution() - scrmode - implement epi::array_c w_image.cpp: ADD_BYTE() - buf_start - Use realloc() rim->block_cache & rim->trans_cache - Use epi::array_c w_textur.cpp: tex_sets - implement epi::array_c w_wad.cpp: data_files - Use an epi::array_c data_files[].flat_lumps - Use an i32array_c data_files[].patch_lumps - Use an i32array_c data_files[].sprite_lumps - Use an i32array_c lumpmap - Use an i32array_c lumpinfo - Use an epi::array_c lumplookup - Use an epi::array_c wadfiles - Use an epi::array_c DATE: 2004/08/05 Sorted out the remaining stack arrays for drawfloors, drawthings, drawplanes and walls. Since this was rendering code, I was not wasteful and ensured that data was not being freed and allocated unnecessary - it would of been very easy to rebuild the arrays for each frame, but there would of been something of performance hit here. I stripped out the Openings code - it was used in software mode only and would of required extra work to replace openings array - and shifted any functions that were required by the GL code from r2_bsp.cpp into rgl_bsp.cpp. Having completed the removal of the stack arrays, I removed the code from the Z_Zone itself. The stack array itself was a tidy bit of code it is own right but had to replaced since it didn't fit it into the object oriented C++. epi::array_c's are not necessary any better in how they behave, but they do allow us to control the allocation and deallocation of objects that they contain. Four things (and not small things these) remain: 1) Z_Malloc/Z_Free need to be replaced by new/delete. 2) Address all the Fixme!!'s created. 3) Restructing the source code: currently objects are scattered left, right and centre - these need to be tidied 4) Implemented epi::error_c throughout the code. Start at EPI level and move through the app. DATE: 2004/08/04 Started work on the rendering arrays. This is going to be fun.... DATE: 2004/08/03 Added an end-of-array pointer to the epi::array_c, along with the every increasingly useful ZeroiseCount() method. The end-of-array pointer allows for the iterator to check its valid without have to calculate the end of the array. Also ZeroiseCount() is a method for simply setting the count of the array to zero without clearing the data down. Useful if you don't want to destroy data or if you wish to avoid the overhead or rebuilding the array and it doesn't matter if objects are not destroyed. Implemented the real_images stack array as an object and put in a temp (and as yet untried fix) for the ONCONDITION bug - #1002106. DATE: 2004/08/02 The intercepts array has been replaced with an epi::array_c based in p_maputl.cpp. May require a tiny bit of optimisation in the scan loop since the iterator does too much maths. DATE: 2004/08/01 Fixed an issue with the GetTailIterator() function return an iterator with a negative value. This occured on arrays where the size was zero. Since I felt it inefficent to check the index value in the iterator class itself (since it should never happen), I made sure the iterator returned had a value of zero if the array it came from is zero. The IsValid() on the iterator will fail in this case. Looks like the only reason for creating a local copy of the spechits array was that P_TeleportMove() cleared the array. Since there appears to be no good reason for this I removed the clearing of the array from P_TeleportMove(). Implemented the spechit array as an object of linelist_c. Line list is an array of pointers to line_t*, but it does not attempt to clear up the lines on deletion. Footnote to self: GAP_RemoveSolid() loads data into an array of set size, but doesn't check that the data goes out of bounds. Its a possible crash bug on extreme levels, but it is possible it never reachs this level. DATE: 2004/07/31 The purpose for structuring the DDF structures into full-blown classes and containers class is simply to remove the old style Stack arrays. This process is complete in terms of actual work, but it should be added that a cleanup operation is required - most notably to each thing that has been labeled with a FIXME. I would liked to have overhauled the states[] table, but I don't wish to be sidetracked at present. I need to deal with the stack arrays that exist outside of DDF. Fortunately there are only a few of these. The first to be looked at is the "spechit" array. Its purpose appears to hold lines that have been intercepted by a thing's movement. Erik has added code to take a local copy when these lines are being processed since it is believed that functions that are called during the line processing alters the "spechit" array itself. I'm currently checking in what way this spechit line is affected during this process and if there is a better way of handling this in a new list object. DATE: 2004/07/29 Removed the wad_epifilesystem files since I don't expect it to be packaged as part of the epi, it will most likely been a DLL or so file. Also removed the used ddf_parser files since I do not expect them to be used. Stripped out chat_macros: Pointless since we have no multiplayer at present and maintaining this is work we don't have time to do. This was not done out of a drive to cut out dead wood: language references in DDF_MainCleanup() were causing me a headache when I moved the language selection routine into e_main.cpp and out of being hacked in DDF_LanguageInit(). The new language interface is now complete and it now reminds me why I walking away from any "refurbishment": it takes a while debugging a shed load of code thats been sat in the theory stage for a couple of days. However, it is done and only requires some minor optimsations. Footnote to self: Some funky char-encoding stuff has appears to have altered some foreign language characters - need to check they're still come out right. DATE: 2004/07/28 Began implementing a new language definition parser handling. I have tried over this period of conversion to using container objects of not reworking the code as I felt that I'd never finish, however I'm making the exception for the language stuff since it very different to how the other DDF code works. Put simply the existing code will be written to use an buildinfo object to store the data used in parsing the files, the data in this object is them put into a more compact format (saving on mem) and the object is destroyed. DATE: 2004/07/27 Introducted the strbox_c object to epi. This has a similar relationship to strlist_c as strent_c does to string_c. As such strbox_c is a container for a group of strings, but there is very limited capacity for manuipulation, whereas the strlist_c can be built up and then pull apart at leisure. There are intended to interface from each other and both have a Set() function to load data from the other. The internals of strbox are a block of data containing the string, an integer containing the size of the data, a list of pointers referring to strings within that data and a size count. This does not carry as much bulk and cause as much memory fragmentation as the strlist_c object. The primary intention for their use currently is the language definition. DATE: 2004/07/26 Implemented a epi::strent_c (String Entry). The purpose for this is to act as a container for null-terminated string which is dynamically allocated. The purpose here is just to contain, not to manipulate. String manipulation is handled very well by the epi::string_c class. DDF_MainGetString() now loads up a epi::strent_c class and all DDF objects have bee amended to use this structure. I'm moving towards using a string table for longer term strings since dynamically allocated objects come with a 8-byte overhead and that we'll want to avoid for things that are not in a constant state of flux. DATE: 2004/07/25 Converted the sfx to use containers. I've done enough for it to work as it did, but there is a memory leak in the way that the system works. In order to cater for sound effects that use strings which include wildcards, we return a point to an sfx_t. This sfx_t is a structure of varying size which holds the number of effects that match the given key and then an array of ints which point to entries within the sfxdefs list. Under most circumstances the pointer return actually points at data with the sfxdef_c (each one contains a single self-reference) for exact matches, otherwise a new sfx_t is allocated. The problem occurs that one cannot delete the sfx_t since it can point to one in an sfxdef_c. Therefore we need to work out a way of managing these sfx_t, most likely in a container of its own. I decided this can wait until the OpenAL revolution. DATE: 2004/07/24 I've got a working WinXP install to hand, so I have something else to test on. I quick download of 1.28a shows there is an issue with key presses being registered. For the most part the keys respond well enough, but the major hole is pressing SHIFT to run. It doesn't work with any consistency and this is pain for the player who still uses this method to run. I shall need to look at this in detail before our next release. DATE: 2004/07/23 Took time to investigate the libraries needed for png and jpeg support. Getting any library to work takes a bit of tweaking, but knowing that we'd been using the mainstream un*x/linux compiler GCC on a windows platform (otherwise known as MinGW) throws us a few issues. Firstly, most of the makefiles written are build with a full GNU toolset to hand which is not the case if you've downloaded MinGW. Secondly, Microsoft's Visual C is the dominent development environment on the windows platform and on some projects there is more support for this, rather than the MinGW environment. Starting with libpng I downloaded and my aim was to at least compile a DLL for this. One prerequiste is the zlib compression library which can be downloaded freely and compiles OK from the gcc Makefile provided in the win32 directory. Libpng itself was a little more frustrating: the makefile.cygwin (nearest relative to MinGW to produce a DLL) relies upon the existence of the full GNU toolset and I ended up creating a DEV-C++ project file using the settings extracted from makefile.cygwin. This requires a little more investigation and probably a submission of a patch to the libpng maintainers. Either that or EDGE will have its own src dist for win32 libpng. Libjpeq was difficult in a different way. The code for this was sourced from gnuwin32.sourceforge.net (which I later found had a libpng dist) and as such contained a relevant Makefile provided. However, this required a few bash scripts of its own to compile. Not having to have time to dig through and install a whole bunch of scripts, I replaced the offending bash script (o2dll) with the appropriate call to dllwrap and a build of the library prior. After a tweak of the EPI (including the images files) and an enabling of the test within thee EDGE. This compiles, links and runs OK. Although I haven't actually used the code in anger at the moment. This will be possible once I've gotten hold of the Doom2 Texturing Project's data on CD. We'll see how well I hack when that happens... Had another look at putting SDL in use on Win32, but again felt that the work involved didn't necessary merit the results. The SDL is nice and tidy - from scratch it may make a great deal of sense, but we have a tidy interface which does work well enough and only needs a few tweaks are needed to resolve outstanding issues. Onto DLLs. Nice idea, f*cking 'mare to maintain. Thats my opinion and its really not changed a great deal over time, so much so that EDGE remains statically linked on windows where possible. However with the inclusion of more features - PNG, JPEG, Font Rendering, OpenAL etc..., its probably time to bite the bullet and deal with the problem. Conflicting DLLs appears to be most problematic and will most likely occur for people who use the source ports and EDGE in the same directory. As a result I think we've going to need to put these DLLs into a seperate directory which will not conflict. Something that can be delayed until crunch time. In terms of what can be put in DLLs and their Un*x like shared objects appear to be purely C functions, they were never really meant to deal with classes within C++ and hence don't. Although I stand to be corrected as I've not dug deep into the subject. The glbsp plugin appears to be a viable candidate for moving a DLL - I think Andrew Apted may have suggested this himself. The other chunks of code I'd like to move out the main executable would be the DDF/RTS parsers. Why? In the same way that a glBSP DLL would allow for editors to build the node info for a level, it would enable them to get information from DDF and RTS without parsing the files themselves. The interface would be interesting, but I suspect that a very limited SQL language with object containers replacing that of database tables, so for a thing search: SELECT * FROM things WHERE name = "IMP"; would return a data object with all the entries for the "IMP" thing. Although I would imagine that the game would load the contents and then ditch the library. A couple of hurdles exists, notably the remaining links into engine code. Stripping out the parsers will remove a shedload of strings and static objects that just sit wasting space after initialisation. Also the containers can be allocated at the correct size and in singular arrays as opposed to being built up as a list of pointers. Its noteworty that every piece of dynamically allocated memory carries at least 8 bytes overhead. So the memory saving could be significant. The savegame code could be a target for this approach since it is built in a similar way to DDF; Although I doubt it would be of much use to developers of Editors :). Back out of the land of random thought and onto making the DDF_Sfx code into objects... DATE: 2004/07/22 Fixed a few glaring errors in the current revamp: Notably the weapons lookup was trying to use the mobjtypes FindFirst(), whereas the mobjtypes Lookup was using a global reference as opposed to itself. Converted damage_t to a damage_c with copy constructor and Default() method. This is handy since it removed the need for copy-every-member-of-the-struct code blocks. label_offset_t is now also a class. DATE: 2004/07/21 Completed work on ddf_weapon.cpp and made weaponkey a class. Will commit tommorrow. DATE: 2004/07/20 Continued work on ddf_weapon.cpp and its move to use the weapondef_c/weapondef_container_c classes. Looks like weaponkey[] will have to be converted to a class in order to manage the memory it allocates for the weapondef_c pointer list. DATE: 2004/07/19 Completed making all the changes required to implemented the container type and classes for weapons in DDF. I've left the weaponkey[] array alone since it does not rely upon the stack array system and will need to be reimplemented if improved anyhow. DATE: 2004/07/18 Found and fixed 2 compile errors. 1) rad_act.cpp was not up-to-date in CVS. 2) A recent installation of apache has overwritten the fnmatch.h in /usr/include. This resulted in warnings of INLINE being redefined and a deliberate syntax error in relating to behind included prior to . DATE: 2004/07/16 Looked at various implementations for font generation. This is something of sidetrack until I resume the weapons definitions. DATE: 2004/07/14 Started on the weapon definitions. DATE: 2004/07/10 Gone a bit mad with the renaming, but I did feel it important that we were consistent and clear. Its a bad habit, but the rest of the world can catch up with this conversion table: donut_t -> donutdef_c elevator_sector_t -> elevatordef_c extrafloor_info_t -> extrafloordef_c ladder_info_t -> ladderdef_c lightdef_t -> lightdef_c linedeftype_t -> linetype_c litetype_e -> lighttype_e mobjdef_c -> mobjtype_c moving_plane_t -> movplanedef_c sliding_door_t -> sliding_door_c specialsector_t -> sectortype_c teleport_point_t -> teleportdef_c This only includes changes to names with the linetypes/sectortypes commit. I have completed the line and sector changes for the new containers, although this code will require extensive testing. I'll stick together a short test plan for use when the rest of the memory management conversion is complete. The remaining changes are states, sound effects, weapons and languages. Languages being the considered the slight oddity, so it is being left to last on the DDF changes. Bit concerned about the executable is putting on a little weight for what it being added. Maybe this will be balanced out when I strip out Z_Zone. The eagled-eyed among you may notice a slight gap in my recent commit for the linetypes/sectors. I'm probably the only coder recently who had to be halted in commiting code to CVS to pick up his motorbike from being serviced... Note to self: Check that saving/loading on a boom level works. I'm concerned that the code may not handle generalised linedefs. DATE: 2004/07/09 Completed the parser functions for lines and sectors. As it stands the code compiles, links and runs OK. Although the donuts and generalised lines+sectors have not yet been implemented. I intend to create additional linetype_container_c & sectortype_container_c objects to hold the generalised types. It seems to make sense for the game engine to manage these. It will call DDF code where necessary to create the lines/sectors, but apart from that the engine can manage it. This seems the most consistent way of handling this. Although I had considered modifying the existing containers, but that would be messy when attempting to maintain the current behaviour. Since it is possible that someone relies upon this. In the future, we may wish the consider the possibily of loading lines.ddf on a pre-level basis. If that becomes true we can dispense with the additional containers. Starting remote debugging using gdb from one linux machine to the other. Quite friendly to setup. Works well. Such is the effectiveness of debugging tools under Linux, it picks up a SIGFPE deep down in the mesa GL drivers for my Radeon when starting EDGE. It appears to be safe to ignore and is not picked up if the executable in run without a debugger. Interesting stat of the day: The largest IWAD released offically for the doom was TeamTNT's evilution (tnt.wad), its size is 19Mb. Switch on all the debugging info for gledge and the epi library - the size of the executable is 32Mb. It would appear that the engine ate all the pies. Added a branch to CVS for the 1.28 release. The tag is "stable-128". Note to self: Need to look into donuts use the data and how best we can implement a solution using the new classes. DATE: 2004/07/08 Footnote to self: Add 'const' to the assignment operator 'rhs'. This is consistent with GCC - and I assume correct construction. Implemented 90% of the sector & linedef types. I'm at the stage where the codebase currently compiles and links OK. The remaining code is the parser functions, Boom handling and donuts. The objects which are embedded into linetype_c and sectortype_c are fortunately of similar construct. So it become suitable for me to generate a little PHP script for outputing these classes. It could be argued that Python would of been more suitable, but the time taken to write the script did save me a lot of time. May consider putting some kinda of generic developer tools into the edge CVS. It will come in handy if we do many more structures to full class conversions. DATE: 2004/07/07 EDGE 1.28A RELEASED. DATE: 2004/07/06 Implemented the body of the linetype_c class (replaces struct linedeftype_t). DATE: 2004/07/05 Since the interface for this line/sectors code is pretty settled already, I took the route of changing the code outside of DDF and then fill in the gaps when it all compiles cleanly. Also fixed misc warnings (unsigned/signed comparisons) and a kernel header include in epiendian.h. Use directly isn't proper, so has been included instead as per warning suggestion. DATE: 2004/07/03 Got myself up and running on Linux (Fedora Core 2/ Kernel 2.6.5 / GCC 3.3.3), since my Win2K bit the dust last night. As a result I just completed the outstanding initial work for lines and sectors. Although I did get the opportunity to test the OpenAL sound libs for Linux, which seemed must more responsive that the normal SDL sound. The one problem is that is don't seem to want to exit and causes X stability issues. DATE: 2004/07/02 Started work on converted linedef structures to classes. I suspect that sectors will get changed at the same point since the two are linked in places. DATE: 2004/07/01 Fixed a few crash bugs that got introduced with the new code. Firstly, I didn't set the currgamedef pointer. It did highly a few issues with the current setup, but the new code - an extra parameter to G_InitNew() and a deferred pointer for gamedef - is no worse that the previous code. Another ones of those battles for another day. I didn't set the defaults properly for the text display in intermissions and as such no text was being displayed, it even managed a nasty lockup on Doom II MAP30's exit message. Setting the defaults correctly has fixed this. DATE: 2004/06/30 Finished all the ddf_levl changes. Compiled - and briefly - tested. I had to tolerate the currmap being set in DDF_LevelCleanup(). The engine doesn't respond well to this being NULL. Thats another battle for another day: it falls over during initialising the menu defaults in m_option.cpp. Have I graduated to a hardcore open source developer? Well using 'gdb' for win32 must elevate me up the scale, but actually using windows is the big downer :). DATE: 2004/06/29 Keep running into strings that need are dynamically allocated, but are changed rarely (if at all) and would be wastful if implemented as a epi::string_c. The overhead in that structure suggests itself as a class for modifying a string in the short term. A longer term class is needed, whose only element is a char* and the methods exist only for gaining length (via strlen) and for copying about. This fits with the Java concept of a string object which holds a string and a string buffer object for pulling apart a string and rearranging as appropriate. Thats will most likely get written once the old stack arrays are stripped out. On that note, I've made further in-roads in updating the DDF code with objects and epi::array_c's. This is very much akin to crossing the desert, but each DDF file marks progress and ddf_levl.cpp (map definitions) is all but complete. At the time of writing I have made the mapstuff_t & finale_t structures into the mapdef_c & map_finaledef_c classes respectively. The remaining bits to light this bit of the progress bar are fixing the compile errors and testing the code itself. One of the things I have tried to do during the conversion process has been to ensure that the containers are very much self-contained and don't rely on external dependencies with themselves and the EPI. Apart from a useful programming exercise it will allow for the code to be modularised in library form. I suspect that all the objects and containers will go in a ddf_objects.cpp/h and ddf_containers.cpp/h eventually. The ddf_main header will of course include these, but will retain their extern definitions. I mention the above since I quickly added a 'game' namespace (whether this will have a usefulness in the longterm remains to be seen) whose only function is LookupMap(). Ideally, we would have used the Lookup() method on the mapdefs (class mapdef_container_c) object, but the code used the W_CheckNumForName() function for checking the existence of the lump. That would be failing the greater good if this was done inside DDF and hence got added to g_game.cpp within the 'game' namespace. I shifted the current and next map extern definition in the g_game header, since they were declared in g_game.cpp. DATE: 2004/06/28 It would appear that GCC and MSVC seem to work out which operators to use differently. The comparison operator on the epi::string_c will work fine under MSVC, but GCC will complain that its not sure which to use. Hence the rule of thumb is to be explicit. Therefore the code if (s2 == "#END") { /* ... */ } is better rewritten as: if (s2.Compare("#END")) { /* ... */ } The change above I have been required to make in ddf_game.cpp actually uses the CompareNoCase() method since DDF should not be case sensitive. DATE: 2004/06/27 Picked up on a possible race condition that locks up Win32 on startup. It seems to be on the first call to I_ControlTicker()->ReadKeyboard() call. I've not been able to reproduce it 100%, but it occurs when the startup has to read the WAD from disk as opposed to using windows disk cache. On the bright side, the world intermission code has been completed and tested. I've also managed to fix the bug where the map has no next map (i.e. end of an episode), but still displays the "Entering" headline. Most of the remaining work for world intermission screen was tied up in added assignment operators to the wi_*def classes in DDF. Fixed a bug where the attack mobjdef's we being created, but not being added to the list. This showed up as a result of loading a savegame which contained an active projectile. Ensure that the copy constructors all have related assignment operators. DATE: 2004/06/26 Spend half the day getting my secondary machine to support OpenGL on the X server. It does render OK in software mode, but it is pig-slow. Mainly due being a Pentium II 400. I shall be raiding my parents machine for their TNT2... :) Stripped out on all the in-game data from the wi_* classes in the DDF area; I also made a naming adjustment to each to indicate them to be definitions. Implemented a wi_c class to wi_stuff which acts as container for all the ingame data. This is placeholder code until we strip out the interface. DATE: 2004/06/25 Starting making adjustments to wi_stuff.c; I think that we should treat everything read in by DDF as read-only data copy. I'll make the change to this tommorrow. DATE: 2004/06/24 The initial DDF stuff has been sorted for gamedef_c. Since I've made the correction of moving wi_map_t -> gamedef_c, I now have to sort how the intermission code works for it to make sense. The code currently takes a copy of the gamedef data and works with it for all the intermission screens. I suspect we'll move away from this and have a purpose build class with contains gamestate data and a pointer to the gamedef_c. It'll probably be only the wi_stuff.* which needs changing initially. Can't see wi_stuff lasting much longer (assuming we have the time) as its not really configurable as it stands. DATE: 2004/06/23 Implemented gamedef_c plus its container class in basic form. I need to update the remaining DDF Code (and remove where necessary) and then update the major engine code. DATE: 2004/06/22 Implemented the wi_anim_c, wi_frame_c & wi_mappos_c plus their container classes in basic form. DATE: 2004/06/21 Continued on implementing the gamedef_c class (replacement for wi_map_t). The whole game definitions code looks to have been written initially to replace the intermissions screens ('wi' prefix = world intermission?). Not sure what to do with the bg_camera[] entry. I will probably leave it as its not doing any harm, even if its a little untidy - its based off the assumption that mobj names can't be longer that 32 characters. The entry itself holds the name of a mobj type to use as a camera position in the intermission screens; but I suspect that'll be ripped up when we start doing screen layout DDF (menus.ddf). DATE: 2004/06/15 Seems fairly obvious that we have a memory trashing bugs. The original level are fine since they don't push the engine, but find a few more complex levels which push the engine will result in a crash. Beyond the obvious checking, I'm not going to do anything about this until the new memory manager has completely replaced the z_zone code. DATE: 2004/06/14 Implemented a strlist_c class (_not_ a string table as mentioned on 11th). I just need a list of strings for the titlepics array in wi_map_t. I also added two int array classes (one for s32_t's, one for u32_t's). These new additions form the new epiutil.h/cpp files. At the moment I've got the idea of extending the wad filesystem in my head. The current one is pretty basic and I've have a task listed for a new format for some while. The whole purpose is to make it possible to support a filesystem, the idea being that someone would not need to compile to a wad before a release and that file extensions could be used to identify files etc. There isn't a reason why the current WAD system could not be built upon to support this. This is however a note for the future and not something that should be attempt now. I do need to nail the idea down first. DATE: 2004/06/12 Fixed a bug whereas the OpenGL code was not allowing a res change on Windows 95. Took a copy of the 1.28 codebase and applied the fixes from the 1.29 codebase. This will form our 1.28a release, which is a bugfix for 1.28. DATE: 2004/06/11 Had a look at the wi_map_t structures in ddf_game.cpp. The structure is an oddity since it contains arrays which get created when parsing the DDF file. I'm not sure I'm keen on too many arrays within arrays. Also I need to implement a stringtable class - maybe integrated in the EPI. I don't think that storing an array of epi::string_c is sane since of the overhead that comes with them and should anyone want to manuipulate the data they can be loaded into an epi::string_c. I aim to create a branch of 1.28 and implement the fixes from the version in CVS (minus EPI implementation) at the weekend. Leaving it a couple of months before fixing the crounching bug would be rude. DATE: 2004/06/10 The class colourmap_t has replaced struct colourmap_t. Couldn't really justify changing the name to include a def. Noted that Lookup() methods should need to throw an error and that this should be handled or ignored if appropriate. DATE: 2004/06/09 The class atkdef_c replaced the struct attacktype_t and atkdef_container_c has been added to act as container. Since DDF is the world of definitions, I've made a point of using the def in the terminology. Hence why mobjinfo_c also got changed to mobjref_c. Its not as though I've just the find and replace in files shortcut... Next up ddf_colm and colourmaps. DATE: 2004/06/08 I decided to change all ddf-built structs to classes for the following reasons: 1) Implement CopyDetail() method for copying all data except the ddf id when the entry has been finished. 2) To Replacing the static template with a Default() method. This is essentially for use in the constructor and for clearing the buffer object down after it has been copied. 3) Allow for greater control over objects and pointers within objects that require management on deconstruction. Objects changed thus far: animdef_t -> animdef_c dlightinfo_t -> dlightinfo_c haloinfo_t -> haloinfo_c mobjinfo_t -> mobjinfo_c pl_entry_t -> pl_entry_c switchdef_t -> switchdef_c Completed the necessary work on mobjinfo_container_c class. Although I need to revisit the savegame code - the lookup() in SR_MobjGetState() replaced a loop with took no account of disabled objects. At first glance it would seem that a disabled object would never get saved. However I need to go over this. It should be understood that maintaining the momentum of the change is more important than checking the fine detail at the point. Once everything is in a position to settle - i.e. all the stack array is removed - then I can revisit these points, if they remain relevant. Appropriate use of the "FIXME!!!" is recommended. DATE: 2004/06/07 Started implementing the mobjinfo_container_c class. This one will require more than the basic functions due to many ways that mobjinfo are referenced. DATE: 2004/06/06 Working on implementing the mobjinfo_t struct and a container class for it. I think that mobjinfo_t would benefit from being converted into a class in order to properly cope with copying this object about. Added the ability to get & set the position of the array_iterator_c class. The iterators are beginning to be my preferred method of array access and as such this functions fill a void, whether or not it is a purist use of an iterator is something I do not know. DATE: 2004/06/05 Implemented a lumpname_c class for the purpose replacing the char[10] defs that are used for storing lump names. Although I need to check why we are using 10 chars for a lumpname since I belived the maxname to be 8 + the null. DATE: 2004/06/04 Changed playlist_* to pl_entry_*. I did write it originally and have to 'fess up to it not making natural language sense, so it got fixed when implementing the container for playlist entries. Major panic on as I found a heap error on MAP30 of scythe.wad. Since I'm working with the memory code at the moment the concern that I had checked-in a memory overwrite bug. Panic over when V1.28 did the same thing. Its a problem, but something I don't have to concern myself with immediately. Made sure we were cleaning up the info data if replacing an existing playlist entry. Implemented switchdef container class. Switchdef was previously called switchlist_t, this is another that didn't really make much sense, so it became a switch definition. Knocked down the DirectX requirements so that it will work with version 3 or later. The latest version doesn't provide any features we use. DATE: 2004/06/03 Implemented a GetTailIterator() in epi::array_c. Means you can now search from back to front. Took the plunge: meaningful code now uses the EPI. The animdefs array has been replaced with the animdef_container_c class. This is our first step in stripping out the Array handling in Z_Zone. I've added a few helper #defines into epiarray_c. Neatly converting from an iterator to a type or pointer and primitive array construction are now handled. Two footnotes to self: 1) Use just the one log file (EDGE.LOG and debugfile to be combined) 2) Get around to finishing the elevator types. DATE: 2004/06/02 The code that tracks the stats in epimalloc attempts to add in allocations made by "foreign" allocation calls. The code will takes the gap between the new and old memory pages and assumes this to have been used. This is problematic if windows goes off and gets a page of memory say over 32Mb away for its last page! - which it was doing with alarming consistency. Decided that we were only interested in memory pages allocated by epimalloc and nothing else. (Wipes sweat from brow). Thought that was going to be a nasty one. Started stripping out the obsolete Z_Zone functions. This will make it easier to focus on those that are actually used. The following have been stripped out thus far: void Z_CheckHeap(void); int Z_FreeMemory(int level); int Z_UsedMemory(int level); bool Z_CheckIfZero(const byte *ptr, int size); DATE: 2004/06/01 Fixed a problem where we used a Win32 API call that did not feature in Win95. As a result the GetFileAttributesEx() has been with a call to FindFirstFile()/FindClose() mechanism. This is detailed in the docs as being supported in Win95. Needs testing that the next version will work and this is the only missing function call. Corrected the coding standard doc (indents increased from 2 to 4) and added sections for classes and namespaces. I'll let them evolve until I formalise. My view is that docs should never cover the detail until the detail has been tried and tested. The big mistake in programming these days is to design everything at the beginning. The memory code is returning odd values for the size (noticed when it tripped the memory size checking). Definitely need to fix this before any committing. Nothing nasty detected when playing my current favourite PWAD for Doom II - its called Scythe (highly recommended). DATE: 2004/05/31 Started work on getting the EPI used by the engine proper. Decided that it was probably best to perform any integration piecemeal. So much as I would like to convert everything at once, the reality begs to differ. A couple of years ago I would of been very critical of such an approach, however I'm a little more pragmatic now. Still sucks thou ;). Created an engine namespace and created functions Main(), Loop() and Tick() to replace E_EDGEMain(), E_EDGELoop() and E_EDGELoopRoutine() respectively. Main() takes the standard main() parameters now, which is passed to M_InitArguments(). The call for this is stripped out of the system specific code for all platforms. The reasoning for this change is to allow for the EPI to be initialised prior to *all* engine code and we don't need any params for the EPI init. Main() calls Startup() which does all the engine initialisation that E_EDGEMain() used to do and returns true if Loop should be called. Ideally Startup() and its sub-routines will throw an epi::error_c in future, so checking the return value would be unnecessary. A try/catch block encapulates the Startup() and Loop(), which means the program *will* return to this point by throwing an error - maybe I've retained a little more idealism that I expected. The catch statement only handles epi::error_c at present, I don't see any reason to change this. I won't be committing this to CVS just yet - its just the beginnings of a bigger change and it doesn't have that much impact. Only sound handling current does new/delete in the C++ style. DATE: 2004/05/30 Berzerker caused a crash if you a theortical target was being used. Turns out that a recent change was checking for the radius of an object from its info; a theory target has no info and hence bailed at this point. Fixed this in two ways: DecideMeleeRange() would always return false if a dummy target was being used (its used to determine whether an attack sound and autoaim is made for the player). In addition the code now computes damage if the CLOSE_COMBAT attack does fail - this handles the situation of damage being done to other objects apart from the target. Also I made the code use the actual radius for the calculation since it is conceivable that the radius of the object would change during its lifetime. Fixed the Arch-vile resurrecting non-solid objects and trapping itself. I fixed this is in the resurrect respawn code a while ago. ALT+TABing under windows does not trigger the TAB 'key' in the game. For most people this means that the map-toggle will not kick in. DATE: 2004/05/23 Prep'd for V1.28 release. DATE: 2004/05/21 Set initial volumes for CD & MIDI to zero. This has the effect of hiding a delay in setting up the mixers following playback. DATE: 2004/05/16 Tested for an hour and updated the readme. DATE: 2004/05/15 Be careful of what you predefine. Spot the difference: 1) #define FL_ROUND(f) ((int) (((f) < 0.0f) ? ((f) - 0.5f) : ((f) + 0.5f))) 2) #define FL_ROUND(n) ((int) (((n) < 0.0f) ? ((n) - 0.5f) : ((n) + 0.5f))) The variable arg is f instead of n. Why is this a problem? VC's preprocessor will attempt to replace every 'f' - including those that suffix the numbers with the contents of 'f'. Rule of thumb? Preprocessors - especially those included with with M$VC - are thick as pig sh*t. Example 2) works as intended. Stopped console's PLAYSOUND from generating a fatal error. This is a temp fix until our next release which will hopefully involve a decent try/catch mechanism. DATE: 2004/05/09 Moment of inspiration and sheer-bloody mindedness has enabled me to add the code to control the mixers under win32. Once you understand how the mixers work, if becomes a lot easier to handle. Each device has mixer and various inputs (source) and outputs (destinations) and that MIDI and CD are treated as sources. Therefore you need to apply the control to the source and it works once you get past the protracted windows structures. Although given the different devices, I supposed one could argue the complexity is justified. Adjusting the operating system volumes is probably _not_ recommended practice. However, it works. I made a point of restoring on exit, the values on entry. This mixer code has been hacked a bit since this will all be in the epi at some point in the near future. One alternate way of controlling the midi volume would be to adjust the midi channel volumes by the current volume and emulate volume control. Verified that win32 was rounding to nearest on all calculations excepting casting to another intregral type. DATE: 2004/05/02 Spend time debugging the linux epi functions. The upgrader tool was developed on the win32 platform via a cross platform lib (in this case the epi) and as such the linux filesystem code needed a little testing. Firstly, rewrote the Copy() function to use try/catch/throw. This made sense since all the code that would have to be written for each failure in the function. Also fixed abug where the Copy() was reading the dest_file's length for how much it should read. Clearly another CIB (Caffiene-induced bug) :(. Onwards, Close() was going into infinite recursion. This happened due to file (linux_epifile) class calling the filesystem Close() function in its deconstructor. This is correct behaviour, the incorrect behaviour existing in Close() where it was not NULL-ifying the filesystem pointer in the file class. This allows for people to destroy a file object without needing to Close() it first. Onwards again, ReadDir() was returning OK, but not loading any contents. My first port of call was the fnmatch() call which turned out to be quite correct. This is a nice little function for comparing a string with a regular expression. I had originally thought that it should be returning a value != FNM_NOMATCH in order to be correct, but == 0 is correct like most posix functions. Next function call was stat() it was refusing to read each file given stating that the file did not exist. Since we were passing a filename with no path, it was using the current directory which was usually not the directory being read. Therefore we store the current dir, change to the directory being read and revert back on exit. The upgrader tool works fine and I didn't have to modify the code of the actual program at all. Not a bad days work since I had to download+compile+install the latest version of GDB since the dev machine I work with has an upgrade of GCC with no matching upgrade of GDB :). DATE: 2004/04/04 -> 2004/04/29 Worked on the upgrader tool, which is to make use of the epi where appropriate. This is the first real test for the library, so it has taken a little longer than expected to develop what is after all a very simple command-line application. The very first problem I encountered was a linker issue on Dev C++. Visual C++ had compiled and linked OK, but our open source alternate was having none this - so far as it was convinced sbrk() was not defined. My initial thinking was that sbrk() was an external lib function and this would explain the linker error. It turns out that sbrk() is implemented in epimalloc.c and that its prototype differed slighty between an external and the statically declared function. As a result Dev C++ was linking to an extern function (ignoring the static function in epimalloc), whereas Visual C++ treated them as one and the same. Remove the extern declaration for win32 and it all works. Thanks the slocombe (user at sourceforge.net) for pointing out a detail that led to this fix. Since I was going down a pure C++ route for this app, I added an error class for the purpose of throw-ing. The class itself is a glorified container whose constructor is used for setting up the data neatly. I found it helpful to contain a string and code within an error as this makes reporting easier. Since this error class is intended to be thrown by the epi and by an app, there is a flag embedded in it which indicates whether the error in an epi or app error. The codes for epi errors are held in the epierror.h itself, but the codes for the app can be determined by the app. One yet unwritten piece of code is something for displaying an epi code & string combination. On the subject of throwing, I encountered a feature that sits in Visual C++, but it prohibited by GCC 3.0+. This piece of code is legal in Visual C++: return epi::error_c(ERROR_INTERNAL); but needs to be modified to this for Dev C++ (GCC 3.2): epi::error_c err(ERROR_INTERNAL); return err; The application would need to work with directories: creation, deletion, reading, detection of and the getting and setting of the current directory. None of this functionality existed in the epi, but has now been added in the following funcs: bool GetCurrDir(const char *dir, unsigned int bufsize); bool SetCurrDir(const char *dir); bool IsDir(const char *dir); bool MakeDir(const char *dir); bool RemoveDir(const char *dir); bool ReadDir(filesystem_dir_c *fsd, const char *dir, const char *mask); The readdir uses filesystem_dir_c class to hold an array of the filesystem_direntry_s struct, which details the directory. The struct is given in epifilesystem.h. The application would also need to copy files about. Not normally a function that used, usually a system call. This has been added to the EPI. Sorted a problem with the GetAt() returning junk under Visual C++ since it intrepreted the dereferencing the *this[idx] as an array of epi::string_c and the pointer position instead of calling the operator[] on the epi::string_c. Moved the crc and md5 code into the epi namespace. The application would need to take two parameters, both of which would need to have defaults depending on what version they were upgrading from and to. For the purposes of speed it is assumed that we are upgrading from V1.27 to V1.28. The parameters taken are "--config-dir=" and "--edge-dir=". --config-dir is where you want you config data to go (which defaults to the home directory of the current user if one exists plus a system specific subdir) and --edge-dir is the current engine directory (This defaults to the current directory). The program will then copy the edge.cfg and any savegames into from the savegame subdir in --edge-dir to --config-dir. A version.dat is written out to prevent accidently re-running and aid any further revisions of the upgrader tool. This file has a crc value at the end to insure against dodgy files being read. DATE: 2004/03/20 Fixed the sliders/thermos on the options menu where they always used to go one movement off the end. Also looked into a problem to do with the +/- screensize change going out of sync with the thermo in the options menu. It appears the two are using different code and one function (M_ChangeScreenSize()) was only updated the one. The screenblocks var was the one in question not being updated. DATE: 2004/03/18 Changed the home directories for the various platform we use. ".edge" is retained for linux/MacOS, "Application Data/Edge" is used for windows. Obviously these subdirs are only ever used if a HOME environment var exists. Cemented the default resolution with a set of #defines in i_defs.h. The default depth is now 16-bit to fix problems with OpenGL code failing to find an 8-bit res, which is not supported anyway. DATE: 2004/02/29 Fixed the epimemorymanager, so that the new/delete functions are actually used(!). Added additional code to monitor the level of memory that is actually used by the code. I'm concerned that the overhead of the monitoring might slow the engine a bit much, but allocation/reallocation/freeing should not be done willy-nilly between frames. We now have something that could adequately monitor the suitation. Hopefully, we don't need to make the code thread-safe as this will result in preformance degradation. DATE: 2004/02/21 Two bugs sorted. 1) Software mode windows were not being drawn under win32 in the correct position. I borrowed the code for positioning windows from the OpenGL version. Its a bit hacked, but it is soon going to be consigned to the cvs history soon, so I'm not concerned about that. It works. 2) Since the app starts minimised under windows, we won't be processing the timer. This is a problem if the initial resolution cannot be set and the program will go into an infinite loop (the delay before trying again is based of the system clock). My solution was to only allow a set number of loops on the initial tick: if the clock isn't moving then the delay will only loop a set number of times. The issue is that is processor speed dependant, but since it should only happen on startup I don't foresee it being a problem. Have had chance to play EDGE using the software renderer, I do think that it would be something of a shame if we didn't introduce a mode in the GL renderer to emulate a few of its oddities. I'm convinced that the GL renderer is indeed accurate, but the game of Doom was written with inaccuracies of the software renderer. Lighting is a very good example: the GL version just doesn't come across as dark enough. This darkness in doom added a lot to the game. Its not massive, but it does need to be considered before the old renderer goes the way of the dodo. The home directory is now used where applicable for storing EDGE data. The '.edge' directory is create and all config files and savegames get loaded/saved to this if it exists. DATE: 2004/02/15 Bugfixing time. Rewrote I_GetModifiedTime() to use win32 api functions. The internals of this function are not supposed to be portable so I was happy enough to stick in something that just worked. The net result is that WAD modification dates are checked against their GWA counterparts and said GWA files are updated if out of date. It should be noted that attempting to use the debugger (Visual C++) on a release mode is not wise since it confuses itself and then you in the process :(. (Bug# 827391). Spent best part of the day toying with window sizing and behaviour. Had to rely on the favoured trick of starting in minimised mode and maximising to get focus. This resolves an issue - on win2k at least - where nothing was being drawn to the fullscreen window. It appears that wglMakeCurrent() is only effective on an active window. Whether this works on Win9x remains to be seen. Encountered a problem where resolution changes were causing the rendering of non-2d objects to stop. Tracked it down to code in the call once RGL_InitUnits() needing to be called again. I implemented a RGL_SoftInitUnits() function which is called on resolution changes (after RGL_SoftInit()). This is not normally an area I venture, so Andrew [Apted] may what to tidy that in his own way. Back to the window positioning. I've added code which works out an area in which the EDGE window can be positioned and enforces the position if the old window position ventures out of that area. Window sizing has finally been sorted. GetSystemMetrics() can return some incredibly useful numbers in regards to screen title, border and frame size. As a result we can now give a exact window size without needed to resort to some hardcoded and guessed at numbers. Only took me 3 years to find that! 8). Its noteworthy that I've only hacked about with the OpenGL windowing (since this is the problem) and have not had chance to sort the software mode in the same way. Almost forgot: Prevented EDGE from having more than one instance of itself running under win32 at the same time. TODOs: * Dragging engine window on the fly (Do we care?). * Make sure software mode still works. Needed for V1.28 release. * Resolution sorting and picklist checking. * Windowed/Fullscreen on the fly (Needed?). DATE: 2004/02/08 Managed to get a build of glEDGE under MinGW. Had a search on the net for a version of DirectX libs for MinGW and found a version for 8. Build and compiled OK and ran fine. Fix an interested bug to do with order-of-execution. Savegames failed to load correctly under the VC.NET version (but did under the MinGW version). It appears that the load code for the save games was dependant on how the code was being generated. The following code: value = SV_GetShort() | (SV_GetShort() << 16); ...is assembled differently on GCC (MinGW/MacOS/Linux) than on Visual C++. GCC does this: Calls SV_GetShort() and push result on stack Calls SV_GetShort(), bitshift 16 to the left and push result on stack OR top two values on the stack. Visual C does the reverse: Calls SV_GetShort(), bitshift 16 to the left and push result on stack Calls SV_GetShort() and push result on stack OR top two values on the stack. Since SV_GetShort() is reading from a file, value is loaded with two very different results. Its hard to say which compiler is correct since the SV_GetShort() were replaced with constants the result would be the same. Needs more investigation. However, the following code forces the order of execution: // -ACB- 2004/02/08 Force the order of execution; otherwise // compiler optimisations may reverse the order of execution unsigned short s1 = SV_GetShort(); unsigned short s2 = SV_GetShort(); return s1 | (s2 << 16); DATE: 2004/02/04 Hacked is some changes to make the berserker and automap last a level. Setting -1 as the parameter for POWERUP_xxxxxx() will result in a level long benefit. DATE: 2004/02/01 Sorted i_video.cpp to compile under C++. Since I only ever debugged using OpenGL I only just got around to the conversion. Fixed a bug where P_CheckAbsPosition() was checking the tm_I (try_move_info_s) before it was being set! Now checks the thing->flags directory. Fixed the issue with monsters resurrecting into another. The resurrection code now checks _properly_ for objects standing in the way. Hacked the armour code a bit since it was reducing the amount of armour I had when picking up an armour suit. DATE: 2004/01/30 Added an array_iterator_c class for the purposes of cycling through the contents of array_c, it is (probably) more efficent than incrementing an index var, calculating the position in the array and then dereferencing the pointer. Never comfortable with friend class usage, but it is appropriate in this case. Wrote the code for hooking/unhooking/calling the flushers in the flusher_list. Also embedded the object within the mem_manager_c class itself. DATE: 2004/01/09 Started building in the mem_manager_c class. The problem for me was not the coding itself, but had been the best way to implement the flushing facility. Anything that wishes to be flushed by the memory manager needs to be derived from the mem_flusher_c class andthen register itself with the memory manager. The function Flush() needs to be implemented by the class its derived from. My preferred name for getting an entry from an array (epi::array_c) and stack (epi::stack_c) had been GetObject(), but M$ have done some interested hacking to their GDI headers to support ASCII and UNICODE versions. The net result is that GetObject() gets interpreted as GetObjectA() and refuses to compile. GetObject() has since become FetchObject(). Its noteworthy that this wasn't picked up by the EPI test since we didn't go the windows GUI routine and the "interesting hacking" would not of been picked up. Also I didn't usually include "epi.h" in the epiarray.cpp and epistack.cpp files. You may have noticed that we've started using a namespace for the EPI (cunning name 'epi'). It seems the tidiest way to break down the code. TODO's from this date: * mem_manager_c to create/destroy 'flusher_list' * mem_manager_c to handle artifical memory limit * mem_manager_c to flush memory under low memory conditions as per old z_zone code DATE: 2003/10/11 Completing writing the basic implementation of the epi_array_c and epi_stack_c classes. Continued to trawl through the mass of warnings generated by compiling the code with C++ restrictions. Most are preformance warning where int values were being treated as boolean values and floats being assigned 'double' values (i.e. 1.0 is a double constant, where 1.0f is the same value as a float constant). DATE: 2003/05/20 After a short (eh-hum) break, back to the grind stone. Two major issues I need to resolve before I can make any real progress with EDGE. 1) the ability to compile on a Win32 platform with remote debugging capabilities and 2) the completion of the EPI so that the development process may be speeded up. This will hopefully be quite relaxing for me, since it will be a break from the meat-ball surgery (re: "M*A*S*H") of developing in the games industry. Quick, clean and tidy - now there is an idealism that will be hard to achieve :). On point 1) I've managed add project files for VC.NET and clear out all the compile errors caused by the FIELD_OFF() defines; however I haven't written the replacement code for DDF and the savegame code; this is now in progress. Andrew Apted's desire to see the parser code re-written will be fulfilled in this one I think. A bit of C++ will certainly help us here. In regards to 2) The EPI will have to be a gradual change - the only addition that will be required first will be memory management. Quick shout out to the developers of Tortoise CVS (www.tortoisecvs.org). Makes for an excellent interface for CVS under windows. I use sourcesafe and alienbrain at work and have to say CVS with Tortoise CVS is a dream to work with (plus you don't have the exclusive checkout issues to worry about 8). I've also had chance to play with makefiles for GCC on the linux version so that all the lib makefiles are called by the 'edge' makefile. The makefile has been moved to root of the codebase. Fore-I-forget, I've received a patch to the SDL code to build under MacOS X for the afore-mentioned Mr Apted (some people can't stay away 8). I will apply this when I've built the EPI up. For the record my current development environments are: Linux Machine: SOFTWARE: --------- GCC 3.2 Anjuta 1.0.2 (GNOME IDE) Maketool 0.7 (Make interface) Redhat 8.0 (GNOME 2.0/XFree86 4.0/Kernel 2.4.18) HARDWARE: --------- Athlon 1.4Ghz 256Mb RAM 30Gb HDD ATI Radeon 9000 Sound Blaster Live! Win2k Machine: SOFTWARE: --------- Visual C++ 7.0 (VC.NET) TortoiseCVS 1.2.2 Windows 2000 HARDWARE: --------- Pentium III 1Ghz 256Mb RAM 20Gb HDD Geforce 2 MX Sound Blaster Live! The linux box is due to be upgraded to a Athlon 2500 with 512Mb of RAM. The sole reason? Doom 3! 8). DATE: 2002/09/08 Implemented some EPI (EDGE Programming Interface) base classes. EPI was originally an idea developed by Erik Sandberg. The system interface code (all files beginning with i_) handled everything specific to each platform, but there were no generic libraries. The EPI was to solved this problem. To aid in the more rapid development of EDGE I have developed my only simple base classes for that very purpose. I'm only planning to use the very basics of C++ classes. All templates, multiple inheritance and STL will be avoided like the plague if possible. It should be noted that this does _not_ mean EDGE will be converted to C++. This could happen, but it is _highly_ unlikely to happen. The original code (for the most part) does work fine and it would lose that aged-old feel in my opinion :). DATE: 2002/04/29 ReadScreen() implemented in software and GL Modes. This VCTX function is now used by the m_misc functions to do with screen shots. DATE: 2002/01/01 Took a fine tooth comb to the source code, so it will compile under C++. Not having had the opportunity to work on EDGE for a while, I've had to drop everything previous and go back to it once this has been finished. DATE: 2001/06/15 Back to back days of development on EDGE - I class this as an achievement :). Made the I_GetModifiedTime function a bit more robust. I've made use of the new function by testing the modification time of the GWA against that of the WAD. If the GWA file is older than the WAD file then EDGE will rebuild the GWA. The engine will not load in the GWA, which means when the playsim starts its initialisation it will build the GWA file. This is really useful in my opinion. DATE: 2001/06/14 Implemented I_GetModifiedTime() on Linux. I've added the prototypes to all the other ports, but I have been unable to test them. DATE: 2001/05/21 Another break from EDGE. All I_WriteDebug() calls have been renamed to L_WriteDebug() and the define has also been removed. Time to get back into the flow. DATE: 2001/03/25 Elevator movement has moved forward, P_ChangeSector() is now aware of other extrafloor sectors, although it takes no account on liquid types. The DDF for Elevators is very much in the same way as floors although the ELEVATOR.DEST_REF does fully function yet (the settings are hard-coded at present, the start is always considered to be the sector->ceil.h and the destination is set to 192). This is my current test DDF config: [440] // EDGE ELEVATOR BASIC TYPE=PUSH; ACTIVATORS=PLAYER; ELEVATOR.TYPE=MOVE; ELEVATOR.SPEED_DOWN=1; ELEVATOR.SPEED_UP=1; ELEVATOR.SFX_DOWN=STNMOV; ELEVATOR.SFX_UP=STNMOV; The work that has been done so far uses the new linkages I have put in place. I'm not happy with keeping up two different methods for linking extrafloors to sectors. I think that I'll eventually remove one of the systems or combine the two. The current method is very much designed around the rendering aspect of the engine and seems to be over-complex for the playsim. DATE: 2001/03/19 Added in the linkages between sectors and their extrafloors. The current code doesn't have link between a controller sector and the sector it provides an extrafloor for; certainly not one that doesn't involve going round the houses for anyway. I'm a pleased to announce a working elevator. It moves up correctly and thats about it. All we have to do now is make it account for the rest of the playsim, move down and fit the specs are the current plane movements. DATE: 2001/02/25 Fixed the stupid error with OpenGL. The window was not properly adjusted to the right in the size on Win32. DATE: 2001/02/18 Fixed the corrupt L_MP3.C on the CVS and recovering from a nuked hard disk. DATE: 2001/02/09 Note to self: Use L_CovertToDB() for Win32 sound code. Continued to work through the whole of p_plane.c. The playsim needs a bit of tiding and I will do that as part of my elevator work. The thing here is that this needs to be done in order to a) pick the overall design and b) improve and optimise. DATE: 2001/02/08 Did an overhaul of p_plane.c: I decided that all moving sectors should be named more correctly as moving planes. I used the generic moving type to create a linked list of all moving parts (planes, elevators & sliders), this move may be reversed as its not as efficent in terms of speed. My aim here is to make a cleaner codebase for the elevator code. I've going to hack in some test data (myself and Andrew have agreed that code linking extrafloor sectors and their parents needs reworking). I have prepared a demo level and the test DDF's are complete. DATE: 2001/02/05 ITs so going to be one of those weeks. Had to upload a bugfix to the CVS source so it would COMPILE :(. DATE: 2001/02/04 Before a use the classes, I want to have a working elevator. I've been working on the bits and committing the changes I've certain of. Moved DDF_GetSectHeightReference() into p_plane.c and made an internal routine. Its not used anywhere else and I can't see any reason as to why it should be a function like DDF_GetLanguageReference(). I've been looking into the networking angle: one benefit of having a nice linux box, is that you can play about with networking without having to continuely restart the machine. Linux network code is not simple, but you can be sure that its not going to fall over for silly reasons. DATE: 2001/01/29 Moved the 'specialdata' into the plane_info_t. I can clearly recall the doom code being listed as compiling with ANSI C with classes, so I integrated this into my design for specialdata. The basic structing involves a moving type (MDT_) with next and previous pointers. This will mean that we can use a single looping routine for each of the moving data. Think its better than the specialdata thing. Must remember to check that '-warp' parameter bug. DATE: 2001/01/28 Fixed the small issue in regards to DirectX and weird unknown crashes either when returning from a function (in Andrew's Case) and doing the Z_Resize() of columnofs in r_main.c (in my case). This was a very hard to locate bug I managed to create mixing up IID_DirectDraw & I_IIDirectDraw2. The differences between the original and V2 interface appeared to be causing the crash. I double-checked and made sure we were using DirectX 7 versions in all said cases. I have to check with Andrew before I can confirm this as a fix. Going to look at the '-warp' bug, seems to be a memory leak, but I've got to look further into this one. My next task is to move the 'void* specialdata' in plane_info_t, but I'm still thinking hwo to use elevators here. Added the ANDYTEMPFIX #define to the makefile, so the sound will work until Andrew has completed his precent_t changes. I was panicing because I thought that in attempting to fix the above problem I'd buggered the sound! Added the MINILZO files to the Win32 Makefile. DATE: 2001/01/15 Implemented the 'i_music_info_t' structure thats been lying about in I_SYSTEM.H for quite a while. I think we incorpate type into this structure as well. I've modified all the system files related and tested them all (except BeOS) they all compiled. Any old excuse to bugger up all the platform-specific code :). I've tested the MP3, MUS & CD for Win32. One thing I have noticed is that there appears to be a bug in the sound code - which is highlight by entering a level and then running "IDKILLALL" cheat. DATE: 2001/01/14 Worked on the build up to elevator code. Continued on the framework: I've added in the functions and structures for the playsim setup. DATE: 2001/01/11 Decided to restart my work on two fronts; one is the DDF to editor config file converter and the elevator code. I started by committing the ddf2edit to the tools directory on CVS. The second front is the elevator code which had been slowly gathering dust: not a good thing for any bit of code. There was talk of renaming sector movements to plane due to the naming confusion that would be huge with the addition of a moving_sector. Instead I choose to call the moving_sector to elevator_sector. I've removed the ELEVATOR #defines so that any dev bugs won't be hidden by enabling/disabling the #define. I don''t think that the elevator code will be too hard to implement. DATE: 2001/01/10 Seems the problem for linedef #10 is not DDF related. The code doesn't seem to activate a sectors sfxstart on satrtup, only on manual movements and changing direction. Fixed the EXE and removed a shedload of debugging notes. Added the code into P_SetupSectorAction(). Its in here, because the code checks whether or not movement should start. DATE: 2001/01/09 Filled in the gaps for the sound looping code. I've done everything for engine code, plus the system specifics DJGPP and WIN32. I had originally thought that the Win32 code wouldn't be too hard to do, then I realised that Microsoft didn't put a little function in to start/stop looping a sound channel. The issue here is that I simply assume to much. The problematic thing here is that Microsoft also managed to completely dump the DirectX docs for V7 (EDGE's perferred version) and hike up V8, which happens to have a different interface. This is gatesy way of forcable moving people on, but leaves me with a problem in relation to documentation. Anyhow, after looking into IDirectSoundNotify I was beginning to get a little worried: this required going into CreateEvent() and windows idea on multi-threaded code. This COM interface is used to call code when a sound buffer has reached a certain point; Not for the faint of heart. I took the simplier route of stopping and restarting the sound without the looping flag. Since Linux and DJGPP have a simple approach I felt that the simple approach here. It worked surprising well - maybe we didn't need to notify interface after all - but it needs testing. I would if the SB PCI will give me grief here? Going back to the actual code I've added a system specific function and two platform functions: bool I_SoundStopLooping(unsigned int chanid); // Stop channel looping void S_StopLoopingSound(mobj_t *origin); // Same format as S_StopSound void S_StopLoopingChannel(int cnum); // Same format as S_StopChannel S_StartSound() used to kill sounds S_StopSound, now it uses S_StopLoopingSound() and is a temp solution to the plane sound code problem. DATE: 2001/01/08 Added prototypes for stopping a sound looping. The need for this has come about because the plane code is causes sounds to stop permaturely on platforms. The problem has been existance for sometime, probably dates back to the DDF-ing of linedefs. DATE: 2001/01/07 Removed the short buffer code from I_SOUND.C. It seems there were some issues arising from SoundBlaster PCI Cards. It seems that every-other card works fine with the exception of a Creative Labs product, no change there then. Maybe thats a little unfair, Creative tend do a really good job normally, but they tend to tweak too much and cause little bugs like this. Apparently Aliens V Predator has a similar problem. I can't really see what the problem was accurately because I've never owned an SB PCI Card, but creating and destroying sound buffers after use seems to solve the problem. Had I more time I would be _much_ more through on finding a solution. DATE: 2000/11/20 Contrary to popular belief, I still exist and have just fixed a minor issue with Win32's I_Video.c. I think it might be better to under hard-code the window and fullscreen code, the aim being to allow it to be switchable. DATE: 2000/10/01 The editor config writer is working very well. I have think of a good description system for linedefs. The system writes a very good Doom2.ini for DOOMCad, but I still need to write one of WADAuthor and Yadex. I also need to update for the latest version of DDF. Continued implementing elevator code. I'm continuing to plan my changes as I don't want to hack this in and also I need to clean the existing code. DATE: 2000/09/05 Decided to best way for a converted was to take the existing parser out of EDGE will all its necessary baggage, it was either this or build a new one, which I'm not keen since the DDF Parser is a complex beast. The ripped out code works OK, once I hack together a system file, implemented the necessary maths files and created a ddf_type.h to hold all the #defines and structs not handled by ddf_main.h. Began work on elevator code. It currently is possible to create a elevator using an extra floor, but it is very messy and doesn't work well. Faced with the option on linking floor and ceiling, I ran a mile: this would be extremely bad coding and confuse the fuck out of everyone including myself. Instead I choose to create an elevator type which will handle this element of the code and won't mean hacking the plane movement code to death. Concerned about the way ceilings and floors are handling in structures, currently that are stored as a struct within a struct, which means they take up space, when not is use - wasting memory. I think that we should setup pointers to data structs instead as this would be better memory wise and wouldn;t look nearly as bad. Added the music info struct to i_system.h. If I know its there I'll do something about implementing it :). Tied a few issues with function naming and commenting. I can read code that looks all the same.... DATE: 2000/09/02 Working on converting DDF to editor config files. I've been lucky enough to get access to a decent linux server through my "dumb" (quite literally) winterm and can work on conversion. Fixed all the DDF Headers from "Doom" to "EDGE Data". EDGE is not Doom. DATE: 2000/08/23 The common MP3 lib code (l_mp3.c & l_mp3.h) had a small bug it in it - the ring buffer read & write positions were not set at any time. This proved to be a problem when closing from one MP3 to another. The L_MP3SetMusicFile() function now sets them equal to each others (means ring buffer is empty). Fixed a problem where some MP3's were causing bad sync errors. These bad sync errors were being caused at the end of some MP3 - I believ they acted as termination and therefore DecodeIntoRingBuffer() returns zero on this error, which causes EDGE to stop the playing MP3. As kester used to say - errors suck. Modified the EDGE code so that any MP3 type entry has to be file-only and the filename - as opposed to the file data - is passed to the EPI. The Win32 code now supports MP3 (thanks to the guys behind XINGMP3 and Andrew Apted common lib code which works a treat): the output is 8-bit 11025Hz Stereo regardless of the MP3 settings itself - the lib code does any necessary conversion. MP3 is essentially a compressed WAV format and therefore access to the sound effects system is required. The DirectSound object for sounds is needed to create a secondary buffer and process the wave data from the lib - I've also managed to get round my serious problem getting a streaming buffer to work and I didn't do anything new.... Working on my GUI code some more. One thing I can say for Micro$oft is that they stick to one method, but once you get use to the methods used its not too bad, although it could be better. Nevertheless, I have produced a set of handlers that will hopefully make creating GUI objects easier and hopefully make it cross-platform also, My first target will be X. The code is basic at present, but it will extended to cover a few advanced features. IN_A_WINDOW #define added. This will force EDGE for Win32 to use a window as opposed to using the whole screen. The code has been tested and the depth of the screen will be changed if the EDGE depth is different to the screen depth. Reworked the sound vol & pan functions: Due to the fact that M$ have said that the panning and volume ranges are subject to change, I have re-written code to convert EDGE panning and volume ranges to their M$ counterparts. Still had to compensate for the fact that below 50% is not/barely (delete as required) audible to the human ear. DATE: 2000/08/13 Working on the tools for EDGE, more than the engine itself. I've worked on producing simple tools ans also front ends. Have added the DDFinWAD tool to CVS which allows integration of DDFs into WADs. Too much for such a short period of time :). DATE: 2000/07/22 Found a bug in the MUS Code - it didn't exit from pause properly because it wasn't told to resume. Worked on getting EDGE to run in a window on WIN32. DATE: 2000/07/20 Fixed a problem with '-infight' and changing levels. It was crashing because the 'targetmobj' was still pointing the freed data. I simplified the routine and removed some code that was now irrelvant. DATE: 2000/07/17 Finally got the MUS Code just right. Next on the TODO List - ALT+TABing and getting it to work without weird effects. DATE: 2000/07/11 Found the annoying little bug in the WIN32 MUS Code: The pitchwheel was not correctly been handled. I could detect that certain notes were not been playing properly and turned some of the great music into sheer pants. I did not include the MUS Code in the release for two reasons - one being the bug and the other being that at that time there was no MUS Support in DJGPP. Now all three main platforms (DJGPP/WIN32/LINUX) support MUS to a decent level I'm happy. I doubt the MP3 Code is going to be so easy to implement. The main plan is that we will produce some generic code that handles the decoding process, which will give a second of sound to stream and this will be passed to whatever sound system is running. How viable this is will remain to be seen, but I feel that using a library to support would be a dis-service to people who would want learn from our code. Besides we only need something relatively simple. The only thing that does need to be done is to make the MUS code for DJGPP and Win32 look similar. Since I took code for several places to create them, it doesn't look good at all, the basic implementation of both is the same and I hope that people can understand how they work. DATE: 2000/07/10 Re-implemented the MUS Code for DJGPP. The first rule of allegro programming with interrupts is LOCK_FUNCTION(). Worked on supporting OpenGL in a window for Win32. I've also added a resource file for Win32, it currently holds a file menu with a very hacked exit routine. I'm going to playing around this to implement front-ends for tools for EDGE. DATE: 2000/07/08 I have been working on porting the original MUS Code so that it works under the current system, should be quick and easy. Tweaked around with Win32 some more. A few minor issues have now been resolved (not being able to click the fatal error dialog box for one). DATE: 2000/07/05 Fixed a minor issue with BCC's Makefile - it didn't think it was compiling a windows application, but working anyway - oops. This is the reason it was starting up in command prompt. Fixed a problem with STANDARDVGAMODES and NT, quite simply the two don't match so it was removed from the DirectDraw creation code. Have been preparing some work for a basic setup program in EDGE. I've been working on the Win32 API to produce a front-end for glBSP also. Looked at the EDGE V1.00 Code to reconstruct the MUS Code for DJGPP. DATE: 2000/07/04 Fixed a few issues with the Win32 Console not updating correctly when alt-tabbing in and out of EDGE, also the cursor is no longer shown on re-entry. Fixed a problem with the automap code not compiling without DEBUG_TRUEBSP. DATE: 2000/06/26 Fixed a few issues with compilation of the new OpenGL code that Andrew Apted has been working with. It would appear that BCC has a different intepretation of #if then most compilers. I have replaced all occurences of #if with #ifdef. DATE: 2000/06/25 Using the new timer that Win32 has I have added buffered input from the DirectInput devices. Its now easier to play in higher resolutions. DATE: 2000/06/18 Disabled MUS Music for release. I've founf that run-time convertion is poor, I will continue work on the MUS->MIDI Conversion. DATE: 2000/06/09 Updated the README.BCC file. DATE: 2000/06/08 Tweaked the WIN32 Console to scroll properly. Fixed a problem within the argument code that was going to cause no end of problems. The current code takes a pointer to the argument string, which might work fine under LINUX and DJGPP, but doesn't under WIN32. Added E_EngineShutdown() which is called by I_SystemShutdown() on a shutdown. I think this is somewhat backward, but I_System.C is probably the only file that should interact with the platform code. Fixed numerous BCC Warnings and an issue with all the IWADs being loaded E_MAIN.C - which for some reasons gets fixed and broken every six months. Fixed a problem with a subtle memory overright problem which turned up with my changes to M_ARGV.C. It was panicing me, but somehow I managed to unearth the little bug that set the turbo-scale to -171726353. Suffice to say it took me two hours to find the little bugger. DATE: 2000/06/07 Removed the engine-specific code from DJGPP's Music Code. DATE: 2000/06/06 It appears that the midiout volume code is only relative to the main volume setting in windows. I must start work on the code to alter the main volume settings. Playlist entries now specify the information format properly, as opposed to assuming by the music type what we info we are reading. I_MusicPlayback() now receives a data pointer in the case of lumps and files. DATE: 2000/06/05 For some reason that I don't fully understand the new timer calls for Win32 EDGE seems to fail at random. I tried starting the timer before any other calls in I_SystemStartup() and killed it last in I_SystemShutdown(). This seems to have solved the problem and since I now know how to get Win32 to call a function interrupt-style, I implemented a tic counter which is now returned in I_GetTime() - same way as DJGPP. Fixed BCC Compiler Warnings. If you ever used Borland's C compiler, you'll know it warns you about more little bits and pieces that really can make a hash of a great piece of code. DirectInput code has been fixed so that any failure to acquire the keyboard or the mouse if not fatal. This allows for ALT+TABing out of EDGE. DATE: 2000/06/04 Fixed numerous warning errors under BCC. I've rigged up MUS MUSIC support under Win32. To the ear its not brillant, but that may have more with my music drivers under Win32 than anything else. I'm going to see what tweaking I can do to improve the situation AFTER I've got new drivers. Modified the default config in M_MISC.C, they don't set any of the keys. This may seem daft, but it means that if uses deliberately don't assign an action, the action remains un-assigned. This does mean that a default config file should need to be released with each binary to set defaults. DATE: 2000/04/21 Fixed a few outstanding issues with the CD Player in windows. It now does repeat play if set to loop. Today I also worked on a the MUS->MIDI converter for DJGPP and WIN32. DATE: 2000/04/18 Added the DirectInput checking for the CAPSLOCK key. DATE: 2000/04/17 Added I_PathIsDirectory() to the EPI. This is because Win32 does not support access() with the D_OK parameter. This fixes the problem with IWAD's and Win32. DATE: 2000/02/26 Started working on changing WIN32 compilers from MSVC to BCC. This change is in part due to Borland's Decision to release its compiler free and in part due to the fact that MSVC doesn't implement optimisation in its standard version. DATE: 2000/02/19 Implement DirectMusic. I am annoyed by the fact that it appears that the microsoft in-ability to go the extra mile and support basic features on current devices exists in DirectMusic. It plays OK, but I cannot give any volume control. FILE: I_DIGMID.C. Added I_UnloadSfx() and modified I_LoadSfx() for the new sound caching by Erik. Added I_CONWIN.C which gives a new output window for the console as opposed to the old default console window which looked like an MSDOS prompt. Its not a brillant terminal window as it doesn't support any codes apart from carriage return ('\n'). DATE: 1999/12/29 Unable to track some malloc problems that occured the yesterday, the crashes where fairly random, but all showed up in the system interface code of both WIN32 and DJGPP. I don't think we have seen the last of that problem. Polished the Sound interface code for WIN32 a bit and did a limited reworking of the DJGPP sound code to output errors to the errordesc if needed. Also the channel control system does not use the allegro handle for reference directly any more. Seems to be rock solid currently. DATE: 1999/12/19 Written M_CheckExtension() in M_MISC.C. This is a little function that compares an extension with a filename and returns information regarding the comparision. The Function Prototype is: exttype_e M_CheckExtension(const char* ext, const char* filename); The const char* ext is a string with a minimum of 1 character and a maximum of 3 - all alphanumeric characters. The const char* filename is a string containing the filename. The return type of exttype_e is as follows: EXT_WEIRD - either filename or ext is invalid. EXT_NONE - filename has no extension. EXT_NOTMATCHING - filename has a non-matching extension. EXT_MATCHING - filename has a matching extension. Using the above procedure, the EDGE engine will detect WAD extensions and add one if none exists. Had to re-jig my WIN32 OpenGL code to actually get it to work. The problem that was to keep the screen copy functions working, although they are not currently needed it is impossible to remove them as coping goes on. The Doom Renderer that the EDGE engine uses was never designed to be modular. However after coding the work around and the code renders nicely. Andrew Apted's TrueBSP renderer (which is in development) is well suited to OpenGL rendering and it produces a nice green and red world (texturing is due soon). More WIN32 work: The DirectSound class I was working on has been completed and I have turned the class in a C module. The C++ code had a few bugs in it that were not found until the extreme testing done under the EDGE engine. I have fixed the small glitches and we now have a fully functional sound system under WIN32 (no more problems with looping and long sounds). The system is simple create and maintain small length buffers which deal with short sounds. Create and dispose of buffers for long and looping sounds. Since most EDGE effects are short and played only once, it means that It does not have to keep creating small buffers for no reason. I did not choose to stream audio as I thought that just creating and destroying would be simplier and less prone to problems on less-than ideal spec machines. I hope to pull together a good C Module and C++ class to distrube for people who what simple sound in WIN32. Another month, another new set of sound prototypes: bool I_StartupSound(void* sysinfo); int I_LoadSfx(unsigned char *data, unsigned int length, unsigned int freq); int I_SoundPlayback(unsigned int soundid, int pan, int vol, bool looping); bool I_SoundAlter(unsigned int chanid, int pan, int vol); bool I_SoundCheck(unsigned int chanid); bool I_SoundPause(unsigned int chanid); bool I_SoundResume(unsigned int chanid); bool I_SoundKill(unsigned int chanid); void I_SoundTicker(void); void I_ShutdownSound(void); char* I_SoundReturnError(void); With the exception of shutting down and the tick function, all functions return something: All bool returns are true on success, false on failure. All int returns are -1 on failure (assume success otherwise). The new addition to the pack is I_SoundReturnError which returns an error string or an empty string on no error. Once the procedure is call the error stored is clears, calling it once again will just return the empty string. This is set if any of the functions return failure. The void* parameter is set for system specific information. DATE: 1999/12/04 Worked on DirectSound and CD-Audio Class. This will become part of a library I intend on building for both test utilities and EDGE itself. The CD-Audio is itself complete, but I am working on a better DirectSound Class. Converted my log into HTML. This is so easy. Web-designers have an easy life :). DATE: 1999/11/24 Written the MIDI handling for DJGPP. I've tested the file handling system to check it works OK, I still need to go over the lump handling (due to fact it requires a function to load into the allegro MIDI structure). I fixed the DDF Parser to deal with unknown control characters and directory seperators. An unknown control character is treated as the character without the backslash. So '\t' is treated as 't'. This was implemented as '\' used to ignore everything if a non-valid control character was found. Directory seperation characters are now defined by the double backslash ('\\') in DDF. This allows for DDF files to be portbale as well due to the fact that different operating systems use different directory seperators. DATE: 1999/11/15 MAXINT is DJGPP specific! Use INT_MAX which is ANSI standard C and is usable by all. I like portable code. DATE: 1999/11/13 Completed the DJGPP CD Interface and the DJGPP system interface. My real concern is that file IO fails when the CD interface is up and running. As a result the saving of the config file is left to the moment prior to closing the debug file. I will feel comfortable when this has minor problem has been removed. I renamed the music functions (as requested by -AJA-) to mirror their sound counterparts. The Music API is now: void I_StartupMusic(void); void I_SetMusicVolume(int* handle, int volume); int I_MusicPlayback(char* strdata, int type, bool file, bool looping); void I_MusicPause(int* handle); void I_MusicResume(int* handle); void I_MusicKill(int* handle); void I_MusicTicker(int* handle); void I_ShutdownMusic(void); to match the sound with: void I_StartupSound(void); int I_SoundPlayback(int soundid, int pan, int vol, bool looping); void I_SoundPause(int channel); void I_SoundResume(int channel); void I_SoundKill(int channel); void I_SoundTicker(void); void I_ShutdownSound(void); void I_LoadSfx(int soundid, void *data, int length, int freq); void I_SoundAlter(int channel, int pan, int vol); bool I_SoundCheck(int channel); A few of the sound API have been renamed to mirror the music API, there have been small changes. The music API requires a pointer to the handle for some of the calls, because it is one good way of indicating failure: a handle of -1 is treated as a non-used music handle. The music handle is otherwise not used by the EDGE main code. Without a working copy of MSVC currently I have been unable to bring the CD Music code upto scratch on that. The MCI CD handler with all need to have the mixer properties available: It is not possible to control the volume via the MCI. Added DDF_MUS.C. This code deals with the playlist requirements, in terms of DDF files it is the most simple. DDF Playlist Descriptor: [] MUSICINFO=::; The entry number is used by other DDF's to reference a music entry; The format can be CD, MIDI, MP3 or MUS; The information format can be FILE or LUMP. FILE means that it will be referencing an external file, LUMP means a data chunk in the wad file. This is ignored for CD Type (although it does need to a valid entry). One idea for the future is STREAM, which could be an audio stream feed via a local intranet or the internet; Reference is a string used for reference in obtaining the music, for CD's this is a track number. Otherwise, when the is FILE, its a filename, when the is LUMP, its the lumpname. Adding the playlist does demonstrate the need to me for further generalisation as some entries removed can only be fixed by the addition of GAME.DDF. S_Start has been renamed to S_SoundLevelInit() as it is more descriptive, S_StopMusic is explicitly called by I_Shutdown to stop the music. This was lacking as previously it was assumed that all audio was stopped by the system interface code: BCD does not stop CD Audio on exit. S_Ticker() has been renamed to S_SoundTicker() with the addition of a new S_MusicTicker(). Isn't this going somewhat crazy on procedures? Not really, it is important that the S_SoundTicker is called often as it maintains the smooth running of the sound effects system: S_MusicTicker does not need to be called anywhere near as much. The music cheat will be reimplemented soon. DATE: 1999/11/09 Used the BCD library as a basis for creating EDGE DJGPP's CD Audio Interface, since it was based heavily on BCD, all functions have a BCD_ prefix. DATE: 1999/11/07 Wrote an OpenGL interface for WIN32. Will start testing as soon as my MSVC CD is replaced. I concerned because the renderers should now be seperated and this is going to cause no end of problems if bot dealt with. DATE: 1999/11/06 Back to the grind stone after some intensive other work. Fixed the zero-based array problem in ddf_sfx.c. Tested the concept of using Borland C++ Builder 3, problems occuring due to use of pure C++ compiler. DATE: 1999/10/20 -> 1999/10/22 Tested a method of reducing the length of code in e_main.c and to kill the code in startup for WIN32. I settle on getting all the functions to return bool depending on if they succeeded without error. The next step was to loop through the functions and exit on failure. I've done 75% of the calls in E_EDGEMain() like this, but I need to make sure that the functions themselves do return true or false correctly. MIDI->MUS conversion outline code has been added in a new S_UTIL.C file. This will be a useful place for code that is not system specific for both sound & music. DATE: 1999/10/16 -> 1999/10/19 Fixed the pausing sound problem. S_PauseSounds() pauses all playing sounds, S_ResumeSounds() resumes all paused sounds. This has required to additional functions to be added to the EDGE Sound System API: I_PauseSound() and I_ResumeSound() have been added and do exactly what they say on the box. This is a slight enhancement on the old system when pausing, which killed all playing sounds. Added I_HandleKeypress to the WIN32 I_CTRL.C, this deals with keys that are caught by the message loop and NOT DirectInput. For some reason DirectX does not handle certain keys well and the PAUSE key is of them. Its important you check that the message loop is not handing you a key that has been held down. This is what if ((lParam & 0x40000000) != 0) break; is responsible for in the I_WindowProc() switch (case WM_KEYDOWN) is for. Tweaked the volume control in WIN32. 50% DirectSound Volume = 1% Allegro Volume. So no-one is playing with an advantage, I adjusted the volume handler in WIN32 I_Sound.C to compensate. The Pan/Seperation calculation is WIN32 I_SOUND.C is now a #define. DATE: 1999/10/15 Fixed the looping problem in DJGPP. I let allegro deal with it, the timing system was not accurate enough and caused a few problems. The sound is only killed now if the sound is not looping. The playmode for looping sounds is logically PLAYMODE_LOOP and non-looping PLAYMODE_PLAY. DATE: 1999/10/13 Wrote a screen shot routine, it uses a new function for obtaining the an RGB value from the current palette (if in 8-bit colour). The routine in V_COLOUR (V_IndexColourToRGB) is needed because TGA format uses RGB Values. TGA was choosen because I had used it in previous OpenGL coding work. TGA uses 24-bit colour with the Red and Blue swapped, the lines are also stored bottom to top. I will add in a PCX format screenshot at some stage, because I did not have time to work out PCX at present. Fixed a problem in E_SetGlobalVars where setting were being overriden here, where that had been already setup in the config file. I now check that the settings have not been set and then check if a parameter sets them. I have been building a MUS to MIDI converter. The formats are very similar with the exception of the way multiply channels are handled. MIDI has a track for each channel, MUS has a single stream of information that tells what channel it is referring to and then what to do. Once I have written this, I will be able to implement MIDI and MUS support in one go. DATE: 1999/10/11 Now everyone repeat after me: LOCKING MEMORY IN ALLEGRO IS VERY IMPORTANT. I could not for the life of me understand why the sounds in my DJGPP version were giving so much grief. I had somehow omitted to lock the memory that my hack-loaded samples was using: A quick point-in-fact, Allegro like most other libraries do not allow you to load raw data into a sound. Having fixed this little problem. I had the effects working as well - if not better - than my Win32 version. Another problem cropped up with I did not expect: allegro seems to have real difficultly in de-allocation of voices after they have finished playing. I had a little blast of E1M1 and the system was running short of sounds. I instituded by use of getting a time (in tics) of when a sound should finish and freeing it manually: this is why having I_UpdateSound() is useful. It really should not be used in Allegro/DJGPP, but comes in useful. I continued to debug the Win32 sound code. So far, I seems to have worked around the problem of sounds repeating: Its not perfect and I'm not happy with it, but it has cured the most of the problem. I set the buffer position to zero when I_SoundKill clears the sound. I think it has to do with DirectX and its inability to stop a buffer playing fast enough. I now have to finish work on streaming sounds longer than the buffers in Win32/DirectX and set the frequency of the buffers on playback. I had for some reason thought that buffer frequencies were fixed (?). DATE: 1999/10/09 I have for the last few days have been plagued by little sound problems. I am now confident that I can play a decent sound in windows without random noise interference. The problem is that locking an entire buffer for even a split second causes noise, something not mentioned in the docs. I did try having a static buffer for each sound which played with random noise; however, since there is likely to more than one occurance of a sound playing at anyone time and I did not want to bugger about with duplicate buffers, I choose to return to using streaming buffers. The trick here is to lock from the write cursor (DSBLOCK_FROMWRITECURSOR) and write the sound effect after and before the buffer. How the Win32 sound system works now is having 16 continously looping buffers which are blanked (value 128) when not used, but sound is written after the write cursor the moment it is played. A time is TICS in kept when the sound should be stopped. Remember DirectSound buffers are circluar. Allegro sound will shortly be re-written. It seems to have real problems when using voice controls, a lot of random noise occurs. Sometimes it will be perfect, other times it will crash allegro. In theory it should work, but does not. Fix this tommorrow. DATE: 1999/10/06 Finished the system specific coding for the sound. The DJGPP/Allegro version is simple enough, however I am not quite so sure about my WIN32/DirectSound code. The DirectSound system is of prototype design, as opposed to destroying and re-building sound buffers all the time: something that may prove to be time consuming. So I took the approach of allocating 16 sound buffers with enough memory to store 1 second of 8-bit 11025hz sound; if EDGE requires to play a sound longer than this, the sound is streamed into the buffer after every half second of sound. I will find out whether it will work properly when I finished the EDGE sound code. S_ResumeSound and S_PauseSound became S_ResumeMusic and S_PauseMusic, respectively. This is all they do. Created S_MUSIC.C: I moved all the music (non-system-specific) functions into this file. Keeping It Simple, Stupid. DATE: 1999/10/05 Actually added a call to E_SetGlobalVars() to E_EDGEMain(). I appear to have forgotten to do this previously. Move a whole bunch of parameter checks to this procedure. Added a lot of the sound code to EDGE. I have concentrated on doing both DJGPP and WIN32 version at the same time, procedure by procedure. I think that once I have completed the system specific stuff I will move onto the main code in general. I have removed the sound length calculation from the system specific code - it should not be system specific. I will complete this work tommorrow. DATE: 1999/10/04 Altered the menu resolution selector to choose a calaculated list of available resolutions. This system works from input from DirectDraw. I am going to look into how this is possible for the DOS Version. I have included 24-bit as a selection as this is planned. The menu selection remember modes, not the width, height and bpp as before. I think that altering all of EDGE's multires to use this is a good idea, but will consult with Erik and Andrew first. Spent last couple of days trying the track a re-alloc problem that was causing a great deal of hassle for Marc Pullen's QDoom. It appears that the re-allocation of memory fails to re-address global pointers. This is major mistake. DATE: 1999/10/01 WIN32 Version now supports hi-colour. I had to manually create the MakeColour function that is part of the allegro library. I think I will have to make it adjustable for other depths of colour as it currently only supports a colour depth of 16-bits. In the future we will probably expand into 24-bit colour and we will also have to support cards that support 555 RGB values in 16-bit colour (as opposed to 565 RGB). DATE: 1999/09/30 Found out why my WIN32 keyboard handler doesn't work: The timer only works when other messages are not being sent. So that means all my keyboard checking must happen once per tic. As opposed to the keyboardISR idea I took from the DOS specific code. This is also why my I_GetTime code failed. My inexperience with WIN32 is beginning to show, however I think that learning the hard way helps. With further examination of the main keyboard handling code and what DirectInput was giving out. I realise quickly what needed doing. DirectInput will only tell you when a key is pressed, not when is pressed then released. In order to do that you keep a record of if a key was recorded as being down on a previous tic. If a key is down, but was reported as being down on a previous tic you don't post an event stating that this key is down. If a key is up, check if last time round it was recorded as being down then post an event stating that this key is up. (WIN32 only). I have also added two pre-calculated tables for the I_ScanCode2DoomCode code, I feel there to be no need to have two big switch procedures, when two tables will do. This is only in WIN32 currently. Changed M_MISC.C read CFG files to store the KEYD code as opposed to the system specific code. This means that EDGE for different platforms can use the same config file. As I am going to add WIN32 Mouse support. A fourth mouse button has been added. WIN32 Mouse support included. DATE: 1999/09/29 Fixed the major error (in WIN32) that was holding the video code up: The dummy screen was not being allocated not correct amount of memory. To rub in the salt, I discounted this as a possibility early on :(. Incidently, it wasn't one of the nuked warnings. I_GetTime code is now based on the timeGetTime() WIN32 function as my SetTimer() system of incrementing 'mselapsed' every tick failed. Keyboard handling works well, with the exception of normal keys. Eventually the system will stop responding to the keyboard totally. For some reason the keyboard can not be aqcuired at all. I going to investigate the problems bugging the WIN32 version. DATE: 1999/09/28 Decided that since I can't trace the error in WIN32 very easily I will have to nuke every warning that MSVC has given. 90% of MSVC warnings can be ignored, but I think one is causing real problems. Removed all the french keyboard rubbish in HU_STUFF.C. Its totally unused. Added (char) cast before all the numbers in HU_STUFF.C shiftxform table. This removes about 40 warnings at least. Cleared up all the warning remaining that required castings. MSVC compiles with 0 errors and 80 warnings. The remaining warnings are to do with the procedure pointer handling by actionf_t. There is nothing I can do about these. Its has however done nothing to kill off my function calling bug. DATE: 1999/09/27 Added M_PI #define to I_Defs.H under WIN32. This is because there is no define for it in MSVC. Fixed some unary minus figure problems in R_MAIN.C. MSVC was compiling that: 'unary minus operator applied to unsigned type, result still unsigned'. The processing order for MSVC and DJGPP is clearly different. In order to get a minus value from: return -tantoangle[SlopeDiv(y,x)]; it needs changing to: return (tantoangle[SlopeDiv(y,x)] * -1); Had some major problems with Win32 video code. The compiler is reporting problems with bad procedure casting, i.e the function was defined with one calling style and used with another. This seems to result in the main_scr width being set to 0, which causes an error. I'm obviously got to take a long look at this. I know for a fact that main_scr->width is set correctly to start off with, but I think the method of picking depth routines is now in question. DATE: 1999/09/25 Moved I_SYSTEM.H to the main source directory. It should not be different between different systems. Someone decided to set a boolean value to minus -1. Which kinda defeated my workaround of setting boolean to an unsigned char. Strictly speaking the value should only ever be 0 or 1. I tracked the problem down the DDF_Anims Code. However, several attempts at a workaround seem to fail for no apparent reason. The problem was that the endname (flat lump) was not being set and some loops were never exiting. Due to time constraints I changed all occurances of boolean to bool. Working in creating a output window for before the switch into graphics mode on Win32 apps. The reason for this is because the debug file seems to stop writing long before exiting the program, so we need a form of output. DATE: 1999/09/24 Add I_EDGELoop to the respective I_SYSTEM.C's and E_EDGELoopRoutine to E_Main.C. Unlike DOS a lot of multi-tasking systems require to control a program. The best example is Microsoft's pet project. I_EDGELoop calls E_EDGELoopRoutine every time the program can run. For DOS this is one infinite loop with no checking; For Win32 this is part of a message handling loop. E_EDGELoop calls I_EDGELoop. Due to some apparent laziness by Microsoft the boolean type gets defined needlessly in some very obscure header file. As a result the boolean definition is now moved from Dm_Type.H to I_Defs.H. typedef-ing boolean as an unsigned char and #define-ing true as 1 and false as 0 works around this problem. I had considered changing boolean to eboolean, but I will wait until the discussion over EDGE typedefs has been completed. I_Warning now prints to the console as well as the debug file. Debug_Printf got nuked and replaced by I_WriteDebug Procedure. Completed all the keyboard startup routines in I_CTRL.C in WIN32. I will now go on to the video controls and hopefully get a basic version up and running on completion. Have completed I_Video Code, but have had several teething problems with how errors are handled and how strncasecmp is actually supposed to work. The code does return non-zero on error as it should, but does not seem to be giving the correct value. The problem I have is that this value is used in the sorting of strings which relys on the correct information. I would like to at this point thank Bruce Lewis for his work on Windoom and his assistance to me on my other projects. It had more than prepared me for porting the EDGE engine, especially working with WIN32. DATE: 1999/09/23 Replaced all occurance of malloc functions in CON_*.* with Z_Malloc functions. Since we allocate a heap we might as well use it. Besides we have control with Z_Malloc functions. Z_Init is now called at the very start of E_EDGEMain so all functions can use it. Removed all I_Printf functions prior to CON_InitConsole. Making my way through all the code replacing all the occurances of malloc functions with their Z_Malloc counterparts. Removed the dreaded alloca() also. Fixed the defines in E_Search.H with Z_Malloc instead of the int var[assumeval] code that is hampering my portability efforts. Renamed the typename var of the cvar_enum_t to typenam. Lets not confuse C++ keywords with identifiers. Unconfused compiler in V_LoadColourmap: the function was adding to a void pointer before being passed to a byte pointer. MSVC did not assume that the pointer was being move in jumps of byte length. Therefore I had to explicitly add (byte*) to force that assumption. With the time at 9:26am got 2 errors and 489 warnings under MSVC. Spent the rest of the day sorting out small errors that had been occured by my extensive removal of non-portable functions and the introduction of Z_Malloc. Finally got a MSVC with no errors. Now I can proceed tommorrow with getting a functioning WIN32 version. DATE: 1999/09/22 Removed all the parameter checks call in I_SYSTEM.C to E_SetGlobalVars. There is nothing system specific about them and they should operate on all platforms. I_ShutdownControl is now called explicitly in I_ShutdownSystem and not using the atexit() routine. I do not like the use of atexit() at the best of times, due to the fact that we are leaving the system in charge. This will also allow for the system to be shutdown and brought back up again if it is ever found to be necessary. Removed all the control shutdown code in I_ShutdownSystem to small functions called by I_ShutdownControl. Allegro Interrupt timer called without allowing for -noirq. I_StartupGraphics removed for E_EDGELoop to I_SystemStartup. Removed the clock checking code in I_GetTime. Interupts only. I personally hope to limit us to the microtimer if enough CPU's support it. I_Error calls I_ShutdownSystem to close system down now. The error is no longer printed in the debug file. I_INPUT.C got renamed to I_CTRL.C. Removed KeyRepeatDelay and KeyRepeatRate for I_CTRL.C and I_SYSTEM.H, they are now represented as #DEFINEs in CON_CON.C. Moved I_StartFrame from E_EDGELoop to the beginning of E_Display. The reason behind this for where a system needed to be told that a frame is about to be rendered. OpenGL is one example. For the record, my first MSVC compile got 2441 errors and 866 warnings. inline statements removed. Incompatible with MSVC. 'long long' is to be replaced by Int64 typedef. GCC supports 'long long' only, whereas MSVC supports _int64. Therefore the follow typedefs occur int i_defs.h: #ifdef DJGPP typedef long long Int64; #endif #ifdef WIN32 typedef _int64 Int64; #endif I expect more to follow. Also #defines with an argument type differ in MSVC and GCC, so therefore all #defines are to be replaced by procedures. Time currently 11:29am with 786 errors and 913 warnings under MSVC. Left EDGE alone to return to do some work of the physical nature, returned at half-hour ago and replaced Debug_Printf & File_Printf with I_WriteDebug Procedure in I_System.C and: With the time at 2:45pm got 495 errors and 850 warnings under MSVC. Removed __attribute__ ((const)) references from W_Wad.H and: With the time at 2:50pm got 180 errors and 587 warnings under MSVC. Added MAXINT #define to the WIN32 part of I_Defs.H. MSVC views this as INT_MAX. I getting confused and cynical. Added numerous 'standard' include files to the WIN32 part of I_Defs.H. A lot of these are not included in MSVC. So I'm going to be writing some functions to compensate. With the time at 3:10pm got 202 errors and 543 warnings under MSVC. Wrote strcasecmp and strncasecmp functions. Added files I_COMPEN.C/H to hold these functions. I'm not sure these functions do exactly what their DJGPP counterparts do, so I going to download the source for GCC to make sure. They do seem to fit the info file description. With the time at 3:45pm got 203 errors and 536 warnings under MSVC. Removed all the inline functions I could find. It would appear that I missed about 33 of them :(. I just do a full DJGPP compile and tested TNT MAP01. Seems to be functioning fine. Now to see if MSVC will give me a break... With the time at 3:55pm got 159 errors and 523 warnings under MSVC. Replaced all the occurances of 'long long' with 'Int64', I missed quite a few of these also :(. Removed all the old system specific stuff that I hadn't replaced in I_*.*. I will complete the code in WIN32 system spec stuff when the main source tree compiles (not links) without error. With the time at 4:20pm got 106 errors and 504 warnings under MSVC. Took a break. Remarked out the internals of blur_view in R_Vbinit.C, the MSVC compiler does not like inline functions written inline of a function. I have no intention of adding #ifdef WIN32 or #ifndef DJGPP defines into the main source. This means that the functions needs to be re-written. With the time at 4:45pm got 53 errors and 503 warnings under MSVC. Removed MAXINT and replaced it with INT_MAX. There is one reference and this #define is support by both MSVC and DJGPP. Added the access defines in DJGPP's to WIN32 of I_DEFS.H. This covers the file access defines used. Remarked out the "portable" code in E_IdentifyVersion. Its another POSIX standard code. Not MSVC specific and we must be as portable as possible. Its a throw up between coding the functions for them or re-writting this E_IdentifyVersion. I think I'll go with the latter. With the time at 5:10pm got 36 errors and 494 warnings under MSVC. The rest of the errors are allocation in the form: void A_Procedure(int arraynum) { int array[arraynum]; // this is barely legal on any compiler } All this working around microsoft stuff is teaching me some bad habits. I just re-wrote a procedure I planned and designed BEFORE hand. Its works an all, which is good. E_IdentifyVersion has been written to lose all the none portable stuff. DATE: 1999/09/21 I_VIDEO.C changes: Removed I_EndRead GetDisk Removed I_BeginRead moved to M_MISC.C (Renamed to M_DisplayDisk) Removed I_EndRead I_InitGraphics renamed to I_StartupGraphics I_FinishUpdate renamed to I_FinishFrame I_EnterGraphicsMode renamed to I_SetScreenSize New parameters for I_SetScreenSize: int width - Screen width int height - Screen height int depth - Screen depth returns boolean - true on successful screen change. I_SetScreenSize returns true on success - Logical R_DoExecuteChangeResolution returns true on success - Logical All D_* files are now E_*. All functions now have an E_ prefix - welcome to the engine with the EDGE. DATE: 1999/09/20 Moved I_GetSfxLumpNum to S_Sound.C. Renamed: S_GetSfxLumpNum. This code is not system specific. Created E_SetGlobalVars is D_MAIN.C to contain all the global var parameter checks. I_INPUT.C Changes: I_StartFrame moved to I_VIDEO.C (Purely a video function) I_InitInput renamed to I_StartupControl I_StartupControl returns nothing (if an error, use I_Error) I_StartTic renamed to I_ControlGetEvents (This is all it does) I_ShutdownInput renamed to I_ShutdownControl I_ShutdownMouse Added (Just in case) I_ShutdownJoystick Added (Just in case) I_KeyboardISR removed from reference (Its an internal function) I_MUSIC.C Changes: MusicTicker Removed, I_MusicTicker should handle this. I_MusicTicker2 renamed to I_MusicTicker I_InitMusic renamed to I_StartupMusic Removed I_StartCDAudio Removed CD_Next Removed CD_Prev Removed CD_Play Removed CheckCD Removed I_SetCDMusicVolume Removed I_RegisterSong (The act of I_PlaySong should do this) Removed I_UnRegisterSong (The act of I_StopSong should do this) New parameters for I_PlaySong: void* data - pointer to data, cd-track number or filename int type - enum for MIDI, MP3, CD etc... boolean file - true if external file or waddata (not relevant for CD) boolean looping - true for repeating music return handle for music I_SOUND.C Changes: Removed I_SetSfxVolume (Handled in S_Sound.C) Removed I_SubmitSound Removed I_CacheSFX Removed I_DecacheSFX I_InitSound renamed to I_StartupSound I_StartupSound now returns nothing. It will effect the global nosound I_UpdateSoundParams renamed to I_SoundAlter I_StartSound renamed to I_SoundPlayback I_StopSound renamed to I_SoundKill I_SoundIsPlaying renamed to I_SoundCheck New Parameters for I_SoundAlter: int channel - current sfx playing channel int pan - new pan value int vol - new volume New Parameter for I_SoundPlayback: int id - sound id reference int pan - pan value int vol - volume boolean looping - repeat forever? New procedure void I_LoadSfx(int *soundid, void* data); Sound id - assigned id number. Data - Sound effects data. I_SYSTEM.C Changes: Removed I_AllocLow Removed I_BaseTiccmd Removed I_ClrScr Removed I_GetMicroSec Removed I_InstallMicroTimer Removed I_ScreenRows Removed I_ScreenCols Removed I_TextAttr Removed I_Waitkey Removed I_Window I_Timer moved to I_INPUT.C I_DoomCode2ScanCode moved to I_INPUT.C I_ScanCode2DoomCode moved to I_INPUT.C I_Init renamed I_SystemStartup I_Quit renamed I_SystemShutdown Created I_DisplayExitscreen - Displays exit screen..... Created I_MoveData(void *src, void *dest, int size) Created I_CloseProgram I_VIDEO.C Changes: Removed I_AutodetectBPP (Replaced by E_SetGlobalVars) Removed I_GetResolution (Replaced by E_SetGlobalVars) Removed I_UpdateNoBlit New exit routines, now: I_SystemShutdown - closes down system specific libraries I_DisplayExitScreen - displays exit screen I_CloseProgram - Exits The order is done like this in cases where the exitscreen does not need to be shown. Removed music and sound system interface calls in s_sound.c. New DDF and portability requires redesign of Music and Sound API. DATE: 1999/09/19 (Mostly done on the fly, my apologies for their short abrupt nature). Added all system specifics through i_defs.h. Had to make a change in Crosshair code: it was using chdir as a int, which caused conflict with the func definition in unistd. I think we should consider uses a graphic from the crosshair here. Removed conflict in wi_stuff.c. A patch_t* time became time_patch, conflicting with time.h func. Stupid name used here. Removed every reference to CD Audio. CD Audio is to be considered a music type just like any other. Disabled CPU Checking. All Functions used are now C Only. I_EnterGraphicsMode got moved to I_Video.c, has been greatly simplified by removing the select_blit_function and all relating stuff. I think that this was probably more trouble than its worth. During the optimisation of EDGE, it may be worth testing the true value of this. I_TruecolInfo (something I managed to omit from my system spec report) got moved to I_Video.C. Removed: MUS_*.* files as these are system specific to allegro/DJGPP. I_ALL*.* files also for the reason above. All I_*.* are moved to SYSTEM directory. I_DEFS.H Remains in the main directory. All files include "i_defs.h", but no other i_* files. Added I_GetHomeDirectory() to I_System.C. Added EDGEHOMEDIR and EDGECONFIGFILE #defines to i_defs.h. Disabled (Remarked out) always-run code in G_GAME.C. Disabled (Remarked out) M_ScreenShot code. Used system specs. Disabled (Remarked out) out all ASM code from the source tree. All system specific includes that do not need to be viewed by main source is now included in i_sysinc.h. Removed I_Error/I_Music/I_Input.H and transferred entries to i_system.h. Removed all CD Cheats and code from M_*.* files. DATE: 1999/09/18 (Yes, this is no mistake. It has been a year) Added a name to the error message to W_CheckNumForName, a useful error message goes a long way. I spent the last day or so finding with system specifics that are spread throughout the code and re-gigging the order for a lot. Work changing all the old DOSDoom Code into EDGE stuff is far from complete and somethings are in desperate need of reworking. A good example is the number of parameter checks in D_DoomMain() - soon to be come E_EDGEMain(). DATE: 1998/09/15 One of major problems with having to break an engine in-order to fix it properly is that it can quite often turn into a long slog of a job, one of the major things that needed to be fixed were the saved games, which had to be altered on a large scale to handle the additional pointers that otherwise would be left undeclared and a definite crash hazard. One of the many things that has been added to the program structures are linked-lists (attack types, current game objects (mobj_t) and so forth). The purpose was to make it easy to do a linear search, although the speed of a search is not the fastest possible. One of the possible solutions for pointers is to declare them as NULL and get the game to assign values again: however the problem that exist that some pointers would be looked for would be found to be NULL and in some cases will crash the game (due to the fact that the number of safeguards in the code is designed to prevent crashes on a running game and assumes that the procedures are correctly handling pointers) also monsters would be asleep when the game is resumed, since they have no knowledge of targets etc; the cheat ability is not good, so this option was scrapped. The second option and the one I have choosen to implement is to record the position in the linked-list of that type. Therefore the position of the target is the current mobj_t list is recorded and restored on loading the game. This works because the mobj_t list is stored in the save game using the same order as was present in the game on saving; the reconstruction order is the same as in the save game. The only flaw in this is that it assumes that the information lists (mobjinfo_t, attacktype_t etc..) are in the same order on loading as they were when saved, this is always correct if the procedures and files for DDF are the same. May be worth storing a checksum of the DDF Files within a savegame. The new warp parameter is: -Warp Since currently only Doom II is functional thats usually MAPxx, so for map 05, you would use -WARP MAP05. DATE: 1998/09/13 Added Fixed and Time Functions to the DDF reader, it is now possible to use both time & fixed-point numbers using numbers with a decimal point: all commands that need such numbers have been altered. This was something that needed to be added to the reader for some time: Since in order to function remotely, DOSDoom requires information in the form of these numbers. Another minor change I made to the reader, was the that the file was read directly into memory and then examined as opposed to the reading and interpretation directly from the file. Teleports no longer use a set effect object for the start and exit points of a teleporting thing. They can be now be defined in sceneryDDF and are indicated by the linedeftype. The linedeftype can specify the effect object at the position left (in) and the position reached (out). SFX cannot be specificed directly, based on the fact that the teleport effect creates the noise. This new system allows for slient teleporters, invisible effects that just produce noise and different teleport types: the hardest trouble I had implementing this the hash table search :). Finished the final work on making the commands in linedef more friendly to the joe-dooming-public. DATE: 1998/09/11 I probably not the best person to work with any type of graphics or the like and I very much tend not touch them with a barge pole, however I have been working with mobj->playxtra to test its effects when used with a DOSDoom defined creature. Originally Doom used to create alterate palettes (calculated at runtime) which were based on the base palette with the exception of altering 0x70->0x7f (Player Sprite Greens) to another group of colours: The original colours were GREY (called indigo), BROWN & RED; they were a form of re-indexing basically, so when a sprite was drawn and had the flags that setup GREY, BROWN or RED, they would use an the alternate palette instead of the base when the sprite was drawn - this translation (remapping) is done at DrawColumn level. Instead of using flags, JC's new 8 player support had to use 4 more colours and as opposed to using more flags, he choose to use a byte (playxtra) that held the number of the translation table (an alternate palette). John Cole had purposed that we use an indexing system (start palette colour, number of colours used) for remapping patches, other multiplayer related stuff and I suppose the player sprite-greens also. I originally implemented the indexing code into patches code (the menu-colour alterations in V0.64 for example) - this system had only one real flaw: To work properly the base palette had to be set out in 16 shades of one colour, 16 shades of another and so forth; continuing through the 256 colours (16 colours with 16 shades). Unfortunately the base palette was only organised in places like this, not all of it: this made any remapping limited, the problem was that to get any sharp contrasting colours, you would of had to remap spreading yourself through the palette. This disallowed decent contrasting white shade and a few other colours! Note: The translation patching in V0.64 remapped all colours into the 16 indexed. My solution is simple, have a pre-compiled remap lump that allows the maximum of 32 colours be re-indexed to create new translation tables. A table consists of 32 remaps, a remap consists of two bytes: the first held the number of the colour index to be replaced, the second held the colour index that would used in replacing. A single remap table would therefore take up only 64 bytes (although expansion to include remapping of the entire palette may be wise and would take up 512 bytes pre table). The wad entry lump that I have included to use this is called PALREMAP and consists of 21 remap tables: 1) Player Green -> Player Grey (Indigo?) 2) Player Green -> Player Brown 3) Player Green -> Player Dull Red 4) Player Green -> Orange 5) Player Green -> Light Grey 6) Player Green -> Bright Red 7) Player Green -> Pink 8) Player Green -> Gold 9) Player Green -> Blue 10) Player Green -> Dark Blue 11) Player Green -> Dark Green 12) Player Green -> Dark Red 13) Player Green -> Red Skin 14) Player Green -> Pale Skin 15) Player Green -> Grey 16) Text Colour Red -> White 17) Red Skin -> Pale Skin 18) Red Skin -> Grey Skin 19) Red Skin -> Blue Skin 20) Red Skin -> Green Skin 21) Red Skin -> Bright Red Skin The player-green remaps are for multiplayer sprites, the Text Colour Red remap is used for the white text and the Red-Skin remaps are test remaps, the red-skin types are used for virtually ever doom creature for skin or blood (most notable are the Demon (whole body), the Baron (Torso) and the Chaingunner (Clothing); to demo this remapping use the commandline parameter '-andymagic'): I'm sure a skilled artist could do a more impressive job of this. Missing: Draw Translucent-Translated Column routine; This is something that is was never written from when the translucency code was added (before the team was created). The translucency is drawn, but none of the colour translation (remapping) is handled - NEEDED URGENTLY - would recommend C & ASM Versions; also I would recommend that someone ASM-codes the translucency code: those plasma firing games slow to a crawl..... Worked on an idea for expanding the key selection that I put to Kester, with his recent developments on linedefs. It is now possible to list the keys you need for a door and the suggest if you need either one of the listed keys or require all of the listed keys (you can now give a list of keys in the linesDDF file). It is now possible to say "you must have the red skull, blue card & yellow skull" or "you need either a red skull or a blue skull". I also had to alter the status bar (st_stuff.c) to show a combination graphic for having both the keys & cards of a specific colour. (added STKEYS6 -> 8 to DOSDoom.WAD) I recommend someone looks into better gfx for these! DATE: 1998/09/09 More minor bug fixing: 1) many WAD's like TeamTNT's Eternal WAD use an effect which causes a floor, a set of stairs or a door to make an instant movement, unfortunately this effect is a WAD Hack, as opposed to design feature. Kester's code had correctly assumed the movement direction required, but the movement speed being used was the default and was not the instant effect required by the WADs. Therefore the different default of -1 was used, which now represents instant movement and can be applied to any linedef. The problem here was the WAD trick used, not the code: it was correct. 2) I mixed up the teleport stomp code, if the thing stomping was a player and the currentmap flags had MPF_NOSTOMP set, then no stomp would take place; should of been if the thing stomping was not player...oops. DATE: 1998/09/07 Bug-fixes: "Stuck-to-a-special-line" monster bug was detected and prompty swatted, the problem was that P_TryMove was testing the movement over special lines and returning false only when the object was referencing a line that it was on the back of, it wasn't taking into account that the linedef could not be activited by the object in question. The solution was to that the activate procedure would return true or false to the question, is it possible for the action to happen, this is then used as the the return value for P_TryMove if the object-in-question was on the front side of a special line. "Changing sector ceiling/floor texture" bug, the problem was the movingPlane structure, it had a set definition for the texture - char tex[9] and due to use of void pointers, and error was not generated when an attempt at mallocing space for a string and giving it to tex; suffice to say that the string referencing was way off. fixed by changing tex[9]->*tex. Fixed two compiler warnings in lu_sound.c & i_sound.c. Formatting: I have a wierd tab setting which makes a lot of source files look odd. Its not unusual for me to go through the code and reformat code from: if (onenumber == anothernumber) { anothernumber = 0; onenumber = 10; } to: if (onenumber == anothernumber) { anothernumber = 0; onenumber = 10; } Its all spaces aswell, so no confusion arises... DATE: 1998/09/06 Toyed with a few ideas, had a nice thought on a meandering state sequence and player supporting monsters, by midday I had all the imps ripping apart everything, but me on MAP18 of Doom II. Works very well. Will push it further and iron out any bugs; might be a useful extension to DDF. Received an update from Kester and merged my bugfixs from two days ago and the current new ideas with the codebase. Worked fine, I made a point of flicking through the linedef pages to make sure it all worked and I understood it: also I did some cleaning up of the code in general I viewed so I could understand it myself! Had to make a few modifications to the new mouse/joystick handling code. The Joystick code (in i_system.c) had a problem with joy_hat as a static int or anything for that matter, so I had to modify the code accordingly (everything names joy_hat became joy_ht); secondly, the two-stage turning (the first 6 tics of turning are slow, the rest are done at the speed of the actual movement) was only designed to work with the Joystick and the keyboard, NOT the mouse. It makes playing with the mouse (as I do) very awkward: therefore I have added a two_stage turning option the analogue option menu. The menu has been renamed from mouseoptions -> analogueoptions. It seems that a lot of the code had been written to make any movements by the analogue object (be it mouse or joystick) to be greatly reduced, this meant that the mouse movement was so low that it became unplayable therefore I have set up a slider for forward/slide/turning movement, that allows the user to select the best choice. I did remember that this was once one of the reasons I used to play Doom95 over Doom in DOS: the mouse sensitivity was better arranged in Doom95, with this new method it allows for proper config of the mouse for each user. A well-choosen set of defaults would not go a miss here either. "The Transporters are off-line" bug; not a bug really, just an oversight, the teleport procedure in P_telept.C was looking for MT_TELEPORTMAN in every sector for its destination - oops, again - the type references are no longer relevant to any object created within the game, therefore no destination points were being found. I fixed the problem by using the mobj linked list to find an mobj (referencing the specials[]) in that sector, the other bug I found in the code was for some reason the distance of the fog from the teleporting object was 40*FRACUNIT, when it should be 20*FRACUNIT. DATE: 1998/09/04 Fixed two irrating bugs I made with the P_ActShotAttack: first I was not setting the correct source angle, which meant that targeting wasn't happening. most notable on MAP29 of Doom II; where the chaingunner on the opposite ledge should hit the guys in front of you at the beginning of the level, however he spent most the time firing above our heads (the enemy and the player object). I made the mistake of subtituting (zero) for the object angle, oops. Error number 2: If the horzaccshift was zero that the objangles angle would be altered by (Random Number - Random Number) bit shifted left (<<) by horzaccshift - yes I should make sure I'm awake before coding. oops again. In my process of missing the object, I did solve the problem of bullets hitting the base of wall with a backsector that had a sky-hack ceiling. Sorted the demo recording and playback. The problem was that the startskill was nor being stored at all, when you started. Not a good thing, sorted that. Also the demos now record the DDF Name of the level, so that its not limited by the gamemap/episode system... Just a note: the top bugfix about when the bullets don't show up against a wall is a good example why demo support of V1.9 is not a good idea. Spawning smoke/puff from a wall uses P_Random(), immediately de-syncing any demo on the spot because the Random Number Generator is now out of sync. DATE: 1998/08/05 -> 1998/08/29 Remember to update often or you leave yourself a hell of Log to write and a lot to remember. During the last fortnight I have began to implement some more major parts of DDF: Creatures/levels/game-setup/languages. For Languages, lu_str.h & lu_str.c have been replaced by ddf_lang.c. This file uses an external file - an LDF (not a DDF) file - which holds the definitions for a language, when DOSDoom looks for a language definition it uses DDF_LanguageLookup(char *ref). The reference it gives is checked against the Language linked list and if the ref is found it will return a pointer to the string referenced itself. In order to do this I had to add a string reading function to the DDF_Reader, as like all parsers it relys on characters to direct it, the string function uses the normal '"' action, that when one is found it reads every character for what it is: ignoring nothing, the only exception is that the DDF Parser will detect the '\n' sequence and substitute a carriage return: when another '"' is found the parser returns to normal operation. An LDF is formatted like this: = so: MAP01Desc="MAP01: ENTRYWAY"; defines "MAP01Desc" as a reference for "MAP01: ENTRYWAY", which means that DDF_LanguageLookup("MAP01Desc") returns a pointer to "MAP01: ENTRYWAY" obviously. This is used when a DDF needs a string, for example: Items.ddf needs a message to display when an item is picked up, this entry is added to an item in items.ddf: PICKUP_MESSAGE=GotMediKit; would ref this in an LDF: GotMediKit="Picked up a medikit, hey!"; so that when this object was picked up it would ref "GotMediKit" in an LDF and for the example LDF "Picked up a medikit, hey!" would be printed. I have implemented a linked list to replace to current set array for the mobjinfo table, with the removal of the type enum (soon to be effected). The number of mobjinfo types in now "limitless". There is a small table of (mobjinfo_t *specials[NUMMOBJSPEC]) pointers to the specials in the list that will be needed regardless of what other things are added. The specials are: Player, Smoke, Blood, Puff, Teleport Fog, Respawn Fog and the teleport-end position. This work has taken place now as it is a requirement that needs to be achieved for DDF, the handling of set down - thing related must be dealt with a reference to its info ref. 90% of this work was done on the 6th so if need to view the changes: look for -ACB- 1998/08/06 in the files P_Enemy.C, P_Map.C & Rad_Trig.C. Implemented and setup the map structure; A map has the following attributes: typedef struct mapstuff_s { char *name; // DDF Name char *description; // Description (automap etc..) char graphicname[9]; // Name used in Intermission char lump[9]; // lump name in the WAD char sky[9]; // graphic sky name char music[9]; // music name char surround[9]; // flat used for the surround int flags; // flags (see below) int partime; // par-time struct intermis_s *interscr; // intermission screen type struct mapstuff_s *next; // next in the maplist struct mapstuff_s *nextlevel; // next level to go char *nextmapname; // name of the next normal level char *secretmapname; // name of the secret level } mapstuff_t; The pointer nextlevel is set when an exit is reached at the end of the currentmap: if the secret exit is used, the name is secretmapname is searched for (compared against each DDF name) and when a match is found, a pointer to it is passed to nextlevel, the nextmapname is used in the same fashion when the level is exited normally. Map Handling FLAGS: Each map has a set of flags, with the id levels only MPF_NOSTOMP is set (with the exception of Map30 of DoomII/TNT/Plutonia, because monsters can stomp you). For new levels, designers have the option to disable such features that effect gameplay or force others. A purist can disable all the new features: these flags override the gameplay menu; if a designer forces a setting, the option menu will not change it. typedef enum { MPF_NOJUMPING = 1, // Disable Jumping MPF_NOMLOOK = 2, // Disable Freelook MPF_NOTRANSLUC = 4, // Disable Translucency MPF_NOCHEATS = 8, // Disable Cheats MPF_ITEMRESPAWN = 16, // Force Item Respawn MPF_NOITEMRESPN = 32, // Disable Item Respawn MPF_FAST = 64, // Force Fast Monsters MPF_RESMONSTER = 128, // Force Resurrect Monsters MPF_TELMONSTER = 256, // Force Teleport Monsters MPF_STRETCHSKY = 512, // Force Stretch Sky MPF_NORMALSKY = 1024, // Force Normal Sky MPF_NOTRUE3D = 2048, // Disable True 3D Gameplay MPF_NOSTOMP = 4096, // Monsters cannot stomp players MPF_NORMBLOOD = 8192 // Use Normal Blood activity } mapsettings_t; ATTACKS... I have finished through the creature.ddf/attacks.ddf files, which handle the movement/actions of the other moving objects in DOSDoom. Formally in a attack frame, the procedure called was specific: an A_* procedure. All new DDF code is P_Act*.* and is used within P_Action.C. The difference between the original code and DDF handling is that you setup a ranged attack and/or close combat attack and called a procedure during a state that calls the individual attack or make a choice between each one. Normally, the object would use a very specific routine, i.e for a baron-of-hell it would fire the item enumed MT_BRUISERSHOT which did a damage in the range of 1-to-8 and multiplied by a number (depending on the missile itself), 8 for our example. The only thing that defined what the objects attack was the very specific attack routines used by the object states, Unfortunately this wasn't very useful for defining and handling of attacks. Instead we have a new attack structure that defines an attack and represents the choosen form of aggression by an object: typedef struct attacktype_s { char *name; // Attack name (referencing) int attackstyle; // Attackstyle int initsound; // Initialisation Sound int sound; // Misc Sound int accuracy; // Accuracy of the attack int xoffset; // X-offset relative to the obj (proj only) int yoffset; // Y-offset relative to the obj (proj only) int height; // Height from the floor (proj only) int range; // Maximum range of the assault int speed; // Speed (Launch-self assault only) int flags; // Flags int count; // Count (Shot attacks, multiple blasts) int tooclose; // If less than, close to target for attack int damage; // Set Damage Value int damagerange; // Damage Range (Doom Damage Calc) int damagemulti; // Damage Multiplier (Doom Damage Calc) int objinitstate; // Spawned object initial state int notracechance; // Chance of no tracing (Tracers only) struct mobjinfo_s *projectile; // Object to create struct attacktype_s *next; // Next in the list of attacks. } attacktype_t; Attack->Name: Used for descriptive and reference purposes, stores the name given to it by the user (in attacks.ddf) and is referenced by the creatures in creatures.ddf. Attack->Attackstyle: An attackstyle can be any of the following: typedef enum { ATK_PROJECTILE, // Projectile: some sort of flying object ATK_SPAWNER, // Spawner: Spawns a defined object in targets direction ATK_TRIPLESPAWNER, // Spawner: Spawns a defined object in three directions ATK_SPREADER, // Spreader: shoots projectiles in a spread (fixed) ATK_RANDOMSPREAD, // Spreader: shoots projectiles in a spread (random) ATK_SHOT, // Shot: Pellet Warfare, traces line to target ATK_TRACKER, // Tracker: Launch an attack that follows ATK_CLOSECOMBAT, // Close-combat: do damage direct ATK_SKULLFLY, // Launch Self: Attack using self as the missile NUMATKCLASS } attackstyle_t; ATK_PROJECTILE: Launchs an attack at the object's target; Uses the attack->height, attack->xoffset & attack->yoffset to define where the projectile starts from. The positions are relative to the object firing, the height is got from object->z + attack->height. A minus xoffset gives a position to the left of the object, a positive one gives a position to the right of the object. A minus yoffset gives a position behind the object, a positive one in front of an object. Normally both xoffset and yoffset are 0. Note: if there is a blocking line between the object and the projectile pos, it will not be fired. ATK_SPAWNER: Launches a spawned object towards its target and the new object's initial state is held in attack->objinitstate. This can be used to a good advantage: the pain elemental uses the second attack frame of a lost soul to make sure it hurtles towards the target when it is spawned. ATK_TRIPLESPAWNER: Same as above, but spawns an object behind, to the left and to the right of the attacker; this was purely designed for the spawning of the lost souls upon death of a pain elemental. However It can be put to an inventive use me thinks. ATK_SPREADER: A Spreader is an project that is aimed at its target and then the angle is then offset. The purpose of this is to counter balance the movement of the object's target. The Doom user of this is the Mancubus. The goes through a fixed cycle: 1) Object angle is altered by 11.25 degrees. 2) Projectile angle is altered by 11.25 degrees. 3) Object angle is altered by -11.25 degrees. 4) Projectile angle is altered by 22.5 degrees. 5) Projectile angle is altered by -5.625 degrees. 6) Projectile angle is altered by 5.625 degrees. The action RESET_SPREADER (P_ActResetSpreadCount) resets the order to 1 should it be required. ATK_RANDOMSPREADER: Same as the above, except that the projectile only is altered by an angle offset that is the numeric value for 90 degrees divided by a "random-number" between 1 and 64. More unpredictable this is. ATK_SHOT: Bullet warfare; This is the attack that covers shotting with pistols, shotguns & chainguns etc. How it works is by tracing a path from the source and following it until it hits a wall or another object. If it is a thing the relevant damage is done and the relevant effect takes place (blood or smoke depending on the thing), if it hits a wall, floor or ceiling, then smoke is generated. The ACCURACY setting is something that comes into play here: multiple firing objects cannot be accurate or they would do some serious damage, so making the shots less then accurate simulates reality as any machine gun will not have the accuracy of a sniper rifle. ATK_TRACKER: Spawns the attack->projectile at the position of the target, what happens next is dependent on both the projectile and the attacker. This attack was designed upon the Arch-Vile attack. To emulate the arch-vile attack, the tracker (attack->projectile) would use the TRACKER_FOLLOW actions where it would follow its assigned target if it the attacker can see its target, thats all the tracker will do. The action now happens where the attacker uses EFFECT_TRACKER: This basically causes the explosion damage; If the tracker for one reason or another does not exist, the explosion damage is not done, but the basic damage is done. The explosion damage is obviously done if the tracker still exists. Although this is the primary purpose of the tracker, it can be used to spawn an explosion at the target area. In true you can spawn any projectile at its target. ATK_CLOSECOMBAT: Does calculated damage to the attackers target if the attacker is within meleerange of it's target. Nice and simple. ATK_SKULLFLY: Launchs its self at speed towards its target and does damage on collision. This is called SKULLFLY because it is the attack used by the lost-soul. Attack->initsound: This is the SFX number used when an attack is being attempted, it is called automatically using (P_ActSkullAttack - ATK_SKULLFLY) or can be called using actions CLOSEATTEMPTSND (P_ActMakeCloseAttemptSound) & RANGEATTEMPTSND (P_ActMakeRangeAttemptSound). Attack->sound: SFX Number referenced when an attack takes place. This is different for each attack: ATK_CLOSECOMBAT - Sound made when closecombat damage is done. ATK_SHOT - Sound made when attack is made. ATK_SKULLFLY - Sound made when attacker hits target. ATK_TRACKER - Sound made when tracker is put into effect. ATK_SPREADER } ATK_RANDOMSPREADER }- Sound made when projectile is launched. ATK_PROJECTILE } ATK_SPAWNER / ATK_TRIPLESPAWNER - Sound made when object is spawned. Attack->accuracy Accuracy level, if zero the shot is perfect, otherwise it performs an random offset bitshifted varied by the accuracy level. This effects the angle of the attack. To be completed..... DATE: 1998/08/04 Added source (struct mobj_s*) to the mobj_t: it is clear trying to make any sense of the procedures was difficult with confusing references. For example: the spawn missile procedure places the source of the procedure in mobj->target, its makes things worse when tracers (revenant missiles) & fires have to know their targets. The original id solution was to add a new struct mobj_s* tracer to hold it - suffice to say it was bloody confusing when reading the code through, the new suitation is: * mobj->source - holds the source of the missile/fire * mobj->target - holds the target of any object * mobj->tracer - holds the fire for the source mobj (normally an arch-vile) P_Mobj.C, P_Map.C & P_Enemy.C require changes. It worth noting for all those people who use DOSDoom as a base and stops them getting as confused as me :). Implemented a fix from Erik Sandberg to allocate space for stateinfo in DDF_MainSplitIntoState: some moron who remain nameless (i.e. me) forgot to allocate space for it, something that Win95 appeared to let me get away with. In DOS it would crash out with a page fault (for obvious reasons). Fixed the problem within the resurrect code that cause monsters to start up and head off in one direction and do nothing until it hit a wall: The movecount was not being reset to Zero, movecount is being used as a counter until respawn. (In P_Mobj.C). Added P_MobjCreateObject, this procedure is the same as P_SpawnMobj with the exception of using a pointer to an mobjinfo_t as opposed to a enum reference. Eventually P_SpawnMobj will be removed. As a lot of new procedures, or modified versions of existing ones come into play, the original ones will be deleted as they are not needed. This is for the transition to DDF from the fixed style originally used. I'm looking at naming procedures with a ref to the file they are in aswell as the type of procedure they are..for example: P_RemoveFlyingMissile -> P_MobjRemoveMissile P_itemRespawn -> P_MobjItemRespawn has been done: P_Mobj is the file, the latter is a description. Its good for people who need to pick up the source and educational purposes. Added/Finalised the attacktype_t which will be used when a mobj goes on the offensive, the mobj_t has a currentattack and mobjinfo_t holds two: closecombat and rangeattack. Added new procedures to P_action.C for the attacks side of DDF: P_ActLaunchMissile is like P_SpawnMissile, however the type of missile launched is an mobjinfo_t* not an enum plus uses the new attacktype_t to discern what projectile is fired, offsets used, height of attack etc.. P_ActCheckMissileSpawn is the same as P_CheckMissileSpawn in P_enemy.C: the code is placed here as eventually P_CheckMissileSpawn will be removed for P_enemy.C as it will no longer be needed. Moved the #define BASEYCENTER to a global variable that is calculated in multires setup. BASEYCENTER is used player weapons. There was a minor offset that "fixed" weapon heights for 400x300 and 800x600 because of the different aspect ratio, the offset being an increase. This caused weapons in a res of 640x400 to appear one pixel above the bottom of the screen, this is fixed by reducing the offset, if this is not done by half a FRACUNIT the weapon clipping is wrong for 400x300 and 800x600. DATE: 1998/07/31 Rewrote the entire Items.DDF & Scenery.DDF files to pick the sprite at each state this was necessary, because I had not anticipated the combinations of sprites that have occured, one name for the spawned object and a different name for the death frames. All the DDF_*.* have been changed to reflect the use of a void pointer in commandlist_t: it was previously a int pointer, I had made the mistake of not setting this as void earlier, so that it is generic. allows the use of any data type pointer in commandlist_t third parameter. A dummy procedure exists to replace procedures that have no useful function on certain DDF files (switches and animations for example, they do not need to read the name). P_RemoveFlyingMissile was added to p_mobj.c, this was to handle missiles that went through the sky properly. The missile should remove itself, but it should not stop the sound it is playing, the fact it is the sky doesn't mean you cannot hear the sound. New code has been added to handle a missile hitting a floor or ceiling that is a sky-hack (P_Z & P_XYMovement). Added in Kester's additional code: DDF_Anim.C has been added. DATE: 1998/07/30 Bug fixes mostly: Ghosting BUG caused when an arch-vile or new nightmare respawn raises a creature that was gibbed (Height and Radius of Zero) and the radius and height remain like this, height and radius are now restored from the info table, not the fallen mobj. Fixed the spawning of a stasis imp at 0,0 - P_KillMobj was not setting the mobj with a MF_DROPPED flag and when the item was attempting to respawn an object that held no info on its original status or position. Itemrespawn-que was made "limitless" and different respawn times are now possible, this has been added to Items DDF. As opposed to two set lists of time and mapthings, it is now a double-linked list of items. item-in-que being the entry. newnmrespawn, respawnparm & respawnmonsters have been replaced with respawnsetting; Nice and easy with one. Added these files to cover DDF Requirements: DDF_ATK.C - Attack types DDF_CTRE.C - Creature types DDF_GAME.C - Game Configuration DDF_LEVL.C - Level Configuration DDF_LINE.C - Linedefs DDF_SECT.C - Sector Definitions DDF_SWTH.C - Switch Definitions DDF_WEAP.C - Player Weapons DATE: 1998/07/29 Removed some of those awful goto's that existed in P_Map.C; trying to trace a goto is a bastard most of time, without it being badly done. I also removed A_ChaseNoMissile from P_Enemy.C, this was an earlier replacement for several goto's within A_Chase and found a more understandable way of writing the code. Found a bug in D_IdentifyVersion, it was adding Plutonia in DOSDoom mode (it should only add Doom.wad & Doom2.wad); I reworked an old version of the code I had written and replaced the existing that works, looks in the correct directory and loads the right wads (sorry, Kester - had to nuke your code again). Heres a description of the DDF Parser, which is long overdue. The DDF Parser is a simple reader that is very limited in error checking, however it can adapt to most tasks, as is required for the variety of stuff need to be loaded in order to configure the DOSDoom Engine. The parser will read an ascii file, character by character an interpret each depending in which mode it is in; Unless an error is encountered or a called procedure stops the parser, it will read everything until EOF is encountered. When the parser function is called, a pointer to a readinfo_t is passed and contains all the info needed, it contains: message - message displayed on the screen. filename - filename to be read, returns error if NULL DDF_MainCheckName - function called when a def has been just began DDF_MainCreateEntry - function called when a def has been completed DDF_MainFinishingCode - function called when EOF is read currentcmdlist - Current list of commands Also when commands are referenced, they use currentcmdlist, which is a pointer to a list of entries, the entries are formatted like this: name - name of command routine - function called to interpret info numeric - pointer to an int value (possibly changed by routine) name is compared with the read command, to see if it matchs. routine called to interpret info, if command name matches read command. numeric is used if a numeric value needs to be changed, by routine. The different parser modes are: waiting_newdef reading_newdef reading_command reading_data reading_remark 'waiting_newdef' is only set at the start of the code, At this point every character with the exception of DEFSTART is ignored. When DEFSTART is encounted, the parser will switch to reading_newdef. DEFSTART the parser will only switches modes and sets firstgo to false. 'reading_newdef' reads all alphanumeric characters and the '_' character - which substitudes for a space character (whitespace is ignored) - until DEFSTOP is read. DEFSTOP passes the read string to DDF_MainCheckName and then clears the string. Mode reading_command is now set. All read stuff is passed to char *buffer. 'reading_command' picks out all the alphabetic characters and passes them to buffer as soon as COMMANDREAD is encountered; DDF_MainReadCommand looks through for a matching command, if none is found a fatal error is returned. If a matching command is found, this function returns a function pointer (into DDF_ReadFunction which is used to interpret the data), a command reference number to command ref and sets the mode to reading_data. if DEFSTART is encountered the procedure will clear the buffer, run DDF_MainCreateEntry (called this as it reflects that in Items & Scenery if starts a new mobj type, in truth it can do anything procedure wise) and then switch mode to reading_newdef. 'reading_data' passes alphanumeric characters, plus a few other characters that are also needed. It continues to feed buffer until a SEPERATOR or a TERMINATOR is found. The difference between SEPERATOR and TERMINATOR is that a TERMINATOR uses the DDF_ReadFunction and then sets the mode to reading_command, whereas SEPERATOR uses the DDF_ReadFunction and a looks for more data on the same command. This is how the multiply states and specials are defined. 'reading_remark' does not process any chars except REMARKSTOP, everything else is ignored. This mode is only set when REMARKSTART is found, when this happens the current mode is held in formerstatus, which is restored when REMARKSTOP is found. The maximum size of BUFFER is set in the BUFFERSIZE define. DDF_MainReadFile & DDF_MainProcessChar handle the main processing of the file, all the procedures in the other DDF files (which the exceptions of the Inits) are called directly or indirectly. DDF_MainReadFile handles to opening, closing and calling of procedures, DDF_MainProcessChar makes sense from the character read from the file. DATE: 1998/07/27 Cleaned up P_Local.H to be understandable (just) and rewrote the P_CalcHeight in P_User.C so that when dead, you don't bob. Also only calculates bobbing when your are alive. Freelook is now limited by two defines: LOOKUPLIMIT & LOOKDOWNLIMIT; Makes this readable. New Action Procedures are now contained in new file P_Action.c; So all the new action code was transfered from P_Enemy.c and use a prefix of P_Act* as opposed to A_*. I hope to include all the new generic action code with P_Action.C. DDF_Main.C's Action Pointer Table was changed to reflect this. DATE: 1998/07/26 Stream-lined the existing DDF Code; I was still using some virtually identical functions for some things, so DDF_MainGetNumeric, DDF_MainLookupSound & DDF_MainCheckCommand replaced their ddf_item & ddf_scen counterparts; passed a pointer to the respective commandlists also, that being was the only difference in code. DDF_MainLoadStates also had a minor revamp. Added the additional bits and pieces to sceneryDDF for explosive items, now complete. Can be variable or set damage from explosions. DATE: 1998/07/25 Worked on the networking code, developed the extended options and made the display more friendly. Continued expanding sceneryDDF to include the explosive items (which at the moment stands at a barrel). I had a lot a played with the idea of key selection. Looks like this will need some changes to networking code. I have tested the networking code and believe the problem caused by a true3d option. Will need to further investigate that little problem. DATE: 1998/07/24 Recieved ASM code from Rasem for the R_DrawColumn & R_DrawSpan; Very impressed as it shaved a huge 4.7fps off the current speed in hicolour mode. Although bits and pieces can be slower. DrawSpan is faster, allowing for a noticable difference. DATE: 1998/07/21 Removed the fatal error in P_SpawnMapThing (where it reads a thing that is not defined, i.e. no matching doomednum in mobjinfo_t) for JDS Compliance, this only makes a report to the debugfile when DEVELOPERS is defined. Fixed the bug in P_FindNextHighestFloor: The procedure was not taking into account floors of the same height, it should have been returning this value. DATE: 1998/07/20 Rethought a lot of the plans for DDF in DOSDoom, it was clearly apparent that certain things need to be generalised (DDF) procedures; The "pellet warfare" attacks should all be one procedure for example. Removed Menu Shade Selections: maybe that wasn't such a great idea :). There are now two control menus (standard & extended) based on the space and also the two distinctive sets of controls. Standard Controls are need to play the game; Extended Controls are assistance controls. DATE: 1998/07/19 Fixed the flicking weapons bug (my fault, not resetting centerfrac in r_things) and completed the integration of M Howe's Work. I have also added in the NightVision code and added it to Items.ddf. Continued by clean-up of the DDF Parser and added DDF_MainFinishingCode which is called when the EOF is found on the current DDF File. Added the following files: DDF_Scen.C - Scenery Objects Parser Code D_Debug.H - Kester's Debug File Removed the 'offensive' end messages from dstrings.h (Note: fix the filename) I was getting an increasing number of mails on this, so i removed it and cleaned up the code in M_Menu.c. Cleaned up DDF_Main.C & H again: Removed any scenery items Removed any unused states Corrected the enums Added the actions table (straight string comparison) Added the specials table (straight string comparison) Made states & sprite checking code generic, moved for ddf_items.c Added addition action code to p_enemy.c (add new file to place this) God knows what else.... :). Added Kester's major bugfix to V_Init8 and V_Init16. Added the i_love_bill setting in: use '-ihatebill' to switch it off. DATE: 1998/07/17 The demos work fine, but the networking is completely up the creek which is something I did anticipate and will need to spend some time fixing. I have spent a lot of time playing around with the menus and decided that the menu shades had to go and seperated the controls menu into standard and extended controls. There is still a lot of work to be done on the menu system. I took a look at the true3d stuff (putting Martin Howe's stuff in) and realised that there are a few things that were not anticipated by Kilbert the person who originally sent in the code and I will need to talk to Martin on this. The Debug File stuff in d_net.c, now has DEVELOPERS wrappers around and uses the debug_Printf system from d_debug.h. I attempted to add the code by Erik Sandberg for new Code for MMX, but it sadly was not designed for a normal Pentium with MMX (K6 more like) and even with the MMX code disabled it caused havoc with my sister's P120. So I have remarked it out, until Erik can find the problem, also there are problems with using it with an AWE64. However he did manage to get the original ASM working with the limitless screen allocation bits (great!). I will include More of Erik's, Dave's and Martin's work when I continue the work on networking, cause it affects a lot of the work. DATE: 1998/07/13 With Kester removal of the demolimit and made the required changes to the ticcmd_t, vertangle and extbuttons added: vertangle is the change in the vertical angle of a player weapon, extbuttons used for new dosdoom only stuff; JUMPING etc. I had to add an entry to mobj_t also, vertangle again - it is actually easier putting it here than in the player structure; DOSDoom had a very hacked approach: it set a global variable that was altered directly, It seems to work a lot better than it did before and mlook is now record in demos and passed over the network, which breaks compatibility with the original EXE. This compatiability is a pain, I feel that when ID released a new version they cared little for compatibility with older version so why should we? DDF code got reworked, The code was rigged to only work for items DDF and did not allow any flexability. The call to DDF_MainReadFile now passes a pointer to a struct with the filename, message and the functions required. I will be continuing my efforts to clean up the DDF parser code. Took a dive into the Radius Trigger Parser, had to make some adjustments so that DDF and Rad_triggers work together, the object generated is referenced by its mapnumber (so the docs will need updating) and also corrected an error where an object was being generated and its was not checking whether it landed on something, therefore the object does not generate if it lands on something. DATE: 1998/07/04 Spent the entire week learning how NOT to fix certain problems; I have been looking at getting the demos to sync properly: mlook is not recorded in the demo as its implementation would require an few changes to ticcmd_t; I do not know whether we should support original demos: this causes problems as DOSDoom's handling of events is sufficently different that of the id EXE. This requires further thought, One of the major problems that always crops up is maintaining compatibility and I am having my doubts about the wisdom of doing so. Fixed a minor bug with weapon selection; Games without the double-barrel now do not have a key to select them. DATE: 1998/07/02 Demos now record as with a Version number of 065, the additional features that would effect gameplay are now stored within the demo. Will be adding the additional mlook code to it. Mlook will auto-aim if it can find a target: if not the weapons shoots it the direction it was fired. DATE: 1998/06/30 Apart from three bugs..is what I should have said: I was trying to compare an unknown pointer with a string (amatuerish mistake). I have been looking at at syncing the demos: Doom V1.9 sync without problem, assuming you haven't got any of the features enabled, DOSDoom does not record its addition features and this does cause some hiccups along the way. I need to investigate further and solve any more problems that crop up. Also added a CPU check at the beginning to assist the asm coders: it will allow us to choose the specific routine optimial for that processor. DATE: 1998/06/29 Hooked in the DDF Reader and apart from 2 bugs, if worked fine! The items that are picked up are now defined in the items DDF. I need to do more ground work to complete this for all functions, however I am a bit happy. The work here was rewriting/writing the reader functions and the correct handling for all of it. I'm too tired to explain the whole bunch of things. DATE: 1998/06/27 Finally got round to updating this log after numerous hic-cups. The Ground work for weapon selection and DDF Items has been done, all that needs to be done is the reader and the file itself. I have had chance to add in code from: Kester: Contined work of removing of limits, ddbug12.wad (Ian Wilson) & runbuddy.wad (Chris Dale sent this) both now work! Hey, hey. Martin: Ground work for a jetpack, added this as a benefit type for DDF Items. File changes: LU_INFO.* => DDF_MAIN.* DOOMSTAT.* => DM_STATE.* DOOMDEF.* => DM_DEFS.* DOOMDATA.* => DM_DATA.* DOOMTYPE.* => DM_TYPE.* LIBAMP.H => MUS_LIB1.H JGMOD.H => MUS_LIB2.H D_ITEMS.* => OBLIVION (got removed, table moved to DDF_MAIN.*) OBLIVION => DDF_ITEM.* (New DDF Features) SOURCE DIRECTORY CHANGES: Removed DJGPP dir, moved contents back into Main directory. (Since we have no time to work on LINUX Version, lets make things as simple as possible). Added MAKEFILE for all those who don't like RHIDE. Added LIBS directory and placed the LIBJGMOD.a & LIBAMP.a files. (The purpose of this is that we should limit the size of src zip where possible, post sources at the website). P_INTER.C has been changed on a major scale, P_TouchSpecialThing has been altered to give the benefit from the mobjinfo_t table as opposed to checking to see what sprite the thing has (it was sprite-ist!). All the procedures have been altered to accept actual amounts from the things and also the limits imposed. The duration of each benefit can be specfied assuming that the benefit is judged in length of time: as opposed to the old method of a LUT, there is also a limit to the benefit time, which is specified in the thing, to use the original effect you have give the same amount as the limit (no higher, no lower - that value or else), making bigger limits gives the user chance to top-up on the time they have left on a benefit. The Ammo amount is give directly, as opposed to number of clips for that ammo. If the armour value given is bigger than 100 the armour type is 2 (blue armour class), else it is 1 (green armour class) - limit for this is specified in the thing. mobjinfo_t has a new addition - backpack_t (a pointer to), which contains info on weapons held, ammo for all types, the most ammo carried for all types, the keys carried, armour and the armour type. This allows multiple different backpacks to be generated by DDF-Items. P_SpawnPlayerBackpack (new Procedure in P_INTER.C) is a bit experimental, it gives all the stuff a dead player died with and generates a backpack with all this stuff in. It does work, but until the Multi-player works properly I can't tell you if it works in deathmatch. P_USER.C/ST_STUFF.C/P_INTER.C: Keys 1->7 have a mapping system, you can choose a primary and secondary weapon for each key, if you have a weaponed mapped to a specfic key it will show up on the weapons owned table. It has no menu so far (working on it). It does mean that if the Double-Barrel is owned, but the single-barrel is not then the number 3 will show up (which it did not before). Changed the weapon enum order in to a logical order and gave the weaponinfo_t a new entry - weapon name. This will be used in the M_Option.C file for selecting weapons as described before-hand. weaponupdate is the flags that tells the weapon widgets on the status bar to update. DDF_MAIN.C (DDF_OldThingInit) just sents up the benefits info for the existing things, When I get the reader sorted, I will removed these and their entries within mobjinfo[] and state[] tables. DATE: 1998/06/18 Lesson: Don't bugger about with something you don't fully understand. The modifications to I_ALLEGV.C cause more problems than it solved. I've tracked the problem down to the use of allegblit(). When this is used it treats black as being see-through, subed the use bankedblit instead. added SCREENDEPTH a global variable that holds the calculation of SCREENHEIGHT*BPP. DATE: 1998/06/14 Reworked the PatchIndirect system, it normally scales the graphics up to the actual res, which when your running 400x300 or 512x384 it looks somewhat tackly, instead downsized the graphics to a ratio of 320x200. Anything that is between 320x200 and 640x400 has a scaled res of 320x200, anything between 640x400 and 800x600 has a scaled res of 640x400 and so forth. Attempt to fix the dodgy resolutions by forcing either the use of VGA or VESA2L modes (which seemed to work for me) in I_ALLEGV.C. The Options Menu and other text menus center themselves vertically. New Mouse Options menu. DATE: 1998/06/10 Add HUlib_drawTextLineTrans(), just like HUlib_drawTextLine() except it uses the translation table for colour by JC. First Change: In Rad_trig.C changed HUlib_drawTextLine() to HUlib_drawTextLineTrans() with grey as the colour (TIP_DisplayTips). Forced the status bar to refresh when a key is picked up. Fixes problem when a key picked-up did not show up on the status bar. (P_GiveCard) in P_Inter.C. Added Linedefs #9000-9006 (scrolling walls), coded passed to me by JC. P_SPEC.C (P_SpawnSpecials & P_UpdateSpecials). Piece of advice, don't enable all of these at one room - does your head in! May have to change to linedef number as not to impose on those already used by other ports. DATE: 1998/06/09 Fixed the error with selecting the supershotgun in doom/utlimate doom. added check for the gamemode in ST_STUFF.C. If the user tries 'idgive3' nothing will happen, 'idfa' and 'idkfa' do not make the supershotgun available. Users can no longer try 'idgive6' & 'idgive7' when in shareware doom (also in ST_STUFF.C). Removed all references to '-cdrom' parameter on account that noone should be playing this from a CDROM. Fixed the 'You haven't picked a quicksave slot yet!cD' Bug (also the French Nightmare Message Bug). Insufficent space allocated from the display string in m_menu.c (m_drawer), increase size from 40 to 50 chars. Set the length of tips in rad_trig.c to 50 (56 is too big). Fixed to problem with displaying HU_text at High Resolutions - Wasn't not displaying the text (only half). (HU_LIB.C). DATE: 1998/05/30 DOOMSTAT.H - Added lostsoulability & spectreability as extern ints. D_MAIN.C - Added lostsoulability & Spectreability as ints. P_ENEMY.C - (A_Look, A_StandardRefire, A_FaceTarget) added invisibility decrease check (if thing stealth) (A_Chase) added invisibility increase check (if thing stealth) (A_Fall) set invisibility = 0 (visible) P_INTER.C - (P_DamageMobj), added invisibility decrease check (if thing stealth). P_MOBJ.H - Removed MF_TRANSLUC25 / 50 / 75 flags in the flags enum. Added MF_STEALTH flag to the flags enum. Added invisibility setting to mobj_t (0=Visible >> stages of translucency >> 4=invisible) R_THINGS - (R_ProjectSprite) setup that if thing is invisible ignore (return). (R_DrawVisSprite) if transluc then use transluc 50% draw. check vis->invisibility to set transluc draw. P_MOBJ.C - (P_MobjThinker) Add sections of code to change lost souls and spectre flags for their visibility/ability. M_OPTION.C - Two New Procedures: (M_ChangeLostAbility & M_ChangeSpectreAbility), alters the info->flags of lost souls/spectres respectively. If also sets the update flag so that P_MobjThinker will update all the relevant things when they "think". Added the options to the options menu. Re-ordered the look-up table colours. Doom-Red is now default. Translucency is now only on and off. Spectres and Lost souls can be: Visible/part-invis/translucent/stealth. Renamed all local procedures M_* to be consistent. G_GAME.C - Unremarked translucent settings and picked out things that were requested to be translucent. Added code to change the flags of lost souls and spectres according to lostsoulability & spectreability respectively. DATE: 1998/05/26 Notes: Temporary fixes for all DDF altered stuff (i.e. correct damage done). Added Global Video Variables: SCREENWMULTIPLIER, SCREENHMULTIPLIER, SCREENWDIVISIER, SCREENHDIVISIER for deltax? and deltay? in the V_Video?.? so that program does not calculate these each time - InDirectPatch procedures. Added: V_DrawPatchTrans8() + V_DrawPatchInDirectTrans8() in V_Video1.C V_DrawPatchTrans16() + V_DrawPatchInDirectTrans16() in V_Video2.C V_Trans.H added (colour translation) M_WriteTextTrans() in M_Menu.C Menu Colour Configuration in Menu (All above code from John Cole - cheers). Options, Video, Control and Gameplay have new graphical title (in dosdoom.wad) Options, Video and Gameplay menu centered. Options Menu has new functions: Zombie Targeting (uses lessaccuratezom which is default.... ...be a psycho, put zombie targeting on perfect!) (Uses code for DDF STUFF) Monster Respawn (None/Teleport/Resurrect Style) ST_STUFF.C: Added the new cheat codes (see dosdoom.his) Pre-DDF Hacks added. A LOT OF CODE CLEANUP! DATE: 1998/04/26 Notes: Human Madness REMOVED Human Explosions REMOVED New AI Temporarily Removed mobjinfo_t in INFO.H has new items - (Definable things) continuning * P_ENEMY.C & INFO.C (new procedures):- A_ChaseNoMissile - program re-structuring A_ZombiePistolAttack - replaces A_POSATTACK (Definable things) A_ZombieShotgunAttack - replaces A_SPOSATTACK (Definable things) A_ZombieChaingunAttack - replaces A_CPOSATTACK (Definable things) A_DeadlyPistolAttack - new accurate enemy pistol attack A_DeadlyShotgunAttack - new accurate enemy shotgun attack A_DeadlyChaingunAttack - new accurate enemy chaingun attack A_StandardAttack - replaces normal enemy attack (not complete) A_StandardRefire - replaces refire for CPOS, BSPI & SPID Overview of changes: Human Madness & explosions removed (crap I did earlier). New AI was temp. removed - to be added to the definable thing. The new procedures are added and existing ones are replaced to make the doom engine more dynamic. The aim is to have all the thing info loaded at runtime from a ASCII file - this will make dehacked obsolete as you can directly tell the engine all the info for a thing and modify it accordingly. This is the earliest very stable version I have and the definable thing is well on its way to completion. Hopefully doom with a -game parameter is possible. INFO.H is also the focus for change. NB: Until I complete the standard attack procedure, all close combat damage will be that of a Baron of Hell! A standard attack is the normal attack used by imps, cacodemons, barons, hellknights, cyberdemons and arachnotrons, it takes the missile type from the actor->info, I have to work on a closecombat attacks - where applicable. A_ChaseNoMissile replaced a goto statement - I may try to get a C++ compile out of this.