📄 xvm.cpp
字号:
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 + -