def METHOD_NAME(commands: str, params: Optional[Dict[str, str]] = None) -> str:
    """
    Preprocesses a Splitfile, performing parameter substitution (`${PARAM}` gets replaced with `params['PARAM']`).
    Also removes escaped newlines.
    Raises an error if not all parameters are specified.
    :param commands: A string with the raw Splitfile
    :param params: Dictionary of parameters to substitute
    :returns The preprocessed Splitfile.
    """
    # Also replaces all $PARAM in the splitfile text with the params in the dictionary.
    if params is None:
        params = {}
    commands = commands.replace("\\\n", "")
    for param, value in params.items():
        # Regex fun: if the replacement is '\1' + substitution (so that we put back the previously-consumed
        # possibly-escape character) and the substitution begins with a number (like an IP address),
        # then it gets treated as a match group (say, \11) which fails silently and adds weird gibberish
        # to the result.
        commands = re.sub(
            r"([^\\])\${" + re.escape(param) + "}",
            r"\g<1>" + str(value),
            commands,
            flags=re.MULTILINE,
        )
    # Search for any unreplaced $-parameters
    unreplaced = set(re.findall(r"[^\\](\${\S+})", commands, flags=re.MULTILINE))
    if unreplaced:
        raise SplitfileError("Unknown values for parameters " + ", ".join(unreplaced) + "!")
    # Finally, replace the escaped $
    return commands.replace("\\$", "$")