Jump to content

All my products and services are free. All my costs are met by donations I receive from my users. If you enjoy using any of my products, please donate to support me. My bare hosting costs are currently not met so please consider donating by either clicking this text or the Patreon link on the right.

Patreon

Recommended Posts

Posted

Thought I'd try and make it easier for would-be coders to "jump in" and get coding! It's not anything special, but if anyone needs it, here's a snap-in template for GameEx plugin creation. This ZIP file includes everything you need to get started, including:

  • GameEx Plugin class, which is fully documented/updated for your coding pleasure. :)
  • A log writing class (which is a modified version of Ben Baker's logging class... Thanks Ben!)
  • An INI reading/writing class (which is a modified version of Ludvik Jerabek's INI class)
  • A blank configuration form

To use it, all you need to do is put the uncompressed ZIP file in your Visual Studio 2010 Templates/Project Templates folder, start a new project, and select it from the list. All the settings have been set already (Strict:On, Target:x86, Framework:2.0).

So... Get coding!!!!!

Download it here.

  • Like 2
Posted

Yeah, I have one every once in a while. ;)

Would really love to see more plugins... It's a neat system and completely underused.

Posted

Adultery -

I think the zip archive may be corrupted in some capacity. I tried re-downloading the file, but the results stay consistent. I'll also try it out on a separate machine when I get home.

7-Zip spits out this:

1 Unsupported compression method for 'Code'

2 Unsupported compression method for 'Forms'

Whereas Winzip gives a bit more information:

Warning: skip[ping "Forms\". The 32-bit CRC stored in the local header for this file is not the same as the 32-bit CRC stored in the central header.

WinZip Help Text:

Mismatch in Local and Central Header Information

WinZip® cannot process one of the files within your Zip file because there is an inconsistency between the local and central header information for the file.

Information about each of the compressed files stored in a Zip file is kept in two places within the Zip file. A local header is stored near the compressed data of each file, and a central header is stored at the end of the Zip file. These headers contain information about the file such as its size, compression method, and CRC.

In a valid Zip file, the information in the local and central headers for each file should be the same. Mismatched information is a sign that some data within the Zip file has been damaged.

Posted

@Null: Hmmm, I just tried DLing/unzipping it 3 times and it worked fine. :) You don't need to unzip it by the way... But I think your download got corrupted somehow.

@uman: No it's not, but the plugin system supports both VB.NET and C#. I dev in vb.net so that's why I supplied the template. :)

  • 1 year later...
  • 2 years later...
Posted

OK - so I'm now resurrecting 2 year old topics :)

Thanks for this Adultery. Having made a start with Visual Basic, I'm now trying to understand/develop plugins for GameEx. However, I'm falling miserably at the first hurdle, and think I'm missing some of the basic concepts involved.

All VS devs to date have been either form or console apps, so get how things work(ish) from that point of view. Downloaded your plugin template from here:

http://www.gameex.info/forums/files/file/38-gameex-plugin-snap-in-template/

Got template up and running fine. However, I'm not sure how to dev a plugin beyond that! It's me being thick probably. A few Q's:

- So, I'm guessing that when a plugin runs, you can catch any Events in GameEx by the looks of your GameEx.plugin file (although how does it do this as there are no handles...)?

- How do you reference the GameEx variables? Normally you'd just do class.variable, but how do this with plugins?

- Where do you actually write you code? gameex.plugin or do you make a new vb.net code document

I'm aware I'm sounding really thick - but all a new concept to me. Any pointers/idiot's guides/guided reading would be appreciated!

:)

Posted

The man himself will be able to field your question leagues better than I can, but I just figured I'd chime in briefly. Have you checked out the documentation available in the wiki? This page is probably the best place to start. Among other things it describes what methods and information can be hooked through the plugin system (check the bottom of the page ... although I think there are also a few more at this point?). I think that Adultery's Function Logger Plugin can also be immensely helpful while sandboxing your ideas.

So yeah ... Adultery will be able to fill in more details on all of this, but if you haven't checked out the resources above it might be a good place to start fooling around.

Posted

Thanks null + yeah - had a good look through the wiki. It's making the conceptual leap I'm struggling with, though.. I understand(ish) the concepts behind variables/classes and events, but just can't grasp how you apply this to plugin development. Hard to explain, but need a bit of an A, B, C to get me started. If can get some kinda dev setup started where GE and a Dev'd Plugin are interacting, I should be able to take it from there.

Yeah - using Function logger too - really handy to see what variables are available at what stage and also what events are triggered when...

In short, I just need a bit of a 'leg-up' hopefully!

Thanks for the response.

Posted

Hey stigzler! So I just spent 25 minutes writing a response to this post and accidentally navigated away from the page and lost it. So this will be more of the abridged version. :)

You should probably know first off that I do a lot of things through my own code base that the PlugIn system doesn't do on it's own. I'm going to look to your utilization of QuickLaunch for my example so that you'll know straght out what you're getting into:

  • Any emulator data you use is my own code (ie additional artwork paths, MAME marquees, databases, etc)
    What I do in code is load all the emulators at the plugin startup in a DataSet and load the needed table when the emulator number changes. Then I hold that data in another class for future use, or until the emulator number changes.
  • All configuration forms that populate emu names, numbers, file paths/file names, etc
    ComboBoxes and include/exclude lists, INI paths, ROM filters, EXE paths, etc are all built and retained throughout the configurations by me in a class. GameEx will not give you this data on its own.
  • Extended ROM variables
    As is the case with emulator data, I will typically parse the emulator table and set my own variables for many of GameEx's game paths, like the custom artwork paths, MAME icons, MAME marquees, cabinet/cartridge/disc art, etc. If you don't see a variable for it in GameEx's enum within the plugin, you need to write code for it.

It might seem like a lot of work, but I link my classes that I use often so that I can update them for one plugin and the change will apply for all of them. I learned early it's much easier to build a repo to pull from instead of trying to maintain the code in 10 different places. After all, many plugins will use the same functions and subs over and over again.

So enough babbling, let me answer these questions:

So, I'm guessing that when a plugin runs, you can catch any Events in GameEx by the looks of your GameEx.plugin file (although how does it do this as there are no handles...)?


I think you're confusing console apps with dll libraries. The DLL will process code when GameEx tells it to, there really isn't a 'handle' per se. So try to think of events as if they were handles: When a game is run, GameEx passes through the Event_GameRun function in the same way you might attach a function to a FormClosing handle that will trigger when the form closes.

You would then run your code based on what GameEx is doing in the appropriate sub/function.

So for example:

  • User selects an emulator and the game list comes up (Event_EmuSelect is called)
    • This is where I will run a sub that grabs the emulator table from the DataSet and holds the variables for later use
    • In GameInfo I will also grab the emulator icon and show it on the secondary monitor
  • User selects a game in the list and presses the button to view the game info screen (Event_GameShowInfo is called)
    • This is where I get the variables for the game from the IntPtr and store them in another class. You can use GameEx's enum obviously, but I prefer to grab this info and hold it myself.
    • This is also where the GameInfo.Description contains the Game Bio from the database.
  • User presses the button to launch the game (Event_GameRun function is called)
    • Here I will verify that the data is the same in the external class I hold Game Info variables
    • This is also where GameInfo.Description contains the ROM File with extension (RomName.iso or whatever)
    • This would also be where you would execute a LaunchBefore command
  • The command line is built and the emulator is launched (Event_CommandLine is called)
    • This is where I will do command line manipulation
    • For example, Virtual Drive Loader will look for the [DTools] flag, run the code to mount the ISO, remove the variable via RegEx and return the command line to GameEx
    • This would also be where you would execute an AlsoLaunch command
  • User plays for a while and exits the game (Event_GameExit is called)
    • This is where I will do any post-processing
    • For example, if Virtual Drive Loader has an ISO mounted, I will run the un-mount command here
    • This would also be where you would execute a LaunchAfter command

You get the idea. :)

How do you reference the GameEx variables? Normally you'd just do class.variable, but how do this with plugins?

As I stated above, I will take the raw DirectCast of the IntPtr data and store it in my own class. There are examples in the wiki that nullPointer linked to above that outline how to keep that data inside the GameEx.PlugIn code, I just don't do it this way because I prefer to do as little as possible in that code section.

So for example, I will pass the IntPtr to my own class:

Public Function Event_CommandLine(ByVal InfoPtr As IntPtr) As String
Dim GameEx_Info as New DracLabs.GameEx_Game()
Dim Plugin_Work as New DracLabs.VDLoader()

GameEx_Info.SetCmdLine(InfoPtr)
Return Plugin_Work.CommandLine()
End Function

Obviously in this case I take the Command Line from my own structure I have set up elsewhere since I know where to get that info and I wouldn't need to pass it in. In this case, that function will take the command line, strip the variables from it, and return it to GameEx.

My own SetCmdLine() sub will also look for and replace any GameEx variables that are there (for example, ssf.exe "[RomPath]\[RomFile]" will automatically replace my internally stored command line with the standard GameEx variable data and pass it back without the substitution since GameEx will do that itself later. So I will hold ssf.exe "C:\Games\CoolRom.iso" but return ssf.exe "[RomPath]\[RomFile]" just like I found it.

Simple right? :)

Where do you actually write you code? gameex.plugin or do you make a new vb.net code document


Well that kind of depends on you. :)

As I mentioned I will write as little code as possible in the GameEx.PlugIn section. I would rather keep my code in my own structure. But that's me. You can really kind of do whatever you feel comfortable with.

Most of my projects are organized within their own sets. So my PlugIn initialization work might be in one folder, my display forms in another folder, my configuration forms in still another folder... I like manageable code so I feel like everything should be under 50 lines or it needs to go into another block. For example, my PlugIn Init block will get called from GameEx.PlugIn and then that function will be ~38 lines and call some additional subs/functions for things like initializing the XML, validate user accounts, start the logger, etc.

GameEx.PlugIn > DracLabs.PlugIn.Initialize >> DracLabs.XML.Load(XML_Path) >> DracLabs.Logger.Init(PlugInName, PlugInVersion) >> DracLabs.GameEx.UserVerify(UserName, PassWd) >> etc.

I don't mind the questions, please feel free to ask. Some things are better explained through trial and error, but I will still try and help where I can. Just be advised it's a lot more work than it looks like, depending of course on what you want to do. :)

There is a Source Code archive in the GameEx > PlugIns folder that Tom includes with the code for the Play Arcade Sound plugin, but that's pretty basic and might not be as helpful as you're looking for. This is really gonna require more of a knowledge of how DLLs work and best practices for well organized code. Unfortunately most everything I write is heavily personalized so I don't really have any SC that I would be able to share. I really should write something to give out that has some code examples in it or finish the wiki one of these days... But, ya know, work and real life. :)

  • Like 1
Posted

Wow, thanks for the full answer, Adultery!! Lots of stuff there for me to get my head around! I've had a day of NVidia drivers screwing up my cab and 5 minute post-boot delays, so head's frazzled and bad day for success today! I'll revisit it when my head's a bit clearer.

I do appreciate the support - especially by the Don of Plugins :)

I'm looking to start simple. A plugin that detects game select change (i.e. when cycling through mame/emu list), and looks in a specified folder (for that system) for a game either mathcing the rom name or some kind of image/selected_game match. It then displays this image, stretched to size on a chosen monitor.

It's basically to display marquee files whilst cycling through games...

How do I set up Visual Studio and GameEx to work together for dev? I tried running the Plugin template, but get some error about how it needs an .exe to run from or something.

Actually, maybe all this plugin stuff is a bit beyond my skills.... :(

Posted

The short answer is to build the DLL and then copy it to the GameEx > Plugins folder and enable it in the plugin repository. Then run the GameEx EXE manually. There are other ways but it's complicated and you can't set external EXEs if you use Express.

What I do is set up a dev GameEx installation on the server and set the debug build path to that installation's GameEx > Plugins folder. Then I make sure it's enabled and run the EXE after I build it. This way I can use different locations to dev (I bounce between a laptop and a PC a lot) and you don't need to install GameEx everywhere. On top of that, my cab always only uses stable builds.

  • Like 1
Posted

Damn - think I'm gonna be a pain on this one....again....sorry!

So managed to get the .dll being built to the GameEx>Plugins folder. It sits there with no build errors!

However - stuck at "enable it in the plugin repository" - I've looked through both the Plugin Manager and Repository Manger (after running GameEx in case inclusion is dependant on this) - but it is nowhere to be seen :(

Using the Plugin Template. All I've changed is Settings>Application>Assembly Information and in the main script:

Namespace GameEx    ''' <summary>    ''' Internal program info for your plugin.    ''' </summary>    Public Structure PluginInfo        Public Const Name As String = "Marquee Masher"        Public Const Version As String = "1.0.0"        Public Const Author As String = "Stigzler"        Public Const Description As String = "Marquee display plugin"        Public Const PluginType As Plugin_Type = Plugin_Type.Emulator        Public Const PluginVersion As String = "1.40"    End Structure

Also had a quick look in Setup Wizard. How do I get GE seeing the plugin?

Posted

Did you check the wiki? There are specific requirements.

http://www.gameex.info/wiki/index.php/Category%3APlugIn_Development#PlugIn_Development_Overview

Also, are you using VS Express? You can also send me your code add I can look at it, I'm sure it's a setting in the compiler you missed.

Posted

Yeah - if it's this bit you mean:

PLEASE NOTE: The plugin system requires all DLLs be compiled for an x86 target environment and built on .NET Framework 2.0 to function properly!

....then had checked that - your template was already setup for these requirements. You also mention " (Strict:On, Target:x86, Framework:2.0)." in the OP - I also tried it with strict on - still no joy :(

Yeah using VS Express....

Some settings:

post-14176-0-73821400-1445801544_thumb.ppost-14176-0-95195400-1445801548_thumb.ppost-14176-0-88434700-1445801552_thumb.p

Do you want me to zip up the whole VS project when you say send the code? I really haven't done much to it - just changed those few details mentioned above, although appreciate may be quicker than guesswork!

Thanks as ever..

Posted

OK - Trial + Error and a stroke of luck - looked into the Random Arcade Sound PLugin and noticed a few tiny differences in the Compile tab. Here's the working settings for anyone else who hits this at the start:

post-14176-0-48374700-1445803735_thumb.p

Right.. now - Let the tinkering begin :)

  • Like 2
Posted

...and so it begins. Good luck in there! :)

Posted

Heh - yeah - got excited for about 10 minutes when I could see Game, Emu + Filenames changing 'on the fly'... :)

Then the reality set in... I see what you were saying about the coding needed to elicit all the other info like Marquee paths etc.

Feeling a bit out my depth. All my vb.net so far has been form applications (with the amateur friendly design view assists....Read: datatables).... Now for something as simple as a single, 4 field datatable , I'm stumped and it feels like all of a sudden having to do things properly (of which, I have no idea how to do! gulp....). I now need to understand namespaces, classes etc etc etc properly... hmmm... maybe back to it another day.

Thanks for the help.

Posted

I'm happy to answer any questions you have... Your first plugin is always the toughest. I got your back. :)

So where are ya stumped? Creating the table or reading the data from it?

Smart code is efficient code. If you start using best practices and do a little research first, you'll thank yourself when it's time to add new features.

Game Info is a good example... It started as iMagic and that was OK, but inefficient and super sloppy. Then I rebuilt it entirely and Game Info was born. Then three years later, I completely overhauled the code again. Now it's in a place where I know exactly what each class does or where exactly a bug that comes up might be living.

You'll miss the mark here and there the first few times, it's part of learning. Start with an easy project as a test. Then add some stuff to it. Then apply what you've learned in the project you really want to do. If you're anything like me, you'll learn best by doing it as opposed to reading about it. :)

  • Like 1
Posted

This all sounds very familiar. However, I really do need to do some theory, I think. tbh, I'm still in a procedural programming mode (my formative coding being the BBC Micro and the C64 basic :) - with a 20 year gap between then and now!) - most of my scripts are very long. I'm struggling to conceptualise when/how you'd use classes as opposed to datasets/subroutines/functions and errrmmm.... Gotos :D (although I have managed to drop those after a year from Batch :) ). Nevermind events, overloads and all the other next-level stuff!

I think I might go old school and buy a book. I just get distracted when reading online.

As I've been coding the few recent apps (CPWizBiz, ControllerRemapGUI, WhoseBox) - I've been thinking - "I know I'm going to want to use this bit of code again at some point..but I know I'm not going to remember where it is in all this code!" I'm guessing that;s where classes come in - know I managed to write some stand alone classes which are essentially a function - but then I get in a mess cross referencing variables in each class (e.g. form1.var1 from form2 and then from2.var1 from from1 etc - all gets messy!)

Hat off to you Adultery for your coding skills - don't think my head could handle your level - it'd pop. :)

Posted

With all due respect, it's my job and I do it every day. Although it's a bit different being a PHP developer professionally, the same general theories still apply. It's only the syntax that changes. :)

I do some variable cross referencing too, it's a part of the game. But a good compiler will let you know if a reference is missing, and when you keep it well organized it's no big deal really. :)

It's gonna be a lot like your apps started, but you'll get the hang of it. I promise!

Think of it this way:

A namespace is like a cabinet. The class is like the drawer in that cabinet. A function/subroutine is like a folder in that drawer. If you organize things from the get go, you know exactly where to look for what you need.

Just bear with it, it's worth it!

  • Like 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...