PDA

View Full Version : Help w/ N64 Plugins & VB.Net...



Juggz
September 15th, 2006, 02:23
Hello,

I started a new project yesterday as I’ve been sick the past couple of days :yucky: , so I have some free programming time on my hands. :bouncy:

For the fun of it I started to make a frontend for one of my N64 emulators & the 1st thing on my list was to conquer the plugins.

Accessing them is pretty simple with a couple of API’s, pretty much the same as if you were to load a PSX plugin, like so:



<DllImport _
("kernel32.dll", CallingConvention:=CallingConvention.Win api, _
EntryPoint:="LoadLibraryA", CharSet:=CharSet.Ansi)> _
Private Function LoadLibrary(ByVal lpLibFileName As String) As Integer
End Function

<DllImport _
("kernel32.dll", CallingConvention:=CallingConvention.Win api, _
EntryPoint:="GetProcAddress", CharSet:=CharSet.Ansi)> _
Private Function GetProcAddress(ByVal hModule As Integer, ByVal lpProcName As String) As Integer
End Function

<DllImport _
("kernel32.dll", CallingConvention:=CallingConvention.Win api, _
EntryPoint:="FreeLibrary", CharSet:=CharSet.Ansi)> _
Private Function FreeLibrary(ByVal hModule As Integer) As Integer
End Function

<DllImport("user32.dll", CallingConvention:=CallingConvention.Win api, _
EntryPoint:="CallWindowProcA", CharSet:=CharSet.Auto)> _
Private Function CallWindowProc(ByVal lpPrevWndFunc As Integer, _
ByVal hwnd As Integer, ByVal Msg As Integer, ByVal wParam As Integer, _
ByVal lParam As Integer) As Integer
End Function

Public Sub PlugConfig(ByVal PlugPath As String)
Dim hProc, hModule, hResult As Integer
hModule = LoadLibrary(PlugPath)

hProc = GetProcAddress(hModule, About)
If hProc Then
hResult = CallWindowProc(hProc, 0, 0, 0, 0)
End If

hProc = GetProcAddress(hModule, "DllConfig")
FreeLibrary(hModule)
End Sub

Public Sub PlugAbout(ByVal PlugPath As String)
Dim hProc, hModule, hResult As Integer
hModule = LoadLibrary(PlugPath)

hProc = GetProcAddress(hModule, About)

If hProc Then
hResult = CallWindowProc(hProc, 0, 0, 0, 0)
End If

hProc = GetProcAddress(hModule, "DllAbout")
FreeLibrary(hModule)
End Sub


Then on a button or your pref. of control call:



PlugConfig(“C:\YourPath\YourPluggin.dll” )


Or



PlugAbout(“C:\YourPath\YourPluggin.dll”)


However I am wondering how I might go about using “GetDllInfo” to gather all the information about the plugin. So far all my attempts to accomplish this have been unsuccessful, any ideas on accomplishing this in VB .NET?

This is my 1st time tackling an N64 EMU-based project & I am not finding too many technical docs on the subject, any recommendations?

Thanks much! :)

Warcon
September 16th, 2006, 21:13
Here is the code that I use to talk to a plugin (this is converted from C#, so I'm not sure if the converter messed stuff).



Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Text

Namespace CWDev.N64Emulator.Plugins

Public Enum PluginType As Short
RSP = 1
Graphic = 2
Audio = 3
Controller = 4
End Enum

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Friend Structure PluginInfo
Public Version As UInt16
Public Type As PluginType

<MarshalAsAttribute(UnmanagedType.ByValTS tr, SizeConst:=100)> _
Public Name As String

Public NormalMemory As Boolean
Public MemoryBswaped As Boolean
End Structure

Public Class Plugin
Implements IDisposable

Public Sub New(ByVal dllName As String)
m_dllName = dllName
m_dllWrapper = New UnmanagedDllWrapper(dllName)

m_delegateGetDllInfo = CType(GetDelegate("GetDllInfo", GetType(DelegateGetPluginInfo)), DelegateGetPluginInfo)
If m_delegateGetDllInfo Is Nothing Then
Throw New Exception(String.Format("Cannot find function 'GetDllInfo' in '{0}'!", m_dllName))
End If

m_pluginInfo = New PluginInfo()
GetDllInfo(m_pluginInfo)

m_dllAboutDelegate = CType(GetDelegate("DllAbout", GetType(DllAboutDelegate)), DllAboutDelegate)
m_dllConfigDelegate = CType(GetDelegate("DllConfig", GetType(DllConfigDelegate)), DllConfigDelegate)
m_dllTestDelegate = CType(GetDelegate("DllTest", GetType(DllTestDelegate)), DllTestDelegate)
m_closeDLLDelegate = CType(GetDelegate("CloseDLL", GetType(CloseDLLDelegate)), CloseDLLDelegate)

m_romOpenDelegate = CType(GetDelegate("RomOpen", GetType(RomOpenDelegate)), RomOpenDelegate)
m_romClosedDelegate = CType(GetDelegate("RomClosed", GetType(RomClosedDelegate)), RomClosedDelegate)
End Sub

Private m_dllName As String
Private m_dllWrapper As UnmanagedDllWrapper

Public Sub Dispose() Implements IDisposable.Dispose
m_dllWrapper.Dispose()
End Sub

Private Delegate Sub DelegateGetPluginInfo(ByRef pluginInfo As PluginInfo)
Private m_delegateGetDllInfo As DelegateGetPluginInfo
Private Sub GetDllInfo(ByRef pluginInfo As PluginInfo)
m_delegateGetDllInfo(pluginInfo)
End Sub

Private Delegate Sub DllAboutDelegate(ByVal parentWindow As IntPtr)
Private m_dllAboutDelegate As DllAboutDelegate
Friend Sub DllAbout(ByVal parentWindow As IntPtr)
If Not m_dllAboutDelegate Is Nothing Then
m_dllAboutDelegate(parentWindow)
End If
End Sub

Private Delegate Sub DllTestDelegate(ByVal parentWindow As IntPtr)
Private m_dllTestDelegate As DllTestDelegate
Friend Sub DllTest(ByVal parentWindow As IntPtr)
If Not m_dllTestDelegate Is Nothing Then
m_dllTestDelegate(parentWindow)
End If
End Sub

Private Delegate Sub DllConfigDelegate(ByVal parentWindow As IntPtr)
Private m_dllConfigDelegate As DllConfigDelegate
Friend Sub DllConfig(ByVal parentWindow As IntPtr)
If Not m_dllConfigDelegate Is Nothing Then
m_dllConfigDelegate(parentWindow)
End If
End Sub

Private Delegate Sub CloseDLLDelegate()
Private m_closeDLLDelegate As CloseDLLDelegate
Friend Sub CloseDLL()
If Not m_closeDLLDelegate Is Nothing Then
m_closeDLLDelegate()
End If
End Sub

Private Delegate Sub RomOpenDelegate()
Private m_romOpenDelegate As RomOpenDelegate
Friend Sub RomOpen()
If Not m_romOpenDelegate Is Nothing Then
m_romOpenDelegate()
End If
End Sub

Private Delegate Sub RomClosedDelegate()
Private m_romClosedDelegate As RomClosedDelegate
Friend Sub RomClosed()
If Not m_romClosedDelegate Is Nothing Then
m_romClosedDelegate()
End If
End Sub

Private m_pluginInfo As PluginInfo

Public ReadOnly Property Name() As String
Get
Return m_pluginInfo.Name
End Get
End Property

Public ReadOnly Property PluginType() As PluginType
Get
Return m_pluginInfo.Type
End Get
End Property

Public ReadOnly Property Version() As Integer
Get
Return m_pluginInfo.Version
End Get
End Property

Public ReadOnly Property IsNormalMemorySupported() As Boolean
Get
Return m_pluginInfo.NormalMemory
End Get
End Property

Public ReadOnly Property IsBswapedMemorySupported() As Boolean
Get
Return m_pluginInfo.MemoryBswaped
End Get
End Property

Protected Function GetDelegate( _
ByVal functionName As String, _
ByVal delegateType As Type _
) As [Delegate]

Dim pointer As IntPtr = m_dllWrapper.GetProcAddress(functionName )
If pointer = IntPtr.Zero Then
Return Nothing
End If

Return Marshal.GetDelegateForFunctionPointer(po inter, delegateType)
End Function

' the nested private class that allocates and release the unmanaged resource
Private Class UnmanagedDllWrapper
Implements IDisposable

Public Handle As IntPtr

Public Sub New(ByVal dllName As String)
Me.Handle = LoadLibrary(dllName)
If Me.Handle = IntPtr.Zero Then
Throw New Win32Exception()
End If
End Sub

' the Dispose method can be invoked only by the parent class
Public Sub Dispose() Implements System.IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub

' the finalizer
Protected Overrides Sub Finalize()
Dispose(False)
End Sub

' This is where the unmanaged resource is actually disposed of.
' Notice that it takes an argument only for compliance with .NET coding standards
' but the disposing argument is never used, because in all cases this class
' can access and release only the single unmanaged resource it wraps.
Private Sub Dispose(ByVal disposing As Boolean)
' exit now if this object didn't completed its constructor correctly
If Me.Handle = IntPtr.Zero Then
Return
End If

' release the unmanaged resource
FreeLibrary(Me.Handle)

' finally, invalidate the handle
Me.Handle = IntPtr.Zero
End Sub

Public Function GetProcAddress(ByVal procName As String) As IntPtr
Return GetProcAddress(Me.Handle, procName)
End Function

<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function LoadLibrary(ByVal dllName As String) As IntPtr
End Function

<DllImport("kernel32.dll")> _
Private Shared Function GetProcAddress(ByVal dllHandle As IntPtr, ByVal procName As String) As IntPtr
End Function

<DllImport("kernel32.dll")> _
Private Shared Function FreeLibrary(ByVal dllHandle As IntPtr) As Integer
End Function

End Class

End Class

End Namespace


To use the class, you can do something like this:



Using plugin As New Plugin("C:\YourPath\YourPluggin.dll")
plugin.DllAbout(myform.Handle)

Dim pluginType As String = plugin.PluginType
Dim pluginName As String = plugin.Name
...

End Using ' End Using automaticly call the Dispose method, which release the handle on the loaded dll


You should know that some plugin cannot be loaded in .Net. By example, most of the Jabo plugin throw an "Invalid access to memory location" exception on LoadLibrary. My guess is that those plugin are doing stuff in their "DllMain" function that doesn't work with the .Net runtime.

Hope this help.