Jump to content
SubSpace Forum Network

Recommended Posts

Posted
SDL_image and SDL_net are separate from SDL itself. You can download those from here. To set up SDL just follow steps 1 to 4 from this guide (for SDL_Image and SDL_net it's the same thing; basically just copy over the necessary header files and library/dll files). You'll also need the zlib library if you don't have that already; the process for setting it up is essentially the same thing (i.e. put the library files in the /lib/, and the header files in the /include/ folder).
  • Replies 97
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

Posted

you're right that it keeps them packed. However, if you create a folder inside the zone folder with the name of an arena, and put graphics inside, it will override the lvz graphics/images for that arena. I think the order continuum checks is:

 

1. arena folder (zoneName/arenaname/graphic.png)

2. (?)zone folder (zoneName/graphic.png)

3. lvz file graphic

4. default graphic (graphics/graphic.png)

 

Maybe it would be good to keep them internal for discretion too, although that would require substantial rework so maybe just unzipping will suffice for now.

 

Some projects have this:

#include "SDL.h"

#include "SDL_thread.h"

 

While others have the SDL/ folder in front... shouldn't they all have the SDL/ ?

Well, you can either unzip them into both directories, which I agree is bad, or change them all to have the SDL folder.

 

SDL_net and SDL_image are cross platform libraries in the spirit of SDL. Check out http://www.libsdl.org/libraries.php for a complete list of libraries and their development packs.

Posted
cause the block is read as one byte block of a definite size, uncompressed, and only then I know it's a bunch of object definitions. So I just scroll through the byte buffer.
Can you paste the code?
Posted
cause the block is read as one byte block of a definite size, uncompressed, and only then I know it's a bunch of object definitions. So I just scroll through the byte buffer.
Can you paste the code?

 

Relevant part:

 

 

if (sectionheader.compressedSize > 0 &&
sectionheader.decompressedSize > 0)
{
u8 decompressedData[sectionheader.decompressedSize];
u8 compressedData[sectionheader.compressedSize];

//Read compressed data
if (fread(compressedData, sectionheader.compressedSize, sizeof(u8), fileh))
{
	int decompressedSize = sectionheader.decompressedSize;

	//Decompress the data
	util->zlibDecompress(
			compressedData,
			sectionheader.compressedSize,
			decompressedData,
			&decompressedSize);

	if (sectionheader.decompressedSize != (unsigned)decompressedSize)
	{
		//expected size doesn't match... ?
	}

	if (sectionheader.fileTime == 0 && slen == 0)
	{
		//This section contains object definitions
		LvzObjectSectionHeader objHeader;
		LvzObjectSectionType   objSectionType = LVZ_UnsupportedFormat;

		//Data pointer to scroll through the definitions section
		u8* dataPtr = decompressedData;

		memcpy(&objHeader, dataPtr, sizeof(objHeader));
		dataPtr += sizeof(objHeader);

		printf("Object definition section: %u objects, %u images\n", objHeader.objectCount, objHeader.imageCount);

		//Determine which format is used
		if (!strcmp_nonnull(objHeader.uncompressedSectionType, 4, "CLV1"))
			objSectionType = LVZ_CLV1;
		else if (!strcmp_nonnull(objHeader.uncompressedSectionType, 4, "CLV2"))
			objSectionType = LVZ_CLV2;


		printf("sizeof(lvzobj)=%i sizeof(imgdef)=%i", sizeof(LvzObjectDefinition), sizeof(LvzImageDefinition));

		//Read each object, one at a time
		for (ii = 0; ii < objHeader.objectCount; ii++)
		{
			addObjectDefinition(currentLvzFile, (LvzObjectDefinition*)dataPtr, objSectionType);
			dataPtr += sizeof(LvzObjectDefinition);
		}

		//Read each image definition, one at a time
		for (ii = 0; ii < objHeader.imageCount; ii++)
		{
			//Grab the image filename, located after the fixed-size header
			strcpy(currentImageFileName, (char*)dataPtr+sizeof(LvzImageDefinition));

			//Add the definition, with the fixed size header located at the pointer
			addImageDefinition(currentLvzFile, (LvzImageDefinition*)dataPtr, currentImageFileName, objSectionType);

			//Advance the data pointer
			dataPtr += sizeof(LvzImageDefinition);
			dataPtr += strlen(currentImageFileName)+1;
		}
	}
	else
	{
		printf("File section '%s'\n", currentLvzFileName);

		//This section contains a file
		addFile(currentLvzFile, currentLvzFileName, decompressedData, decompressedSize);
	}
}
else
	printf("Could not read compressed data\n");
}
else
printf("Section size = 0\n");

 

 

 

Entire loadLvzFromFile function:

 

 

BOOL loadLvzFromFile(const char * filename)
{

unsigned int i, ii;
LvzFileHeader lvzheader;
LvzSectionHeader sectionheader;

LvzFile* currentLvzFile;
char 	 currentLvzFileName[_MAX_FNAME];
char 	 currentImageFileName[_MAX_FNAME];

BOOL success = FALSE;
FILE * fileh = NULL;

printf("Opening LVZ file '%s'\n", filename);

if (util->isLegalFilename(filename))
{
	fileh = fopen(filename, "rb");

	if (fileh)
	{
		//File opened

		if (fread(&lvzheader, sizeof(lvzheader), 1, fileh) == 1)
		{
			//Lvz header read

			//Header must contain 'CONT'
			if (!strcmp_nonnull(lvzheader.fileType, 4, "CONT"))
			{
				//We have a valid LVZ file
				currentLvzFile = addLvzFile(filename);

				printf("%i sections in LVZ\n", lvzheader.sectionsCount);

				for (i = 0; i < lvzheader.sectionsCount; i++)
				{
					if (fread(&sectionheader, sizeof(sectionheader), 1, fileh) == 1)
					{
						if (!strcmp_nonnull(sectionheader.sectionType, 4, "CONT"))
						{
							//Section header read

							//Read the filename (null-terminated string)
							int slen = freadstr(fileh, currentLvzFileName, _MAX_FNAME);

							printf("Section %i: '%s', %i -> %i\n", i, currentLvzFileName, sectionheader.compressedSize, sectionheader.decompressedSize);


							if (sectionheader.compressedSize > 0 &&
								sectionheader.decompressedSize > 0)
							{
								u8 decompressedData[sectionheader.decompressedSize];
								u8 compressedData[sectionheader.compressedSize];

								//Read compressed data
								if (fread(compressedData, sectionheader.compressedSize, sizeof(u8), fileh))
								{
									int decompressedSize = sectionheader.decompressedSize;

									//Decompress the data
									util->zlibDecompress(
											compressedData,
											sectionheader.compressedSize,
											decompressedData,
											&decompressedSize);

									if (sectionheader.decompressedSize != (unsigned)decompressedSize)
									{
										//expected size doesn't match... ?
									}

									if (sectionheader.fileTime == 0 && slen == 0)
									{
										//This section contains object definitions
										LvzObjectSectionHeader objHeader;
										LvzObjectSectionType   objSectionType = LVZ_UnsupportedFormat;

										//Data pointer to scroll through the definitions section
										u8* dataPtr = decompressedData;

										memcpy(&objHeader, dataPtr, sizeof(objHeader));
										dataPtr += sizeof(objHeader);

										printf("Object definition section: %u objects, %u images\n", objHeader.objectCount, objHeader.imageCount);

										//Determine which format is used
										if (!strcmp_nonnull(objHeader.uncompressedSectionType, 4, "CLV1"))
											objSectionType = LVZ_CLV1;
										else if (!strcmp_nonnull(objHeader.uncompressedSectionType, 4, "CLV2"))
											objSectionType = LVZ_CLV2;


										printf("sizeof(lvzobj)=%i sizeof(imgdef)=%i", sizeof(LvzObjectDefinition), sizeof(LvzImageDefinition));

										//Read each object, one at a time
										for (ii = 0; ii < objHeader.objectCount; ii++)
										{
											addObjectDefinition(currentLvzFile, (LvzObjectDefinition*)dataPtr, objSectionType);
											dataPtr += sizeof(LvzObjectDefinition);
										}

										//Read each image definition, one at a time
										for (ii = 0; ii < objHeader.imageCount; ii++)
										{
											//Grab the image filename, located after the fixed-size header
											strcpy(currentImageFileName, (char*)dataPtr+sizeof(LvzImageDefinition));

											//Add the definition, with the fixed size header located at the pointer
											addImageDefinition(currentLvzFile, (LvzImageDefinition*)dataPtr, currentImageFileName, objSectionType);

											//Advance the data pointer
											dataPtr += sizeof(LvzImageDefinition);
											dataPtr += strlen(currentImageFileName)+1;
										}
									}
									else
									{
										printf("File section '%s'\n", currentLvzFileName);

										//This section contains a file
										addFile(currentLvzFile, currentLvzFileName, decompressedData, decompressedSize);
									}
								}
								else
									printf("Could not read compressed data\n");
							}
							else
								printf("Section size = 0\n");
						}
						else
							printf("Invalid section %i data\n", i);
					}
					else
						printf("Could not read section %i\n", i);
				} //end for each section
				success = TRUE;
			}
			else
				printf("Invalid LVZ file '%s'\n", filename);
		}
		else
			printf("fread failed\n");
	}
	else
		printf("fopen failed\n");
}
else
	printf("'%s' not a legal filename\n", filename);

printf("Opened LVZ file '%s', success=%i\n", filename, success);

return success;
}

 

Posted

For errors that shouldn't occur use the LOG_ERROR(const char*) macro, or LOG_ERROR2(const char*, arg1), or LOG_ERROR3(const char*, arg1, arg2) <- printf like format

 

 

LvzObjectSectionHeader objHeader;
...
memcpy(&objHeader, dataPtr, sizeof(objHeader));

Here, the correctness depends on the endianness of the architecture (the way in which the structure is laid out in memory). If objHeader is interpreted as laid out differently (for example on a powerpc mac), this won't work as expected.

Posted

LvzObjectSectionHeader objHeader;
...
memcpy(&objHeader, dataPtr, sizeof(objHeader));

Here, the correctness depends on the endianness of the architecture (the way in which the structure is laid out in memory). If objHeader is interpreted as laid out differently (for example on a powerpc mac), this won't work as expected.

 

 

hmmm

typedef struct
{
char uncompressedSectionType[4];	//'CLV1' or 'CLV2'
u32  objectCount;		//Mapobjects+Screenobjects count
u32  imageCount;		//Image definitions count
} LvzObjectSectionHeader;

The format in the file itself is fixed... So... I'm not sure how else I would do this. If I read it block by block, I'll have the same problem; I'll end up having to memcpy a u32 from the file data to the header. ?

I can see how to do this for my LvzObjectDefinition struct, which has bitfields, but for this one, I have no idea.

Posted

I think this'll work:

 

Settings Used:

 

/*

[images]

;;;;One of these per Image Definition

LVZ__imagePath=

LVZ__imageFrames=(,)

 

[Animations]

 

;;;;One of these per mapobject/screenobject

LVZ__obj Unique Image = LVZ__image

LVZ__obj Animation Milliseconds =

 

*/

 

Example:

 

[images]

LVZ_center_image0Path=center_image

LVZ_center_image0Frames=(1,1)

 

LVZ_center_image1Path=center_anim

LVZ_center_image1Frames=(10,3)

 

 

[Animations]

LVZ_center_obj0 Unique Image = LVZ_center_image0

LVZ_center_obj0 Animation Milliseconds = 1000

 

 

LVZ_center_obj1 Unique Image = LVZ_center_image1

LVZ_center_obj1 Animation Milliseconds = 1500

 

 

This should work fine for image definitions that define an image from another lvz file, so should be good.

 

 

 

 

 

Edit: well, that indentation isn't a problem on my widescreen monitor blum.gif but that's an idea

Posted
Callbacks... basically they're events that a module can trigger, and another module could "listen" for a specific callback and do something about it, right? For example, I could have a callback that says a specific LVZ file is done loading (or all lvz's requested are loaded, or they didn't load right), and whatever module loads the map/graphics when entering an arena will have to wait for this before loading stuff, cause the lvz might override graphics. (Or not, since it would just be a function call, no delay involved)

 

I'll also need to somehow listen for the objon/off/set/move packets, and mess with the animations. I think I seen some code that told the Net module to pass on every packet about "something", or something like that... Anyway, I'll start by unpacking some lvz's blum.gif

Yes callbacks are events you listen to, which are sort of like interrupts. Rather than periodically polling if a player has died, it's much cleaner to simply say "call this function when a player dies". This is the idea with callbacks. For the packets, however, you'll want to do the following:

 

register and wait for the CB_REGPACKETS callback to occur, then call Net::regPacketFunc for any packets they wish to handle. regPacketFunc takes in a string for the type of packet you want to listen for and a callback-like function. The packet types and relevant fields are defined in conf/modules/net.conf in the [Packet Templates] section. grep for regPacketFunc to see some examples.

 

How do you define packets with variable size in the packet templates (objset packets are 2xN bytes)? ;)

Posted

use type "raw", see the "incoming file transfer" type in net.conf (grep for it to see how it's handled in code)

 

The format in the file itself is fixed... So... I'm not sure how else I would do this.

 

you can do like:

 

u32 value = (data[3] << 24) | (data[2] << 16) | (data[1] <<  | data[0];

and it will work everywhere. There are functions to do this in Modules/Shared/LittleEndian.h/.cpp

 

// extract a little endian u32
u32 getU32(u8* loc)
{	
u32 rv = 0;

for (int x = 3; x >= 0; --x)
{
	rv *= 256;
	rv += loc[x];
}

return rv;
}

Posted

amidoinitrite?

 

/*
* Reads data from rawData and formats the information the lvzImage structure
* Returns the number of bytes read (should be 6+strlen(filename)+1 with CLV1 or CLV2)
*/
int rawToLvzImage(const u8* rawData, LvzImage* lvzImage, LvzObjectSectionType sectionType)
{
switch (sectionType)
{
case LVZ_CLV1:
case LVZ_CLV2:

	lvzImage->framesX = rawData[1] << 8 | rawData[0];
	lvzImage->framesY = rawData[3] << 8 | rawData[2];
	lvzImage->animationTime = rawData[5] << 8 | rawData[4];

	//Grab the image filename, located after the fixed-size header
	lvzImage->imageName.assign((char*)rawData+6);

	//include the '\0' character in the count
	return 7 + lvzImage->imageName.size();

case LVZ_UnsupportedFormat:
	return 0;
}
}

 

edit: wee, that seems to work

Posted

I did some modifications in SettingsHandler to be able to use the ScreenLocation stuff directly, without having to actually write a setting for it...

 

 

 

void getScreenLocation(Point* loc, char letterX, int offsetX, char letterY, int offsetY)
{
map <char, Point>::iterator i;

i = letterLocationMap.find(letterX);

if (i != letterLocationMap.end())
	loc->x = offsetX;
else
	loc->x = offsetX + i->second.x;

// and y
i = letterLocationMap.find(letterY);

if (i != letterLocationMap.end()) // fine, just a regular coordinate
	loc->y = offsetY;
else
	loc->y  = offsetY + i->second.y;

AssignedPoint ap;
ap.ptr = loc;
ap.letterX = letterX;
ap.letterY = letterY;
ap.xOffset = offsetX;
ap.yOffset = offsetY;

letterAssignments.push_back(ap);
}

void getSettingAsScreenLocation(Point* loc, const char* category, const char* setting)
{
string defaultLoc = "(0, 0)";
string set = *sh.getSettingAsString2(category,setting,&defaultLoc);

if (set.length() < 3 || set[0] != '(' || set[set.length() - 1] != ')')
	LOG_ERROR2("malformed screen location (no parenthesis): '%s'",set.c_str());
else
{
	set = set.substr(1,set.size() - 2); // strip parenthesis
	size_t comma_loc = set.find(',');

	if (comma_loc == string::npos)
		LOG_ERROR2("malformed screen location (no comma): '%s'",set.c_str());
	else
	{
		string first = set.substr(0,comma_loc);
		string second = set.substr(comma_loc + 1);

		trimWhitespace(&first);
		trimWhitespace(&second);

		if (first.size() > 0 && second.size() > 0)
		{
			int offsetX;
			char letterX = tolower(first[0]);

			map <char, Point>::iterator i = letterLocationMap.find(letterX);

			if (isdigit(letterX) || letterX == '-' ) // fine, just a regular coordinate
			{
				letterX = 0;
				offsetX = strtol(first.c_str(),0,0);
			}
			else
			{
				offsetX = strtol(first.c_str() + 1,0,0);
			}

			// and y
			int offsetY;
			char letterY = tolower(second[0]);
			
			i = letterLocationMap.find(letterY);

			if (isdigit(letterY)) // fine, just a regular coordinate
			{
				letterY = 0;
				offsetY = strtol(second.c_str(),0,0);
			}
			else
			{
				offsetY = strtol(second.c_str() + 1,0,0);
			}
			
			getScreenLocation(loc, letterX, offsetX, letterY, offsetY);
		}
		else
			LOG_ERROR2("Screen Location Setting doesn't contain two sets of values: '%s'",set.c_str());
	}
}
}

 

 

Not tested yet, so it may contain minor bugs, but the point is... I'd find it weird to have an interface function in settingsHandler that doesn't actually play with settings... So how would you have done it? I guess I could write a setting, then getSettingAsScreenLocation, but that seems like even more trouble for me, as I'd have to convert the already binary data to text, then back to binary through the interface. And where would that setting go anyway?

 

Speaking of settings... all these settings are written only for the current arena, right? Say I write a bunch of settings in images and animations while loading arena 1, then go to arena 2, these settings will be gone?

Posted
hmmmm... so my LvzObject struct has a Point * that gives it its x/y... for screenobject I just use the functions above and it will handle the object (creating and deleting it in memory); but if I have a mapobject... I could cheat and use the same functions with a 0 reference, and I know I'll use these coordinates as map reference when calling the animations... otherwise I have to keep a list of points of my own only for the mapobjects? 8)
Posted

your functions look fine; even though the extra one does not deal directly with the settings, it does so indirectly (if the screen location anchors change it will update the points accordingly). It seems okay to keep it in the SettingsHandler for that reason.

 

Your second question is an interesting one, although I think there's some misunderstanding. For the above functions, you pass in a pointer to a Point which you have allocated (either on the stack or on the heap); SettingsHandler does no memory management in this respect.

 

 

For mapobjects, there are no relative values, so just get the x/y values of the mapobject and call Animation* (*playLoopingAnimation)(const char* name, int xPixel, int yPixel, bool centered, int layer);

 

for screenobjects, the animation location may be change. Luckily, the Animations interface doesn't handle screenobjects yet so you can write it any way you want. Since all screen objects are likely to be within the bounds of the screen, it's fairly pointless to do sorting and such things for bounds checking on the screen (as is done for mapobjects for efficiency since the majority of active mapobjects are likely to be off screen). I believe it is sufficient to, internally within Animations, just have a single list of screenobjects with their Point and their display time and such. Then, the interface for creating a screenobject would be something like Animation* (*playLoopingScreenAnimation)(const char* name, char letterX, int offsetX, char letterY, int offsetY, bool centered, int layer); (in addition to the timed variant). The memory for the Point then would be managed internally within the Animations interface.

 

If you want me to make the modifications to Animations let me know and I'll do it. Also let me know if I didn't answer what you were asking.

Posted

Oh, that clears things up, thanks;

 

So... I could just have a Point in my struct, and pass the pointer to the settingshandler. And then it will change the coordinates directly in my structure when the reference changes, right? (atleast that's what I understand from this bit of comment: "Note that the point pointer you pass into this function may be modified long after the call, as is the case in continuum. For example, if the player list gets resized some of the points may be moved, so DON'T USE A STACK VARIABLE.")

 

But isn't there some kind of risk that it still tries to change my data after my structure has ceased to "exist"?

 

You're right that the Animation interface itself could handle the Point, but will the Point data be updated as the reference changes (i.e. player hits F2), and what will happen if the reference changes after the animation is done playing and the pointer is invalid?

Posted

Alright, this should be pretty platform-independant, and it works!

 

LVZ ini

 

 

Outfile=disc_test.lvz

 

File=system.bmp

File=boom.bmp

 

[objectimages]

IMAGE1=system.bmp,10,6,500

IMAGE2=boom.bmp,10,4,400

 

[mapobjects]

-28000,28000,IMAGE1,BelowAll,ServerControlled,500,1

-24000,24000,IMAGE1,BelowAll,ServerControlled,500,5000

-1000,1000,IMAGE1,BelowAll,ServerControlled,500,10000

1,1,IMAGE1,BelowAll,ServerControlled,500,16900

0,0,IMAGE1,BelowAll,ServerControlled,500,32500

 

[screenobjects]

0,-6,IMAGE1,TopMost,ServerControlled,500

C0,B-6,IMAGE1,TopMost,Kill,500

R-0,R-9,IMAGE2,AfterChat,ShowAlways,400

S2047,R-1,IMAGE2,AfterChat,Death,400

S-1150,R110,IMAGE2,AfterChat,Death,400

R-0,R110,IMAGE2,AfterChat,Death,400

 

 

 

Console output

 

 

Opening LVZ file 'disc_test.lvz'

Lvz file 'disc_test.lvz' added

3 sections in LVZ

Section 0: 'system.bmp', 12608 -> 287566

File section 'system.bmp'

File 'system.bmp' added

Section 1: 'boom.bmp', 32515 -> 485078

File section 'boom.bmp'

File 'boom.bmp' added

Section 2: '', 131 -> 154

Object definition section: 11 objects, 2 images

isMap:1 ID:1 Loc:( -28000, 28000)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:1 ID:5000 Loc:( -24000, 24000)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:1 ID:10000 Loc:( -1000, 1000)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:1 ID:16900 Loc:( 1, 1)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:1 ID:32500 Loc:( 0, 0)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:0 ID:0 Loc:(r0,r-9)

dispTime:4000 Layer:650 Image:1 Mode:0

isMap:0 ID:0 Loc:(s-1986,r0)

dispTime:4000 Layer:650 Image:1 Mode:4

isMap:0 ID:0 Loc:(s-1150,r110)

dispTime:4000 Layer:650 Image:1 Mode:4

isMap:0 ID:0 Loc:(r0,r110)

dispTime:4000 Layer:650 Image:1 Mode:4

isMap:0 ID:0 Loc:( 0, -6)

dispTime:5000 Layer:50 Image:0 Mode:5

isMap:0 ID:0 Loc:(c0,b-6)

dispTime:5000 Layer:50 Image:0 Mode:3

Image definition 'system.bmp' added (10,6,500)

Image definition 'boom.bmp' added (10,4,400)

Opened LVZ file 'disc_test.lvz', success=1

 

 

 

Da code

 

 

/*
* Reads data from rawData, and formats the information in the lvzObject structure
* Returns the number of bytes read (should be 10 with CLV1 or CLV2)
*
* Some fields of lvzObject are NOT filled by this functions:
*   -imageHandle   (this requires the UniqueImage data to be created, which requires the image definitions to be read)
*   -parentLvz     (this is filled in addObjectDefinition, which is called after this function)
*   -objectName    (this requires the name of the parent LVZ)
*   -animationTime (this is determined by the image definition, which are after the object definitions)
*/
/* Data layout in file 
Mapobject
0: [low 7 bits id] [1 bit mapobject]
1: [high 8 bits id]
2: [low 8 bits x]
3: [high 8 bits x]
4: [low 8 bits y]
5: [high 8 bits y]
6: [8 bits image num]
7: [8 bits layer]
8: [low 8 bits display time]
9: [4 bits mode] [high 4 bits display time]
ScreenObject:
0: [low 7 bits id] [1 bit mapobject]
1: [high 8 bits id]
2: [low 4 bits x_coord] [4 bits x_type]
3: [high 8 bits x_coord]
4: [low 4 bits x_coord] [ 4 bits x_type]
5: [high 8 bits y_coord]
6: [8 bits image num]
7: [8 bits layer]
8: [low 8 bits display time]
9: [4 bits mode] [high 4 bits display time]
*/
int rawToLvzObject(const u8* rawData, LvzObject* lvzObject, LvzObjectSectionType sectionType)
{
switch (sectionType)
{
case LVZ_CLV1:
case LVZ_CLV2:
	//MapObject:
	lvzObject->isMapObject = rawData[0] & 0x01;
	lvzObject->objectID    = (rawData[0] & 0xFE) >> 1 | rawData[1] << 7;

	if (sectionType == LVZ_CLV2 && !lvzObject->isMapObject)
	{
		lvzObject->objectRef = Point(LVZ_SCREEN_REFERENCES[rawData[2]&0x0F],
									LVZ_SCREEN_REFERENCES[rawData[4]&0x0F]);

		lvzObject->objectLoc = Point(unsignedToSigned( (rawData[2]&0xF0) >> 4 | rawData[3] << 4, 12),
									 unsignedToSigned( (rawData[4]&0xF0) >> 4 | rawData[5] << 4, 12) );
	}
	else
	{
		lvzObject->objectRef = Point(0, 0);

		lvzObject->objectLoc = Point(unsignedToSigned( rawData[2] | rawData[3] << 8, 16) ,
									unsignedToSigned( rawData[4] | rawData[5] << 8, 16) );
	}

	lvzObject->imageID = rawData[6];

	lvzObject->objectLayer = LVZ_LAYERS[ rawData[7]%LVZ_TopMost ];

	//Display time for mapobjects and screenobjects are in 1/10th of second in the file
	lvzObject->displayTime = ( rawData[8] | (rawData[9] & 0x0F) << 8 ) * 100;

	lvzObject->displayMode = (rawData[9] & 0xF0) >> 4;



	printf("isMap:%i  ID:%i  Loc:(%c%i,%c%i)\n",
			lvzObject->isMapObject, lvzObject->objectID,
			(lvzObject->objectRef.x ? lvzObject->objectRef.x:' '), lvzObject->objectLoc.x,
			(lvzObject->objectRef.y ? lvzObject->objectRef.y:' '), lvzObject->objectLoc.y);
	printf("dispTime:%i Layer:%i Image:%i Mode:%i\n", lvzObject->displayTime, lvzObject->objectLayer, lvzObject->imageID, lvzObject->displayMode);
	return 10;

case LVZ_UnsupportedFormat:
default:
	return 0;
}
}

 

 

 

I have some interesting functions that might be useful in other modules, dunno if they'd qualify for utilities or shared or something like that

 

 

Headers

 

 

/* strcmp_nonnull
* Compares a non-null terminated string with another string
* Useful to validate headers
*/
int strcmp_nonnull(const char * nonNullStr, int nonNullStrLen, const char * str2);

/* freadstr
* Source: http://www.daniweb.com/forums/thread171897.html#
*
* reads a null-terminated string from a file, from its current position
*
* Returns the length of the string read
* Returns -1 if an error occurs
*/
int freadstr(FILE* fid, char* str, size_t max_size);

/*
* Interprets an unsigned value of n-bits as a signed value
* @param unsignedValue unsigned int value to convert
* @param numberOfBits number of bits on which the unsigned value is represented
* @return signed value; output may be unpredictable if unsignedValue > 2^numberOfBits - 1
*/
int unsignedToSigned(unsigned int unsignedValue, int numberOfBits);

 

 

Body

 

 


int unsignedToSigned(unsigned int unsignedValue, int numberOfBits)
{
if (unsignedValue >= (unsigned)(1 << (numberOfBits - 1)))
	//Value is negative
	return -((1 << numberOfBits) - unsignedValue);
else
	//Value is positive
	return unsignedValue;
}

int freadstr(FILE* fid, char* str, size_t max_size)
{
   int c;
   size_t count = 0;

   do {
       c = fgetc(fid);
       if (c == EOF) {
           /* EOF means either an error or end of <strong class="highlight">file</strong> but
            * we do not care which. Clear <strong class="highlight">file</strong> error flag
            * and return -1 */
           clearerr(fid);
           return -1;
       } else {
           /* Cast c to char */
           *str = (char) c;
           if (*str != '\0')
           	count++;
       }
   } while ((*str++ != '\0') && (count < max_size));
   return count;
}


int strcmp_nonnull(const char * nonNullStr, int nonNullStrLen, const char * str2)
{
int i;

for (i = 0; i < nonNullStrLen; i++)
	if (nonNullStr[i] != str2[i])
		return nonNullStr[i] - str2[i];

return 0;
}

 

 

 

 

 

 

Now... gotta list these object and image definitions, and link the objects to the images

Posted

you're right, passing a stack pointer is a bad idea. Right now, the pointers are kept forever. It's probably necessary to add a function to SettingsHandler to stop tracking Point*'s when you dispose of animations. Then, it's probably a good idea to change in SettingsHandler

 

list letterAssignments;

 

to

 

map letterAssignments;

 

for quick freeing.

Posted

Trying to get some images to show up... and I must say it's not going well blum.gif

 

Is there some callback I need to wait for before using the playAnimations stuff? Or maybe some place where the level is loaded that I could call my functions, instead of loading it all with the init() of my module? I think the Animations module didn't even get to its postload step, and I'm trying to make it display animations... that could explain the segfaults blum.gif

 

Also, how do I fopen/fwrite to the path of the current zone? It currently writes in the bin/bin folder... not a problem to test for now though, I just moved the files manually to the Single Player folder, and it should work there.

Posted

You probably should wait until the downloads complete before reading the lvz and drawing animations, the callback from FileTransfer.h is CB_PREENTER_DOWNLOADS_DONE . Doing it too early will cause segfaults, as you described. For things with precedence relationships there will usually be a callback, although for lvz waiting for the file transfers to complete will suffice (make sure it is called in single player mode though, it's possible it's not; let me know if it's not and I'll add it).

 

For the zone path, use a function from the Net interface:

 

/**
* Get the path to the directory where the zone's file are kept, do after you set zone name, obviously.
* this has the '/' at the end so you can just append a filename
* @return path to the directory where the zone's file are kept
*/
const char* (*getZoneDataPath)();

Again, use it in CB_PREENTER_DOWNLOADS_DONE and it should be valid.

 

Also, while you're making the module (after it works), think of some cool and easy extensions to put in (for example, animations relative to specific ship types was one thing people suggested, so they could have animations on top of each type of ship). Maybe a mode like "InRegionXYZ" where XYZ is an asss region name (then again, I need a region module too), where an lvz would only display when you're in a certain region. Maybe we could incorporate sounds into lvz too (I also need a sounds module), for like entering regions, or sounds coming from certain locations on the map (I think the SDL_mixer library supports such things easily). Are there any other cool ones you can think of?

Posted

For some reason, it crashes instantly with a 'send report' dialog when I start the .bat... I think it doesn't like my SettingsHandler module; had to recompile it with the new getScreenLocation function :/

I tried by changing the version of the interface "I-SettingsHandler-23" to "I-SettingsHandler-24", and it gave me a warning about module/code versions...

 

 

Also, I still can't compile 'some' projects (FileTransfer, Graphics, Net) because of:

'cannot find -|SDL_net' or -|SDL_image

Even though the includes for SDL_net and SDL_image now work fine

 

Also can't compile utilities, it seems I'm missing zlib.h ... tried to get one, but it still wouldn't work (i.e. crc32 wasn't defined)

 

Edit: what the hell?

 

When I run the .bat, it creates a 'SettingsHandler.so' file in \bin\Modules (NOT \bin\Modules\SettingsHandler)

Posted

The instant crash is because the settings handler version MUST be updated if you change the interface, and therefore all modules which use the interface must be recompiled (changing the I_ version macro will ensure it does not try to load an old version, which would lead to lead to unexpected behavior since the modules expect the function pointers to have certain offsets within the interface class, but if you change the class and recompile those offsets may change).

 

-|SDL_net' or -|SDL_image
There are two types of directories, include directories (for header files) (gcc flag -I) and library directories (for static libraries) (gcc flag -L). Header files include the function headers... ever wonder where the implementation is? It's either precompiled into a static library file (.lib), or linked dynamically during runtime (.dll or .so). For sdl_net and sdl_image, they are linked statically at compile time, so you must add the static library search path into your project. You need to add the correct library directory to project, check Prject->Properties->C/C++ Build->Settings->Tool Settings->MinGW C++ Linker->Libraries->Library Search Path.

 

For zlib, you want version 1.2.3 (from http://www.zlib.net/ ).

 

When I run the .bat, it creates a 'SettingsHandler.so' file in \bin\Modules (NOT \bin\Modules\SettingsHandler)
Yes that's on purpose and for a reason. The front end handles the updates, and the updates MAY include an update to SettingsHandler.so . Since you can't overwrite an .so file when it's in use, and the front end uses the settings handler module, the solution is to write the updated file to Modules/SettingsHandler/SettingsHandler.so. When the front end runs, it compares \bin\Modules\SettingsHandler.so and \bin\Modules\SettingsHandler\SettingsHandler.so and, if they differ, copies \bin\Modules\SettingsHandler\SettingsHandler.so to \bin\Modules\SettingsHandler.so and loads that one.

 

You will also need to recompile the front end (cskinviewer) to reflect the new version of the SettingsHandler module. The directory with the eclipse project is disc_client\src\FrontEnd\cskinviewer

Posted

hmm, and what about zdll? I managed to get everything working now, except that blum.gif "cannot find -lzdll"

I added the search path to C:\MinGW\lib\zlib-1.2.3 , where I unzipped the whole zlib 1.2.3 source

 

bleh

 

 

Edit: ok got it... now to aedGuiBak...

 

 

Edit2: emm... added a search path to "D:\Sam\Prog Projects\Discretion\client\trunk\disc_client\deps\aedGUI-0.1.8a-bak\Release", still doesn't want to work...

Posted

Here's mine:

 

http://img.photobucket.com/albums/v622/bak2007/cskin_settings.png

 

 

I think with gcc/minGW you can even link directly to the .dll instead of using a library... also that stuff I said before about static libraries is true, but these ones are all dynamic (they have a corresponding .dll file), the library simply includes the offsets within the .dll, or something to that effect, not the actual source.

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.

Loading...

×
×
  • Create New...