Files
int2ssl/FalloutScriptDecompile.cpp
T

881 lines
30 KiB
C++
Raw Normal View History

2015-02-13 16:59:11 +03:00
#include "stdafx.h"
#include "FalloutScript.h"
#include "ObjectAttributes.h"
2015-02-15 16:16:45 +03:00
#include "Utility.h"
2015-02-13 16:59:11 +03:00
2015-02-13 23:30:41 +03:00
#include <iostream>
2015-02-15 16:16:45 +03:00
#include <algorithm>
2015-02-13 23:30:41 +03:00
2015-02-13 16:59:11 +03:00
// Globals
2015-02-15 16:59:52 +03:00
extern bool g_bIgnoreWrongNumOfArgs;
extern bool g_bInsOmittedArgsBackward;
2015-02-14 14:38:14 +03:00
2015-02-13 16:59:11 +03:00
void CFalloutScript::InitDefinitions()
{
2015-02-14 13:39:47 +03:00
ULONG ulNameOffset;
INT_PTR nObjectIndex;
2015-02-15 16:16:45 +03:00
std::string c_strGlobalVarTemplate("GVar%u");
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
m_Definitions.RemoveAll();
2015-02-13 16:59:11 +03:00
2015-02-13 23:30:41 +03:00
for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++)
{
2015-02-14 13:39:47 +03:00
ulNameOffset = m_Namespace.GetOffsetByIndex(i);
2015-02-13 23:30:41 +03:00
if ((nObjectIndex = GetIndexOfProc(ulNameOffset)) != -1)
{
2015-02-14 13:39:47 +03:00
m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_PROCEDURE, 0, ULONG(nObjectIndex)));
}
2015-02-13 23:30:41 +03:00
else if ((nObjectIndex = GetIndexOfExportedVariable(ulNameOffset)) != -1)
{
2015-02-15 18:10:01 +03:00
uint16_t wOpcode = m_ExportedVarValue[nObjectIndex].GetOperator();
2015-02-14 23:18:15 +03:00
ULONG ulValue = m_ExportedVarValue[nObjectIndex].GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_EXPORT | wOpcode, ulValue));
}
}
2015-02-13 16:59:11 +03:00
2015-02-15 16:16:45 +03:00
m_GlobalVarsNames.resize(m_GlobalVar.GetSize());
2015-02-13 16:59:11 +03:00
2015-02-15 16:16:45 +03:00
for(INT_PTR i = 0; i < m_GlobalVarsNames.size(); i++)
2015-02-13 23:30:41 +03:00
{
2015-02-15 16:16:45 +03:00
m_GlobalVarsNames[i] = format(c_strGlobalVarTemplate, i);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::ProcessCode()
{
2015-02-14 13:39:47 +03:00
printf(" Intial reducing\n");
InitialReduce();
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
printf(" Building execution tree\n");
2015-02-13 22:31:52 +03:00
for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++)
{
2015-02-13 23:30:41 +03:00
printf(" Procedure: %d\n", i);
2015-02-14 23:18:15 +03:00
BuildTree(m_ProcBodies[i]);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
printf(" Extracting and reducing conditions\n");
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++)
{
if (m_ProcTable[i].m_ulType & P_CONDITIONAL)
{
2015-02-14 23:18:15 +03:00
ExtractAndReduceCondition(m_ProcBodies[i], m_Conditions[i], 0);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
for(INT_PTR j = 0; j < m_ProcBodies[i].GetSize(); j++)
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
if (m_ProcBodies[i][j].m_Opcode.GetOperator() == COpcode::O_CALL_CONDITION)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
CNodeArray Condition;
2015-02-14 23:18:15 +03:00
CNode node = m_ProcBodies[i][j].m_Arguments[0];
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() != COpcode::O_INTOP)
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid opcode for start address of condition\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
ULONG ulCondStartAddress = node.m_Opcode.GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
do
{
2015-02-14 23:18:15 +03:00
node = m_ProcBodies[i][j = NextNodeIndex(m_ProcBodies[i], j, -1)];
2015-02-14 14:38:14 +03:00
}
while(node.m_ulOffset != ulCondStartAddress);
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
j = NextNodeIndex(m_ProcBodies[i], j, -1); // For O_JMP opcode
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
ExtractAndReduceCondition(m_ProcBodies[i], Condition, j);
m_ProcBodies[i][j].m_Arguments[0] = Condition[0];
2015-02-14 13:39:47 +03:00
}
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
printf(" Setting borders of blocks\n");
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++)
{
2015-02-14 13:39:47 +03:00
printf(" Procedure: %d\r", i);
2015-02-14 23:18:15 +03:00
SetBordersOfBlocks(m_ProcBodies[i]);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
printf(" Renaming global variables\n");
TryRenameGlobalVariables();
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
printf(" Renaming imported variables\n");
TryRenameImportedVariables();
2015-02-13 16:59:11 +03:00
}
2015-02-13 23:09:21 +03:00
INT_PTR CFalloutScript::GetIndexOfProc(const char* lpszName)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
INT_PTR nResult = -1;
2015-02-15 16:16:45 +03:00
std::string strName(lpszName);
std::string strTestName;
2015-02-13 16:59:11 +03:00
2015-02-15 16:16:45 +03:00
std::transform(strName.begin(), strName.end(), strName.begin(), ::tolower);
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++)
{
2015-02-13 16:59:11 +03:00
strTestName = m_Namespace[m_ProcTable[i].m_ulNameOffset];
2015-02-15 16:16:45 +03:00
std::transform(strTestName.begin(), strTestName.end(), strTestName.begin(), ::tolower);
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (strTestName == strName)
{
2015-02-14 13:39:47 +03:00
nResult = i;
break;
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
return nResult;
2015-02-13 16:59:11 +03:00
}
INT_PTR CFalloutScript::GetIndexOfProc(ULONG ulNameOffset)
{
2015-02-14 13:39:47 +03:00
INT_PTR nResult = -1;
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++)
{
if (m_ProcTable[i].m_ulNameOffset == ulNameOffset)
{
2015-02-14 13:39:47 +03:00
nResult = i;
break;
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
return nResult;
2015-02-13 16:59:11 +03:00
}
INT_PTR CFalloutScript::GetIndexOfExportedVariable(ULONG ulNameOffset)
{
2015-02-14 13:39:47 +03:00
INT_PTR nResult = -1;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < m_ExportedVarValue.GetSize(); i += 2)
{
2015-02-14 23:18:15 +03:00
if (m_ExportedVarValue[i + 1].GetArgument() == ulNameOffset)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
nResult = i;
break;
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
return nResult;
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::SetExternalVariable(ULONG ulNameOffset)
{
2015-02-14 13:39:47 +03:00
CDefObject defObject;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (!m_Definitions.Lookup(ulNameOffset, defObject))
{
2015-02-14 13:39:47 +03:00
m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_IMPORT));
}
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::TryRenameGlobalVariables()
{
2015-02-14 13:39:47 +03:00
INT_PTR nNamesCount = m_Namespace.GetSize();
INT_PTR nDefinitionsCount = m_Definitions.GetSize();
INT_PTR nGlobalVarCount = m_GlobalVar.GetSize();
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
CDefObject defObject;
INT_PTR nGlobalVarIndex = 0;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (nNamesCount - nDefinitionsCount == nGlobalVarCount)
{
for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++)
{
if (!m_Definitions.Lookup(m_Namespace.GetOffsetByIndex(i), defObject))
{
2015-02-14 13:39:47 +03:00
defObject.m_ObjectType = CDefObject::OBJECT_VARIABLE;
2015-02-14 23:18:15 +03:00
defObject.m_ulAttributes = V_GLOBAL | m_GlobalVar[nGlobalVarIndex].GetOperator();
defObject.m_ulVarValue = m_GlobalVar[nGlobalVarIndex].GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
m_Definitions.SetAt(m_Namespace.GetOffsetByIndex(i), defObject);
2015-02-14 23:18:15 +03:00
m_GlobalVarsNames[nGlobalVarIndex] = m_Namespace.GetStringByIndex(i);
2015-02-14 13:39:47 +03:00
nGlobalVarIndex++;
}
}
}
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::TryRenameImportedVariables()
{
2015-02-14 13:39:47 +03:00
CDefObject defObject;
ULONG ulNameOffset;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (m_GlobalVar.GetSize() == 0)
{
for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++)
{
2015-02-14 13:39:47 +03:00
ulNameOffset = m_Namespace.GetOffsetByIndex(i);
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (!m_Definitions.Lookup(ulNameOffset, defObject))
{
2015-02-14 13:39:47 +03:00
m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_IMPORT));
}
}
}
2015-02-13 16:59:11 +03:00
}
INT_PTR CFalloutScript::NextNodeIndex( CNodeArray& NodeArray, INT_PTR nCurrentIndex, INT_PTR nStep)
{
2015-02-14 13:39:47 +03:00
INT_PTR nResult = nCurrentIndex + nStep;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if ((nResult < 0) || (nResult > NodeArray.GetUpperBound()))
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
printf("Error: Index of node out of range\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
return nResult;
2015-02-13 16:59:11 +03:00
}
2015-02-15 18:10:01 +03:00
bool CFalloutScript::CheckSequenceOfNodes(CNodeArray& NodeArray, INT_PTR nStartIndex, const uint16_t wSequence[], INT_PTR nSequenceLen)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
return RemoveSequenceOfNodes(NodeArray, nStartIndex, 0, wSequence, nSequenceLen);
2015-02-13 16:59:11 +03:00
}
2015-02-15 18:10:01 +03:00
bool CFalloutScript::RemoveSequenceOfNodes(CNodeArray& NodeArray, INT_PTR nStartIndex, INT_PTR nCount, const uint16_t wSequence[], INT_PTR nSequenceLen)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
INT_PTR nCurrentNodeIndex = nStartIndex - 1;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < nSequenceLen; i++)
{
2015-02-14 13:39:47 +03:00
nCurrentNodeIndex = NextNodeIndex(NodeArray, nCurrentNodeIndex, 1);
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
if (NodeArray[nCurrentNodeIndex].m_Opcode.GetOperator() != wSequence[nCurrentNodeIndex - nStartIndex])
2015-02-14 14:38:14 +03:00
{
2015-02-15 16:59:52 +03:00
return false;
2015-02-14 13:39:47 +03:00
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
NodeArray.RemoveAt(nStartIndex, nCount);
2015-02-13 16:59:11 +03:00
2015-02-15 16:59:52 +03:00
return true;
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::InitialReduce()
{
2015-02-15 18:10:01 +03:00
static uint16_t awTailOfProc[3] = {
2015-02-14 13:39:47 +03:00
COpcode::O_POP_TO_BASE,
COpcode::O_POP_BASE,
COpcode::O_POP_RETURN
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awTailOfCriticalProc[4] = {
2015-02-14 13:39:47 +03:00
COpcode::O_POP_TO_BASE,
COpcode::O_POP_BASE,
COpcode::O_CRITICAL_DONE,
COpcode::O_POP_RETURN
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awCheckArgCount[3] = {
2015-02-14 13:39:47 +03:00
COpcode::O_DUP,
COpcode::O_INTOP,
COpcode::O_CHECK_ARG_COUNT
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awShortCircuitAnd[5] = {
2015-02-14 13:39:47 +03:00
COpcode::O_DUP,
COpcode::O_INTOP,
COpcode::O_SWAP,
COpcode::O_IF,
COpcode::O_POP
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awShortCircuitOr[6] = {
2015-02-14 13:39:47 +03:00
COpcode::O_DUP,
COpcode::O_INTOP,
COpcode::O_SWAP,
COpcode::O_NOT,
COpcode::O_IF,
COpcode::O_POP
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awStoreReturnAdress[2] = {
2015-02-14 13:39:47 +03:00
COpcode::O_INTOP,
COpcode::O_D_TO_A
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awReturn[6] = {
2015-02-14 13:39:47 +03:00
COpcode::O_D_TO_A,
COpcode::O_SWAPA,
COpcode::O_POP_TO_BASE,
COpcode::O_POP_BASE,
COpcode::O_A_TO_D,
COpcode::O_POP_RETURN,
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awCriticalReturn[7] = {
2015-02-14 13:39:47 +03:00
COpcode::O_D_TO_A,
COpcode::O_SWAPA,
COpcode::O_POP_TO_BASE,
COpcode::O_POP_BASE,
COpcode::O_A_TO_D,
COpcode::O_CRITICAL_DONE,
COpcode::O_POP_RETURN,
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
uint16_t* pwCode;
2015-02-14 13:39:47 +03:00
INT_PTR nCount;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0 ; i < m_ProcBodies.GetSize(); i++)
{
2015-02-14 13:39:47 +03:00
// Tail
2015-02-14 23:18:15 +03:00
if (!m_ProcBodies[i].IsEmpty())
2015-02-14 14:38:14 +03:00
{
2015-02-13 16:59:11 +03:00
pwCode = (m_ProcTable[i].m_ulType & P_CRITICAL) ? awTailOfCriticalProc : awTailOfProc;
nCount = (m_ProcTable[i].m_ulType & P_CRITICAL) ? 4 : 3;
2015-02-14 23:18:15 +03:00
if (!RemoveSequenceOfNodes(m_ProcBodies[i], m_ProcBodies[i].GetSize() - nCount, nCount, pwCode, nCount))
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid tail of procedure\'s body\n");
AfxThrowUserException();
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Body
2015-02-14 23:18:15 +03:00
for(INT_PTR j = 0; j < m_ProcBodies[i].GetSize(); j++)
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
switch(m_ProcBodies[i][j].m_Opcode.GetOperator())
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
case COpcode::O_DUP:
// 'Check procedure's arguments count' statement
2015-02-14 23:18:15 +03:00
if (!RemoveSequenceOfNodes(m_ProcBodies[i], j, 3, awCheckArgCount, 3))
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
// short circuit AND
2015-02-15 18:20:01 +03:00
uint16_t actualOperator = CheckSequenceOfNodes(m_ProcBodies[i], j, awShortCircuitAnd, 5)
2015-02-14 13:39:47 +03:00
? COpcode::O_AND
2015-02-14 23:18:15 +03:00
: (CheckSequenceOfNodes(m_ProcBodies[i], j, awShortCircuitOr, 6)
2015-02-14 13:39:47 +03:00
? COpcode::O_OR
: 0);
2015-02-14 14:38:14 +03:00
if (actualOperator)
{
2015-02-15 18:20:01 +03:00
uint32_t k, skipOffset = m_ProcBodies[i][j+1].m_Opcode.GetArgument();
2015-02-14 13:39:47 +03:00
k = j - 1;
2015-02-14 14:38:14 +03:00
do
{
2015-02-14 23:18:15 +03:00
k = NextNodeIndex(m_ProcBodies[i], k, 1);
2015-02-14 14:38:14 +03:00
}
2015-02-14 23:18:15 +03:00
while (skipOffset > m_ProcBodies[i][k].m_ulOffset);
2015-02-14 14:38:14 +03:00
2015-02-14 23:18:15 +03:00
m_ProcBodies[i].InsertAt(k, m_ProcBodies[i][j]);
m_ProcBodies[i][k].m_Opcode.SetOperator(actualOperator); // place AND/OR here, so BuildTree() will treat it as a regular binary operator
m_ProcBodies[i][k].m_ulOffset = m_ProcBodies[i][k-1].m_ulOffset + COpcode::OPERATOR_SIZE; // adjust offset
m_ProcBodies[i].RemoveAt(j, (actualOperator == COpcode::O_AND) ? 5 : 6); // reduce
2015-02-14 14:38:14 +03:00
}
else
{
2015-02-14 13:39:47 +03:00
printf("Error: Unknown sequence of opcodes\n");
AfxThrowUserException();
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
j--;
break;
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
case COpcode::O_D_TO_A:
// 'return' and 'store return address' statements
2015-02-13 16:59:11 +03:00
pwCode = (m_ProcTable[i].m_ulType & P_CRITICAL) ? awCriticalReturn : awReturn;
nCount = (m_ProcTable[i].m_ulType & P_CRITICAL) ? 7 : 6;
2015-02-14 23:18:15 +03:00
if (!RemoveSequenceOfNodes(m_ProcBodies[i], j, nCount - 1, pwCode, nCount))
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
if (!RemoveSequenceOfNodes(m_ProcBodies[i], j - 1, 2, awStoreReturnAdress, 2))
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
printf("Error: Unknown sequence of opcodes\n");
AfxThrowUserException();
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
j--;
break;
}
}
}
2015-02-13 16:59:11 +03:00
}
// build tree for all nodes from nStartIndex to file offset ulEndOffset (not including)
ULONG CFalloutScript::BuildTreeBranch(CNodeArray& NodeArray, ULONG nStartIndex, ULONG ulEndOffset)
{
2015-02-15 18:10:01 +03:00
uint16_t wOperator;
2015-02-14 13:39:47 +03:00
ULONG ulArgument;
INT_PTR nNumOfArgs;
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
COpcode::COpcodeAttributes opcodeAttributes;
INT_PTR j;
2015-02-14 23:18:15 +03:00
for (j = nStartIndex; (j < NodeArray.GetSize() && NodeArray[j].m_ulOffset < ulEndOffset); j++)
2015-02-13 22:31:52 +03:00
{
2015-02-14 23:18:15 +03:00
wOperator = NodeArray[j].m_Opcode.GetOperator();
ulArgument = NodeArray[j].m_Opcode.GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
opcodeAttributes = NodeArray[j].m_Opcode.GetAttributes();
2015-02-14 13:39:47 +03:00
nNumOfArgs = INT_PTR(opcodeAttributes.m_ulNumArgs);
2015-02-13 16:59:11 +03:00
2015-02-13 22:31:52 +03:00
switch(wOperator)
{
2015-02-13 23:30:41 +03:00
case COpcode::O_FETCH_EXTERNAL:
case COpcode::O_STORE_EXTERNAL:
{
2015-02-14 14:38:14 +03:00
INT_PTR nExtVarNameNodeIndex = NextNodeIndex(NodeArray, j, -1);
2015-02-15 18:10:01 +03:00
uint16_t wOpeartor = NodeArray[nExtVarNameNodeIndex].m_Opcode.GetOperator();
2015-02-14 23:18:15 +03:00
ULONG ulArgument = NodeArray[nExtVarNameNodeIndex].m_Opcode.GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if ((wOpeartor != COpcode::O_STRINGOP) && (wOpeartor != COpcode::O_INTOP))
{
printf("Error: Invalid reference to external variable\n");
AfxThrowUserException();
2015-02-13 23:30:41 +03:00
}
2015-02-14 14:38:14 +03:00
SetExternalVariable(ulArgument);
2015-02-13 23:30:41 +03:00
break;
2015-02-14 14:38:14 +03:00
}
2015-02-13 23:30:41 +03:00
case COpcode::O_CALL:
2015-02-14 14:38:14 +03:00
{
INT_PTR nProcNumOfArgsNodeIndex = NextNodeIndex(NodeArray, j, -2);
2015-02-15 18:10:01 +03:00
uint16_t wProcNumOfArgsOperator = NodeArray[nProcNumOfArgsNodeIndex].m_Opcode.GetOperator();
2015-02-14 23:18:15 +03:00
ULONG ulProcNumOfArgs = NodeArray[nProcNumOfArgsNodeIndex].m_Opcode.GetArgument();
2015-02-14 14:38:14 +03:00
if (wProcNumOfArgsOperator != COpcode::O_INTOP)
2015-02-13 22:31:52 +03:00
{
2015-02-14 14:38:14 +03:00
printf("Error: Invalid opcode for procedure\'s number of arguments\n");
AfxThrowUserException();
2015-02-13 23:30:41 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
nNumOfArgs = INT_PTR(ulProcNumOfArgs) + 2;
2015-02-13 23:30:41 +03:00
break;
2015-02-14 14:38:14 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-13 23:30:41 +03:00
case COpcode::O_ADDREGION:
2015-02-14 14:38:14 +03:00
{
INT_PTR nAddRegionNumOfArgsNodeIndex = NextNodeIndex(NodeArray, j, -1);
2015-02-15 18:10:01 +03:00
uint16_t wAddRegionNumOfArgsOperator = NodeArray[nAddRegionNumOfArgsNodeIndex].m_Opcode.GetOperator();
2015-02-14 23:18:15 +03:00
ULONG ulAddRegionNumOfArgs = NodeArray[nAddRegionNumOfArgsNodeIndex].m_Opcode.GetArgument();
2015-02-14 14:38:14 +03:00
if (wAddRegionNumOfArgsOperator != COpcode::O_INTOP)
2015-02-13 23:30:41 +03:00
{
2015-02-14 14:38:14 +03:00
printf("Error: Invalid opcode for addRegion number of arguments\n");
AfxThrowUserException();
2015-02-13 23:30:41 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
nNumOfArgs = INT_PTR(ulAddRegionNumOfArgs) + 1;
2015-02-13 23:30:41 +03:00
break;
2015-02-14 14:38:14 +03:00
}
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Check nodes
INT_PTR nOmittedArgStartIndex = nNumOfArgs;
COpcode::COpcodeAttributes checkOpcodeAttributes;
INT_PTR nNodeIndex = j;
2015-02-13 16:59:11 +03:00
2015-02-13 23:30:41 +03:00
for(INT_PTR k = 0; k < nNumOfArgs; k++)
{
2015-02-14 13:39:47 +03:00
nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, -1);
2015-02-14 23:18:15 +03:00
if (!NodeArray[nNodeIndex].IsExpression())
2015-02-13 23:30:41 +03:00
{
if (g_bIgnoreWrongNumOfArgs)
{
if (IsOmittetArgsAllowed(wOperator))
{
2015-02-14 13:39:47 +03:00
printf("Warning: Omitted expression found\n");
nOmittedArgStartIndex = k;
break;
}
2015-02-13 23:30:41 +03:00
else
{
2015-02-14 23:18:15 +03:00
printf("Error: Not enough arguments for %X\n", NodeArray[j].m_ulOffset);
2015-02-14 13:39:47 +03:00
AfxThrowUserException();
}
}
2015-02-13 23:30:41 +03:00
else
{
2015-02-14 23:18:15 +03:00
printf("Error: Expression required for %X\n", NodeArray[j].m_ulOffset);
2015-02-14 13:39:47 +03:00
AfxThrowUserException();
}
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Move arguments
2015-02-13 22:31:52 +03:00
for(INT_PTR k = 0; k < nNumOfArgs; k++)
{
if (k < nOmittedArgStartIndex)
{
2015-02-14 23:18:15 +03:00
NodeArray[j].m_Arguments.InsertAt(0, NodeArray[j-1]);
2015-02-14 13:39:47 +03:00
NodeArray.RemoveAt(j - 1);
j--;
}
2015-02-13 22:31:52 +03:00
else
{
if (g_bInsOmittedArgsBackward)
{
2015-02-14 23:18:15 +03:00
NodeArray[j].m_Arguments.Add(CNode(CNode::TYPE_OMITTED_ARGUMENT));
2015-02-14 13:39:47 +03:00
}
2015-02-13 22:31:52 +03:00
else
{
2015-02-14 23:18:15 +03:00
NodeArray[j].m_Arguments.InsertAt(0, CNode(CNode::TYPE_OMITTED_ARGUMENT));
2015-02-14 13:39:47 +03:00
}
}
}
2015-02-13 16:59:11 +03:00
2015-02-13 23:30:41 +03:00
if (wOperator == COpcode::O_IF)
{
// process possible conditional expression - this may be either normal IF statement or (x IF y ELSE z) expression
2015-02-14 23:18:15 +03:00
ULONG ulElseOffset = NodeArray[j].m_Arguments[0].m_Opcode.GetArgument();
2015-02-14 13:39:47 +03:00
ULONG ulElseIndex, ulSkipIndex = -1;
ulElseIndex = BuildTreeBranch(NodeArray, j + 1, ulElseOffset); // true branch
2015-02-14 23:18:15 +03:00
if (NodeArray[ulElseIndex - 1].m_Opcode.GetOperator() == COpcode::O_JMP)
2015-02-13 23:30:41 +03:00
{
2015-02-14 23:18:15 +03:00
ULONG ulSkipOffset = NodeArray[ulElseIndex - 1].m_Opcode.GetArgument();
if (ulSkipOffset > NodeArray[j].m_ulOffset)
2015-02-13 23:30:41 +03:00
{
2015-02-14 13:39:47 +03:00
ulSkipIndex = BuildTreeBranch(NodeArray, ulElseIndex, ulSkipOffset); // false branch
2015-02-14 23:18:15 +03:00
if (NodeArray[ulElseIndex - 2].IsExpression() && NodeArray[ulSkipIndex - 1].IsExpression())
2015-02-13 23:30:41 +03:00
{ // conditional expression
2015-02-14 23:18:15 +03:00
NodeArray[j].m_Type = CNode::TYPE_CONDITIONAL_EXPRESSION;
NodeArray[j].m_Arguments.RemoveAt(0); // address not needed anymore
NodeArray[j].m_Arguments.InsertAt(0, NodeArray[ulElseIndex - 2]); // true expression
NodeArray[j].m_Arguments.InsertAt(2, NodeArray[ulSkipIndex - 1]); // false expression
2015-02-14 13:39:47 +03:00
NodeArray.RemoveAt(j + 1, ulSkipIndex - j - 1);
continue;
}
}
}
j = ((ulSkipIndex != -1) ? ulSkipIndex : ulElseIndex) - 1; // skip already built
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
return j;
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::BuildTree(CNodeArray& NodeArray)
{
2015-02-13 22:31:52 +03:00
if (NodeArray.GetSize() > 0)
{
2015-02-14 23:18:15 +03:00
BuildTreeBranch(NodeArray, 0, NodeArray[NodeArray.GetSize() - 1].m_ulOffset + COpcode::OPERATOR_SIZE);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::ExtractAndReduceCondition(CNodeArray& Source, CNodeArray& Destination, INT_PTR nStartIndex)
{
2015-02-14 13:39:47 +03:00
// Extract
CNode node;
INT_PTR nNodeIndex;;
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
node = Source[nNodeIndex = NextNodeIndex(Source, nStartIndex - 1, 1)];
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() != COpcode::O_JMP)
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid startup of condition\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
CNode nodeJumpAddress = node.m_Arguments[0];
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (nodeJumpAddress.m_Opcode.GetOperator() != COpcode::O_INTOP)
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid startup of condition\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
ULONG ulJumpOffset = node.m_Arguments[0].m_Opcode.GetArgument();
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
do
{
2015-02-14 23:18:15 +03:00
node = Source[nNodeIndex = NextNodeIndex(Source, nNodeIndex, 1)];
2015-02-14 14:38:14 +03:00
}
while(node.m_ulOffset < ulJumpOffset);
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
Destination.SetSize(nNodeIndex - nStartIndex);
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR j = 0; j < nNodeIndex - nStartIndex; j++)
{
2015-02-14 23:18:15 +03:00
Destination[j] = Source[nStartIndex + j];
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Reduce
2015-02-15 18:10:01 +03:00
static uint16_t awStartupOfCondition[2] = {
2015-02-14 13:39:47 +03:00
COpcode::O_JMP,
COpcode::O_CRITICAL_START
};
2015-02-13 16:59:11 +03:00
2015-02-15 18:10:01 +03:00
static uint16_t awCleanupOfCondition[2] = {
2015-02-14 13:39:47 +03:00
COpcode::O_CRITICAL_DONE,
COpcode::O_STOP_PROG
};
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Startup
2015-02-14 14:38:14 +03:00
if (!RemoveSequenceOfNodes(Destination, 0, 2, awStartupOfCondition, 2))
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid startup of condition\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Cleanup
2015-02-14 14:38:14 +03:00
if (!RemoveSequenceOfNodes(Destination, Destination.GetSize() - 2, 2, awCleanupOfCondition, 2))
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid cleanup of condition\n");
AfxThrowUserException();
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Check condition
2015-02-14 14:38:14 +03:00
if (Destination.GetSize() != 1)
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid condition. Only one expression allowed\n");
AfxThrowUserException();
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-14 23:18:15 +03:00
if (Destination[0].m_Opcode.GetAttributes().m_Type != COpcode::COpcodeAttributes::TYPE_EXPRESSION)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid condition. Expression required\n");
AfxThrowUserException();
}
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Remove from source
Source.RemoveAt(nStartIndex, nNodeIndex - nStartIndex);
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::SetBordersOfBlocks(CNodeArray& NodeArray)
{
2015-02-14 14:38:14 +03:00
if (NodeArray.IsEmpty())
{
2015-02-14 13:39:47 +03:00
return;
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
ULONG ulOffset;
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// Start of procedure
2015-02-14 23:18:15 +03:00
if (NodeArray[0].m_Opcode.GetOperator() == COpcode::O_PUSH_BASE)
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
ulOffset = NodeArray[0].m_ulOffset;
NodeArray[0] = c_NodeBeginOfBlock;
NodeArray[0].m_ulOffset = ulOffset;
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
// End of procedure
INT_PTR nLastNodeIndex = NodeArray.GetUpperBound();
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
if ((NodeArray[nLastNodeIndex].m_Opcode.GetOperator() == COpcode::O_POP_RETURN) &&
(NodeArray[nLastNodeIndex].m_Opcode.GetArgument() == 0) &&
(NodeArray[nLastNodeIndex].m_Arguments[0].m_Opcode.GetOperator() == COpcode::O_INTOP))
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
ulOffset = NodeArray[nLastNodeIndex].m_ulOffset;
NodeArray[nLastNodeIndex] = c_NodeEndOfBlock;
NodeArray[nLastNodeIndex].m_ulOffset = ulOffset;
2015-02-14 14:38:14 +03:00
}
else
{
2015-02-14 23:18:15 +03:00
ulOffset = NodeArray[nLastNodeIndex].m_ulOffset;
2015-02-14 13:39:47 +03:00
NodeArray.InsertAt(nLastNodeIndex + 1, CNode(c_NodeEndOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[nLastNodeIndex].m_ulOffset = ulOffset;
2015-02-14 13:39:47 +03:00
}
// Body
CNode node;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for(INT_PTR i = 0; i < NodeArray.GetSize(); i++)
{
2015-02-14 23:18:15 +03:00
switch(NodeArray[i].m_Opcode.GetOperator())
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
case COpcode::O_WHILE:
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
CNode node = NodeArray[i].m_Arguments[0];
ULONG loopOffset = NodeArray[i].m_Arguments[1].GetTopOffset();
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() != COpcode::O_INTOP)
2015-02-14 13:39:47 +03:00
{
2015-02-14 14:38:14 +03:00
printf("Error: Invalid opcode for jump-address\n");
AfxThrowUserException();
}
NodeArray.InsertAt(i + 1, CNode(c_NodeBeginOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[i + 1].m_ulOffset = NodeArray[i].m_ulOffset;
2015-02-14 14:38:14 +03:00
ulOffset = node.m_Opcode.GetArgument();
INT_PTR nNodeIndex = i + 1;
CArray <INT_PTR, INT_PTR&> jumps;
2015-02-14 13:39:47 +03:00
2015-02-14 14:38:14 +03:00
do
{
2015-02-14 23:18:15 +03:00
node = NodeArray[nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, 1)];
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() == COpcode::O_JMP && node.m_Type == CNode::TYPE_NORMAL && node.m_Arguments.GetSize() > 0)
{
2015-02-14 23:18:15 +03:00
ULONG ofs = node.m_Arguments[0].m_Opcode.GetArgument();
2015-02-14 14:38:14 +03:00
if (ofs == ulOffset)
{
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_Type = CNode::TYPE_BREAK;
2015-02-14 14:38:14 +03:00
}
else if (ofs == loopOffset)
{
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_Type = CNode::TYPE_CONTINUE; // continue in "while" loop
2015-02-14 14:38:14 +03:00
}
else
{
jumps.Add(nNodeIndex);
2015-02-14 13:39:47 +03:00
}
}
2015-02-14 14:38:14 +03:00
}
while(node.m_ulOffset < ulOffset);
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
bool isForLoop = false;
2015-02-14 23:18:15 +03:00
if (NodeArray[nNodeIndex - 2].m_Arguments.GetSize() > 0 && i > 0)
2015-02-14 14:38:14 +03:00
{ // *might* be a "for" loop
2015-02-14 23:18:15 +03:00
loopOffset = NodeArray[nNodeIndex - 2].GetTopOffset();
2015-02-14 14:38:14 +03:00
for (INT_PTR j=0; j<jumps.GetSize(); j++)
{
2015-02-14 23:18:15 +03:00
if (NodeArray[jumps[j]].m_Arguments[0].m_Opcode.GetArgument() == loopOffset)
2015-02-14 14:38:14 +03:00
{ // jump points to the last statement in loop
2015-02-14 23:18:15 +03:00
NodeArray[jumps[j]].m_Type = CNode::TYPE_CONTINUE; // it's a continue
2015-02-14 14:38:14 +03:00
isForLoop = true; // in a "for" loop
}
2015-02-14 13:39:47 +03:00
}
}
2015-02-14 14:38:14 +03:00
NodeArray.InsertAt(nNodeIndex, CNode(c_NodeEndOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_ulOffset = NodeArray[nNodeIndex + 1].m_ulOffset;
2015-02-14 14:38:14 +03:00
2015-02-14 23:18:15 +03:00
node = NodeArray[nNodeIndex - 1];
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() != COpcode::O_JMP)
{
printf("Error: Invalid tail of \'while\' statement\n");
AfxThrowUserException();
}
2015-02-14 23:18:15 +03:00
if (node.m_Arguments[0].m_Opcode.GetOperator() != COpcode::O_INTOP)
2015-02-14 14:38:14 +03:00
{
printf("Error: Invalid opcode for jump-address\n");
AfxThrowUserException();
}
if (isForLoop)
{
2015-02-14 23:18:15 +03:00
NodeArray[i].m_Type = CNode::TYPE_FOR_LOOP;
NodeArray[i].m_Arguments[0] = NodeArray[i - 1]; // "for" initializer
NodeArray[i].m_Arguments.Add(NodeArray[nNodeIndex - 2]); // "for" increment
2015-02-14 14:38:14 +03:00
NodeArray.RemoveAt(i - 1); // eat statement before "while"
NodeArray.RemoveAt(nNodeIndex - 3, 2); // eat last statement in loop along with jmp
}
else
{
NodeArray.RemoveAt(nNodeIndex - 1);
2015-02-14 23:18:15 +03:00
NodeArray[i].m_Arguments.RemoveAt(0);
2015-02-14 14:38:14 +03:00
}
}
break;
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
case COpcode::O_IF:
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
if (NodeArray[i].m_Type == CNode::TYPE_CONDITIONAL_EXPRESSION)
2015-02-14 13:39:47 +03:00
{
2015-02-14 14:38:14 +03:00
printf("Error: Conditional expression left in stack\n");
AfxThrowUserException();
}
2015-02-14 23:18:15 +03:00
CNode node = NodeArray[i].m_Arguments[0];
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() != COpcode::O_INTOP)
{
printf("Error: Invalid opcode for jump-address\n");
AfxThrowUserException();
}
NodeArray.InsertAt(i + 1, CNode(c_NodeBeginOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[i + 1].m_ulOffset = NodeArray[i + 2].m_ulOffset;
2015-02-14 14:38:14 +03:00
ulOffset = node.m_Opcode.GetArgument(); // offset for jump
INT_PTR nNodeIndex = i + 1;
do
{
2015-02-14 23:18:15 +03:00
node = NodeArray[nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, 1)];
2015-02-14 14:38:14 +03:00
}
while(node.m_ulOffset < ulOffset);
NodeArray.InsertAt(nNodeIndex, CNode(c_NodeEndOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_ulOffset = NodeArray[nNodeIndex + 1].m_ulOffset;
2015-02-14 14:38:14 +03:00
2015-02-14 23:18:15 +03:00
node = NodeArray[nNodeIndex - 1];
2015-02-14 14:38:14 +03:00
if (node.m_Opcode.GetOperator() == COpcode::O_JMP && node.m_Type != CNode::TYPE_BREAK && node.m_Type != CNode::TYPE_CONTINUE)
{ // else block
2015-02-14 23:18:15 +03:00
if (node.m_Arguments[0].m_Opcode.GetOperator() != COpcode::O_INTOP)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
printf("Error: Invalid opcode for jump-address\n");
AfxThrowUserException();
}
2015-02-14 14:38:14 +03:00
//ULONG jumpPastElseOffset =
2015-02-14 23:18:15 +03:00
ulOffset = node.m_Arguments[0].m_Opcode.GetArgument();
2015-02-14 14:38:14 +03:00
//printf("(else) goto %x > %x", ulOffset, node.m_ulOffset);
if (ulOffset > node.m_ulOffset)
{
NodeArray.RemoveAt(nNodeIndex - 1); // remove jump
NodeArray.InsertAt(nNodeIndex, CNode(c_NodeBeginOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_ulOffset = NodeArray[nNodeIndex + 1].m_ulOffset;
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
CNode Bnode = NodeArray[nNodeIndex - 1];
CNode Cnode = NodeArray[nNodeIndex + 1];
2015-02-14 14:38:14 +03:00
if ((Bnode.m_Type == CNode::TYPE_END_OF_BLOCK)/* &&
(Cnode.m_Opcode.GetOperator() != COpcode::O_IF)*/)
{
do
{
2015-02-14 23:18:15 +03:00
node = NodeArray[nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, 1)];
2015-02-14 13:39:47 +03:00
}
2015-02-14 14:38:14 +03:00
while(node.m_ulOffset < ulOffset);
NodeArray.InsertAt(nNodeIndex, CNode(c_NodeEndOfBlock));
2015-02-14 23:18:15 +03:00
NodeArray[nNodeIndex].m_ulOffset = NodeArray[nNodeIndex + 1].m_ulOffset;
2015-02-14 13:39:47 +03:00
}
}
}
2015-02-14 14:38:14 +03:00
}
2015-02-14 23:18:15 +03:00
NodeArray[i].m_Arguments.RemoveAt(0);
2015-02-14 14:38:14 +03:00
i++;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
break;
2015-02-14 13:39:47 +03:00
}
}
2015-02-13 16:59:11 +03:00
}
void CFalloutScript::ReduceConditionalExpressions(CNodeArray& NodeArray)
{
2015-02-14 14:38:14 +03:00
/*
if (NodeArray.IsEmpty())
{
2015-02-14 13:39:47 +03:00
return;
}
CNode node;
2015-02-13 16:59:11 +03:00
2015-02-14 14:38:14 +03:00
for (INT_PTR i = 0; i < NodeArray.GetSize(); i++)
{
2015-02-14 23:18:15 +03:00
if (NodeArray[i].m_Opcode.GetOperator() == COpcode::O_IF)
2015-02-14 14:38:14 +03:00
{
if (ReduceExpressionBlock(NodeArray, i+1))
{
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
}
}
2015-02-14 14:38:14 +03:00
}
*/
2015-02-13 16:59:11 +03:00
}
2015-02-15 18:10:01 +03:00
bool CFalloutScript::IsOmittetArgsAllowed(uint16_t wOpcode)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
if (((wOpcode >= COpcode::O_END_CORE) && (wOpcode < COpcode::O_END_OP)) ||
2015-02-14 14:38:14 +03:00
(wOpcode == COpcode::O_POP_RETURN))
{
2015-02-15 16:59:52 +03:00
return true;
2015-02-14 13:39:47 +03:00
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-15 16:59:52 +03:00
return false;
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
}