3D Lemmings Memory Hacking

Started by namida, July 18, 2019, 02:52:40 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

namida

Here's a list of (potentially) useful offsets in memory I've found. You can use the hidden memory-hacking features in L3DUtils, or a debugger version of DOSBox, to make use of these. There's probably also ways to use them with software like Cheat Engine, but that's beyond the scope of what I'm interested in here - if anyone else wants to do a write-up of how to get that working, I'm happy to add it to this first post.

NOTE: Unless explicitly mentioned otherwise, all multi-byte values are in in-memory order, not taking into account endianness either way. Though FWIW - almost universally (if not completely universally?), L3D uses little-endian values.

0x001938 - The four bytes starting here will have the value 0xFFFFFFFF if Lemmings 3D has terminated, but other values while it's running. Useful as a "Is L3D still running?" check.

0x01090F - The string "V1.13 26/07/95 17:23:11" starts here in the full version of Lemmings 3D, which can be used both to identify versions and to locate L3D in DosBox memory (indeed - this string is what L3DUtils' replay tool uses to locate it!).

0x010952 - These two bytes seem to affect which scene comes up next when leaving the title screen, and also get set during other title screen events. This may be some kind of raw memory / EXE data pointer, as the values are spaced and invalid ones usually cause crashes. Setting this value alone does nothing; it seems to need to be combined with a manual trigger or 0x01D822-triggered transition. Additionally, the title screen ignores input (except mouse movement) when this is not set to 0x0000.
0x010952 known values
Only those that have a fade-out have been tested by injecting; others have only been determined by reading the memory values when the options are selected.

0x0000 - Quits the game; these bytes will also have this value when at the title screen and no option has been selected
0x0305 - Goes to options menu
0x04A0 - Changes the difficulty rank
0x1205 - Brings up the "Exit?" confirmation prompt
0xB012 - Goes to level select of currently selected rank
0xBE09 - Goes to code entry screen

0x011394 - On the level code screen, contains 0x65 if an invalid password was entered, and 0x54 if a valid password was entered.

0x011396 - On the level code screen, contains the remaining time (unsure of units) before fadeout begins, after confirming a code.

0x0113A6 - On the level code screen, contains the entered code in plain text.

0x0113B1 - On the level code screen, contains the entered code in an encrypted form (00 = "A", and it's XOR'd with something, I forget what off-hand.)

0x011642 - This byte has bitwise flags that have effects in-game, including at the preview / postview screens. So far, I haven't noticed any effects at the title / level-select / code screens, although values do get set to it at these screens.
0x011642 Known Flags
Note: The "always"es are based on quite limited testing. Maybe they change during transitions, or maybe they change if you're replaying vs first attempt, or maybe they depend on if you viewed the preview screen, etc. Take anything that's semi-unknown with a grain of salt here. If not stated otherwise, unknowns are always off (as far as I've observed).

0x0001 - In-game, invokes an exit. In the menu-type screens, can be used to flag "exit to title screen" during a transition out.
0x0002 - unknown, always on when in-game but not on preview / postview screens
0x0004 - unknown, always on at wallpaper screen but not any other screens
0x0008 - Marks the game as paused. Also always-on at wallpaper screen when idle (gets turned off when changing screen, even if going to level preview), but not any other screens.
0x0010 - unknown, might do nothing
0x0020 - Marks the game as in fast-forward mode.
0x0040 - unknown, might do nothing
0x0080 - If active alongside 0x0001 when in-game, the exit is a restart / go to postview, not an exit-to-title.
0x0100 - If active, the mouse cursor is visible. Glitchy at the preview screens but displays fine at the postview screen.
0x0200 - unknown, always on when idle in-game or at wallpaper screen, but not the other two
0x0400 - unknown, always on when idle at any of these screens other than postview
0x0800 - unknown, might do nothing
0x1000 - unknown, seems to be always-on when solidly in a screen, but off during at least some transitions (tested: Wallpaper -> Ingame, Wallpaper -> Level Preview)
0x2000 - unknown, might do nothing
0x4000 - unknown, always on in-game but not at any other screen
0x8000 - If active when transitioning from wallpaper to in-game, the level view preview is displayed first.

0x011688 - 0x11 (17) bytes, the filename of the level file to use, null-terminated.
0x011699 - 0x0F (15) bytes, the filename of the BLK file to use, null-terminated. It may be the case that these strings aren't fixed-length, but simply "one immediately follows the other". I have not bothered to investigate this.

0x016B34 - When in-game, this byte contains the number of lemmings saved (NOT the number displayed as the "IN" value, but the actual saved count).

0x01D300 - Contains a copy of the most recently loaded BLK file. 0x580 (1408) bytes in size.

0x01D882 - This byte contains the time (not sure of measurement unit) until a new screen will be loaded, when fading between screens. A value of 0x00 means "no new screen is being loaded". It's usually set to 0x32 (50) when a transition begins. Note that the fade animation is independent of this - if the transition is delayed by repeatedly setting this byte to a high value, the screen will fade out but the new menu won't load until the value stops being overwritten. Likewise, if the value is immediately set to a value lower than 0x32, the screen will change without fully fading out first.

0x01E1E4 - A two-byte value containing the current level number; if it mismatches, the replay data is cleared when gameplay begins (but otherwise no ill effects of it being wrong). This only gets set when starting gameplay the first time (not while on the preview screens), which is why (prior to me adding a workaround) L3DUtils used to require starting gameplay once before a replay could be loaded. You can use the level / BLK filenames above to get correct data even at these screens.

0x026580 - Contains a copy of the most recently loaded LEVEL file. 0x10200 (66048) bytes in size.

0x065460 - Save data is loaded to here. Limited usefulness, as you can easily obtain a copy on-disk, and it's reloaded from disk almost every time it's actually used for anything.

0x224000 - Replay data is stored here. It's 0xFD22 (64,802) bytes in size. Weird stuff can happen if this is partially overwritten, or overwritten mid-gameplay without immediately restarting, or overwritten during playback.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)

namida

#1
Here's an amusing - though probably not all that useful (I assume it can likely be extracted from a file anyway) - find.

There are also similar "graphics" (maybe actual graphics, that just so happen to be 16px wide) starting at 0x13C000. These are in fact the editor-type graphics we discovered in the data files a while back, confirming that for some reason L3D does load these.
My projects
2D Lemmings: NeoLemmix (engine) | Lemmings Plus Series (level packs) | Doomsday Lemmings (level pack)
3D Lemmings: Loap (engine) | L3DEdit (level / graphics editor) | L3DUtils (replay / etc utility) | Lemmings Plus 3D (level pack)
Non-Lemmings: Commander Keen: Galaxy Reimagined (a Commander Keen fangame)