diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..114784d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,49 @@ +set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build (by default Debug)") + +cmake_minimum_required(VERSION 2.8) + +project(int2ssl) + +set(SOURCES main.cpp +Hacks/Types.h +Hacks/CString.h +Hacks/CString.cpp +Hacks/CArray.h +Hacks/CArray.cpp +Hacks/CArchive.h +Hacks/CArchive.cpp +Hacks/CFile.h +Hacks/CFile.cpp +Hacks/CMap.h +Hacks/CMap.cpp +FalloutScript.h +Namespace.h +Node.h +ObjectAttributes.h +Opcode.h +ProcTable.h +StartupCode.h +stdafx.h +Utility.h +XGetopt.h +FalloutScript.cpp +FalloutScriptDecompile.cpp +FalloutScriptDefObject.cpp +FalloutScriptDump.cpp +FalloutScriptStore.cpp +Namespace.cpp +Node.cpp +OpcodeAttributes.cpp +Opcode.cpp +ProcTable.cpp +StartupCode.cpp +stdafx.cpp +Utility.cpp +XGetopt.cpp +) + +add_definitions (-std=c++11 -Wall) + +add_executable(int2ssl ${SOURCES}) +#target_link_libraries(int2ssl) + diff --git a/FalloutScript.cpp b/FalloutScript.cpp new file mode 100644 index 0000000..9c9a67d --- /dev/null +++ b/FalloutScript.cpp @@ -0,0 +1,277 @@ +// FalloutScript.cpp : implementation file +// + +#include "stdafx.h" +#include "FalloutScript.h" + +#include + +// Constants +//c_strBogusProcedureName = ".............."; +//c_strArgumentTemplate = "arg%u"; +//c_strGlobalVarTemplate = "GVar%u"; +//c_strLocalVarTemplate = "LVar%u"; + + +// CFalloutScript + +CFalloutScript::CFalloutScript() +{ +} + +CFalloutScript::~CFalloutScript() +{ +} + +void CFalloutScript::Serialize(CArchive& ar) +{ + + //if (ar.IsStoring()) { + if (false) + { + // ASSERT(FALSE); + } + else { + printf(" Read strtup code\n"); + m_StartupCode.Serialize(ar); + + printf(" Read procedures table\n"); + m_ProcTable.Serialize(ar); + + printf(" Read namespace\n"); + m_Namespace.Serialize(ar); + + printf(" Read stringspace\n"); + m_Stringspace.Serialize(ar); + + COpcode opcode; + + printf(" Read tail of startup code\n"); + opcode.Expect(ar, COpcode::O_SET_GLOBAL); + + // Sections with variable sizes + ar.Flush(); + ULONG ullCurrentOffset = ar.GetFile()->GetPosition(); + + // Load globals + m_GlobalVar.RemoveAll(); + m_ExportedVar.RemoveAll(); + m_ExportedVarValue.RemoveAll(); + m_ExportedProc.RemoveAll(); + + COpcodeArray HeaderTail; + + while(ullCurrentOffset < m_ProcTable.GetOffsetOfProcSection()) { + opcode.Serialize(ar); + ullCurrentOffset += opcode.GetSize(); + HeaderTail.Add(opcode); + } + + // Jump to 'start' procedure + printf(" Check \"Jump to \'start\' procedure\" / \"Jump to end of statup code\"\n"); + + if (!HeaderTail.IsEmpty()) { + INT_PTR nIndexOfStart = GetIndexOfProc("start"); + ULONG ulStartProcAddress = (nIndexOfStart != -1) ? m_ProcTable[nIndexOfStart].m_ulBodyOffset : 18; + + opcode = HeaderTail.at(HeaderTail.GetUpperBound()); + + if (opcode.GetOperator() == COpcode::O_JMP) { + HeaderTail.RemoveAt(HeaderTail.GetUpperBound()); + + if (HeaderTail.IsEmpty()) { + printf("\n"); + printf("Warning: Omitted address of jump\n"); + printf("\n"); + } + else { + opcode = HeaderTail.at(HeaderTail.GetUpperBound()); + + if (opcode.GetOperator() == COpcode::O_INTOP) { + HeaderTail.RemoveAt(HeaderTail.GetUpperBound()); + + if (opcode.GetArgument() != ulStartProcAddress) { + printf("\n"); + printf("Warning: Invalid jump address\n"); + printf("\n"); + } + } + else { + printf("\n"); + printf("Warning: Invalid opcode for jump addres\n"); + printf("\n"); + } + } + } + else { + printf("\n"); + printf("Warning: Omitted \"Jump to \'start\' procedure\" / \"Jump to end of statup code\"\n"); + printf("\n"); + } + } + + // # of argument to 'start' procedure + printf(" Check \"# of argument to \'start\' procedure\"\n"); + + CString strNumOfArgsWarning("Warning: Omitted \"# of argument to \'start\' procedure\"\n"); + + if (!HeaderTail.IsEmpty()) { + opcode = HeaderTail.at(HeaderTail.GetUpperBound()); + + if (opcode.GetOperator() == COpcode::O_CRITICAL_DONE) { + HeaderTail.RemoveAt(HeaderTail.GetUpperBound()); + + if (!HeaderTail.IsEmpty()) { + opcode = HeaderTail.at(HeaderTail.GetUpperBound()); + + if (opcode.HasArgument()) { + HeaderTail.RemoveAt(HeaderTail.GetUpperBound()); + } + else { + printf("\n"); + printf("%s", strNumOfArgsWarning.c_str()); + printf("\n"); + } + } + else { + printf("\n"); + printf("%s", strNumOfArgsWarning.c_str()); + printf("\n"); + } + } + else { + printf("\n"); + printf("Warning: Omitted expected opcode 0x8003. Opcode with # of arguments will be not analysed\n"); + printf("\n"); + } + } + else { + printf("\n"); + printf("%s", strNumOfArgsWarning.c_str()); + printf("\n"); + } + + // Extract 'Export var' section + printf(" Extract \"Export var\" section\n"); + ExtractCodeElements(HeaderTail, m_ExportedVar, COpcode::O_EXPORT_VAR, 2, "Error: Malformed \"Export var\" section\n", &CFalloutScript::CheckExportVarCode); + + // Extract 'Set exported var values' section + printf(" Extract \"Set exported var values\" section\n"); + ExtractCodeElements(HeaderTail, m_ExportedVarValue, COpcode::O_STORE_EXTERNAL, 3, "Error: Malformed \"Set exported var values\" section\n", &CFalloutScript::CheckSetExportedVarValueCode); + + // Extract 'Export procedures' section + printf(" Extract \"Export procedures\" section\n"); + ExtractCodeElements(HeaderTail, m_ExportedProc, COpcode::O_EXPORT_PROC, 3, "Error: Malformed \"Export procedures\" section\n", &CFalloutScript::CheckExportProcCode); + + // Global variables + printf(" Extract \"Global variables\" section\n"); + + for(INT_PTR i = 0; i < HeaderTail.GetSize(); i++) { + WORD wGlobalVarOperator = HeaderTail.at(i).GetOperator(); + + if ((wGlobalVarOperator != COpcode::O_STRINGOP) && + (wGlobalVarOperator != COpcode::O_FLOATOP) && + (wGlobalVarOperator != COpcode::O_INTOP)) { + printf("Error: Malformed \"Global variables\" section\n"); + AfxThrowUserException(); + } + + m_GlobalVar.Add(HeaderTail.at(i)); + } + + // Procedures bodyes + printf(" Read procedure\'s bodies\n"); + m_ProcBodies.RemoveAll(); // Destroy old data + m_Conditions.RemoveAll(); + m_ProcBodies.SetSize(m_ProcTable.GetSize()); + m_Conditions.SetSize(m_ProcTable.GetSize()); + + CNode node; + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + printf(" Procedure: %d\r", i); + ULONG ulOffset = m_ProcTable[i].m_ulBodyOffset; + ULONG ulSize = m_ProcTable.GetSizeOfProc(i); + ar.Flush(); + ar.GetFile()->Seek(ulOffset, CFile::begin); + + while(ulOffset < m_ProcTable[i].m_ulBodyOffset + ulSize) { + node.m_Opcode.Serialize(ar); + node.m_ulOffset = ulOffset; + m_ProcBodies.at(i).Add(node); + ulOffset += node.m_Opcode.GetSize(); + } + } + } +} + +void CFalloutScript::ExtractCodeElements(COpcodeArray& Source, COpcodeArray& Destination, WORD wDelimeter, int nSizeOfCodeItem, LPCTSTR lpszErrorMessage, BOOL (CFalloutScript::*pCheckFunc)(WORD, INT_PTR)) +{ + INT_PTR i = 0; + + for(; i < Source.GetSize(); i++) { + if (Source.at(i).GetOperator() == wDelimeter) { + break; + } + } + + if (i < Source.GetSize()) { + if (i < nSizeOfCodeItem - 1) { + printf(lpszErrorMessage); + AfxThrowUserException(); + } + + while(Source.at(i).GetOperator() == wDelimeter) { + for(INT_PTR j = 0; j < nSizeOfCodeItem - 1; j++) { + if (!((this->*pCheckFunc)(Source.at(i - nSizeOfCodeItem + 1 + j).GetOperator(), j))) { + printf(lpszErrorMessage); + AfxThrowUserException(); + } + } + + for(INT_PTR j = 0; j < nSizeOfCodeItem - 1; j++) { + Destination.Add(Source.at(i - nSizeOfCodeItem + 1)); + Source.RemoveAt(i - nSizeOfCodeItem + 1); + } + + Source.RemoveAt(i - nSizeOfCodeItem + 1); // Delimeter + + + if (i > Source.GetUpperBound()) { + break; + } + } + } +} + +BOOL CFalloutScript::CheckExportVarCode(WORD wOperator, INT_PTR nIndex) +{ + return (nIndex == 0) && (wOperator == COpcode::O_STRINGOP); +} + +BOOL CFalloutScript::CheckSetExportedVarValueCode(WORD wOperator, INT_PTR nIndex) +{ + switch(nIndex) { + case 0: + return (wOperator == COpcode::O_STRINGOP) || + (wOperator == COpcode::O_FLOATOP) || + (wOperator == COpcode::O_INTOP); + case 1: + return (wOperator == COpcode::O_STRINGOP); + + default: + return FALSE; + } +} + +BOOL CFalloutScript::CheckExportProcCode(WORD wOperator, INT_PTR nIndex) +{ + return ((nIndex == 0) || (nIndex == 1)) && (wOperator == COpcode::O_INTOP); +} + +bool CFalloutScript::ArgNeedParens( const CNode& node, const CNode& argument, CFalloutScript::Assoc assoc) +{ + return (argument.IsInfix() + && ((GetPriority(argument.m_Opcode.GetOperator()) != GetPriority(node.m_Opcode.GetOperator())) + || (GetAssociation(node.m_Opcode.GetOperator()) != assoc))); +} diff --git a/FalloutScript.h b/FalloutScript.h new file mode 100644 index 0000000..ed1dbf2 --- /dev/null +++ b/FalloutScript.h @@ -0,0 +1,118 @@ +#pragma once + +#ifndef FALLOUT_SCRIPT_H +#define FALLOUT_SCRIPT_H + +#include "StartupCode.h" +#include "ProcTable.h" +#include "Namespace.h" +#include "Node.h" + + +// Constants + +// CFalloutScript +class CFalloutScript : public CObject { +public: + CFalloutScript(); + virtual ~CFalloutScript(); + +public: + virtual void Serialize(CArchive& ar); + + void Dump(CArchive& ar); + + void InitDefinitions(); + void ProcessCode(); + + void StoreSource(CArchive& ar); + void StoreTree(CArchive& ar); + +private: + enum Assoc { + NON_ASSOC, + LEFT_ASSOC, + RIGHT_ASSOC, + }; + +private: + void ExtractCodeElements(COpcodeArray& Source, COpcodeArray& Destination, WORD wDelimeter, int nSizeOfCodeItem, LPCTSTR lpszErrorMessage, BOOL (CFalloutScript::*pCheckFunc)(WORD, INT_PTR)); + BOOL CheckExportVarCode(WORD wOperator, INT_PTR nIndex); + BOOL CheckSetExportedVarValueCode(WORD wOperator, INT_PTR nIndex); + BOOL CheckExportProcCode(WORD wOperator, INT_PTR nIndex); + + INT_PTR GetIndexOfProc(LPCTSTR lpszName); + INT_PTR GetIndexOfProc(ULONG ulNameOffset); + INT_PTR GetIndexOfExportedVariable(ULONG ulNameOffset); + + void SetExternalVariable(ULONG ulNameOffset); + void TryRenameGlobalVariables(); + void TryRenameImportedVariables(); + + INT_PTR NextNodeIndex( CNodeArray& NodeArray, INT_PTR nCurrentIndex, INT_PTR nSteep); + BOOL CheckSequenceOfNodes(CNodeArray& NodeArray, INT_PTR nStartIndex, const WORD wSequence[], INT_PTR nSequenceLen); + BOOL RemoveSequenceOfNodes(CNodeArray& NodeArray,INT_PTR nStartIndex, INT_PTR nCount, const WORD wSequence[], INT_PTR nSequenceLen); + + void InitialReduce(); + void BuildTree(CNodeArray& NodeArray); + void ExtractAndReduceCondition(CNodeArray& Source, CNodeArray& Destination, INT_PTR nStartIndex); + void SetBordersOfBlocks(CNodeArray& NodeArray); + ULONG BuildTreeBranch(CNodeArray& NodeArray, ULONG nStartIndex, ULONG ulEndOffset); + void ReduceConditionalExpressions(CNodeArray& NodeArray); + BOOL IsOmittetArgsAllowed(WORD wOpcode); + + void StoreDefinitions(CArchive& ar); + void StoreDeclarations(CArchive& ar); + + CString GetSource( CNode& node, BOOL bLabel, ULONG ulNumArgs); + CString GetSource( CNode& node, BOOL bLabel, ULONG ulNumArgs, ULONG aulProcArg[], ULONG ulProcArgCount); + bool ArgNeedParens(const CNode& node, const CNode& argument, CFalloutScript::Assoc assoc = CFalloutScript::NON_ASSOC); + CString GetIndentString(INT_PTR nLevel); + + int GetPriority(WORD wOperator); + Assoc GetAssociation(WORD wOperator); + +private: + // CDefObject + class CDefObject { + public: + enum ObjectType { + OBJECT_VARIABLE, + OBJECT_PROCEDURE + }; + + public: + CDefObject(ObjectType type = OBJECT_VARIABLE, ULONG ulAttributes = 0, ULONG ulObjectData = 0); + + public: + ObjectType m_ObjectType; + ULONG m_ulAttributes; + + union { + ULONG m_ulVarValue; + ULONG m_ulProcIndex; + }; + }; + +private: + // CMapULongToDefObject + typedef CMap CMapULongToDefObject; + + CStartupCode m_StartupCode; + CProcTable m_ProcTable; + CNamespace m_Namespace; + CNamespace m_Stringspace; + + COpcodeArray m_GlobalVar; + COpcodeArray m_ExportedVar; + COpcodeArray m_ExportedVarValue; + COpcodeArray m_ExportedProc; + + CArrayOfNodeArray m_ProcBodies; + CArrayOfNodeArray m_Conditions; + + CMapULongToDefObject m_Definitions; + CStringArray m_GlobalVarsNames; +}; + +#endif diff --git a/FalloutScriptDecompile.cpp b/FalloutScriptDecompile.cpp new file mode 100644 index 0000000..2082739 --- /dev/null +++ b/FalloutScriptDecompile.cpp @@ -0,0 +1,772 @@ +// FalloutScriptDecompile.cpp : implementation file +// + +#include "stdafx.h" +#include "FalloutScript.h" +#include "ObjectAttributes.h" + +// Globals +extern BOOL g_bIgnoreWrongNumOfArgs; +extern BOOL g_bInsOmittedArgsBackward; +// CFalloutScript +void CFalloutScript::InitDefinitions() +{ + ULONG ulNameOffset; + INT_PTR nObjectIndex; + CString c_strGlobalVarTemplate("GVar%u"); + + + m_Definitions.RemoveAll(); + + for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++) { + ulNameOffset = m_Namespace.GetOffsetByIndex(i); + + if ((nObjectIndex = GetIndexOfProc(ulNameOffset)) != -1) { + m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_PROCEDURE, 0, ULONG(nObjectIndex))); + } + else if ((nObjectIndex = GetIndexOfExportedVariable(ulNameOffset)) != -1) { + WORD wOpcode = m_ExportedVarValue.at(nObjectIndex).GetOperator(); + ULONG ulValue = m_ExportedVarValue.at(nObjectIndex).GetArgument(); + + m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_EXPORT | wOpcode, ulValue)); + } + } + + m_GlobalVarsNames.SetSize(m_GlobalVar.GetSize()); + + for(INT_PTR i = 0; i < m_GlobalVarsNames.GetSize(); i++) { + m_GlobalVarsNames.at(i).Format(c_strGlobalVarTemplate.c_str(), i); + } +} + +void CFalloutScript::ProcessCode() +{ + printf(" Intial reducing\n"); + InitialReduce(); + + printf(" Building execution tree\n"); + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + printf(" Procedure: %d\r", i); + BuildTree(m_ProcBodies.at(i)); + } + + printf(" Extracting and reducing conditions\n"); + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + if (m_ProcTable[i].m_ulType & P_CONDITIONAL) { + ExtractAndReduceCondition(m_ProcBodies.at(i), m_Conditions.at(i), 0); + } + + for(INT_PTR j = 0; j < m_ProcBodies.at(i).GetSize(); j++) { + if (m_ProcBodies.at(i).at(j).m_Opcode.GetOperator() == COpcode::O_CALL_CONDITION) { + CNodeArray Condition; + CNode node = m_ProcBodies.at(i).at(j).m_Arguments.at(0); + + if (node.m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid opcode for start address of condition\n"); + AfxThrowUserException(); + } + + ULONG ulCondStartAddress = node.m_Opcode.GetArgument(); + + do { + node = m_ProcBodies.at(i).at(j = NextNodeIndex(m_ProcBodies.at(i), j, -1)); + } while(node.m_ulOffset != ulCondStartAddress); + + j = NextNodeIndex(m_ProcBodies.at(i), j, -1); // For O_JMP opcode + + ExtractAndReduceCondition(m_ProcBodies.at(i), Condition, j); + m_ProcBodies.at(i).at(j).m_Arguments.at(0) = Condition.at(0); + } + } + } + + + printf(" Setting borders of blocks\n"); + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + printf(" Procedure: %d\r", i); + SetBordersOfBlocks(m_ProcBodies.at(i)); + } + + printf(" Renaming global variables\n"); + TryRenameGlobalVariables(); + + printf(" Renaming imported variables\n"); + TryRenameImportedVariables(); +} + +INT_PTR CFalloutScript::GetIndexOfProc(LPCTSTR lpszName) +{ + INT_PTR nResult = -1; + CString strName(lpszName); + CString strTestName; + + strName.MakeLower(); + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + strTestName = m_Namespace[m_ProcTable[i].m_ulNameOffset]; + strTestName.MakeLower(); + + if (strTestName == strName) { + nResult = i; + break; + } + } + + return nResult; +} + +INT_PTR CFalloutScript::GetIndexOfProc(ULONG ulNameOffset) +{ + INT_PTR nResult = -1; + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + if (m_ProcTable[i].m_ulNameOffset == ulNameOffset) { + nResult = i; + break; + } + } + + return nResult; +} + +INT_PTR CFalloutScript::GetIndexOfExportedVariable(ULONG ulNameOffset) +{ + INT_PTR nResult = -1; + + for(INT_PTR i = 0; i < m_ExportedVarValue.GetSize(); i += 2) { + if (m_ExportedVarValue.at(i + 1).GetArgument() == ulNameOffset) { + nResult = i; + break; + } + } + + return nResult; +} + +void CFalloutScript::SetExternalVariable(ULONG ulNameOffset) +{ + CDefObject defObject; + + if (!m_Definitions.Lookup(ulNameOffset, defObject)) { + m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_IMPORT)); + } +} + +void CFalloutScript::TryRenameGlobalVariables() +{ + INT_PTR nNamesCount = m_Namespace.GetSize(); + INT_PTR nDefinitionsCount = m_Definitions.GetSize(); + INT_PTR nGlobalVarCount = m_GlobalVar.GetSize(); + + CDefObject defObject; + INT_PTR nGlobalVarIndex = 0; + + if (nNamesCount - nDefinitionsCount == nGlobalVarCount) { + for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++) { + if (!m_Definitions.Lookup(m_Namespace.GetOffsetByIndex(i), defObject)) { + defObject.m_ObjectType = CDefObject::OBJECT_VARIABLE; + defObject.m_ulAttributes = V_GLOBAL | m_GlobalVar.at(nGlobalVarIndex).GetOperator(); + defObject.m_ulVarValue = m_GlobalVar.at(nGlobalVarIndex).GetArgument(); + + m_Definitions.SetAt(m_Namespace.GetOffsetByIndex(i), defObject); + m_GlobalVarsNames.at(nGlobalVarIndex) = m_Namespace.GetStringByIndex(i); + nGlobalVarIndex++; + } + } + } +} + +void CFalloutScript::TryRenameImportedVariables() +{ + CDefObject defObject; + ULONG ulNameOffset; + + if (m_GlobalVar.GetSize() == 0) { + for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++) { + ulNameOffset = m_Namespace.GetOffsetByIndex(i); + + if (!m_Definitions.Lookup(ulNameOffset, defObject)) { + m_Definitions.SetAt(ulNameOffset, CDefObject(CDefObject::OBJECT_VARIABLE, V_IMPORT)); + } + } + } +} + +INT_PTR CFalloutScript::NextNodeIndex( CNodeArray& NodeArray, INT_PTR nCurrentIndex, INT_PTR nStep) +{ + INT_PTR nResult = nCurrentIndex + nStep; + +// if ((nResult < 0) || (nResult > NodeArray.GetUpperBound())) +if ((nResult < 0) || (nResult > NodeArray.GetUpperBound())) + { + printf("Error: Index of node out of range\n"); + AfxThrowUserException(); + } + + return nResult; +} + +BOOL CFalloutScript::CheckSequenceOfNodes(CNodeArray& NodeArray, INT_PTR nStartIndex, const WORD wSequence[], INT_PTR nSequenceLen) +{ + return RemoveSequenceOfNodes(NodeArray, nStartIndex, 0, wSequence, nSequenceLen); +} + +BOOL CFalloutScript::RemoveSequenceOfNodes(CNodeArray& NodeArray, INT_PTR nStartIndex, INT_PTR nCount, const WORD wSequence[], INT_PTR nSequenceLen) +{ + INT_PTR nCurrentNodeIndex = nStartIndex - 1; + + for(INT_PTR i = 0; i < nSequenceLen; i++) { + nCurrentNodeIndex = NextNodeIndex(NodeArray, nCurrentNodeIndex, 1); + + if (NodeArray.at(nCurrentNodeIndex).m_Opcode.GetOperator() != wSequence[nCurrentNodeIndex - nStartIndex]) { + return FALSE; + } + } + + NodeArray.RemoveAt(nStartIndex, nCount); + + return TRUE; +} + +void CFalloutScript::InitialReduce() +{ + static WORD awTailOfProc[3] = { + COpcode::O_POP_TO_BASE, + COpcode::O_POP_BASE, + COpcode::O_POP_RETURN + }; + + static WORD awTailOfCriticalProc[4] = { + COpcode::O_POP_TO_BASE, + COpcode::O_POP_BASE, + COpcode::O_CRITICAL_DONE, + COpcode::O_POP_RETURN + }; + + static WORD awCheckArgCount[3] = { + COpcode::O_DUP, + COpcode::O_INTOP, + COpcode::O_CHECK_ARG_COUNT + }; + + static WORD awShortCircuitAnd[5] = { + COpcode::O_DUP, + COpcode::O_INTOP, + COpcode::O_SWAP, + COpcode::O_IF, + COpcode::O_POP + }; + + static WORD awShortCircuitOr[6] = { + COpcode::O_DUP, + COpcode::O_INTOP, + COpcode::O_SWAP, + COpcode::O_NOT, + COpcode::O_IF, + COpcode::O_POP + }; + + static WORD awStoreReturnAdress[2] = { + COpcode::O_INTOP, + COpcode::O_D_TO_A + }; + + static WORD awReturn[6] = { + 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, + }; + + static WORD awCriticalReturn[7] = { + 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, + }; + + WORD* pwCode; + INT_PTR nCount; + + for(INT_PTR i = 0 ; i < m_ProcBodies.GetSize(); i++) { + // Tail + if (!m_ProcBodies.at(i).IsEmpty()) { + pwCode = (m_ProcTable[i].m_ulType & P_CRITICAL) ? awTailOfCriticalProc : awTailOfProc; + nCount = (m_ProcTable[i].m_ulType & P_CRITICAL) ? 4 : 3; + + if (!RemoveSequenceOfNodes(m_ProcBodies.at(i), m_ProcBodies.at(i).GetSize() - nCount, nCount, pwCode, nCount)) { + printf("Error: Invalid tail of procedure\'s body\n"); + AfxThrowUserException(); + } + } + + // Body + for(INT_PTR j = 0; j < m_ProcBodies.at(i).GetSize(); j++) { + switch(m_ProcBodies.at(i).at(j).m_Opcode.GetOperator()) { + case COpcode::O_DUP: + // 'Check procedure's arguments count' statement + if (!RemoveSequenceOfNodes(m_ProcBodies.at(i), j, 3, awCheckArgCount, 3)) { + // short circuit AND + UINT actualOperator = CheckSequenceOfNodes(m_ProcBodies.at(i), j, awShortCircuitAnd, 5) + ? COpcode::O_AND + : (CheckSequenceOfNodes(m_ProcBodies.at(i), j, awShortCircuitOr, 6) + ? COpcode::O_OR + : 0); + if (actualOperator) { + UINT k, skipOffset = m_ProcBodies.at(i).at(j+1).m_Opcode.GetArgument(); + CNode node; + k = j - 1; + do { + k = NextNodeIndex(m_ProcBodies.at(i), k, 1); + } while (skipOffset > m_ProcBodies.at(i).at(k).m_ulOffset); + m_ProcBodies.at(i).InsertAt(k, m_ProcBodies.at(i).at(j)); + m_ProcBodies.at(i).at(k).m_Opcode.SetOperator(actualOperator); // place AND/OR here, so BuildTree() will treat it as a regular binary operator + m_ProcBodies.at(i).at(k).m_ulOffset = m_ProcBodies.at(i).at(k-1).m_ulOffset + COpcode::OPERATOR_SIZE; // adjust offset + m_ProcBodies.at(i).RemoveAt(j, (actualOperator == COpcode::O_AND) ? 5 : 6); // reduce + } else { + printf("Error: Unknown sequence of opcodes\n"); + AfxThrowUserException(); + } + } + + j--; + break; + + case COpcode::O_D_TO_A: + // 'return' and 'store return address' statements + pwCode = (m_ProcTable[i].m_ulType & P_CRITICAL) ? awCriticalReturn : awReturn; + nCount = (m_ProcTable[i].m_ulType & P_CRITICAL) ? 7 : 6; + + if (!RemoveSequenceOfNodes(m_ProcBodies.at(i), j, nCount - 1, pwCode, nCount)) { + if (!RemoveSequenceOfNodes(m_ProcBodies.at(i), j - 1, 2, awStoreReturnAdress, 2)) { + printf("Error: Unknown sequence of opcodes\n"); + AfxThrowUserException(); + } + } + + j--; + break; + } + } + } +} + +// build tree for all nodes from nStartIndex to file offset ulEndOffset (not including) +ULONG CFalloutScript::BuildTreeBranch(CNodeArray& NodeArray, ULONG nStartIndex, ULONG ulEndOffset) +{ + WORD wOperator; + ULONG ulArgument; + INT_PTR nNumOfArgs; + + COpcode::COpcodeAttributes opcodeAttributes; + INT_PTR j; + for (j = nStartIndex; (j < NodeArray.GetSize() && NodeArray.at(j).m_ulOffset < ulEndOffset); j++) { + wOperator = NodeArray.at(j).m_Opcode.GetOperator(); + ulArgument = NodeArray.at(j).m_Opcode.GetArgument(); + + opcodeAttributes = NodeArray.at(j).m_Opcode.GetAttributes(); + nNumOfArgs = INT_PTR(opcodeAttributes.m_ulNumArgs); + + switch(wOperator) { + case COpcode::O_FETCH_EXTERNAL: + case COpcode::O_STORE_EXTERNAL: + { + INT_PTR nExtVarNameNodeIndex = NextNodeIndex(NodeArray, j, -1); + WORD wOpeartor = NodeArray.at(nExtVarNameNodeIndex).m_Opcode.GetOperator(); + ULONG ulArgument = NodeArray.at(nExtVarNameNodeIndex).m_Opcode.GetArgument(); + + if ((wOpeartor != COpcode::O_STRINGOP) && (wOpeartor != COpcode::O_INTOP)) { + printf("Error: Invalid reference to external variable\n"); + AfxThrowUserException(); + } + + SetExternalVariable(ulArgument); + } + + break; + + case COpcode::O_CALL: + { + INT_PTR nProcNumOfArgsNodeIndex = NextNodeIndex(NodeArray, j, -2); + WORD wProcNumOfArgsOperator = NodeArray.at(nProcNumOfArgsNodeIndex).m_Opcode.GetOperator(); + ULONG ulProcNumOfArgs = NodeArray.at(nProcNumOfArgsNodeIndex).m_Opcode.GetArgument(); + + if (wProcNumOfArgsOperator != COpcode::O_INTOP) { + printf("Error: Invalid opcode for procedure\'s number of arguments\n"); + AfxThrowUserException(); + } + + nNumOfArgs = INT_PTR(ulProcNumOfArgs) + 2; + } + + break; + + case COpcode::O_ADDREGION: + { + INT_PTR nAddRegionNumOfArgsNodeIndex = NextNodeIndex(NodeArray, j, -1); + WORD wAddRegionNumOfArgsOperator = NodeArray.at(nAddRegionNumOfArgsNodeIndex).m_Opcode.GetOperator(); + ULONG ulAddRegionNumOfArgs = NodeArray.at(nAddRegionNumOfArgsNodeIndex).m_Opcode.GetArgument(); + + if (wAddRegionNumOfArgsOperator != COpcode::O_INTOP) { + printf("Error: Invalid opcode for addRegion number of arguments\n"); + AfxThrowUserException(); + } + + nNumOfArgs = INT_PTR(ulAddRegionNumOfArgs) + 1; + } + + break; + } + + // Check nodes + INT_PTR nOmittedArgStartIndex = nNumOfArgs; + COpcode::COpcodeAttributes checkOpcodeAttributes; + INT_PTR nNodeIndex = j; + + for(INT_PTR k = 0; k < nNumOfArgs; k++) { + nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, -1); + if (!NodeArray.at(nNodeIndex).IsExpression()) { + if (g_bIgnoreWrongNumOfArgs) { + if (IsOmittetArgsAllowed(wOperator)) { + printf("Warning: Omitted expression found\n"); + nOmittedArgStartIndex = k; + break; + } + else { + printf("Error: Not enough arguments for %X\n", NodeArray.at(j).m_ulOffset); + AfxThrowUserException(); + } + } + else { + printf("Error: Expression required for %X\n", NodeArray.at(j).m_ulOffset); + AfxThrowUserException(); + } + } + } + + // Move arguments + for(INT_PTR k = 0; k < nNumOfArgs; k++) { + if (k < nOmittedArgStartIndex) { + NodeArray.at(j).m_Arguments.InsertAt(0, NodeArray.at(j - 1)); + NodeArray.RemoveAt(j - 1); + j--; + } + else { + if (g_bInsOmittedArgsBackward) { + NodeArray.at(j).m_Arguments.Add(CNode(CNode::TYPE_OMITTED_ARGUMENT)); + } + else { + NodeArray.at(j).m_Arguments.InsertAt(0, CNode(CNode::TYPE_OMITTED_ARGUMENT)); + } + } + } + + if (wOperator == COpcode::O_IF) { // process possible conditional expression - this may be either normal IF statement or (x IF y ELSE z) expression + ULONG ulElseOffset = NodeArray.at(j).m_Arguments.at(0).m_Opcode.GetArgument(); + ULONG ulElseIndex, ulSkipIndex = -1; + ulElseIndex = BuildTreeBranch(NodeArray, j + 1, ulElseOffset); // true branch + if (NodeArray.at(ulElseIndex - 1).m_Opcode.GetOperator() == COpcode::O_JMP) { + ULONG ulSkipOffset = NodeArray.at(ulElseIndex - 1).m_Opcode.GetArgument(); + if (ulSkipOffset > NodeArray.at(j).m_ulOffset) { + ulSkipIndex = BuildTreeBranch(NodeArray, ulElseIndex, ulSkipOffset); // false branch + if (NodeArray.at(ulElseIndex - 2).IsExpression() && NodeArray.at(ulSkipIndex - 1).IsExpression()) { // conditional expression + NodeArray.at(j).m_Type = CNode::TYPE_CONDITIONAL_EXPRESSION; + NodeArray.at(j).m_Arguments.RemoveAt(0); // address not needed anymore + NodeArray.at(j).m_Arguments.InsertAt(0, NodeArray.at(ulElseIndex - 2)); // true expression + NodeArray.at(j).m_Arguments.InsertAt(2, NodeArray.at(ulSkipIndex - 1)); // false expression + NodeArray.RemoveAt(j + 1, ulSkipIndex - j - 1); + continue; + } + } + } + j = ((ulSkipIndex != -1) ? ulSkipIndex : ulElseIndex) - 1; // skip already built + } + } + + return j; +} + +void CFalloutScript::BuildTree(CNodeArray& NodeArray) +{ + if (NodeArray.GetSize() > 0) { + BuildTreeBranch(NodeArray, 0, NodeArray.at(NodeArray.GetSize() - 1).m_ulOffset + COpcode::OPERATOR_SIZE); + } +} + +void CFalloutScript::ExtractAndReduceCondition(CNodeArray& Source, CNodeArray& Destination, INT_PTR nStartIndex) +{ + // Extract + CNode node; + INT_PTR nNodeIndex;; + + node = Source.at(nNodeIndex = NextNodeIndex(Source, nStartIndex - 1, 1)); + + if (node.m_Opcode.GetOperator() != COpcode::O_JMP) { + printf("Error: Invalid startup of condition\n"); + AfxThrowUserException(); + } + + CNode nodeJumpAddress = node.m_Arguments.at(0); + + if (nodeJumpAddress.m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid startup of condition\n"); + AfxThrowUserException(); + } + + ULONG ulJumpOffset = node.m_Arguments.at(0).m_Opcode.GetArgument(); + + do { + node = Source.at(nNodeIndex = NextNodeIndex(Source, nNodeIndex, 1)); + } while(node.m_ulOffset < ulJumpOffset); + + Destination.SetSize(nNodeIndex - nStartIndex); + + for(INT_PTR j = 0; j < nNodeIndex - nStartIndex; j++) { + Destination.at(j) = Source.at(nStartIndex + j); + } + + // Reduce + static WORD awStartupOfCondition[2] = { + COpcode::O_JMP, + COpcode::O_CRITICAL_START + }; + + static WORD awCleanupOfCondition[2] = { + COpcode::O_CRITICAL_DONE, + COpcode::O_STOP_PROG + }; + + // Startup + if (!RemoveSequenceOfNodes(Destination, 0, 2, awStartupOfCondition, 2)) { + printf("Error: Invalid startup of condition\n"); + AfxThrowUserException(); + } + + // Cleanup + if (!RemoveSequenceOfNodes(Destination, Destination.GetSize() - 2, 2, awCleanupOfCondition, 2)) { + printf("Error: Invalid cleanup of condition\n"); + AfxThrowUserException(); + } + + // Check condition + if (Destination.GetSize() != 1) { + printf("Error: Invalid condition. Only one expression allowed\n"); + AfxThrowUserException(); + } + else { + if (Destination.at(0).m_Opcode.GetAttributes().m_Type != COpcode::COpcodeAttributes::TYPE_EXPRESSION) { + printf("Error: Invalid condition. Expression required\n"); + AfxThrowUserException(); + } + } + + // Remove from source + Source.RemoveAt(nStartIndex, nNodeIndex - nStartIndex); +} + +void CFalloutScript::SetBordersOfBlocks(CNodeArray& NodeArray) +{ + if (NodeArray.IsEmpty()) { + return; + } + + ULONG ulOffset; + + // Start of procedure + if (NodeArray.at(0).m_Opcode.GetOperator() == COpcode::O_PUSH_BASE) { + ulOffset = NodeArray.at(0).m_ulOffset; + NodeArray.at(0) = c_NodeBeginOfBlock; + NodeArray.at(0).m_ulOffset = ulOffset; + } + + // End of procedure + INT_PTR nLastNodeIndex = NodeArray.GetUpperBound(); + + if ((NodeArray.at(nLastNodeIndex).m_Opcode.GetOperator() == COpcode::O_POP_RETURN) && + (NodeArray.at(nLastNodeIndex).m_Opcode.GetArgument() == 0) && + (NodeArray.at(nLastNodeIndex).m_Arguments.at(0).m_Opcode.GetOperator() == COpcode::O_INTOP)){ + ulOffset = NodeArray.at(nLastNodeIndex).m_ulOffset; + NodeArray.at(nLastNodeIndex) = c_NodeEndOfBlock; + NodeArray.at(nLastNodeIndex).m_ulOffset = ulOffset; + } else /*if ((NodeArray.at(nLastNodeIndex).m_Opcode.GetOperator() == COpcode::O_POP_RETURN) && + (NodeArray.at(nLastNodeIndex).m_Arguments.at(0).m_Opcode.GetOperator() == COpcode::O_INTOP))*/ { + ulOffset = NodeArray.at(nLastNodeIndex).m_ulOffset; + //NodeArray.at(nLastNodeIndex) = c_NodeEndOfBlock; + NodeArray.InsertAt(nLastNodeIndex + 1, CNode(c_NodeEndOfBlock)); + NodeArray.at(nLastNodeIndex).m_ulOffset = ulOffset; + } + + // Body + CNode node; + + for(INT_PTR i = 0; i < NodeArray.GetSize(); i++) { + switch(NodeArray.at(i).m_Opcode.GetOperator()) { + case COpcode::O_WHILE: + { + CNode node = NodeArray.at(i).m_Arguments.at(0); + ULONG loopOffset = NodeArray.at(i).m_Arguments.at(1).GetTopOffset(); + + if (node.m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid opcode for jump-address\n"); + AfxThrowUserException(); + } + + NodeArray.InsertAt(i + 1, CNode(c_NodeBeginOfBlock)); + NodeArray.at(i + 1).m_ulOffset = NodeArray.at(i).m_ulOffset; + ulOffset = node.m_Opcode.GetArgument(); + + INT_PTR nNodeIndex = i + 1; + CArray jumps; + //CMap elses = CMap (); + //bool unused; + do { + node = NodeArray.at(nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, 1)); + if (node.m_Opcode.GetOperator() == COpcode::O_JMP && node.m_Type == CNode::TYPE_NORMAL && node.m_Arguments.GetSize() > 0) { + ULONG ofs = node.m_Arguments.at(0).m_Opcode.GetArgument(); + if (ofs == ulOffset) { + NodeArray.at(nNodeIndex).m_Type = CNode::TYPE_BREAK; + } else if (ofs == loopOffset) { + NodeArray.at(nNodeIndex).m_Type = CNode::TYPE_CONTINUE; // continue in "while" loop + } else { + //if (!elses.Lookup(NodeArray[nNodeIndex+1].GetTopOffset(), unused)) { + jumps.Add(nNodeIndex); + //} + } + }/* else if (node.m_Opcode.GetOperator() == COpcode::O_IF && node.m_Arguments.GetSize() > 0) { + elses[node.m_Arguments.at(0).m_Opcode.GetArgument()] = true; + }*/ + } while(node.m_ulOffset < ulOffset); + + bool isForLoop = false; + if (NodeArray.at(nNodeIndex - 2).m_Arguments.GetSize() > 0 && i > 0) { // *might* be a "for" loop + loopOffset = NodeArray.at(nNodeIndex - 2).GetTopOffset(); + for (INT_PTR j=0; j %x", ulOffset, node.m_ulOffset); + if (ulOffset > node.m_ulOffset) { + NodeArray.RemoveAt(nNodeIndex - 1); // remove jump + NodeArray.InsertAt(nNodeIndex, CNode(c_NodeBeginOfBlock)); + NodeArray.at(nNodeIndex).m_ulOffset = NodeArray.at(nNodeIndex + 1).m_ulOffset; + + CNode Bnode = NodeArray.at(nNodeIndex - 1); + CNode Cnode = NodeArray.at(nNodeIndex + 1); + if ((Bnode.m_Type == CNode::TYPE_END_OF_BLOCK)/* && + (Cnode.m_Opcode.GetOperator() != COpcode::O_IF)*/) { + do { + node = NodeArray.at(nNodeIndex = NextNodeIndex(NodeArray, nNodeIndex, 1)); + } while(node.m_ulOffset < ulOffset); + NodeArray.InsertAt(nNodeIndex, CNode(c_NodeEndOfBlock)); + NodeArray.at(nNodeIndex).m_ulOffset = NodeArray.at(nNodeIndex + 1).m_ulOffset; + } + } + } + } + NodeArray.at(i).m_Arguments.RemoveAt(0); + i++; + + break; + } + } +} + +void CFalloutScript::ReduceConditionalExpressions(CNodeArray& NodeArray) +{ + /*if (NodeArray.IsEmpty()) { + return; + } + CNode node; + + for (INT_PTR i = 0; i < NodeArray.GetSize(); i++) { + if (NodeArray.at(i).m_Opcode.GetOperator() == COpcode::O_IF) { + if (ReduceExpressionBlock(NodeArray, i+1)) { + + } + } + }*/ +} + +BOOL CFalloutScript::IsOmittetArgsAllowed(WORD wOpcode) +{ + if (((wOpcode >= COpcode::O_END_CORE) && (wOpcode < COpcode::O_END_OP)) || + (wOpcode == COpcode::O_POP_RETURN)) { + return TRUE; + } + else { + return FALSE; + } +} diff --git a/FalloutScriptDefObject.cpp b/FalloutScriptDefObject.cpp new file mode 100644 index 0000000..b9d7a11 --- /dev/null +++ b/FalloutScriptDefObject.cpp @@ -0,0 +1,21 @@ +// FalloutScript.cpp : implementation file +// + +#include "stdafx.h" +#include "FalloutScript.h" + + +// CFalloutScript::CDefObject +CFalloutScript::CDefObject::CDefObject(ObjectType type, ULONG ulAttributes, ULONG ulObjectData) +{ + m_ulAttributes = ulAttributes; + + switch(m_ObjectType = type) { + case OBJECT_VARIABLE: + m_ulVarValue = ulObjectData; + break; + + case OBJECT_PROCEDURE: + m_ulProcIndex = ulObjectData; + } +} diff --git a/FalloutScriptDump.cpp b/FalloutScriptDump.cpp new file mode 100644 index 0000000..ef7081a --- /dev/null +++ b/FalloutScriptDump.cpp @@ -0,0 +1,156 @@ +// FalloutScript.cpp : implementation file +// + +#include "stdafx.h" +#include "FalloutScript.h" + +// CFalloutScript +void CFalloutScript::Dump(CArchive& ar) +{ + ar.WriteString("============== Procedures table ==================\n"); + ar.WriteString("\n"); + m_ProcTable.Dump(ar); + ar.WriteString("\n"); + ar.WriteString("\n"); + + ar.WriteString("============== Namespace ==================\n"); + m_Namespace.Dump(ar); + ar.WriteString("\n"); + ar.WriteString("\n"); + + ar.WriteString("============== Stringspace ==================\n"); + m_Stringspace.Dump(ar); + ar.WriteString("\n"); + ar.WriteString("\n"); + + + CString strOutLine; + WORD wOperator; + ULONG ulArgument = 0; + + ar.WriteString("============== Global variables values ==================\n"); + + if (m_GlobalVar.IsEmpty()) { + ar.WriteString("Not found\n"); + } + else { + for(INT_PTR i = 0; i < m_GlobalVar.GetSize(); i++) { + wOperator = m_GlobalVar.at(i).GetOperator(); + ulArgument = m_GlobalVar.at(i).GetArgument(); + + switch(wOperator) { + case COpcode::O_STRINGOP: + case COpcode::O_INTOP: + strOutLine.Format("%d: %s(0x%08x) // %u (%d)\n", + i, + m_GlobalVar.at(i).GetAttributes().m_strMnemonic.c_str(), + ulArgument, + ulArgument, + ulArgument); + ar.WriteString(strOutLine); + break; + + case COpcode::O_FLOATOP: + strOutLine.Format("%d: %s(0x%08x) // %05f\n", + i, + m_GlobalVar.at(i).GetAttributes().m_strMnemonic.c_str(), + ulArgument, + *((float*)(&ulArgument))); + ar.WriteString(strOutLine); + } + } + } + + ar.WriteString("\n"); + ar.WriteString("\n"); + + ar.WriteString("============== Exported variables ==================\n"); + + if (m_ExportedVarValue.IsEmpty()) { + ar.WriteString("Not found\n"); + } + else { + for(INT_PTR i = 0; i < m_ExportedVarValue.GetSize(); i += 2) { + wOperator = m_ExportedVarValue.at(i).GetOperator(); + ulArgument = m_ExportedVarValue.at(i).GetArgument(); + ULONG ulNameArgument = m_ExportedVarValue.at(i + 1).GetArgument(); + + switch(wOperator) { + case COpcode::O_STRINGOP: + strOutLine.Format("%s := \"%s\"\n", + m_Namespace[ulNameArgument].c_str(), + m_Stringspace[ulArgument].c_str()); + ar.WriteString(strOutLine); + break; + + case COpcode::O_INTOP: + strOutLine.Format("%s := %u (%d)\n", + m_Namespace[ulNameArgument].c_str(), + ulArgument, + ulArgument); + ar.WriteString(strOutLine); + break; + + case COpcode::O_FLOATOP: + strOutLine.Format("%s := %05f\n", + m_Namespace[ulNameArgument].c_str(), + *((float*)(&ulArgument))); + ar.WriteString(strOutLine); + } + } + } + + ar.WriteString("\n"); + ar.WriteString("\n"); + + ar.WriteString("============== Procedures ==================\n"); + ar.WriteString("\n"); + + for(INT_PTR nIndexOfProc = 0; nIndexOfProc < m_ProcTable.GetSize(); nIndexOfProc++) { + strOutLine.Format("%d: %s (0x%08x)\n", nIndexOfProc, + m_Namespace[m_ProcTable[nIndexOfProc].m_ulNameOffset].c_str(), + m_ProcTable[nIndexOfProc].m_ulBodyOffset + ); + ar.WriteString(strOutLine); + ar.WriteString("===============================\n"); + + for(INT_PTR i = 0; i < m_ProcBodies.at(nIndexOfProc).GetSize(); i++) { + wOperator = m_ProcBodies.at(nIndexOfProc).at(i).m_Opcode.GetOperator(); + ulArgument = m_ProcBodies.at(nIndexOfProc).at(i).m_Opcode.GetArgument(); + + switch(wOperator) { + case COpcode::O_STRINGOP: + case COpcode::O_INTOP: + strOutLine.Format("0x%08X: 0x%04X 0x%08x - %s(0x%08x) // %u (%d)\n", + m_ProcBodies.at(nIndexOfProc).at(i).m_ulOffset, + wOperator, + ulArgument, + m_ProcBodies.at(nIndexOfProc).at(i).m_Opcode.GetAttributes().m_strMnemonic.c_str(), + ulArgument, + ulArgument, + ulArgument); + ar.WriteString(strOutLine); + break; + + case COpcode::O_FLOATOP: + strOutLine.Format("0x%08X: 0x%04X 0x%08X - %s // %05f\n", + m_ProcBodies.at(nIndexOfProc).at(i).m_ulOffset, + wOperator, + ulArgument, + m_ProcBodies.at(nIndexOfProc).at(i).m_Opcode.GetAttributes().m_strMnemonic.c_str(), + *((float*)(&ulArgument))); + ar.WriteString(strOutLine); + break; + + default: + strOutLine.Format("0x%08X: 0x%04X - %s\n", + m_ProcBodies.at(nIndexOfProc).at(i).m_ulOffset, + wOperator, + m_ProcBodies.at(nIndexOfProc).at(i).m_Opcode.GetAttributes().m_strMnemonic.c_str()); + ar.WriteString(strOutLine); + } + } + + ar.WriteString("\n"); + } +} diff --git a/FalloutScriptStore.cpp b/FalloutScriptStore.cpp new file mode 100644 index 0000000..b4a61b7 --- /dev/null +++ b/FalloutScriptStore.cpp @@ -0,0 +1,1004 @@ +// FalloutScript.cpp : implementation file +// + +#include "stdafx.h" +#include "FalloutScript.h" +#include "ObjectAttributes.h" + +// Globals +extern CString g_strIndentFill; + +// CFalloutScript +void CFalloutScript::StoreTree(CArchive& ar) +{ + CString strOutLine; + + ar.WriteString("============== Procedures ==================\n"); + ar.WriteString("\n"); + + for(INT_PTR nIndexOfProc = 0; nIndexOfProc < m_ProcTable.GetSize(); nIndexOfProc++) { + strOutLine.Format("%d: %s (0x%08x)\n", nIndexOfProc, m_Namespace[m_ProcTable[nIndexOfProc].m_ulNameOffset].c_str(), m_ProcTable[nIndexOfProc].m_ulBodyOffset); + ar.WriteString(strOutLine); + ar.WriteString("===============================\n"); + + if (m_ProcTable[nIndexOfProc].m_ulType & P_CONDITIONAL) { + ar.WriteString("Condition\n"); + ar.WriteString("===============================\n"); + + for(INT_PTR i = 0; i < m_Conditions.at(nIndexOfProc).GetSize(); i++) { + strOutLine.Format("0x%08X: ", m_Conditions.at(nIndexOfProc).at(i).m_ulOffset); + ar.WriteString(strOutLine); + m_Conditions.at(nIndexOfProc).at(i).StoreTree(ar, 0, 0); + } + + ar.WriteString("\n"); + ar.WriteString("Body\n"); + ar.WriteString("===============================\n"); + } + + for(INT_PTR i = 0; i < m_ProcBodies.at(nIndexOfProc).GetSize(); i++) { + strOutLine.Format("0x%08X: ", m_ProcBodies.at(nIndexOfProc).at(i).m_ulOffset); + ar.WriteString(strOutLine); + m_ProcBodies.at(nIndexOfProc).at(i).StoreTree(ar, 0, 0); + } + + ar.WriteString("\n"); + } + +} + +void CFalloutScript::StoreSource(CArchive& ar) +{ + StoreDefinitions(ar); + ar.WriteString("\n"); + ar.WriteString("\n"); + StoreDeclarations(ar); +// StoreTree(ar); +} + + + +void CFalloutScript::StoreDefinitions(CArchive& ar) +{ + CString c_strBogusProcedureName(".............."); + CString c_strArgumentTemplate("arg%u"); + + printf(" Storing definitions\n"); + + // Unnamed global variables + INT_PTR nNamesCount = m_Namespace.GetSize(); + INT_PTR nDefinitionsCount = m_Definitions.GetSize(); + CString strDefinition; + ULONG ulVarValue; + + if (nNamesCount != nDefinitionsCount) { + ar.WriteString("/*******************************************************\n"); + ar.WriteString("* Some unreferenced imported varables found. *\n"); + ar.WriteString("* Because of it it is impossible to specify *\n"); + ar.WriteString("* the real names of global variables. *\n"); + ar.WriteString("*******************************************************/\n"); + ar.WriteString("\n"); + + for(INT_PTR i = 0; i < m_GlobalVar.GetSize(); i++) { + ulVarValue = m_GlobalVar.at(i).GetArgument(); + strDefinition += "variable "; + strDefinition += m_GlobalVarsNames.at(i); + + switch(m_GlobalVar.at(i).GetOperator()) { + case COpcode::O_STRINGOP: + strDefinition.Format(strDefinition + " := \"%s\"", m_Stringspace[ulVarValue].c_str()); + break; + + case COpcode::O_FLOATOP: + strDefinition.Format(strDefinition + " := %.5f", *((float*)(&ulVarValue))); + break; + + case COpcode::O_INTOP: + if (ulVarValue != 0) { + strDefinition.Format(strDefinition + " := %d", (long)ulVarValue); + } + + break; + } + + strDefinition += ";"; + + if ((m_GlobalVar.at(i).GetOperator() == COpcode::O_INTOP) && (ulVarValue & 0x80000000)) { + strDefinition.Format(strDefinition + " /* (%d) */", ulVarValue); + } + + ar.WriteString(strDefinition + "\n"); + } + + ar.WriteString("\n"); + } + + + // Named objects + ULONG ulNameOffset; + CDefObject defObject; + + enum OutDefObject { + OUT_NOTHING, + OUT_UNKNOWN_VARIABLE, + OUT_GLOBAL_VARIABLE, + OUT_EXPORTED_VARIABLE, + OUT_IMPORTED_VARIABLE, + OUT_PROCEDURE, + OUT_EXPORTED_PROCEDURE, + OUT_IMPORTED_PROCEDURE + }; + + OutDefObject lastOut = OUT_NOTHING; + OutDefObject currentOut = OUT_NOTHING; + CProcDescriptor procDescriptor; + + for(INT_PTR i = 0; i < m_Namespace.GetSize(); i++) { + ulNameOffset = m_Namespace.GetOffsetByIndex(i); + + if (i == 0) { + if (m_Namespace[ulNameOffset] == c_strBogusProcedureName.c_str()) { + continue; + } + else { + std::string msg = "Warning: Bogus procedure with name "; + msg += c_strBogusProcedureName; + msg += " not found at expected location\n"; + printf(msg.c_str()); + } + } + + if (m_Definitions.Lookup(ulNameOffset, defObject)) { + strDefinition = ""; + + switch(defObject.m_ObjectType) { + case CDefObject::OBJECT_PROCEDURE: + procDescriptor = m_ProcTable[defObject.m_ulProcIndex]; + + if (procDescriptor.m_ulType & P_IMPORT) { + strDefinition = "import "; + currentOut = OUT_IMPORTED_PROCEDURE; + } + else if (procDescriptor.m_ulType & P_EXPORT) { + strDefinition = "export "; + currentOut = OUT_EXPORTED_PROCEDURE; + } + else { + currentOut = OUT_PROCEDURE; + } + + strDefinition += "procedure "; + strDefinition += m_Namespace[ulNameOffset]; + + if (procDescriptor.m_ulNumArgs != 0) { + strDefinition += "("; + + for(ULONG i = 0; i < procDescriptor.m_ulNumArgs; i++) { + if (i == 0) { + strDefinition.Format(strDefinition + "variable " + c_strArgumentTemplate.c_str(), i); + } + else { + strDefinition.Format(strDefinition + ", variable " + c_strArgumentTemplate.c_str(), i); + } + } + + strDefinition += ")"; + } + + strDefinition += ";"; + + if (procDescriptor.m_ulType & P_NOTIMPLEMENTED) { + strDefinition += " /* Prodedure defined, but not implemented */"; + } + + break; + + case CDefObject::OBJECT_VARIABLE: + if (defObject.m_ulAttributes & V_IMPORT) { + strDefinition = "import "; + currentOut = OUT_IMPORTED_VARIABLE; + } + else if (defObject.m_ulAttributes & V_EXPORT) { + strDefinition = "export "; + currentOut = OUT_EXPORTED_VARIABLE; + } + else { + currentOut = OUT_GLOBAL_VARIABLE; + } + + strDefinition += "variable "; + strDefinition += m_Namespace[ulNameOffset]; + + if (!(defObject.m_ulAttributes & V_IMPORT)) { + switch(defObject.m_ulAttributes & 0xFFFF) { + case COpcode::O_STRINGOP: + strDefinition.Format(strDefinition + " := \"%s\"", m_Stringspace[defObject.m_ulVarValue].c_str()); + break; + + case COpcode::O_FLOATOP: + strDefinition.Format(strDefinition + " := %.5f", *((float*)(&defObject.m_ulVarValue))); + break; + + case COpcode::O_INTOP: + if (defObject.m_ulVarValue != 0) { + strDefinition.Format(strDefinition + " := %d", (long)defObject.m_ulVarValue); + } + + break; + } + } + + strDefinition += ";"; + + //if (((defObject.m_ulAttributes & 0xFFFF) == COpcode::O_INTOP) && + // (defObject.m_ulVarValue & 0x80000000)) { + // strDefinition.Format(strDefinition + " /* (%d) */", defObject.m_ulVarValue); + //} + } + } + else { + currentOut = OUT_UNKNOWN_VARIABLE; + strDefinition = "/* ?import? variable "; + strDefinition+= m_Namespace.GetStringByIndex(i) + "; */"; + } + + if ((currentOut != lastOut) && (lastOut != OUT_NOTHING)) { + ar.WriteString("\n"); + } + + lastOut = currentOut; + ar.WriteString(strDefinition + "\n"); + } +} + +void CFalloutScript::StoreDeclarations(CArchive& ar) +{ + CString c_strBogusProcedureName(".............."); + CString c_strArgumentTemplate("arg%u"); + CString c_strLocalVarTemplate("LVar%u"); + + printf(" Storing declarations\n"); + + CString strOutLine; + + for(INT_PTR i = 0; i < m_ProcTable.GetSize(); i++) { + printf(" Procedure: %d\r", i); + + // Bogus procedure + if ((i == 0) && (m_Namespace[m_ProcTable[i].m_ulNameOffset] == c_strBogusProcedureName.c_str())) { + continue; + } + + // Empty procedure + if (m_ProcTable.GetSizeOfProc(i) == 0) { + ar.WriteString("/*******************************************************\n"); + ar.WriteString("* Found Procedure without body. *\n"); + ar.WriteString("* *\n"); + strOutLine = "* Name: "; + strOutLine+= m_Namespace[m_ProcTable[i].m_ulNameOffset]; + + while(strOutLine.GetLength() < 55) { + strOutLine += " "; + } + + strOutLine += "*\n"; + ar.WriteString(strOutLine); + + ar.WriteString("* *\n"); + + if (!(m_ProcTable[i].m_ulType & P_NOTIMPLEMENTED)) { + ar.WriteString("* Other possible name(s): *\n"); + + for(INT_PTR j = i + 1; j < m_ProcTable.GetSize(); j++) { + if (m_ProcTable[j].m_ulBodyOffset == m_ProcTable[i].m_ulBodyOffset) { + strOutLine = "* "; + strOutLine+= m_Namespace[m_ProcTable[j].m_ulNameOffset]; + + while(strOutLine.GetLength() < 55) { + strOutLine += " "; + } + + strOutLine += "*\n"; + ar.WriteString(strOutLine); + strOutLine = "* "; + } + } + } + else { + ar.WriteString("* Not implemented *\n"); + } + + ar.WriteString("* *\n"); + ar.WriteString("*******************************************************/\n"); + ar.WriteString("\n"); + continue; + } + + // 'Normal' procedure + CProcDescriptor procDescriptor = m_ProcTable[i]; + + if (procDescriptor.m_ulType & P_CRITICAL) { + strOutLine = "critical "; + } + else { + strOutLine = ""; + } + + strOutLine += "procedure "; + strOutLine+= m_Namespace[m_ProcTable[i].m_ulNameOffset]; + + if (procDescriptor.m_ulNumArgs != 0) { + strOutLine += "("; + + for(ULONG i = 0; i < procDescriptor.m_ulNumArgs; i++) { + if (i == 0) { + strOutLine.Format(strOutLine + "variable " + c_strArgumentTemplate.c_str(), i); + } + else { + strOutLine.Format(strOutLine + ", variable " + c_strArgumentTemplate.c_str(), i); + } + } + + strOutLine += ")"; + } + + if (procDescriptor.m_ulType & P_TIMED) { + strOutLine.Format(strOutLine + " in %d", procDescriptor.m_ulTime); + } + else if (procDescriptor.m_ulType & P_CONDITIONAL) { + strOutLine.Format(strOutLine + " when (%s)", GetSource(m_Conditions.at(i).at(0), FALSE, procDescriptor.m_ulNumArgs).c_str()); + } + + ar.WriteString(strOutLine + "\n"); + + BOOL bLocalVar = TRUE; + ULONG ulLocalVarIndex = procDescriptor.m_ulNumArgs; + INT_PTR nIndentLevel = 0; + CNode::Type prevNodeType = CNode::TYPE_NORMAL; + + for(INT_PTR nNodeIndex = 0; nNodeIndex < m_ProcBodies.at(i).GetSize(); nNodeIndex++) { + if (m_ProcBodies.at(i).at(nNodeIndex).m_Type == CNode::TYPE_BEGIN_OF_BLOCK) { + /*if (((nNodeIndex - 1 > 0) && (m_ProcBodies.at(i).at(nNodeIndex - 1).m_Type == CNode::TYPE_END_OF_BLOCK)) && + ((nNodeIndex + 1 <= m_ProcBodies.at(i).GetSize()) && (m_ProcBodies.at(i)[nNodeIndex + 1].m_Opcode.GetOperator() == COpcode::O_IF))) { + ar.WriteString(GetIndentString(nIndentLevel) + "else\n"); + } + else */if ((nNodeIndex - 1 > 0) && (m_ProcBodies.at(i).at(nNodeIndex - 1).m_Type == CNode::TYPE_END_OF_BLOCK)) { + ar.WriteString(GetIndentString(nIndentLevel) + "else begin\n"); + nIndentLevel++; + } + else { + ar.WriteString("begin\n"); + nIndentLevel++; + } + prevNodeType = CNode::TYPE_BEGIN_OF_BLOCK; + } + else if (m_ProcBodies.at(i).at(nNodeIndex).m_Type == CNode::TYPE_END_OF_BLOCK) { + nIndentLevel--; + ar.WriteString(GetIndentString(nIndentLevel) + "end\n"); + prevNodeType = CNode::TYPE_END_OF_BLOCK; + } + else { + prevNodeType = CNode::TYPE_NORMAL; + WORD wOperator = m_ProcBodies.at(i).at(nNodeIndex).m_Opcode.GetOperator(); + + if ((m_ProcBodies.at(i).at(nNodeIndex).m_Opcode.GetAttributes().m_Type == COpcode::COpcodeAttributes::TYPE_EXPRESSION) && + (wOperator != COpcode::O_STRINGOP) && (wOperator != COpcode::O_FLOATOP) && (wOperator != COpcode::O_INTOP)) { + printf("Warning: Result of expression is left in stack. (Opcode 0x%04X at 0x%08X)\n", wOperator, m_ProcBodies.at(i).at(nNodeIndex).m_ulOffset); + } + + switch(wOperator) { + case COpcode::O_STRINGOP: + case COpcode::O_FLOATOP: + case COpcode::O_INTOP: + { + if (!bLocalVar) { + printf("Warning: Free value found. Converted to definition of local variable\n"); + } + + std::string str = "variable "; + str += c_strLocalVarTemplate + " := "; + + strOutLine.Format(str.c_str(), ulLocalVarIndex); + ar.WriteString(GetIndentString(nIndentLevel) + strOutLine + GetSource(m_ProcBodies.at(i).at(nNodeIndex), FALSE, procDescriptor.m_ulNumArgs) + ";\n"); + ulLocalVarIndex++; + break; + } + case COpcode::O_IF: + ar.WriteString(GetIndentString(nIndentLevel) + GetSource(m_ProcBodies.at(i).at(nNodeIndex), FALSE, procDescriptor.m_ulNumArgs) + " then "); + break; + + case COpcode::O_WHILE: + if (m_ProcBodies.at(i).at(nNodeIndex).m_Type == CNode::TYPE_FOR_LOOP) { + CString str = GetIndentString(nIndentLevel) + "for ("; + for (INT_PTR j = 0; j < m_ProcBodies.at(i).at(nNodeIndex).m_Arguments.GetSize(); j++) { + if (j > 0) str += "; "; + str += GetSource(m_ProcBodies.at(i).at(nNodeIndex).m_Arguments.at(j), FALSE, procDescriptor.m_ulNumArgs); + } + str += ") "; + ar.WriteString(str); + } else { + ar.WriteString(GetIndentString(nIndentLevel) + GetSource(m_ProcBodies.at(i).at(nNodeIndex), FALSE, procDescriptor.m_ulNumArgs) + " do "); + } + break; + + default: + ar.WriteString(GetIndentString(nIndentLevel) + GetSource(m_ProcBodies.at(i).at(nNodeIndex), FALSE, procDescriptor.m_ulNumArgs) + ";\n"); + + if ((m_ProcBodies.at(i).at(nNodeIndex).m_Type != CNode::TYPE_BEGIN_OF_BLOCK) && + (m_ProcBodies.at(i).at(nNodeIndex).m_Type != CNode::TYPE_END_OF_BLOCK)) { + bLocalVar = FALSE; + } + } + } + } + + ar.WriteString("\n"); + } +} + +CString CFalloutScript::GetSource(CNode& node, BOOL bLabel, ULONG ulNumArgs) +{ + CString c_strArgumentTemplate("arg%u"); + CString c_strLocalVarTemplate("LVar%u"); + + CString strResult("Damn!!!"); + + if (node.m_Type == CNode::TYPE_OMITTED_ARGUMENT) { + return CString("/* Omitted argument */"); + } + + WORD wOperator = node.m_Opcode.GetOperator(); + ULONG ulArgument = node.m_Opcode.GetArgument(); + + // sslc additions: + if (wOperator == COpcode::O_JMP) { + if (node.m_Type == CNode::TYPE_BREAK) { + return CString("break"); + } else if (node.m_Type == CNode::TYPE_CONTINUE) { + return CString("continue"); + } + } + switch(wOperator) { + case COpcode::O_STRINGOP: + try { + if (bLabel) { + strResult = m_Namespace[ulArgument]; + } + else { + strResult = "\""; + strResult += m_Stringspace[ulArgument] + "\""; + } + } + + catch(UserException& e) + { + printf("Warning: Restoration after exception. Object name replaced with '/* Fake object name */'\n"); + strResult = "/* Fake object name */"; + } + + break; + + case COpcode::O_FLOATOP: + strResult.Format("%.5f", *((float*)(&ulArgument))); + break; + + case COpcode::O_INTOP: + try { + if (bLabel) { + strResult = m_Namespace[ulArgument]; +// strResult = m_Namespace[m_ProcTable[ulArgument].m_ulNameOffset]; + } + else { + strResult.Format("%d", (long)ulArgument); + } + } + + catch(UserException& e) { + printf("Warning: Restoration after exception. Object name replaced with '/* Fake object name */'\n"); + strResult = "/* Fake object name */"; + } + break; + + case COpcode::O_POP_RETURN: + strResult = "return "; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + break; + + case COpcode::O_LOOKUP_STRING_PROC: + strResult = GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + break; + + case COpcode::O_FETCH_GLOBAL: + if (node.m_Arguments.at(0).m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid argument to O_FETCH_GLOBAL opcode\n"); + AfxThrowUserException(); + } + + if (INT_PTR(node.m_Arguments.at(0).m_Opcode.GetArgument()) > m_GlobalVarsNames.GetUpperBound()) { + printf("Error: Invalid index of global variable\n"); + AfxThrowUserException(); + } + + strResult = m_GlobalVarsNames.at(node.m_Arguments.at(0).m_Opcode.GetArgument()); + break; + + case COpcode::O_STORE_GLOBAL: + if (node.m_Arguments.at(1).m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid argument to O_STORE_GLOBAL opcode\n"); + AfxThrowUserException(); + } + + if (INT_PTR(node.m_Arguments.at(1).m_Opcode.GetArgument()) > m_GlobalVarsNames.GetUpperBound()) { + printf("Error: Invalid index of global variable\n"); + AfxThrowUserException(); + } + + strResult = m_GlobalVarsNames.at(node.m_Arguments.at(1).m_Opcode.GetArgument()) + " := " + GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + break; + + case COpcode::O_FETCH_EXTERNAL: + { + WORD wOperator = node.m_Arguments.at(0).m_Opcode.GetOperator(); + + if ((wOperator != COpcode::O_STRINGOP) && (wOperator != COpcode::O_INTOP)) { + printf("Error: Invalid argument to O_FETCH_EXTERNAL opcode\n"); + AfxThrowUserException(); + } + } + + strResult = GetSource(node.m_Arguments.at(0), TRUE, ulNumArgs); + break; + + case COpcode::O_STORE_EXTERNAL: + { + WORD wOperator = node.m_Arguments.at(1).m_Opcode.GetOperator(); + + if ((wOperator != COpcode::O_STRINGOP) && (wOperator != COpcode::O_INTOP)) { + printf("Error: Invalid argument to O_STORE_EXTERNAL opcode\n"); + AfxThrowUserException(); + } + } + + strResult = GetSource(node.m_Arguments.at(1), TRUE, ulNumArgs) + " := " + GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + break; + + case COpcode::O_FETCH: + if (node.m_Arguments.at(0).m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid argument to O_FETCH opcode\n"); + AfxThrowUserException(); + } + + { + ULONG ulVarNum = node.m_Arguments.at(0).m_Opcode.GetArgument(); + + if (ulVarNum < ulNumArgs) { + strResult.Format(c_strArgumentTemplate.c_str(), ulVarNum); + } + else { + strResult.Format(c_strLocalVarTemplate.c_str(), ulVarNum); + } + } + + break; + + case COpcode::O_STORE: + if (node.m_Arguments.at(1).m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid argument to O_STORE opcode\n"); + AfxThrowUserException(); + } + + { + ULONG ulVarNum = node.m_Arguments.at(1).m_Opcode.GetArgument(); + if (ulVarNum < ulNumArgs) { + strResult.Format(c_strArgumentTemplate.c_str(), ulVarNum); + } else { + strResult.Format(c_strLocalVarTemplate.c_str(), ulVarNum); + } + strResult += " := "; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + } + + break; + + case COpcode::O_POP: + strResult = GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + + if (node.m_Arguments.at(0).m_Opcode.GetOperator() == COpcode::O_CALL) { + strResult = "call "; + strResult += strResult; + } + + break; + + case COpcode::O_CALL: + if (node.m_Arguments.at(node.m_Arguments.GetUpperBound()).m_Opcode.GetOperator() == COpcode::O_INTOP) { + strResult = m_Namespace[m_ProcTable[node.m_Arguments.at(node.m_Arguments.GetUpperBound()).m_Opcode.GetArgument()].m_ulNameOffset]; + } + else { + strResult = GetSource(node.m_Arguments.at(node.m_Arguments.GetUpperBound()), FALSE, ulNumArgs); + } + + //if (node.m_Arguments.GetSize() > 2) { + strResult += "("; + + for(INT_PTR nArgIndex = 0; nArgIndex < node.m_Arguments.GetUpperBound() - 1; nArgIndex++) { + if (nArgIndex == 0) { + strResult += GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + else { + strResult += ", "; + strResult += GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + } + + strResult += ")"; + //} + + break; + + case COpcode::O_CALL_AT: + strResult = "call "; + + if (node.m_Arguments.at(1).m_Opcode.GetOperator() == COpcode::O_INTOP) { + strResult += m_Namespace[m_ProcTable[node.m_Arguments.at(1).m_Opcode.GetArgument()].m_ulNameOffset]; + } + else { + strResult += GetSource(node.m_Arguments.at(1), FALSE, ulNumArgs); + } + + strResult += " in ("; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs) + ")"; + break; + + case COpcode::O_CALL_CONDITION: + strResult = "call "; + + if (node.m_Arguments.at(1).m_Opcode.GetOperator() == COpcode::O_INTOP) { + strResult += m_Namespace[m_ProcTable[node.m_Arguments.at(1).m_Opcode.GetArgument()].m_ulNameOffset]; + } + else { + strResult += GetSource(node.m_Arguments.at(1), FALSE, ulNumArgs); + } + + strResult += " when ("; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs) + ")"; + break; + + case COpcode::O_ADDREGION: + strResult = "addRegion "; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs) + " { "; + + for(INT_PTR nArgIndex = 1; nArgIndex < node.m_Arguments.GetUpperBound(); nArgIndex++) { + if (nArgIndex == 1) { + strResult += GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + else { + strResult += ", "; + strResult += GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + } + + strResult += " }"; + break; + + case COpcode::O_REFRESHMOUSE: + { + ULONG aulProcArg[1] = { 1 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_ADDBUTTONPROC: + { + ULONG aulProcArg[4] = { 2, 3, 4, 5 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 4); + } + + break; + + case COpcode::O_ADDBUTTONRIGHTPROC: + { + ULONG aulProcArg[2] = { 2, 3 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 2); + } + + break; + + case COpcode::O_SAYOPTION: + { + if (node.m_Arguments.at(1).m_Opcode.GetOperator() == COpcode::O_INTOP) { + ULONG aulProcArg[2] = { 2 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + else { + strResult = "sayOption("; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs) + ", " + GetSource(node.m_Arguments.at(1), FALSE, ulNumArgs) + ")"; + } + } + + break; + + case COpcode::O_ADDREGIONPROC: + { + ULONG aulProcArg[4] = { 2, 3, 4, 5 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 4); + } + + break; + + case COpcode::O_ADDREGIONRIGHTPROC: + { + ULONG aulProcArg[2] = { 2, 3 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 2); + } + + break; + + case COpcode::O_ADDNAMEDEVENT: + { + ULONG aulProcArg[1] = { 2 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_ADDNAMEDHANDLER: + { + ULONG aulProcArg[1] = { 2 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_ADDKEY: + { + ULONG aulProcArg[1] = { 2 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_GSAY_OPTION: + { + ULONG aulProcArg[1] = { 3 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_GIQ_OPTION: + { + ULONG aulProcArg[1] = { 4 }; + strResult = GetSource(node, bLabel, ulNumArgs, aulProcArg, 1); + } + + break; + + case COpcode::O_CANCEL: + if (node.m_Arguments.at(0).m_Opcode.GetOperator() != COpcode::O_INTOP) { + printf("Error: Invalid argument to O_CANCEL opcode\n"); + AfxThrowUserException(); + } + + strResult = "cancel("; + strResult += m_Namespace[m_ProcTable[node.m_Arguments.at(0).m_Opcode.GetArgument()].m_ulNameOffset] + ")"; + break; + + case COpcode::O_NEGATE: + if (node.m_Arguments.at(0).m_Opcode.GetAttributes().m_Category == COpcode::COpcodeAttributes::CATEGORY_INFIX) { + strResult = "-("; + strResult += GetSource(node.m_Arguments.at(0), bLabel, ulNumArgs) + ")"; + } + else { + strResult = "-"; + strResult += GetSource(node.m_Arguments.at(0), bLabel, ulNumArgs); + } + + break; + +// case COpcode::O_SETGLOBALMOUSEFUNC: +// printf("Warning: Fallout2 don'\t have implemented handler for O_SETGLOBALMOUSEFUNC opcode\n"); +// continue default execution + + default: + COpcode::COpcodeAttributes attributes = node.m_Opcode.GetAttributes(); + ULONG *procArgs = attributes.m_procArgs; + ULONG numProcArgs = attributes.m_numProcArgs; + if (numProcArgs > 0) { + strResult = GetSource(node, bLabel, ulNumArgs, procArgs, numProcArgs); + break; + } + if (node.m_Type == CNode::TYPE_CONDITIONAL_EXPRESSION) { + if (node.m_Arguments.GetSize() != 3) { + printf("Error: Invalid number of arguments in conditional expression\n"); + AfxThrowUserException(); + } + CString sPostfix[] = { CString(" if "), CString(" else "), CString("")}; + strResult = ""; + for(INT_PTR i = 0; i < node.m_Arguments.GetSize(); i++) { + bool bParens = ArgNeedParens(node, node.m_Arguments.at(i), CFalloutScript::RIGHT_ASSOC); + strResult += (bParens ? CString("(") : CString("")) + GetSource(node.m_Arguments.at(i), bLabel, ulNumArgs) + (bParens ? ")" : "") + sPostfix[i]; + } + break; + } + switch(attributes.m_Category) { + case COpcode::COpcodeAttributes::CATEGORY_INFIX: + if (ArgNeedParens(node, node.m_Arguments.at(0), CFalloutScript::LEFT_ASSOC)) { + strResult = "("; + strResult += GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs) + ")"; + } + else { + strResult = GetSource(node.m_Arguments.at(0), FALSE, ulNumArgs); + } + + strResult += " "; + strResult += attributes.m_strName + " "; + + + if (ArgNeedParens(node, node.m_Arguments.at(1), CFalloutScript::RIGHT_ASSOC)) { + strResult += "("; + strResult += GetSource(node.m_Arguments.at(1), FALSE, ulNumArgs) + ")"; + } + else { + strResult += GetSource(node.m_Arguments.at(1), FALSE, ulNumArgs); + } + + break; + + case COpcode::COpcodeAttributes::CATEGORY_PREFIX: + strResult = attributes.m_strName; + + if (node.m_Arguments.GetSize() != 0) { + if (wOperator == COpcode::O_IF || wOperator == COpcode::O_WHILE) { + strResult += " "; + } + + strResult += "("; + + for(INT_PTR i = 0; i < node.m_Arguments.GetSize(); i++) { + if (i == 0) { + strResult += GetSource(node.m_Arguments.at(i), FALSE, ulNumArgs); + } + else { + strResult += ", "; + strResult += GetSource(node.m_Arguments.at(i), FALSE, ulNumArgs); + } + } + + strResult += ")"; + } + + break; + } + } + + return strResult; +} + +CString CFalloutScript::GetSource( CNode& node, BOOL bLabel, ULONG ulNumArgs, ULONG aulProcArg[], ULONG ulProcArgCount) +{ + COpcode::COpcodeAttributes attributes = node.m_Opcode.GetAttributes(); + CString strResult = attributes.m_strName + "("; + CString strArgument; + BOOL bIsProcArg; + + for(INT_PTR nArgIndex = 0; nArgIndex < node.m_Arguments.GetSize(); nArgIndex++) { + bIsProcArg = FALSE; + + for(ULONG ulProcArgIndex = 0; ulProcArgIndex < ulProcArgCount; ulProcArgIndex++) { + if (nArgIndex == aulProcArg[ulProcArgIndex] - 1) { + bIsProcArg = TRUE; + break; + } + } + + if (bIsProcArg) { + if (node.m_Arguments.at(nArgIndex).m_Opcode.GetOperator() == COpcode::O_INTOP) { + try + { + strArgument = m_Namespace[m_ProcTable[node.m_Arguments.at(nArgIndex).m_Opcode.GetArgument()].m_ulNameOffset]; + } + + catch(UserException& e) { + printf("Warning: Restoration after exception. Object name replaced with '/* Fake object name */'\n"); + strArgument.Format("/* Fake object name: %u (%d)*/", node.m_Arguments.at(nArgIndex).m_Opcode.GetArgument(), node.m_Arguments.at(nArgIndex).m_Opcode.GetArgument()); + } + + } + else { + strArgument = GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + } + else { + strArgument = GetSource(node.m_Arguments.at(nArgIndex), FALSE, ulNumArgs); + } + + if (nArgIndex == 0) { + strResult += strArgument; + } + else { + strResult += ", "; + strResult += strArgument; + } + } + + strResult += ")"; + + return strResult; +} + +CString CFalloutScript::GetIndentString(INT_PTR nLevel) +{ + CString strResult; + + for(; nLevel > 0; nLevel--) { + strResult += g_strIndentFill; + } + + return strResult; +} + +int CFalloutScript::GetPriority(WORD wOperator) +{ + switch(wOperator) { + case COpcode::O_IF: + return 0; + case COpcode::O_OR: + case COpcode::O_AND: + return 2; + + case COpcode::O_GREATER: + case COpcode::O_LESS: + case COpcode::O_GREATER_EQUAL: + case COpcode::O_LESS_EQUAL: + case COpcode::O_EQUAL: + case COpcode::O_NOT_EQUAL: + return 3; + + case COpcode::O_ADD: + case COpcode::O_SUB: + case COpcode::O_BWXOR: + case COpcode::O_BWOR: + case COpcode::O_BWAND: + return 4; + + case COpcode::O_MUL: + case COpcode::O_DIV: + case COpcode::O_MOD: + case COpcode::O_TS_POW: + return 5; + + default: + return 6; + } +} + +CFalloutScript::Assoc CFalloutScript::GetAssociation(WORD wOperator) +{ + switch(wOperator) { + case COpcode::O_GREATER: + case COpcode::O_LESS: + case COpcode::O_GREATER_EQUAL: + case COpcode::O_LESS_EQUAL: + case COpcode::O_EQUAL: + case COpcode::O_NOT_EQUAL: + return CFalloutScript::NON_ASSOC; + + case COpcode::O_OR: + case COpcode::O_AND: + case COpcode::O_ADD: + case COpcode::O_SUB: + case COpcode::O_BWXOR: + case COpcode::O_BWOR: + case COpcode::O_BWAND: + case COpcode::O_MUL: + case COpcode::O_DIV: + case COpcode::O_MOD: + return CFalloutScript::LEFT_ASSOC; + + default: + return CFalloutScript::NON_ASSOC; + } +} + diff --git a/Hacks/CArchive.cpp b/Hacks/CArchive.cpp new file mode 100644 index 0000000..50dc152 --- /dev/null +++ b/Hacks/CArchive.cpp @@ -0,0 +1,28 @@ +#include "CArchive.h" + +CArchive::CArchive(CFile* file, unsigned int mode) +{ + _file = file; +} + +void CArchive::Flush() +{ +} + +CFile* CArchive::GetFile() +{ + return _file; +} + +void CArchive::WriteString(const char * value) +{ + _file->_ostream << value; +} + +ULONG CArchive::Read(char *buffer, ULONG size) +{ + ULONG count; + count = _file->_istream.readsome(buffer, size); + //_file->_istream.seekg(_file->_istream.tellg(), std::ios_base::beg); + return count; +} diff --git a/Hacks/CArchive.h b/Hacks/CArchive.h new file mode 100644 index 0000000..902f4fa --- /dev/null +++ b/Hacks/CArchive.h @@ -0,0 +1,28 @@ +#ifndef CARCHIVE_H +#define CARCHIVE_H + +#include "../Hacks/Types.h" +#include "../Hacks/CFile.h" + +class CArchive +{ +protected: + CFile* _file = 0; + +public: + static const unsigned int load = 1; + static const unsigned int store = 2; + + CArchive(CFile* file, unsigned int mode); + void Flush(); + + CFile* GetFile(); + + void WriteString(const char * value); + + ULONG Read(char * buffer, ULONG size); + + +}; + +#endif // CARCHIVE_H diff --git a/Hacks/CArray.cpp b/Hacks/CArray.cpp new file mode 100644 index 0000000..e05b14c --- /dev/null +++ b/Hacks/CArray.cpp @@ -0,0 +1,2 @@ +#include "CArray.h" + diff --git a/Hacks/CArray.h b/Hacks/CArray.h new file mode 100644 index 0000000..df96552 --- /dev/null +++ b/Hacks/CArray.h @@ -0,0 +1,71 @@ +#ifndef CARRAY_H +#define CARRAY_H + +#include "../Hacks/Types.h" +#include + +template +class CArray +{ + std::vector _vector; +public: + CArray() + { + } + + void RemoveAll() + { + while (!_vector.empty()) _vector.pop_back(); + } + + void Add(A value) + { + _vector.push_back(value); + } + + bool IsEmpty() + { + return _vector.empty(); + } + + INT_PTR GetUpperBound() + { + if (_vector.size() == 0) return 0; + return _vector.size() - 1; + } + + void RemoveAt(ULONG n, ULONG count = 1) + { + _vector.erase(_vector.begin() + n, _vector.begin() + n + count); + } + + ULONG GetSize() + { + return _vector.size(); + } + + void SetSize(ULONG n) + { + _vector.resize(n); + } + + void InsertAt(ULONG position, A value) + { + _vector.insert(_vector.begin() + position, value); + } + + A& at(ULONG n) + { + return _vector.at(n); + } + + void Copy(CArray source) + { + for (auto it = source._vector.begin(); it != source._vector.end(); ++it) + { + _vector.push_back(*it); + } + } +}; + +#endif // CARRAY_H diff --git a/Hacks/CFile.cpp b/Hacks/CFile.cpp new file mode 100644 index 0000000..3ce2b1c --- /dev/null +++ b/Hacks/CFile.cpp @@ -0,0 +1,78 @@ +#include "CFile.h" + +#include + +CFile::CFile() +{ +} + +bool CFile::Open(CString name, unsigned int mode) +{ + switch (_mode) + { + case modeRead: + _istream.open(name.c_str(), std::ios_base::in | std::ios_base::binary); + return _istream.is_open(); + break; + + case modeWrite: + _ostream.open(name.c_str(), std::ios_base::out | std::ios_base::ate); + return _ostream.is_open(); + } +} + +ULONG CFile::GetPosition() +{ + switch (_mode) + { + case modeWrite: + return _ostream.tellp(); + break; + } + + return _istream.tellg(); +} + +void CFile::Seek(ULONG position, unsigned int mode) +{ + switch (_mode) + { + case modeWrite: + _ostream.seekp(position, std::ios_base::beg); + break; + default: + _istream.seekg(position, std::ios_base::beg); + break; + } +} + +ULONG CFile::GetLength() +{ + ULONG size = 0; + switch (_mode) + { + case modeWrite: + { + ULONG oldPosition = _ostream.tellp(); + _ostream.seekp(0, std::ios_base::end); + size = _ostream.tellp(); + _ostream.seekp(oldPosition, std::ios_base::beg); + break; + } + default: + { + ULONG oldPosition = _istream.tellg(); + _istream.seekg(0, std::ios_base::end); + size = _istream.tellg(); + _istream.seekg(oldPosition, std::ios_base::beg); + break; + } + } + + return size; +} + +CStdioFile::CStdioFile() : CFile() +{ + +} diff --git a/Hacks/CFile.h b/Hacks/CFile.h new file mode 100644 index 0000000..21be967 --- /dev/null +++ b/Hacks/CFile.h @@ -0,0 +1,43 @@ +#ifndef CFILE_H +#define CFILE_H + +#include + +#include "../Hacks/Types.h" +#include "../Hacks/CString.h" + +class CFile +{ + protected: + unsigned int _mode = 1; + + + public: + std::ifstream _istream; + std::ofstream _ostream; + static const unsigned int modeRead = 1; + static const unsigned int modeWrite = 2; + static const unsigned int shareDenyWrite = 3; + static const unsigned int modeCreate = 4; + static const unsigned int typeText = 5; + static const unsigned int begin = 6; + + + CFile(); + + bool Open(CString name, unsigned int mode); + ULONG GetPosition(); + void Seek(ULONG position, unsigned int mode); + ULONG GetLength(); + +}; + +class CStdioFile : public CFile +{ +protected: + unsigned int _mode = 2; +public: + CStdioFile(); +}; + +#endif // CFILE_H diff --git a/Hacks/CMap.cpp b/Hacks/CMap.cpp new file mode 100644 index 0000000..5ee0ef8 --- /dev/null +++ b/Hacks/CMap.cpp @@ -0,0 +1,2 @@ +#include "CMap.h" + diff --git a/Hacks/CMap.h b/Hacks/CMap.h new file mode 100644 index 0000000..55b35ed --- /dev/null +++ b/Hacks/CMap.h @@ -0,0 +1,53 @@ +#ifndef CMAP_H +#define CMAP_H + +#include +#include "../Hacks/Types.h" + +template +class CMap +{ + std::map _map; + + public: + CMap() + { + } + + ULONG GetSize() const + { + return _map.size(); + } + + void RemoveAll() + { + _map.clear(); + } + + void SetAt(ULONG offset, C value) + { + if (_map.find(offset) != _map.end()) + { + _map.at(offset) = value; + } + + _map.insert(std::pair(offset, value)); + } + + bool Lookup(ULONG offset, C& value) const + { + if (_map.find(offset) != _map.end()) + { + value = _map.at(offset); + return true; + } + return false; + } + + void InitHashTable(ULONG n) + { + + } +}; + +#endif // CMAP_H diff --git a/Hacks/CString.cpp b/Hacks/CString.cpp new file mode 100644 index 0000000..f6add18 --- /dev/null +++ b/Hacks/CString.cpp @@ -0,0 +1,101 @@ +#include "CString.h" + +#include + +CString::CString() +{ +} + +CString::CString(std::string string) +{ + _string = string; +} + +CString::CString(const CString& cstring) +{ + _string = cstring._string; +} + +const char * CString::c_str() const +{ + return _string.c_str(); +} + +CString& CString::operator=(const char* value) +{ + _string += value; + return *this; +} + +CString& CString::operator+=(const char* value) +{ + _string += value; + return *this; +} + +CString& CString::operator+(const char* value) +{ + _string += value; + return *this; +} + +CString::operator const char* () const +{ + return _string.c_str(); +} + +void CString::MakeLower() +{ + std::transform(_string.begin(), _string.end(), _string.begin(), ::tolower); +} + +ULONG CString::GetLength() +{ + return _string.length(); +} + +char* CString::GetBuffer(ULONG size) +{ + return (char*) _string.data(); +} + + +void CString::ReleaseBufferSetLength(ULONG size) +{ + _string.resize(size); +} + +void CString::ReleaseBuffer() +{ + +} + +void CString::Format(const char *format, ...) +{ + char buff[1024]; + int size; + + va_list args; + va_start( args, format ); + + size = sprintf(buff, format, args); + std::string stroka(buff, size); + _string = stroka; +} + +std::string CString::str() +{ + return _string; +} + +void CString::Replace(CString search, CString replace) +{ + std::string str = _string; + size_t pos = 0; + while((pos = str.find(search.str(), pos)) != std::string::npos) + { + str.replace(pos, search.str().length(), replace.str()); + pos += replace.str().length(); + } + _string = str; +} diff --git a/Hacks/CString.h b/Hacks/CString.h new file mode 100644 index 0000000..83de9f7 --- /dev/null +++ b/Hacks/CString.h @@ -0,0 +1,33 @@ +#ifndef CSTRING_H +#define CSTRING_H + +#include +#include + +#include "../Hacks/Types.h" + +class CString +{ +protected: + std::string _string; +public: + CString(); + CString(std::string string); + CString(const CString& cstring); + + const char* c_str() const; + CString& operator=(const char* value); + CString& operator+=(const char* value); + CString& operator+(const char* value); + operator const char* () const; + void MakeLower(); + ULONG GetLength(); + char* GetBuffer(ULONG size); + void ReleaseBufferSetLength(ULONG size); + void ReleaseBuffer(); + std::string str(); + + void Format(const char * format, ...); + void Replace(CString search, CString replacement); +}; +#endif // CSTRING_H diff --git a/Hacks/Types.h b/Hacks/Types.h new file mode 100644 index 0000000..b3a7778 --- /dev/null +++ b/Hacks/Types.h @@ -0,0 +1,20 @@ +#ifndef TYPES_H +#define TYPES_H + +#include +#include + +typedef char BYTE; +typedef const char * LPCTSTR; +typedef char * LPTSTR; +typedef unsigned int ULONG; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef unsigned int UINT; +typedef bool BOOL; +typedef char TCHAR; +#define TRUE true +#define FALSE false +typedef size_t INT_PTR; + +#endif // TYPES_H diff --git a/Namespace.cpp b/Namespace.cpp new file mode 100644 index 0000000..de31b05 --- /dev/null +++ b/Namespace.cpp @@ -0,0 +1,158 @@ +// Namespace.cpp : implementation file +// + +#include "stdafx.h" +#include "Namespace.h" +#include "Utility.h" + +#include "Hacks/CString.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// CNamespace + +CNamespace::CNamespace() +{ + m_Map.InitHashTable(128); +} + +CNamespace::~CNamespace() +{ +} + +void CNamespace::Serialize(CArchive& ar) +{ + //if (ar.IsStoring()) { + if (false) + { + //ASSERT(FALSE); + } + else { + m_Map.RemoveAll(); + m_Order.RemoveAll(); + + ULONG ulLength; + + if (ReadMSBULong(ar, ulLength) != 4) { + printf("Error: Unable read length of namespace\n"); + AfxThrowUserException(); + } + + if (ulLength != 0xFFFFFFFF) { + ULONG ulTotalRead = 0; + WORD wLengthOfString; + CString strNewString; + LPTSTR lpszNewString; + + while(ulTotalRead < ulLength) { + if (ReadMSBWord(ar, wLengthOfString) != 2) { + printf("Error: Unable read length of string\n"); + AfxThrowUserException(); + }; + + if ((wLengthOfString < 2) || (wLengthOfString & 0x0001)) { + printf("Error: Invalid length of string\n"); + AfxThrowUserException(); + } + + lpszNewString = strNewString.GetBuffer(wLengthOfString); + + if (ar.Read(lpszNewString, wLengthOfString) != wLengthOfString) { + strNewString.ReleaseBufferSetLength(0); + printf("Error: Unable read string in namespace\n"); + AfxThrowUserException(); + } + + if ((lpszNewString[wLengthOfString - 1] != '\x00') && (lpszNewString[wLengthOfString - 2] != '\x00')) { + strNewString.ReleaseBufferSetLength(0); + printf("Error: Invalid end of string in namespace\n"); + AfxThrowUserException(); + } + + strNewString.ReleaseBuffer(); + +/* + // Convert Nongraphic Characters to Escape sequence + CString strNonGraph("\\\a\b\f\n\r\t\""); + CString strEscape("\\abfnrt\""); + + for(int i = 0; i < strNonGraph.GetLength(); i++) { + strNewString.Replace(CString(strNonGraph[i]), CString('\\') + strEscape[i]); + } +*/ + m_Map.SetAt(ulTotalRead + 6, strNewString); + m_Order.Add(ulTotalRead + 6); + + ulTotalRead += (2 + wLengthOfString); + } + + ULONG ulTerminator; + + if (ReadMSBULong(ar, ulTerminator) != 4) { + printf("Error: Unable read terminator of namespace\n"); + AfxThrowUserException(); + } + + if (ulTerminator != 0xFFFFFFFF) { + printf("Error: Invalid terminator of namespace\n"); + AfxThrowUserException(); + } + +// //For debugging only +// for(INT_PTR i = 0; i < GetSize(); i++) { +// printf("Offset: 0x%08X (%9d), string: %s\n", m_Order[i], m_Order[i], GetStringByIndex(i)); +// } +// +// printf("\n"); + } + } +} + +INT_PTR CNamespace::GetSize() const +{ + return m_Map.GetSize(); +} + +CString CNamespace::GetStringByIndex(INT_PTR nIndex) +{ + return (this->operator [] (m_Order.at(nIndex))); +} + +ULONG CNamespace::GetOffsetByIndex(INT_PTR nIndex) +{ + return m_Order.at(nIndex); +} + +void CNamespace::Dump(CArchive& ar) +{ + CString strOutLine; + + if (m_Order.IsEmpty()) { + ar.WriteString("Empty\n"); + } + else { + for(INT_PTR i = 0; i < m_Order.GetSize(); i++) { + strOutLine.Format("0x%08X: \"%s\"\n", m_Order.at(i), GetStringByIndex(i).c_str()); + ar.WriteString(strOutLine); + } + + ar.WriteString("==================\n"); + strOutLine.Format("%d item(s)\n", m_Order.GetSize()); + ar.WriteString(strOutLine); + } +} + +CString CNamespace::operator [] (ULONG ulOffset) const +{ + CString strResult; + + if (!m_Map.Lookup(ulOffset, strResult)) { + printf("Error: No string at offset 0x%08x\n", ulOffset); + AfxThrowUserException(); + } + + return strResult; +} diff --git a/Namespace.h b/Namespace.h new file mode 100644 index 0000000..625673a --- /dev/null +++ b/Namespace.h @@ -0,0 +1,36 @@ +#pragma once + +#ifndef NAMESPACE_H +#define NAMESPACE_H + +#include "Hacks/CArchive.h" +#include "Hacks/CMap.h" + +// CNamespace +class CNamespace : public CObject { +public: + CNamespace(); + virtual ~CNamespace(); + +public: + virtual void Serialize(CArchive& ar); + +public: + INT_PTR GetSize() const; + CString GetStringByIndex(INT_PTR nIndex) ; + ULONG GetOffsetByIndex(INT_PTR nIndex) ; + + void Dump(CArchive& ar); + +public: + CString operator [] (ULONG ulOffset) const; + +private: + // CMapDWordToString + typedef CMap CMapDWordToString; + + CMapDWordToString m_Map; + CDWordArray m_Order; +}; + +#endif diff --git a/Node.cpp b/Node.cpp new file mode 100644 index 0000000..ce15f1e --- /dev/null +++ b/Node.cpp @@ -0,0 +1,117 @@ +// Node.cpp : implementation file +// + +#include "stdafx.h" +#include "Node.h" + + +// CNode + +CNode::CNode(Type type) : + m_ulOffset(0), + m_Type(type) +{ +} + + +CNode::CNode(const CNode& node) : + m_ulOffset(node.m_ulOffset), + m_Opcode(node.m_Opcode), + m_Type(node.m_Type) +{ + m_Arguments.Copy(node.m_Arguments); +} + +CNode::~CNode() +{ +} + +CNode& CNode::operator = (const CNode& node) +{ + if (&node != this) { + m_ulOffset = node.m_ulOffset; + m_Opcode = node.m_Opcode; + m_Type = node.m_Type; + m_Arguments.Copy(node.m_Arguments); + } + + return (*this); +} + +void CNode::StoreTree(CArchive& ar, int nIndent, int nIndex) +{ + // Indent + if (nIndex != 0) { + ar.WriteString(" "); + + for(int i = 0; i < nIndent; i++) { + ar.WriteString(" "); + } + } + + switch(m_Type) { + case TYPE_BEGIN_OF_BLOCK: + ar.WriteString("========= begin of block =========\n"); + return; + + case TYPE_END_OF_BLOCK: + ar.WriteString("========= end of block =========\n"); + return; + } + + // Node + CString strOutLine; + WORD wOperator = m_Opcode.GetOperator(); + ULONG ulArgument = m_Opcode.GetArgument(); + + switch(wOperator) { + case COpcode::O_STRINGOP: + case COpcode::O_INTOP: + strOutLine.Format("0x%04X 0x%08x ", + wOperator, + ulArgument); + ar.WriteString(strOutLine); + break; + + case COpcode::O_FLOATOP: + strOutLine.Format("0x%04X 0x%08X ", + wOperator, + ulArgument); + ar.WriteString(strOutLine); + break; + + default: + strOutLine.Format("0x%04X .......... ", + wOperator); + ar.WriteString(strOutLine); + } + if (!m_Arguments.IsEmpty()) { + for(int i = 0; i < m_Arguments.GetSize(); i++) { + m_Arguments.at(i).StoreTree(ar, nIndent + 1, i); + } + } + else { + ar.WriteString("\n"); + } + +} + +ULONG CNode::GetTopOffset() +{ + if (m_Arguments.GetSize() > 0) + return m_Arguments.at(0).GetTopOffset(); + else + return m_ulOffset; +} + +bool CNode::IsExpression() const +{ + return (m_Opcode.GetAttributes().m_Type == COpcode::COpcodeAttributes::TYPE_EXPRESSION + || m_Type == TYPE_CONDITIONAL_EXPRESSION); +} + +bool CNode::IsInfix() const +{ + return (m_Opcode.GetAttributes().m_Category == COpcode::COpcodeAttributes::CATEGORY_INFIX + || m_Type == TYPE_CONDITIONAL_EXPRESSION); +} diff --git a/Node.h b/Node.h new file mode 100644 index 0000000..dfea829 --- /dev/null +++ b/Node.h @@ -0,0 +1,65 @@ +#pragma once + +#ifndef NODE_H +#define NODE_H + +#include "Namespace.h" +#include "Opcode.h" + + +// Forward declaration of CNode +class CNode; + + +// CNodeArray +typedef CArray CNodeArray; + + +// CNode +class CNode : public CObject { +public: + enum Type { + TYPE_NORMAL, + TYPE_BEGIN_OF_BLOCK, + TYPE_END_OF_BLOCK, + TYPE_OMITTED_ARGUMENT, + TYPE_BREAK, + TYPE_CONTINUE, + TYPE_FOR_LOOP, + TYPE_CONDITIONAL_EXPRESSION + }; + +public: + CNode(Type type = TYPE_NORMAL); + CNode(const CNode& node); + virtual ~CNode(); + +public: + CNode& operator = (const CNode& node); + +public: + void StoreTree(CArchive& ar, int nIndent, int nIndex); + ULONG GetTopOffset(); + bool IsExpression() const; + bool IsInfix() const; + +public: + ULONG m_ulOffset; + COpcode m_Opcode; + + Type m_Type; + CNodeArray m_Arguments; +}; + + +// CNodeArray +typedef CArray CNodeArray; + +// CArrayOfNodeArray +typedef CArray CArrayOfNodeArray; + +// 'Begin' end 'End of block' 'End Else Begin' nodes +const CNode c_NodeBeginOfBlock(CNode::TYPE_BEGIN_OF_BLOCK); +const CNode c_NodeEndOfBlock(CNode::TYPE_END_OF_BLOCK); + +#endif diff --git a/ObjectAttributes.h b/ObjectAttributes.h new file mode 100644 index 0000000..cb925d0 --- /dev/null +++ b/ObjectAttributes.h @@ -0,0 +1,26 @@ +#pragma once + +#ifndef OBJECT_ATTRIBUTES_H +#define OBJECT_ATTRIBUTES_H + + +// ProcedureAttributes +enum ProcAttributes { + P_TIMED = 0x01, + P_CONDITIONAL = 0x02, + P_IMPORT = 0x04, + P_EXPORT = 0x08, + P_CRITICAL = 0x10, + + P_NOTIMPLEMENTED = 0x80000000 +}; + + +// VariableAtributes +enum VariableAtributes { + V_GLOBAL = 0x00010000, + V_IMPORT = 0x00020000, + V_EXPORT = 0x00040000 +}; + +#endif diff --git a/Opcode.cpp b/Opcode.cpp new file mode 100644 index 0000000..48f7258 --- /dev/null +++ b/Opcode.cpp @@ -0,0 +1,172 @@ +// Opcode.cpp : implementation file +// + +#include "stdafx.h" +#include "Opcode.h" +#include "Utility.h" + + +#include + +// Globals +extern int g_nFalloutVersion; + + +// COpcode + +COpcode::COpcode() : + m_wOperator(O_NOOP), + m_ulArgument(0) +{ +} + +COpcode::COpcode(const COpcode& opcode) : + m_wOperator(opcode.m_wOperator), + m_ulArgument(opcode.m_ulArgument) +{ +} + + +COpcode::~COpcode() +{ +} + +COpcode& COpcode::operator = (const COpcode& opcode) +{ + m_wOperator = opcode.m_wOperator; + m_ulArgument = opcode.m_ulArgument; + + return (*this); +} + +void COpcode::Serialize(CArchive& ar) +{ + //if (ar.IsStoring()) { + if (false) + { + // ASSERT(FALSE); + } + else + { + if (ReadMSBWord(ar, m_wOperator) != OPERATOR_SIZE) { + + printf("Error: Unable read opcode\n"); + AfxThrowUserException(); + } + + std::cout << std::hex << m_wOperator << std::endl; + + if ((m_wOperator < O_OPERATOR) || + ((m_wOperator >= O_END_OP) && + (m_wOperator != O_STRINGOP) && + (m_wOperator != O_FLOATOP)&& + (m_wOperator != O_INTOP))) { + ar.Flush(); + printf("Error: Invalid opcode at 0x%08x\n", ar.GetFile()->GetPosition() - 2); + AfxThrowUserException(); + } + + if ((m_wOperator == O_STRINGOP) || (m_wOperator == O_FLOATOP) || (m_wOperator == O_INTOP)) { + if (ReadMSBULong(ar, m_ulArgument) != ARGUMENT_SIZE) { + printf("Error: Unable read opcode argument\n"); + AfxThrowUserException(); + } + } + } +} + +void COpcode::Expect(CArchive& ar, WORD wOperator, BOOL bArgumentFound, ULONG ulArgument) +{ + Serialize(ar); + + if (m_wOperator != wOperator) { + printf("Error: Unexpected opcode (0x%04X expected, but 0x%04X found)\n", wOperator, m_wOperator); + AfxThrowUserException(); + } + + if (bArgumentFound && ((m_wOperator == O_STRINGOP) || (m_wOperator == O_FLOATOP) || (m_wOperator == O_INTOP))) { + if (m_ulArgument != ulArgument) { + printf("Error: Unexpected argument of opcode. (0x%08X expected, but 0x%08X found)\n", ulArgument, m_ulArgument); + AfxThrowUserException(); + } + } +} + +void COpcode::Expect(CArchive& ar, int nCount, WORD pwOperators[]) +{ + Serialize(ar); + BOOL bFound = FALSE; + + for(int i = 0; i < nCount; i++) { + if (m_wOperator == pwOperators[i]) { + bFound = TRUE; + break; + } + } + + if (!bFound) { + printf("Error: Unexpected opcode ("); + + for(int i = 0; i < nCount; i++) { + if (i != 0) { + printf(" or "); + } + + printf("0x%04X", pwOperators[i]); + } + + printf(" expected, but 0x%04X found)\n", m_wOperator); + AfxThrowUserException(); + } +} + +BOOL COpcode::HasArgument() const +{ + return ((m_wOperator == O_STRINGOP) || (m_wOperator == O_FLOATOP) || (m_wOperator == O_INTOP)); +} + +int COpcode::GetSize() const +{ + if ((m_wOperator == O_STRINGOP) || (m_wOperator == O_FLOATOP) || (m_wOperator == O_INTOP)) { + return OPERATOR_SIZE + ARGUMENT_SIZE; + } + else { + return OPERATOR_SIZE; + } +} + +WORD COpcode::GetOperator() const +{ + return m_wOperator; +} + +void COpcode::SetOperator(WORD op) +{ + m_wOperator = op; +} + +ULONG COpcode::GetArgument() const +{ + return m_ulArgument; +} + +const COpcode::COpcodeAttributes COpcode::GetAttributes() const +{ + static CF1OpcodeAttributesMap f1OpcodeAttributes; + static CF2OpcodeAttributesMap f2OpcodeAttributes; + + COpcodeAttributes result; + + if (g_nFalloutVersion == 1) { + if (f1OpcodeAttributes.Lookup(m_wOperator, result)) { + return result; + } + } + + if (!f2OpcodeAttributes.Lookup(m_wOperator, result)) { + printf("Error: Attempt to obtain attributes of unknown opcode\n"); + AfxThrowUserException(); + } + + return result; +} diff --git a/Opcode.h b/Opcode.h new file mode 100644 index 0000000..b96dcb0 --- /dev/null +++ b/Opcode.h @@ -0,0 +1,845 @@ +#pragma once + +#ifndef OPCODE_H +#define OPCODE_H + +#include "Hacks/CString.h" +#include "Hacks/CArchive.h" +#include "Hacks/CMap.h" + +// COpcode +class COpcode : public CObject { +public: + enum Size { + OPERATOR_SIZE = 2, + ARGUMENT_SIZE = 4 + }; + + enum O_Base { + O_STRING = 0x1000, + O_FLOAT = 0x2000, + O_INT = 0x4000, + O_OPERATOR = 0x8000 + }; + + // const O_IF_EXPR = 1000; + + enum O_Core { + O_NOOP = O_OPERATOR, + O_CONST, + O_CRITICAL_START, + O_CRITICAL_DONE, + O_JMP, + O_CALL, + O_CALL_AT, // timed function calls + O_CALL_CONDITION, + O_CALLSTART, + O_EXEC, + O_SPAWN, + O_FORK, + O_A_TO_D, + O_D_TO_A, + O_EXIT, // exit prog and purge it from process queue + O_DETACH, // detach spawned process from its parent. + O_EXIT_PROG, // exit program but leave it in process queue + O_STOP_PROG, + O_FETCH_GLOBAL, + O_STORE_GLOBAL, + O_FETCH_EXTERNAL, + O_STORE_EXTERNAL, + O_EXPORT_VAR, + O_EXPORT_PROC, + O_SWAP, + O_SWAPA, + O_POP, + O_DUP, + O_POP_RETURN, + O_POP_EXIT, + O_POP_ADDRESS, + O_POP_FLAGS, + O_POP_FLAGS_RETURN, + O_POP_FLAGS_EXIT, + O_POP_FLAGS_RETURN_EXTERN, + O_POP_FLAGS_EXIT_EXTERN, + O_POP_FLAGS_RETURN_VAL_EXTERN, + + // return from a procedure called from C, leaving the return value + // on the stack. + O_POP_FLAGS_RETURN_VAL_EXIT, + O_POP_FLAGS_RETURN_VAL_EXIT_EXTERN, + + O_CHECK_ARG_COUNT, // call to do a run-time check of arguments to functions + O_LOOKUP_STRING_PROC, // call to lookup a procedure index given a string + O_POP_BASE, + O_POP_TO_BASE, + O_PUSH_BASE, + O_SET_GLOBAL, + O_FETCH_PROC_ADDRESS, + O_DUMP, + O_IF, + O_WHILE, + O_STORE, + O_FETCH, + O_EQUAL, + O_NOT_EQUAL, + O_LESS_EQUAL, + O_GREATER_EQUAL, + O_LESS, + O_GREATER, + O_ADD, + O_SUB, + O_MUL, + O_DIV, + O_MOD, + O_AND, + O_OR, + O_BWAND, + O_BWOR, + O_BWXOR, + O_BWNOT, + O_FLOOR, + O_NOT, + O_NEGATE, + O_WAIT, + O_CANCEL, + O_CANCELALL, + + O_STARTCRITICAL, + O_ENDCRITICAL, + + O_END_CORE // don't use this anywhere, or you'll die + }; + + enum O_Lib { + O_SAYQUIT = O_END_CORE, + O_SAYEND, + O_SAYSTART, + O_SAYSTARTPOS, + O_SAYREPLYTITLE, + O_SAYGOTOREPLY, + O_SAYREPLY, + O_SAYOPTION, + O_SAYMESSAGE, + O_SAYREPLYWINDOW, // sayreplywindow(sx, sy, w, h, "fill3x3 pattern"); + O_SAYOPTIONWINDOW, // sayoptionwindow '' + O_SAYBORDER, // sayoptionborder(x, y) + O_SAYSCROLLUP, + O_SAYSCROLLDOWN, + O_SAYSETSPACING, + O_SAYOPTIONCOLOR, + O_SAYREPLYCOLOR, + O_SAYRESTART, + O_SAYGETLASTPOS, + O_SAYREPLYFLAGS, + O_SAYOPTIONFLAGS, + O_SAYMESSAGETIMEOUT, // removes sayMsg in x time, unless x = 0 + + O_CREATEWIN, + O_DELETEWIN, + O_SELECTWIN, + O_RESIZEWIN, + O_SCALEWIN, + O_SHOWWIN, + O_FILLWIN, + O_FILLRECT, + O_FILLWIN3X3, + O_DISPLAY, + O_DISPLAYGFX, + O_DISPLAYRAW, + O_LOADPALETTETABLE, + O_FADEIN, + O_FADEOUT, + O_GOTOXY, + O_PRINT, + O_FORMAT, + O_PRINTRECT, + O_SETFONT, + O_SETTEXTFLAGS, + O_SETTEXTCOLOR, + O_SETHIGHLIGHTCOLOR, + O_STOPMOVIE, + O_PLAYMOVIE, + O_MOVIEFLAGS, + O_PLAYMOVIERECT, + O_PLAYMOVIEALPHA, + O_PLAYMOVIEALPHARECT, + O_ADDREGION, + O_ADDREGIONFLAG, + O_ADDREGIONPROC, + O_ADDREGIONRIGHTPROC, + O_DELETEREGION, + O_ACTIVATEREGION, + O_CHECKREGION, // returns if a region exists or not + + O_ADDBUTTON, + O_ADDBUTTONTEXT, + O_ADDBUTTONFLAG, + O_ADDBUTTONGFX, + O_ADDBUTTONPROC, + O_ADDBUTTONRIGHTPROC, + O_DELETEBUTTON, + + O_HIDEMOUSE, + O_SHOWMOUSE, + O_MOUSESHAPE, + O_REFRESHMOUSE, + O_SETGLOBALMOUSEFUNC, + + O_ADDNAMEDEVENT, + O_ADDNAMEDHANDLER, + O_CLEARNAMED, + O_SIGNALNAMED, + + O_ADDKEY, + O_DELETEKEY, + + O_SOUNDPLAY, + O_SOUNDPAUSE, + O_SOUNDRESUME, + O_SOUNDSTOP, + O_SOUNDREWIND, + O_SOUNDDELETE, + O_SETONEOPTPAUSE, + + O_SELECTFILELIST, + + O_TOKENIZE, + O_END_LIB // don't use this anywhere or your head will explode + }; + + enum O_Extra { + // define any user-specific opcodes here, starting at O_END_LIB + // ending with O_END_OP + O_GIVE_EXP_POINTS = O_END_LIB, + O_SCR_RETURN, + O_PLAY_SFX, + O_OBJ_NAME, + O_SFX_BUILD_OPEN_NAME, + O_GET_PC_STAT, + O_TILE_CONTAINS_PID_OBJ, + O_SET_MAP_START, + O_OVERRIDE_MAP_START, + O_HAS_SKILL, + O_USING_SKILL, + O_ROLL_VS_SKILL, + O_SKILL_CONTEST, + O_DO_CHECK, + O_IS_SUCCESS, + O_IS_CRITICAL, + O_HOW_MUCH, + O_MARK_AREA_KNOWN, + O_REACTION_INFLUENCE, + O_RANDOM, + O_ROLL_DICE, + O_MOVE_TO, + O_CREATE_OBJECT_SID, + O_DISPLAY_MSG, + O_SCRIPT_OVERRIDES, + O_OBJ_IS_CARRYING_OBJ_PID, + O_TILE_CONTAINS_OBJ_PID, + O_SELF_OBJ, + O_SOURCE_OBJ, + O_TARGET_OBJ, + O_DUDE_OBJ, + O_OBJ_BEING_USED_WITH, + O_LOCAL_VAR, + O_SET_LOCAL_VAR, + O_MAP_VAR, + O_SET_MAP_VAR, + O_GLOBAL_VAR, + O_SET_GLOBAL_VAR, + O_SCRIPT_ACTION, + O_OBJ_TYPE, + O_OBJ_ITEM_SUBTYPE, + O_GET_CRITTER_STAT, + O_SET_CRITTER_STAT, + O_ANIMATE_STAND_OBJ, + O_ANIMATE_STAND_REVERSE_OBJ, + O_ANIMATE_MOVE_OBJ_TO_TILE, + O_TILE_IN_TILE_RECT, + O_ATTACK_COMPLEX, + O_MAKE_DAYTIME, + O_TILE_DISTANCE, + O_TILE_DISTANCE_OBJS, + O_TILE_NUM, + O_TILE_NUM_IN_DIRECTION, + O_PICKUP_OBJ, + O_DROP_OBJ, + O_ADD_OBJ_TO_INVEN, + O_RM_OBJ_FROM_INVEN, + O_WIELD_OBJ_CRITTER, + O_USE_OBJ, + O_OBJ_CAN_SEE_OBJ, + O_ATTACK, + O_START_GDIALOG, + O_END_DIALOGUE, + O_DIALOGUE_REACTION, + O_METARULE3, + O_SET_MAP_MUSIC, + O_SET_OBJ_VISIBILITY, + O_LOAD_MAP, + O_WM_AREA_SET_POS, + O_SET_EXIT_GRIDS, + O_ANIM_BUSY, + O_CRITTER_HEAL, + O_SET_LIGHT_LEVEL, + O_GAME_TIME, + O_GAME_TIME_IN_SECONDS, + O_ELEVATION, + O_KILL_CRITTER, + O_KILL_CRITTER_TYPE, + O_CRITTER_DMG, + O_ADD_TIMER_EVENT, + O_RM_TIMER_EVENT, + O_GAME_TICKS, + O_HAS_TRAIT, + O_DESTROY_OBJECT, + O_OBJ_CAN_HEAR_OBJ, + O_GAME_TIME_HOUR, + O_FIXED_PARAM, + O_TILE_IS_VISIBLE, + O_DIALOGUE_SYSTEM_ENTER, + O_ACTION_BEING_USED, + O_CRITTER_STATE, + O_GAME_TIME_ADVANCE, + O_RADIATION_INC, + O_RADIATION_DEC, + O_CRITTER_ATTEMPT_PLACEMENT, + O_OBJ_PID, + O_CUR_MAP_INDEX, + O_CRITTER_ADD_TRAIT, + O_CRITTER_RM_TRAIT, + O_PROTO_DATA, + O_MESSAGE_STR, + O_CRITTER_INVEN_OBJ, + O_OBJ_SET_LIGHT_LEVEL, + O_WORLD_MAP, + O_INVEN_CMDS, + O_FLOAT_MSG, + O_METARULE, + O_ANIM, + O_OBJ_CARRYING_PID_OBJ, + O_REG_ANIM_FUNC, + O_REG_ANIM_ANIMATE, + O_REG_ANIM_ANIMATE_REVERSE, + O_REG_ANIM_OBJ_MOVE_TO_OBJ, + O_REG_ANIM_OBJ_RUN_TO_OBJ, + O_REG_ANIM_OBJ_MOVE_TO_TILE, + O_REG_ANIM_OBJ_RUN_TO_TILE, + O_PLAY_GMOVIE, + O_ADD_MULT_OBJS_TO_INVEN, + O_RM_MULT_OBJS_FROM_INVEN, + O_GET_MONTH, + O_GET_DAY, + O_EXPLOSION, + O_DAYS_SINCE_VISITED, + O_GSAY_START, + O_GSAY_END, + O_GSAY_REPLY, + O_GSAY_OPTION, + O_GSAY_MESSAGE, + O_GIQ_OPTION, + O_POISON, + O_GET_POISON, + O_PARTY_ADD, + O_PARTY_REMOVE, + O_REG_ANIM_ANIMATE_FOREVER, + O_CRITTER_INJURE, + O_COMBAT_IS_INITIALIZED, + O_GDIALOG_MOD_BARTER, + O_DIFFICULTY_LEVEL, + O_RUNNING_BURNING_GUY, + O_INVEN_UNWIELD, + O_OBJ_IS_LOCKED, + O_OBJ_LOCK, + O_OBJ_UNLOCK, + O_OBJ_IS_OPEN, + O_OBJ_OPEN, + O_OBJ_CLOSE, + O_GAME_UI_DISABLE, + O_GAME_UI_ENABLE, + O_GAME_UI_IS_DISABLED, + O_GFADE_OUT, + O_GFADE_IN, + O_ITEM_CAPS_TOTAL, + O_ITEM_CAPS_ADJUST, + O_ANIM_ACTION_FRAME, + O_REG_ANIM_PLAY_SFX, + O_CRITTER_MOD_SKILL, + O_SFX_BUILD_CHAR_NAME, + O_SFX_BUILD_AMBIENT_NAME, + O_SFX_BUILD_INTERFACE_NAME, + O_SFX_BUILD_ITEM_NAME, + O_SFX_BUILD_WEAPON_NAME, + O_SFX_BUILD_SCENERY_NAME, + O_ATTACK_SETUP, + O_DESTROY_MULT_OBJS, + O_USE_OBJ_ON_OBJ, + O_ENDGAME_SLIDESHOW, + O_MOVE_OBJ_INVEN_TO_OBJ, + O_ENDGAME_MOVIE, + O_OBJ_ART_FID, + O_ART_ANIM, + O_PARTY_MEMBER_OBJ, + O_ROTATION_TO_TILE, + O_JAM_LOCK, + O_GDIALOG_SET_BARTER_MOD, + O_COMBAT_DIFFICULTY, + O_OBJ_ON_SCREEN, + O_CRITTER_IS_FLEEING, + O_CRITTER_SET_FLEE_STATE, + O_TERMINATE_COMBAT, + O_DEBUG_MSG, + O_CRITTER_STOP_ATTACKING, + +//sfall start + O_READ_BYTE, + O_READ_SHORT, + O_READ_INT, + O_READ_STRING, + O_SET_PC_BASE_STAT, + O_SET_PC_EXTRA_STAT, + O_GET_PC_BASE_STAT, + O_GET_PC_EXTRA_STAT, + O_SET_CRITTER_BASE_STAT, + O_SET_CRITTER_EXTRA_STAT, + O_GET_CRITTER_BASE_STAT, + O_GET_CRITTER_EXTRA_STAT, + O_TAP_KEY, + O_GET_YEAR, + O_GAME_LOADED, + O_GRAPHICS_FUNCS_AVAILABLE, + O_LOAD_SHADER, + O_FREE_SHADER, + O_ACTIVATE_SHADER, + O_DEACTIVATE_SHADER, + O_SET_GLOBAL_SCRIPT_REPEAT, + O_INPUT_FUNCS_AVAILABLE, + O_KEY_PRESSED, + + O_SET_SHADER_INT, + O_SET_SHADER_FLOAT, + O_SET_SHADER_VECTOR, + O_IN_WORLD_MAP, + O_FORCE_ENCOUNTER, + O_SET_WORLD_MAP_POS, + O_GET_WORLD_MAP_X_POS, + O_GET_WORLD_MAP_Y_POS, + + O_SET_DM_MODEL, + O_SET_DF_MODEL, + O_SET_MOVIE_PATH, + + O_SET_PERK_IMAGE, + O_SET_PERK_RANKS, + O_SET_PERK_LEVEL, + O_SET_PERK_STAT, + O_SET_PERK_STAT_MAG, + O_SET_PERK_SKILL1, + O_SET_PERK_SKILl1_MAG, + O_SET_PERK_TYPE, + O_SET_PERK_SKILL2, + O_SET_PERK_SKILL2_MAG, + O_SET_PERK_STR, + O_SET_PERK_PER, + O_SET_PERK_END, + O_SET_PERK_CHR, + O_SET_PERK_INT, + O_SET_PERK_AGL, + O_SET_PERK_LCK, + O_SET_PERK_NAME, + O_SET_PERK_DESC, + + O_SET_PIPBOY_AVAILABLE, + + O_GET_KILL_COUNTER, + O_MOD_KILL_COUNTER, + + O_GET_PERK_OWED, + O_SET_PERK_OWED, + O_GET_PERK_AVAILABLE, + + O_GET_CRITTER_AP, + O_SET_CRITTER_AP, + + O_GET_ACTIVE_HAND, + O_TOGGLE_ACTIVE_HAND, + + O_SET_WEAPON_KNOCKBACK, + O_SET_TARGET_KNOCKBACK, + O_SET_ATTACKER_KNOCKBACK, + O_REMOVE_WEAPON_KNOCKBACK, + O_REMOVE_TARGET_KNOCKBACK, + O_REMOVE_ATTACKER_KNOCKBACK, + + O_SET_GLOBAL_SCRIPT_TYPE, + O_AVAILABLE_GLOBAL_SCRIPT_TYPES, + + O_SET_SFALL_GLOBAL, + O_GET_SFALL_GLOBAL_INT, + O_GET_SFALL_GLOBAL_FLOAT, + + O_SET_PICKPOCKET_MAX, + O_SET_HIT_CHANCE_MAX, + O_SET_SKILL_MAX, + + O_EAX_AVAILABLE, + O_SET_EAX_ENVIRONMENT, + + O_INC_NPC_LEVEL, + + O_GET_VIEWPORT_X, + O_GET_VIEWPORT_Y, + O_SET_VIEWPORT_X, + O_SET_VIEWPORT_Y, + + O_SET_XP_MOD, + O_SET_PERK_LEVEL_MOD, + + O_GET_INI_SETTING, + + O_GET_SHADER_VERSION, + O_SET_SHADER_MODE, + + O_GET_GAME_MODE, + + O_FORCE_GRAPHICS_REFRESH, + O_GET_SHADER_TEXTURE, + O_SET_SHADER_TEXTURE, + + O_GET_UPTIME, + + O_SET_STAT_MAX, + O_SET_STAT_MIN, + + O_SET_CAR_CURRENT_TOWN, + + O_SET_PC_STAT_MAX, + O_SET_PC_STAT_MIN, + O_SET_NPC_STAT_MAX, + O_SET_NPC_STAT_MIN, + + O_SET_FAKE_PERK, + O_SET_FAKE_TRAIT, + O_SET_SELECTABLE_PERK, + O_SET_PERKBOX_TITLE, + O_HIDE_REAL_PERKS, + O_SHOW_REAL_PERKS, + O_HAS_FAKE_PERK, + O_HAS_FAKE_TRAIT, + O_PERK_ADD_MODE, + O_CLEAR_SELECTABLE_PERKS, + + O_SET_CRITTER_HIT_CHANCE_MOD, + O_SET_BASE_HIT_CHANCE_MOD, + O_SET_CRITTER_SKILL_MOD, + O_SET_BASE_SKILL_MOD, + O_SET_CRITTER_PICKPOCKET_MOD, + O_SET_BASE_PICKPOCKET_MOD, + + O_SET_PYROMANIAC_MOD, + O_APPLY_HEAVEHO_FIX, + O_SET_SWIFTLEARNER_MOD, + O_SET_HP_LEVEL_MOD, + + O_WRITE_BYTE, + O_WRITE_SHORT, + O_WRITE_INT, + + O_CALL_OFFSET_V0, + O_CALL_OFFSET_V1, + O_CALL_OFFSET_V2, + O_CALL_OFFSET_V3, + O_CALL_OFFSET_V4, + O_CALL_OFFSET_R0, + O_CALL_OFFSET_R1, + O_CALL_OFFSET_R2, + O_CALL_OFFSET_R3, + O_CALL_OFFSET_R4, + + O_SHOW_IFACE_TAG, + O_HIDE_IFACE_TAG, + O_IS_IFACE_TAG_ACTIVE, + O_GET_BODYPART_HIT_MODIFIER, + O_SET_BODYPART_HIT_MODIFIER, + + O_SET_CRITICAL_TABLE, + O_GET_CRITICAL_TABLE, + O_RESET_CRITICAL_TABLE, + O_GET_SFALL_ARG, + O_SET_SFALL_RETURN, + O_SET_UNSPENT_AP_BONUS, + O_GET_UNSPENT_AP_BONUS, + O_SET_UNSPENT_AP_PERK_BONUS, + O_GET_UNSPENT_AP_PERK_BONUS, + O_INIT_HOOK, + O_GET_INI_STRING, + + O_SQRT, + O_ABS, + O_SIN, + O_COS, + O_TAN, + O_ARCTAN, + O_SET_PALETTE, + + O_REMOVE_SCRIPT, + O_SET_SCRIPT, + O_GET_SCRIPT, + O_NB_CREATE_CHAR, + O_FS_CREATE, + O_FS_COPY, + O_FS_FIND, + O_FS_WRITE_BYTE, + O_FS_WRITE_SHORT, + O_FS_WRITE_INT, + O_FS_WRITE_FLOAT, + O_FS_WRITE_STRING, + O_FS_DELETE, + O_FS_SIZE, + O_FS_POS, + O_FS_SEEK, + O_FS_RESIZE, + O_GET_PROTO_DATA, + + O_SET_PROTO_DATA, + O_SET_SELF, + O_REGISTER_HOOK, + O_FS_WRITE_BSTRING, + O_FS_READ_BYTE, + O_FS_READ_SHORT, + O_FS_READ_INT, + O_FS_READ_FLOAT, + O_LIST_BEGIN, + O_LIST_NEXT, + O_LIST_END, + + O_SFALL_VER_MAJOR, + O_SFALL_VER_MINOR, + O_SFALL_VER_BUILD, + + O_HERO_SELECT_WIN, + O_SET_HERO_RACE, + O_SET_HERO_STYLE, + + O_SET_CRITTER_BURST_DISABLE, + + O_GET_WEAPON_AMMO_PID, + O_SET_WEAPON_AMMO_PID, + O_GET_WEAPON_AMMO_COUNT, + O_SET_WEAPON_AMMO_COUNT, + O_WRITE_STRING, + O_GET_MOUSE_X, + O_GET_MOUSE_Y, + O_GET_MOUSE_BUTTONS, + O_GET_WINDOW_UNDER_MOUSE, + O_GET_SCREEN_WIDTH, + O_GET_SCREEN_HEIGHT, + O_STOP_GAME, + O_RESUME_GAME, + O_CREATE_MESSAGE_WINDOW, + O_REMOVE_TRAIT, + O_GET_LIGHT_LEVEL, + O_REFRESH_PC_ART, + O_GET_ATTACK_TYPE, + O_FORCE_ENCOUNTER_WITH_FLAGS, + O_SET_MAP_TIME_MULTI, + O_PLAY_SFALL_SOUND, + O_STOP_SFALL_SOUND, + O_CREATE_ARRAY, + O_SET_ARRAY, + O_GET_ARRAY, + O_FREE_ARRAY, + + O_TS_LEN_ARRAY, + O_TS_RESIZE_ARRAY, + O_TS_TEMP_ARRAY, + O_TS_FIX_ARRAY, + + O_TS_STRING_SPLIT, + + O_TS_LIST_AS_ARRAY, + + O_TS_ATOI, + O_TS_ATOF, + + O_TS_SCAN_ARRAY, + + O_TS_TILE_PID, + + O_TS_MODIFIED_INI, + + O_TS_GET_SFALL_ARGS, + + O_TS_SET_SFALL_ARG, + + O_TS_FORCE_AIMED_SHOTS, + O_TS_DISABLE_AIMED_SHOTS, + + O_TS_MARK_MOVIE_PLAYED, + + O_TS_GET_NPC_LEVEL, + + O_TS_SET_CRITTER_SKILL_POINTS, + O_TS_GET_CRITTER_SKILL_POINTS, + O_TS_SET_AVAILABLE_SKILL_POINTS, + O_TS_GET_AVAILABLE_SKILL_POINTS, + O_TS_MOD_SKILL_POINTS_PER_LEVEL, + O_TS_SET_PERK_FREQ, + + O_TS_GET_LAST_ATTACKER, + O_TS_GET_LAST_TARGET, + O_TS_BLOCK_COMBAT, + + O_TS_TILE_UNDER_CURSOR, + O_TS_GET_BARTER_MOD, + O_TS_SET_INVEN_AP_COST, + + O_TS_SUBSTR, + O_TS_STRLEN, + O_TS_SPRINTF, + O_TS_ORD, + O_TS_RESERVD2, + O_TS_TYPEOF, + + O_TS_SAVE_ARRAY, + O_TS_LOAD_ARRAY, + O_TS_GET_ARRAY_KEY, + O_TS_STACK_ARRAY, + + O_TS_RESERVD3, + O_TS_RESERVD4, + + O_TS_REG_ANIM_DESTROY, + O_TS_REG_ANIM_ANIMATE_AND_HIDE, + O_TS_REG_ANIM_COMBAT_CHECK, + O_TS_REG_ANIM_LIGHT, + O_TS_REG_ANIM_CHANGE_FID, + O_TS_REG_ANIM_TAKE_OUT, + O_TS_REG_ANIM_TURN_TOWARDS, + + O_TS_EXPLOSIONS_METARULE, + O_TS_REGISTER_HOOK_PROC, + + O_TS_POW, + O_TS_LOG, + O_TS_EXP, + O_TS_CEIL, + O_TS_ROUND, + + O_TS_RESERVD5, + O_TS_RESERVD6, + O_TS_RESERVD7, + + O_TS_MESSAGE_STR_GAME, + O_TS_SNEAK_SUCCESS, + O_TS_TILE_LIGHT, + + O_TS_MAKE_STRAIGHT_PATH, + O_TS_OBJ_BLOCKING_AT, + O_TS_TILE_GET_OBJECTS, + O_TS_GET_PARTY_MEMBERS, + O_TS_PATH_FIND, + O_TS_CREATE_SPATIAL, + O_TS_ART_EXISTS, + O_TS_OBJ_IS_CARRYING_OBJ, + +//sfall end + O_END_OP + }; + + enum O_DataType { + O_STRINGOP = (O_CONST | O_STRING), // 0x9001 + O_FLOATOP = (O_CONST | O_FLOAT), // 0xA001 + O_INTOP = (O_CONST | O_INT) // 0xC001 + }; + + enum O_F1_Specific { + O_REACTION = 0x80B2, + O_ANIMATE_JUMP = 0x80CF, + O_TURN_OFF_OBJS_IN_AREA = 0x80E1, + O_TURN_ON_OBJS_IN_AREA = 0x80E2, + O_BARTER_OFFER = 0x80E5, + O_BARTER_ASKING = 0x80E6, + O_TOWN_MAP = 0x8109 + }; + + // COpcodeAttributes + class COpcodeAttributes { + public: + enum Type { + TYPE_STATEMENT, + TYPE_EXPRESSION + }; + + enum Category { + CATEGORY_PREFIX, + CATEGORY_INFIX + }; + + public: + COpcodeAttributes(LPCTSTR lpszMnemonic = "", LPCTSTR lpszName = "", ULONG ulNumArgs = 0, + Type type = TYPE_STATEMENT, Category category = CATEGORY_PREFIX, ULONG *procArgs = NULL, ULONG numProcArgs = 0); + COpcodeAttributes(const COpcodeAttributes& attributes); + + public: + COpcodeAttributes& operator = (const COpcodeAttributes& attributes); + + public: + void InitAttributes(); + + public: + CString m_strMnemonic; + + CString m_strName; + ULONG m_ulNumArgs; + + Type m_Type; + Category m_Category; + ULONG *m_procArgs; + ULONG m_numProcArgs; + }; + + // CF2OpcodeAttributesMap + class CF2OpcodeAttributesMap : public CMap { + public: + CF2OpcodeAttributesMap(); + }; + + // C12OpcodeAttributesMap + class CF1OpcodeAttributesMap : public CMap { + public: + CF1OpcodeAttributesMap(); + }; + +public: + COpcode(); + COpcode(const COpcode& opcode); + virtual ~COpcode(); + +public: + COpcode& operator = (const COpcode& opcode); + +public: + virtual void Serialize(CArchive& ar); + void Expect(CArchive& ar, WORD wOperator, BOOL bArgumentFound = FALSE, ULONG ulArgument = 0); + void Expect(CArchive& ar, int nCount, WORD pwOperators[]); + + BOOL HasArgument() const; + int GetSize() const; + + WORD GetOperator() const; + void SetOperator(WORD op); + ULONG GetArgument() const; + + const COpcodeAttributes GetAttributes() const; + +private: + WORD m_wOperator; + ULONG m_ulArgument; +}; + +// COpcodeArray +typedef CArray COpcodeArray; + +#endif diff --git a/OpcodeAttributes.cpp b/OpcodeAttributes.cpp new file mode 100644 index 0000000..ea40858 --- /dev/null +++ b/OpcodeAttributes.cpp @@ -0,0 +1,788 @@ +// OpcodeMnemonic.cpp : COpcode class implementation file +// + +#include "stdafx.h" +#include "Opcode.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// COpcode::COpcodeAttributes +COpcode::COpcodeAttributes::COpcodeAttributes(LPCTSTR lpszMnemonic, LPCTSTR lpszName, ULONG ulNumArgs, + Type type, Category category, ULONG *procArgs, ULONG numProcArgs) : + m_strMnemonic(lpszMnemonic), + m_strName(lpszName), + m_ulNumArgs(ulNumArgs), + m_Type(type), + m_Category(category), + m_procArgs(procArgs), + m_numProcArgs(numProcArgs) +{ +} + +COpcode::COpcodeAttributes::COpcodeAttributes(const COpcodeAttributes& attributes) : + m_strMnemonic(attributes.m_strMnemonic), + m_strName(attributes.m_strName), + m_ulNumArgs(attributes.m_ulNumArgs), + m_Type(attributes.m_Type), + m_Category(attributes.m_Category), + m_procArgs(attributes.m_procArgs), + m_numProcArgs(attributes.m_numProcArgs) +{ +} + +COpcode::COpcodeAttributes& COpcode::COpcodeAttributes::operator = (const COpcodeAttributes& attributes) +{ + if (&attributes != this) { + m_strMnemonic = attributes.m_strMnemonic; + m_strName = attributes.m_strName; + m_ulNumArgs = attributes.m_ulNumArgs; + m_Type = attributes.m_Type; + m_Category = attributes.m_Category; + m_procArgs = attributes.m_procArgs; + m_numProcArgs = attributes.m_numProcArgs; + } + + return (*this); +} + +// COpcode::CF1OpcodeAttributesMap +COpcode::CF1OpcodeAttributesMap::CF1OpcodeAttributesMap() +{ + COpcode::COpcodeAttributes::Type expression = COpcode::COpcodeAttributes::TYPE_EXPRESSION; + COpcode::COpcodeAttributes::Category infix = COpcode::COpcodeAttributes::CATEGORY_INFIX; + + InitHashTable(32); + + SetAt(O_REACTION, COpcodeAttributes("O_REACTION", "reaction", 3, expression)); + SetAt(O_ANIMATE_JUMP, COpcodeAttributes("O_ANIMATE_JUMP", "animate_jump", 0)); + SetAt(O_TURN_OFF_OBJS_IN_AREA, COpcodeAttributes("O_TURN_OFF_OBJS_IN_AREA", "turn_off_objs_in_area", 4)); + SetAt(O_TURN_ON_OBJS_IN_AREA, COpcodeAttributes("O_TURN_ON_OBJS_IN_AREA", "turn_on_objs_in_area", 4)); + SetAt(O_BARTER_OFFER, COpcodeAttributes("O_BARTER_OFFER", "barter_offer", 3)); + SetAt(O_BARTER_ASKING, COpcodeAttributes("O_BARTER_ASKING", "barter_asking", 3)); + SetAt(O_TOWN_MAP, COpcodeAttributes("O_TOWN_MAP", "town_map", 0)); +} + +ULONG procArgs_register_hook_proc[1] = {2}; + +// COpcode::CF2OpcodeAttributesMap +COpcode::CF2OpcodeAttributesMap::CF2OpcodeAttributesMap() +{ + COpcode::COpcodeAttributes::Type expression = COpcode::COpcodeAttributes::TYPE_EXPRESSION; + COpcode::COpcodeAttributes::Category infix = COpcode::COpcodeAttributes::CATEGORY_INFIX; + + InitHashTable(512); + + SetAt(O_NOOP, COpcodeAttributes("O_NOOP", "/* O_NOOP */", 0)); + SetAt(O_CONST, COpcodeAttributes("O_CONST", "/* O_CONST */", 0)); + SetAt(O_CRITICAL_START, COpcodeAttributes("O_CRITICAL_START", "/* O_CRITICAL_START */", 0)); + SetAt(O_CRITICAL_DONE, COpcodeAttributes("O_CRITICAL_DONE", "/* O_CRITICAL_START */", 0)); + SetAt(O_JMP, COpcodeAttributes("O_JMP", "// O_JMP ", 1)); + SetAt(O_CALL, COpcodeAttributes("O_CALL", "/* O_CALL */", 0, expression)); + SetAt(O_CALL_AT, COpcodeAttributes("O_CALL_AT", "/* O_CALL_AT */", 2)); + SetAt(O_CALL_CONDITION, COpcodeAttributes("O_CALL_CONDITION", "/* O_CALL_CONDITION */", 2)); + SetAt(O_CALLSTART, COpcodeAttributes("O_CALLSTART", "callStart", 1)); + SetAt(O_EXEC, COpcodeAttributes("O_EXEC", "exec", 1)); + SetAt(O_SPAWN, COpcodeAttributes("O_SPAWN", "spawn", 1)); + SetAt(O_FORK, COpcodeAttributes("O_FORK", "fork", 1)); + SetAt(O_A_TO_D, COpcodeAttributes("O_A_TO_D", "/* O_A_TO_D */", 0)); + SetAt(O_D_TO_A, COpcodeAttributes("O_D_TO_A", "/* O_D_TO_A */", 0)); + SetAt(O_EXIT, COpcodeAttributes("O_EXIT", "exit", 0)); + SetAt(O_DETACH, COpcodeAttributes("O_DETACH", "detach", 0)); + SetAt(O_EXIT_PROG, COpcodeAttributes("O_EXIT_PROG", "/* O_EXIT_PROG */", 0)); + SetAt(O_STOP_PROG, COpcodeAttributes("O_STOP_PROG", "/* O_STOP_PROG */", 0)); + SetAt(O_FETCH_GLOBAL, COpcodeAttributes("O_FETCH_GLOBAL", "/* O_FETCH_GLOBAL */", 1, expression)); + SetAt(O_STORE_GLOBAL, COpcodeAttributes("O_STORE_GLOBAL", ":=", 2)); + SetAt(O_FETCH_EXTERNAL, COpcodeAttributes("O_FETCH_EXTERNAL", "/* O_FETCH_EXTERNAL */", 1, expression)); + SetAt(O_STORE_EXTERNAL, COpcodeAttributes("O_STORE_EXTERNAL", ":=", 2)); + SetAt(O_EXPORT_VAR, COpcodeAttributes("O_EXPORT_VAR", "/* O_EXPORT_VAR */", 0)); + SetAt(O_EXPORT_PROC, COpcodeAttributes("O_EXPORT_PROC", "/* O_EXPORT_PROC */", 0)); + SetAt(O_SWAP, COpcodeAttributes("O_SWAP", "/* O_SWAP */", 0)); + SetAt(O_SWAPA, COpcodeAttributes("O_SWAPA", "/* O_SWAPA */", 0)); + SetAt(O_POP, COpcodeAttributes("O_POP", "/* O_POP */", 1)); + SetAt(O_DUP, COpcodeAttributes("O_DUP", "/* O_DUP */", 0)); + SetAt(O_POP_RETURN, COpcodeAttributes("O_POP_RETURN", "return", 1)); + SetAt(O_POP_EXIT, COpcodeAttributes("O_POP_EXIT", "/* O_POP_EXIT */", 0)); + SetAt(O_POP_ADDRESS, COpcodeAttributes("O_POP_ADDRESS", "/* O_POP_ADDRESS */", 0)); + SetAt(O_POP_FLAGS, COpcodeAttributes("O_POP_FLAGS", "/* O_POP_FLAGS */", 0)); + SetAt(O_POP_FLAGS_RETURN, COpcodeAttributes("O_POP_FLAGS_RETURN", "/* O_POP_FLAGS_RETURN */", 0)); + SetAt(O_POP_FLAGS_EXIT, COpcodeAttributes("O_POP_FLAGS_EXIT", "/* O_POP_FLAGS_EXIT */", 0)); + SetAt(O_POP_FLAGS_RETURN_EXTERN, COpcodeAttributes("O_POP_FLAGS_RETURN_EXTERN", "/* O_POP_FLAGS_RETURN_EXTERN */", 0)); + SetAt(O_POP_FLAGS_EXIT_EXTERN, COpcodeAttributes("O_POP_FLAGS_EXIT_EXTERN", "/* O_POP_FLAGS_EXIT_EXTERN */", 0)); + SetAt(O_POP_FLAGS_RETURN_VAL_EXTERN, COpcodeAttributes("O_POP_FLAGS_RETURN_VAL_EXTERN", "/* O_POP_FLAGS_RETURN_VAL_EXTERN */", 0)); + SetAt(O_POP_FLAGS_RETURN_VAL_EXIT, COpcodeAttributes("O_POP_FLAGS_RETURN_VAL_EXIT", "/* O_POP_FLAGS_RETURN_VAL_EXIT */", 0)); + SetAt(O_POP_FLAGS_RETURN_VAL_EXIT_EXTERN, COpcodeAttributes("O_POP_FLAGS_RETURN_VAL_EXIT_EXTERN", "/* O_POP_FLAGS_RETURN_VAL_EXIT_EXTERN */", 0)); + SetAt(O_CHECK_ARG_COUNT, COpcodeAttributes("O_CHECK_ARG_COUNT", "/* O_CHECK_ARG_COUNT */", 0)); + SetAt(O_LOOKUP_STRING_PROC, COpcodeAttributes("O_LOOKUP_STRING_PROC", "/* O_LOOKUP_STRING_PROC */", 1, expression)); + SetAt(O_POP_BASE, COpcodeAttributes("O_POP_BASE", "/* O_POP_BASE */", 0)); + SetAt(O_POP_TO_BASE, COpcodeAttributes("O_POP_TO_BASE", "/* O_POP_TO_BASE */", 0)); + SetAt(O_PUSH_BASE, COpcodeAttributes("O_PUSH_BASE", "/* O_PUSH_BASE */", 0)); + SetAt(O_SET_GLOBAL, COpcodeAttributes("O_SET_GLOBAL", "/* O_SET_GLOBAL */", 0)); + SetAt(O_FETCH_PROC_ADDRESS, COpcodeAttributes("O_FETCH_PROC_ADDRESS", "/* O_FETCH_PROC_ADDRESS */", 0)); + SetAt(O_DUMP, COpcodeAttributes("O_DUMP", "/* O_DUMP */", 0)); + SetAt(O_IF, COpcodeAttributes("O_IF", "if", 2)); + SetAt(O_WHILE, COpcodeAttributes("O_WHILE", "while", 2)); + SetAt(O_STORE, COpcodeAttributes("O_STORE", ":=", 2)); + SetAt(O_FETCH, COpcodeAttributes("O_FETCH", "/* O_FETCH */", 1, expression)); + SetAt(O_EQUAL, COpcodeAttributes("O_EQUAL", "==", 2, expression, infix)); + SetAt(O_NOT_EQUAL, COpcodeAttributes("O_NOT_EQUAL", "!=", 2, expression, infix)); + SetAt(O_LESS_EQUAL, COpcodeAttributes("O_LESS_EQUAL", "<=", 2, expression, infix)); + SetAt(O_GREATER_EQUAL, COpcodeAttributes("O_GREATER_EQUAL", ">=", 2, expression, infix)); + SetAt(O_LESS, COpcodeAttributes("O_LESS", "<", 2, expression, infix)); + SetAt(O_GREATER, COpcodeAttributes("O_GREATER", ">", 2, expression, infix)); + SetAt(O_ADD, COpcodeAttributes("O_ADD", "+", 2, expression, infix)); + SetAt(O_SUB, COpcodeAttributes("O_SUB", "-", 2, expression, infix)); + SetAt(O_MUL, COpcodeAttributes("O_MUL", "*", 2, expression, infix)); + SetAt(O_DIV, COpcodeAttributes("O_DIV", "/", 2, expression, infix)); + SetAt(O_MOD, COpcodeAttributes("O_MOD", "%", 2, expression, infix)); + SetAt(O_AND, COpcodeAttributes("O_AND", "and", 2, expression, infix)); + SetAt(O_OR, COpcodeAttributes("O_OR", "or", 2, expression, infix)); + SetAt(O_BWAND, COpcodeAttributes("O_BWAND", "bwand", 2, expression, infix)); + SetAt(O_BWOR, COpcodeAttributes("O_BWOR", "bwor", 2, expression, infix)); + SetAt(O_BWXOR, COpcodeAttributes("O_BWXOR", "bwxor", 2, expression, infix)); + SetAt(O_BWNOT, COpcodeAttributes("O_BWNOT", "bwnot", 1, expression)); + SetAt(O_FLOOR, COpcodeAttributes("O_FLOOR", "floor", 1, expression)); + SetAt(O_NOT, COpcodeAttributes("O_NOT", "not", 1, expression)); + SetAt(O_NEGATE, COpcodeAttributes("O_NEGATE", "-", 1, expression)); + SetAt(O_WAIT, COpcodeAttributes("O_WAIT", "wait", 1)); + SetAt(O_CANCEL, COpcodeAttributes("O_CANCEL", "cancel", 1)); + SetAt(O_CANCELALL, COpcodeAttributes("O_CANCELALL", "cancelAll", 0)); + SetAt(O_STARTCRITICAL, COpcodeAttributes("O_STARTCRITICAL", "startCritical", 0)); + SetAt(O_ENDCRITICAL, COpcodeAttributes("O_ENDCRITICAL", "endCritical", 0)); + SetAt(O_SAYQUIT, COpcodeAttributes("O_SAYQUIT", "sayQuit", 0)); + SetAt(O_SAYEND, COpcodeAttributes("O_SAYEND", "sayEnd", 0)); + SetAt(O_SAYSTART, COpcodeAttributes("O_SAYSTART", "sayStart", 0)); + SetAt(O_SAYSTARTPOS, COpcodeAttributes("O_SAYSTARTPOS", "sayStartPos", 1)); + SetAt(O_SAYREPLYTITLE, COpcodeAttributes("O_SAYREPLYTITLE", "sayReplyTitle", 1)); + SetAt(O_SAYGOTOREPLY, COpcodeAttributes("O_SAYGOTOREPLY", "sayGotoReply", 1)); + SetAt(O_SAYREPLY, COpcodeAttributes("O_SAYREPLY", "sayReply", 2)); + SetAt(O_SAYOPTION, COpcodeAttributes("O_SAYOPTION", "sayOption", 2)); + SetAt(O_SAYMESSAGE, COpcodeAttributes("O_SAYMESSAGE", "sayMessage", 2)); + SetAt(O_SAYREPLYWINDOW, COpcodeAttributes("O_SAYREPLYWINDOW", "sayReplyWindow", 5)); + SetAt(O_SAYOPTIONWINDOW, COpcodeAttributes("O_SAYOPTIONWINDOW", "sayOptionWindow", 5)); + SetAt(O_SAYBORDER, COpcodeAttributes("O_SAYBORDER", "sayBorder", 2)); + SetAt(O_SAYSCROLLUP, COpcodeAttributes("O_SAYSCROLLUP", "sayScrollUp", 6)); + SetAt(O_SAYSCROLLDOWN, COpcodeAttributes("O_SAYSCROLLDOWN", "sayScrollDown", 6)); + SetAt(O_SAYSETSPACING, COpcodeAttributes("O_SAYSETSPACING", "saySetSpacing", 1)); + SetAt(O_SAYOPTIONCOLOR, COpcodeAttributes("O_SAYOPTIONCOLOR", "sayOptionColor", 3)); + SetAt(O_SAYREPLYCOLOR, COpcodeAttributes("O_SAYREPLYCOLOR", "sayReplyColor", 3)); + SetAt(O_SAYRESTART, COpcodeAttributes("O_SAYRESTART", "sayRestart", 0)); + SetAt(O_SAYGETLASTPOS, COpcodeAttributes("O_SAYGETLASTPOS", "sayGetLastPos", 0, expression)); + SetAt(O_SAYREPLYFLAGS, COpcodeAttributes("O_SAYREPLYFLAGS", "sayReplyFlags", 1)); + SetAt(O_SAYOPTIONFLAGS, COpcodeAttributes("O_SAYOPTIONFLAGS", "sayOptionFlags", 1)); + SetAt(O_SAYMESSAGETIMEOUT, COpcodeAttributes("O_SAYMESSAGETIMEOUT", "sayMessageTimeout", 1)); + SetAt(O_CREATEWIN, COpcodeAttributes("O_CREATEWIN", "createWin", 5)); + SetAt(O_DELETEWIN, COpcodeAttributes("O_DELETEWIN", "deleteWin", 1)); + SetAt(O_SELECTWIN, COpcodeAttributes("O_SELECTWIN", "selectWin", 1)); + SetAt(O_RESIZEWIN, COpcodeAttributes("O_RESIZEWIN", "resizeWin", 5)); + SetAt(O_SCALEWIN, COpcodeAttributes("O_SCALEWIN", "scaleWin", 5)); + SetAt(O_SHOWWIN, COpcodeAttributes("O_SHOWWIN", "showWin", 0)); + SetAt(O_FILLWIN, COpcodeAttributes("O_FILLWIN", "fillWin", 3)); + SetAt(O_FILLRECT, COpcodeAttributes("O_FILLRECT", "fillRect", 7)); + SetAt(O_FILLWIN3X3, COpcodeAttributes("O_FILLWIN3X3", "fillWin3x3", 1)); + SetAt(O_DISPLAY, COpcodeAttributes("O_DISPLAY", "display", 1)); + SetAt(O_DISPLAYGFX, COpcodeAttributes("O_DISPLAYGFX", "displayGfx", 5)); + SetAt(O_DISPLAYRAW, COpcodeAttributes("O_DISPLAYRAW", "displayRaw", 1)); + SetAt(O_LOADPALETTETABLE, COpcodeAttributes("O_LOADPALETTETABLE", "loadPaletteTable", 1)); + SetAt(O_FADEIN, COpcodeAttributes("O_FADEIN", "fadeIn", 1)); + SetAt(O_FADEOUT, COpcodeAttributes("O_FADEOUT", "fadeOut", 1)); + SetAt(O_GOTOXY, COpcodeAttributes("O_GOTOXY", "gotoXY", 2)); + SetAt(O_PRINT, COpcodeAttributes("O_PRINT", "print", 1)); + SetAt(O_FORMAT, COpcodeAttributes("O_FORMAT", "format", 6)); + SetAt(O_PRINTRECT, COpcodeAttributes("O_PRINTRECT", "printRect", 3)); + SetAt(O_SETFONT, COpcodeAttributes("O_SETFONT", "setFont", 1)); + SetAt(O_SETTEXTFLAGS, COpcodeAttributes("O_SETTEXTFLAGS", "setTextFlags", 1)); + SetAt(O_SETTEXTCOLOR, COpcodeAttributes("O_SETTEXTCOLOR", "setTextColor", 3)); + SetAt(O_SETHIGHLIGHTCOLOR, COpcodeAttributes("O_SETHIGHLIGHTCOLOR", "setHighlightColor", 3)); + SetAt(O_STOPMOVIE, COpcodeAttributes("O_STOPMOVIE", "stopMovie", 0)); + SetAt(O_PLAYMOVIE, COpcodeAttributes("O_PLAYMOVIE", "playMovie", 1)); + SetAt(O_MOVIEFLAGS, COpcodeAttributes("O_MOVIEFLAGS", "movieFlags", 1)); + SetAt(O_PLAYMOVIERECT, COpcodeAttributes("O_PLAYMOVIERECT", "playMovieRect", 5)); + SetAt(O_PLAYMOVIEALPHA, COpcodeAttributes("O_PLAYMOVIEALPHA", "playmoviealpha", 2)); + SetAt(O_PLAYMOVIEALPHARECT, COpcodeAttributes("O_PLAYMOVIEALPHARECT", "playMovieAlphaRect", 6)); + SetAt(O_ADDREGION, COpcodeAttributes("O_ADDREGION", "addRegion", 5, expression)); + SetAt(O_ADDREGIONFLAG, COpcodeAttributes("O_ADDREGIONFLAG", "addRegionFlag", 2)); + SetAt(O_ADDREGIONPROC, COpcodeAttributes("O_ADDREGIONPROC", "addRegionProc", 5)); + SetAt(O_ADDREGIONRIGHTPROC, COpcodeAttributes("O_ADDREGIONRIGHTPROC", "addRegionRightProc", 3)); + SetAt(O_DELETEREGION, COpcodeAttributes("O_DELETEREGION", "deleteRegion", 1)); + SetAt(O_ACTIVATEREGION, COpcodeAttributes("O_ACTIVATEREGION", "activateRegion", 2)); + SetAt(O_CHECKREGION, COpcodeAttributes("O_CHECKREGION", "checkRegion", 1, expression)); + SetAt(O_ADDBUTTON, COpcodeAttributes("O_ADDBUTTON", "addButton", 5)); + SetAt(O_ADDBUTTONTEXT, COpcodeAttributes("O_ADDBUTTONTEXT", "addButtonText", 2)); + SetAt(O_ADDBUTTONFLAG, COpcodeAttributes("O_ADDBUTTONFLAG", "addButtonFlag", 2)); + SetAt(O_ADDBUTTONGFX, COpcodeAttributes("O_ADDBUTTONGFX", "addButtonGfx", 4)); + SetAt(O_ADDBUTTONPROC, COpcodeAttributes("O_ADDBUTTONPROC", "addButtonProc", 5)); + SetAt(O_ADDBUTTONRIGHTPROC, COpcodeAttributes("O_ADDBUTTONRIGHTPROC", "addButtonRightProc", 3)); + SetAt(O_DELETEBUTTON, COpcodeAttributes("O_DELETEBUTTON", "deleteButton", 1)); + SetAt(O_HIDEMOUSE, COpcodeAttributes("O_HIDEMOUSE", "hideMouse", 0)); + SetAt(O_SHOWMOUSE, COpcodeAttributes("O_SHOWMOUSE", "showMouse", 0)); + SetAt(O_MOUSESHAPE, COpcodeAttributes("O_MOUSESHAPE", "mouseShape", 3)); + SetAt(O_REFRESHMOUSE, COpcodeAttributes("O_REFRESHMOUSE", "refreshMouse", 1)); + SetAt(O_SETGLOBALMOUSEFUNC, COpcodeAttributes("O_SETGLOBALMOUSEFUNC", "setGlobalMouseFunc", 4)); + SetAt(O_ADDNAMEDEVENT, COpcodeAttributes("O_ADDNAMEDEVENT", "addNamedEvent", 2)); + SetAt(O_ADDNAMEDHANDLER, COpcodeAttributes("O_ADDNAMEDHANDLER", "addNamedHandler", 2)); + SetAt(O_CLEARNAMED, COpcodeAttributes("O_CLEARNAMED", "clearNamed", 1)); + SetAt(O_SIGNALNAMED, COpcodeAttributes("O_SIGNALNAMED", "signalNamed", 1)); + SetAt(O_ADDKEY, COpcodeAttributes("O_ADDKEY", "addKey", 2)); + SetAt(O_DELETEKEY, COpcodeAttributes("O_DELETEKEY", "deleteKey", 1)); + SetAt(O_SOUNDPLAY, COpcodeAttributes("O_SOUNDPLAY", "soundPlay", 2, expression)); + SetAt(O_SOUNDPAUSE, COpcodeAttributes("O_SOUNDPAUSE", "soundPause", 1)); + SetAt(O_SOUNDRESUME, COpcodeAttributes("O_SOUNDRESUME", "soundResume", 1)); + SetAt(O_SOUNDSTOP, COpcodeAttributes("O_SOUNDSTOP", "soundStop", 1)); + SetAt(O_SOUNDREWIND, COpcodeAttributes("O_SOUNDREWIND", "soundRewind", 1)); + SetAt(O_SOUNDDELETE, COpcodeAttributes("O_SOUNDDELETE", "soundDelete", 1)); + SetAt(O_SETONEOPTPAUSE, COpcodeAttributes("O_SETONEOPTPAUSE", "setOneOptPause", 1)); + SetAt(O_SELECTFILELIST, COpcodeAttributes("O_SELECTFILELIST", "selectFileList", 2, expression)); + SetAt(O_TOKENIZE, COpcodeAttributes("O_TOKENIZE", "tokenize", 3, expression)); + SetAt(O_GIVE_EXP_POINTS, COpcodeAttributes("O_GIVE_EXP_POINTS", "give_exp_points", 1)); + SetAt(O_SCR_RETURN, COpcodeAttributes("O_SCR_RETURN", "scr_return", 1)); + SetAt(O_PLAY_SFX, COpcodeAttributes("O_PLAY_SFX", "play_sfx", 1)); + SetAt(O_OBJ_NAME, COpcodeAttributes("O_OBJ_NAME", "obj_name", 1, expression)); + SetAt(O_SFX_BUILD_OPEN_NAME, COpcodeAttributes("O_SFX_BUILD_OPEN_NAME", "sfx_build_open_name", 2, expression)); + SetAt(O_GET_PC_STAT, COpcodeAttributes("O_GET_PC_STAT", "get_pc_stat", 1, expression)); + SetAt(O_TILE_CONTAINS_PID_OBJ, COpcodeAttributes("O_TILE_CONTAINS_PID_OBJ", "tile_contains_pid_obj", 3, expression)); + SetAt(O_SET_MAP_START, COpcodeAttributes("O_SET_MAP_START", "set_map_start", 4)); + SetAt(O_OVERRIDE_MAP_START, COpcodeAttributes("O_OVERRIDE_MAP_START", "override_map_start", 4)); + SetAt(O_HAS_SKILL, COpcodeAttributes("O_HAS_SKILL", "has_skill", 2, expression)); + SetAt(O_USING_SKILL, COpcodeAttributes("O_USING_SKILL", "using_skill", 2, expression)); + SetAt(O_ROLL_VS_SKILL, COpcodeAttributes("O_ROLL_VS_SKILL", "roll_vs_skill", 3, expression)); + SetAt(O_SKILL_CONTEST, COpcodeAttributes("O_SKILL_CONTEST", "skill_contest", 3, expression)); + SetAt(O_DO_CHECK, COpcodeAttributes("O_DO_CHECK", "do_check", 3, expression)); + SetAt(O_IS_SUCCESS, COpcodeAttributes("O_IS_SUCCESS", "is_success", 1, expression)); + SetAt(O_IS_CRITICAL, COpcodeAttributes("O_IS_CRITICAL", "is_critical", 1, expression)); + SetAt(O_HOW_MUCH, COpcodeAttributes("O_HOW_MUCH", "how_much", 0, expression)); + SetAt(O_MARK_AREA_KNOWN, COpcodeAttributes("O_MARK_AREA_KNOWN", "mark_area_known", 3)); + SetAt(O_REACTION_INFLUENCE, COpcodeAttributes("O_REACTION_INFLUENCE", "reaction_influence", 3, expression)); + SetAt(O_RANDOM, COpcodeAttributes("O_RANDOM", "random", 2, expression)); + SetAt(O_ROLL_DICE, COpcodeAttributes("O_ROLL_DICE", "roll_dice", 2, expression)); + SetAt(O_MOVE_TO, COpcodeAttributes("O_MOVE_TO", "move_to", 3, expression)); + SetAt(O_CREATE_OBJECT_SID, COpcodeAttributes("O_CREATE_OBJECT_SID", "create_object_sid", 4, expression)); + SetAt(O_DISPLAY_MSG, COpcodeAttributes("O_DISPLAY_MSG", "display_msg", 1)); + SetAt(O_SCRIPT_OVERRIDES, COpcodeAttributes("O_SCRIPT_OVERRIDES", "script_overrides", 0)); + SetAt(O_OBJ_IS_CARRYING_OBJ_PID, COpcodeAttributes("O_OBJ_IS_CARRYING_OBJ_PID", "obj_is_carrying_obj_pid", 2, expression)); + SetAt(O_TILE_CONTAINS_OBJ_PID, COpcodeAttributes("O_TILE_CONTAINS_OBJ_PID", "tile_contains_obj_pid", 3, expression)); + SetAt(O_SELF_OBJ, COpcodeAttributes("O_SELF_OBJ", "self_obj", 0, expression)); + SetAt(O_SOURCE_OBJ, COpcodeAttributes("O_SOURCE_OBJ", "source_obj", 0, expression)); + SetAt(O_TARGET_OBJ, COpcodeAttributes("O_TARGET_OBJ", "target_obj", 0, expression)); + SetAt(O_DUDE_OBJ, COpcodeAttributes("O_DUDE_OBJ", "dude_obj", 0, expression)); + SetAt(O_OBJ_BEING_USED_WITH, COpcodeAttributes("O_OBJ_BEING_USED_WITH", "obj_being_used_with", 0, expression)); + SetAt(O_LOCAL_VAR, COpcodeAttributes("O_LOCAL_VAR", "local_var", 1, expression)); + SetAt(O_SET_LOCAL_VAR, COpcodeAttributes("O_SET_LOCAL_VAR", "set_local_var", 2)); + SetAt(O_MAP_VAR, COpcodeAttributes("O_MAP_VAR", "map_var", 1, expression)); + SetAt(O_SET_MAP_VAR, COpcodeAttributes("O_SET_MAP_VAR", "set_map_var", 2)); + SetAt(O_GLOBAL_VAR, COpcodeAttributes("O_GLOBAL_VAR", "global_var", 1, expression)); + SetAt(O_SET_GLOBAL_VAR, COpcodeAttributes("O_SET_GLOBAL_VAR", "set_global_var", 2)); + SetAt(O_SCRIPT_ACTION, COpcodeAttributes("O_SCRIPT_ACTION", "script_action", 0, expression)); + SetAt(O_OBJ_TYPE, COpcodeAttributes("O_OBJ_TYPE", "obj_type", 1, expression)); + SetAt(O_OBJ_ITEM_SUBTYPE, COpcodeAttributes("O_OBJ_ITEM_SUBTYPE", "obj_item_subtype", 1, expression)); + SetAt(O_GET_CRITTER_STAT, COpcodeAttributes("O_GET_CRITTER_STAT", "get_critter_stat", 2, expression)); + SetAt(O_SET_CRITTER_STAT, COpcodeAttributes("O_SET_CRITTER_STAT", "set_critter_stat", 3, expression)); + SetAt(O_ANIMATE_STAND_OBJ, COpcodeAttributes("O_ANIMATE_STAND_OBJ", "animate_stand_obj", 1)); + SetAt(O_ANIMATE_STAND_REVERSE_OBJ, COpcodeAttributes("O_ANIMATE_STAND_REVERSE_OBJ", "animate_stand_reverse_obj", 1)); + SetAt(O_ANIMATE_MOVE_OBJ_TO_TILE, COpcodeAttributes("O_ANIMATE_MOVE_OBJ_TO_TILE", "animate_move_obj_to_tile", 3)); + SetAt(O_TILE_IN_TILE_RECT, COpcodeAttributes("O_TILE_IN_TILE_RECT", "tile_in_tile_rect", 5, expression)); + SetAt(O_ATTACK_COMPLEX, COpcodeAttributes("O_ATTACK_COMPLEX", "attack_complex", 8)); + SetAt(O_MAKE_DAYTIME, COpcodeAttributes("O_MAKE_DAYTIME", "make_daytime", 0)); + SetAt(O_TILE_DISTANCE, COpcodeAttributes("O_TILE_DISTANCE", "tile_distance", 2, expression)); + SetAt(O_TILE_DISTANCE_OBJS, COpcodeAttributes("O_TILE_DISTANCE_OBJS", "tile_distance_objs", 2, expression)); + SetAt(O_TILE_NUM, COpcodeAttributes("O_TILE_NUM", "tile_num", 1, expression)); + SetAt(O_TILE_NUM_IN_DIRECTION, COpcodeAttributes("O_TILE_NUM_IN_DIRECTION", "tile_num_in_direction", 3, expression)); + SetAt(O_PICKUP_OBJ, COpcodeAttributes("O_PICKUP_OBJ", "pickup_obj", 1)); + SetAt(O_DROP_OBJ, COpcodeAttributes("O_DROP_OBJ", "drop_obj", 1)); + SetAt(O_ADD_OBJ_TO_INVEN, COpcodeAttributes("O_ADD_OBJ_TO_INVEN", "add_obj_to_inven", 2)); + SetAt(O_RM_OBJ_FROM_INVEN, COpcodeAttributes("O_RM_OBJ_FROM_INVEN", "rm_obj_from_inven", 2)); + SetAt(O_WIELD_OBJ_CRITTER, COpcodeAttributes("O_WIELD_OBJ_CRITTER", "wield_obj_critter", 2)); + SetAt(O_USE_OBJ, COpcodeAttributes("O_USE_OBJ", "use_obj", 1)); + SetAt(O_OBJ_CAN_SEE_OBJ, COpcodeAttributes("O_OBJ_CAN_SEE_OBJ", "obj_can_see_obj", 2, expression)); + SetAt(O_ATTACK, COpcodeAttributes("O_ATTACK", "attack", 8)); + SetAt(O_START_GDIALOG, COpcodeAttributes("O_START_GDIALOG", "start_gdialog", 5)); + SetAt(O_END_DIALOGUE, COpcodeAttributes("O_END_DIALOGUE", "end_dialogue", 0)); + SetAt(O_DIALOGUE_REACTION, COpcodeAttributes("O_DIALOGUE_REACTION", "dialogue_reaction", 1)); + SetAt(O_METARULE3, COpcodeAttributes("O_METARULE3", "metarule3", 4, expression)); + SetAt(O_SET_MAP_MUSIC, COpcodeAttributes("O_SET_MAP_MUSIC", "set_map_music", 2)); + SetAt(O_SET_OBJ_VISIBILITY, COpcodeAttributes("O_SET_OBJ_VISIBILITY", "set_obj_visibility", 2)); + SetAt(O_LOAD_MAP, COpcodeAttributes("O_LOAD_MAP", "load_map", 2)); + SetAt(O_WM_AREA_SET_POS, COpcodeAttributes("O_WM_AREA_SET_POS", "wm_area_set_pos", 3)); + SetAt(O_SET_EXIT_GRIDS, COpcodeAttributes("O_SET_EXIT_GRIDS", "set_exit_grids", 5)); + SetAt(O_ANIM_BUSY, COpcodeAttributes("O_ANIM_BUSY", "anim_busy", 1, expression)); + SetAt(O_CRITTER_HEAL, COpcodeAttributes("O_CRITTER_HEAL", "critter_heal", 2, expression)); + SetAt(O_SET_LIGHT_LEVEL, COpcodeAttributes("O_SET_LIGHT_LEVEL", "set_light_level", 1)); + SetAt(O_GAME_TIME, COpcodeAttributes("O_GAME_TIME", "game_time", 0, expression)); + SetAt(O_GAME_TIME_IN_SECONDS, COpcodeAttributes("O_GAME_TIME_IN_SECONDS", "game_time_in_seconds", 0, expression)); + SetAt(O_ELEVATION, COpcodeAttributes("O_ELEVATION", "elevation", 1, expression)); + SetAt(O_KILL_CRITTER, COpcodeAttributes("O_KILL_CRITTER", "kill_critter", 2)); + SetAt(O_KILL_CRITTER_TYPE, COpcodeAttributes("O_KILL_CRITTER_TYPE", "kill_critter_type", 2)); + SetAt(O_CRITTER_DMG, COpcodeAttributes("O_CRITTER_DMG", "critter_dmg", 3)); + SetAt(O_ADD_TIMER_EVENT, COpcodeAttributes("O_ADD_TIMER_EVENT", "add_timer_event", 3)); + SetAt(O_RM_TIMER_EVENT, COpcodeAttributes("O_RM_TIMER_EVENT", "rm_timer_event", 1)); + SetAt(O_GAME_TICKS, COpcodeAttributes("O_GAME_TICKS", "game_ticks", 1, expression)); + SetAt(O_HAS_TRAIT, COpcodeAttributes("O_HAS_TRAIT", "has_trait", 3, expression)); + SetAt(O_DESTROY_OBJECT, COpcodeAttributes("O_DESTROY_OBJECT", "destroy_object", 1)); + SetAt(O_OBJ_CAN_HEAR_OBJ, COpcodeAttributes("O_OBJ_CAN_HEAR_OBJ", "obj_can_hear_obj", 2, expression)); + SetAt(O_GAME_TIME_HOUR, COpcodeAttributes("O_GAME_TIME_HOUR", "game_time_hour", 0, expression)); + SetAt(O_FIXED_PARAM, COpcodeAttributes("O_FIXED_PARAM", "fixed_param", 0, expression)); + SetAt(O_TILE_IS_VISIBLE, COpcodeAttributes("O_TILE_IS_VISIBLE", "tile_is_visible", 1, expression)); + SetAt(O_DIALOGUE_SYSTEM_ENTER, COpcodeAttributes("O_DIALOGUE_SYSTEM_ENTER", "dialogue_system_enter", 0)); + SetAt(O_ACTION_BEING_USED, COpcodeAttributes("O_ACTION_BEING_USED", "action_being_used", 0, expression)); + SetAt(O_CRITTER_STATE, COpcodeAttributes("O_CRITTER_STATE", "critter_state", 1, expression)); + SetAt(O_GAME_TIME_ADVANCE, COpcodeAttributes("O_GAME_TIME_ADVANCE", "game_time_advance", 1)); + SetAt(O_RADIATION_INC, COpcodeAttributes("O_RADIATION_INC", "radiation_inc", 2)); + SetAt(O_RADIATION_DEC, COpcodeAttributes("O_RADIATION_DEC", "radiation_dec", 2)); + SetAt(O_CRITTER_ATTEMPT_PLACEMENT, COpcodeAttributes("O_CRITTER_ATTEMPT_PLACEMENT", "critter_attempt_placement", 3, expression)); + SetAt(O_OBJ_PID, COpcodeAttributes("O_OBJ_PID", "obj_pid", 1, expression)); + SetAt(O_CUR_MAP_INDEX, COpcodeAttributes("O_CUR_MAP_INDEX", "cur_map_index", 0, expression)); + SetAt(O_CRITTER_ADD_TRAIT, COpcodeAttributes("O_CRITTER_ADD_TRAIT", "critter_add_trait", 4, expression)); + SetAt(O_CRITTER_RM_TRAIT, COpcodeAttributes("O_CRITTER_RM_TRAIT", "critter_rm_trait", 4, expression)); + SetAt(O_PROTO_DATA, COpcodeAttributes("O_PROTO_DATA", "proto_data", 2, expression)); + SetAt(O_MESSAGE_STR, COpcodeAttributes("O_MESSAGE_STR", "message_str", 2, expression)); + SetAt(O_CRITTER_INVEN_OBJ, COpcodeAttributes("O_CRITTER_INVEN_OBJ", "critter_inven_obj", 2, expression)); + SetAt(O_OBJ_SET_LIGHT_LEVEL, COpcodeAttributes("O_OBJ_SET_LIGHT_LEVEL", "obj_set_light_level", 3)); + SetAt(O_WORLD_MAP, COpcodeAttributes("O_WORLD_MAP", "world_map", 0)); + SetAt(O_INVEN_CMDS, COpcodeAttributes("O_INVEN_CMDS", "inven_cmds", 3, expression)); + SetAt(O_FLOAT_MSG, COpcodeAttributes("O_FLOAT_MSG", "float_msg", 3)); + SetAt(O_METARULE, COpcodeAttributes("O_METARULE", "metarule", 2, expression)); + SetAt(O_ANIM, COpcodeAttributes("O_ANIM", "anim", 3)); + SetAt(O_OBJ_CARRYING_PID_OBJ, COpcodeAttributes("O_OBJ_CARRYING_PID_OBJ", "obj_carrying_pid_obj", 2, expression)); + SetAt(O_REG_ANIM_FUNC, COpcodeAttributes("O_REG_ANIM_FUNC", "reg_anim_func", 2)); + SetAt(O_REG_ANIM_ANIMATE, COpcodeAttributes("O_REG_ANIM_ANIMATE", "reg_anim_animate", 3)); + SetAt(O_REG_ANIM_ANIMATE_REVERSE, COpcodeAttributes("O_REG_ANIM_ANIMATE_REVERSE", "reg_anim_animate_reverse", 3)); + SetAt(O_REG_ANIM_OBJ_MOVE_TO_OBJ, COpcodeAttributes("O_REG_ANIM_OBJ_MOVE_TO_OBJ", "reg_anim_obj_move_to_obj", 3)); + SetAt(O_REG_ANIM_OBJ_RUN_TO_OBJ, COpcodeAttributes("O_REG_ANIM_OBJ_RUN_TO_OBJ", "reg_anim_obj_run_to_obj", 3)); + SetAt(O_REG_ANIM_OBJ_MOVE_TO_TILE, COpcodeAttributes("O_REG_ANIM_OBJ_MOVE_TO_TILE", "reg_anim_obj_move_to_tile", 3)); + SetAt(O_REG_ANIM_OBJ_RUN_TO_TILE, COpcodeAttributes("O_REG_ANIM_OBJ_RUN_TO_TILE", "reg_anim_obj_run_to_tile", 3)); + SetAt(O_PLAY_GMOVIE, COpcodeAttributes("O_PLAY_GMOVIE", "play_gmovie", 1)); + SetAt(O_ADD_MULT_OBJS_TO_INVEN, COpcodeAttributes("O_ADD_MULT_OBJS_TO_INVEN", "add_mult_objs_to_inven", 3)); + SetAt(O_RM_MULT_OBJS_FROM_INVEN, COpcodeAttributes("O_RM_MULT_OBJS_FROM_INVEN", "rm_mult_objs_from_inven", 3, expression)); + SetAt(O_GET_MONTH, COpcodeAttributes("O_GET_MONTH", "get_month", 0, expression)); + SetAt(O_GET_DAY, COpcodeAttributes("O_GET_DAY", "get_day", 0, expression)); + SetAt(O_EXPLOSION, COpcodeAttributes("O_EXPLOSION", "explosion", 3)); + SetAt(O_DAYS_SINCE_VISITED, COpcodeAttributes("O_DAYS_SINCE_VISITED", "days_since_visited", 0, expression)); + SetAt(O_GSAY_START, COpcodeAttributes("O_GSAY_START", "gsay_start", 0)); + SetAt(O_GSAY_END, COpcodeAttributes("O_GSAY_END", "gsay_end", 0)); + SetAt(O_GSAY_REPLY, COpcodeAttributes("O_GSAY_REPLY", "gsay_reply", 2)); + SetAt(O_GSAY_OPTION, COpcodeAttributes("O_GSAY_OPTION", "gsay_option", 4)); + SetAt(O_GSAY_MESSAGE, COpcodeAttributes("O_GSAY_MESSAGE", "gsay_message", 3)); + SetAt(O_GIQ_OPTION, COpcodeAttributes("O_GIQ_OPTION", "giq_option", 5)); + SetAt(O_POISON, COpcodeAttributes("O_POISON", "poison", 2)); + SetAt(O_GET_POISON, COpcodeAttributes("O_GET_POISON", "get_poison", 1, expression)); + SetAt(O_PARTY_ADD, COpcodeAttributes("O_PARTY_ADD", "party_add", 1)); + SetAt(O_PARTY_REMOVE, COpcodeAttributes("O_PARTY_REMOVE", "party_remove", 1)); + SetAt(O_REG_ANIM_ANIMATE_FOREVER, COpcodeAttributes("O_REG_ANIM_ANIMATE_FOREVER", "reg_anim_animate_forever", 2)); + SetAt(O_CRITTER_INJURE, COpcodeAttributes("O_CRITTER_INJURE", "critter_injure", 2)); + SetAt(O_COMBAT_IS_INITIALIZED, COpcodeAttributes("O_COMBAT_IS_INITIALIZED", "combat_is_initialized", 0, expression)); + SetAt(O_GDIALOG_MOD_BARTER, COpcodeAttributes("O_GDIALOG_MOD_BARTER", "gdialog_mod_barter", 1)); + SetAt(O_DIFFICULTY_LEVEL, COpcodeAttributes("O_DIFFICULTY_LEVEL", "difficulty_level", 0, expression)); + SetAt(O_RUNNING_BURNING_GUY, COpcodeAttributes("O_RUNNING_BURNING_GUY", "running_burning_guy", 0, expression)); + SetAt(O_INVEN_UNWIELD, COpcodeAttributes("O_INVEN_UNWIELD", "inven_unwield", 0)); + SetAt(O_OBJ_IS_LOCKED, COpcodeAttributes("O_OBJ_IS_LOCKED", "obj_is_locked", 1, expression)); + SetAt(O_OBJ_LOCK, COpcodeAttributes("O_OBJ_LOCK", "obj_lock", 1)); + SetAt(O_OBJ_UNLOCK, COpcodeAttributes("O_OBJ_UNLOCK", "obj_unlock", 1)); + SetAt(O_OBJ_IS_OPEN, COpcodeAttributes("O_OBJ_IS_OPEN", "obj_is_open", 1, expression)); + SetAt(O_OBJ_OPEN, COpcodeAttributes("O_OBJ_OPEN", "obj_open", 1)); + SetAt(O_OBJ_CLOSE, COpcodeAttributes("O_OBJ_CLOSE", "obj_close", 1)); + SetAt(O_GAME_UI_DISABLE, COpcodeAttributes("O_GAME_UI_DISABLE", "game_ui_disable", 0)); + SetAt(O_GAME_UI_ENABLE, COpcodeAttributes("O_GAME_UI_ENABLE", "game_ui_enable", 0)); + SetAt(O_GAME_UI_IS_DISABLED, COpcodeAttributes("O_GAME_UI_IS_DISABLED", "game_ui_is_disabled", 0, expression)); + SetAt(O_GFADE_OUT, COpcodeAttributes("O_GFADE_OUT", "gfade_out", 1)); + SetAt(O_GFADE_IN, COpcodeAttributes("O_GFADE_IN", "gfade_in", 1)); + SetAt(O_ITEM_CAPS_TOTAL, COpcodeAttributes("O_ITEM_CAPS_TOTAL", "item_caps_total", 1, expression)); + SetAt(O_ITEM_CAPS_ADJUST, COpcodeAttributes("O_ITEM_CAPS_ADJUST", "item_caps_adjust", 2, expression)); + SetAt(O_ANIM_ACTION_FRAME, COpcodeAttributes("O_ANIM_ACTION_FRAME", "anim_action_frame", 2, expression)); + SetAt(O_REG_ANIM_PLAY_SFX, COpcodeAttributes("O_REG_ANIM_PLAY_SFX", "reg_anim_play_sfx", 3)); + SetAt(O_CRITTER_MOD_SKILL, COpcodeAttributes("O_CRITTER_MOD_SKILL", "critter_mod_skill", 3)); + SetAt(O_SFX_BUILD_CHAR_NAME, COpcodeAttributes("O_SFX_BUILD_CHAR_NAME", "sfx_build_char_name", 3, expression)); + SetAt(O_SFX_BUILD_AMBIENT_NAME, COpcodeAttributes("O_SFX_BUILD_AMBIENT_NAME", "sfx_build_ambient_name", 1, expression)); + SetAt(O_SFX_BUILD_INTERFACE_NAME, COpcodeAttributes("O_SFX_BUILD_INTERFACE_NAME", "sfx_build_interface_name", 1, expression)); + SetAt(O_SFX_BUILD_ITEM_NAME, COpcodeAttributes("O_SFX_BUILD_ITEM_NAME", "sfx_build_item_name", 1, expression)); + SetAt(O_SFX_BUILD_WEAPON_NAME, COpcodeAttributes("O_SFX_BUILD_WEAPON_NAME", "sfx_build_weapon_name", 4, expression)); + SetAt(O_SFX_BUILD_SCENERY_NAME, COpcodeAttributes("O_SFX_BUILD_SCENERY_NAME", "sfx_build_scenery_name", 3, expression)); + SetAt(O_ATTACK_SETUP, COpcodeAttributes("O_ATTACK_SETUP", "attack_setup", 2)); + SetAt(O_DESTROY_MULT_OBJS, COpcodeAttributes("O_DESTROY_MULT_OBJS", "destroy_mult_objs", 2, expression)); + SetAt(O_USE_OBJ_ON_OBJ, COpcodeAttributes("O_USE_OBJ_ON_OBJ", "use_obj_on_obj", 2)); + SetAt(O_ENDGAME_SLIDESHOW, COpcodeAttributes("O_ENDGAME_SLIDESHOW", "endgame_slideshow", 0)); + SetAt(O_MOVE_OBJ_INVEN_TO_OBJ, COpcodeAttributes("O_MOVE_OBJ_INVEN_TO_OBJ", "move_obj_inven_to_obj", 2)); + SetAt(O_ENDGAME_MOVIE, COpcodeAttributes("O_ENDGAME_MOVIE", "endgame_movie", 0)); + SetAt(O_OBJ_ART_FID, COpcodeAttributes("O_OBJ_ART_FID", "obj_art_fid", 1, expression)); + SetAt(O_ART_ANIM, COpcodeAttributes("O_ART_ANIM", "art_anim", 1, expression)); + SetAt(O_PARTY_MEMBER_OBJ, COpcodeAttributes("O_PARTY_MEMBER_OBJ", "party_member_obj", 1, expression)); + SetAt(O_ROTATION_TO_TILE, COpcodeAttributes("O_ROTATION_TO_TILE", "rotation_to_tile", 2, expression)); + SetAt(O_JAM_LOCK, COpcodeAttributes("O_JAM_LOCK", "jam_lock", 1)); + SetAt(O_GDIALOG_SET_BARTER_MOD, COpcodeAttributes("O_GDIALOG_SET_BARTER_MOD", "gdialog_set_barter_mod", 1)); + SetAt(O_COMBAT_DIFFICULTY, COpcodeAttributes("O_COMBAT_DIFFICULTY", "combat_difficulty", 0, expression)); + SetAt(O_OBJ_ON_SCREEN, COpcodeAttributes("O_OBJ_ON_SCREEN", "obj_on_screen", 1, expression)); + SetAt(O_CRITTER_IS_FLEEING, COpcodeAttributes("O_CRITTER_IS_FLEEING", "critter_is_fleeing", 1, expression)); + SetAt(O_CRITTER_SET_FLEE_STATE, COpcodeAttributes("O_CRITTER_SET_FLEE_STATE", "critter_set_flee_state", 2)); + SetAt(O_TERMINATE_COMBAT, COpcodeAttributes("O_TERMINATE_COMBAT", "terminate_combat", 0)); + SetAt(O_DEBUG_MSG, COpcodeAttributes("O_DEBUG_MSG", "debug_msg", 1)); + SetAt(O_CRITTER_STOP_ATTACKING, COpcodeAttributes("O_CRITTER_STOP_ATTACKING", "critter_stop_attacking", 1)); + + //sall start + + SetAt(O_READ_BYTE, COpcodeAttributes("O_READ_BYTE", "read_byte", 1, expression)); + SetAt(O_READ_SHORT, COpcodeAttributes("O_READ_SHORT", "read_short", 1, expression)); + SetAt(O_READ_INT, COpcodeAttributes("O_READ_INT", "read_int", 1, expression)); + SetAt(O_READ_STRING, COpcodeAttributes("O_READ_STRING", "read_string", 1, expression)); + + SetAt(O_SET_PC_BASE_STAT, COpcodeAttributes("O_SET_PC_BASE_STAT", "set_pc_base_stat", 2)); + SetAt(O_SET_PC_EXTRA_STAT, COpcodeAttributes("O_SET_PC_EXTRA_STAT", "set_pc_extra_stat", 2)); + SetAt(O_GET_PC_BASE_STAT, COpcodeAttributes("O_GET_PC_BASE_STAT", "get_pc_base_stat", 1, expression)); + SetAt(O_GET_PC_EXTRA_STAT, COpcodeAttributes("O_GET_PC_EXTRA_STAT", "get_pc_extra_stat", 1, expression)); + + SetAt(O_SET_CRITTER_BASE_STAT, COpcodeAttributes("O_SET_CRITTER_BASE_STAT", "set_critter_base_stat", 3)); + SetAt(O_SET_CRITTER_EXTRA_STAT, COpcodeAttributes("O_SET_CRITTER_EXTRA_STAT", "set_critter_extra_stat", 3)); + SetAt(O_GET_CRITTER_BASE_STAT, COpcodeAttributes("O_GET_CRITTER_BASE_STAT", "get_critter_base_stat", 2, expression)); + SetAt(O_GET_CRITTER_EXTRA_STAT, COpcodeAttributes("O_GET_CRITTER_EXTRA_STAT", "get_critter_extra_stat", 2, expression)); + + SetAt(O_TAP_KEY, COpcodeAttributes("O_TAP_KEY", "tap_key", 1)); + SetAt(O_GET_YEAR, COpcodeAttributes("O_GET_YEAR", "get_year", 0, expression)); + + SetAt(O_GAME_LOADED, COpcodeAttributes("O_GAME_LOADED", "game_loaded", 0, expression)); + SetAt(O_GRAPHICS_FUNCS_AVAILABLE, COpcodeAttributes("O_GRAPHICS_FUNCS_AVAILABLE", "graphics_funcs_available", 0, expression)); + SetAt(O_LOAD_SHADER, COpcodeAttributes("O_LOAD_SHADER", "load_shader", 1, expression)); + SetAt(O_FREE_SHADER, COpcodeAttributes("O_FREE_SHADER", "free_shader", 1)); + SetAt(O_ACTIVATE_SHADER, COpcodeAttributes("O_ACTIVATE_SHADER", "activate_shader", 1)); + SetAt(O_DEACTIVATE_SHADER, COpcodeAttributes("O_DEACTIVATE_SHADER", "deactivate_shader", 1)); + SetAt(O_SET_GLOBAL_SCRIPT_REPEAT, COpcodeAttributes("O_SET_GLOBAL_SCRIPT_REPEAT", "set_global_script_repeat", 1)); + SetAt(O_INPUT_FUNCS_AVAILABLE, COpcodeAttributes("O_INPUT_FUNCS_AVAILABLE", "input_funcs_available", 0, expression)); + SetAt(O_KEY_PRESSED, COpcodeAttributes("O_KEY_PRESSED", "key_pressed", 1, expression)); + + SetAt(O_SET_SHADER_INT, COpcodeAttributes("O_SET_SHADER_INT", "set_shader_int", 3)); + SetAt(O_SET_SHADER_FLOAT, COpcodeAttributes("O_SET_SHADER_FLOAT", "set_shader_float", 3)); + SetAt(O_SET_SHADER_VECTOR, COpcodeAttributes("O_SET_SHADER_VECTOR", "set_shader_vector", 6)); + SetAt(O_IN_WORLD_MAP, COpcodeAttributes("O_IN_WORLD_MAP", "in_world_map", 0, expression)); + SetAt(O_FORCE_ENCOUNTER, COpcodeAttributes("O_FORCE_ENCOUNTER", "force_encounter", 1)); + SetAt(O_SET_WORLD_MAP_POS, COpcodeAttributes("O_SET_WORLD_MAP_POS", "set_world_map_pos", 2)); + SetAt(O_GET_WORLD_MAP_X_POS, COpcodeAttributes("O_GET_WORLD_MAP_X_POS", "get_world_map_x_pos", 0, expression)); + SetAt(O_GET_WORLD_MAP_Y_POS, COpcodeAttributes("O_GET_WORLD_MAP_Y_POS", "get_world_map_y_pos", 0, expression)); + + SetAt(O_SET_DM_MODEL, COpcodeAttributes("O_SET_DM_MODEL", "set_dm_model", 1)); + SetAt(O_SET_DF_MODEL, COpcodeAttributes("O_SET_DF_MODEL", "set_df_model", 1)); + SetAt(O_SET_MOVIE_PATH, COpcodeAttributes("O_SET_MOVIE_PATH", "set_movie_path", 2)); + + SetAt(O_SET_PERK_IMAGE, COpcodeAttributes("O_SET_PERK_IMAGE", "set_perk_image", 2)); + SetAt(O_SET_PERK_RANKS, COpcodeAttributes("O_SET_PERK_RANKS", "set_perk_ranks", 2)); + SetAt(O_SET_PERK_LEVEL, COpcodeAttributes("O_SET_PERK_LEVEL", "set_perk_level", 2)); + SetAt(O_SET_PERK_STAT, COpcodeAttributes("O_SET_PERK_STAT", "set_perk_stat", 2)); + SetAt(O_SET_PERK_STAT_MAG, COpcodeAttributes("O_SET_PERK_STAT_MAG", "set_perk_stat_mag", 2)); + SetAt(O_SET_PERK_SKILL1, COpcodeAttributes("O_SET_PERK_SKILL1", "set_perk_skill1", 2)); + SetAt(O_SET_PERK_SKILl1_MAG, COpcodeAttributes("O_SET_PERK_SKILl1_MAG", "set_perk_skill1_mag", 2)); + SetAt(O_SET_PERK_TYPE, COpcodeAttributes("O_SET_PERK_TYPE", "set_perk_type", 2)); + SetAt(O_SET_PERK_SKILL2, COpcodeAttributes("O_SET_PERK_SKILL2", "set_perk_skill2", 2)); + SetAt(O_SET_PERK_SKILL2_MAG, COpcodeAttributes("O_SET_PERK_SKILL2_MAG", "set_perk_skill2_mag", 2)); + SetAt(O_SET_PERK_STR, COpcodeAttributes("O_SET_PERK_STR", "set_perk_str", 2)); + SetAt(O_SET_PERK_PER, COpcodeAttributes("O_SET_PERK_PER", "set_perk_per", 2)); + SetAt(O_SET_PERK_END, COpcodeAttributes("O_SET_PERK_END", "set_perk_end", 2)); + SetAt(O_SET_PERK_CHR, COpcodeAttributes("O_SET_PERK_CHR", "set_perk_chr", 2)); + SetAt(O_SET_PERK_INT, COpcodeAttributes("O_SET_PERK_INT", "set_perk_int", 2)); + SetAt(O_SET_PERK_AGL, COpcodeAttributes("O_SET_PERK_AGL", "set_perk_agl", 2)); + SetAt(O_SET_PERK_LCK, COpcodeAttributes("O_SET_PERK_LCK", "set_perk_lck", 2)); + SetAt(O_SET_PERK_NAME, COpcodeAttributes("O_SET_PERK_NAME", "set_perk_name", 2)); + SetAt(O_SET_PERK_DESC, COpcodeAttributes("O_SET_PERK_DESC", "set_perk_desc", 2)); + + SetAt(O_SET_PIPBOY_AVAILABLE, COpcodeAttributes("O_SET_PIPBOY_AVAILABLE", "set_pipboy_available", 1)); + + SetAt(O_GET_KILL_COUNTER, COpcodeAttributes("O_GET_KILL_COUNTER", "get_kill_counter", 1, expression)); + SetAt(O_MOD_KILL_COUNTER, COpcodeAttributes("O_MOD_KILL_COUNTER", "mod_kill_counter", 2)); + + SetAt(O_GET_PERK_OWED, COpcodeAttributes("O_GET_PERK_OWED", "get_perk_owed", 0, expression)); + SetAt(O_SET_PERK_OWED, COpcodeAttributes("O_SET_PERK_OWED", "set_perk_owed", 1)); + SetAt(O_GET_PERK_AVAILABLE, COpcodeAttributes("O_GET_PERK_AVAILABLE", "get_perk_available", 1, expression)); + + SetAt(O_GET_CRITTER_AP, COpcodeAttributes("O_GET_CRITTER_AP", "get_critter_current_ap", 1, expression)); + SetAt(O_SET_CRITTER_AP, COpcodeAttributes("O_SET_CRITTER_AP", "set_critter_current_ap", 2)); + + SetAt(O_GET_ACTIVE_HAND, COpcodeAttributes("O_GET_ACTIVE_HAND", "active_hand", 0, expression)); + SetAt(O_TOGGLE_ACTIVE_HAND, COpcodeAttributes("O_TOGGLE_ACTIVE_HAND", "toggle_active_hand", 0)); + + SetAt(O_SET_WEAPON_KNOCKBACK, COpcodeAttributes("O_SET_WEAPON_KNOCKBACK", "set_weapon_knockback", 3)); + SetAt(O_SET_TARGET_KNOCKBACK, COpcodeAttributes("O_SET_TARGET_KNOCKBACK", "set_target_knockback", 3)); + SetAt(O_SET_ATTACKER_KNOCKBACK, COpcodeAttributes("O_SET_ATTACKER_KNOCKBACK", "set_attacker_knockback", 3)); + SetAt(O_REMOVE_WEAPON_KNOCKBACK, COpcodeAttributes("O_REMOVE_WEAPON_KNOCKBACK", "remove_weapon_knockback", 1)); + SetAt(O_REMOVE_TARGET_KNOCKBACK, COpcodeAttributes("O_REMOVE_TARGET_KNOCKBACK", "remove_target_knockback", 1)); + SetAt(O_REMOVE_ATTACKER_KNOCKBACK, COpcodeAttributes("O_REMOVE_ATTACKER_KNOCKBACK", "remove_attacker_knockback", 1)); + + SetAt(O_SET_GLOBAL_SCRIPT_TYPE, COpcodeAttributes("O_SET_GLOBAL_SCRIPT_TYPE", "set_global_script_type", 1)); + SetAt(O_AVAILABLE_GLOBAL_SCRIPT_TYPES, COpcodeAttributes("O_AVAILABLE_GLOBAL_SCRIPT_TYPES", "available_global_script_types", 0, expression)); + + SetAt(O_SET_SFALL_GLOBAL, COpcodeAttributes("O_SET_SFALL_GLOBAL", "set_sfall_global", 2)); + SetAt(O_GET_SFALL_GLOBAL_INT, COpcodeAttributes("O_GET_SFALL_GLOBAL_INT", "get_sfall_global_int", 1, expression)); + SetAt(O_GET_SFALL_GLOBAL_FLOAT, COpcodeAttributes("O_GET_SFALL_GLOBAL_FLOAT", "get_sfall_global_float", 1, expression)); + + SetAt(O_SET_PICKPOCKET_MAX, COpcodeAttributes("O_SET_PICKPOCKET_MAX", "set_pickpocket_max", 1)); + SetAt(O_SET_HIT_CHANCE_MAX, COpcodeAttributes("O_SET_HIT_CHANCE_MAX", "set_hit_chance_max", 1)); + SetAt(O_SET_SKILL_MAX, COpcodeAttributes("O_SET_SKILL_MAX", "set_skill_max", 1)); + + SetAt(O_EAX_AVAILABLE, COpcodeAttributes("O_EAX_AVAILABLE", "eax_available", 0, expression)); + SetAt(O_SET_EAX_ENVIRONMENT, COpcodeAttributes("O_SET_EAX_ENVIRONMENT", "set_eax_environment", 1)); + + SetAt(O_INC_NPC_LEVEL, COpcodeAttributes("O_INC_NPC_LEVEL", "inc_npc_level", 1)); + + SetAt(O_GET_VIEWPORT_X, COpcodeAttributes("O_GET_VIEWPORT_X", "get_viewport_x", 0, expression)); + SetAt(O_GET_VIEWPORT_Y, COpcodeAttributes("O_GET_VIEWPORT_Y", "get_viewport_y", 0, expression)); + SetAt(O_SET_VIEWPORT_X, COpcodeAttributes("O_SET_VIEWPORT_X", "set_viewport_x", 1)); + SetAt(O_SET_VIEWPORT_Y, COpcodeAttributes("O_SET_VIEWPORT_Y", "set_viewport_y", 1)); + + SetAt(O_SET_XP_MOD, COpcodeAttributes("O_SET_XP_MOD", "set_xp_mod", 1)); + SetAt(O_SET_PERK_LEVEL_MOD, COpcodeAttributes("O_SET_PERK_LEVEL_MOD", "set_perk_level_mod", 1)); + + SetAt(O_GET_INI_SETTING, COpcodeAttributes("O_GET_INI_SETTING", "get_ini_setting", 1, expression)); + + SetAt(O_GET_SHADER_VERSION, COpcodeAttributes("O_GET_SHADER_VERSION", "get_shader_version", 0, expression)); + SetAt(O_SET_SHADER_MODE, COpcodeAttributes("O_SET_SHADER_MODE", "set_shader_mode", 2)); + + SetAt(O_GET_GAME_MODE, COpcodeAttributes("O_GET_GAME_MODE", "get_game_mode", 0, expression)); + + SetAt(O_FORCE_GRAPHICS_REFRESH, COpcodeAttributes("O_FORCE_GRAPHICS_REFRESH", "force_graphics_refresh", 1)); + SetAt(O_GET_SHADER_TEXTURE, COpcodeAttributes("O_GET_SHADER_TEXTURE", "get_shader_texture", 2, expression)); + SetAt(O_SET_SHADER_TEXTURE, COpcodeAttributes("O_SET_SHADER_TEXTURE", "set_shader_texture", 3)); + + SetAt(O_GET_UPTIME, COpcodeAttributes("O_GET_UPTIME", "get_uptime", 0, expression)); + + SetAt(O_SET_STAT_MAX, COpcodeAttributes("O_SET_STAT_MAX", "set_stat_max", 2)); + SetAt(O_SET_STAT_MIN, COpcodeAttributes("O_SET_STAT_MIN", "set_stat_min", 2)); + + SetAt(O_SET_CAR_CURRENT_TOWN, COpcodeAttributes("O_SET_CAR_CURRENT_TOWN", "set_car_current_town", 1)); + + SetAt(O_SET_PC_STAT_MAX, COpcodeAttributes("O_SET_PC_STAT_MAX", "set_pc_stat_max", 2)); + SetAt(O_SET_PC_STAT_MIN, COpcodeAttributes("O_SET_PC_STAT_MIN", "set_pc_stat_min", 2)); + SetAt(O_SET_NPC_STAT_MAX, COpcodeAttributes("O_SET_NPC_STAT_MAX", "set_npc_stat_max", 2)); + SetAt(O_SET_NPC_STAT_MIN, COpcodeAttributes("O_SET_NPC_STAT_MIN", "set_npc_stat_min", 2)); + + SetAt(O_SET_FAKE_PERK, COpcodeAttributes("O_SET_FAKE_PERK", "set_fake_perk", 4)); + SetAt(O_SET_FAKE_TRAIT, COpcodeAttributes("O_SET_FAKE_TRAIT", "set_fake_trait", 4)); + SetAt(O_SET_SELECTABLE_PERK, COpcodeAttributes("O_SET_SELECTABLE_PERK", "set_selectable_perk", 4)); + SetAt(O_SET_PERKBOX_TITLE, COpcodeAttributes("O_SET_PERKBOX_TITLE", "set_perkbox_title", 1)); + SetAt(O_HIDE_REAL_PERKS, COpcodeAttributes("O_HIDE_REAL_PERKS", "hide_real_perks", 0)); + SetAt(O_SHOW_REAL_PERKS, COpcodeAttributes("O_SHOW_REAL_PERKS", "show_real_perks", 0)); + SetAt(O_HAS_FAKE_PERK, COpcodeAttributes("O_HAS_FAKE_PERK", "has_fake_perk", 1, expression)); + SetAt(O_HAS_FAKE_TRAIT, COpcodeAttributes("O_HAS_FAKE_TRAIT", "has_fake_trait", 1, expression)); + SetAt(O_PERK_ADD_MODE, COpcodeAttributes("O_PERK_ADD_MODE", "perk_add_mode", 1)); + SetAt(O_CLEAR_SELECTABLE_PERKS, COpcodeAttributes("O_CLEAR_SELECTABLE_PERKS", "clear_selectable_perks", 0)); + + SetAt(O_SET_CRITTER_HIT_CHANCE_MOD, COpcodeAttributes("O_SET_CRITTER_HIT_CHANCE_MOD", "set_critter_hit_chance_mod", 3)); + SetAt(O_SET_BASE_HIT_CHANCE_MOD, COpcodeAttributes("O_SET_BASE_HIT_CHANCE_MOD", "set_base_hit_chance_mod", 2)); + SetAt(O_SET_CRITTER_SKILL_MOD, COpcodeAttributes("O_SET_CRITTER_SKILL_MOD", "set_critter_skill_mod", 2)); + SetAt(O_SET_BASE_SKILL_MOD, COpcodeAttributes("O_SET_BASE_SKILL_MOD", "set_base_skill_mod", 1)); + SetAt(O_SET_CRITTER_PICKPOCKET_MOD, COpcodeAttributes("O_SET_CRITTER_PICKPOCKET_MOD", "set_critter_pickpocket_mod", 3)); + SetAt(O_SET_BASE_PICKPOCKET_MOD, COpcodeAttributes("O_SET_BASE_PICKPOCKET_MOD", "set_base_pickpocket_mod", 2)); + + SetAt(O_SET_PYROMANIAC_MOD, COpcodeAttributes("O_SET_PYROMANIAC_MOD", "set_pyromaniac_mod", 1)); + SetAt(O_APPLY_HEAVEHO_FIX, COpcodeAttributes("O_APPLY_HEAVEHO_FIX", "apply_heaveho_fix", 0)); + SetAt(O_SET_SWIFTLEARNER_MOD, COpcodeAttributes("O_SET_SWIFTLEARNER_MOD", "set_swiftlearner_mod", 1)); + SetAt(O_SET_HP_LEVEL_MOD, COpcodeAttributes("O_SET_HP_LEVEL_MOD", "set_hp_per_level_mod", 1)); + + SetAt(O_WRITE_BYTE, COpcodeAttributes("O_WRITE_BYTE", "write_byte", 2)); + SetAt(O_WRITE_SHORT, COpcodeAttributes("O_WRITE_SHORT", "write_short", 2)); + SetAt(O_WRITE_INT, COpcodeAttributes("O_WRITE_INT", "write_int", 2)); + + SetAt(O_CALL_OFFSET_V0, COpcodeAttributes("O_CALL_OFFSET_V0", "call_offset_v0", 1)); + SetAt(O_CALL_OFFSET_V1, COpcodeAttributes("O_CALL_OFFSET_V1", "call_offset_v1", 2)); + SetAt(O_CALL_OFFSET_V2, COpcodeAttributes("O_CALL_OFFSET_V2", "call_offset_v2", 3)); + SetAt(O_CALL_OFFSET_V3, COpcodeAttributes("O_CALL_OFFSET_V3", "call_offset_v3", 4)); + SetAt(O_CALL_OFFSET_V4, COpcodeAttributes("O_CALL_OFFSET_V4", "call_offset_v4", 5)); + SetAt(O_CALL_OFFSET_R0, COpcodeAttributes("O_CALL_OFFSET_R0", "call_offset_r0", 1, expression)); + SetAt(O_CALL_OFFSET_R1, COpcodeAttributes("O_CALL_OFFSET_R1", "call_offset_r1", 2, expression)); + SetAt(O_CALL_OFFSET_R2, COpcodeAttributes("O_CALL_OFFSET_R2", "call_offset_r2", 3, expression)); + SetAt(O_CALL_OFFSET_R3, COpcodeAttributes("O_CALL_OFFSET_R3", "call_offset_r3", 4, expression)); + SetAt(O_CALL_OFFSET_R4, COpcodeAttributes("O_CALL_OFFSET_R4", "call_offset_r4", 5, expression)); + + SetAt(O_SHOW_IFACE_TAG, COpcodeAttributes("O_SHOW_IFACE_TAG", "show_iface_tag", 1)); + SetAt(O_HIDE_IFACE_TAG, COpcodeAttributes("O_HIDE_IFACE_TAG", "hide_iface_tag", 1)); + SetAt(O_IS_IFACE_TAG_ACTIVE, COpcodeAttributes("O_IS_IFACE_TAG_ACTIVE", "is_iface_tag_active", 1, expression)); + + SetAt(O_GET_BODYPART_HIT_MODIFIER, COpcodeAttributes("O_GET_BODYPART_HIT_MODIFIER", "get_bodypart_hit_modifier", 1, expression)); + SetAt(O_SET_BODYPART_HIT_MODIFIER, COpcodeAttributes("O_SET_BODYPART_HIT_MODIFIER", "set_bodypart_hit_modifier", 2)); + + + + //1.41 + SetAt(O_SET_CRITICAL_TABLE, COpcodeAttributes("O_SET_CRITICAL_TABLE", "set_critical_table", 5)); + SetAt(O_GET_CRITICAL_TABLE, COpcodeAttributes("O_GET_CRITICAL_TABLE", "get_critical_table", 4, expression)); + SetAt(O_RESET_CRITICAL_TABLE, COpcodeAttributes("O_RESET_CRITICAL_TABLE", "reset_critical_table", 4)); + SetAt(O_GET_SFALL_ARG, COpcodeAttributes("O_GET_SFALL_ARG", "get_sfall_arg", 0, expression)); + SetAt(O_SET_SFALL_RETURN, COpcodeAttributes("O_SET_SFALL_RETURN", "set_sfall_return", 1)); + SetAt(O_SET_UNSPENT_AP_BONUS, COpcodeAttributes("O_SET_UNSPENT_AP_BONUS", "set_unspent_ap_bonus", 1)); + SetAt(O_GET_UNSPENT_AP_BONUS, COpcodeAttributes("O_GET_UNSPENT_AP_BONUS", "get_unspent_ap_bonus", 0, expression)); + SetAt(O_SET_UNSPENT_AP_PERK_BONUS, COpcodeAttributes("O_SET_UNSPENT_AP_PERK_BONUS", "set_unspent_ap_perk_bonus", 1)); + SetAt(O_GET_UNSPENT_AP_PERK_BONUS, COpcodeAttributes("O_GET_UNSPENT_AP_PERK_BONUS", "get_unspent_ap_perk_bonus", 0, expression)); + SetAt(O_INIT_HOOK, COpcodeAttributes("O_INIT_HOOK", "init_hook", 0, expression)); + SetAt(O_GET_INI_STRING, COpcodeAttributes("O_GET_INI_STRING", "get_ini_string", 1, expression)); + + //1.42 + SetAt(O_SQRT, COpcodeAttributes("O_SQRT", "sqrt", 1, expression)); + SetAt(O_ABS, COpcodeAttributes("O_ABS", "abs", 1, expression)); + SetAt(O_SIN, COpcodeAttributes("O_SIN", "sin", 1, expression)); + SetAt(O_COS, COpcodeAttributes("O_COS", "cos", 1, expression)); + SetAt(O_TAN, COpcodeAttributes("O_TAN", "tan", 1, expression)); + SetAt(O_ARCTAN, COpcodeAttributes("O_ARCTAN", "arctan", 2, expression)); + SetAt(O_SET_PALETTE, COpcodeAttributes("O_SET_PALETTE", "set_palette", 1)); + + //1.46b + SetAt(O_REMOVE_SCRIPT, COpcodeAttributes("O_REMOVE_SCRIPT", "remove_script", 1)); + SetAt(O_SET_SCRIPT, COpcodeAttributes("O_SET_SCRIPT", "set_script", 2)); + SetAt(O_GET_SCRIPT, COpcodeAttributes("O_GET_SCRIPT", "get_script", 1, expression)); + SetAt(O_NB_CREATE_CHAR, COpcodeAttributes("O_NB_CREATE_CHAR", "nb_create_char", 0, expression)); + SetAt(O_FS_CREATE, COpcodeAttributes("O_FS_CREATE", "fs_create", 2, expression)); + SetAt(O_FS_COPY, COpcodeAttributes("O_FS_COPY", "fs_copy", 2, expression)); + SetAt(O_FS_FIND, COpcodeAttributes("O_FS_FIND", "fs_find", 1, expression)); + SetAt(O_FS_WRITE_BYTE, COpcodeAttributes("O_FS_WRITE_BYTE", "fs_write_byte", 2)); + SetAt(O_FS_WRITE_SHORT, COpcodeAttributes("O_FS_WRITE_SHORT", "fs_write_short", 2)); + SetAt(O_FS_WRITE_INT, COpcodeAttributes("O_FS_WRITE_INT", "fs_write_int", 2)); + SetAt(O_FS_WRITE_FLOAT, COpcodeAttributes("O_FS_WRITE_FLOAT", "fs_write_float", 2)); + SetAt(O_FS_WRITE_STRING,COpcodeAttributes("O_FS_WRITE_STRING","fs_write_string",2)); + SetAt(O_FS_DELETE, COpcodeAttributes("O_FS_DELETE", "fs_delete", 1)); + SetAt(O_FS_SIZE, COpcodeAttributes("O_FS_SIZE", "fs_size", 1, expression)); + SetAt(O_FS_POS, COpcodeAttributes("O_FS_POS", "fs_pos", 1, expression)); + SetAt(O_FS_SEEK, COpcodeAttributes("O_FS_SEEK", "fs_seek", 2)); + SetAt(O_FS_RESIZE, COpcodeAttributes("O_FS_RESIZE", "fs_resize", 2)); + SetAt(O_GET_PROTO_DATA, COpcodeAttributes("O_GET_PROTO_DATA", "get_proto_data", 2, expression)); + + //1.47b + SetAt(O_SET_PROTO_DATA, COpcodeAttributes("O_SET_PROTO_DATA", "set_proto_data", 3)); + SetAt(O_SET_SELF, COpcodeAttributes("O_SET_SELF", "set_self", 1)); + SetAt(O_REGISTER_HOOK, COpcodeAttributes("O_REGISTER_HOOK", "register_hook", 1)); + + SetAt(O_FS_WRITE_BSTRING, COpcodeAttributes("O_FS_WRITE_BSTRING", "fs_write_bstring", 2)); + SetAt(O_FS_READ_BYTE, COpcodeAttributes("O_FS_READ_BYTE", "fs_read_byte", 1, expression)); + SetAt(O_FS_READ_SHORT, COpcodeAttributes("O_FS_READ_SHORT", "fs_read_short", 1, expression)); + SetAt(O_FS_READ_INT, COpcodeAttributes("O_FS_READ_INT", "fs_read_int", 1, expression)); + SetAt(O_FS_READ_FLOAT, COpcodeAttributes("O_FS_READ_FLOAT", "fs_read_float", 1, expression)); + + + SetAt(O_LIST_BEGIN, COpcodeAttributes("O_LIST_BEGIN", "list_begin", 1, expression)); + SetAt(O_LIST_NEXT, COpcodeAttributes("O_LIST_NEXT", "list_next", 1, expression)); + SetAt(O_LIST_END, COpcodeAttributes("O_LIST_END", "list_end", 1)); + + //1.49d + SetAt(O_SFALL_VER_MAJOR, COpcodeAttributes("O_SFALL_VER_MAJOR", "sfall_ver_major", 0, expression)); + SetAt(O_SFALL_VER_MINOR, COpcodeAttributes("O_SFALL_VER_MINOR", "sfall_ver_minor", 0, expression)); + SetAt(O_SFALL_VER_BUILD, COpcodeAttributes("O_SFALL_VER_BUILD", "sfall_ver_build", 0, expression)); + + SetAt(O_HERO_SELECT_WIN, COpcodeAttributes("O_HERO_SELECT_WIN", "hero_select_win", 1)); + SetAt(O_SET_HERO_RACE, COpcodeAttributes("O_SET_HERO_RACE", "set_hero_race", 1)); + SetAt(O_SET_HERO_STYLE, COpcodeAttributes("O_SET_HERO_STYLE", "set_hero_style", 1)); + + SetAt(O_SET_CRITTER_BURST_DISABLE, COpcodeAttributes("O_SET_CRITTER_BURST_DISABLE", "set_critter_burst_disable", 2)); + + + + SetAt(O_GET_WEAPON_AMMO_PID, COpcodeAttributes("O_GET_WEAPON_AMMO_PID", "get_weapon_ammo_pid", 1, expression)); + SetAt(O_SET_WEAPON_AMMO_PID, COpcodeAttributes("O_SET_WEAPON_AMMO_PID", "set_weapon_ammo_pid", 2)); + SetAt(O_GET_WEAPON_AMMO_COUNT, COpcodeAttributes("O_GET_WEAPON_AMMO_COUNT", "get_weapon_ammo_count", 1, expression)); + SetAt(O_SET_WEAPON_AMMO_COUNT, COpcodeAttributes("O_SET_WEAPON_AMMO_COUNT", "set_weapon_ammo_count", 2)); + SetAt(O_WRITE_STRING, COpcodeAttributes("O_WRITE_STRING", "write_String", 2)); + SetAt(O_GET_MOUSE_X, COpcodeAttributes("O_GET_MOUSE_X", "get_mouse_x", 0, expression)); + SetAt(O_GET_MOUSE_Y, COpcodeAttributes("O_GET_MOUSE_Y", "get_mouse_y", 0, expression)); + SetAt(O_GET_MOUSE_BUTTONS, COpcodeAttributes("O_GET_MOUSE_BUTTONS", "get_mouse_buttons", 0, expression)); + SetAt(O_GET_WINDOW_UNDER_MOUSE, COpcodeAttributes("O_GET_WINDOW_UNDER_MOUSE", "get_window_under_mouse", 0, expression)); + SetAt(O_GET_SCREEN_WIDTH, COpcodeAttributes("O_GET_SCREEN_WIDTH", "get_screen_width", 0, expression)); + SetAt(O_GET_SCREEN_HEIGHT, COpcodeAttributes("O_GET_SCREEN_HEIGHT", "get_screen_height", 0, expression)); + SetAt(O_STOP_GAME, COpcodeAttributes("O_STOP_GAME", "stop_game", 0)); + SetAt(O_RESUME_GAME, COpcodeAttributes("O_RESUME_GAME", "resume_game", 0)); + SetAt(O_CREATE_MESSAGE_WINDOW, COpcodeAttributes("O_CREATE_MESSAGE_WINDOW", "create_message_window", 1)); + SetAt(O_REMOVE_TRAIT, COpcodeAttributes("O_REMOVE_TRAIT", "remove_trait", 1)); + SetAt(O_GET_LIGHT_LEVEL, COpcodeAttributes("O_GET_LIGHT_LEVEL", "get_light_level", 0, expression)); + SetAt(O_REFRESH_PC_ART, COpcodeAttributes("O_REFRESH_PC_ART", "refresh_pc_art", 0)); + SetAt(O_GET_ATTACK_TYPE, COpcodeAttributes("O_GET_ATTACK_TYPE", "get_attack_type", 0, expression)); + SetAt(O_FORCE_ENCOUNTER_WITH_FLAGS, COpcodeAttributes("O_FORCE_ENCOUNTER_WITH_FLAGS", "force_encounter_with_flags", 2)); + SetAt(O_SET_MAP_TIME_MULTI, COpcodeAttributes("O_SET_MAP_TIME_MULTI", "set_map_time_multi", 1)); + SetAt(O_PLAY_SFALL_SOUND, COpcodeAttributes("O_PLAY_SFALL_SOUND", "play_sfall_sound", 2, expression)); + SetAt(O_STOP_SFALL_SOUND, COpcodeAttributes("O_STOP_SFALL_SOUND", "stop_sfall_sound", 1)); + SetAt(O_CREATE_ARRAY, COpcodeAttributes("O_CREATE_ARRAY", "create_array", 2, expression)); + SetAt(O_SET_ARRAY, COpcodeAttributes("O_SET_ARRAY", "set_array", 3)); + SetAt(O_GET_ARRAY, COpcodeAttributes("O_GET_ARRAY", "get_array", 2, expression)); + SetAt(O_FREE_ARRAY, COpcodeAttributes("O_FREE_ARRAY", "free_array", 1)); + + //sfall vrs 2.8 + SetAt(O_TS_LEN_ARRAY, COpcodeAttributes("O_TS_LEN_ARRAY", "len_array", 1, expression)); + SetAt(O_TS_RESIZE_ARRAY, COpcodeAttributes("O_TS_RESIZE_ARRAY", "resize_array", 2)); + SetAt(O_TS_TEMP_ARRAY, COpcodeAttributes("O_TS_TEMP_ARRAY", "temp_array", 2, expression)); + SetAt(O_TS_FIX_ARRAY, COpcodeAttributes("O_TS_FIX_ARRAY", "fix_array", 1)); + SetAt(O_TS_STRING_SPLIT, COpcodeAttributes("O_TS_STRING_SPLIT", "string_split", 2, expression)); + SetAt(O_TS_LIST_AS_ARRAY, COpcodeAttributes("O_TS_LIST_AS_ARRAY", "list_as_array", 1, expression)); + + // sfall 2.8b + SetAt(O_TS_ATOI, COpcodeAttributes("O_TS_ATOI", "atoi", 1, expression)); + SetAt(O_TS_ATOF, COpcodeAttributes("O_TS_ATOF", "atof", 1, expression)); + + // sfall 2.9a + SetAt(O_TS_SCAN_ARRAY, COpcodeAttributes("O_TS_SCAN_ARRAY", "scan_array", 2, expression)); + SetAt(O_TS_TILE_PID, COpcodeAttributes("O_TS_TILE_PID", "get_tile_fid", 1, expression)); + SetAt(O_TS_MODIFIED_INI, COpcodeAttributes("O_TS_MODIFIED_INI", "modified_ini", 0, expression)); + SetAt(O_TS_GET_SFALL_ARGS, COpcodeAttributes("O_TS_GET_SFALL_ARGS", "get_sfall_args", 0, expression)); + + // sfall 2.12 + SetAt(O_TS_SET_SFALL_ARG, COpcodeAttributes("O_TS_GET_SFALL_ARG", "set_sfall_arg", 2)); + + // sfall 2.16 + SetAt(O_TS_FORCE_AIMED_SHOTS, COpcodeAttributes("O_TS_FORCE_AIMED_SHOTS", "force_aimed_shots", 1)); + SetAt(O_TS_DISABLE_AIMED_SHOTS, COpcodeAttributes("O_TS_DISABLE_AIMED_SHOTS", "disable_aimed_shots", 1)); + SetAt(O_TS_MARK_MOVIE_PLAYED, COpcodeAttributes("O_TS_MARK_MOVIE_PLAYED", "mark_movie_played", 1)); + + // sfall 2.17 + SetAt(O_TS_GET_NPC_LEVEL, COpcodeAttributes("O_TS_GET_NPC_LEVEL", "get_npc_level", 1, expression)); + + // sfall 3.0 + SetAt(O_TS_SET_CRITTER_SKILL_POINTS, COpcodeAttributes("O_TS_SET_CRITTER_SKILL_POINTS", "set_critter_skill_points", 3)); + SetAt(O_TS_GET_CRITTER_SKILL_POINTS, COpcodeAttributes("O_TS_GET_CRITTER_SKILL_POINTS", "get_critter_skill_points", 2, expression)); + SetAt(O_TS_SET_AVAILABLE_SKILL_POINTS, COpcodeAttributes("O_TS_SET_AVAILABLE_SKILL_POINTS", "set_available_skill_points", 1)); + SetAt(O_TS_GET_AVAILABLE_SKILL_POINTS, COpcodeAttributes("O_TS_GET_AVAILABLE_SKILL_POINTS", "get_available_skill_points", 0, expression)); + SetAt(O_TS_MOD_SKILL_POINTS_PER_LEVEL, COpcodeAttributes("O_TS_MOD_SKILL_POINTS_PER_LEVEL", "mod_skill_points_per_level", 1)); + SetAt(O_TS_SET_PERK_FREQ, COpcodeAttributes("O_TS_SET_PERK_FREQ", "set_perk_freq", 1)); + SetAt(O_TS_GET_LAST_TARGET, COpcodeAttributes("O_TS_GET_LAST_TARGET", "get_last_attacker", 1, expression)); + SetAt(O_TS_GET_LAST_ATTACKER, COpcodeAttributes("O_TS_GET_LAST_ATTACKER", "get_last_target", 1, expression)); + SetAt(O_TS_BLOCK_COMBAT, COpcodeAttributes("O_TS_BLOCK_COMBAT", "block_combat", 1)); + + // sfall 3.3 + SetAt(O_TS_TILE_UNDER_CURSOR, COpcodeAttributes("O_TS_TILE_UNDER_CURSOR", "tile_under_cursor", 0, expression)); + SetAt(O_TS_GET_BARTER_MOD, COpcodeAttributes("O_TS_GET_BARTER_MOD", "gdialog_get_barter_mod", 0, expression)); + SetAt(O_TS_SET_INVEN_AP_COST, COpcodeAttributes("O_TS_SET_INVEN_AP_COST", "set_inven_ap_cost", 1)); + + // sfall 3.4 + SetAt(O_TS_SUBSTR, COpcodeAttributes("O_TS_SUBSTR", "substr", 3, expression)); + SetAt(O_TS_STRLEN, COpcodeAttributes("O_TS_STRLEN", "strlen", 1, expression)); + SetAt(O_TS_SPRINTF, COpcodeAttributes("O_TS_SPRINTF", "sprintf", 2, expression)); + SetAt(O_TS_ORD, COpcodeAttributes("O_TS_ORD", "charcode", 1, expression)); // sfall 3.5 + //SetAt(O_TS_RESERVD2, COpcodeAttributes("O_TS_RESERVD2", "substr", 3, expression)); + SetAt(O_TS_TYPEOF, COpcodeAttributes("O_TS_TYPEOF", "typeof", 1, expression)); + SetAt(O_TS_LOG, COpcodeAttributes("O_TS_LOG", "log", 1, expression)); // sfall 3.5 + SetAt(O_TS_EXP, COpcodeAttributes("O_TS_EXP", "exponent", 1, expression)); // sfall 3.5 + //SetAt(O_TS_CEIL, COpcodeAttributes("O_TS_CEIL", "ceil", 1, expression)); + SetAt(O_TS_ROUND, COpcodeAttributes("O_TS_ROUND", "round", 1, expression)); // sfall 3.5 + SetAt(O_TS_SAVE_ARRAY, COpcodeAttributes("O_TS_SAVE_ARRAY", "save_array", 2)); + SetAt(O_TS_LOAD_ARRAY, COpcodeAttributes("O_TS_LOAD_ARRAY", "load_array", 1, expression)); + SetAt(O_TS_GET_ARRAY_KEY, COpcodeAttributes("O_TS_GET_ARRAY_KEY", "array_key", 2, expression)); + SetAt(O_TS_STACK_ARRAY, COpcodeAttributes("O_TS_STACK_ARRAY", "arrayexpr", 2, expression)); + + SetAt(O_TS_REG_ANIM_DESTROY, COpcodeAttributes("O_TS_REG_ANIM_DESTROY", "reg_anim_destroy", 1)); + SetAt(O_TS_REG_ANIM_ANIMATE_AND_HIDE, COpcodeAttributes("O_TS_REG_ANIM_ANIMATE_AND_HIDE", "reg_anim_animate_and_hide", 3)); + SetAt(O_TS_REG_ANIM_COMBAT_CHECK, COpcodeAttributes("O_TS_REG_ANIM_COMBAT_CHECK", "reg_anim_combat_check", 1)); + SetAt(O_TS_REG_ANIM_LIGHT, COpcodeAttributes("O_TS_REG_ANIM_LIGHT", "reg_anim_light", 3)); + SetAt(O_TS_REG_ANIM_CHANGE_FID, COpcodeAttributes("O_TS_REG_ANIM_CHANGE_FID", "reg_anim_change_fid", 3)); + SetAt(O_TS_REG_ANIM_TAKE_OUT, COpcodeAttributes("O_TS_REG_ANIM_TAKE_OUT", "reg_anim_take_out", 3)); + SetAt(O_TS_REG_ANIM_TURN_TOWARDS, COpcodeAttributes("O_TS_REG_ANIM_TURN_TOWARDS", "reg_anim_turn_towards", 3)); + + SetAt(O_TS_EXPLOSIONS_METARULE, COpcodeAttributes("O_TS_EXPLOSIONS_METARULE", "metarule2_explosions", 3, expression)); + + // sfall 3.5 + SetAt(O_TS_REGISTER_HOOK_PROC, COpcodeAttributes("O_TS_REGISTER_HOOK_PROC", "register_hook_proc", 2, COpcodeAttributes::TYPE_STATEMENT, COpcodeAttributes::CATEGORY_PREFIX, procArgs_register_hook_proc, 1)); + SetAt(O_TS_POW, COpcodeAttributes("O_POW", "^", 2, expression, infix)); + SetAt(O_TS_MESSAGE_STR_GAME, COpcodeAttributes("O_TS_MESSAGE_STR_GAME", "message_str_game", 2, expression)); + SetAt(O_TS_SNEAK_SUCCESS, COpcodeAttributes("O_TS_SNEAK_SUCCESS", "sneak_success", 0, expression)); + SetAt(O_TS_TILE_LIGHT, COpcodeAttributes("O_TS_SNEAK_SUCCESS", "tile_light", 2, expression)); + SetAt(O_TS_MAKE_STRAIGHT_PATH, COpcodeAttributes("O_TS_MAKE_STRAIGHT_PATH", "obj_blocking_line", 3, expression)); + SetAt(O_TS_OBJ_BLOCKING_AT, COpcodeAttributes("O_TS_OBJ_BLOCKING_AT", "obj_blocking_tile", 3, expression)); + SetAt(O_TS_TILE_GET_OBJECTS, COpcodeAttributes("O_TS_TILE_GET_OBJECTS", "tile_get_objs", 2, expression)); + SetAt(O_TS_GET_PARTY_MEMBERS, COpcodeAttributes("O_TS_GET_PARTY_MEMBERS", "party_member_list", 1, expression)); + SetAt(O_TS_PATH_FIND, COpcodeAttributes("O_TS_PATH_FIND", "path_find_to", 3, expression)); + SetAt(O_TS_CREATE_SPATIAL, COpcodeAttributes("O_TS_CREATE_SPATIAL", "create_spatial", 4, expression)); + SetAt(O_TS_ART_EXISTS, COpcodeAttributes("O_TS_ART_EXISTS", "art_exists", 1, expression)); + SetAt(O_TS_OBJ_IS_CARRYING_OBJ, COpcodeAttributes("O_TS_OBJ_IS_CARRYING_OBJ", "obj_is_carrying_obj", 2, expression)); + //sfall end + + SetAt(O_STRINGOP, COpcodeAttributes("O_STRINGOP", "", 0, expression)); + SetAt(O_FLOATOP, COpcodeAttributes("O_FLOATOP", "", 0, expression)); + SetAt(O_INTOP, COpcodeAttributes("O_INTOP", "", 0, expression)); +} diff --git a/ProcTable.cpp b/ProcTable.cpp new file mode 100644 index 0000000..3d36af3 --- /dev/null +++ b/ProcTable.cpp @@ -0,0 +1,305 @@ +// ProcTable.cpp : implementation file +// + +#include "stdafx.h" +#include "ProcTable.h" +#include "Utility.h" +#include "ObjectAttributes.h" + +#include "Hacks/CString.h" +#include + +// CProcDescriptor + +CProcDescriptor::CProcDescriptor() : + m_ulNameOffset(0), + m_ulType(0), + m_ulTime(0), + m_ulExpressionOffset(0), + m_ulBodyOffset(0), + m_ulNumArgs(0) +{ +} + +CProcDescriptor::CProcDescriptor(const CProcDescriptor& Item) : + m_ulNameOffset(Item.m_ulNameOffset), + m_ulType(Item.m_ulType), + m_ulTime(Item.m_ulTime), + m_ulExpressionOffset(Item.m_ulExpressionOffset), + m_ulBodyOffset(Item.m_ulBodyOffset), + m_ulNumArgs(Item.m_ulNumArgs) +{ +} + + +CProcDescriptor::~CProcDescriptor() +{ +} + +CProcDescriptor& CProcDescriptor::operator = (const CProcDescriptor& Item) +{ + if (&Item != this) { + m_ulNameOffset = Item.m_ulNameOffset; + m_ulType = Item.m_ulType; + m_ulTime = Item.m_ulTime; + m_ulExpressionOffset = Item.m_ulExpressionOffset; + m_ulBodyOffset = Item.m_ulBodyOffset; + m_ulNumArgs = Item.m_ulNumArgs; + } + + return (*this); +} + +void CProcDescriptor::Serialize(CArchive& ar) +{ + //if (ar.IsStoring()) { + if (false) + { + // ASSERT(FALSE); + } + else { + UINT uiTotalRead; + + uiTotalRead = ReadMSBULong(ar, m_ulNameOffset); + uiTotalRead += ReadMSBULong(ar, m_ulType); + uiTotalRead += ReadMSBULong(ar, m_ulTime); + uiTotalRead += ReadMSBULong(ar, m_ulExpressionOffset); + uiTotalRead += ReadMSBULong(ar, m_ulBodyOffset); + uiTotalRead += ReadMSBULong(ar, m_ulNumArgs); + +// printf("=================\n"); +// printf("uiTotalRead = %u\n", uiTotalRead); +// printf("m_ulNameOffset = 0x%08X\n", m_ulNameOffset); +// printf("m_ulType = 0x%08X\n", m_ulType); +// printf("m_ulTime = 0x%08X\n", m_ulTime); +// printf("m_ulExpressionOffset = 0x%08X\n", m_ulExpressionOffset); +// printf("m_ulBodyOffset = 0x%08X\n", m_ulBodyOffset); +// printf("m_ulNumArgs = 0x%08X\n", m_ulNumArgs); + + + if (uiTotalRead != (sizeof(ULONG) * 6)) { + printf("Error: Unable read procedure descriptor\n"); + AfxThrowUserException(); + } + } +} + +void CProcDescriptor::Dump(CArchive& ar) +{ + CString strOutLine; + CString strType; + + if (m_ulType != 0x00000000) { + strType = "( "; + + if (m_ulType & P_TIMED) { + strType += "timed "; + } + + if (m_ulType & P_CONDITIONAL) { + strType += "conditional "; + } + + if (m_ulType & P_IMPORT) { + strType += "import "; + } + + if (m_ulType & P_EXPORT) { + strType += "export "; + } + + if (m_ulType & P_CRITICAL) { + strType += "critical "; + } + + strType += ")"; + } + else { + strType = "No special types"; + } + + strOutLine.Format("Name offset: 0x%08X\n", m_ulNameOffset); + ar.WriteString(strOutLine); + strOutLine.Format("Type: 0x%08X // %s\n", m_ulType, strType.c_str()); + ar.WriteString(strOutLine); + strOutLine.Format("Time: 0x%08X // %d\n", m_ulTime, m_ulTime); + ar.WriteString(strOutLine); + strOutLine.Format("Expression offset: 0x%08X\n", m_ulExpressionOffset); + ar.WriteString(strOutLine); + strOutLine.Format("Body offset: 0x%08X\n", m_ulBodyOffset); + ar.WriteString(strOutLine); + strOutLine.Format("Number of args: 0x%08X // %d\n", m_ulNumArgs, m_ulNumArgs); + ar.WriteString(strOutLine); +} + + +// CProcTable + +CProcTable::CProcTable() +{ +} + +CProcTable::~CProcTable() +{ +} + +struct ProcBodyOffset { + ULONG m_ulProcIndex; + ULONG m_ulBodyOffset; +}; + +int compareProcBodyOffsets(const void* elem0, const void* elem1) +{ + ProcBodyOffset offset0 = *((ProcBodyOffset*)elem0); + ProcBodyOffset offset1 = *((ProcBodyOffset*)elem1); + + if (offset0.m_ulBodyOffset < offset1.m_ulBodyOffset) { + return -1; + } + else if (offset0.m_ulBodyOffset > offset1.m_ulBodyOffset) { + return 1; + } + else { + if (offset0.m_ulProcIndex < offset1.m_ulProcIndex) { + return -1; + } + else if (offset0.m_ulProcIndex > offset1.m_ulProcIndex) { + return 1; + } + else { + return 0; + } + } +} + +void CProcTable::Serialize(CArchive& ar) +{ + //if (ar.IsStoring()) { + if(false) + { + // ASSERT(FALSE); + } + else { + m_Table.RemoveAll(); + m_ProcSize.RemoveAll(); + + ULONG ulSizeOfTable; + ULONG ulRead; + + ar.Flush(); + ULONG ulSizeOfFile = ULONG(ar.GetFile()->GetLength()); + + ulRead = ReadMSBULong(ar, ulSizeOfTable); + + if (ulRead != sizeof(ulSizeOfTable)) { + printf("Error: Unable read size of procedures table\n"); + AfxThrowUserException(); + } + + m_Table.SetSize(ulSizeOfTable); + m_ProcSize.SetSize(ulSizeOfTable); + + ULONG ulIndexOfProcOffset = 0; + ProcBodyOffset* pOffsets = new ProcBodyOffset[ulSizeOfTable + 1]; + + if (pOffsets == NULL) { +// AfxThrowMemoryException(); + throw 1; + } + + for(ULONG i = 0; i < ulSizeOfTable; i++) { +// printf("======== %u =========\n", i); + m_Table.at(i).Serialize(ar); + m_ProcSize.at(i) = 0; // Initialize size of procedure + + if (!(m_Table.at(i).m_ulType & P_IMPORT)) { + if ((m_Table.at(i).m_ulBodyOffset != 0) && (m_Table.at(i).m_ulBodyOffset != ulSizeOfFile)) { + pOffsets[ulIndexOfProcOffset].m_ulProcIndex = i; + pOffsets[ulIndexOfProcOffset].m_ulBodyOffset = m_Table.at(i).m_ulBodyOffset; + ulIndexOfProcOffset++; + } + else { + m_Table.at(i).m_ulType |= P_NOTIMPLEMENTED; + } + } + } + + pOffsets[ulIndexOfProcOffset].m_ulProcIndex = ulIndexOfProcOffset + 1; + pOffsets[ulIndexOfProcOffset].m_ulBodyOffset = ulSizeOfFile; + + qsort(pOffsets, ulIndexOfProcOffset, sizeof(ProcBodyOffset), compareProcBodyOffsets); + + // Sizes of procedures + for(ULONG i = 0; i < ulIndexOfProcOffset; i++) { + if (pOffsets[i + 1].m_ulBodyOffset >= pOffsets[i].m_ulBodyOffset) { + m_ProcSize.at(pOffsets[i].m_ulProcIndex) = pOffsets[i + 1].m_ulBodyOffset - pOffsets[i].m_ulBodyOffset; + } + else { + printf("Error: Procedures are not sorted in ascending address order\n"); + AfxThrowUserException(); + } + } + + delete [] pOffsets; + + for(ULONG i = 0; i < ulSizeOfTable; i++) { + if (m_Table.at(i).m_ulBodyOffset != 0) { + m_ulOffsetOfProcSection = m_Table.at(i).m_ulBodyOffset; + break; + } + } + +// // For debugging only +// printf("Total: %d\n", m_Table.GetSize()); +// +// for(i = 0; i < ulSizeOfTable; i++) { +// printf("Offset: 0x%08X, size: 0x%08X\n", m_Table.at(i).m_ulBodyOffset, m_ProcSize.at(i)); +// } + +// printf("m_ulOffsetOfProcSection: 0x%08X\n", m_ulOffsetOfProcSection); + } +} + +INT_PTR CProcTable::GetSize() +{ + return m_Table.GetSize(); +} + +ULONG CProcTable::GetSizeOfProc(INT_PTR nIndex) +{ + if ((nIndex < 0) || (nIndex > m_ProcSize.GetUpperBound())) { + printf("Warning: Invalid index of procedure (%d). Exception will be thrown\n", nIndex); + AfxThrowUserException(); + } + + return m_ProcSize.at(nIndex); +} + +ULONG CProcTable::GetOffsetOfProcSection() +{ + return m_ulOffsetOfProcSection; +} + + +void CProcTable::Dump(CArchive& ar) +{ + CString strOutLine; + + for(INT_PTR i = 0; i < m_Table.GetSize(); i++) { + strOutLine.Format("======== Procedure %d ========\n", i); + ar.WriteString(strOutLine); + m_Table.at(i).Dump(ar); + ar.WriteString("\n"); + } +} + + +CProcDescriptor& CProcTable::operator [] (INT_PTR nIndex) +{ + if ((nIndex < 0) || (nIndex > m_ProcSize.GetUpperBound())) { + printf("Warning: Invalid index of procedure (%d). Exception will be thrown\n", nIndex); + AfxThrowUserException(); + } + + return m_Table.at(nIndex); +} diff --git a/ProcTable.h b/ProcTable.h new file mode 100644 index 0000000..710b42b --- /dev/null +++ b/ProcTable.h @@ -0,0 +1,60 @@ +#pragma once + +#ifndef PROC_TABLE_H +#define PROC_TABLE_H + +#include "Hacks/CArchive.h" + +// CProcDescriptor +class CProcDescriptor : public CObject { +public: + CProcDescriptor(); + CProcDescriptor(const CProcDescriptor& Item); + virtual ~CProcDescriptor(); + +public: + virtual void Serialize(CArchive& ar); + + void Dump(CArchive& ar); + +public: + CProcDescriptor& operator = (const CProcDescriptor& Item); + +public: + ULONG m_ulNameOffset; // Index into namespace for procedure name + ULONG m_ulType; // Type of function (P_TIMED, P_CONDITIONAL, none) + ULONG m_ulTime; // Time this proc should go off, if timed + ULONG m_ulExpressionOffset; // Pointer to conditional code, if conditional + ULONG m_ulBodyOffset; // Pointer to procedure + ULONG m_ulNumArgs; // Number of args to procedure +}; + + +// CProcTable +class CProcTable : public CObject { +public: + CProcTable(); + virtual ~CProcTable(); + +public: + virtual void Serialize(CArchive& ar); + + INT_PTR GetSize(); + ULONG GetSizeOfProc(INT_PTR nIndex); + ULONG GetOffsetOfProcSection(); + + void Dump(CArchive& ar); + +public: + CProcDescriptor& operator [] (INT_PTR nIndex); + +private: + // CProcTableArray + typedef CArray CProcTableArray; + + CProcTableArray m_Table; + CDWordArray m_ProcSize; + ULONG m_ulOffsetOfProcSection; +}; + +#endif diff --git a/StartupCode.cpp b/StartupCode.cpp new file mode 100644 index 0000000..21309b0 --- /dev/null +++ b/StartupCode.cpp @@ -0,0 +1,54 @@ +// StartupCode.cpp : implementation file +// + +#include "stdafx.h" +#include "StartupCode.h" + +// CStartupCode + +CStartupCode::CStartupCode() +{ +} + +CStartupCode::~CStartupCode() +{ +} + +void CStartupCode::Serialize(CArchive& ar) +{ + //if (ar.IsStoring()) { + if (false) + { + // ASSERT(FALSE); + } + else { + WORD wExpectOpcodes[17] = { + COpcode::O_CRITICAL_START, + COpcode::O_INTOP, + COpcode::O_D_TO_A, + COpcode::O_INTOP, + COpcode::O_JMP, + COpcode::O_EXIT_PROG, + COpcode::O_POP, + COpcode::O_POP_FLAGS_RETURN, + COpcode::O_POP, + COpcode::O_POP_FLAGS_EXIT, + COpcode::O_POP, + COpcode::O_POP_FLAGS_RETURN_EXTERN, + COpcode::O_POP, + COpcode::O_POP_FLAGS_EXIT_EXTERN, + COpcode::O_POP_FLAGS_RETURN_VAL_EXTERN, + COpcode::O_POP_FLAGS_RETURN_VAL_EXIT, + COpcode::O_POP_FLAGS_RETURN_VAL_EXIT_EXTERN + }; + + for(INT_PTR i = 0; i < 17; i++) { + if (i == 1) { + m_Code[i].Expect(ar, wExpectOpcodes[i], TRUE, 18); + } + else { + m_Code[i].Expect(ar, wExpectOpcodes[i]); + } + } + } +} diff --git a/StartupCode.h b/StartupCode.h new file mode 100644 index 0000000..02d2e3f --- /dev/null +++ b/StartupCode.h @@ -0,0 +1,27 @@ +#pragma once + +#ifndef STARTUP_CODE_H +#define STARTUP_CODE_H + + +#include "Opcode.h" + +// CStartupCode +class CStartupCode : public CObject { +public: + enum Defaults { + c_nDefaultSize = 42 + }; + +public: + CStartupCode(); + virtual ~CStartupCode(); + +public: + virtual void Serialize(CArchive& ar); + +private: + COpcode m_Code[17]; +}; + +#endif diff --git a/Utility.cpp b/Utility.cpp new file mode 100644 index 0000000..2d5a84e --- /dev/null +++ b/Utility.cpp @@ -0,0 +1,16 @@ +#include "stdafx.h" +#include "Utility.h" + + +UINT ReadMSBWord(CArchive& ar, WORD& wValue) +{ + BYTE* pBuffer = reinterpret_cast(&wValue); + return (ar.Read(pBuffer + 1, 1) + ar.Read(pBuffer, 1)); +} + +UINT ReadMSBULong(CArchive& ar, ULONG& ulValue) +{ + BYTE* pBuffer = reinterpret_cast(&ulValue); + return (ar.Read(pBuffer + 3, 1) + ar.Read(pBuffer + 2, 1) + + ar.Read(pBuffer + 1, 1) + ar.Read(pBuffer, 1)); +} diff --git a/Utility.h b/Utility.h new file mode 100644 index 0000000..1f20e5a --- /dev/null +++ b/Utility.h @@ -0,0 +1,12 @@ +#pragma once + +#ifndef UTILITY_H +#define UTILITY_H + +#include "Hacks/CArchive.h" + +// Utility functions +UINT ReadMSBWord(CArchive& ar, WORD& wValue); +UINT ReadMSBULong(CArchive& ar, ULONG& ulValue); + +#endif diff --git a/XGetopt.cpp b/XGetopt.cpp new file mode 100644 index 0000000..33bc82d --- /dev/null +++ b/XGetopt.cpp @@ -0,0 +1,221 @@ +// XGetopt.cpp Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// Description: +// XGetopt.cpp implements getopt(), a function to parse command lines. +// +// History +// Version 1.2 - 2003 May 17 +// - Added Unicode support +// +// Version 1.1 - 2002 March 10 +// - Added example to XGetopt.cpp module header +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// if you are using precompiled headers then include this line: +#include "stdafx.h" +/////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +// if you are not using precompiled headers then include these lines: +//#include +//#include +//#include +/////////////////////////////////////////////////////////////////////////////// + + +#include "XGetopt.h" + + +/////////////////////////////////////////////////////////////////////////////// +// +// X G e t o p t . c p p +// +// +// NAME +// getopt -- parse command line options +// +// SYNOPSIS +// int getopt(int argc, TCHAR *argv[], TCHAR *optstring) +// +// extern TCHAR *optarg; +// extern int optind; +// +// DESCRIPTION +// The getopt() function parses the command line arguments. Its +// arguments argc and argv are the argument count and array as +// passed into the application on program invocation. In the case +// of Visual C++ programs, argc and argv are available via the +// variables __argc and __argv (double underscores), respectively. +// getopt returns the next option letter in argv that matches a +// letter in optstring. (Note: Unicode programs should use +// __targv instead of __argv. Also, all character and string +// literals should be enclosed in _T( ) ). +// +// optstring is a string of recognized option letters; if a letter +// is followed by a colon, the option is expected to have an argument +// that may or may not be separated from it by white space. optarg +// is set to point to the start of the option argument on return from +// getopt. +// +// Option letters may be combined, e.g., "-ab" is equivalent to +// "-a -b". Option letters are case sensitive. +// +// getopt places in the external variable optind the argv index +// of the next argument to be processed. optind is initialized +// to 0 before the first call to getopt. +// +// When all options have been processed (i.e., up to the first +// non-option argument), getopt returns EOF, optarg will point +// to the argument, and optind will be set to the argv index of +// the argument. If there are no non-option arguments, optarg +// will be set to NULL. +// +// The special option "--" may be used to delimit the end of the +// options; EOF will be returned, and "--" (and everything after it) +// will be skipped. +// +// RETURN VALUE +// For option letters contained in the string optstring, getopt +// will return the option letter. getopt returns a question mark (?) +// when it encounters an option letter not included in optstring. +// EOF is returned when processing is finished. +// +// BUGS +// 1) Long options are not supported. +// 2) The GNU double-colon extension is not supported. +// 3) The environment variable POSIXLY_CORRECT is not supported. +// 4) The + syntax is not supported. +// 5) The automatic permutation of arguments is not supported. +// 6) This implementation of getopt() returns EOF if an error is +// encountered, instead of -1 as the latest standard requires. +// +// EXAMPLE +// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[]) +// { +// int c; +// +// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) +// { +// switch (c) +// { +// case _T('a'): +// TRACE(_T("option a\n")); +// // +// // set some flag here +// // +// break; +// +// case _T('B'): +// TRACE( _T("option B\n")); +// // +// // set some other flag here +// // +// break; +// +// case _T('n'): +// TRACE(_T("option n: value=%d\n"), atoi(optarg)); +// // +// // do something with value here +// // +// break; +// +// case _T('?'): +// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); +// return FALSE; +// break; +// +// default: +// TRACE(_T("WARNING: no handler for option %c\n"), c); +// return FALSE; +// break; +// } +// } +// // +// // check for non-option args here +// // +// return TRUE; +// } +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +TCHAR *optarg; // global argument pointer +int optind = 0; // global argv index + +int getopt(int argc, TCHAR *argv[], TCHAR *optstring) +{ + static TCHAR *next = NULL; + if (optind == 0) + next = NULL; + + optarg = NULL; + + if (next == NULL || *next == '\0') + { + if (optind == 0) + optind++; + + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') + { + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + if (strcmp(argv[optind], "--") == 0) + { + optind++; + optarg = NULL; + if (optind < argc) + optarg = argv[optind]; + return EOF; + } + + next = argv[optind]; + next++; // skip past - + optind++; + } + + TCHAR c = *next++; + TCHAR *cp = strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + if (*cp == ':') + { + if (*next != '\0') + { + optarg = next; + next = NULL; + } + else if (optind < argc) + { + optarg = argv[optind]; + optind++; + } + else + { + return '?'; + } + } + + return c; +} diff --git a/XGetopt.h b/XGetopt.h new file mode 100644 index 0000000..970ae8d --- /dev/null +++ b/XGetopt.h @@ -0,0 +1,23 @@ +// XGetopt.h Version 1.2 +// +// Author: Hans Dietrich +// hdietrich2@hotmail.com +// +// This software is released into the public domain. +// You are free to use it in any way you like. +// +// This software is provided "as is" with no expressed +// or implied warranty. I accept no liability for any +// damage or loss of business that this software may cause. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef XGETOPT_H +#define XGETOPT_H + +extern int optind, opterr; +extern TCHAR *optarg; + +int getopt(int argc, TCHAR *argv[], TCHAR *optstring); + +#endif //XGETOPT_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0adac22 --- /dev/null +++ b/main.cpp @@ -0,0 +1,242 @@ +// int2ssl.cpp : Defines the entry point for the console application. +// +#include "stdafx.h" +#include "FalloutScript.h" +#include "XGetopt.h" +#include + +using namespace std; + +// The one and only application object + +// Globals + + +BOOL g_bDump = FALSE; +int g_nFalloutVersion = 2; +CString g_strIndentFill("\t"); +BOOL g_bIgnoreWrongNumOfArgs = FALSE; +BOOL g_bInsOmittedArgsBackward = FALSE; +BOOL g_bStopOnError = FALSE; + +CString g_strInputFileName; +CString g_strOutputFileName; + + +// Functions +void PrintUsage(char* lpszFileName); +BOOL ProcessCommandLine(int argc, char* argv[]); + +int main(int argc, char* argv[]) +{ + int nRetCode = 0; + + + printf("Fallout script decompiler, version 8.3.0 (sfall edition)\n"); + printf("Copyright (C) Anchorite (TeamX), 2005-2009\n"); + printf("anchorite2001@yandex.ru\n"); + printf("Continued by Nirran, phobos2077 (2014-2015)\n"); + printf("Usage: int2ssl.exe [options] [-s value] file.int [file.ssl]\n"); + printf("Example: int2ssl.exe -d-1-a-b-e-s3 random.int\n"); + printf(" -d: dump file\n"); + printf(" -1: input file is Fallout 1 script\n"); + printf(" -a: ignore wrong number of arguments\n"); + printf(" -b: insert omitted arguments backward\n"); + printf(" -s: use Space instead of tab to indent\n"); + printf(" -e: stop decompiling on error\n"); + printf(" --: end of options\n"); + printf("\n"); + + //if (argc < 2) { + // PrintUsage(argv[0]); + // cin.get(); + // return 1; + //} + + //if (!ProcessCommandLine(argc, argv)) { + // return 1; + //} + + CFile fileInput; + CStdioFile fileOutput; + + //if (fileInput.Open(g_strInputFileName, CFile::modeRead | CFile::shareDenyWrite)) { + if (fileInput.Open(CString("BECA.int"), CFile::modeRead | CFile::shareDenyWrite)) { + //if (fileOutput.Open(g_strOutputFileName, CFile::modeCreate | CFile::modeWrite | CFile::typeText | CFile::shareDenyWrite)) { + if (fileOutput.Open(CString("BECA.int.ssl"), CFile::modeCreate | CFile::modeWrite | CFile::typeText | CFile::shareDenyWrite)) { + try { + CArchive arInput(&fileInput, CArchive::load); + CFalloutScript Script; + + printf("Loading file %s...\n", g_strInputFileName.c_str()); + Script.Serialize(arInput); + + printf("File %s loaded successfuly\n", g_strInputFileName.c_str()); + printf("\n"); + + CArchive arOutput(&fileOutput, CArchive::store); + + if (g_bDump) { + printf("Dumping...\n", g_strInputFileName.c_str()); + Script.Dump(arOutput); + + printf("File %s dumped successfuly\n", g_strInputFileName.c_str()); + } + else { + printf("Decompiling...\n"); + + printf(" Init definitions\n"); + Script.InitDefinitions(); + + printf(" Processing code\n"); + Script.ProcessCode(); + + printf(" Storing sources\n"); + Script.StoreSource(arOutput); + printf("File %s decompiled successfuly\n", g_strInputFileName.c_str()); + } + } + + catch (const UserException& e) + { + // Error message already displayed + if (g_bStopOnError == TRUE) { + printf("Press ENTER to continue.\n"); + cin.get(); + } + return 1; + } + + catch(...) { + return 1; + /* + const int c_nErrMsgLen = 1024; + TCHAR lpszErrMsg[c_nErrMsgLen]; + e->GetErrorMessage(lpszErrMsg, c_nErrMsgLen); + printf("Error: %s.\n", lpszErrMsg); + if (g_bStopOnError == TRUE) { + printf("Press ENTER to continue.\n"); + cin.get(); + } + return 1;*/ + } + + return 0; + } + else { + printf("Error: Unable open file %s.\n", g_strOutputFileName.c_str()); + if (g_bStopOnError == TRUE) { + printf("Press ENTER to continue.\n"); + cin.get(); + } + return 1; + } + } + else { + printf("Error: Unable open file %s.\n", g_strInputFileName.c_str()); + if (g_bStopOnError == TRUE) { + printf("Press ENTER to continue.\n"); + cin.get(); + } + return 1; + } + +} + +void PrintUsage(char* lpszFileName) +{ + printf("Usage: int2ssl.exe [options] [-s value] file.int [file.ssl]\n"); + printf("Example: int2ssl.exe -d-1-a-b-e-s3 random.int\n"); + printf("\n"); + printf("Options\n"); + printf(" -d: dump file\n"); + printf(" -1: input file is Fallout 1 script\n"); + printf(" -a: ignore wrong number of arguments\n"); + printf(" -b: insert omitted arguments backward\n"); + printf(" -s: use Space instead of tab to indent\n"); + printf(" -e: stop decompiling on error\n"); + printf(" --: end of options\n"); +} + +BOOL ProcessCommandLine(int argc, char* argv[]) +{ + int c; + int nIndentWidth; + + while((c = getopt(argc, argv, "d1abes:")) != EOF) { + switch (c) { + case 'd': + g_bDump = TRUE; + printf("dump file is on.\n"); + break; + + case '1': + g_nFalloutVersion = 1; + printf("int2ssl is using Fallout 1 code.\n"); + break; + + case 'a': + g_bIgnoreWrongNumOfArgs = TRUE; + printf("ignore wrong number of arguments is on.\n"); + break; + + case 'b': + g_bInsOmittedArgsBackward = TRUE; + printf("insert omitted arguments backward is on.\n"); + break; + + case 'e': + g_bStopOnError = TRUE; + printf("stop decompiling on error is on.\n"); + break; + + case 's': + nIndentWidth = atoi(optarg); + + if (nIndentWidth <= 0) { + printf("Warning: Invalid indent width. Indent set 3\n"); + nIndentWidth = 3; + } + + g_strIndentFill = ""; + + for(; nIndentWidth > 0; nIndentWidth--) + g_strIndentFill += " "; + + break; + } + } + + if (optind == argc) { + printf("Error: Input file name omitted\n"); + if (g_bStopOnError == TRUE) { + printf("Press ENTER to continue.\n"); + cin.get(); + } + return FALSE; + } + + g_strInputFileName = argv[optind]; + optind++; + + if (optind < argc) { + g_strOutputFileName = argv[optind]; + } + else { + g_strOutputFileName = g_strInputFileName; + + /* + if (g_strOutputFileName.Right(4).MakeLower() == ".int") { + g_strOutputFileName = g_strOutputFileName.Left(g_strOutputFileName.GetLength() - 4); + } + */ + + if (g_bDump) { + g_strOutputFileName += ".dump"; + } + else { + g_strOutputFileName += ".ssl"; + } + } + return TRUE; +} diff --git a/sfall function list.txt b/sfall function list.txt new file mode 100644 index 0000000..1de06fb --- /dev/null +++ b/sfall function list.txt @@ -0,0 +1,278 @@ + +*0x8156 - int read_byte(int address) +*0x8157 - int read_short(int address) +*0x8158 - int read_int(int address) +*0x8159 - char* read_string(int address) + +*0x81cf - void write_byte(int address, int value) +*0x81d0 - void write_short(int address, int value) +*0x81d1 - void write_int(int address, int value) +*0x821b - void write_string(int address, char* value) + +*0x81d2 - void call_offset_v0(int address) +*0x81d3 - void call_offset_v1(int address, int arg1) +*0x81d4 - void call_offset_v2(int address, int arg1, int arg2) +*0x81d5 - void call_offset_v3(int address, int arg1, int arg2, int arg3) +*0x81d6 - void call_offset_v4(int address, int arg1, int arg2, int arg3, int arg4) +*0x81d7 - int call_offset_r0(int address) +*0x81d8 - int call_offset_r1(int address, int arg1) +*0x81d9 - int call_offset_r2(int address, int arg1, int arg2) +*0x81da - int call_offset_r3(int address, int arg1, int arg2, int arg3) +*0x81db - int call_offset_r4(int address, int arg1, int arg2, int arg3, int arg4) + +0x815a - void set_pc_base_stat(int StatID, int value) +0x815b - void set_pc_extra_stat(int StatID, int value) +0x815c - int get_pc_base_stat(int StatID) +0x815d - int get_pc_extra_stat(int StatID) + +0x815e - void set_critter_base_stat(CritterPtr, int StatID, int value) +0x815f - void set_critter_extra_stat(CritterPtr, int StatID, int value) +0x8160 - int get_critter_base_stat(CritterPtr, int StatID) +0x8161 - int get_critter_extra_stat(CritterPtr, int StatID) + +0x81b4 - void set_stat_max(int stat, int value) +0x81b5 - void set_stat_min(int stat, int value) +0x81b7 - void set_pc_stat_max(int stat, int value) +0x81b8 - void set_pc_stat_min(int stat, int value) +0x81b9 - void set_npc_stat_max(int stat, int value) +0x81ba - void set_npc_stat_min(int stat, int value) + +0x816b - int input_funcs_available() +ox816c - int key_pressed(int dxScancode) +0x8162 - void tap_key(int dxScancode) +0x821c - int get_mouse_x() +0x821d - int get_mouse_y() +0x821e - int get_mouse_buttons() +0x821f - int get_window_under_mouse() + +0x8163 - int get_year() + +0x8164 - bool game_loaded() + +0x8165 - bool graphics_funcs_available() +0x8166 - int load_shader(char* path) +0x8167 - void free_shader(int ID) +0x8168 - void activate_shader(int ID) +0x8169 - void deactivate_shader(int ID) +0x816d - void set_shader_int(int ID, char* param, int value) +0x816e - void set_shader_float(int ID, char* param, float value) +0x816f - void set_shader_vector(int ID, char* param, float f1, float f2, float f3, float f4) +0x81ad - int get_shader_version() +0x81ae - void set_shader_mode(int mode) +0x81b0 - void force_graphics_refresh(bool enabled) +0x81b1 - int get_shader_texture(int ID, int texture) +0x81b2 - void set_shader_texture(int ID, char* param, int texID) + +0x816a - void set_global_script_repeat(int frames) +0x819b - void set_global_script_type(int type) +0x819c - int available_global_script_types() + +0x8170 - bool in_world_map() + +0x8171 - void force_encounter(int map) +0x8229 - void force_encounter_with_flags(int map, int flags) +0x822a - void set_map_time_multi(float multi) + +0x8172 - void set_world_map_pos(int x, int y) +0x8173 - int get_world_map_x_pos() +0x8174 - int get_world_map_y_pos() + +0x8175 - void set_dm_model(char* name) +0x8176 - void set_df_model(char* name) +0x8177 - void set_movie_path(char* filename, int movieid) + +0x8178 - void set_perk_image(int perkID, int value) +0x8179 - void set_perk_ranks(int perkID, int value) +0x817a - void set_perk_level(int perkID, int value) +0x817b - void set_perk_stat(int perkID, int value) +0x817c - void set_perk_stat_mag(int perkID, int value) +0x817d - void set_perk_skill1(int perkID, int value) +0x817e - void set_perk_skill1_mag(int perkID, int value) +0x817f - void set_perk_type(int perkID, int value) +0x8180 - void set_perk_skill2(int perkID, int value) +0x8181 - void set_perk_skill2_mag(int perkID, int value) +0x8182 - void set_perk_str(int perkID, int value) +0x8183 - void set_perk_per(int perkID, int value) +0x8184 - void set_perk_end(int perkID, int value) +0x8185 - void set_perk_chr(int perkID, int value) +0x8196 - void set_perk_int(int perkID, int value) +0x8187 - void set_perk_agl(int perkID, int value) +0x8188 - void set_perk_lck(int perkID, int value) +0x8189 - void set_perk_name(int perkID, char* value) +0x818a - void set_perk_desc(int perkID, char* value) + +0x818b - void set_pipboy_available(int available) + +0x818c - int get_kill_counter(int critterType) +0x818d - void mod_kill_counter(int critterType, int amount) + +0x818e - int get_perk_owed() +0x818f - void set_perk_owed(int value) +0x8190 - int get_perk_available(int perk) + +0x8191 - int get_critter_current_ap(CritterPtr) +0x8192 - void set_critter_current_ap(CritterPtr, int ap) + +0x8193 - int active_hand() +0x8194 - void toggle_active_hand() + +0x8195 - void set_weapon_knockback(WeaponPtr, int type, float value) +0x8196 - void set_target_knockback(CritterPtr, int type, float value) +0x8197 - void set_attacker_knockback(CritterPtr, int type, float value) +0x8198 - void remove_weapon_knockback(WeaponPtr) +0x8199 - void remove_target_knockback(CritterPtr) +0x819a - void remove_attacker_knockback(CritterPtr) + +0x819d - void set_sfall_global(string/int varname, int/float value) +0x819e - int get_sfall_global_int(string/int varname) +0x819f - float get_sfall_global_float(string/int varname) +0x822d - int create_array(int elementcount, int elementsize) +0x822e - void set_array(int array, int element, any value) +0x822f - any get_array(int array, int element) +0x8230 - void free_array(int array) + +0x81a0 - void set_pickpocket_max(int percentage) +0x81a1 - void set_hit_chance_max(int percentage) +0x81a2 - void set_skill_max(int value) +0x81aa - void set_xp_mod(int percentage) +0x81ab - void set_perk_level_mod(int levels) + +0x81c5 - void set_critter_hit_chance_mod(CritterPtr, int max, int mod) +0x81c6 - void set_base_hit_chance_mod(int max, int mod) +0x81c7 - void set_critter_skill_mod(CritterPtr, int max, int mod) +0x81c8 - void set_base_skill_mod(int max, int mod) +0x81c9 - void set_critter_pickpocket_mod(CritterPtr, int max, int mod) +0x81ca - void set_base_pickpocket_mod(int max, int mod) + +0x81a3 - int eax_available() +0x81a4 - void set_eax_environment(int environment) + +0x81a5 - void inc_npc_level(char* npc) + +0x81a6 - int get_viewport_x() +0x81a7 - int get_viewport_y() +0x81a8 - void set_viewport_x(int view_x) //fixed by nirran +0x81a9 - void set_viewport_y(int view_y) //fixed by nirran + +0x81ac - int get_ini_setting(char* setting) +0x81eb - char* get_ini_string(char* setting) + +0x81af - int get_game_mode() + +0x81b3 - int get_uptime() + +0x81b6 - void set_car_current_town(int town) + +0x81bb - void set_fake_perk(char* name, int level, int image, char* desc) +0x81bc - void set_fake_trait(char* name, int active, int image, char* desc) +0x81bd - void set_selectable_perk(char* name, int active, int image, char* desc) +0x81be - void set_perkbox_title(char* title) +0x81bf - void hide_real_perks() +0x81c0 - void show_real_perks() +0x81c1 - int has_fake_perk(char* name) +0x81c2 - int has_fake_trait(char* name) +0x81c3 - void perk_add_mode(int type) +0x81c4 - void clear_selectable_perks() +0x8225 - void remove_trait(int traitID) + +0x81cb - void set_pyromaniac_mod(int bonus) //fixed by nirran +0x81cc - void apply_heaveho_fix +0x81cd - void set_swiftlearner_mod(int bonus) +0x81ce - void set_hp_per_level_mod(int mod) //fixed by nirran + +0x81dc - void show_iface_tag(int tag) +0x81dd - void hide_iface_tag(int tag) +0x81de - int is_iface_tag_active(int tag) + +0x81df - int get_bodypart_hit_modifier(int bodypart) +0x81e0 - void set_bodypart_hit_modifier(int bodypart, int value) + +0x81e1 - void set_critical_table(int crittertype, int bodypart, int level, int valuetype, int value) +0x81e2 - int get_critical_table(int crittertype, int bodypart, int level, int valuetype) +0x81e3 - void reset_critical_table(int crittertype, int bodypart, int level, int valuetype) + +0x81e4 - int get_sfall_arg() +0x81e5 - void set_sfall_return(int value) +0x81ea - int init_hook() + +0x81e6 - void set_unspent_ap_bonus(int multiplier) +0x81e7 - int get_unspent_ap_bonus() +0x81e8 - void set_unspent_ap_perk_bonus(int multiplier) +0x81e9 - int get_unspent_ap_perk_bonus() + +0x81ec - float sqrt(float) +0x81ed - float abs(float) +0x81ee - float sin(float) +0x81ef - float cos(float) +0x81f0 - float tan(float) +0x81f1 - float arctan(float x, float y) + +0x81f2 - void set_palette(char* path) + +0x81f3 - void remove_script(objptr) +0x81f4 - void set_script(objptr, int scriptid) +0x81f5 - int get_script(objptr) + +0x81f6 - int nb_create_char() + +0x81f7 - int fs_create(string path, int size) +0x81f8 - int fs_copy(string path, string source) +0x81f9 - int fs_find(string path) +0x81fa - void fs_write_byte(int id, int data) +0x81fb - void fs_write_short(int id, int data) +0x81fc - void fs_write_int(int id, int data) +0x81fd - void fs_write_float(int id, int data) +0x81fe - void fs_write_string(int id, string data) +0x8208 - void fs_write_bstring(int id, string data) +0x8209 - int fs_read_byte(int id) +0x820a - int fs_read_short(int id) +0x820b - int fs_read_int(int id) +0x820c - float fs_read_float(int id) +0x81ff - void fs_delete(int id) +0x8200 - int fs_size(int id) +0x8201 - int fs_pos(int id) +0x8202 - void fs_seek(int id, int pos) +0x8203 - void fs_resize(int id, int size) + +0x8204 - int get_proto_data(objptr, int offset) +0x8205 - void set_proto_data(objptr, int offset, int value) //fixed by nirran + +0x8206 - void set_self(objptr) +0x8207 - void register_hook(int hook) + +0x820d - int list_begin(int type) +0x820e - int list_next(int listid) +0x820f - void list_end(int listid) + +0x8210 - int sfall_ver_major() +0x8211 - int sfall_ver_minor() +0x8212 - int sfall_ver_build() + +0x8213 - void hero_select_win(int) +0x8214 - void set_hero_race(int style) +0x8215 - void set_hero_style(int style) + +0x8216 - void set_critter_burst_disable(int critter, int disable) + +0x8217 - int get_weapon_ammo_pid(objptr weapon) +0x8218 - void set_weapon_ammo_pid(objptr weapon, int pid) +0x8219 - int get_weapon_ammo_count(objptr weapon) +0x821a - void set_weapon_ammo_count(objptr weapon, int count) + +0x8220 - int get_screen_width() +0x8221 - int get_screen_height() + +0x8222 - void stop_game() +0x8223 - void resume_game() +0x8224 - void create_message_window(char* message) + +0x8226 - int get_light_level() + +0x8227 - void refresh_pc_art + +0x8228 - int get_attack_type + +0x822b - int play_sfall_sound(char* file, int loop) +0x822c - void stop_sfall_sound(int ptr) + +* These functions require AllowUnsafeScripting to be enabled in ddraw.ini \ No newline at end of file diff --git a/stdafx.cpp b/stdafx.cpp new file mode 100644 index 0000000..c7e3d00 --- /dev/null +++ b/stdafx.cpp @@ -0,0 +1,12 @@ +#include "stdafx.h" + +CObject::CObject() +{ +} + + +void AfxThrowUserException() +{ + throw UserException(); +} + diff --git a/stdafx.h b/stdafx.h new file mode 100644 index 0000000..b349842 --- /dev/null +++ b/stdafx.h @@ -0,0 +1,42 @@ +#ifndef STDAFX_H +#define STDAFX_H + +#include +#include +#include + +#include "Hacks/Types.h" +#include "Hacks/CArray.h" + +class CString; + +class CObject +{ +public : + CObject(); +}; + + +class CDWordArray : public CArray +{ + +}; + +class CStringArray : public CArray +{ + +}; + +class UserException +{ + +}; + + + + + +void AfxThrowUserException(); + + +#endif