Exemplo n.º 1
0
// load a list of triggers
static BOOL eventLoadTriggerList(WZ_DECL_UNUSED const SDWORD version, char *pBuffer, UDWORD *pSize)
{
	UDWORD				size, event, offset, time;
	char				*pPos;
	SDWORD				numTriggers, context, type, trigger, i;
	SCRIPT_CONTEXT		*psContext;

	size = 0;
	pPos = pBuffer;

	// get the number of triggers
	endian_sdword((SDWORD*)pPos);
	numTriggers = *((SDWORD*)pPos);
	pPos += sizeof(SDWORD);
	size += sizeof(SDWORD);

	for(i=0; i<numTriggers; i+= 1)
	{
		endian_udword((UDWORD*)pPos);
		time = *((UDWORD*)pPos);
		pPos += sizeof(UDWORD);

		endian_sword((SWORD*)pPos);
		context = *((SWORD*)pPos);
		pPos += sizeof(SWORD);
		if (!eventFindContext(context, &psContext))
		{
			debug( LOG_FATAL, "eventLoadTriggerList: couldn't find context" );
			abort();
			return false;
		}

		endian_sword((SWORD*)pPos);
		type = *((SWORD*)pPos);
		pPos += sizeof(SWORD);

		endian_sword((SWORD*)pPos);
		trigger = *((SWORD*)pPos);
		pPos += sizeof(SWORD);

		endian_uword((UWORD*)pPos);
		event = *((UWORD*)pPos);
		pPos += sizeof(UWORD);

		endian_uword((UWORD*)pPos);
		offset = *((UWORD*)pPos);
		pPos += sizeof(UWORD);

		size += sizeof(UDWORD) + sizeof(SWORD)*3 + sizeof(UWORD)*2;

		if (!eventLoadTrigger(time, psContext, type, trigger, event, offset))
		{
			return false;
		}
	}

	*pSize = size;

	return true;
}
Exemplo n.º 2
0
// Load the state of the event system
bool eventLoadState(char *pBuffer, UDWORD fileSize)
{
	UDWORD			size, totalSize, version;
	char			*pPos;
	EVENT_SAVE_HDR	*psHdr;

	pPos = pBuffer;
	totalSize = 0;

	// Get the header
	psHdr = (EVENT_SAVE_HDR *)pPos;
	endian_udword(&psHdr->version);
	ASSERT_OR_RETURN(false, strncmp(psHdr->aFileType, "evnt", 4) == 0, "Invalid file header");
	version = psHdr->version;
	pPos += sizeof(EVENT_SAVE_HDR);
	totalSize += sizeof(EVENT_SAVE_HDR);

	// load the event contexts
	if (!eventLoadContext(version, pPos, &size))
	{
		return false;
	}

	pPos += size;
	totalSize += size;

	// load the normal triggers
	if (!eventLoadTriggerList(version, pPos, &size))
	{
		return false;
	}
	pPos += size;
	totalSize += size;

	// load the callback triggers
	if (!eventLoadTriggerList(version, pPos, &size))
	{
		return false;
	}
	pPos += size;
	totalSize += size;

	if (totalSize != fileSize)
	{
		debug( LOG_FATAL, "eventLoadState: corrupt save file" );
		abort();
		return false;
	}

	return true;
}
Exemplo n.º 3
0
// Load the state of the event system
BOOL eventLoadState(char *pBuffer, UDWORD fileSize, BOOL bHashed)
{
	UDWORD			size, totalSize, version;
	char			*pPos;
	EVENT_SAVE_HDR	*psHdr;


	pPos = pBuffer;
	totalSize = 0;

	// Get the header
	psHdr = (EVENT_SAVE_HDR *)pPos;
	endian_udword(&psHdr->version);
	if (strncmp(psHdr->aFileType, "evnt", 4) != 0)
	{
		debug( LOG_FATAL, "eventLoadState: invalid file header" );
		abort();
		return false;
	}
/*	if ((psHdr->version != 1) &&
		(psHdr->version != 2))
	{
		DBERROR(("eventLoadState: invalid file version"));
		return false;
	}*/
	version = psHdr->version;
	pPos += sizeof(EVENT_SAVE_HDR);
	totalSize += sizeof(EVENT_SAVE_HDR);


	// load the event contexts
	if (!eventLoadContext(version, pPos, &size, bHashed))
	{
		return false;
	}

	pPos += size;
	totalSize += size;

	// load the normal triggers
	if (!eventLoadTriggerList(version, pPos, &size))
	{
		return false;
	}
	pPos += size;
	totalSize += size;

	// load the callback triggers
	if (!eventLoadTriggerList(version, pPos, &size))
	{
		return false;
	}
	pPos += size;
	totalSize += size;

	if (totalSize != fileSize)
	{
		debug( LOG_FATAL, "eventLoadState: corrupt save file" );
		abort();
		return false;
	}

	return true;
}
Exemplo n.º 4
0
// Save the state of the event system
BOOL eventSaveState(SDWORD version, char **ppBuffer, UDWORD *pFileSize)
{
	UDWORD			size, totalSize;
	char			*pBuffer, *pPos;
	EVENT_SAVE_HDR	*psHdr;

	totalSize = sizeof(EVENT_SAVE_HDR);

	// find the size of the context save
	if (!eventSaveContext(NULL, &size))
	{
		return false;
	}
	totalSize += size;

	// find the size of the trigger save
	if (!eventSaveTriggerList(psTrigList, NULL, &size))
	{
		return false;
	}
	totalSize += size;

	// find the size of the callback trigger save
	if (!eventSaveTriggerList(psCallbackList, NULL, &size))
	{
		return false;
	}
	totalSize += size;



	// Allocate the buffer to save to
	pBuffer = (char*)malloc(totalSize);
	if (pBuffer == NULL)
	{
		debug( LOG_FATAL, "eventSaveState: out of memory" );
		abort();
		return false;
	}
	pPos = pBuffer;


	// set the header
	psHdr = (EVENT_SAVE_HDR *)pPos;
	psHdr->aFileType[0] = 'e';
	psHdr->aFileType[1] = 'v';
	psHdr->aFileType[2] = 'n';
	psHdr->aFileType[3] = 't';
	psHdr->version = version;
	endian_udword(&psHdr->version);

	pPos += sizeof(EVENT_SAVE_HDR);


	// save the contexts
	if (!eventSaveContext(pPos, &size))
	{
		return false;
	}
	pPos += size;

	// save the triggers
	if (!eventSaveTriggerList(psTrigList, pPos, &size))
	{
		return false;
	}
	pPos += size;

	// save the callback triggers
	if (!eventSaveTriggerList(psCallbackList, pPos, &size))
	{
		return false;
	}
	pPos += size;

	*ppBuffer = pBuffer;
	*pFileSize = totalSize;

	return true;
}
Exemplo n.º 5
0
// save the context information for the script system
static BOOL eventSaveContext(char *pBuffer, UDWORD *pSize)
{
	UDWORD				size, valSize;
	SDWORD				numVars, i, numContext;
	SCRIPT_CONTEXT		*psCCont;
	VAL_CHUNK			*psCVals;
	INTERP_VAL			*psVal;
	SCR_VAL_SAVE		saveFunc;
	char				*pPos;
//not hashed	char				*pScriptID;
	UDWORD				hashedName;
	UWORD				*pValSize = NULL;


	size = 0;
	numContext = 0;
	pPos = pBuffer;

	// reserve space to store how many contexts are saved
	if (pBuffer != NULL)
	{
		pPos += sizeof(SWORD);
	}
	size += sizeof(SWORD);

	// go through the context list
	for(psCCont = psContList; psCCont != NULL; psCCont = psCCont->psNext)
	{
		numContext += 1;

		// save the context info
//nothashed if (!resGetIDfromData("SCRIPT", psCCont->psCode, &hashedName))
		if (!resGetHashfromData("SCRIPT", psCCont->psCode, &hashedName))
		{
			debug( LOG_FATAL, "eventSaveContext: couldn't find script resource id" );
			abort();
			return false;
		}
		numVars = psCCont->psCode->numGlobals + psCCont->psCode->arraySize;

		if (pBuffer != NULL)
		{
//not hashed			strcpy(pPos, pScriptID);
//not hashed			pPos += strlen(pScriptID) + 1;
			*((UDWORD*)pPos) = (UDWORD)hashedName;
			endian_udword((UDWORD*)pPos);
			pPos += sizeof(UDWORD);

			*((SWORD*)pPos) = (SWORD)numVars;
			endian_sword((SWORD*)pPos);
			pPos += sizeof(SWORD);

			*pPos = (UBYTE)psCCont->release;
			pPos += sizeof(UBYTE);
		}

//not hashed		size += strlen(pScriptID) + 1 + sizeof(SWORD) + sizeof(UBYTE);
		size += sizeof(UDWORD) + sizeof(SWORD) + sizeof(UBYTE);

		// save the context variables
		for(psCVals = psCCont->psGlobals; psCVals != NULL; psCVals = psCVals->psNext)
		{
			for(i=0; i < CONTEXT_VALS; i+= 1)
			{
				psVal = psCVals->asVals + i;

				// store the variable type
				if (pBuffer != NULL)
				{
					ASSERT( psVal->type < SWORD_MAX,
						"eventSaveContext: variable type number too big" );

					*((SWORD*)pPos) = (SWORD)psVal->type;
					endian_sword((SWORD*)pPos);

					pPos += sizeof(SWORD);
				}
				size += sizeof(SWORD);

				// store the variable value
				if (psVal->type == VAL_STRING)
				{
					UDWORD stringLen = 0;

					if(psVal->v.sval != NULL && strlen(psVal->v.sval) > 0)
					{
						stringLen = strlen(psVal->v.sval) + 1;
					}

					if (pBuffer != NULL)
					{
						*((UDWORD *)pPos) = stringLen;
						endian_udword((UDWORD *)pPos);
						pPos += sizeof(UDWORD);

						if(stringLen > 0)
						{
							strcpy((char *)pPos, psVal->v.sval);
						}
						pPos += stringLen;
					}

					size += sizeof(UDWORD) + stringLen;
				}
				else if (psVal->type < VAL_USERTYPESTART)
				{
					// internal type
					if (pBuffer != NULL)
					{
/* FIXME: this does not work for VAL_OBJ_GETSET, VAL_FUNC_EXTERN */
						*((UDWORD *)pPos) = (UDWORD)psVal->v.ival;
						endian_udword((UDWORD*)pPos);
						
						pPos += sizeof(UDWORD);
					}

					size += sizeof(UDWORD);
				}
				else
				{
					// user defined type
					saveFunc = asScrTypeTab[psVal->type - VAL_USERTYPESTART].saveFunc;

					ASSERT( saveFunc != NULL,
						"eventSaveContext: no save function for type %d\n", psVal->type );

					// reserve some space to store how many bytes the value uses
					if (pBuffer != NULL)
					{
						pValSize = (UWORD *)pPos;
						pPos += sizeof(UWORD);
					}
					size += sizeof(UWORD);

					if (!saveFunc(psVal, pPos, &valSize))
					{
						debug( LOG_FATAL, "eventSaveContext: couldn't get variable value size" );
						abort();
						return false;
					}

					if (pBuffer != NULL)
					{
						*pValSize = (UWORD)valSize;
						endian_uword((UWORD*)pValSize);

						pPos += valSize;
					}
					size += valSize;
				}

				numVars -=1;
				if (numVars <= 0)
				{
					// done all the variables
					ASSERT( psCVals->psNext == NULL,
						"eventSaveContext: number of context variables does not match the script code" );
					break;
				}
			}
		}
		ASSERT( numVars == 0,
			"eventSaveContext: number of context variables does not match the script code" );
	}

	// actually store how many contexts have been saved
	if (pBuffer != NULL)
	{
		*((SWORD *)pBuffer) = (SWORD)numContext;
		endian_sword((SWORD*)pBuffer);
	}
	*pSize = size;

	return true;
}
Exemplo n.º 6
0
// save a list of triggers
static BOOL eventSaveTriggerList(ACTIVE_TRIGGER *psList, char *pBuffer, UDWORD *pSize)
{
	ACTIVE_TRIGGER		*psCurr;
	UDWORD				size;
	char				*pPos;
	SDWORD				numTriggers, context;

	size = 0;
	pPos = pBuffer;

	// reserve some space for the number of triggers
	if (pBuffer != NULL)
	{
		pPos += sizeof(SDWORD);
	}
	size += sizeof(SDWORD);

	numTriggers = 0;
	for(psCurr = psList; psCurr != NULL; psCurr = psCurr->psNext)
	{
		numTriggers += 1;

		if (pBuffer != NULL)
		{
			*((UDWORD*)pPos) = psCurr->testTime;
			endian_udword((UDWORD*)pPos);

			pPos += sizeof(UDWORD);
			if (!eventGetContextIndex(psCurr->psContext, &context))
			{
				debug( LOG_FATAL, "eventSaveTriggerList: couldn't find context" );
				abort();
				return false;
			}
			*((SWORD*)pPos) = (SWORD)context;
			endian_sword((SWORD*)pPos);
			pPos += sizeof(SWORD);
			*((SWORD*)pPos) = psCurr->type;
			endian_sword((SWORD*)pPos);
			pPos += sizeof(SWORD);
			*((SWORD*)pPos) = psCurr->trigger;
			endian_sword((SWORD*)pPos);
			pPos += sizeof(SWORD);
			*((UWORD*)pPos) = psCurr->event;
			endian_uword((UWORD*)pPos);
			pPos += sizeof(UWORD);
			*((UWORD*)pPos) = psCurr->offset;
			endian_uword((UWORD*)pPos);
			pPos += sizeof(UWORD);
		}
		size += sizeof(UDWORD) + sizeof(SWORD)*3 + sizeof(UWORD)*2;
	}
	if (pBuffer != NULL)
	{
		*((SDWORD*)pBuffer) = numTriggers;
		endian_sdword((SDWORD*)pBuffer);
	}

	*pSize = size;

	return true;
}
Exemplo n.º 7
0
// load the context information for the script system
static BOOL eventLoadContext(const SDWORD version, char *pBuffer, UDWORD *pSize, BOOL bHashed)
{
	UDWORD				size, valSize,stringLen;
	SDWORD				numVars, i, numContext, context;
	SCRIPT_CONTEXT		*psCCont;
	INTERP_TYPE			type;
	SCR_VAL_LOAD		loadFunc;
	char				*pPos;
	char				*pScriptID = NULL;
	UDWORD				hashedName;
	SCRIPT_CODE			*psCode;
	CONTEXT_RELEASE			release;
	INTERP_VAL			*psVal, data;

	size = 0;
	pPos = pBuffer;

	// get the number of contexts in the save file
	endian_sword((SWORD*)pPos);
	numContext = *((SWORD *)pPos);
	pPos += sizeof(SWORD);
	size += sizeof(SWORD);

	// go through the contexts
	for(context=0; context < numContext; context += 1)
	{
	    if(bHashed) {
    		endian_udword((UDWORD*)pPos);
    		hashedName = *((UDWORD*)pPos);
    		psCode = (SCRIPT_CODE*)resGetDataFromHash("SCRIPT", hashedName);
    		pPos += sizeof(UDWORD);
	    } else {
    		// get the script code
    		pScriptID = (char *)pPos;
    		psCode = (SCRIPT_CODE*)resGetData("SCRIPT", pScriptID);
    		pPos += strlen(pScriptID) + 1;
    	}
		// check the number of variables
		endian_sword((SWORD*)pPos);
   		numVars = psCode->numGlobals + psCode->arraySize;
        
		if (numVars != *((SWORD*)pPos))
		{
			ASSERT(false, "Context %d of %d: Number of context variables (%d) does not match the script code (%d)", 
			       context, numContext, numVars, *((SWORD*)pPos));
			return false;
		}
		pPos += sizeof(SWORD);

		release = (CONTEXT_RELEASE)*pPos;
		pPos += sizeof(UBYTE);

		// create the context
		if (!eventNewContext(psCode, release, &psCCont))
		{
			return false;
		}

		// bit of a hack this - note the id of the context to link it to the triggers
		psContList->id = (SWORD)context;

        if(bHashed) {
            size += sizeof(UDWORD) + sizeof(SWORD) + sizeof(UBYTE);
        } else {
		    size += strlen(pScriptID) + 1 + sizeof(SWORD) + sizeof(UBYTE);
		}

		// set the context variables
		for(i=0; i < numVars; i+= 1)
		{
			// get the variable type
			endian_sword((SWORD*)pPos);
			type = (INTERP_TYPE) *((SWORD*)pPos);
			pPos += sizeof(SWORD);
			size += sizeof(SWORD);

			// get the variable value
			if (type < VAL_USERTYPESTART)
			{
				data.type = type;

				endian_udword((UDWORD*)pPos);

				switch (type) {
				case VAL_BOOL:
					data.v.bval = *((BOOL*)pPos);
					pPos += sizeof(BOOL);
					size += sizeof(BOOL);
					break;
				case VAL_FLOAT:
					data.v.fval = *((float*)pPos);
					pPos += sizeof(float);
					size += sizeof(float);
					break;
				case VAL_INT:
				case VAL_TRIGGER:
				case VAL_EVENT:
				case VAL_VOID:
				case VAL_OPCODE:
				case VAL_PKOPCODE:
					data.v.ival = *((UDWORD *)pPos);
					pPos += sizeof(UDWORD);
					size += sizeof(UDWORD);
					break;
				case VAL_STRING:
					data.v.sval = (char*)malloc(MAXSTRLEN);
					strcpy(data.v.sval, "\0");

					stringLen = *((UDWORD *)pPos);	//read string length
					
					pPos += sizeof(UDWORD);
					size += sizeof(UDWORD);

					//load string
					if(stringLen > 0)
					{
						strlcpy(data.v.sval, (char *)pPos, MIN(stringLen + 1, MAXSTRLEN));
						pPos += stringLen;
						size += stringLen;
					}
					break;
				case VAL_OBJ_GETSET:
/* FIXME: saving pointer on disk! */
					data.v.pObjGetSet = *((SCRIPT_VARFUNC*)pPos);
					pPos += sizeof(SCRIPT_VARFUNC);
					size += sizeof(SCRIPT_VARFUNC);
					break;
				case VAL_FUNC_EXTERN:
/* FIXME: saving pointer on disk! */
					data.v.pFuncExtern = *((SCRIPT_FUNC*)pPos);
					pPos += sizeof(SCRIPT_FUNC);
					size += sizeof(SCRIPT_FUNC);
					break;
				default:
					ASSERT( false, "eventLoadContext: invalid internal type" );
				}

				// set the value in the context
				if (!eventSetContextVar(psCCont, (UDWORD)i, &data))
				{
					debug( LOG_FATAL, "eventLoadContext: couldn't set variable value" );
					abort();
					return false;
				}
			}
			else
			{
				// user defined type
				loadFunc = asScrTypeTab[type - VAL_USERTYPESTART].loadFunc;

				ASSERT( loadFunc != NULL,
					"eventLoadContext: no load function for type %d\n", type );

				endian_uword((UWORD*)pPos);
				valSize = *((UWORD *)pPos);

				pPos += sizeof(UWORD);
				size += sizeof(UWORD);

				// get the value pointer so that the loadFunc can write directly
				// into the variables data space.
				if (!eventGetContextVal(psCCont, (UDWORD)i, &psVal))
				{
					debug( LOG_FATAL, "eventLoadContext: couldn't find variable in context" );
					abort();
					return false;
				}

				if (!loadFunc(version, psVal, pPos, valSize))
				{
					debug( LOG_FATAL, "eventLoadContext: couldn't get variable value" );
					abort();
					return false;
				}

				pPos += valSize;
				size += valSize;
			}
		}
	}

	*pSize = size;

	return true;
}
Exemplo n.º 8
0
/// default value load routine
bool scrValDefLoad(SDWORD version, INTERP_VAL *psVal, char *pBuffer, UDWORD size)
{
	char			*pPos;
	DROID			*psCDroid;
	SDWORD			index, members, savedMembers;
	UDWORD			id;
	LEVEL_DATASET	*psLevel;
	DROID_GROUP		*psGroup = NULL;
	const char              *pName;
	bool			bObjectDefined;

	switch ((unsigned)psVal->type)  // Unsigned cast to suppress compiler warnings due to enum abuse.
	{
	case ST_INTMESSAGE:
		if ((size == 1) &&
			(*pBuffer == 0))
		{
			psVal->v.oval = NULL;
		}
		else
		{
			psVal->v.oval = (void*)getViewData(pBuffer);
			if (psVal->v.oval == NULL)
			{
				return false;
			}
		}
		break;
	case ST_BASEOBJECT:
	case ST_DROID:
	case ST_STRUCTURE:
	case ST_FEATURE:
		id = *((UDWORD *)pBuffer);
		endian_udword(&id);

		if (id == UDWORD_MAX)
		{
			psVal->v.oval = NULL;
		}
		else
		{
			psVal->v.oval = (void*)getBaseObjFromId(id);
			if (!psVal->v.oval)
			{
				debug(LOG_ERROR, "Could not find object id %d", id);
			}
		}
		break;
	case ST_BASESTATS:
	case ST_COMPONENT:
		break;
	case ST_STRUCTURESTAT:
		index = getStructStatFromName(pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find structure stat %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_FEATURESTAT:
		index = getFeatureStatFromName(pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find feature stat %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_BODY:
		index = getCompFromResName(COMP_BODY, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find body component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_PROPULSION:
		index = getCompFromResName(COMP_PROPULSION, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find propulsion component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_ECM:
		index = getCompFromResName(COMP_ECM, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find ECM component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_SENSOR:
		index = getCompFromResName(COMP_SENSOR, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find sensor component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_CONSTRUCT:
		index = getCompFromResName(COMP_CONSTRUCT, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find constructor component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_WEAPON:
		index = getCompFromResName(COMP_WEAPON, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find weapon %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_REPAIR:
		index = getCompFromResName(COMP_REPAIRUNIT, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find repair component %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_BRAIN:
		index = getCompFromResName(COMP_BRAIN, pBuffer);
		if (index == -1)
		{
			debug( LOG_FATAL, "scrValDefLoad: couldn't find repair brain %s", pBuffer );
			abort();
			index = 0;
		}
		psVal->v.ival = index;
		break;
	case ST_TEMPLATE:
		id = *((UDWORD *)pBuffer);
		endian_udword(&id);

		if (id == UDWORD_MAX)
		{
			psVal->v.oval = NULL;
		}
		else
		{
			psVal->v.oval = (void*)IdToTemplate(id, ANYPLAYER);
			if ((DROID_TEMPLATE*)(psVal->v.oval) == NULL)
			{
				debug( LOG_FATAL, "scrValDefLoad: couldn't find template id %d", id );
				abort();
			}
		}
		break;
	case ST_TEXTSTRING:
		{
			const char* str;
			char* idStr;
			uint16_t len;

			if (size < sizeof(len))
			{
				debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len)), (unsigned int)size);
				return false;
			}

			len = *((uint16_t*)pBuffer);
			endian_uword(&len);

			if (size < sizeof(len) + len)
			{
				debug(LOG_ERROR, "Data size is too small, %u is expected, but %u is provided", (unsigned int)(sizeof(len) + len), (unsigned int)size);
				return false;
			}

			if (len == 0)
			{
				psVal->v.sval = NULL;
				return true;
			}

			idStr = (char *)malloc(len);
			if (!idStr)
			{
				debug(LOG_ERROR, "Out of memory (tried to allocate %u bytes)", (unsigned int)len);
				// Don't abort() here, as this might be the result from a bad "len" field in the data
				return false;
			}

			memcpy(idStr, pBuffer + sizeof(len), len);

			if (idStr[len - 1] != '\0')
			{
				debug(LOG_WARNING, "Non-NUL terminated string encountered!");
			}
			idStr[len - 1] = '\0';

			str = strresGetString(psStringRes, idStr);
			if (!str)
			{
				debug(LOG_ERROR, "Couldn't find string with id \"%s\"", idStr);
				free(idStr);
				return false;
			}
			free(idStr);

			psVal->v.sval = strdup(str);
			if (!psVal->v.sval)
			{
				debug(LOG_FATAL, "Out of memory");
				abort();
				return false;
			}
		}
		break;
	case ST_LEVEL:
		if ((size == 1) &&
			(*pBuffer == 0))
		{
			psVal->v.sval = '\0';
		}
		else
		{
			psLevel = levFindDataSet(pBuffer);
			if (psLevel == NULL)
			{
				debug( LOG_FATAL, "scrValDefLoad: couldn't find level dataset %s", pBuffer );
				abort();
			}
			psVal->v.sval = psLevel->pName;
		}
		break;
	case ST_RESEARCH:
		if ((size == 1) &&
			(*pBuffer == 0))
		{
			psVal->v.oval = NULL;
		}
		else
		{
			psVal->v.oval = (void*)getResearch(pBuffer);
			if (psVal->v.oval == NULL)
			{
				debug( LOG_FATAL, "scrValDefLoad: couldn't find research %s", pBuffer );
				abort();
			}
		}
		break;
	case ST_GROUP:
		bObjectDefined = true;

		if (psVal->v.oval == NULL)
		{
			DROID_GROUP *tmp = grpCreate();
			tmp->add(NULL);
			psVal->v.oval = tmp;
		}

		pPos = pBuffer;

		if (version < 2)
		{
			members = size / sizeof(UDWORD);
		}
		else if (version < 3)
		{
			members = (size - sizeof(SDWORD)*4) / sizeof(UDWORD);
		}
		else
		{
			members = (size - sizeof(SDWORD)*6) / sizeof(UDWORD);

			// get saved group member count/nullpointer flag
			endian_sdword((SDWORD*)pPos);
			bObjectDefined = ( *((SDWORD *)pPos) != UNALLOCATED_OBJECT );

			if(bObjectDefined)
			{
				savedMembers = *((SDWORD *)pPos);	// get number of saved group members

				ASSERT(savedMembers == members, "scrValDefLoad: calculated and saved group member count did not match." );
			}
			pPos += sizeof(SDWORD);
		}

		// make sure group was allocated when it was saved (relevant starting from version 3)
		if( version < 3 || bObjectDefined )
		{
			if (version >= 2)
			{
				// load the retreat data
				psGroup = (DROID_GROUP*)(psVal->v.oval);
				endian_sdword((SDWORD*)pPos);
				psGroup->sRunData.sPos.x = *((SDWORD *)pPos);
				pPos += sizeof(SDWORD);
				endian_sdword((SDWORD*)pPos);
				psGroup->sRunData.sPos.y = *((SDWORD *)pPos);
				pPos += sizeof(SDWORD);
				endian_sdword((SDWORD*)pPos);
				psGroup->sRunData.forceLevel = (UBYTE)(*((SDWORD *)pPos));
				pPos += sizeof(SDWORD);
				endian_sdword((SDWORD*)pPos);
				psGroup->sRunData.leadership = (UBYTE)(*((SDWORD *)pPos));
				pPos += sizeof(SDWORD);
			}
			if (version >= 3)
			{
				endian_sdword((SDWORD*)pPos);
				psGroup->sRunData.healthLevel = (UBYTE)(*((SDWORD *)pPos));
				pPos += sizeof(SDWORD);
			}

			// load the droids
			while (members > 0)
			{
				endian_udword((UDWORD*)pPos);
				id = *((UDWORD *) pPos);
				psCDroid = (DROID *)getBaseObjFromId(id);
				if (!psCDroid)
				{
					debug(LOG_ERROR, "Could not find object id %d", id);
				}
				else
				{
					((DROID_GROUP*)(psVal->v.oval))->add(psCDroid);
				}

				pPos += sizeof(UDWORD);
				members -= 1;
			}
		}
		else		// a group var was unallocated during saving
		{
			pPos += sizeof(UWORD);
		}
		break;
	case ST_SOUND:
		// find audio id

		// don't use sound if it's disabled
		if (audio_Disabled())
		{
			psVal->v.ival = NO_SOUND;
			break;
		}

		pName = pBuffer;
		index = audio_GetTrackID( pName );
		if (index == SAMPLE_NOT_FOUND)
		{
			// find empty id and set track vals
			index = audio_SetTrackVals(pName, false, 100, 1800);
			if (!index)			//this is a NON fatal error.
			{
				// We can't find filename of the sound for some reason.
				debug(LOG_ERROR, "Sound ID not available %s not found", pName);
				break;
			}
		}
		psVal->v.ival = index;
		break;
	case ST_STRUCTUREID:
	case ST_DROIDID:
	default:
		// just set the contents directly
		psVal->v.ival = *((SDWORD *)pBuffer);
		endian_sdword(&psVal->v.ival);
		break;
	}

	return true;
}
Exemplo n.º 9
0
// default value save routine
//TODO: use union
bool scrValDefSave(INTERP_VAL *psVal, char *pBuffer, UDWORD *pSize)
{
	VIEWDATA	*psIntMessage;
	const char	*pName;
	RESEARCH	*psResearch;
	char		*pPos;
	DROID		*psCDroid;

	switch ((unsigned)psVal->type)  // Unsigned cast to suppress compiler warnings due to enum abuse.
	{
	case ST_INTMESSAGE:
		// save the name
		psIntMessage = (VIEWDATA *)psVal->v.oval;
		if (psIntMessage != NULL)
		{
			if (pBuffer)
			{
				strcpy(pBuffer, psIntMessage->pName);
			}
			*pSize = strlen(psIntMessage->pName)+1;
		}
		else
		{
			if (pBuffer)
			{
				*pBuffer = '\0';
			}
			*pSize = 1;
		}
		break;
	case ST_BASEOBJECT:
	case ST_DROID:
	case ST_STRUCTURE:
	case ST_FEATURE:
		// just save the id
		if (pBuffer)
		{
			if (psVal->v.oval == NULL || ((BASE_OBJECT *)psVal->v.oval)->died > NOT_CURRENT_LIST)
			{
				*((UDWORD*)pBuffer) = UDWORD_MAX;
			}
			else
			{
				*((UDWORD*)pBuffer) = ((BASE_OBJECT *)psVal->v.oval)->id;
			}
			endian_udword((UDWORD*)pBuffer);
		}
		*pSize = sizeof(UDWORD);
		break;
	case ST_BASESTATS:
	case ST_COMPONENT:
	case ST_FEATURESTAT:
	case ST_STRUCTURESTAT:
	case ST_BODY:
	case ST_PROPULSION:
	case ST_ECM:
	case ST_SENSOR:
	case ST_CONSTRUCT:
	case ST_WEAPON:
	case ST_REPAIR:
	case ST_BRAIN:
		pName = scrGetStatName(psVal->type, psVal->v.ival);
		if (pName != NULL)
		{
			if (pBuffer)
			{
				strcpy(pBuffer, pName);
			}
			*pSize = strlen(pName) + 1;
		}
		else
		{
			return false;
		}
		break;
	case ST_TEMPLATE:
		if (pBuffer)
		{
			if (psVal->v.oval == NULL)
			{
				*((UDWORD*)pBuffer) = UDWORD_MAX;
			}
			else
			{
				*((UDWORD*)pBuffer) = ((DROID_TEMPLATE *)psVal->v.oval)->multiPlayerID;
			}
			endian_udword((UDWORD*)pBuffer);
		}
		*pSize = sizeof(UDWORD);
		break;
	case ST_TEXTSTRING:
	{
		const char * const idStr = psVal->v.sval ? strresGetIDfromString(psStringRes, psVal->v.sval) : NULL;
		uint16_t len = idStr ? strlen(idStr) + 1 : 0;

		if (pBuffer)
		{
			*((uint16_t*)pBuffer) = len;
			endian_uword((uint16_t*)pBuffer);

			memcpy(pBuffer + sizeof(len), idStr, len);
		}
		*pSize = sizeof(len) + len;
		break;
	}
	case ST_LEVEL:
		if (psVal->v.sval != NULL)
		{
			if (pBuffer)
			{
				strcpy(pBuffer, psVal->v.sval);
			}
			*pSize = strlen(psVal->v.sval)+1;
		}
		else
		{
			if (pBuffer)
			{
				*pBuffer = '\0';
			}
			*pSize = 1;
		}
		break;
	case ST_RESEARCH:
		psResearch = (RESEARCH *)psVal->v.oval;
		if (psResearch != NULL)
		{
			if (pBuffer)
			{
				strcpy(pBuffer, psResearch->pName);
			}
			*pSize = strlen(psResearch->pName)+1;
		}
		else
		{
			if (pBuffer)
			{
				*pBuffer = '\0';
			}
			*pSize = 1;
		}
		break;
	case ST_GROUP:
	{
		DROID_GROUP* const psGroup = (DROID_GROUP *)psVal->v.oval;
		const int members = psGroup ? psGroup->getNumMembers() : UNALLOCATED_OBJECT;

		if (pBuffer)
		{
			pPos = pBuffer;

			*((SDWORD *)pPos) = members;
			endian_sdword((SDWORD*)pPos);
			pPos += sizeof(SDWORD);

			if (psGroup)
			{
				// store the run data
				*((SDWORD *)pPos) = psGroup->sRunData.sPos.x;
				endian_sdword((SDWORD*)pPos);
				pPos += sizeof(SDWORD);
				*((SDWORD *)pPos) = psGroup->sRunData.sPos.y;
				endian_sdword((SDWORD*)pPos);
				pPos += sizeof(SDWORD);
				*((SDWORD *)pPos) = psGroup->sRunData.forceLevel;
				endian_sdword((SDWORD*)pPos);
				pPos += sizeof(SDWORD);
				*((SDWORD *)pPos) = psGroup->sRunData.leadership;
				endian_sdword((SDWORD*)pPos);
				pPos += sizeof(SDWORD);
				*((SDWORD *)pPos) = psGroup->sRunData.healthLevel;
				endian_sdword((SDWORD*)pPos);
				pPos += sizeof(SDWORD);

				// now store the droids
				for (psCDroid = psGroup->psList; psCDroid; psCDroid = psCDroid->psGrpNext)
				{
					checkValidId(psCDroid->id);

					*((UDWORD *)pPos) = psCDroid->id;
					endian_udword((UDWORD*)pPos);

					pPos += sizeof(UDWORD);
				}
			}
		}

		if (!psGroup)
		{
			*pSize = sizeof(SDWORD);
		}
		else
		{
			*pSize = sizeof(SDWORD) + sizeof(UDWORD) * members + sizeof(SDWORD) * 5;	// members + runData
		}
		break;
	}
	case ST_SOUND:
		if(psVal->v.ival)
		{
			// can also return NULL
			pName = sound_GetTrackName((UDWORD)psVal->v.ival);
		}
		else
		{
			pName = NULL;
		}
		if (pName == NULL)
		{
			debug(LOG_WARNING, "scrValDefSave: couldn't get sound track name");
			// just save an empty string
			pName = "";
		}
		if (pBuffer)
		{
			strcpy(pBuffer, pName);
		}
		*pSize = strlen(pName) + 1;
		break;
	case ST_STRUCTUREID:
	case ST_DROIDID:
		// just save the variable contents directly
		if (pBuffer)
		{
			*((UDWORD *)pBuffer) = psVal->v.ival;
			endian_udword((UDWORD*)pBuffer);
		}
		*pSize = sizeof(UDWORD);
		break;
	default:
		ASSERT( false, "scrValDefSave: unknown script variable type for save" );
		break;
	}
	return true;
}