Holy crud! It works! I followed the instructions at the link you posted and came up with this:
Quote:
Imports System.Runtime.InteropServices
Imports RGiesecke.DllExport
Public Module fmsel
Public Enum eFMSelReturn
kSelFMRet_OK = 0 ' run selected FM 'data->sName' (0-len string to run without an FM)
kSelFMRet_Cancel = -1 ' cancel FM selection And start game As-Is (no FM Or If defined In cam_mod.ini use that)
kSelFMRet_ExitGame = 1 ' abort And quit game
End Enum
<StructLayout(LayoutKind.Sequential, Pack:=4)>
Public Structure sFMSelectorData
' sizeof(sFMSelectorData)
Dim nStructSize As Integer
' game version string as returned by AppName() (ie. in the form "Thief 2 Final 1.19")
<MarshalAs(UnmanagedType.LPStr)>
Dim sGameVersion As String
' supplied initial FM root path (the FM Selector may change this)
<MarshalAs(UnmanagedType.LPStr)>
Dim sRootPath As String
Dim nMaxRootLen As Integer
' buffer to copy the selected FM name
<MarshalAs(UnmanagedType.LPStr)>
Dim sName As String
Dim nMaxNameLen As Integer
' set to non-zero when selector Is invoked after game exit (if requested during game start)
Dim bExitedGame As Integer
' FM selector should set this to non-zero if it wants to be invoked after game exits (only done for FMs)
Dim bRunAfterGame As Integer
' optional list of paths to exclude from mod_path/uber_mod_path in + separated format And Like the config
' vars, Or if "*" all Mod paths are excluded (leave buffer empty for no excludes)
' the specified exclude paths work as if they had a "*\" wildcard prefix
<MarshalAs(UnmanagedType.LPStr)>
Dim sModExcludePaths As String
Dim nMaxModExcludeLen As Integer
End Structure
<DllExport(CallingConvention:=CallingConvention.Cdecl, ExportName:="SelectFM")>
Public Function SelectFM(<MarshalAs(UnmanagedType.Struct)> ByRef data As sFMSelectorData) As Int32
MsgBox("nStructSize: " & data.nStructSize & vbCrLf &
"sGameVersion: " & data.sGameVersion & vbCrLf &
"sRootPath: " & data.sRootPath & vbCrLf &
"nMaxRootLen: " & data.nMaxRootLen & vbCrLf &
"sName: " & data.sName & vbCrLf &
"nMaxNameLen: " & data.nMaxNameLen & vbCrLf &
"dataSize: " & data.GetType.ToString
)
Select Case MsgBox("Start the game?", MsgBoxStyle.Question Or MsgBoxStyle.YesNo)
Case MsgBoxResult.Yes : Return eFMSelReturn.kSelFMRet_Cancel
Case MsgBoxResult.No : Return eFMSelReturn.kSelFMRet_ExitGame
End Select
Return eFMSelReturn.kSelFMRet_Cancel
End Function
End Module
I copied the compiled dll into the thief gold directory and started the game. The MessageBox popped up and if I click the Yes button in the MessageBox, it starts the game. If I click No, it does not start the game...
I'm sure i'll probably have to Marshal those string variables to make it work completely, but this is a good start. [EDIT]: I changed the code above to what ultimately worked. I now have a boilerplate to build something using the FMSEL API.
So you can use .NET to write a fmsel.dll. Thanks for that link!
[EDIT]: Feel free to take the code and use it. Just remember to use NuGet to install the Unmanaged Exports package to your project.
The one thing that i'm disappointed with is that the sGameVersion variable always says "Thief 2 Final 1.21", even if it's Thief Gold that's running. I was hoping to use that to determine which game i'm running in.
[EDIT]: I just verified it worked in SS2, T1, T2, and T3. For T1 & T2, it reports as "Thief 2 Final 1.21". For SS2, it reports as "System Shock 2 Patch Final 2.42". And for T3, it reports as "Thief 3 1.1.5.2"