Difference between revisions of "Wintermute/Externals"

Jump to navigation Jump to search
11,248 bytes added ,  03:54, 2 December 2020
update for ResidualVM merge
(update for ResidualVM merge)
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
This page lists known external functions for most [[Wintermute/Games|Wintermute games]].
This page lists known external functions for most [[Wintermute/Games|Wintermute games]].


WME allows game scripts to call external functions from DLL libraries. This way game creator can either call Win32 API functions or use custom extension DLL libraries.
Original WME 1.x allows game scripts to call external functions from DLL libraries. This way game creator can either call Win32 API functions or use custom extension DLL libraries.
 
ScummVM's WME contain mocks and reimplementations for functions listed below, emulating import those functions from a given DLL.


= 2D games =
= 2D games =


== James Peris (Demo 2012) ==
== James Peris (Demo 2012) ==
=== getURLContent ===
=== geturl.dll ===
==== getURLContent ====
Used to download news headlines at Demo 2012 of James Peris
Used to download news headlines at Demo 2012 of James Peris


Line 16: Line 19:


Sets 3rd param to "Request Error." on error
Sets 3rd param to "Request Error." on error
Context:
    var buf = new String(255);
    var buf2 = new String(255);
    getURLContent("http://www.lacosaweb.com", DirURL, buf);
    if((((buf == "Request Error.") || (buf == null)) || (buf == ""))) {
        SCUPDalt.Red = 0;
        textoscup1 = "www.jamesperis.com";
        textoscup2 = "www.jamesperis.com";
    }
    else {
        SCUPDalt.Red = 1;
        textoscup1 = buf;
        getURLContent("http://www.lacosaweb.com", DirURL2, buf2);
        textoscup2 = buf2;
    }


== Various games by HeroCraft ==
== Various games by HeroCraft ==
=== SetValueToReg ===
=== tools.dll ===
==== SetValueToReg ====
Used to switch game's windowed/fullscreen mode at games by HeroCraft
Used to switch game's windowed/fullscreen mode at games by HeroCraft


Line 25: Line 45:
Known usage: SetValueToReg("Software\HeroCraft\<GameID>\Video", "Windowed", 1)
Known usage: SetValueToReg("Software\HeroCraft\<GameID>\Video", "Windowed", 1)


=== changeWindowCaption ===
Context:
    if(checkBox.Pressed) {
        SetValueToReg("Software\HeroCraft\Pole\Video", "Windowed", 0);
        Game.windowedState = 0;
    }
    else {
        SetValueToReg("Software\HeroCraft\Pole\Video", "Windowed", 1);
        Game.windowedState = 1;
    }
 
=== img.dll ===
==== changeWindowCaption ====
Used to change game's window caption at games by HeroCraft
Used to change game's window caption at games by HeroCraft


Line 32: Line 63:
Known usage: changeWindowCaption(Game.Hwnd, <Title>)
Known usage: changeWindowCaption(Game.Hwnd, <Title>)


=== maximizedWindow ===
Context:
    if(Game.WindowedMode) {
        maximizedWindow(Game.Hwnd, 1024, 768);
    }
    changeWindowCaption(Game.Hwnd, getStr("Поле Чудес"));
 
==== maximizedWindow ====
Used to change game's window size at games by HeroCraft
Used to change game's window size at games by HeroCraft


Line 40: Line 77:


== Wilma Tetris ==
== Wilma Tetris ==
=== ShellExecuteA ===
=== shell32.dll ===
==== ShellExecuteA ====
Used to open URL in browser at Wilma Tetris
Used to open URL in browser at Wilma Tetris


Line 48: Line 86:


Returns value >32 on success
Returns value >32 on success
Context:
    function RunDocument(Filename) {
        ShellExecuteA(0, "open", Filename, "", "", 3);
        return null;
    }
   
    ...
   
    on "off_url" {
        RunDocument("http://offstudio.fabry.cz");
        return;
    }
    on "dc_url" {
        RunDocument("http://dead-code.org");
        return;
    }


= 2.5D games =
= 2.5D games =
Those games are out of ScummVM scope and are not supported by ResidualVM yet. However, their external function calls are mocked or implemented.
These games are in the process of being implemented.
== Art of Murder: FBI Confidential ==
== Art of Murder: FBI Confidential ==
=== _InstallUtilAnsi@0 ===
=== installutil.dll ===
==== _InstallUtilAnsi@0 ====
Used to check if DVD is inserted at Art of Murder: FBI Confidential
Used to check if DVD is inserted at Art of Murder: FBI Confidential


Line 61: Line 117:
Returns 1 on success, other value on fail (which leads to Game.QuitGame() in non-Debug mode)
Returns 1 on success, other value on fail (which leads to Game.QuitGame() in non-Debug mode)


== Various games by Corbomite Games ===
Context:
=== IRC_init ===
    var ivlmsg = Game.ExpandString("/vld0002/Proszę włożyć płytę ''Art of Murder Sztuka Zbrodni'' do napędu DVD-ROM.");
    var valid = _InstallUtilAnsi@0();
    if((valid != 1)) {
        var query = Game.ConfirmBox(ivlmsg);
        valid = _InstallUtilAnsi@0();
        if((valid != 1)) {
            if(Game.DebugMode) {
                Game.Msg("!!! no media !!!");
            }
            else {
                Game.QuitGame();
            }
        }
    }
 
== Various games by Corbomite Games ==
=== dlltest.dll ===
==== IRC_init ====
Used to connect to debug IRC server at games by Corbomite Games
Used to connect to debug IRC server at games by Corbomite Games


Line 81: Line 154:
Returns 0 on success, other value on error
Returns 0 on success, other value on error


=== ChangeNick ===
Context:
    if(EnableIRC) {
        IRCConnected = IRC_init(PlayerName);
    }
 
==== ChangeNick ====
Used to update nick at debug IRC server at games by Corbomite Games
Used to update nick at debug IRC server at games by Corbomite Games


Line 90: Line 168:
Return value is never used
Return value is never used


=== IRC_SendString ===
Context:
    if(EnableIRC) {
        ChangeNick(PlayerName);
    }
 
==== IRC_SendString ====
Used to send debug and chat lines to an IRC server at games by Corbomite Games
Used to send debug and chat lines to an IRC server at games by Corbomite Games


Line 99: Line 182:
Known Channel values are: "#Zbeng" and "#ZbengDebug"
Known Channel values are: "#Zbeng" and "#ZbengDebug"


=== IRC_GetChatStrings ===
Context:
    function SendMessageToIrc(inStr) {
        if((IRCConnected == 0)) {
            IRC_SendString(inStr, "#zbeng");
        }
        return null;
    }
    function SendDebugMessageToIrc(inStr) {
        if((IRCConnected == 0)) {
            IRC_SendString(inStr, "#ZbengDebug");
        }
        return null;
    }
 
==== IRC_GetChatStrings ====
Used to get chat lines from an IRC server at games by Corbomite Games
Used to get chat lines from an IRC server at games by Corbomite Games


Line 106: Line 203:
Known usage: IRC_GetChatStrings(<Buffer>, 65535)
Known usage: IRC_GetChatStrings(<Buffer>, 65535)


=== IRC_quit ===
==== IRC_quit ====
Used to disconnect from debug IRC server at games by Corbomite Games
Used to disconnect from debug IRC server at games by Corbomite Games


Line 113: Line 210:
Known usage: IRC_quit()
Known usage: IRC_quit()


=== LoadLibraryA ===
=== kernel32.dll ===
==== LoadLibraryA ====
Used for checking library availability at games by Corbomite Games
Used for checking library availability at games by Corbomite Games


Line 122: Line 220:
Return values are only compared with zero and are never used in other APIs
Return values are only compared with zero and are never used in other APIs


=== FreeLibrary ===
Context:
    var inifile = new File("Zbang.ini");
    inifile.OpenAsText(1);
    IRCWinSetting = inifile.ReadText(1);
    if(((IRCWinSetting != 1) && (IRCWinSetting != 2))) {
        IRCWinSetting = 0;
    }
    DEBUG(("IRCWinSetting " + IRCWinSetting));
    if((IRCWinSetting > 0)) {
        IRCDllLib = LoadLibraryA("dlltest.dll");
    }
    if((IRCDllLib == 0)) {
        EnableIRC = 0;
    }
 
==== FreeLibrary ====
Declared at games by Corbomite Games
Declared at games by Corbomite Games


Line 129: Line 242:
Specification: external "kernel32.dll" stdcall FreeLibrary(long)
Specification: external "kernel32.dll" stdcall FreeLibrary(long)


=== GetEnvironmentVariableA ===
==== GetEnvironmentVariableA ====
Used for getting environment variables at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
Used for getting environment variables at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest


Line 140: Line 253:
Known EnvName values used in licensing code: "FULLGAME"
Known EnvName values used in licensing code: "FULLGAME"


=== Register ===
Context:
    method getEnvironmentVar(envName) {
        var envContent = new String(65535);
        var retval = GetEnvironmentVariableA(envName, envContent, 65535);
        return envContent;
        return null;
    }
    method CheckArmadillo() {
        var path = getEnvironmentVar("");
        DEBUG(path);
        var variarblesArr = new Array("USERKEY", "ALTUSERNAME", "ENHFINGERPRINT", "EXTRAINFO", "FINGERPRINT", "KEYSTRING", "STOLENKEY", "TRIAL", "FULLGAME");
        var len = variarblesArr.Length;
        var i = 0;
        while((i < len)) {
            var key = variarblesArr[i];
            var variable = getEnvironmentVar(key);
            DEBUG(((key + "=") + variable));
            i = (i + 1);
        }
        global g_Publisher;
        if(!(g_Publisher.DRM)) {
            if(!(g_Publisher.OverrideFullgame)) {
                var PublisherFullGame = getEnvironmentVar("FULLGAME");
                if((PublisherFullGame != "TRUE")) {
                    isFullDemo = 1;
                }
            }
            else {
                global isBought = 1;
            }
        }
        return null;
    }
 
=== httpconnect ===
==== Register ====
Used to register license key online at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
Used to register license key online at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest


Line 177: Line 325:
For some reason always returns -7 for me in a test game
For some reason always returns -7 for me in a test game


=== Validate ===
Context:
    method RegisterKey(inProductkey) {
        var productID = new String(65535);
        var productKey = new String(65535);
        productKey = inProductkey;
        productID = "357868";
        var rerVal = Register(productID, 65535, productKey, 65535);
        DEBUG(("Validate : " + rerVal));
        if((rerVal == 1)) {
            return 1;
        }
        productID = "353058";
        rerVal = Register(productID, 65535, productKey, 65535);
        DEBUG(("Validate : " + rerVal));
        if((rerVal == 1)) {
            return 1;
        }
        productID = "353006";
        rerVal = Register(productID, 65535, productKey, 65535);
        DEBUG(("Validate : " + rerVal));
        if((rerVal == 1)) {
            return 1;
        }
        ShowMessage(rerVal);
        return rerVal;
        return null;
    }
 
==== Validate ====
Used to validate something at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
Used to validate something at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest


Line 190: Line 366:
For some reason always returns 1 for me in a test game
For some reason always returns 1 for me in a test game


=== SendHTTPAsync ===
==== SendHTTPAsync ====
Used to send game progress events to server at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
Used to send game progress events to server at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest


Line 205: Line 381:
Return value is never used
Return value is never used


=== SendRecvHTTP (6 params variant) ===
Context:
    method sendEventNow(inEventName, extraParams) {
        global NetworkEnabled;
        if((NetworkEnabled != 1)) {
            DEBUG("Not sending event due to network disabled");
            return 0;
        }
        if(firewall) {
            DEBUG("Not sending event due to firewall");
            return 0;
        }
        var httpStr = new String(65535);
        var Request = new String(65535);
        var server = new String(65535);
        Request = ((((((((((("http://backend.pizzamorgana.com/event.php?Event=" + inEventName) + "&player=") + this.PlayerName) + "&extraParams=") + extraParams) + "&SN=") + this.SN) + "&Episode=1&GameTime=") + Game.CurrentTime) + "&UniqueID=") + this.Unique);
        server = "backend.pizzamorgana.com";
        DEBUG((((("Send: '" + Request) + "' to server '") + server) + "'"));
        if((Request != null)) {
            SendHTTPAsync(server, 65535, Request, 65535, httpStr, 65535);
        }
        httpStr = httpStr.Substr(0, 256);
        DEBUG((("Recv: '" + httpStr) + "'"));
        return httpStr;
        return null;
    }
 
==== SendRecvHTTP (6 params variant) ====
Declared at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest
Declared at Pizza Morgana: Episode 1 - Monsters and Manipulations in the Magical Forest


Line 214: Line 416:
Always returns -7 for me in a test game, probably returns the same network errors as Register()
Always returns -7 for me in a test game, probably returns the same network errors as Register()


=== SendRecvHTTP (4 params variant) ===
==== SendRecvHTTP (4 params variant) ====
Used to call HTTP methods at Zbang! The Game
Used to call HTTP methods at Zbang! The Game


Line 226: Line 428:


Return value is never used in Zbang scripts
Return value is never used in Zbang scripts
== Stroke of Fate dilogy ==
=== [TODO]routine.dll ===
==== GetDPI ====
Used at CheckFont() function to select font DPI.
Unused, if Game.RegReadNumber("DefaultDPI", 0) is not 0.
Specification: external "routine.dll" cdecl long GetDPI()
Known usage: dpi = GetDPI()
Context:
    function CheckFont() {
        var dpi = Game.RegReadNumber("DefaultDPI", 0);
        BASEFONT = "fonts";
        if((dpi == 0)) {
            dpi = GetDPI();
        }
        if((dpi <= 72)) {
            dpi = 72;
        } else if((dpi <= 96)) {
            dpi = 96;
        } else if((dpi <= 120)) {
            dpi = 120;
        } else {
            dpi = 144;
        }
        if((dpi == 72)) {
            BASEFONT = "fonts.72";
        }
        if((dpi == 120)) {
            BASEFONT = "fonts.120";
        }
        if((dpi == 144)) {
            BASEFONT = "fonts.144";
        }
    }
==== GetCaption ====
Used at CheckCaption() function to get window title.
Expects CheckCaption(Game.Hwnd).IndexOf("Wintermute Engine", 0) >= 0
Specification: external "routine.dll" cdecl string GetCaption(long)
Known usage: GetCaption(Game.Hwnd)
Context:
    function CheckCaption() {
        var p = "Wintermute Engine";
        while(1) {
            var s = GetCaption(Game.Hwnd);
            s = new String(s);
            if((s.IndexOf(p, 0) >= 0)) {
                break;
            }
            Sleep(1);
        }
        SetCaption(Game.Hwnd, Game.ExpandString("/MAIN_CAPTION3/"));
    }
==== SetCaption ====
Used at CheckCaption() function to set window title.
Specification: external "routine.dll" cdecl bool SetCaption(long, string)
Known usage: SetCaption(Game.Hwnd, Game.ExpandString("/MAIN_CAPTION3/"))
==== RemoveFile ====
Used at SaveTempScreenShot() & RemoveTempScreenShot() functions to manage screenshot files.
Specification: external "routine.dll" cdecl bool RemoveFile(string)
Known usage: RemoveFile(Directory.TempDirectory + "\tempss.bmp")
Known usage: RemoveFile(Game.SaveDirectory + "\" + newname + ".bmp")
Context:
    var sd = Game.SaveDirectory;
    if((sd == NULL)) {
        sd = "qsaves";
    }
    sd = (sd + "\");
    this.SaveFilePath = sd;
    this.SaveFileExtention = ".dat";
    this.TempScreenShot = (Directory.TempDirectory + "\tempss.bmp");
   
    ...
   
    method RemoveTempScreenShot() {
        var filename = this.TempScreenShot;
        if(Game.FileExists(filename)) {
            RemoveFile(filename);
        }
        return null;
    }
    method SaveTempScreenShot(newname) {
        var oldname = this.TempScreenShot;
        if(!(Game.FileExists(oldname))) {
            log.Add((("svg::SaveTempScreenShot(" + GetValue(newname)) + ") error, temporary screenshot is unavailable"));
            return null;
        }
        if((newname == NULL)) {
            newname = "qsave";
        }
        newname = ((this.SaveFilePath + newname) + ".bmp");
        if(Game.FileExists(newname)) {
            RemoveFile(newname);
        }
        RenameFile(oldname, newname);
        return null;
    }
==== RenameFile ====
Used at SaveTempScreenShot() & RemoveTempScreenShot() functions to manage screenshot files.
Specification: external "routine.dll" cdecl bool RenameFile(string, string)
Known usage: RenameFile(Directory.TempDirectory + "\tempss.bmp", Game.SaveDirectory + "\" + newname + ".bmp")
=== [TODO]protect.dll ===
Steam version of Stroke of Fate: Operation Bunker does not have this DLL.
However, game code contain some checks that depend on GetOptions() results, which use some of those calls.
Specifications:
    external "protect.dll" stdcall long PSA_DisableFeaturesGrantedByLicense(membuffer);
    external "protect.dll" stdcall PSA_DummyFunction();
    external "protect.dll" stdcall long PSA_GetFeaturesGrantedByLicense(membuffer);
    external "protect.dll" stdcall long PSA_IsDemoMode(membuffer);
    external "protect.dll" stdcall long PSA_IsTrialMode(membuffer);
PSA_GetFeaturesGrantedByLicense sets 4-byte buffer's first 5 bits with some feature flags of unknown semantics. Maybe same game features are missing in Steam version because of this.
PSA_IsDemoMode sets 1-byte buffer to non-zero if license is Demo.
PSA_IsTrialMode sets 1-byte buffer to non-zero if license is Trial.
PSA_DisableFeaturesGrantedByLicense & PSA_DummyFunction are never used.
Context:
    function GetOptions() {
        var p;
        var buf = new MemBuffer(4);
        buf.SetInt(0, 0);
        PSA_GetFeaturesGrantedByLicense(buf);
        p.R1 = (buf.GetInt(0) % 2);
        p.R2 = (((buf.GetInt(0) - p.R1) / 2) % 2);
        p.R3 = (((buf.GetInt(0) - p.R2) / 4) % 2);
        p.R4 = (((buf.GetInt(0) - p.R3) / 8) % 2);
        p.R5 = (((buf.GetInt(0) - p.R4) / 16) % 2);
        buf.SetSize(1);
        buf.SetBool(0, FALSE);
        PSA_IsDemoMode(buf);
        p.D = buf.GetBool(0);
        buf.SetBool(0, FALSE);
        PSA_IsTrialMode(buf);
        p.T = buf.GetBool(0);
        return p;
    }
Known checks:
    o = (!(o.R1) && o.R5)
    if(((((Random(0, 1) == 0) || (enl.safe_state == "oil")) || DEBUG) && (!(o.D) && !(o.R2))))
    if(((quest.herda == 12) && o.R3))
    o = (!(o.T) && o.R3)
    if(o.R3)
    if(o.R4)
    if((((((((enl.linge_a && enl.linge_b1) && enl.linge_b2) && enl.linge_b3) && enl.linge_b4) && enl.linge_d) || TRUE) && (!(o.T) && o.R4)))
8,012

edits

Navigation menu