- Loading an empty, foreign or outdated savegame slot from a running game leaves the running game untouched; the game was unloaded before the file was checked
- A savegame that fails to load after the old level was unloaded returns to the main menu; the game went on with a destroyed or half restored level
- A failed restore no longer overwrites the mission's level states and deletes the level state files
- Answering "No" to the load confirmation no longer replaces or deletes the secret level save of the running game
- The stale secret level save is really deleted when a savegame without one is loaded; the delete did nothing before
- A full disk or read error while the secret level save is copied no longer ends the game; the partial copy is deleted and the error reported
- Savegames of a newer version and savegames with the "between levels" flag are refused; the object section stops at the end of the file and when no object slot is left
- A savegame whose wall, trigger, robot maker, equipment maker or producer counts differ from the level is loaded with the level's counts; surplus records are skipped
- Exploding walls, active doors and cloaking walls of a savegame that name walls or segments outside the level are dropped or reduced to their valid part
- Object data of a savegame (type, id, control / movement / render type, model, textures, animation clip, segment, attach links, sound data) is validated
- A savegame without a ship for the local player is refused; a ship with negative shield is no longer turned into an empty object while loading
- A co-op savegame with an impossible player count or local player number is refused and ends in the main menu; missing player objects no longer crash the restore
- Weapon numbers, laser level, slow motion speed, afterburner charge and ship type of a savegame are limited to their valid ranges
- The reactor state and the reactor's trigger targets of a savegame are checked against the level
- Boss teleport and gate segment lists of a savegame are validated; a refused list fails the restore instead of crashing when the boss teleports
- Saving no longer crashes while a death or end level camera exists (co-op save arriving while the local player is dying)
- Saving a level with a lightning effect whose waypoint does not exist stores "no waypoint" instead of crashing
- Load menu in low resolution menu mode: the thumbnail of the selected slot is shown; it came from a wrong or non-existing slot
- The save / load menu copes with a thumbnail image that cannot be allocated
Complete list of fixes in v2.0.0 b8
Re: Complete list of fixes in v2.0.0 b8
Savegames
Re: Complete list of fixes in v2.0.0 b8
Game data files
- Every table count of a HAM file (descent2.ham, mission and mod HAMs) is checked against its table; a bad count ends the read instead of overwriting memory or ending the game
- A truncated or unusable descent2.ham ends the program start with an error message instead of running with half loaded tables
- Descent 1 game data: descent.pig variants without game data are no longer parsed as game data; texture, clip, effect, wall animation, robot, weapon and model counts are limited
- Descent 1 wall animations: frame counts above the table are cut and frame numbers outside the texture table are reset
- d2x.ham and HXM files (robot replacements, cambot.hxm): negative counts, negative model numbers and object bitmap numbers outside the tables are refused
- Model data in HAM, HXM and exit.ham with an impossible size is refused; a model that fails its check stays empty (a replacement keeps the original model) and the file is read on
- Exit models that cannot be loaded no longer leave invalid exit model numbers behind
- Object bitmap indices, texture effect clips, "destroyed" textures, robot explosion clips and dying / dead model numbers outside their tables are reset when game data is read
- Animation clips: frame counts are limited to the frame table, frame bitmap numbers outside the bitmap table become 0, surplus clips are skipped
- A weapon or effect whose animation clip number lies outside the clip table, or whose clip has no positive play time, is not drawn instead of ending the game or hanging the renderer
- Robot gun points: a gun number or sub model outside the model no longer reads behind the model's tables
- hoard.ham: frame counts, sizes and the free room in the clip, effect, texture and bitmap tables are checked before anything is changed; a bad file is refused
- Hoard / Entropy / Monsterball: the monsterball no longer shares the orb's bitmap memory (overwritten texture, double free at exit)
- Hoard / Entropy / Monsterball: unloading a level no longer removes four regular sounds each time
- A HOG file with more than 300 entries is read up to the limit, reading went on from the closed file before; over-long entry names are cut
- File reads are limited to the file or HOG entry: numbers read at the end are 0 instead of random values, reads no longer run into the next entry, negative counts are refused
- A compressed cache block whose stored size exceeds the rest of the file is refused before memory is allocated
- Opening a file inside a HOG for writing fails normally instead of ending the program; counting the lines of a text file no longer loops forever on a read error
- File and folder search handles are closed again (single level missions, folder creation); they piled up during a session
- Over-long installation, user, cache, mod and HOG paths are refused or cut instead of overflowing the path buffers
- Mission files: empty lines and lines of blanks or tabs only no longer read and write in front of the line buffer
- Mission files: repeated num_levels / num_secrets blocks restart the counts instead of adding up beyond the name tables; the previous mission's secret level count is not kept
- A mission with exactly 100 levels no longer writes its last level state behind the level state table
- Mission list: mission and level file names too long for their path buffers are skipped instead of overflowing them (also with "show level version" on)
- d2x.ini and command line: a switch without value, a line of blanks only or a switch as last argument no longer crashes the program start
Re: Complete list of fixes in v2.0.0 b8
Level mesh
- A level whose last segment has no visible side no longer ends the game while its mesh is built or loaded from the cache
- The vertex table is never shrunk below the level's vertex count while the faces are built (levels with far more vertices than visible sides)
- Lighting "basic" with triangular sides: the undefined fourth corner is skipped when the tessellation atlas is built; it reset the vertex count and memory was overwritten
- Mesh cache files (.mesh) are validated completely (header counts, block sizes, every face and triangle record) before they replace the built mesh; a damaged file is rebuilt
- A split triangular side with a relief texture no longer reads a vertex that does not exist
- Tessellation cache files (.tess): file size and all edge, link and face records are validated; a damaged file is rebuilt and overwritten
- Level texture arrays: walls with a clip outside the animation table are skipped, frame loops stop at the table size, frames with bitmap numbers outside the bitmap table are skipped
- A mesh cache file that cannot be written or read back no longer makes the level unloadable: the mesh in memory is used and the broken cache file is deleted
- Running out of memory while the level mesh is built fails the level load instead of ending the game
Re: Complete list of fixes in v2.0.0 b8
Textures and images
- A level palette that names a missing or invalid PIG file no longer closes all texture files: the PIG is checked (id, version, bitmap count) first and the default PIG is used instead
- descent.pig is reopened by itself when a Descent 1 texture has to be read while the file is closed
- A texture that cannot be read no longer ends the game with an exception: the low resolution bitmap is used, and if that fails too, a placeholder; the texture export skips it
- A PIG file or descent.pig with a bitmap count outside the bitmap table is refused (descent.pig: for textures and sounds); a full bitmap or name table no longer ends the program
- Bitmap numbers from HAM files that lie outside the bitmap table are replaced by 0; reading bitmap number lists stops at the end of the table and of the file
- Descent 1 texture numbers from descent.pig are range checked before they are stored; extra Descent 1 bitmaps are only added while the bitmap table has room
- POG files: the entry count must fit the file size; entries with a texture number below 1 or beyond the texture table are skipped and reported once per file
- POG files: a replacement only takes over the size of the original texture when that fits its own data; an entry that cannot be read or is too high (TGA) is skipped
- Requesting a texture with a number outside the texture table is ignored instead of raising an exception
- Preloading level textures checks model numbers, model texture ranges, texture overrides, animation numbers and frame counts (objects, weapons, robots, wall effects, robot makers)
- Preloading robot textures no longer recurses without end when a robot in a boss's gate list is such a boss itself
- PNG, DDS and TGA images too large for the 16 bit size fields of a bitmap (32 bit images from 8192 pixels wide) are refused with a log line instead of crashing in a copy
- Animated textures: the per frame transparency flags are only written and read for the 128 frames they have room for; stored frame counts are limited to 255
- A block compressed (DDS) texture strip whose frames cannot be cut (more than 255 frames, frame height below 4 or no multiple of 4) is loaded as one frame with a log line
- A frame number outside the frames of an animated texture is clamped where the frame is selected
- TGA: only 24 and 32 bit files are accepted; 8 and 16 bit files passed the header check and were processed as RGBA
- IFF / BBM: a negative or overflowing chunk length, a chunk longer than the file (except the picture body) and a palette above 768 bytes make the file invalid
- IFF / BBM: a header with width or height below 1 (ILBM: also bit planes outside 1 ..
, a body without header and a delta chunk in a plain picture make the file invalid - IFF / BBM: the body decoder stays inside the picture and the file data; an incomplete uncompressed row makes the file invalid
- RLE bitmaps (PIG, descent.pig, POG): row table, rows and run codes are checked against the data; a bitmap that cannot be expanded is dropped instead of being decoded unbounded later
- PCX: sizes outside 1 .. 32767 and a target bitmap of another size than the file are refused, runs are cut at the end of the row, the file is closed on every error
- A level or mod HAM file with a wrong id and a palette that cannot be loaded (once a default palette exists) are logged and skipped instead of ending the program
- Font files are validated when loaded (signature, data size, character range, width / data / kerning offsets, glyph sizes); a damaged font is not loaded
- Text that ends inside a colour or line spacing code is measured and drawn up to its end instead of reading past it
- Measuring tabbed text terminates its work buffer and reads at most the six tab stops of the tab table
- Formatted text output is limited to its 1000 character buffer
- A tab in a text rendered into a bitmap can no longer move the write position in front of the bitmap buffer
- Text output copes with a font that is not loaded (no division by zero when padding, nothing is drawn without a current font) and with characters the hot key font lacks
- File names of hires textures, surface maps, add-on bitmaps, palettes and mod HAM files are built with the buffer size instead of overflowing with long folder names
- A bitmap number outside the texture table is ignored when the super transparency flag is set or a hires frame is freed; a bitmap filled from an IFF picture gets its number reset
- No memory for a bitmap object, a surface map or the Descent 1 texture table: the item is skipped instead of an exception; savegame thumbnails and the key configuration cope with it
- Freeing the texture list of a model is bounded by the length of its name and bitmap lists
Re: Complete list of fixes in v2.0.0 b8
Models
- Polygon model data (HAM, HXM, POL) is validated before use: records inside the data, recursion depth, sub model numbers, at least 3 vertices per polygon, vertex and texture numbers
- A polygon model that fails this check is left out with one log line; an unknown opcode no longer ends the program (also in the hit box code and when render models are built)
- Models that exceed the 16 bit counters of a render model (65535 vertices, 21845 triangles, 255 sub models) are refused when read, with the file name, instead of overrunning buffers
- A model file without sub models, faces or vertices is refused (ASE, OOF) instead of crashing when the model is built
- ASE: a sub model whose material lies outside the material list and OOF: a textured face whose texture lies outside the texture list make the model invalid
- ASE: node names, parent names and bitmap file names that do not fit their buffers make the model invalid; a name line without a value no longer passes a null text on
- ASE: team textures are only accepted for color0 .. color7; 1 .. 100 materials are accepted
- ASE: the vertex normal list is as long as the vertex list, so a model with more vertices than face corners no longer writes past it
- ASE model cache: counts, model number, folder flag, name lengths, sub model order, parents, totals and the remaining file size are verified; a bad cache is discarded and the ASE file read
- An error in a model cache is reported as "model cache" instead of going through a text file that is not open
- OOF: counts are checked against the rest of the file before memory is allocated; a truncated file or a text with an invalid length makes the model invalid
- OOF: a face with fewer than 3 vertices, more vertices than the file can hold or a vertex number outside the sub model's vertex list makes the model invalid
- OOF: sub models beyond the declared count, repeated header, texture, gun point, special point, attach point or weapon battery chunks and a chunk with a negative length end the read
- OOF: sub model properties that do not fit their 200 byte buffers are ignored; an invalid $fov value no longer fails an assertion
- OOF: surplus gun points are dropped (the game uses at most
, a gun point parent outside the sub model list is corrected or skipped, the parent walk is bounded - Sub model parents (ASE, OOF, caches, render models): a parent outside the list, a self reference or a cycle is cut and reported once instead of looping or writing past the list
- Hit boxes: the list is sized by the number of sub models the validated model data really calls; it was written without knowing its size
- A POF file whose model has no data (exit model files) is reported and not counted instead of being dereferenced; the same when the model table is full
- Model textures: numbers outside the bitmap tables give texture 0, a texture range that leaves the table is reported, alternative texture lists are passed with their length
- Model numbers outside the model table are refused where models are prepared, built and drawn; reading the model list stops at the table length
- A model without vertices gets the radius 0 instead of a huge value; a replacement model only stores a radius above 0
- A low resolution replacement model only replaces the stock model when it was read completely; otherwise the stock model stays
- Preparing the models no longer dereferences object 0 when no object exists
- POF faces with a texture number outside the model's bitmap list no longer index the list; a face vertex number beyond the vertex count makes the model invalid
- For flat POF faces the texture coordinate words were read behind the end of the model data (also in stock models); they are only read inside the data now
- Faces with fewer than 3 vertices are skipped when a render model and its edge list are built
- A sub model animation number outside the object's angle table is set to 0 when the model is built and gives zero angles when it is drawn
- Ship gun points of OOF models: the pointer is taken after the list was resized; building a model without an object no longer dereferences a null object
- A vertex that is not finite is left out of the bounding sphere, whose construction could run for hours with it
- Cached joint models are checked for face order, vertex counts, sub model face counts, parents and animation numbers; a file that fails is rebuilt from the model data
- Model texture animations: frame counts are limited to the table size, the critical animation number is range checked, a negative effect count no longer loops for billions of steps
- Ship weapon sub models: an object id that is no player number is treated like "no object"; gun and missile position tables are only indexed inside their range
- Rod shaped objects with a bitmap number beyond the bitmap table are not drawn
- Requesting more model textures than the caller's list holds fills the entries that fit; they were returned uninitialised
Re: Complete list of fixes in v2.0.0 b8
Graphics interface
- A side texture number outside the texture table is drawn as texture 0 instead of reading beyond the table
- An animated texture whose frames cannot be cut or allocated is shown as a single image and reported once instead of ending the game
- A default surface map that cannot be allocated stays empty and is skipped instead of ending the game
- The texture frame of a maker segment is left unchanged when the maker's producer number is outside the producer table (it comes unchecked from level or savegame)
- Model shadows: a sub model whose animation angle number is outside the object's angle table is drawn without animation angles instead of reading beyond the table
- Model shadows: collecting the shadow casters of a segment stops at an object that does not exist
- Screenshots: the search for a free file name ends after 9999 tries (it never ended when all names were taken) and reports the problem once
- Screenshots: a file name that does not fit its buffer refuses the shot instead of overflowing the buffer
- Screenshots: the HUD message is printed as plain text, so a percent sign in the text file line can no longer act as a format
- If the scene buffer cannot be activated, the half resolution effect pass and the shadow pass skip their composite and the draw buffers are left alone instead of crashing
- The stereo screen distance from the profile is clamped to its table; it was used unchecked as a table index and the result is a divisor
Re: Complete list of fixes in v2.0.0 b8
Rendering the mine
- A side whose base or overlay texture number is outside the texture table keeps the face's previous textures instead of reading beyond the table
- The light range setting is clamped to its table, both in the mine lighting and when the level's lights are created
- Drawing the fireballs attached to an object stops at an entry that does not belong to the object and after at most the object count; a closed chain hung the renderer
- Zoom key: a mouse button number from the key bindings is tested against the number of mouse buttons instead of 255
- A frame is not rendered when there is no viewer object (also for automap and end level sequence), and the fade in of the mine is skipped without a local player object
- A view start segment outside the level (e.g. in the end level sequence) gives an empty frame instead of a crash in the visibility walk; the fog lookup for the eye skips it too
- Objects whose segment number is outside the level are skipped when the visible objects are gathered
- Building the render object lists per segment and drawing the skybox objects stop at an object number that does not exist
- Portal visibility: a level without a single portal gets its work tables too; they were missing and the first use ended the game
Re: Complete list of fixes in v2.0.0 b8
Rendering objects
- A model number outside the model table draws nothing instead of crashing (objects, weapon models, model pictures)
- An object texture override outside the texture table is ignored and the object is drawn with its own textures
- The player colour textures are only used for a colour number between 1 and the maximum player count (normal and cloaked ships)
- A ship model with more than 6 textures no longer reads beyond its row of player colour textures; a texture override now covers up to 256 model textures (was 63)
- Sprite objects and the towed flag are not drawn when their frame bitmap number is outside the bitmap table
- Morph effect: a model with more than 10000 vertices appears without the effect instead of reading beyond the vertex buffer; an object that is no polygon model is not morphed
- A shield or monsterball sphere that cannot be created is not drawn instead of ending the game; the monsterball no longer crashes when the shield sphere is missing
- Sphere outline (cartoon style): the edge buffers are sized for the sphere before it is drawn; they were sized for the level and could be overrun
- Object visibility: the number of visible objects read back from the GPU is limited to the size of the list
- Cameras: no more than the maximum number of cameras is created for a level; more targets relocated the camera list and left dangling pointers
- Cameras: a teleport camera is only created for a wall whose trigger exists and has at least one target
- Radar: position, size, range and colour from the profile are clamped to their tables before the radar is drawn
- Automap: when a game frame run by the automap changes the level or the function mode, the automap loop ends at once instead of drawing the old level's data
- Automap: leaving it after a failed level load no longer touches the missing player object; the free camera is restored only while a level is loaded
- Automap: players without an object are skipped, and the view starts at the own ship when the flight path is empty
- Automap: the title of a built-in mission no longer reads beyond the table of system names for a level number above the table
- Automap: a full edge table makes the edge search report "not found" instead of ending the game with an error
- Automap: a side with a one way connection is no longer asked for a wall on the missing opposite side
- Automap: the marker message is only shown for a highlighted marker slot that exists, and its text is length limited
- Automap: level number, level name and the help texts are printed as plain text, so a percent sign in a level name can no longer act as a format
Re: Complete list of fixes in v2.0.0 b8
Dynamic lighting
- A light whose object no longer exists counts as having no segment and keeps shining at its last position instead of crashing the light lists and the light visibility test
- Switching a light: the list of changed segments holds 43 entries, the most that two levels of spreading can produce (the 30 entries before could be overrun)
- Flickering lights: a record whose segment does not exist or whose side is not 0 to 5 is switched off instead of crashing
- Flickering lights: a delay of 0 or less switches the light off (a negative delay hung the game), and a timer far behind is reset so the catch-up always ends
- Light changes (destroyed or switched lights) only walk records inside the delta light table, and the index search no longer reads in front of the table
- Headlights: a player number outside the player table has no headlight and is ignored when headlights are added or removed
- Headlights whose player object is gone are removed before the lights are transformed
- Nearest light lists: entries that name a light beyond the current light count are skipped (they come from the cached light data)
- An object whose segment does not exist is drawn with full brightness, and its own light is not applied, instead of crashing
Re: Complete list of fixes in v2.0.0 b8
Light precalculation
- Light visibility sample points: a triangular side only uses its three corners, the remaining sample slots get the side centre (it read an undefined fourth corner)
- Light data cache (.light): light visibility, segment visibility, segment distance and nearest light tables are checked for offsets, counts and index ranges when loaded
- A .light file whose contents are refused is reported once, all its tables are emptied and the light data is computed again
- Lightmap cache (.lmap): the tile table is checked before the textures are created - every tile must lie on an existing atlas page and inside it, and the page count must match
- Lightmap baking always starts with a clean baker and finishes it when the progress window ends early; the next bake no longer runs on the previous level's mesh and occluders
- Light precalculation: when the progress window ends before the calculation is done, the buffers are released and the incomplete light data is not saved
- Light precalculation: when buffers, portal data or shadow maps cannot be created, this is reported and the level runs without precomputed light data instead of ending the game
- Shadow occluders left over from another level are destroyed before the light precalculation builds its own
- The lightmap file name is built with a lighting method clamped to the valid range; a value outside it (from the profile) read beyond a table
