What is required to compile a plugin / FWrite/FRead Question

Started by Scavenger, Mon 24/08/2015 18:50:36

Previous topic - Next topic

Scavenger

Hey, I'm trying to write a short engine plugin for my game, but I've long since switched computers and lost all of my Visual Studio stuff. I know a bit of C++ so the coding itself isn't an issue, but setting up the project is. I've plum forgotten how to set it up. Compiling was always a weak point for me. I've tried a few versions of VS, but none of them seem to have the DLL Project set up I remember?

Could someone tell me which version of VS I need and the settings I need to use, or link me to a VS project version of the engine plugin sample code? I can work it out from there, but I have no idea where to begin. The only projects I can find for AGS plugins are the editor ones. :(

Wyz

From the top of my head:
  • Set compiler flag -DTHIS_IS_THE_PLUGIN=1
  • Set the project to produce a dynamic linked library (linker flag /LD). When you use the project wizard to create a DLL project this is already set.
  • Persoanlly I would link all libraries I use statically; might not always be possible due to licensing.
Life is like an adventure without the pixel hunts.

Scavenger

Alright, I've managed to compile it! Thanks! The rest should be just fine.

Monsieur OUXX

But... Wasn't there a demo plugin for download, ready to be compiled, coming along a nice .sln file? I think there was. And on the download page, some instructions regarding the proper VS to use, etc.
 

Scavenger

That was for the editor plugin, AFAIK. I couldn't find one for the engine plugin. It doesn't matter, though, I've already done it.

I'm currently trying to render a translucent sprite using the same method as I use in my module, but hopefully this is faster. I've coded out something that will write a 320x200 sprite to the screen, but as soon as it tries to run AGS throws up an illegal exception. The plugin runs when this code isn't running, so it's not anything outside of this:

Quote
---------------------------
Illegal exception
---------------------------
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x10001202 ; program pointer is +5, ACI version 3.21.1115, gtags (920,320)

And the code I was using is:

Code: ags


int LoadCLUT (int slot) 
{
	clutslot = slot;
	return 0;
}
//This is run in the Room After Fade in manually, to point the plugin towards a 256*2048 CLUT I made earlier. 

int AGS_EngineOnEvent (int event, int data) {
  if (event == AGSE_POSTSCREENDRAW) {
    if (clutslot > 0)
	{
		// Get a reference to the screen we'll draw onto
		BITMAP *virtsc = engine->GetVirtualScreen();
		BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
		BITMAP *rain = engine->GetSpriteGraphic (920);
		unsigned char **charbuffer = engine->GetRawBitmapSurface (virtsc);
		unsigned char **clutarray = engine->GetRawBitmapSurface (clutspr);
		unsigned char **rainarray = engine->GetRawBitmapSurface (rain);
		int x = 0;
		int y = 0;
		int transamount = 256 * 4;
		while (y < 200)
		{
			while (x < 320)
			{
				charbuffer[x][y] = clutarray [charbuffer[x][y]][rainarray [x][y]+transamount];	//This compares the screen's colour and the sprite's colour, and adds an offset
                                                                                                                //so we're clearly in the 50% transparency zone. I'll add 0 index checking later.
				x++;
			}
			x=0;
			y++;
		}

		// Release the screen so that the engine can continue
		engine->ReleaseBitmapSurface (virtsc);
		engine->ReleaseBitmapSurface (clutspr);
		engine->ReleaseBitmapSurface (rain);
	}
	}
  return 0;
}


I'm not exactly sure what's going on, as it should work, unless this is way out of my league C++ wise.

Crimson Wizard

Well, in general case it would make sense to test the object pointers you get from somewhere else, like engine in this case, to assert object was successfully retrieved.
Like:
Code: cpp

BITMAP *virtsc = engine->GetVirtualScreen();
BITMAP *clutspr = engine->GetSpriteGraphic (clutslot);
BITMAP *rain = engine->GetSpriteGraphic (920);
if (!virtsc || !clutspr || !rain)
{
    // possibly output some debug string here
    return 0;
}



I can also point out that you are possibly using array indexes incorrectly.
The raw bitmap data has row (line) index first and column index second.
So it should be like
Code: cpp

charbuffer[y][x]

instead.

Scavenger

Oh my god, I didn't think it would be that simple, I'm so used to things going x-y and not y-x.

It. Works.



Thank you so much! Now I can make all the neat effects I could possibly want!! A full screen translucent overlay with no overhead and no green tinge like I had last time! I'm going to use the hell out of this thing!

Monsieur OUXX

 

Scavenger

Okay, one last question and my plugin will be fully complete.

I have the following struct and variable I need to save in AGSE_SAVEGAME and restore otherwise my plugin will not carry over effects when I restore the game.

Code: ags
struct transoverlaytype {
	int sprite;
	int x;
	int y;
	int trans;
	int level;
	bool enabled;
} overlay[10];

int clutslot;


How would I write and read this data with FWrite/FRead? Can I directly type in engine->FWrite(*overlay,??,data), or do I need to format it somehow? I'm a little lost at this point.

Crimson Wizard

Quote from: Scavenger on Wed 02/09/2015 18:20:40
How would I write and read this data with FWrite/FRead? Can I directly type in engine->FWrite(*overlay,??,data), or do I need to format it somehow? I'm a little lost at this point.
You could do it like that, and that would work for starters, but I won't recommend this; AGS saved structs like that and it was a headache to make it load this data back on different platforms (non-Windows, non-32 bit).
In brief, the problem is that on different systems (even with different compilers) the struct may be positioned in memory differently (this is known as data padding). Your case may be simple, because you have mostly ints in your struct, nevertheless, writing struct in whole may lead to bad habits in future.

I would suggest to read/write one variable at a time.
E.g.
Code: cpp

for (int i = 0; i < 10; ++i)
{
    engine->FWrite(overlay[i].sprite, sizeof(int), data);
    engine->FWrite(overlay[i].x, sizeof(int), data);
    engine->FWrite(overlay[i].y, sizeof(int), data);
    <...>
}

Scavenger

Alright, I managed to do this:

Code: C++
	if (event == AGSE_SAVEGAME)
	{
		for (int i = 0; i < 10; ++i)
			{
				engine->FWrite(&overlay[i].sprite, sizeof(int), data);
				engine->FWrite(&overlay[i].x, sizeof(int), data);
				engine->FWrite(&overlay[i].y, sizeof(int), data);
				engine->FWrite(&overlay[i].level, sizeof(int), data);
				engine->FWrite(&overlay[i].trans, sizeof(int), data);
				engine->FWrite(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FWrite(&clutslot, sizeof(int), data);
	}
	if (event == AGSE_RESTOREGAME)
	{
		for (int i = 0; i < 10; ++i)
			{
				engine->FRead(&overlay[i].sprite, sizeof(int), data);
				engine->FRead(&overlay[i].x, sizeof(int), data);
				engine->FRead(&overlay[i].y, sizeof(int), data);
				engine->FRead(&overlay[i].level, sizeof(int), data);
				engine->FRead(&overlay[i].trans, sizeof(int), data);
				engine->FRead(&overlay[i].enabled, sizeof(bool), data);
			}
		engine->FRead(&clutslot, sizeof(int), data);
	}


And it seems to be working! It just needed that little & sign I've seen before where things wouldn't take anything but pointers. Hopefully that'll be all for this plugin!

Monsieur OUXX

Do you think your could open-source your plugin, so that people can see how to make one? (the "save/restore" aspect of it is very interesting)
 

SMF spam blocked by CleanTalk