ScummVM-Help is a helper library which aims to facilitate the creation of ASL scripts for ScummVM games.
Its main goal is to enable people to write ASLs that work across all versions of ScummVM (without multiple state descriptors and version checks), and to eliminate the need for tedious pointer scans.
Currently, every release version from 2.0.0 onwards is supported:
2.0.032-bit2.1.032-bitand64-bit2.1.132-bitand64-bit2.1.232-bitand64-bit2.2.032-bitand64-bit2.5.032-bitand64-bit2.5.132-bitand64-bit2.6.032-bitand64-bit2.6.132-bitand64-bit2.7.032-bitand64-bit2.7.132-bitand64-bit2.8.032-bitand64-bit2.8.132-bitand64-bit2.9.032-bitand64-bit2.9.132-bitand64-bit
Full functionality cannot be guaranteed when playing on custom or nightly builds of ScummVM.
Load the helper in startup {} specifying the engine of your game. For example, if the ASL script is for an SCI game:
startup {
Assembly.Load(File.ReadAllBytes("Components/scummvm-help")).CreateInstance("SCI");
}This loads the helper into vars.ScummVM to be accessed anywhere in your script.
Then, initialize the helper at the start of init {}:
init {
vars.ScummVM.Init();
}This attaches the helper to the game process and starts a signature scan for ScummVM's g_engine.
g_engine is a pointer within ScummVM which points to the currently active engine and which will function as the base address of any pointer paths you build using the helper.
If you just want g_engine and build your own raw pointer paths, you can use vars.ScummVM.GEngine as the base address, e.g.:
var dp = new DeepPointer((IntPtr)vars.ScummVM.GEngine, 0x50, 0x14);(Note: The g_engine scan is expected to work even on most custom builds and all nightly builds post 2.0.0)
Useful as vars.ScummVM.GEngine may be, the main advantage the library offers is that pointer paths can be built using ScummVM class field names.
For this, the API exposes the following methods:
vars.ScummVM.Watch<T> creates a MemoryWatcher<T> using field names.
For example:
vars.myWatcher = vars.ScummVM.Watch<ushort>("_card", "_id");Now, vars.myWatcher is a MemoryWatcher watching the value at the address reached via g_engine -> _card -> _id.
The second memory utility is Read<T>. As the name suggests, it merely reads a value of type T at the specified address rather than creating a watcher.
Use it for one-time reads, like this:
var capacity = vars.ScummVM.Read<int>("_gamestate", "_segMan", "_heap", "_capacity");You can also assign any MemoryWatchers to vars.ScummVM[<NAME>] like this:
vars.ScummVM["card"] = vars.ScummVM.Watch<ushort>("_card", "_id");You can then access the value with vars.ScummVM["card"].Current|Old or, conveniently, via current.card / old.card.
To keep your watchers updated, place this in update {}:
update {
vars.ScummVM.Update();
}The following debug flags exist (set them in startup{}):
vars.ScummVM.LogResolvedPaths(): print raw pointer paths any timeWatch<T>orRead<T>are called.[ScummVM-Help] Resolved path: 0x7FF67FF1CA38, 0x200, 0x8, 0x8vars.ScummVM.LogChangedWatchers(): print changes in any watchers stored inside the helper'sMemoryWatcherList.[ScummVM-Help] room: 100 -> 101
(Use TraceSpy (recommended) or DebugView to view debug prints)
- Groovie
- Mohawk_Myst
- Mohawk_Riven
- SCI
- Scumm (forthcoming)