From 529598ef70c84715beb5230a89cd7f5259bfcbe6 Mon Sep 17 00:00:00 2001 From: alexeevdv Date: Fri, 13 Feb 2015 16:59:11 +0300 Subject: [PATCH] initial commit --- CMakeLists.txt | 49 ++ FalloutScript.cpp | 277 ++++++++++ FalloutScript.h | 118 +++++ FalloutScriptDecompile.cpp | 772 +++++++++++++++++++++++++++ FalloutScriptDefObject.cpp | 21 + FalloutScriptDump.cpp | 156 ++++++ FalloutScriptStore.cpp | 1004 ++++++++++++++++++++++++++++++++++++ Hacks/CArchive.cpp | 28 + Hacks/CArchive.h | 28 + Hacks/CArray.cpp | 2 + Hacks/CArray.h | 71 +++ Hacks/CFile.cpp | 78 +++ Hacks/CFile.h | 43 ++ Hacks/CMap.cpp | 2 + Hacks/CMap.h | 53 ++ Hacks/CString.cpp | 101 ++++ Hacks/CString.h | 33 ++ Hacks/Types.h | 20 + Namespace.cpp | 158 ++++++ Namespace.h | 36 ++ Node.cpp | 117 +++++ Node.h | 65 +++ ObjectAttributes.h | 26 + Opcode.cpp | 172 ++++++ Opcode.h | 845 ++++++++++++++++++++++++++++++ OpcodeAttributes.cpp | 788 ++++++++++++++++++++++++++++ ProcTable.cpp | 305 +++++++++++ ProcTable.h | 60 +++ StartupCode.cpp | 54 ++ StartupCode.h | 27 + Utility.cpp | 16 + Utility.h | 12 + XGetopt.cpp | 221 ++++++++ XGetopt.h | 23 + main.cpp | 242 +++++++++ sfall function list.txt | 278 ++++++++++ stdafx.cpp | 12 + stdafx.h | 42 ++ 38 files changed, 6355 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 FalloutScript.cpp create mode 100644 FalloutScript.h create mode 100644 FalloutScriptDecompile.cpp create mode 100644 FalloutScriptDefObject.cpp create mode 100644 FalloutScriptDump.cpp create mode 100644 FalloutScriptStore.cpp create mode 100644 Hacks/CArchive.cpp create mode 100644 Hacks/CArchive.h create mode 100644 Hacks/CArray.cpp create mode 100644 Hacks/CArray.h create mode 100644 Hacks/CFile.cpp create mode 100644 Hacks/CFile.h create mode 100644 Hacks/CMap.cpp create mode 100644 Hacks/CMap.h create mode 100644 Hacks/CString.cpp create mode 100644 Hacks/CString.h create mode 100644 Hacks/Types.h create mode 100644 Namespace.cpp create mode 100644 Namespace.h create mode 100644 Node.cpp create mode 100644 Node.h create mode 100644 ObjectAttributes.h create mode 100644 Opcode.cpp create mode 100644 Opcode.h create mode 100644 OpcodeAttributes.cpp create mode 100644 ProcTable.cpp create mode 100644 ProcTable.h create mode 100644 StartupCode.cpp create mode 100644 StartupCode.h create mode 100644 Utility.cpp create mode 100644 Utility.h create mode 100644 XGetopt.cpp create mode 100644 XGetopt.h create mode 100644 main.cpp create mode 100644 sfall function list.txt create mode 100644 stdafx.cpp create mode 100644 stdafx.h 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