Y U NO ENABLE IMAGES
Banner

No Quarter: V-Sides

No Quarter is an album of original games inspired by arcade and console classics. Cryptic Sea released a preview called V-Sides (scroll down), containing three games: Rescue Helicopter, Return to Snowboard Mountain, and a hidden preview of Hitlers Must Die!. HMD is planned to be a mostly-monochrome side-scrolling shooter with 2D physics. V-Sides includes one short demo level of HMD.

This guy (who also made some Hitlers Must Die! fan art) wouldn't stop bugging me about it, so I decided to try something new with this mini-game. Initially, all he wanted was a single-step (frame advance) hack, which was trivial (hook SDL_GL_SwapBuffers). Later I noticed that the data segment of the executable was a whopping 143 MB. I wondered, could the game store all data statically and not use dynamic memory allocation? I added few lines of code to save/restore the data segment to test this, and lo' and behold, instant save-states! I continued by hooking up input, timing and random functions, and, after some tweaking and debugging, I had everything to allow creating a tool-assisted speedrun.

Which I did.

My "100% items/kills" tool-assisted speedrun.

Despite the non-notability of the game, I think that it is quite noteworthy that it's possible to verifiably TAS a game with practically no reverse-engineering. The same idea could be expanded to other games, without having to resort to "overkill" techniques such as system-level virtualization.


Implementation details:

  • Since the game runs at a variable FPS, the FPS had to be "fixed" by making the game think that it is running at a constant 60 FPS. This has the side effect that the game will not run at the correct speed on systems with a monitor refresh rate different than 60 FPS. In theory, this could be mitigated by using a lower replay FPS, then artificially lowering the video FPS to the replay FPS.
  • Saving and restoring is performed at the same execution point (when the video buffers are swapped). The function is called from the same location (the stack pointer is always the same during a session), therefore it's safe to save/restore the stack and other memory regions at this point.
  • The following functions are hooked: SDL_GL_SwapBuffers, SDL_GetKeyState, SDL_GetTicks, SDL_Delay, rand. rand is imported from the Visual C++ Runtime Library – had it been linked statically, this wouldn't've been necessary, as the random seeds would be in the data segment.
  • The one offset that was found using reverse-engineering indicates whether a game has been selected from the main menu. This was technically optional.
  • The DLL patches some code to remove the intro and the need to input the Konami Code to activate HMD. However, this is strictly optional.
  • Although it's possible to record and redub the replay using just the game + the TAS DLL extension, I found it much more comfortable to use a text format to specify the replay, which allows comments and easy editing.
  • Yes, V-Sides contains two other games which can be TASed with this extension as well, but they're not really that interesting.

Files:

No one commented on this page yet. Why not be the first?