======================================
ATROXIAN REALM - Modified by K1n9_Duk3
======================================

-------------------------------------------------------------------------------

WARNING: The updated executable is NOT compatible with the saved games from
earlier versions. I recommend creating a backup of your saved games before
trying out the updated executable.

-------------------------------------------------------------------------------

Version 1.5 changes:
--------------------

- TODO: insert level patch notes!

- Cleaned up the source code a bit (added missing prototypes, disabled some
  "Parameter is never used" warnings for think and contact functions, disabled
  some unused code that caused compiler warnings). This got rid of about 100
  compiler warnings. There are still some problems in the code, though.

- Replaced the AdLib detection code with a more robust version that should no
  longer fail when run in DOSBox with cycles=max


Version 1.4 changes:
--------------------

- Removed the hacks in CA_CacheMarks() and StartMusic() and instead added code
  to the memory manager that allows it to move memory blocks around to merge
  multiple small blocks of free memory into one big block of free memory.

- Changed compiler settings to optimize for size instead of speed. This frees
  up around 4k of memory (because the code is smaller).

- Fixed a potential issue in EndText() where the arrow graphics might not be
  cached after CacheLayoutGraphics is done.


Version 1.3 changes:
--------------------

- Fixed an issue with the activity limits after loading a checkpoint or a saved
  game. This bug was introduced by some last-minute edits I made just before
  releasing version 1.2.

- The /NOEMS and /NOXMS parameters have been modified. For whatever reason, the
  /NOEMS parameter disabled both EMS and XMS dectection while /NOXMS had no
  effect whatsoever in the old version. Now both parameters work correctly.

- The sprite graphics have been optimized for less memory usage. Now the game
  only requires 491k of memory (instead of 518k) to play all levels with music.
  To play without music, you only need 455k (instead of 500k) of memory. If you
  change the sound setting to PC Speaker effects, you only need 453k, if sounds
  are turned off entirely, 449k should be enough to play all levels.

- The memory check at startup has been modified to show the warning message if
  less than 455k of memory are available to the game. The message also no longer
  claims that it might be impossible to free up enough memory on real DOS PCs.

- The game now shows the "Not enough memory to load level" message and returns
  to the world map when not all graphics (sprites and tiles) for the current
  level could be loaded. Earlier versions allowed the player to play the level
  anyway (with some garbled graphics), but this still caused crashes if the game
  tried to re-cache the graphics later (because the player opened the main menu
  or help menu or triggered a story screen).

- Improved CA_CacheMarks() to avoid situations where the game technically has
  enough memory to load everything but can't use all of it because the memory
  is too fragmented.

- Also added some code in StartMusic() to avoid the "Insufficient memory for
  background music!" error as much as possible. This can take a few seconds
  depending on your CPU and disk speeds, but at least you get to hear the music.
  Turn the music off to skip that delay if you don't have enough memory for the
  music and/or the delay starts to annoy you.

  Note: Trying to load a game can still cause an "Out of memory" crash if there
        is not enough memory available to load the graphics for that level.


Version 1.2 changes:
--------------------

- Added end-of-level statistics to show how many items remained uncollected.
  Purely for the completionists out there, but kinda useless right now, since
  some levels don't allow the player to collect 100% of the items.

- CK5_ACT_MapFlagFlips5 used the wrong sprite, so the flag flipping animation
  didn't look like the one in Keen 4 and Keen 6.

  Side Note: Two of the flipping/spinning flag sprites are never used in Keen
  4-6 and Atroxian Realm. But since these sprites are only cached on the world
  map, removing them would only help you if your mod runs out of memory on the
  world map.

- Moved the code that removes all key gems (and the security card) from the
  inventory into a new function named CK_ResetLevelVars to avoid redundancy.
  CK_ResetLevelVars also resets a new variable that indicates that Keen picked
  up a Hyper Star in the level.

- Added a CountHyperStars routine that checks if Keen picked up a Hyper Star
  in the current level. If Keen did and this is the first time he picked up a
  Hyper Star in the current level, the total number of Hyper Stars collected
  so far is increased by one.

- CK_SubmitHighScore now moves the lower ranks down by one BEFORE overwriting
  the old entry with the new entry. In the old version, the new high score
  entry was effectively added twice, overwriting the entry that would have
  followed directly after the new entry with a blank name and the same score
  as the new entry.

- High Scores now use the array defined in ID_US_1.C instead of using a
  completely different array declared in KD_INTER.C, so High Scores are
  actually saved and restored correctly now.

- Changed position of high score elements on screen and made the game display
  the number of collected hyper stars for each high score entry. Also increased
  the maximum name width from 112 to 160 pixels.

- Number of collected hyper stars is now passed to CK_SubmitHighScore.

- Changed ConfigVersion from 1 to 2 because the high scores now use 8 entries
  instead of the 10 entries stored in the old config files.

- LoadTheGame() and SaveTheGame() now load and save the current camera position
  to avoid issues with bad camera positions after loading the game. This also
  makes it difficult to win a level by dying and abusing save/load to let Keen
  move to the right edge of the map.

- Levels can no longer be won by exiting to the left or right while Keen is in
  noclip mode (i.e. Keen is dying).

- Displaying the list of remaining items at the end of each level can now be
  turned on or off in the menu and the setting is saved in the config file.
  The default setting is OFF.

- The "?" items now have their own category in the list of remaining items.

- The points for all the bonus items (excluding "?" items) are now calculated
  and displayed in the list of remaining items along with the number of bonus
  items.

- Added WallDebug (Y+F10) and the missing tile graphics for this feature.

- Added new debug code F+F10 to erase the foreground attribute for all tiles,
  so that Keen and items hidden in walls are always visible. You need to quit
  to DOS or use U+F10 to undo this.

- Added new debug code U+F10 to undo WallDebug and restore the foreground bits
  (by re-caching the tile images and re-loading the MAPHEAD.* file).

- Disabled huffman decoding in ID_CA.C, since the huffman tables in the game
  don't actually encode anything. Loading EGA chunks is a LOT faster now.

- Removed the huffman tree variables in ID_CA.C when NOHUFF is defined, thus
  freeing up about 2k of memory (each huffman tree takes up 1020 bytes).

- Loading window is now drawn before caching in the map itself. It also won't
  disappear before the loading sound finishes. Without the fix, the loading
  messages usually disappeared way too fast and the game would show a black
  screen while waiting for the sound to finish.

- Added new options in the Keyboard Buttons menu, allowing the player to remap
  the keys for the status window and the new "remaining items" window. Also
  added a remappable key to toggle the score box.

- Fixed another bug with the Krile Ghost. Loading a saved game or a checkpoint
  used to increase the numAxosis field of the gamestate struct, which meant
  that the ghost code kept searching for the next Axosis when there was no
  Axosis left in the level. Now loading a game or a checkpoint won't change the
  numAxosis field anymore and the ghost will set its user4 field (next Axosis)
  to NULL when no Axosis can be found.

- Also made sure that all Axosis/Ghost-related pointers are set to NULL when
  loading a saved game or a checkpoint. There was a slight chance that some of
  these pointers might not be set correctly.


Version 1.1 changes:
--------------------

- The Terminator intro's "Commander Keen" text stays blue during the shrinking
  and fizzle-fade animations.

- VW_SetScreen skips waiting for a VBL by default. Waiting for a VBL could
  cause random slowdowns when playing in DOSBox at the default settings
  (3000 cycles). If this causes any new problems, run the game with the
  /WAITVBL parameter to go back to the old behavior.

  Note: Running Atroxian Realm WITHOUT the /WAITVBL parameter gives you
  basically the same behavior as running BioMenace 1.1 WITH the /LATCHPEL
  parameter.

  Edit: This is not quite true anymore. See below.

- StartMusic now calls StopMusic instead of SD_MusicOff to make sure all music
  memory can be purged by the memory manager.

- StartMusic also locks the music buffer now to prevent the memory manager from
  moving it while the music is playing. StopMusic unlocks the music buffer.
  The Wolfenstein 3-D source code does exactly the same in its StartMusic and
  StopMusic functions. The game wouldn't crash if the memory manager moved the
  music around, but the music would be totally messed up if this happened.

- Various message functions now call CA_ClearMarks to make sure the game does
  not cache in more than the desired images during CA_CacheMarks. The message
  functions also call StopMusic before calling CA_DownLevel to make sure any
  music is stopped and made purgable before CA_DownLevel re-loads the marked
  graphics for the previous cache level.

- Help Screens and End Screens now lock the text buffer to prevent the memory
  manager from moving it around. If the memory manager moves the text buffer,
  the game usually quits with the "PageLayout: Text not headed with ^P" error.
  Help Screens also call StopMusic before calling CA_DownLevel to make more
  memory available for re-caching the old graphics.

- CK_LoadLevel no longer (pre-)caches the music for the level. This comment was
  in there:

  // AR HACK for large songs that still can't load
  // Load the music here FIRST before all of the other little chunks go in
  // Game will BOMB if not enough memory

  I don't know what this was supposed to accomplish. At this point, the game
  hasn't even made any unused graphics purgable, which means this can cause
  the game to crash even if it would have been able to load the music after
  loading all the required graphics chunks (and purging all the unused chunks
  in the process).

- InitGame now uses more reliable numbers to warn the user that there is not
  enough memory to play the game without encountering a crash at some point.
  It also won't cause DOSBox to lock up anymore when the user quits at that
  point. Run the game with /NOEMS if you want to test this.

- The unused thruster sprites for the red platforms are not loaded anymore.

- Added some code to purge all tile graphics and (almost) all sprites and stop
  the music before trying to load a new map. This should fix "out of memory"
  issues when warping to certain levels from within another level. Also helps
  when returning to the world map if the system had barely enough memory to
  load the current level.

- Fixed a bug in CK5_FallPlatFall that could cause falling platforms to fall
  through blockers. Stand on a falling platform at its bottom position, then
  open the main menu and return to the game two or three times to trigger this
  bug in the old version.

- Fixed bug in AR_LoadCheckpoint that caused the Krile Ghost to operate with
  outdated pointers after loading the checkpoint. This bug could cause the
  ghost to turn ANY object into a stunned Axosis or hunt an object that does
  not even exist in the level.

- Added code to make the Krile Ghost teleport out immediately when an Axosis
  is squished. This prevents the ghost from getting stuck near a dead Axosis.

- Fixed a bug in CK_HandleInput. The code used the variable ck_twoButtonFiring
  instead of oldshooting. ck_twoButtonFiring is not used anywhere else and is
  always false, so two button firing didn't work.

- The game now frees up map memory directly instead of loading level 25 (BWB)
  to free up memory for ending text 3 (Atroxus). The BWB level requires about
  22k of memory just to cache in the map planes, so why waste that?

- USL_DoLoadGame only redraws the load menu when loading a game fails, instead
  of always redrawing it. That means the "Loading (name of savegame)" text no
  longer disappears while the level graphics are being cached in (which can
  take several seconds when playing in DOSBox at 3000 cycles).

- Fixed a nasty bug in the checkpoint system. The checkpoints used to save the
  game during the checkpoint's collision function, which was a very bad idea.
  The problem is that this means the state is saved after all the level objects
  have been moved, but before they have executed their React/Draw code. When
  the checkpoint is loaded, the game lets the ojects move again without
  executing their React/Draw code first. This could leave objects in a bad
  state after loading the checkpoint. For example, if a Magmine just moved off
  a ledge when the checkpoint was saved, it is not moved back to its previous
  position (which is what its React function would have taken care of), causing
  it to get stuck in mid-air.

  I fixed the bug by setting a variable in the checkpoint's collide function
  and moving the actual checkpoint saving code into the PlayLoop function.
  After updating all the level objects, the PlayLoop function checks the
  variable that indicates if a checkpoint was touched and saves the checkpoint
  if it has to, clearing the variable afterwards.

- Destroying an Atroxian now spawns the same explosion as the Magmine, which
  means the explosion will now hurt Keen if it touches him, as requested by
  Gridlock.

- CK_PlayDemo now locks DemoBuffer before starting the demo playback. The old
  version locked the graphics chunk that contains the demo data, but that chunk
  is not used during the demo playback (it is actually freed right after the
  code locks it). Unfortunately, this does not prevent the demos from going out
  of sync.

- Fixed small bug in FadeAndUnhook. Now demos will always play out exactly the
  same every single time. Some demos need to be re-recorded, though, since this
  bug also affected the game's timing while the demo was being recorded.

  Note: You should NEVER pause the game in any way while recording a demo, as
  that might cause timing issues.

- Fixed small issue in CK_StunCreature. The creature's 'timeUntillThink' value
  is now set to 0 to avoid any pause between the creature getting stunned and
  the creature doing the little jump that goes along with it. This bug was only
  noticeable on hornets, but this should fix it for any object type.

- MM_SortMem no longer stops any sounds. It always locks the sound block that
  is currently being played anyway, so stopping the sound doesn't really seem
  necessary here unless you want an audible hint that the engine is sorting
  memory blocks.

- Decreased Axtroxus' left, right and down movement speed by 25% on easy mode.
  Moving up still uses the full speed to make sure it can still fly up high
  enough so that Keen can stand beneath it and shoot it from below.

- Modified VW_SetScreen code slightly. Instead of skipping the wait for a VBL
  entirely, the code will now abort the wait if more than 14.28 milliseconds
  have passed while waiting, which means the code missed the VBL due to an
  interrupt. This, however, would lead to jerky scrolling in DOSBox (seen as
  the scorebox moving back and forth as the screen scrolls). But skipping the
  wait for a VBL would cause sprite flickering and other issues. Because of
  that, the code will now wait for a VBL after setting the panning register
  (and abort the wait if it takes too long). This should get rid of the jerky
  scrolling as well as the sprite flickering, while still avoiding the random
  slowdowns that were the reason why I looked into the Atroxian Realm codebase
  in the first place.

  I think I finally found the perfect solution, at least as far as playing the
  game in DOSBox is concerned. There might be other issues on actual hardware
  due to the lack of actual standards for EGA/VGA/SVGA cards when it comes to
  timing and features, though.

- Boss doesn't spawn its shockwave effect on easy dificulty.


Further additions to the code base (disabled in Atroxian Realm):
----------------------------------------------------------------

- Text display (help texts and end texts) routines can be modified to cache
  each individual image as required instead of caching all images at once.
  This means turning from one page to the next can take a little longer, but
  the upside is that you can use as many images as you want without having to
  worry (much) about running out of memory.

- Additional text commands can be added for help and end texts. These are:

  ^Mxxx - start playing level music number xxx (can be negative)
  ^Sxxx - play sound number xxx
  ^W    - wait until the current sound is done (does not update the screen)
  ^Dttt - wait ttt tics (screen will be updated)
  ^Q    - "quiet" - stops sounds and music


Room for "improvements":
------------------------

- removing paddle war would free up 1200 bytes of code
- removing the Terminator intro would free uf 4910 bytes of code
- removing the Star Wars text would free up 1677 bytes of code

  Hacking all of this out is probably not worth the 7.6k you would gain by
  doing so. It's not nearly enough to make Atroxian Realm fully playable on
  actual DOS PCs anyway.

- You can get about 4k more memory by compiling the game using the 80186 
  instruction set instead of 8088/8086 instructions. The only downside is that
  the game wouldn't run on 8088 or 8086 CPUs anymore, but since Atroxian Realm
  is meant to be played in DOSBox anyway, that's not really a problem.

- You could probably make even more memory available by letting the compiler
  perform some optimizations, but you need to be very careful with this. The
  ID engine doesn't mark any of the variables as 'volatile', which means the
  compiler doesn't know that some variables might be changed during an
  interrupt and ends up generating code that doesn't work correctly anymore.
  In short: Don't use any optimizations unless you know what you're doing!

- Getting rid of all the pre-shifted sprites and making the game shift the
  sprites when they are drawn would greatly reduce the memory requirements and
  would make it possible to run the game on actual DOS PCs without eventually
  running out of memory. But you would obviously need a much more powerful PC
  that is fast enough to perform the shifts while drawing. This would also
  allow you to use pixel-perfect movement and scrolling, instead of being
  forced to move everything in multiples of 2 pixels.