Files
int2ssl/FalloutScript.cpp
T

305 lines
9.1 KiB
C++
Raw Normal View History

2015-02-15 18:53:04 +03:00
/**
*
* Copyright (c) 2005-2009 Anchorite (TeamX), <anchorite2001@yandex.ru>
2015-02-15 21:33:27 +03:00
* Copyright (c) 2014-2015 Nirran, phobos2077
* Copyright (c) 2015 alexeevdv <mail@alexeevdv.ru>
2015-02-15 18:53:04 +03:00
* Distributed under the GNU GPL v3. For full terms see the file license.txt
*
*/
2015-02-15 16:59:52 +03:00
// C++ standard includes
#include <iostream>
2015-02-16 00:30:55 +03:00
#include <fstream>
2015-02-15 16:59:52 +03:00
// int2ssl includes
2015-02-13 16:59:11 +03:00
#include "FalloutScript.h"
2015-02-15 16:59:52 +03:00
// Third party includes
2015-02-13 16:59:11 +03:00
2015-02-16 00:30:55 +03:00
extern std::ifstream g_ifstream;
extern std::ofstream g_ofstream;
2015-02-13 16:59:11 +03:00
CFalloutScript::CFalloutScript()
{
}
CFalloutScript::~CFalloutScript()
{
}
2015-02-16 00:30:55 +03:00
void CFalloutScript::Serialize()
2015-02-13 16:59:11 +03:00
{
2017-10-12 00:29:39 +07:00
std::cout << " Read startup code" << std::endl;
2015-02-16 00:30:55 +03:00
m_StartupCode.Serialize();
2015-02-13 23:09:21 +03:00
2015-02-15 16:59:52 +03:00
std::cout << " Read procedures table" << std::endl;
2015-02-16 00:30:55 +03:00
m_ProcTable.Serialize();
2015-02-13 23:09:21 +03:00
2015-02-15 16:59:52 +03:00
std::cout << " Read namespace" << std::endl;
2015-02-16 00:30:55 +03:00
m_Namespace.Serialize();
2015-02-13 23:09:21 +03:00
2015-02-15 16:59:52 +03:00
std::cout << " Read stringspace" << std::endl;
2015-02-16 00:30:55 +03:00
m_Stringspace.Serialize();
2015-02-13 23:09:21 +03:00
COpcode opcode;
2015-02-15 16:59:52 +03:00
std::cout << " Read tail of startup code" << std::endl;
2015-02-16 00:30:55 +03:00
opcode.Expect(COpcode::O_SET_GLOBAL);
2015-02-13 23:09:21 +03:00
// Sections with variable sizes
2015-02-16 00:30:55 +03:00
uint32_t ullCurrentOffset = g_ifstream.tellg();
2015-02-13 23:09:21 +03:00
// Load globals
2015-02-15 21:30:47 +03:00
m_GlobalVar.clear();
m_ExportedVar.clear();
m_ExportedVarValue.clear();
m_ExportedProc.clear();
2015-02-13 23:09:21 +03:00
COpcodeArray HeaderTail;
while(ullCurrentOffset < m_ProcTable.GetOffsetOfProcSection())
2015-02-13 16:59:11 +03:00
{
2015-02-16 00:30:55 +03:00
opcode.Serialize();
2015-02-13 23:09:21 +03:00
ullCurrentOffset += opcode.GetSize();
2015-02-15 21:30:47 +03:00
HeaderTail.push_back(opcode);
2015-02-13 23:09:21 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
// Jump to 'start' procedure
2015-02-15 16:59:52 +03:00
std::cout << " Check \"Jump to \'start\' procedure\" / \"Jump to end of statup code\"" << std::endl;
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
if (!HeaderTail.empty())
2015-02-13 23:09:21 +03:00
{
2015-02-15 19:05:45 +03:00
int32_t nIndexOfStart = GetIndexOfProc("start");
2015-02-15 18:28:27 +03:00
uint32_t ulStartProcAddress = (nIndexOfStart != -1) ? m_ProcTable[nIndexOfStart].m_ulBodyOffset : 18;
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
opcode = HeaderTail.back();
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
if (opcode.GetOperator() == COpcode::O_JMP)
2015-02-13 22:31:52 +03:00
{
2015-02-15 21:30:47 +03:00
HeaderTail.pop_back();
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
if (HeaderTail.empty())
2015-02-13 22:31:52 +03:00
{
2015-02-13 23:09:21 +03:00
printf("\n");
printf("Warning: Omitted address of jump\n");
printf("\n");
}
2015-02-13 22:31:52 +03:00
else
{
2015-02-15 21:30:47 +03:00
opcode = HeaderTail.back();
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
if (opcode.GetOperator() == COpcode::O_INTOP)
{
2015-02-15 21:30:47 +03:00
HeaderTail.pop_back();
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
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
2015-02-13 22:31:52 +03:00
{
2015-02-13 23:09:21 +03:00
printf("\n");
printf("Warning: Omitted \"Jump to \'start\' procedure\" / \"Jump to end of statup code\"\n");
printf("\n");
}
}
2015-02-13 16:59:11 +03:00
2015-02-13 23:09:21 +03:00
// # of argument to 'start' procedure
printf(" Check \"# of argument to \'start\' procedure\"\n");
2015-02-15 16:16:45 +03:00
std::string strNumOfArgsWarning = "Warning: Omitted \"# of argument to \'start\' procedure\"\n";
2015-02-13 23:09:21 +03:00
2015-02-15 21:30:47 +03:00
if (!HeaderTail.empty())
2015-02-14 14:38:14 +03:00
{
2015-02-15 21:30:47 +03:00
opcode = HeaderTail.back();
2015-02-13 23:09:21 +03:00
2015-02-14 14:38:14 +03:00
if (opcode.GetOperator() == COpcode::O_CRITICAL_DONE)
{
2015-02-15 21:30:47 +03:00
HeaderTail.pop_back();
2015-02-13 23:09:21 +03:00
2015-02-15 21:30:47 +03:00
if (!HeaderTail.empty())
2015-02-14 14:38:14 +03:00
{
2015-02-15 21:30:47 +03:00
opcode = HeaderTail.back();
2015-02-13 23:09:21 +03:00
2015-02-14 14:38:14 +03:00
if (opcode.HasArgument())
{
2015-02-15 21:30:47 +03:00
HeaderTail.pop_back();
2015-02-13 23:09:21 +03:00
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-13 23:09:21 +03:00
printf("\n");
printf("%s", strNumOfArgsWarning.c_str());
printf("\n");
}
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-13 23:09:21 +03:00
printf("\n");
printf("%s", strNumOfArgsWarning.c_str());
printf("\n");
}
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-13 23:09:21 +03:00
printf("\n");
printf("Warning: Omitted expected opcode 0x8003. Opcode with # of arguments will be not analysed\n");
printf("\n");
}
}
2015-02-14 14:38:14 +03:00
else
{
2015-02-13 23:09:21 +03:00
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");
2015-02-15 22:27:31 +03:00
for(uint32_t i = 0; i < HeaderTail.size(); i++)
2015-02-14 14:38:14 +03:00
{
2015-02-15 18:10:01 +03:00
uint16_t wGlobalVarOperator = HeaderTail[i].GetOperator();
2015-02-13 23:09:21 +03:00
if ((wGlobalVarOperator != COpcode::O_STRINGOP) &&
(wGlobalVarOperator != COpcode::O_FLOATOP) &&
2015-02-14 14:38:14 +03:00
(wGlobalVarOperator != COpcode::O_INTOP))
{
2015-02-13 23:09:21 +03:00
printf("Error: Malformed \"Global variables\" section\n");
2015-02-15 19:14:18 +03:00
throw std::exception();
2015-02-13 23:09:21 +03:00
}
2015-02-15 21:30:47 +03:00
m_GlobalVar.push_back(HeaderTail[i]);
2015-02-13 23:09:21 +03:00
}
// Procedures bodyes
printf(" Read procedure\'s bodies\n");
2015-02-15 21:30:47 +03:00
m_ProcBodies.clear(); // Destroy old data
m_Conditions.clear();
m_ProcBodies.resize(m_ProcTable.GetSize());
m_Conditions.resize(m_ProcTable.GetSize());
2015-02-13 23:09:21 +03:00
CNode node;
2015-02-15 22:27:31 +03:00
for(uint32_t i = 0; i < m_ProcTable.GetSize(); i++)
2015-02-13 23:09:21 +03:00
{
printf(" Procedure: %d\r", i);
2015-02-15 18:28:27 +03:00
uint32_t ulOffset = m_ProcTable[i].m_ulBodyOffset;
uint32_t ulSize = m_ProcTable.GetSizeOfProc(i);
2015-02-16 00:30:55 +03:00
g_ifstream.seekg(ulOffset, std::ios_base::beg);
2015-02-13 23:09:21 +03:00
while(ulOffset < m_ProcTable[i].m_ulBodyOffset + ulSize)
{
2015-02-16 00:30:55 +03:00
node.m_Opcode.Serialize();
2015-02-13 23:09:21 +03:00
node.m_ulOffset = ulOffset;
2015-02-15 21:30:47 +03:00
m_ProcBodies[i].push_back(node);
2015-02-13 23:09:21 +03:00
ulOffset += node.m_Opcode.GetSize();
}
}
2015-02-13 16:59:11 +03:00
}
2015-02-15 22:27:31 +03:00
void CFalloutScript::ExtractCodeElements(COpcodeArray& Source, COpcodeArray& Destination, uint16_t wDelimeter, uint32_t nSizeOfCodeItem, const char* lpszErrorMessage, bool (CFalloutScript::*pCheckFunc)(uint16_t, int32_t))
2015-02-13 16:59:11 +03:00
{
2015-02-15 22:27:31 +03:00
uint32_t i = 0;
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
for(; i < Source.size(); i++)
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
if (Source[i].GetOperator() == wDelimeter)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
break;
}
}
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
if (i < Source.size())
2015-02-14 14:38:14 +03:00
{
if (i < nSizeOfCodeItem - 1)
{
2015-02-15 22:55:52 +03:00
std::cout << lpszErrorMessage << std::endl;
2015-02-15 19:14:18 +03:00
throw std::exception();
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-14 23:18:15 +03:00
while(Source[i].GetOperator() == wDelimeter)
2015-02-14 14:38:14 +03:00
{
2015-02-15 22:27:31 +03:00
for(uint32_t j = 0; j < nSizeOfCodeItem - 1; j++)
2015-02-14 14:38:14 +03:00
{
2015-02-14 23:18:15 +03:00
if (!((this->*pCheckFunc)(Source[i - nSizeOfCodeItem + 1 + j].GetOperator(), j)))
2015-02-14 14:38:14 +03:00
{
2015-02-15 22:55:52 +03:00
std::cout << lpszErrorMessage << std::endl;
2015-02-15 19:14:18 +03:00
throw std::exception();
2015-02-14 13:39:47 +03:00
}
}
2015-02-13 16:59:11 +03:00
2015-02-15 22:27:31 +03:00
for(uint32_t j = 0; j < nSizeOfCodeItem - 1; j++)
2015-02-14 14:38:14 +03:00
{
2015-02-15 21:30:47 +03:00
Destination.push_back(Source[i - nSizeOfCodeItem + 1]);
Source.erase(Source.begin() + i - nSizeOfCodeItem + 1);
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
Source.erase(Source.begin() + i - nSizeOfCodeItem + 1); // Delimeter
2015-02-13 16:59:11 +03:00
2015-02-15 21:30:47 +03:00
if (i > Source.size() - 1)
2015-02-14 14:38:14 +03:00
{
2015-02-14 13:39:47 +03:00
break;
}
}
}
2015-02-13 16:59:11 +03:00
}
2015-02-15 19:05:45 +03:00
bool CFalloutScript::CheckExportVarCode(uint16_t wOperator, int32_t nIndex)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
return (nIndex == 0) && (wOperator == COpcode::O_STRINGOP);
2015-02-13 16:59:11 +03:00
}
2015-02-15 19:05:45 +03:00
bool CFalloutScript::CheckSetExportedVarValueCode(uint16_t wOperator, int32_t nIndex)
2015-02-13 16:59:11 +03:00
{
2015-02-14 14:38:14 +03:00
switch(nIndex)
{
2015-02-14 13:39:47 +03:00
case 0:
return (wOperator == COpcode::O_STRINGOP) ||
(wOperator == COpcode::O_FLOATOP) ||
(wOperator == COpcode::O_INTOP);
case 1:
return (wOperator == COpcode::O_STRINGOP);
2015-02-13 16:59:11 +03:00
2015-02-14 13:39:47 +03:00
default:
2015-02-15 16:59:52 +03:00
return false;
2015-02-14 13:39:47 +03:00
}
2015-02-13 16:59:11 +03:00
}
2015-02-15 19:05:45 +03:00
bool CFalloutScript::CheckExportProcCode(uint16_t wOperator, int32_t nIndex)
2015-02-13 16:59:11 +03:00
{
2015-02-14 13:39:47 +03:00
return ((nIndex == 0) || (nIndex == 1)) && (wOperator == COpcode::O_INTOP);
2015-02-13 16:59:11 +03:00
}
bool CFalloutScript::ArgNeedParens( const CNode& node, const CNode& argument, CFalloutScript::Assoc assoc)
{
2015-02-14 13:39:47 +03:00
return (argument.IsInfix()
&& ((GetPriority(argument.m_Opcode.GetOperator()) != GetPriority(node.m_Opcode.GetOperator()))
|| (GetAssociation(node.m_Opcode.GetOperator()) != assoc)));
2015-02-13 16:59:11 +03:00
}
2015-02-14 14:38:14 +03:00