Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
Maes

Vanilla compatible saving

Recommended Posts

I finally managed to implement 100% compatible vanilla game saving + loading in Mocha Doom (well, at least to the extend I can test it). It loads and saves stuff with byte-exactness, and is even able to reconstruct infighting targets from the saved target pointers in mobjs. In fact, this system works so well that when objects are serialized for saving, I save them with their Java hashcodes instead of indices, and it still works great (as long as whatever you're saving is unique).

Compatibility works both ways, in general: Mocha Doom is able to load Vanilla savegames (with enhanced functionality, actually, since it can restore infighting), and Vanilla Doom can load the Mocha Doom savegames.

Mocha Doom in itself is not limited in how it should load/save its games: it's possible to create specific loaders for any kind of well-documented savegame format, and extend them to your heart's content.

So far I only tested this functionality vs Shareware Doom v1.9, but it should probably work OK with other versions too.

Share this post


Link to post

Heh I'll give it a go, assuming whater IWAD/PWAD it is for doesn't cause trouble of its own (e.g. I must add a load-time safeguard against sector references of "-1" value, as those are often unused/invalid but potentially load-breaking as well).

The very least It will be easy to see WHAT is causing the problem.

Is it for Memento Mori 2, BTW?

Share this post


Link to post

So, the walls should start scrolling upwards? :-p



To be fair, I had to make the pointer ungarbling code overflow tolerant to complete the load.

Share this post


Link to post
Maes said:

So, the walls should start scrolling upwards? :-p

Actually, if I remember correctly, it was the ceiling that was raising indefinitely (with the pegged walls trailing), until Doom would crash if you were to enter the sector.

Share this post


Link to post
Maes said:

So, the walls should start scrolling upwards? :-p

With ceiling of that untagged sector I think. There is no ability to look upwards in vanilla :)

Share this post


Link to post

Well I can wait and see what happens if I wait long enough ;-)

About my code, the problem was actually in a stupid ++ operator in a for loop (should be --) ;-)

The pointer ungarbling code works by assuming that the player object is the only one which can be readily identified, because the saved player_t actually contains a pointer to it. Once I identify which one of the loaded mobj_t's is the player, and thus has a known hash, I scan forward (which worked) and backwards (which had that a stupid bug) to "reattach" objects to their targets. In fact, in the savegame you sent me, the player is NOT the first mobj to be saved, but the 50th (index 49).

Thanks for the stress test ;-)

P.S.: Here are some savegames near that spot produced by mocha doom.

http://utopia.duth.gr/~ve5822/mm2-mochadoom.7z

Doom2.exe was perfectly able to load all of them. After a while, both "executables" crashed in that room, mochadoom with an uncaught exception in Makespans (with an index of 64K+ in one of the spanstart/stop arrays) while vanilla quit on R_MapPlane with a caught error (well, pointless since it quit anyway...)

Share this post


Link to post

Another cool thing I managed to do, was to induce a venetian blinds crash in vanilla Doom, by saving on Doom II MAP30 with the spitter activated, just before the A_BrainSpit function was called. Loading that in vanilla, caused the aforementioned crash.

Mocha didn't have that problem initially, until I restarted the whole program again, and then the culprit was immediately obvious: a division by zero in A_BrainSpit, because numbraintargets hadn't been set by A_BrainAwake. Since that's a global/wide scope variable, playing MAP30 normally, waking the boss and THEN loading works OK in both versions, since it value won't be 0 (in fact, it's never explicitly zeroed outside of A_BrainAwake).

I also managed to get vanilla to produce a crashing savegame, by waking the brain, exiting, and reloading it: it crashed at the first attempt to spit ;-)

To futher stress test the thing, I tried to load some Doom II v1.666 savegames, after changing the version string: they all worked like a charm.

Share this post


Link to post
Maes said:

mochadoom with an uncaught exception in Makespans (with an index of 64K+ in one of the spanstart/stop arrays) while vanilla quit on R_MapPlane with a caught error (well, pointless since it quit anyway...)

Say hello to the "Numeric overflow crash in tall areas" bug ;)

Share this post


Link to post

Are you trying to emulate those bugs, or to fix them? I prefer the latter.

Share this post


Link to post
printz said:

Are you trying to emulate those bugs, or to fix them? I prefer the latter.


I only "emulate" them deliberately to the degree that they don't result in catastrophic crashes (e.g. I can't emulate "tutti frutti" because in Java it will result in an immediate overflow exception, so I have to eliminate it completely like e.g. ZDoom does).

Also, even if not widely publicized. Mocha Doom is 100% limit removing with regards to the following:

  • Drawsegs
  • Visplanes
  • Spechits
  • BSG segs trasversal (triggered e.g. in TNT MAP30 when raising the stairs in the cyberdemon fight) -> Asymptomatic in vanilla?
  • Vissprites (only partially, but will be fully implemented soon).
Most of the time "emulating" just means leaving the code as it is: most bugs are not simply the result of C's artifacts, but plain old wrong code, which I don't always fix (e.g. I left ouchface bug in).

The only overflow feature I deliberately emulated is the finetangent overflow (which however only affects the renderer), by allowing accesses beyond the 4095 mark and copying some of the values of finesine after that. From a programming point of view, it's easy to do and makes the code automatically overflow-proof, so why not?

Other stuff I tested and which I found to work exactly like in vanilla:
  • Voodoo dolls
  • Ghost monster bug
  • Telefrag deaths
  • Dead player linedef activation
  • Infinitely raising ceilings (well, just did that).
For the latter however, it worked because the status that led to it happening was already saved in the savegame. It's unclear if it could be generated during normal gameplay (if actual overflow breaking is involved, by overwriting part of the memory contents, then probably not, and you'd get an overflow exception somewhere along the way). As I said, Mochadoom is not like that infamous MS-DOS emulator written in Java that also runs Doom, and emulating the memory model exactly is not its goal: it's simply a reasonably "close" or "faithful" port, to the extent possible with "clean" code.

Of course, it's possible to include code to deliberately induce bug-compatible behavior. An immense advantage of Mocha Doom over anything written in C/C++ is that debugging is MUCH simpler, and even vexing bugs can be pinpointed in great detail, even stuff that is normally asymptomatic in vanilla or other C/C++ based ports (e.g. none was aware of the finetangent overflow in the vanilla renderer, and I never heard of solidsegs overflows in the BSP, either).

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×