SplitScript reference / Migration
Migration
Choose the source language first, then the task or source concept. Stable catalog identities remain searchable, but the navigation follows the way a porter approaches the work.
ASL
For lifecycle and semantic context, start with the complete ASL porting guide.
Attachment and state
-
Assignments to current: Assign directly to
current.fieldfor an explicit post-read override;oldremains read-only. Use a trailing state-fieldifwhen rejection must happen at the transactional acceptance boundary, including the first snapshot. Supported directly -
Attachment state declaration: Declare one native process name, an array of alternate process names, or a typed emulator provider per autosplitter file. An ASL declaration listing multiple processes becomes alternate names for one attachment, not concurrent attachments. Names are exact host identities, so Windows executable candidates currently include
.exe. The declaration owns attachment and defines the fields polled intooldandcurrent. Use a typed pattern -
Attempt-scoped and run-scoped variables: Declare a bare top-level
letand assign it on every completingonStartpath. The inferred attempt-scoped value remains available across process detach and is cleared afteronReset, replacing manually reset run-owned state in polling code. Supported directly -
Bounded native stringN state: Choose the native encoding explicitly:
utf8bounds bytes andutf16lebounds two-byte code units. Use a typed pattern -
Contiguous memory aggregates: Read physically contiguous values as one naturally aligned record or fixed-length
[T; N]array when that type exactly matches the target-memory layout. Use a typed pattern -
MemoryWatcher: Declare polled memory in
state; use a trailing fieldifwithvalueand returnErr(message)when a transient candidate should retain its last accepted value. Use a typed pattern -
MemoryWatcherList: Use
statefor a fixed set of named transactional reads or retain runtime-discovered homogeneous addresses in an array; managed collection enumeration remains a distinct provider requirement. Use a typed pattern -
State snapshots in helper functions: Helpers may read
oldandcurrentdirectly or accept caller-selected snapshots as inferred parameters. The compiler propagates direct snapshot requirements and rejects calls before committed snapshots exist. Supported directly -
Version-labelled state blocks: Use named layouts in one state block and return the selected layout from
onAttach. Use a typed pattern
Process and memory
-
Attached process identity: Use
process.name()to read the exact process candidate that matched during attachment; use module metadata when the executable name alone does not identify a build. Supported directly -
Background signature scans: Remove legacy worker threads and await a module, explicit-range, or process-wide scan. Scans inspect a bounded window per tick and process closure cancels pending discovery. Use a typed pattern
-
DeepPointer: Use typed state paths for polled fields or
process.followfor discovered paths. Supported directly -
Loaded module discovery: Replace the enumerable ASL module bag with the narrow typed probe that matches the source intent: main executable discovery, a known optional module, a required module, or typed build identity. Preserve genuine unknown-name enumeration as an explicit host-runtime gap. Use a typed pattern
-
Task.Run: Replace worker threads with cooperative
awaitdiscovery or a boundedretrytransaction so timer updates keep yielding predictably. Use a typed pattern
Lifecycle and timer
-
Current timer split index: Call
timer.currentSplitIndex()and handle its optionalu64result so the host's negative no-attempt sentinel cannot become a route index. Supported directly -
Current timer state: Replace
timer.CurrentPhasewithtimer.state()and compare the exhaustiveTimerStateenum instead of relying on legacy numeric phase values. Supported directly -
exit lifecycle block: Use
onDetachfor cleanup that runs exactly once after an attached process closes. Use a typed pattern -
Exit-time game-time cleanup: Use
onDetachfor process-exit cleanup and explicitly pause or resume game time only when the original exit block changes that host state. Supported directly -
init lifecycle block: Use
onAttachfor pre-poll process discovery andonStateReadyfor post-refresh snapshot initialization. Use a typed pattern -
Load removal: Return the game's known loading state from
isLoading; fall through or returnNonewhen the script has no new loading-state observation. Supported directly -
Monotonic delays and debouncing: Replace elapsed-time uses of
DateTime.NoworStopwatchwith anInstantcaptured at the source event and an exactDurationcomparison. Use a typed pattern -
refreshRate: Use the declarative
tickRatepolicy for stable attached and detached polling rates; reservesetTickRatefor temporary dynamic changes. Supported directly -
Script-computed game time: Return a typed
DurationfromgameTimewhen the game exposes its own elapsed clock; fall through or returnNonewhen no new value is available. Supported directly -
start and reset timer event handlers: Keep
onStartandonReset; SplitScript samples timer transitions before process attachment so both actions also run while detached. Supported directly -
startup lifecycle block: Use settings and global declarations for data, then
setupfor remaining process-independent startup statements. Use a typed pattern -
update lifecycle block: Use
whileAttached; returning false skips the remaining timer decisions for that update. Use a typed pattern
Settings
-
Dynamic settings lookup: Replace
settings[key]withsettings.enabled(key)andsettings.ContainsKey(key)withsettings.contains(key). Declare exact host strings withkey "..."; choice and file settings remain statically typed. Supported directly -
Finite startup-generated settings: Use a compile-time settings family for bounded integer-keyed booleans; it lowers to ordinary declarations and remains available through
settings.enabled(key). Supported directly -
Runtime settings registration: Move
settings.Addcalls into the staticsettingsdeclaration, preserving the display label, stable host key, default, hierarchy, and tooltip explicitly. A boundedsettings.Addloop becomes a compile-timesettings familyinstead of hand-expanded declarations. Use a typed pattern
Collections and text
-
Bounded integer ranges: Use
..<for an exclusive upper endpoint or..=for an inclusive one; SplitScript rejects bare..so the endpoint policy is explicit. Supported directly -
List
collections : Use[T]for C# ordered list semantics; size-changing operations belong on variable-length arrays, while[T; N]remains fixed and no separate List type is planned. Use a typed pattern
Unity and emulators
-
GameCube emulator attachment and memory mapping: Use
GCNfor Dolphin and the supported RetroArch Dolphin core. The provider owns emulator discovery, address translation, and big-endian decoding, sogcnreads original GameCube addresses without manual byte swapping. Supported directly -
GBA emulator attachment and memory mapping: Use
GBAfor VisualBoyAdvance or VBA-M, mGBA, NO$GBA, Mednafen, supported RetroArch cores, and mGBA-based BizHawk. The provider owns emulator discovery and thegbaroot reads original EWRAM and IWRAM addresses without manualDeepPointermappings. Supported directly -
Genesis emulator attachment and memory mapping: Use
Genesisfor Fusion, Gens, BlastEm, Sega Game Room or Genesis Classics, and supported RetroArch cores. The provider owns discovery, normalizes emulator storage and byte order, and reads original work-RAM offsets throughgenesis. Supported directly -
Master System and Game Gear emulator attachment: Use
SMSfor Fusion, BlastEm, Mednafen, and supported RetroArch Master System or Game Gear cores. The provider owns emulator discovery and thesmsroot reads original work-RAM addresses. Supported directly -
PlayStation 2 emulator attachment and memory mapping: Use
PS2for PCSX2 and the supported RetroArch PCSX2 core. The provider owns emulator discovery and theps2root reads original PlayStation 2 addresses without manual host-memory mappings. Supported directly -
PlayStation emulator attachment and memory mapping: Use
PS1for ePSXe, pSX, DuckStation, Mednafen, PCSX-Redux, XEBRA, and supported RetroArch cores. The provider owns emulator discovery and theps1root reads original PlayStation addresses. Supported directly -
UnityASL, mono.Make, and managed metadata: Use the
Unitystate provider with top-levelimage,namespace, andclassschemas instead of manually discovering Mono or IL2CPP metadata withUnityASL,mono.Make<T>, ormono.MakeString. Supported directly -
Wii emulator attachment and memory mapping: Use
Wiifor Dolphin and the supported RetroArch Dolphin core. The provider owns emulator discovery, MEM1 and MEM2 translation, and big-endian decoding, sowiireads original Wii addresses without manual byte swapping. Supported directly
Unsupported host behavior
-
LiveSplit current game time: Keep script-computed game time as a typed
Duration; reading the host's coherent optional game-time snapshot requires additional runtime support. Planned -
LiveSplit current real time: Use
Instantonly for independent elapsed-time checks; exacttimer.CurrentTime.RealTimemetadata requires additional host support. Planned -
LiveSplit run and segment metadata: Current segment identity, route length, category/game names, and splits-file metadata require a typed read-only host snapshot. Planned
-
LiveSplit timer configuration: Run-offset and timing-method access needs an ordered least-privilege host contract; ports must not silently omit these user-visible mutations. Planned
-
shutdown lifecycle block: Exact script teardown needs the planned host shutdown notification;
onDetachis not equivalent. Planned -
split timer event handler: Exact
onSplitdelivery still needs an ordered host event contract that can distinguish splits, skips, and undos between updates. Planned
C#
-
Array length: Call
values.length()for theu32element count of dynamic and fixed arrays. Supported directly -
ASCII string lowercasing: Use
toAsciiLowerCasewhen game identifiers require ASCII-only normalization; this is not culture-sensitive Unicode lowercasing. Supported directly -
ASCII string uppercasing: Use
toAsciiUpperCasewhen game identifiers require ASCII-only normalization; this is not culture-sensitive Unicode uppercasing. Supported directly -
ASCII whitespace trimming: Use
trimAsciiWhitespacefor text known to use ASCII boundary whitespace; review Unicode and character-set trimming explicitly. Use a typed pattern -
Bitwise complement: Use type-directed
!: it is logical negation for booleans and width-preserving bitwise complement for integers. Supported directly -
Boolean conversion: Use
value != 0for numbers, the value itself for bool, and explicit trimmed ASCII-insensitive true/false handling for strings. Use a typed pattern -
Bulk array extension: Call
values.extend(moreValues)to append a typed array in order; extending an array with itself duplicates its original contents once. Supported directly -
C# duration ticks: Convert 100-nanosecond C# ticks to a source unit explicitly, with range review; SplitScript does not expose C# ticks as a native duration unit. Use a typed pattern
-
Collection count: After choosing an array or set from the source's ordering and uniqueness requirements, call
values.length()for itsu32count. Supported directly -
Display conversion: Use
value as Stringfor ordinary Display conversion andinteger.toString(radix)for bases 2 through 36; culture, null, and object overloads require separate policies. Use a typed pattern -
Exact string replacement: Use fallible
replaceAllfor immutable exact replacement; explicitly handle failure and translate a null C# replacement to an empty string only when deletion was intended. Use a typed pattern -
Fixed-width numeric types: Memory-facing numbers use explicit signedness and bit widths. Supported directly
-
Floating-point ceiling: Use
value.ceil()with an explicit f32 or f64 boundary; review C# decimal inputs separately. Use a typed pattern -
Floating-point conversion: Use an explicit f32/f64
ascast for numbers,String.parsefor text, or anifexpression for booleans. Use a typed pattern -
Floating-point floor: Use
value.floor()with an explicit f32 or f64 boundary; review C# decimal inputs separately. Use a typed pattern -
Floating-point rounding: Use
value.round()orvalue.roundTo(digits)for midpoint-to-even floating-point rounding; review result width, decimal inputs, and explicit midpoint modes. Use a typed pattern -
Floating-point square root: Use
value.sqrt()with an explicit f32 or f64 boundary when preserving C# Math versus MathF semantics. Use a typed pattern -
Floating-point truncation: Use
value.truncate()with an explicit f32 or f64 boundary when preserving C# Math versus MathF semantics. Use a typed pattern -
Function declarations: Functions and methods use the
fndeclaration keyword. Supported directly -
Integer conversion: Choose fixed-width
as, midpoint-to-even rounding, strict string parsing, or an explicit boolean mapping from the source type; C# checked overflow is not SplitScript cast behavior. Use a typed pattern -
Last substring position: Use
lastIndexOffor an optional final UTF-8 byte offset; review C# UTF-16 index arithmetic and replace the-1sentinel withT?handling. Use a typed pattern -
Nullable blank strings: Use
String.isBlankfor required strings and matchString?explicitly when absence should also count as blank. Use a typed pattern -
Nullable string emptiness: Use
String.isEmptyfor required strings and matchString?explicitly when absence should also count as empty. Use a typed pattern -
Numeric maximum: Use
left.max(right)after establishing one intended numeric type; review C# implicit conversions and decimal overloads. Use a typed pattern -
Numeric minimum: Use
left.min(right)after establishing one intended numeric type; review C# implicit conversions and decimal overloads. Use a typed pattern -
Numeric powers: Use
value.squared()for the corpus-proven exponent two and an explicit typed shift for power-of-two masks; general floating powers remain planned. Use a typed pattern -
Numeric string parsing: Replace static Parse/TryParse calls and output parameters with fallible
text.parse()and ordinaryT!handling. Supported directly -
Signed absolute value: Use
value.abs()after establishing a signed numeric type; review C# signed-minimum overflow, unsigned conversions, and decimal inputs. Use a typed pattern -
String collection joining: Use
String.join(values, separator)for a typed string array; convert C# object, variadic, enumerable, and range overloads explicitly. Use a typed pattern -
String equality: Use
==or!=for exact string content equality; useequalsIgnoreAsciiCaseonly when ASCII-insensitive matching is intended. Supported directly -
String length: Use
isEmpty()for emptiness andbyteLength()only for UTF-8 byte-oriented or proven ASCII logic; C#Lengthcounts UTF-16 code units. Use a typed pattern -
String padding: Use
padStart(width, fill)orpadEnd(width, fill)with an explicit character; review C# UTF-16 widths against SplitScript's Unicode-scalar widths. Use a typed pattern -
String type: The immutable UTF-8 string type is named
String. Supported directly -
Substring extraction: Use fallible
slice(start, exclusiveEnd)only after translating C#'s length argument and verifying that UTF-16 source positions are valid UTF-8 byte offsets. Use a typed pattern -
Substring position: Use
indexOffor an optional UTF-8 byte offset; review C# UTF-16 index arithmetic and replace the-1sentinel withT?handling. Use a typed pattern -
Text duration parsing: Replace
TimeSpan.Parseaccording to whether the input is fixed data or an already-typed timer value; do not preserve culture-sensitive parsing by default. Use a typed pattern -
Timer durations: Use
Durationinstead of C#'sTimeSpan. Supported directly -
Variable declarations: Use one inferred
letdeclaration; SplitScript has no const/let split. Supported directly
JavaScript
-
Absent optional values:
Noneis SplitScript's zero-sized unit value and the absent side of an option. Supported directly -
Strict equality operators: Use typed
==and!=; SplitScript has no coercing equality operators, so JavaScript's extra=is unnecessary. Supported directly
Rust
- Numeric byte order: Use
Numeric.swapBytesto reverse a numeric value's raw bytes after reading data stored in the opposite byte order. It preserves the exact integer or floating-point type; eight-bit values are unchanged. Supported directly