-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash/unexpected behavior in Keen 6 when exiting level 2 via Impossible Bullet after level 1 has been loaded #28
Comments
Interesting… I can't actually reproduce the crash on my machine (it works fine with the Linux builds, as well as the windows builds under wine) — the glitch is working correctly whether or not I enter level 1 first. That being said, valgrind gave me some out-of-bounds memory accesses in TI_ForeBottom():
It looks like the bug may involve integer underflow in the y coordinate in CK_PhysClipVert(), causing a whole row of invalid tiles to be checked. Making TI_ForeBottom() always return 0 for invalid tiles seems to not break the glitch itself, so I suspect that adding the appropriate checks to the tileinfo functions may work around the crash. In any case, I want to experiment a bit more before I try to fix this properly. If you want, try adding something like this to all of the
If that fixes the crash, then it's the tileinfo going out of bounds that's causing the actual. If it still crashes, I'd bet it's the level data going out-of-bounds (which I think is slightly less likely, and fixing that may break the glitch totally). Cheers, |
I was just coming back here to post that I found the same thing as you re. everything working fine on Linux when I got around to trying it there. I also realized upon looking at my Event Viewer logs that under Windows, Omnispeak is basically coredumping with an access violation, which comports with what you're seeing there in valgrind. The change you recommended fixes the crash and that particular Impossible Bullet out-of-bounds clip now works as expected. There are some other out-of-bounds tricks used to finish the other two Guard Posts (levels 9 and 12) that I can't do consistently enough to say for sure whether they are affected. |
In Pull Request #18 (specifically commit 2e57635 ), we removed the -mno-ms-bitfields option, as it didn't seem to be doing anything: none of the structures we cared about used bitfields. However, this may have caused the CI Windows builds to no-longer be able to load levels, as they use an older build of mingw (specifically a GCC 6.3.0-based one), which is affected by a bug with packed structures: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 Because the CA_MapHead struct is packed, and is filled with an array of uint32_t which is unaligned by definition (following the 2-byte rleTag), it falls afoul of this bug, causing the wrong map header offset to be read, a bad seek to occur, and the game to Quit with "Couldn't read map header from GAMEMAPS!" This bug was reported by @tgies in issue #28.
In some circumstances, when using a glitch to read past the bounds of a level, invalid tileinfo data can be read. This reads potentially invalid memory, and can therefore cause a crash. With this change, all out-of-bounds tileinfo access returns 0. The glitches still appear to function as expected in DOS with this change, but without crashing. See Issue #28 for more details. Note that in debug builds, we log a warning for each out-of-bounds tileinfo access. This spams a lot of log messages in the case of this glitch (when level 2 is played after level 1), so may slow the game down a bit.
Thanks again for the bug report. I've added the fix, and this works at the moment. I've also fixed the Windows GitHub artefacts builds. However, when I spent some time looking at how we handle out-of-bounds map acesses (which cause this glitch), I've stumbled across a couple of problems. We're actually already trying to handle out-of-bounds map acesses by generating pseudo-random tile values, but those values can still be out-of-bounds. This is partly due to integer underflow and its interactions with the way the mod operator ('%') handles negative numbers. (Technically, we always allowed slightly out-of-bounds values.) If I fix that, to only generate valid values, I'm losing the glitch. The very similar Keen 4 Lifewater Oasis top-of-screen glitch still works, though its behaviour is slightly different. Even the Guard Post 1 glitch still can be made to work by running into the right-hand side of the screen instead of looking down. Given these are important-enough glitches, I'll look into a better way of generating random tile values to see if I can find some to reproduce the glitch without having actually invalid tile values being passed through the code. In the meantime, though, this should work. (I haven't been able to reproduce the other Keen 6 glitches you mentioned, but I can't manage to do them on the real Keen 6 either, so that's on me.) |
A glitch commonly used to finish level 2 early in Keen 6 appears to crash Omnispeak, but only if level 1 has been loaded in the current game.
Steps to reproduce the crash scenario:
Note that if you enter level 2 without first having loaded level 1, the trick works and exits the level as expected.
Additionally, I was able to produce some other weird behavior (e.g. Keen teleporting to a completely unexpected part of level 2 instead of exiting the level) by substituting other levels for level 1 in the steps above, but these seem harder to consistently reproduce and most levels do not trigger a problem.
My guess is that Impossible Bulleting out of bounds in this level ends up reading something out of bounds of level 2's actual map data and runs into data left there by the previously loaded map. The outcome of this is probably different on DOS due to its different memory model, hence the trick reliably exiting the level on DOS vs. having unpredictable outcomes in Omnispeak depending on which level was loaded previously, the dimensions of that level, etc.
Tested with the Windows build from davidgow.net as well as my own win64 and win32 builds (FWIW, the Windows builds in the GitHub artifacts seem to crash upon entering a game for me).
Here is a playloop dump from the crash scenario, but I don't know if it tells you anything useful or manages to capture the frame that triggers the crash.
dumplevel2crash.zip
The text was updated successfully, but these errors were encountered: