IRC Channel Discord Channel

RO Patcher Lite Help (c) 2009-2022 Ai4rei/AN This pre-release content is subject to changes.

This article has been migrated to the help system and might not apply the necessary markups to fit with the remaining content.

Plug-in API Documentation

[v2.4.5+]None of this applies anymore, plug-in support has been removed in favor of the RO Patcher Lite+ROCred merge.

This describes the mechanics and interfaces of the RSU plug-in API. Everything is explained using C notation, but can be applied to all languages, that are able to generate DLLs and use the __stdcall calling convention, unless noted otherwise.

Interfaces - Version 1

This version was introduced in 1.4.1.334, on 2010-05-19.

IPlugCommon

Handles plug-in interaction and non-categorized services.

IPlugCommon::InterfaceRegister

bool InterfaceRegister(const unsigned long* lpInterfaceId, unsigned long luVersion, void* lpReserved, void* lpInterface);
Purpose:
Registers an interface, that is then available to all other plug-ins.

Parameters:
  • lpInterfaceId
    A static pointer to an unique static identifier for the interface.
  • luVersion
    Version of the interface being registered. Meaning of this value is plug-in dependent.
  • lpReserved
    Reserved for future use, must be NULL.
  • lpInterface
    Pointer to a static interface, which is used by other plug-ins to access it's methods. It must be available during entire life-time of the plug-in. The first two members must comply the IPlugUnknown interface.
Return value:
If the registration was successful true, otherwise false.

Note:
If there is already an interface with this id and same version, the registration will fail.

IPlugCommon::InterfaceQuery

bool InterfaceQuery(const unsigned long* lpInterfaceId, unsigned long luVersion, void* lpReserved, void** lppInterface);
Purpose:
Requests an interface of an another plug-in. Cannot be used for built-in interfaces.

Parameters:
  • lpInterfaceId
    A static pointer to an unique static identifier of the interface.
  • luVersion
    Version of the interface being requested.
  • lpReserved
    Reserved for future use, must be NULL.
  • lpInterface
    Pointer to a interface pointer, which receives the requested interface. InterfaceQuery already issues Acquire, so you do not need to call it.
Return value:
When the interface was found with given version true, otherwise false.

IPlugCommon::GetPatchInfo

bool GetPatchInfo(unsigned long luType, const char** lppszString);
Purpose:
Retrieves a patch information member value.

Parameters:
  • luType
    One of the RSU_IPATCH_* constants, which identifies the member whose value should be retrieved.
  • lppszString
    Pointer to a pointer, which receives the pointer to current value of the requested member.
Return value:
Is true, when the value was retrieved, otherwise false.

IPlugCommon::SetPatchInfo

bool SetPatchInfo(unsigned long luType, const char* lpszString);
Purpose:
Sets a patch information member value.

Parameters:
  • luType
    One of the RSU_IPATCH_* constants, which identifies the member whose value should be set.
  • lpszString
    Pointer to a buffer, which should become the new value for given member. This value must be static.
Return value:
Is true, when the value was set, otherwise false.

IPlugCommon::PushTask

bool PushTask(bool (*lpTaskFunc)(void* lpContext), void* lpContext, int nFailType);
Purpose:
Adds a task for worker thread processing. Can be only used during processing of RSU_PLUG_EVENT_QUERYTASK.

Parameters:
  • lpTaskFunc
    Pointer to a function, that will do desired task inside patcher's worker thread. Return value indicates whether or not the task failed. Can be NULL to set-up default patch sequence using current patch information, lpContext must be NULL in such case.
  • lpContext
    Plugin-defined data to pass to lpTaskFunc.
  • nFailType
    One of the RSU_TASK_FAIL_* constants, which identifies the action upon failure of given task. RSU_TASK_FAIL_RETRYONCE can be or'd (|) to any other constant to retry the task once, before the task is considered failed.
Return value:
When the task was successfully added true, otherwise false.

Note:
The amount of tasks is limited to 10 per RSU_PLUG_EVENT_QUERYTASK. Do NOT rely on the fact, that the function will actually be called. If you supply dynamically allocated resources in lpContext, make sure, that you have the means to detect and release them, even when the function is not run.

IPlugUI

Handles all user interface related actions. Can be only used after RSU_PLUG_EVENT_UI_INITDONE has been received.

IPlugUI::SetProgress

void SetProgress(unsigned long luDone, unsigned long luTotal);
Purpose:
Sets the value of the patcher progress bar.

Parameters:
  • luDone
    Amount of units completed.
  • luTotal
    Amount of units total.
Return value:
None.

IPlugUI::GetStatus

bool GetStatus(char* lpszBuf, unsigned long luSize);
Purpose:
Retrieves the current status line text.

Parameters:
  • lpszBuf
    Pointer to a buffer, which receives the status line contents.
  • luSize
    Size of the buffer pointed to by lpszBuf.
Return value:
When the value could be successfully copied true, otherwise false.

IPlugUI::SetStatus

void SetStatus(const char* lpszText);
Purpose:
Sets the status line text.

Parameters:
  • lpszText
    Pointer to a zero-terminated buffer, which contains new status line text.
Return value:
None.

IPlugUI::SetTitle

void SetTitle(const char* lpszTitle);
Purpose:
Sets the window title text.

Parameters:
  • lpszTitle
    Pointer to a zero-terminated buffer, which contains new window title text.
Return value:
None.

IPlugUI::GetHandle

void* GetHandle(void);
Purpose:
Retrieves handle to the main window.

Parameters:
None.

Return value:
Main window handle (HWND) on success, otherwise NULL when UI is not yet initialized.

IPlugGRF

Handles GRF archive reading and writing. All in-archive file names are case-insensitive and include the path, with \ being the path separator (e.g. data\wav\sound.wav).

IPlugGRF::Open

void* Open(const char* lpszFileName, bool bReadOnly);
Purpose:
Opens a GRF archive.

Parameters:
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the name of the GRF archive to open.
  • bReadOnly
    If true no modifications to the archive will be allowed, if the archive does not exist, the action will fail. If false and the archive does not exist, an empty archive will be created.
Return value:
Handle to the GRF archive on success, NULL on failure.

IPlugGRF::Commit

bool Commit(void* hGrf);
Purpose:
Applies scheduled changes to the GRF archive.

Parameters:
  • hGrf
    Handle to a writable GRF archive.
Return value:
When the commit succeeded true, otherwise false.

IPlugGRF::Revert

void Revert(void* hGrf);
Purpose:
Undoes all scheduled changes since the last IPlugGRF::Commit or IPlugGRF::Open.

Parameters:
  • hGrf
    Handle to a writable GRF archive.
Return value:
None.

IPlugGRF::Close

void Close(void* hGrf);
Purpose:
Closes a GRF archive handle. Implies IPlugGRF::Revert.

Parameters:
  • hGrf
    Handle to a GRF archive.
Return value:
None.

IPlugGRF::Exists

bool Exists(void* hGrf, const char* lpszFileName);
Purpose:
Checks, whether or not a file exists inside the GRF archive.

Parameters:
  • hGrf
    Handle to a GRF archive.
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the path und file name of the file to check.
Return value:
If the file exists true, otherwise false.

IPlugGRF::Delete

bool Delete(void* hGrf, const char* lpszFileName);
Purpose:
Deletes a file inside the GRF archive.

Parameters:
  • hGrf
    Handle to a writable GRF archive.
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the path und file name of the file to delete.
Return value:
If the file could be deleted true, otherwise false.

IPlugGRF::Rename

bool Rename(void* hGrf, const char* lpszOldName, const char* lpszNewName);
Purpose:
Renames/moves a file inside the GRF archive.

Parameters:
  • hGrf
    Handle to a writable GRF archive.
  • lpszOldName
    Pointer to a zero-terminated buffer, which contains the path und file name of the file to rename/move.
  • lpszNewName
    Pointer to a zero-terminated buffer, which contains the path und file name to rename/move to.
Return value:
If the file could be renamed/moved true, otherwise false.

IPlugGRF::Put

bool Put(void* hGrf, const char* lpszFileName, const unsigned char* lpPtr, unsigned long luSize);
Purpose:
Adds a file into the GRF archive. If such file already exists, it will be overwritten. Keep in mind, that if the GRF archive on-disk size reaches 4 GiB, you will not be able to IPlugGRF::Commit (file-format limitation).

Parameters:
  • hGrf
    Handle to a writable GRF archive.
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the path und file name to save the data under.
  • lpPtr
    Pointer to a buffer, which contains file's data.
  • luSize
    Amount of data pointed to by lpPtr.
Return value:
If the file could be stored true, otherwise false.

IPlugGRF::Get

bool Get(void* hGrf, const char* lpszFileName, unsigned char* lpPtr, unsigned long* luSize);
Purpose:
Retrieves a file from the GRF archive.

Parameters:
  • hGrf
    Handle to a GRF archive.
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the path und file name of the file to retrieve.
  • lpPtr
    Pointer to a buffer, which will receive the file's data. It must be large enough for the entire file, otherwise the function will fail.
  • luSize
    Size of the buffer pointed to by lpPtr.
Return value:
If the file could be retrieved true, otherwise false.

IPlugGRF::Merge

bool Merge(void* hGrf, void* hPatchGrf);
Purpose:
Merges two GRF archives (applying patches).

Parameters:
  • hGrf
    Handle to a writable GRF archive.
  • hPatchGrf
    Handle to a GRF archive.
Return value:
If the patch archive could be merged into the GRF archive true, otherwise false.

IPlugRGZ

Handles RGZ archive extraction.
[v3]This interface has been removed.

IPlugRGZ::Open

void* Open(const char* lpszFileName);
Purpose:
Opens an RGZ archive.

Parameters:
  • lpszFileName
    Pointer to a zero-terminated buffer, which contains the name of the RGZ archive to open.
Return value:
Handle to the RGZ archive on success, NULL on failure.

IPlugRGZ::Extract

bool Extract(void* hRGZ);
Purpose:
Extracts the RGZ archive in patcher's folder.

Parameters:
  • hRGZ
    Handle to an RGZ archive.
Return value:
None.

IPlugRGZ::Close

void Close(void* hRGZ);
Purpose:
Closes an RGZ archive.

Parameters:
  • hRGZ
    Handle to an RGZ archive.
Return value:
None.

IPlugIntl

Handles patcher i18n.

IPlugIntl::GetMsgStr

const char* GetMsgStr(unsigned long luId);
Purpose:
Retrieves an i18n string.

Parameters:
  • luId
    One of the TXT_* (rsu.i18n.h) constants, which identify a i18n string.
Return value:
Associated string on success, otherwise NULL.

IPlugIntl::SetMsgStr

bool SetMsgStr(unsigned long luId, const char* lpszString);
Purpose:
Sets an i18n string. You cannot set protected strings (ids above TXT_LOCALIZE_MAX).

Parameters:
  • luId
    One of the TXT_* (rsu.i18n.h) constants, which identify a i18n string.
  • lpszString
    Pointer to a buffer, which contains a new value for the i18n member. This pointer must be static.
Return value:
If the string could be set true, otherwise false.

IPlugSetting

Handles patcher settings. Only available, when there is a settings file present. For more information, see the Settings Documentation.
[v3]This interface is now always available, regardless of whether a settings file exists or not.

IPlugSetting::Get

bool Get(const char* lpszSection, const char* lpszKey, const char* lpszDefault, char* lpszBuffer, unsigned long luBufferSize);
Purpose:
Retrieves a setting value from settings file.

Parameters:
  • lpszSection
    Pointer to a zero-terminated buffer, which contains the name of the section, which contains the requested key.
  • lpszKey
    Pointer to a zero-terminated buffer, which contains the name of the key, to which the requested value is assigned.
  • lpszDefault
    Pointer to a zero-terminated buffer, which contains a default value, which is lpszBuffer set to, when the value was not found.
  • lpszBuffer
    Pointer to a buffer, which receives the requested value.
  • luBufferSize
    Size of the buffer pointed to by lpszBuffer.
Return value:
When no errors occured true, otherwise false.

Interfaces - Version 2

This version was introduced in 2.0.0.467, on 2010-10-10.

IPlugCommon

Handles plug-in interaction and non-categorized services. Inherits all methods from version 1.

IPlugCommon::GetPatchInfoNum

bool GetPatchInfoNum(unsigned long luType, unsigned long* luNumber);
Purpose:
Retrieves a numeric patch information member value.

Parameters:
  • luType
    One of the RSU_IPATCH_* constants, which identifies the member whose value should be retrieved.
  • luNumber
    Pointer to a variable, which receives the current value of the requested member.
Return value:
Is true, when the value was retrieved, otherwise false.

IPlugCommon::SetPatchInfoNum

bool SetPatchInfoNum(unsigned long luType, unsigned long luNumber);
Purpose:
Sets a numeric patch information member value.

Parameters:
  • luType
    One of the RSU_IPATCH_* constants, which identifies the member whose value should be set.
  • luNumber
    An expression which should become the new value for given member.
Return value:
Is true, when the value was set, otherwise false.

Interfaces - Version 3

This version was introduced in 3.0.0.?, on 2011-06-25.

IPlugCommon

Handles plug-in interaction and non-categorized services. Inherits all methods from version 2.

IPlugCommon::HanRegister

bool HanRegister(const char* lpszExtension, HANHANDLERESULT PLUGDEF(lpHandle)(LPHANHANDLEINFO lpInfo), bool PLUGDEF(lpFinal)(void));
Purpose:
Registers a handler for a specific file type. Allows handling of file types, that are not natively supported by the patcher.

Parameters:
  • lpszExtension
    File extension of the file type to handle. If such file type is already registered, the registration will fail.
  • lpHandle
    Specifies a callback function, that is called when the registered file type is to be handled. Return value indicates whether the function succeeded or not.
  • lpFinal
    Specifies a callback function, that is called when the patch process is about to complete. Return value indicates whether the function succeeded or not. Can be NULL.
Return value:
When no errors occured true, otherwise false.

Version-neutral functions and interfaces

Following functions and interfaces are most-likely not to change, since they ensure version-independence of the plug-in system.

IPlugUnknown

This interface is part of all other interfaces, which means, every interface pointer casted to IPlugUnknown must be able to provide Acquire and Release functions properly.

IPlugUnknown::Acquire

void Acquire(void* lpSelf);
Purpose:
Increases the reference counter. To be used, when the pointer to the interface changes scope (e.g. is passed to another function).

Parameters:
  • lpSelf
    Pointer to the interface, that calls Acquire.
Return value:
None.

IPlugUnknown::Release

void Release(void* lpSelf);
Purpose:
Decreases the reference counter. To be used, when the pointer to the interface no longer required in it's scope.

Parameters:
  • lpSelf
    Pointer to the interface, that calls Release.
Return value:
None.

Plugin Exports

These functions are supposed to be exported by every plug-in DLL. They are required for proper registration, initialization and termination of a plug-in.
bool Plugin_Load(unsigned long luAppVersion, unsigned long* luPlugVersion);
Purpose:
Allows the patcher and the plug-in to do version-checking of each other. Called immediately after a plug-in was loaded. Must not do any initialization.

Parameters:
  • luAppVersion
    Contains the version of the plug-in interface of the patcher.
  • luPlugVersion
    Pointer to a variable, that receives the version of the plug-in interface, the plug-in was designed for, usually RSU_PLUG_VERSION_CURRENT.
Return value:
Return true if the patcher should continue processing this plug-in, otherwise false to unload this plug-in.

Note:
If the patcher rejects the version from the plug-in, it is unloaded without further notification, thus no initialization must be done inside Plugin_Load.
bool Plugin_Init(PlugInterfaceQueryFunc lpInterfaceQuery, PlugInterfaceOnEventFunc* lppOnEvent, void* lpReserved);
Purpose:
Allows the plugin perform all necessary initialization, such as allocating memory or registering own interfaces.

Parameters:
  • lpInterfaceQuery
    Pointer to the Plug_InterfaceQuery function, which allows querying all built-in interfaces.
  • lppOnEvent
    Pointer to a function pointer, which receives the plug-in event handling function. Can be NULL, if the plug-in does not want to receive event notifications.
  • lpReserved
    Reserved for future use.
Return value:
Return true if the patcher should continue processing this plug-in, otherwise false to ignore this plug-in.

void Plugin_Quit(void);
Purpose:
Notifies the plugin, that it is about being unloaded and should release all acquired resources.

Parameters:
None.

Return value:
None.

Events

Events notify the plug-in of things, that the patcher either is about to do, or has done. In some cases the plug-in is able to abort the event, that is about to happen.

RSU_PLUG_EVENT_NULL

No effect. Might be used to test, if the plug-in is responsive. Must not be processed.

RSU_PLUG_EVENT_INIT

Reserved for future use.
  • luData
    Unused.
  • lpData
    Unused.

RSU_PLUG_EVENT_INITDONE

All plug-ins have been initialized. The plug-in may now request interfaces from other plug-ins.
  • luData
    High-order word contains amount of plug-ins loaded, lower-order word contains amount of plug-ins, that made it past initialization.
  • lpData
    Unused.

RSU_PLUG_EVENT_HANDLEOBJECT

The patcher was not able to handle a downloaded file internally, thus the plug-ins are asked, if they can handle it.
[v3]This event is deprecated, use IPlugCommon3::HanRegister instead.
  • luData
    Unused.
  • lpData
    Pointer to a PlugEventHandleObjectInfo structure. The lpszFileName member contains name of the file object in question, member bHandled, if the plugin handled the file or not. Ignore this message, if another plug-in already handled the file (means, never set to false manually).

RSU_PLUG_EVENT_PATCHALLOW

Notification about the result of patch_allow.txt contents. This event is sent even when patch_allow.txt was by-passed.
  • luData
    Is 0 if patch allow is 'deny', otherwise 1.
  • lpData
    Unused.

RSU_PLUG_EVENT_SYSMENUINIT

Patcher system menu is about being initialized.
  • luData
    Unused.
  • lpData
    Handle to the menu (HMENU), which allows the plug-in to add entries on it's own.

RSU_PLUG_EVENT_UI_REGISTER

Patcher window class is about being registered. Allows hooking the window procedure for more control over the window and required for own system menu entries.
  • luData
    Unused.
  • lpData
    Pointer to WNDCLASSEX structure, which is about being passed to RegisterClassEx. If you replace the lpfnWndProc member, make sure, that the plug-in's window procedure calls the old pointer, otherwise the window will not respond to user's actions.

RSU_PLUG_EVENT_UI_INIT

Main window has been created. Allows resizing and moving of the window, before all other controls are created.
  • luData
    Unused.
  • lpData
    Handle to the main window (HWND).

RSU_PLUG_EVENT_UI_BASE

Query for the control position base point, on which all controls will move their position to.
  • luData
    Unused.
  • lpData
    Pointer to a variable (unsigned long), which contains and receives a new base point for all controls. By default 7, which is top of the client area.

RSU_PLUG_EVENT_UI_FONT

Window font is being set. Allows plug-in created controls to apply this font as well, before the window is being displayed.
  • luData
    Unused.
  • lpData
    Handle to current window font (HFONT).

RSU_PLUG_EVENT_UI_INITDONE

The main window has completed initialization and is now visible to the user. IPlugUI interface can be used now.
  • luData
    Unused.
  • lpData
    Unused.

RSU_PLUG_EVENT_UI_DESTROY

The main window and all it's controls are about being destroyed. IPlugUI interface is not available after returning from this event.
  • luData
    Unused.
  • lpData
    Unused.

RSU_PLUG_EVENT_QUERYTASK

Task queue is empty, thus the plug-ins are asked, if they wish to add more tasks before the worker thread quits. During processing of this event, IPlugCommon::PushTask can be used.
  • luData
    Unused.
  • lpData
    Unused.

RSU_PLUG_EVENT_WEBCONNFAULT

[since 1.4.4] File download from HTTP has failed, plug-ins are asked to provide alternative patch information or otherwise handle the failure.
  • luData
    Unused.
  • lpData
    Pointer to a variable (bool), which indicates whether or not to retry the last action. Ignore this message, if another plug-in already handled the failure (means, never set to false manually).

RSU_PLUG_EVENT_FTPCONNFAULT

[since 1.4.4] File download from FTP has failed, plug-ins are asked to provide alternative patch information or otherwise handle the failure.
  • luData
    Unused.
  • lpData
    Pointer to a variable (bool), which indicates whether or not to retry the last action. Ignore this message, if another plug-in already handled the failure (means, never set to false manually).

Plug-in API usage limitations

These guidelines are provided for the most important issues, you may run into, while using the plug-in API. Not following them might cause your plug-in either not to work, or getting banned.

You may…

  • …license your plug-in code with any license you wish.
  • …ommit the plug-in SDK in your distribution, any working version can be downloaded from the website at any time.
  • …extend patcher's functionality in either way you wish.

You may not…

  • …use newer plug-ins with older patchers.
  • …process RSU_PLUG_EVENT_NULL, which means, plug-in's Plug_OnEvent must always return false to this event.
  • …feed intentionally any method or function with junk data, which might cause the patcher to crash.
  • …use this plug-in API in that way, that the patcher serves as framework for new software.
  • …extend patcher's functionality in that way, that would cause harm to it's users, including but not limited to software and hardware damage.
  • …extend patcher's functionality in that way, that it operates outside of the folder, the patcher resides in, except if it requires user's consent.
  • …remove any copyright notice inside the plug-in SDK nor force a different license on it or the patcher itself.

tl;dr: Your plug-ins are supposed to conform this API description, may not be used for evil purposes and are considered unrelated software.


Last built on Thu, 10 Mar 2022 15:35:54 +0100.