⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xvm.cpp

📁 < Game Script Mastery>> source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			g_Scripts [ iCurrScriptIndex ].HostAPICallTable.ppstrCalls = NULL;
		}

        // ---- Initialize the host API

        for ( int iCurrHostAPIFunc = 0; iCurrHostAPIFunc < MAX_HOST_API_SIZE; ++ iCurrHostAPIFunc )
        {
            g_HostAPI [ iCurrHostAPIFunc ].iIsActive = FALSE;
            g_HostAPI [ iCurrHostAPIFunc ].pstrName = NULL;
        }

		// ---- Set up the threads

        g_iCurrThreadMode = THREAD_MODE_MULTI;
		g_iCurrThread = 0;
	}

	/******************************************************************************************
	*
	*	XS_ShutDown ()
	*
	*	Shuts down the runtime environment.
	*/

	void XS_ShutDown ()
	{
		// ---- Unload any scripts that may still be in memory

		for ( int iCurrScriptIndex = 0; iCurrScriptIndex < MAX_THREAD_COUNT; ++ iCurrScriptIndex )
            XS_UnloadScript ( iCurrScriptIndex );

        // ---- Free the host API's function name strings

        for ( int iCurrHostAPIFunc = 0; iCurrHostAPIFunc < MAX_HOST_API_SIZE; ++ iCurrHostAPIFunc )
            if ( g_HostAPI [ iCurrHostAPIFunc ].pstrName )
                free ( g_HostAPI [ iCurrHostAPIFunc ].pstrName );
	}

	/******************************************************************************************
	*
	*	XS_LoadScript ()
	*
	*	Loads an .XSE file into memory.
	*/

	int XS_LoadScript ( char * pstrFilename, int & iThreadIndex, int iThreadTimeslice )
	{
		// ---- Find the next free script index

		int iFreeThreadFound = FALSE;
		for ( int iCurrThreadIndex = 0; iCurrThreadIndex < MAX_THREAD_COUNT; ++ iCurrThreadIndex )
		{
			// If the current thread is not in use, use it

			if ( ! g_Scripts [ iCurrThreadIndex ].iIsActive )
			{
				iThreadIndex = iCurrThreadIndex;
				iFreeThreadFound = TRUE;
				break;
			}
		}

		// If a thread wasn't found, return an out of threads error

		if ( ! iFreeThreadFound )
			return XS_LOAD_ERROR_OUT_OF_THREADS;

        // ---- Open the input file

        FILE * pScriptFile;
        if ( ! ( pScriptFile = fopen ( pstrFilename, "rb" ) ) )
            return XS_LOAD_ERROR_FILE_IO;

        // ---- Read the header

        // Create a buffer to hold the file's ID string (4 bytes + 1 null terminator = 5)

		char * pstrIDString;
        if ( ! ( pstrIDString = ( char * ) malloc ( 5 ) ) )
			return XS_LOAD_ERROR_OUT_OF_MEMORY;

		// Read the string (4 bytes) and append a null terminator

        fread ( pstrIDString, 4, 1, pScriptFile );
		pstrIDString [ strlen ( XSE_ID_STRING ) ] = '\0';

        // Compare the data read from the file to the ID string and exit on an error if they don't
        // match

        if ( strcmp ( pstrIDString, XSE_ID_STRING ) != 0 )
            return XS_LOAD_ERROR_INVALID_XSE;

        // Free the buffer

        free ( pstrIDString );

		// Read the script version (2 bytes total)

		int iMajorVersion = 0,
			iMinorVersion = 0;

		fread ( & iMajorVersion, 1, 1, pScriptFile );
		fread ( & iMinorVersion, 1, 1, pScriptFile );

		// Validate the version, since this prototype only supports version 0.8 scripts

		if ( iMajorVersion != 0 || iMinorVersion != 8 )
			return XS_LOAD_ERROR_UNSUPPORTED_VERS;

		// Read the stack size (4 bytes)

		fread ( & g_Scripts [ iThreadIndex ].Stack.iSize, 4, 1, pScriptFile );

		// Check for a default stack size request

		if ( g_Scripts [ iThreadIndex ].Stack.iSize == 0 )
			g_Scripts [ iThreadIndex ].Stack.iSize = DEF_STACK_SIZE;

		// Allocate the runtime stack

        int iStackSize = g_Scripts [ iThreadIndex ].Stack.iSize;
		if ( ! ( g_Scripts [ iThreadIndex ].Stack.pElmnts = ( Value * ) malloc ( iStackSize * sizeof ( Value ) ) ) )
			return XS_LOAD_ERROR_OUT_OF_MEMORY;

        // Read the global data size (4 bytes)

        fread ( & g_Scripts [ iThreadIndex ].iGlobalDataSize, 4, 1, pScriptFile );

		// Check for presence of _Main () (1 byte)

		fread ( & g_Scripts [ iThreadIndex ].iIsMainFuncPresent, 1, 1, pScriptFile );

        // Read _Main ()'s function index (4 bytes)

        fread ( & g_Scripts [ iThreadIndex ].iMainFuncIndex, 4, 1, pScriptFile );

        // Read the priority type (1 byte)

        int iPriorityType = 0;
        fread ( & iPriorityType, 1, 1, pScriptFile );

        // Read the user-defined priority (4 bytes)

        fread ( & g_Scripts [ iThreadIndex ].iTimesliceDur, 4, 1, pScriptFile );

        // Override the script-specified priority if necessary

        if ( iThreadTimeslice != XS_THREAD_PRIORITY_USER )
            iPriorityType = iThreadTimeslice;

        // If the priority type is not set to user-defined, fill in the appropriate timeslice
        // duration

        switch ( iPriorityType )
        {
            case XS_THREAD_PRIORITY_LOW:
                g_Scripts [ iThreadIndex ].iTimesliceDur = THREAD_PRIORITY_DUR_LOW;
                break;

            case XS_THREAD_PRIORITY_MED:
                g_Scripts [ iThreadIndex ].iTimesliceDur = THREAD_PRIORITY_DUR_MED;
                break;

            case XS_THREAD_PRIORITY_HIGH:
                g_Scripts [ iThreadIndex ].iTimesliceDur = THREAD_PRIORITY_DUR_HIGH;
                break;
        }

		// ---- Read the instruction stream

		// Read the instruction count (4 bytes)

		fread ( & g_Scripts [ iThreadIndex ].InstrStream.iSize, 4, 1, pScriptFile );

		// Allocate the stream

		if ( ! ( g_Scripts [ iThreadIndex ].InstrStream.pInstrs = ( Instr * ) malloc ( g_Scripts [ iThreadIndex ].InstrStream.iSize * sizeof ( Instr ) ) ) )
			return XS_LOAD_ERROR_OUT_OF_MEMORY;

		// Read the instruction data

		for ( int iCurrInstrIndex = 0; iCurrInstrIndex < g_Scripts [ iThreadIndex ].InstrStream.iSize; ++ iCurrInstrIndex )
		{
			// Read the opcode (2 bytes)

			g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpcode = 0;
			fread ( & g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpcode, 2, 1, pScriptFile );

			// Read the operand count (1 byte)

			g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount = 0;
			fread ( & g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount, 1, 1, pScriptFile );

			int iOpCount = g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount;

			// Allocate space for the operand list in a temporary pointer

			Value * pOpList;
			if ( ! ( pOpList = ( Value * ) malloc ( iOpCount * sizeof ( Value ) ) ) )
				return XS_LOAD_ERROR_OUT_OF_MEMORY;

			// Read in the operand list (N bytes)

			for ( int iCurrOpIndex = 0; iCurrOpIndex < iOpCount; ++ iCurrOpIndex )
			{
				// Read in the operand type (1 byte)

				pOpList [ iCurrOpIndex ].iType = 0;
				fread ( & pOpList [ iCurrOpIndex ].iType, 1, 1, pScriptFile );

				// Depending on the type, read in the operand data

				switch ( pOpList [ iCurrOpIndex ].iType )
				{
					// Integer literal

					case OP_TYPE_INT:
						fread ( & pOpList [ iCurrOpIndex ].iIntLiteral, sizeof ( int ), 1, pScriptFile );
						break;

					// Floating-point literal

					case OP_TYPE_FLOAT:
						fread ( & pOpList [ iCurrOpIndex ].fFloatLiteral, sizeof ( float ), 1, pScriptFile );
						break;

					// String index

					case OP_TYPE_STRING:

						// Since there's no field in the Value structure for string table
						// indices, read the index into the integer literal field and set
						// its type to string index

						fread ( & pOpList [ iCurrOpIndex ].iIntLiteral, sizeof ( int ), 1, pScriptFile );
						pOpList [ iCurrOpIndex ].iType = OP_TYPE_STRING;
						break;

					// Instruction index

					case OP_TYPE_INSTR_INDEX:
						fread ( & pOpList [ iCurrOpIndex ].iInstrIndex, sizeof ( int ), 1, pScriptFile );
						break;

					// Absolute stack index

					case OP_TYPE_ABS_STACK_INDEX:
						fread ( & pOpList [ iCurrOpIndex ].iStackIndex, sizeof ( int ), 1, pScriptFile );
						break;

					// Relative stack index

					case OP_TYPE_REL_STACK_INDEX:
						fread ( & pOpList [ iCurrOpIndex ].iStackIndex, sizeof ( int ), 1, pScriptFile );
						fread ( & pOpList [ iCurrOpIndex ].iOffsetIndex, sizeof ( int ), 1, pScriptFile );
						break;

					// Function index

					case OP_TYPE_FUNC_INDEX:
						fread ( & pOpList [ iCurrOpIndex ].iFuncIndex, sizeof ( int ), 1, pScriptFile );
						break;

					// Host API call index

					case OP_TYPE_HOST_API_CALL_INDEX:
						fread ( & pOpList [ iCurrOpIndex ].iHostAPICallIndex, sizeof ( int ), 1, pScriptFile );
						break;

					// Register

					case OP_TYPE_REG:
						fread ( & pOpList [ iCurrOpIndex ].iReg, sizeof ( int ), 1, pScriptFile );
						break;
				}
			}

			// Assign the operand list pointer to the instruction stream

			g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].pOpList = pOpList;
		}

		// ---- Read the string table

		// Read the table size (4 bytes)

		int iStringTableSize;
		fread ( & iStringTableSize, 4, 1, pScriptFile );

		// If the string table exists, read it

		if ( iStringTableSize )
		{
			// Allocate a string table of this size

			char ** ppstrStringTable;
			if ( ! ( ppstrStringTable = ( char ** ) malloc ( iStringTableSize * sizeof ( char * ) ) ) )
				return XS_LOAD_ERROR_OUT_OF_MEMORY;

			// Read in each string

			for ( int iCurrStringIndex = 0; iCurrStringIndex < iStringTableSize; ++ iCurrStringIndex )
			{
				// Read in the string size (4 bytes)

				int iStringSize;
				fread ( & iStringSize, 4, 1, pScriptFile );

				// Allocate space for the string plus a null terminator

				char * pstrCurrString;
				if ( ! ( pstrCurrString = ( char * ) malloc ( iStringSize + 1 ) ) )
					return XS_LOAD_ERROR_OUT_OF_MEMORY;

				// Read in the string data (N bytes) and append the null terminator

				fread ( pstrCurrString, iStringSize, 1, pScriptFile );
				pstrCurrString [ iStringSize ] = '\0';

				// Assign the string pointer to the string table

				ppstrStringTable [ iCurrStringIndex ] = pstrCurrString;
			}

			// Run through each operand in the instruction stream and assign copies of string
			// operand's corresponding string literals

			for ( int iCurrInstrIndex = 0; iCurrInstrIndex < g_Scripts [ iThreadIndex ].InstrStream.iSize; ++ iCurrInstrIndex )
			{
				// Get the instruction's operand count and a copy of it's operand list

				int iOpCount = g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].iOpCount;
				Value * pOpList = g_Scripts [ iThreadIndex ].InstrStream.pInstrs [ iCurrInstrIndex ].pOpList;

				// Loop through each operand

				for ( int iCurrOpIndex = 0; iCurrOpIndex < iOpCount; ++ iCurrOpIndex )
				{
					// If the operand is a string index, make a local copy of it's corresponding
					// string in the table

					if ( pOpList [ iCurrOpIndex ].iType == OP_TYPE_STRING )
					{
						// Get the string index from the operand's integer literal field

						int iStringIndex = pOpList [ iCurrOpIndex ].iIntLiteral;

						// Allocate a new string to hold a copy of the one in the table

						char * pstrStringCopy;
						if ( ! ( pstrStringCopy = ( char * ) malloc ( strlen ( ppstrStringTable [ iStringIndex ] ) + 1 ) ) )
							return XS_LOAD_ERROR_OUT_OF_MEMORY;

						// Make a copy of the string

						strcpy ( pstrStringCopy, ppstrStringTable [ iStringIndex ] );

						// Save the string pointer in the operand list

						pOpList [ iCurrOpIndex ].pstrStringLiteral = pstrStringCopy;
					}
				}
			}

			// ---- Free the original strings

			for ( iCurrStringIndex = 0; iCurrStringIndex < iStringTableSize; ++ iCurrStringIndex )
				free ( ppstrStringTable [ iCurrStringIndex ] );

			// ---- Free the string table itself

			free ( ppstrStringTable );
		}

		// ---- Read the function table

		// Read the function count (4 bytes)

		int iFuncTableSize;
		fread ( & iFuncTableSize, 4, 1, pScriptFile );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -