Page 1 of 1

Demo recording/playback for debugging purposes (Ep 1-3)

Posted: Sun Jul 28, 2013 7:07 pm
by NY00123
UPDATE (Dec 24th, 2016): Edited download link since Dropbox' "Public" folder is expected to become private by March 2017.

Hey all,

There is a patch I have added to the KeenWiki today that takes advantage of unused code found in the Keen executables for recording and playing back demos. Note that the demo files are much larger than what you get for Keen 4-6, but I stayed with what was experimented with back then (as observed by the unused code).

Further note that the patch overrides the function letting you load a saved game. In fact, from the main menu you may record a demo, rather than load a saved. To watch recorded demos, simply hide the menu while still having the title in the background.

I know this may seem to make the patch useless. But, I still have found a way to take advantage of it... Furthermore, some code reshuffling may probably let you support demo playback and saved game loading altogether (possibly with the cost of losing some other feature).

Patch page on the KeenWiki: http://www.shikadi.net/keenwiki/Patch:Demo

Link to an archive containing the patches, along with ASM sources and sample demo files: https://www.dropbox.com/s/3fl8ah3khjg39 ... 8.zip?dl=0

Posted: Mon Jul 29, 2013 5:25 am
by levellass
So why does it disable the continue game code? Is there a lack of space in the menu or does the code overwriting wipe out the continue game code?

Posted: Mon Jul 29, 2013 8:38 am
by NY00123
Well, it basically goes like this:
- The menu loop code is modified so, after displaying the title (without the menu) for not much more than a second it goes to demo playback loop. Basically, for Keen 1 it loads and plays back DEMO0.CK1 if the file is found, then repeats this with DEMO1.CK1 and so on, up to DEMO9.CK1. If a file is not found then it is simply skipped. Furthermore, once it's done with DEMO9.CK1, the loop restarts. Finally, the user can halt demo playback by pressing on the 'ESC' key and then on any of the 'T' and 'D' keys, the same way it's done in an actual game.
- Some of the continue_game code is overwritten with demo recording functionality.
- Finally, a different portion of the continue_game code is overwritten with a couple of functions used for recording and playback altogether. Each of these functions resets some things. The first does so *before* demo recording/playback, resetting a few things that usually the worldmap loop resets when started (like the player's score). It also resets the player's position to (0,0), a workaround done to counter a vanilla Keen bug*. The second does the same *after* demo recording/playback, resetting stuff that generally the menu loop function resets when it is called (such as the amount of gun shots).
- It worths to note that some things, like cheat codes, may still be (de)activated during demo recording/playback.

Again, yeah, this patch may seem useless due to the absence of continue_game with no modification applied, but I have my own reason for this kind of implementation, which (assuming things go as planned) is going to be revealed soon.

* Vanilla Keen bug description: When an actual level map (not the world map) is loaded, a loop goes over the map checking for sprites. For some sprites the player's location is queried, usually to determine if a creature should initially walk to the left or to the right. Problem is that the player may have not yet been found on the map...
So, what happens? Well, usually, when something goes wrong, the player's location *on the world map* is queried. One may see the problem such a thing can have on the ability to record/playback demos, independently of any world map. So, as a workaround the player's location is initially set to a pair of zeros before demo recording/playback begins.

Posted: Tue Jul 30, 2013 5:29 am
by levellass
Interesting. Well with the tile space patch I'm sure there would be enough space to have both demo and continue game.

Also, are the patches in the archive you linked complete for Keen2 and 3 or are modifications require to integrate them?

Posted: Tue Jul 30, 2013 8:35 am
by NY00123
Yeah, the patches for all episodes (as given in the .PAT files) should be complete. The ASM files are what I've used for some portions of code, to be compiled to binary files with NASM and then patched either:
- using %patchfile (which luckily works since there is no relative address to fix),
- or by converting the binary contents to textual hex values understood by CKPATCH, when used with %patch. (That has been done for having self-contained patches on the KeenWiki.)

Posted: Wed Jul 31, 2013 5:31 am
by levellass
Cool. I may have to tweak that entry to allow people to see both the archive you linked and the self contained patches.

Posted: Tue Aug 06, 2013 5:55 pm
by ckguy
Cool!

Is the reason that the files are bigger for these demos than in Galaxy that all of the enemies' movements need to be stored? I recall that in Galaxy in demo recording mode, only Keen's movements are stored, and all the other sprites go into a special 'no-randomness' mode so the demos are reproducible.

Posted: Wed Aug 07, 2013 10:38 am
by NY00123
ckguy wrote:Cool!

Is the reason that the files are bigger for these demos than in Galaxy that all of the enemies' movements need to be stored? I recall that in Galaxy in demo recording mode, only Keen's movements are stored, and all the other sprites go into a special 'no-randomness' mode so the demos are reproducible.
Thanks!

Actually, all that is stored in the Vorticons demo files is the game-related input, although in a way which does take much more space than similar Galaxy demo files.

Basically, there is this function that I refer to by the name of "handle_ctrl", which returns a struct telling:
- Keen's direction of movement on the worldmap or in an ordinary level (if any).
- If the jump key/button is pressed.
- If the pogo key/button is pressed.

In practice, this function is also called from the menu code and more places, but you get the idea.

If I haven't missed anything, then while an actual level playback is in session, one call to handle_ctrl is done per "level loop iteration" (corresponding to a new frame displayed on screen). There are approximately 24.26666 such iterations per second.

While demo recording is in session, the value to be returned by a call to handle_ctrl is packed into a single byte and added to a temporarily buffer. Eventually the buffer's contents are saved to the demo file. Note that the very first byte of the demo file tells the level number.
For demo playback, the file is simply loaded to the same buffer and handle_ctrl acts differently, retrieving an action from the buffer rather than actual input devices.