iw8 build
This commit is contained in:
6
src/iw8/stdafx.cpp
Normal file
6
src/iw8/stdafx.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#include "stdafx.hpp"
|
38
src/iw8/stdafx.hpp
Normal file
38
src/iw8/stdafx.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
// Warnings
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable:4244)
|
||||
#pragma warning(disable:4267)
|
||||
#pragma warning(disable:4005)
|
||||
#pragma warning(disable:4065)
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
// C/C++
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <array>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <stdio.h>
|
||||
|
||||
// Ext
|
||||
using namespace std::literals;
|
||||
|
||||
#include "xsk/iw8.hpp"
|
682
src/iw8/xsk/assembler.cpp
Normal file
682
src/iw8/xsk/assembler.cpp
Normal file
@ -0,0 +1,682 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#include "stdafx.hpp"
|
||||
#include "iw8.hpp"
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
auto assembler::output_script() -> std::vector<std::uint8_t>
|
||||
{
|
||||
std::vector<std::uint8_t> script;
|
||||
|
||||
if(script_ == nullptr) return script;
|
||||
|
||||
script.resize(script_->pos());
|
||||
memcpy(script.data(), script_->buffer().data(), script.size());
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
auto assembler::output_stack() -> std::vector<std::uint8_t>
|
||||
{
|
||||
std::vector<std::uint8_t> stack;
|
||||
|
||||
if(stack_ == nullptr) return stack;
|
||||
|
||||
stack.resize(stack_->pos());
|
||||
memcpy(stack.data(), stack_->buffer().data(), stack.size());
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
void assembler::assemble(const std::string& file, std::vector<std::uint8_t>& data)
|
||||
{
|
||||
std::vector<std::string> assembly = utils::string::clean_buffer_lines(data);
|
||||
std::vector<gsc::function_ptr> functions;
|
||||
gsc::function_ptr func = nullptr;
|
||||
std::uint32_t index = 1;
|
||||
std::uint16_t switchnum = 0;
|
||||
|
||||
for (auto& line : assembly)
|
||||
{
|
||||
if (line == "" || line.substr(0, 2) == "//")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (line.substr(0, 4) == "sub_")
|
||||
{
|
||||
func = std::make_unique<gsc::function>();
|
||||
func->index = index;
|
||||
func->name = line.substr(4);
|
||||
}
|
||||
else if (line.substr(0, 4) == "end_")
|
||||
{
|
||||
if (func != nullptr)
|
||||
{
|
||||
func->size = index - func->index;
|
||||
functions.push_back(std::move(func));
|
||||
}
|
||||
}
|
||||
else if (line.substr(0, 4) == "loc_")
|
||||
{
|
||||
func->labels[index] = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto data = utils::string::parse_code(line);
|
||||
|
||||
if (switchnum)
|
||||
{
|
||||
if (data[0] == "case" || data[0] == "default")
|
||||
{
|
||||
for (auto& entry : data)
|
||||
{
|
||||
func->instructions.back()->data.push_back(entry);
|
||||
}
|
||||
switchnum--;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw gsc::asm_error("invalid instruction inside endswitch \""s + line + "\"!");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto inst = std::make_unique<gsc::instruction>();
|
||||
inst->index = index;
|
||||
inst->opcode = static_cast<std::uint8_t>(resolver::opcode_id(data[0]));
|
||||
inst->size = opcode_size(inst->opcode);
|
||||
data.erase(data.begin());
|
||||
inst->data = std::move(data);
|
||||
|
||||
if (opcode(inst->opcode) == opcode::OP_endswitch)
|
||||
{
|
||||
switchnum = static_cast<std::uint16_t>(std::stoi(inst->data[0]));
|
||||
inst->size += 7 * switchnum;
|
||||
}
|
||||
|
||||
index += inst->size;
|
||||
func->instructions.push_back(std::move(inst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->assemble(file, functions);
|
||||
}
|
||||
|
||||
void assembler::assemble(const std::string& file, std::vector<gsc::function_ptr>& functions)
|
||||
{
|
||||
script_ = std::make_unique<utils::byte_buffer>(0x100000);
|
||||
stack_ = std::make_unique<utils::byte_buffer>(0x100000);
|
||||
filename_ = file;
|
||||
functions_ = std::move(functions);
|
||||
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(opcode::OP_End));
|
||||
|
||||
for (const auto& func : functions_)
|
||||
{
|
||||
this->assemble_function(func);
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_function(const gsc::function_ptr& func)
|
||||
{
|
||||
labels_ = func->labels;
|
||||
|
||||
stack_->write<std::uint32_t>(func->size);
|
||||
|
||||
func->id = func->name.substr(0, 3) == "_ID" ? std::stoi(func->name.substr(3)) : resolver::token_id(func->name);
|
||||
stack_->write<std::uint32_t>(func->id);
|
||||
|
||||
if (func->id == 0)
|
||||
{
|
||||
stack_->write_c_string(func->name);
|
||||
}
|
||||
|
||||
for (const auto& inst : func->instructions)
|
||||
{
|
||||
this->assemble_instruction(inst);
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_instruction(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
switch (opcode(inst->opcode))
|
||||
{
|
||||
case opcode::OP_CastFieldObject:
|
||||
case opcode::OP_plus:
|
||||
case opcode::OP_GetGameRef:
|
||||
case opcode::OP_GetThisthread:
|
||||
case opcode::OP_greater:
|
||||
case opcode::OP_shift_right:
|
||||
case opcode::OP_dec:
|
||||
case opcode::OP_bit_or:
|
||||
case opcode::OP_equality:
|
||||
case opcode::OP_ClearLocalVariableFieldCached0:
|
||||
case opcode::OP_notify:
|
||||
case opcode::OP_PreScriptCall:
|
||||
case opcode::OP_GetUndefined:
|
||||
case opcode::OP_SetLocalVariableFieldCached0:
|
||||
case opcode::OP_GetLevel:
|
||||
case opcode::OP_size:
|
||||
case opcode::OP_AddArray:
|
||||
case opcode::OP_endon:
|
||||
case opcode::OP_shift_left:
|
||||
case opcode::OP_EvalLocalArrayRefCached0:
|
||||
case opcode::OP_Return:
|
||||
case opcode::OP_SafeSetVariableFieldCached0:
|
||||
case opcode::OP_GetSelfObject:
|
||||
case opcode::OP_GetGame:
|
||||
case opcode::OP_EvalArray:
|
||||
case opcode::OP_GetSelf:
|
||||
case opcode::OP_End:
|
||||
case opcode::OP_less_equal:
|
||||
case opcode::OP_EvalLocalVariableCached0:
|
||||
case opcode::OP_EvalLocalVariableCached1:
|
||||
case opcode::OP_EvalLocalVariableCached2:
|
||||
case opcode::OP_EvalLocalVariableCached3:
|
||||
case opcode::OP_EvalLocalVariableCached4:
|
||||
case opcode::OP_EvalLocalVariableCached5:
|
||||
case opcode::OP_ScriptMethodCallPointer:
|
||||
case opcode::OP_checkclearparams:
|
||||
case opcode::OP_waittillmatch2:
|
||||
case opcode::OP_minus:
|
||||
case opcode::OP_greater_equal:
|
||||
case opcode::OP_vector:
|
||||
case opcode::OP_ClearArray:
|
||||
case opcode::OP_DecTop:
|
||||
case opcode::OP_CastBool:
|
||||
case opcode::OP_EvalArrayRef:
|
||||
case opcode::OP_GetZero:
|
||||
case opcode::OP_wait:
|
||||
case opcode::OP_waittill:
|
||||
case opcode::OP_GetAnimObject:
|
||||
case opcode::OP_mod:
|
||||
case opcode::OP_clearparams:
|
||||
case opcode::OP_ScriptFunctionCallPointer:
|
||||
case opcode::OP_EmptyArray:
|
||||
case opcode::OP_ClearVariableField:
|
||||
case opcode::OP_EvalNewLocalVariableRefCached0:
|
||||
case opcode::OP_BoolComplement:
|
||||
case opcode::OP_less:
|
||||
case opcode::OP_BoolNot:
|
||||
case opcode::OP_waittillFrameEnd:
|
||||
case opcode::OP_waitframe:
|
||||
case opcode::OP_GetLevelObject:
|
||||
case opcode::OP_inc:
|
||||
case opcode::OP_GetAnim:
|
||||
case opcode::OP_SetVariableField:
|
||||
case opcode::OP_divide:
|
||||
case opcode::OP_multiply:
|
||||
case opcode::OP_EvalLocalVariableRefCached0:
|
||||
case opcode::OP_bit_and:
|
||||
case opcode::OP_voidCodepos:
|
||||
case opcode::OP_inequality:
|
||||
case opcode::OP_bit_ex_or:
|
||||
/*
|
||||
case opcode::OP_NOP:
|
||||
case opcode::OP_abort:
|
||||
case opcode::OP_object:
|
||||
case opcode::OP_thread_object:
|
||||
case opcode::OP_EvalLocalVariable:
|
||||
case opcode::OP_EvalLocalVariableRef:
|
||||
case opcode::OP_breakpoint:
|
||||
case opcode::OP_assignmentBreakpoint:
|
||||
case opcode::OP_manualAndAssignmentBreakpoint:
|
||||
*/
|
||||
case opcode::OP_BoolNotAfterAnd:
|
||||
case opcode::OP_IsDefined:
|
||||
case opcode::OP_IsTrue:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
break;
|
||||
case opcode::OP_GetByte:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
case opcode::OP_GetNegByte:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::int8_t>(static_cast<std::int8_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
case opcode::OP_GetUnsignedShort:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint16_t>(static_cast<std::uint16_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
case opcode::OP_GetNegUnsignedShort:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::int16_t>(static_cast<std::int16_t>(std::stoi(inst->data[0])));
|
||||
case opcode::OP_GetInteger:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::int32_t>(std::stoi(inst->data[0]));
|
||||
break;
|
||||
case opcode::OP_GetFloat:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<float>(std::stof(inst->data[0]));
|
||||
break;
|
||||
case opcode::OP_GetVector:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<float>(std::stof(inst->data[0]));
|
||||
script_->write<float>(std::stof(inst->data[1]));
|
||||
script_->write<float>(std::stof(inst->data[2]));
|
||||
break;
|
||||
case opcode::OP_GetString:
|
||||
case opcode::OP_GetIString:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint32_t>(0);
|
||||
stack_->write_c_string(utils::string::to_code(inst->data[0]));
|
||||
break;
|
||||
case opcode::OP_GetAnimation:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint32_t>(0);
|
||||
script_->write<std::uint32_t>(0);
|
||||
stack_->write_c_string(utils::string::unquote(inst->data[0]));
|
||||
stack_->write_c_string(utils::string::unquote(inst->data[1]));
|
||||
break;
|
||||
case opcode::OP_GetAnimTree:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(0);
|
||||
stack_->write_c_string(utils::string::unquote(inst->data[0]));
|
||||
break;
|
||||
case opcode::OP_waittillmatch:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint16_t>(0);
|
||||
break;
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0:
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0:
|
||||
case opcode::OP_SafeCreateVariableFieldCached:
|
||||
case opcode::OP_ClearLocalVariableFieldCached:
|
||||
case opcode::OP_SetLocalVariableFieldCached:
|
||||
case opcode::OP_RemoveLocalVariables:
|
||||
case opcode::OP_EvalLocalVariableRefCached:
|
||||
case opcode::OP_EvalLocalArrayRefCached:
|
||||
case opcode::OP_SafeSetVariableFieldCached:
|
||||
case opcode::OP_EvalLocalVariableCached:
|
||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||
case opcode::OP_CreateLocalVariable:
|
||||
case opcode::OP_EvalLocalVariableObjectCached:
|
||||
case opcode::OP_EvalLocalArrayCached:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
case opcode::OP_EvalSelfFieldVariable:
|
||||
case opcode::OP_SetLevelFieldVariableField:
|
||||
case opcode::OP_ClearFieldVariable:
|
||||
case opcode::OP_EvalFieldVariable:
|
||||
case opcode::OP_EvalFieldVariableRef:
|
||||
case opcode::OP_EvalLevelFieldVariable:
|
||||
case opcode::OP_SetAnimFieldVariableField:
|
||||
case opcode::OP_SetSelfFieldVariableField:
|
||||
case opcode::OP_EvalAnimFieldVariableRef:
|
||||
case opcode::OP_EvalLevelFieldVariableRef:
|
||||
case opcode::OP_EvalAnimFieldVariable:
|
||||
case opcode::OP_EvalSelfFieldVariableRef:
|
||||
this->assemble_field_variable(inst);
|
||||
break;
|
||||
case opcode::OP_CallBuiltinPointer:
|
||||
case opcode::OP_CallBuiltinMethodPointer:
|
||||
case opcode::OP_ScriptThreadCallPointer:
|
||||
case opcode::OP_ScriptChildThreadCallPointer:
|
||||
case opcode::OP_ScriptMethodThreadCallPointer:
|
||||
case opcode::OP_ScriptMethodChildThreadCallPointer:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
case opcode::OP_GetLocalFunction:
|
||||
case opcode::OP_ScriptLocalFunctionCall2:
|
||||
case opcode::OP_ScriptLocalFunctionCall:
|
||||
case opcode::OP_ScriptLocalMethodCall:
|
||||
this->assemble_local_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_ScriptLocalThreadCall:
|
||||
case opcode::OP_ScriptLocalChildThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodChildThreadCall:
|
||||
this->assemble_local_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_GetFarFunction:
|
||||
case opcode::OP_ScriptFarFunctionCall2:
|
||||
case opcode::OP_ScriptFarFunctionCall:
|
||||
case opcode::OP_ScriptFarMethodCall:
|
||||
this->assemble_far_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_ScriptFarThreadCall:
|
||||
case opcode::OP_ScriptFarChildThreadCall:
|
||||
case opcode::OP_ScriptFarMethodThreadCall:
|
||||
case opcode::OP_ScriptFarMethodChildThreadCall:
|
||||
this->assemble_far_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_CallBuiltin:
|
||||
this->assemble_builtin_call(inst, false, true);
|
||||
break;
|
||||
case opcode::OP_CallBuiltinMethod:
|
||||
this->assemble_builtin_call(inst, true, true);
|
||||
break;
|
||||
case opcode::OP_GetBuiltinFunction:
|
||||
case opcode::OP_CallBuiltin0:
|
||||
case opcode::OP_CallBuiltin1:
|
||||
case opcode::OP_CallBuiltin2:
|
||||
case opcode::OP_CallBuiltin3:
|
||||
case opcode::OP_CallBuiltin4:
|
||||
case opcode::OP_CallBuiltin5:
|
||||
this->assemble_builtin_call(inst, false, false);
|
||||
break;
|
||||
case opcode::OP_GetBuiltinMethod:
|
||||
case opcode::OP_CallBuiltinMethod0:
|
||||
case opcode::OP_CallBuiltinMethod1:
|
||||
case opcode::OP_CallBuiltinMethod2:
|
||||
case opcode::OP_CallBuiltinMethod3:
|
||||
case opcode::OP_CallBuiltinMethod4:
|
||||
case opcode::OP_CallBuiltinMethod5:
|
||||
this->assemble_builtin_call(inst, true, false);
|
||||
break;
|
||||
case opcode::OP_JumpOnFalseExpr:
|
||||
case opcode::OP_JumpOnTrueExpr:
|
||||
case opcode::OP_JumpOnFalse:
|
||||
case opcode::OP_JumpOnTrue:
|
||||
this->assemble_jump(inst, true, false);
|
||||
break;
|
||||
case opcode::OP_jumpback:
|
||||
this->assemble_jump(inst, false, true);
|
||||
break;
|
||||
case opcode::OP_jump:
|
||||
this->assemble_jump(inst, false, false);
|
||||
break;
|
||||
case opcode::OP_switch:
|
||||
this->assemble_switch(inst);
|
||||
break;
|
||||
case opcode::OP_endswitch:
|
||||
this->assemble_end_switch(inst);
|
||||
break;
|
||||
/*
|
||||
case opcode::OP_prof_begin:
|
||||
script_->write<std::uint32_t>(0); // TODO: skipped data
|
||||
script_->write<std::uint8_t>(0);
|
||||
break;
|
||||
case opcode::OP_prof_end:
|
||||
script_->write<std::uint8_t>(0); // TODO: skipped data
|
||||
break;
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled:
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled:
|
||||
case opcode::OP_CreateLocalVariable_Precompiled:
|
||||
case opcode::OP_SafeCreateVariableFieldCached_Precompiled:
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
break;
|
||||
*/
|
||||
case opcode::OP_FormalParams:
|
||||
// case opcode::OP_FormalParams_Precompiled:
|
||||
this->assemble_formal_params(inst);
|
||||
break;
|
||||
/*
|
||||
case opcode::OP_NativeGetLocalFunction:
|
||||
case opcode::OP_NativeLocalFunctionCall:
|
||||
case opcode::OP_NativeLocalFunctionCall2:
|
||||
case opcode::OP_NativeLocalMethodCall:
|
||||
this->assemble_local_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_NativeGetFarFunction:
|
||||
case opcode::OP_NativeFarFunctionCall:
|
||||
case opcode::OP_NativeFarFunctionCall2:
|
||||
case opcode::OP_NativeFarMethodCall:
|
||||
this->assemble_far_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_NativeLocalFunctionThreadCall:
|
||||
case opcode::OP_NativeLocalMethodThreadCall:
|
||||
case opcode::OP_NativeLocalFunctionChildThreadCall:
|
||||
case opcode::OP_NativeLocalMethodChildThreadCall:
|
||||
this->assemble_local_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_NativeFarFunctionThreadCall:
|
||||
case opcode::OP_NativeFarMethodThreadCall:
|
||||
case opcode::OP_NativeFarFunctionChildThreadCall:
|
||||
case opcode::OP_NativeFarMethodChildThreadCall:
|
||||
this->assemble_far_call(inst, true);
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
throw gsc::asm_error(utils::string::va("Unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index));
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::uint16_t id = 0;
|
||||
|
||||
if (arg_num)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
|
||||
if (method)
|
||||
id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::method_id(inst->data[1]);
|
||||
else
|
||||
id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::function_id(inst->data[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (method)
|
||||
id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::method_id(inst->data[0]);
|
||||
else
|
||||
id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::function_id(inst->data[0]);
|
||||
}
|
||||
|
||||
script_->write<std::uint16_t>(id);
|
||||
}
|
||||
|
||||
void assembler::assemble_local_call(const gsc::instruction_ptr& inst, bool thread)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::int32_t addr = this->resolve_function(inst->data[0]);
|
||||
|
||||
std::int32_t offset = addr - inst->index - 1;
|
||||
|
||||
this->assemble_offset(offset);
|
||||
|
||||
if (thread)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[1])));
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_far_call(const gsc::instruction_ptr& inst, bool thread)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
script_->write<std::uint8_t>(0);
|
||||
script_->write<std::uint16_t>(0);
|
||||
|
||||
std::uint32_t file_id = 0;
|
||||
std::uint32_t func_id = 0;
|
||||
|
||||
if (thread)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[0])));
|
||||
|
||||
file_id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::file_id(inst->data[1]);
|
||||
func_id = inst->data[2].substr(0, 3) == "_ID" ? std::stoi(inst->data[2].substr(3)) : resolver::token_id(inst->data[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
file_id = inst->data[0].substr(0, 3) == "_ID" ? std::stoi(inst->data[0].substr(3)) : resolver::file_id(inst->data[0]);
|
||||
func_id = inst->data[1].substr(0, 3) == "_ID" ? std::stoi(inst->data[1].substr(3)) : resolver::token_id(inst->data[1]);
|
||||
}
|
||||
|
||||
stack_->write<std::uint32_t>(file_id);
|
||||
if (file_id == 0) stack_->write_c_string(thread ? inst->data[1] : inst->data[0]);
|
||||
stack_->write<std::uint32_t>(func_id);
|
||||
if (func_id == 0) stack_->write_c_string(thread ? inst->data[2] : inst->data[1]);
|
||||
}
|
||||
|
||||
void assembler::assemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::int32_t addr = this->resolve_label(inst->data[0]);
|
||||
|
||||
if (expr)
|
||||
{
|
||||
script_->write<std::int16_t>(addr - inst->index - 3);
|
||||
}
|
||||
else if (back)
|
||||
{
|
||||
script_->write<std::int16_t>((inst->index + 3) - addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_->write<std::int32_t>(addr - inst->index - 5);
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_field_variable(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::uint32_t field_id = 0;
|
||||
|
||||
if (inst->data[0].substr(0, 3) == "_ID")
|
||||
{
|
||||
field_id = std::stoi(inst->data[0].substr(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
field_id = resolver::token_id(inst->data[0]);
|
||||
|
||||
if (field_id == 0)
|
||||
{
|
||||
field_id = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
script_->write<std::uint32_t>(field_id);
|
||||
|
||||
if (field_id > 0x13160) // 0xE2C0 or 0x13160
|
||||
{
|
||||
stack_->write<std::uint32_t>(0);
|
||||
stack_->write_c_string(inst->data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_formal_params(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
auto size = std::stoi(inst->data[0]);
|
||||
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(size));
|
||||
|
||||
for(auto i = 1; i <= size; i++)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(std::stoi(inst->data[i])));
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_switch(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::int32_t addr = this->resolve_label(inst->data[0]);
|
||||
|
||||
script_->write<std::int32_t>(addr - inst->index - 4);
|
||||
}
|
||||
|
||||
void assembler::assemble_end_switch(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
script_->write<std::uint8_t>(static_cast<std::uint8_t>(inst->opcode));
|
||||
|
||||
std::uint16_t casenum = 0;
|
||||
|
||||
if (utils::string::is_number(inst->data[0]))
|
||||
{
|
||||
casenum = std::stoi(inst->data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gsc::asm_error("invalid endswitch number!");
|
||||
}
|
||||
|
||||
script_->write<std::uint16_t>(casenum);
|
||||
|
||||
std::uint32_t internal_index = inst->index + 3;
|
||||
|
||||
for (std::uint16_t i = 0; i < casenum; i++)
|
||||
{
|
||||
if (inst->data[1 + (3 * i)] == "case")
|
||||
{
|
||||
if (utils::string::is_number(inst->data[1 + (3 * i) + 1]))
|
||||
{
|
||||
script_->write<uint32_t>((std::stoi(inst->data[1 + (3 * i) + 1]) & 0xFFFFFF) + 0x800000);
|
||||
}
|
||||
else
|
||||
{
|
||||
script_->write<uint32_t>(i + 1);
|
||||
stack_->write_c_string(utils::string::unquote(inst->data[1 + (3 * i) + 1]));
|
||||
}
|
||||
|
||||
internal_index += 4;
|
||||
|
||||
std::int32_t addr = this->resolve_label(inst->data[1 + (3 * i) + 2]);
|
||||
|
||||
this->assemble_offset(addr - internal_index);
|
||||
|
||||
internal_index += 3;
|
||||
}
|
||||
else if (inst->data[1 + (3 * i)] == "default")
|
||||
{
|
||||
script_->write<uint32_t>(0);
|
||||
stack_->write_c_string("\x01");
|
||||
|
||||
internal_index += 4;
|
||||
std::int32_t addr = this->resolve_label(inst->data[1 + (3 * i) + 1]);
|
||||
|
||||
this->assemble_offset(addr - internal_index);
|
||||
|
||||
internal_index += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assembler::assemble_offset(std::int32_t offset)
|
||||
{
|
||||
std::array<std::uint8_t, 4> bytes = {};
|
||||
|
||||
offset = (offset << 8) >> 8;
|
||||
|
||||
*reinterpret_cast<std::int32_t*>(bytes.data()) = offset;
|
||||
|
||||
script_->write<std::uint8_t>(bytes[0]);
|
||||
script_->write<std::uint8_t>(bytes[1]);
|
||||
script_->write<std::uint8_t>(bytes[2]);
|
||||
}
|
||||
|
||||
auto assembler::resolve_function(const std::string& name) -> std::uint32_t
|
||||
{
|
||||
auto temp = name.substr(0, 4) == "sub_" ? name.substr(4) : name;
|
||||
|
||||
for (const auto& func : functions_)
|
||||
{
|
||||
if (func->name == temp)
|
||||
{
|
||||
return func->index;
|
||||
}
|
||||
}
|
||||
|
||||
throw gsc::asm_error("Couldn't resolve local function address of '" + temp + "'!");
|
||||
}
|
||||
|
||||
auto assembler::resolve_label(const std::string& name) -> std::uint32_t
|
||||
{
|
||||
for (auto& func : labels_)
|
||||
{
|
||||
if (func.second == name)
|
||||
{
|
||||
return func.first;
|
||||
}
|
||||
}
|
||||
|
||||
throw gsc::asm_error("Couldn't resolve label address of '" + name + "'!");
|
||||
}
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
41
src/iw8/xsk/assembler.hpp
Normal file
41
src/iw8/xsk/assembler.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
class assembler : public gsc::assembler
|
||||
{
|
||||
std::string filename_;
|
||||
utils::byte_buffer_ptr script_;
|
||||
utils::byte_buffer_ptr stack_;
|
||||
std::vector<gsc::function_ptr> functions_;
|
||||
std::unordered_map<std::uint32_t, std::string> labels_;
|
||||
|
||||
public:
|
||||
auto output_script() -> std::vector<std::uint8_t>;
|
||||
auto output_stack() -> std::vector<std::uint8_t>;
|
||||
void assemble(const std::string& file, std::vector<std::uint8_t>& data);
|
||||
void assemble(const std::string& file, std::vector<gsc::function_ptr>& functions);
|
||||
|
||||
private:
|
||||
void assemble_function(const gsc::function_ptr& func);
|
||||
void assemble_instruction(const gsc::instruction_ptr& inst);
|
||||
void assemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num);
|
||||
void assemble_local_call(const gsc::instruction_ptr& inst, bool thread);
|
||||
void assemble_far_call(const gsc::instruction_ptr& inst, bool thread);
|
||||
void assemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back);
|
||||
void assemble_field_variable(const gsc::instruction_ptr& inst);
|
||||
void assemble_formal_params(const gsc::instruction_ptr& inst);
|
||||
void assemble_switch(const gsc::instruction_ptr& inst);
|
||||
void assemble_end_switch(const gsc::instruction_ptr& inst);
|
||||
void assemble_offset(std::int32_t offset);
|
||||
auto resolve_function(const std::string& name) -> std::uint32_t;
|
||||
auto resolve_label(const std::string& name) -> std::uint32_t;
|
||||
};
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
2453
src/iw8/xsk/compiler.cpp
Normal file
2453
src/iw8/xsk/compiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
152
src/iw8/xsk/compiler.hpp
Normal file
152
src/iw8/xsk/compiler.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
enum class opcode : std::uint8_t;
|
||||
|
||||
class compiler : public gsc::compiler
|
||||
{
|
||||
std::string filename_;
|
||||
std::vector<gsc::function_ptr> assembly_;
|
||||
gsc::function_ptr function_;
|
||||
std::uint32_t index_;
|
||||
std::uint32_t label_idx_;
|
||||
std::uint8_t stack_idx_;
|
||||
std::vector<std::string> local_stack_;
|
||||
std::vector<std::string> local_functions_;
|
||||
std::vector<include_t> includes_;
|
||||
std::vector<animtree_t> animtrees_;
|
||||
std::unordered_map<std::string, gsc::expr_ptr> constants_;
|
||||
std::function<std::vector<std::uint8_t>(const std::string&)> callback_readf_;
|
||||
std::vector<gsc::context*> break_ctxs_;
|
||||
std::vector<gsc::context*> continue_ctxs_;
|
||||
bool can_break_;
|
||||
bool can_continue_;
|
||||
|
||||
public:
|
||||
auto output() -> std::vector<gsc::function_ptr>;
|
||||
void compile(const std::string& file, std::vector<std::uint8_t>& data);
|
||||
void set_readf_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func);
|
||||
|
||||
private:
|
||||
auto parse_buffer(const std::string& file, std::vector<std::uint8_t>& data) -> gsc::program_ptr;
|
||||
auto parse_file(const std::string& file) -> gsc::program_ptr;
|
||||
void compile_program(const gsc::program_ptr& program);
|
||||
void emit_include(const gsc::include_ptr& include);
|
||||
void emit_define(const gsc::define_ptr& define);
|
||||
void emit_usingtree(const gsc::usingtree_ptr& animtree);
|
||||
void emit_constant(const gsc::constant_ptr& constant);
|
||||
void emit_thread(const gsc::thread_ptr& thread);
|
||||
void emit_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params);
|
||||
void emit_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt, bool last);
|
||||
void emit_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt, bool last);
|
||||
void emit_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt);
|
||||
void emit_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt);
|
||||
void emit_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt);
|
||||
void emit_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt);
|
||||
void emit_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt);
|
||||
void emit_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt);
|
||||
void emit_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt);
|
||||
void emit_stmt_waittillframeend(const gsc::context_ptr& ctx, const gsc::stmt_waittillframeend_ptr& stmt);
|
||||
void emit_stmt_waitframe(const gsc::context_ptr& ctx, const gsc::stmt_waitframe_ptr& stmt);
|
||||
void emit_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt, bool last);
|
||||
void emit_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt, bool last);
|
||||
void emit_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt);
|
||||
void emit_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt);
|
||||
void emit_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt);
|
||||
void emit_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt);
|
||||
void emit_stmt_case(const gsc::context_ptr& ctx, const gsc::stmt_case_ptr& stmt);
|
||||
void emit_stmt_default(const gsc::context_ptr& ctx, const gsc::stmt_default_ptr& stmt);
|
||||
void emit_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt);
|
||||
void emit_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt);
|
||||
void emit_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt);
|
||||
void emit_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr);
|
||||
void emit_expr_assign(const gsc::context_ptr& ctx, const gsc::expr_assign_ptr& expr);
|
||||
void emit_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr);
|
||||
void emit_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr);
|
||||
void emit_expr_isdefined(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr);
|
||||
void emit_expr_istrue(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& expr);
|
||||
void emit_expr_bool_not_after_and(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr);
|
||||
void emit_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr);
|
||||
void emit_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr);
|
||||
void emit_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr);
|
||||
void emit_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr);
|
||||
void emit_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void emit_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void emit_expr_call_pointer_type(const gsc::context_ptr& ctx, int args, bool builtin, bool method, bool thread, bool child);
|
||||
void emit_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void emit_expr_call_function_builtin(const gsc::context_ptr& ctx, const std::string& func, int args, bool method);
|
||||
void emit_expr_call_function_local(const gsc::context_ptr& ctx, const std::string& func, int args, bool method, bool thread, bool child);
|
||||
void emit_expr_call_function_far(const gsc::context_ptr& ctx, const std::string& file, const std::string& func, int args, bool method, bool thread, bool child);
|
||||
void emit_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& arg_list);
|
||||
void emit_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& node);
|
||||
void emit_expr_clear_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& lvalue);
|
||||
void emit_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr);
|
||||
void emit_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr);
|
||||
void emit_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr, bool set);
|
||||
void emit_array_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr, bool set);
|
||||
void emit_field_variable_ref(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr, bool set);
|
||||
void emit_local_variable_ref(const gsc::context_ptr& ctx, const gsc::name_ptr& expr, bool set);
|
||||
void emit_variable(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr);
|
||||
void emit_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr);
|
||||
void emit_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr);
|
||||
void emit_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr);
|
||||
void emit_clear_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr);
|
||||
void emit_create_local_vars(const gsc::context_ptr& ctx);
|
||||
void emit_remove_local_vars(const gsc::context_ptr& ctx);
|
||||
void emit_object(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr);
|
||||
void emit_animtree(const gsc::context_ptr& ctx, const gsc::animtree_ptr& animtree);
|
||||
void emit_animation(const gsc::context_ptr& ctx, const gsc::animation_ptr& animation);
|
||||
void emit_istring(const gsc::context_ptr& ctx, const gsc::istring_ptr& str);
|
||||
void emit_string(const gsc::context_ptr& ctx, const gsc::string_ptr& str);
|
||||
void emit_color(const gsc::context_ptr& ctx, const gsc::color_ptr& color);
|
||||
void emit_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec);
|
||||
void emit_float(const gsc::context_ptr& ctx, const gsc::float_ptr& num);
|
||||
void emit_integer(const gsc::context_ptr& ctx, const gsc::integer_ptr& num);
|
||||
void emit_false(const gsc::context_ptr& ctx, const gsc::false_ptr& expr);
|
||||
void emit_true(const gsc::context_ptr& ctx, const gsc::true_ptr& expr);
|
||||
void emit_opcode(const gsc::context_ptr& ctx, opcode op);
|
||||
void emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::string& data);
|
||||
void emit_opcode(const gsc::context_ptr& ctx, opcode op, const std::vector<std::string>& data);
|
||||
void process_thread(const gsc::context_ptr& ctx, const gsc::thread_ptr& thread);
|
||||
void process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params);
|
||||
void process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt);
|
||||
void process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt);
|
||||
void process_expr(const gsc::context_ptr& ctx, const gsc::expr_ptr& expr);
|
||||
void process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt);
|
||||
void process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt);
|
||||
void process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt);
|
||||
void process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt);
|
||||
void process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt);
|
||||
void process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt);
|
||||
void process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt);
|
||||
void process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt);
|
||||
void process_stmt_continue(const gsc::context_ptr& ctx, const gsc::stmt_continue_ptr& stmt);
|
||||
void process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt);
|
||||
void register_variable(const gsc::context_ptr& ctx, const std::string& name);
|
||||
void initialize_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name);
|
||||
void create_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& name);
|
||||
auto variable_stack_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::uint8_t;
|
||||
auto variable_create_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string;
|
||||
auto variable_access_index(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> std::string;
|
||||
auto variable_initialized(const gsc::context_ptr& ctx, const gsc::name_ptr& name) -> bool;
|
||||
auto is_include_call(const std::string& name, std::string& file) -> bool;
|
||||
auto is_local_call(const std::string& name) -> bool;
|
||||
auto is_builtin_call(const std::string& name) -> bool;
|
||||
auto is_builtin_func(const std::string& name) -> bool;
|
||||
auto is_builtin_method(const std::string& name) -> bool;
|
||||
auto is_constant_condition(const gsc::expr_ptr& expr) -> bool;
|
||||
auto create_label() -> std::string;
|
||||
auto insert_label() -> std::string;
|
||||
void insert_label(const std::string& label);
|
||||
|
||||
auto map_known_includes(const std::string& include) -> bool;
|
||||
};
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
3386
src/iw8/xsk/decompiler.cpp
Normal file
3386
src/iw8/xsk/decompiler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
95
src/iw8/xsk/decompiler.hpp
Normal file
95
src/iw8/xsk/decompiler.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
class decompiler : public gsc::decompiler
|
||||
{
|
||||
std::string filename_;
|
||||
std::unique_ptr<utils::byte_buffer> output_;
|
||||
gsc::program_ptr program_;
|
||||
gsc::thread_ptr func_;
|
||||
std::unordered_map<std::uint32_t, std::string> labels_;
|
||||
std::vector<std::string> expr_labels_;
|
||||
std::vector<std::string> tern_labels_;
|
||||
std::stack<gsc::node_ptr> stack_;
|
||||
std::vector<gsc::context> blocks_;
|
||||
|
||||
public:
|
||||
auto output() -> std::vector<std::uint8_t>;
|
||||
void decompile(const std::string& file, std::vector<gsc::function_ptr>& functions);
|
||||
|
||||
private:
|
||||
void decompile_function(const gsc::function_ptr& func);
|
||||
void decompile_statements(const gsc::function_ptr& func);
|
||||
void decompile_expr();
|
||||
void decompile_ternary();
|
||||
void decompile_block(const gsc::stmt_list_ptr& block);
|
||||
void decompile_search_infinite(const gsc::stmt_list_ptr& block);
|
||||
void decompile_search_loop(const gsc::stmt_list_ptr& block);
|
||||
void decompile_search_switch(const gsc::stmt_list_ptr& block);
|
||||
void decompile_search_ifelse(const gsc::stmt_list_ptr& block);
|
||||
void decompile_break_continue(const gsc::stmt_list_ptr& block);
|
||||
void decompile_if(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_last_ifelse(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_infinite(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_loop(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_while(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_for(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_foreach(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end);
|
||||
void decompile_switch(const gsc::stmt_list_ptr& block, std::uint32_t start);
|
||||
auto find_location_reference(const gsc::stmt_list_ptr& block, std::uint32_t start, std::uint32_t end, const std::string& location) -> bool;
|
||||
auto find_location_index(const gsc::stmt_list_ptr& block, const std::string& location) -> std::uint32_t;
|
||||
auto last_location_index(const gsc::stmt_list_ptr& block, std::uint32_t index) -> bool;
|
||||
void process_stack(const gsc::thread_ptr& thread);
|
||||
void process_parameters(const gsc::context_ptr& ctx, const gsc::parameters_ptr& params);
|
||||
void process_stmt(const gsc::context_ptr& ctx, const gsc::stmt_ptr& stmt);
|
||||
void process_stmt_list(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt);
|
||||
void process_stmt_call(const gsc::context_ptr& ctx, const gsc::stmt_call_ptr& stmt);
|
||||
void process_stmt_assign(const gsc::context_ptr& ctx, const gsc::stmt_assign_ptr& stmt);
|
||||
void process_stmt_endon(const gsc::context_ptr& ctx, const gsc::stmt_endon_ptr& stmt);
|
||||
void process_stmt_notify(const gsc::context_ptr& ctx, const gsc::stmt_notify_ptr& stmt);
|
||||
void process_stmt_wait(const gsc::context_ptr& ctx, const gsc::stmt_wait_ptr& stmt);
|
||||
void process_stmt_waittill(const gsc::context_ptr& ctx, const gsc::stmt_waittill_ptr& stmt);
|
||||
void process_stmt_waittillmatch(const gsc::context_ptr& ctx, const gsc::stmt_waittillmatch_ptr& stmt);
|
||||
void process_stmt_waittillframeend(const gsc::context_ptr& ctx, const gsc::stmt_waittillframeend_ptr& stmt);
|
||||
void process_stmt_if(const gsc::context_ptr& ctx, const gsc::stmt_if_ptr& stmt);
|
||||
void process_stmt_ifelse(const gsc::context_ptr& ctx, const gsc::stmt_ifelse_ptr& stmt);
|
||||
void process_stmt_while(const gsc::context_ptr& ctx, const gsc::stmt_while_ptr& stmt);
|
||||
void process_stmt_for(const gsc::context_ptr& ctx, const gsc::stmt_for_ptr& stmt);
|
||||
void process_stmt_foreach(const gsc::context_ptr& ctx, const gsc::stmt_foreach_ptr& stmt);
|
||||
void process_stmt_switch(const gsc::context_ptr& ctx, const gsc::stmt_switch_ptr& stmt);
|
||||
void process_stmt_cases(const gsc::context_ptr& ctx, const gsc::stmt_list_ptr& stmt);
|
||||
void process_stmt_break(const gsc::context_ptr& ctx, const gsc::stmt_break_ptr& stmt);
|
||||
void process_stmt_return(const gsc::context_ptr& ctx, const gsc::stmt_return_ptr& stmt);
|
||||
void process_expr(const gsc::context_ptr& ctx, gsc::expr_ptr& expr);
|
||||
void process_expr_assign(const gsc::context_ptr& ctx, gsc::expr_assign_ptr& expr);
|
||||
void process_expr_ternary(const gsc::context_ptr& ctx, const gsc::expr_ternary_ptr& expr);
|
||||
void process_expr_binary(const gsc::context_ptr& ctx, const gsc::expr_binary_ptr& expr);
|
||||
void process_expr_and(const gsc::context_ptr& ctx, const gsc::expr_and_ptr& expr);
|
||||
void process_expr_or(const gsc::context_ptr& ctx, const gsc::expr_or_ptr& expr);
|
||||
void process_expr_complement(const gsc::context_ptr& ctx, const gsc::expr_complement_ptr& expr);
|
||||
void process_expr_not(const gsc::context_ptr& ctx, const gsc::expr_not_ptr& expr);
|
||||
void process_expr_call(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void process_expr_call_pointer(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void process_expr_call_function(const gsc::context_ptr& ctx, const gsc::expr_call_ptr& expr);
|
||||
void process_expr_arguments(const gsc::context_ptr& ctx, const gsc::expr_arguments_ptr& arg_list);
|
||||
void process_expr_function(const gsc::context_ptr& ctx, const gsc::expr_function_ptr& node);
|
||||
void process_expr_add_array(const gsc::context_ptr& ctx, const gsc::expr_add_array_ptr& expr);
|
||||
void process_expr_size(const gsc::context_ptr& ctx, const gsc::expr_size_ptr& expr);
|
||||
void process_array_variable(const gsc::context_ptr& ctx, const gsc::expr_array_ptr& expr);
|
||||
void process_field_variable(const gsc::context_ptr& ctx, const gsc::expr_field_ptr& expr);
|
||||
void process_local_variable(const gsc::context_ptr& ctx, const gsc::name_ptr& expr);
|
||||
void process_vector(const gsc::context_ptr& ctx, const gsc::vector_ptr& vec);
|
||||
void process_var_create(const gsc::context_ptr& ctx, gsc::expr_ptr& expr, bool fromstmt = false);
|
||||
void process_var_access(const gsc::context_ptr& ctx, gsc::expr_ptr& expr);
|
||||
void process_var_remove(const gsc::context_ptr& ctx, const gsc::asm_remove_ptr& expr);
|
||||
};
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
644
src/iw8/xsk/disassembler.cpp
Normal file
644
src/iw8/xsk/disassembler.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#include "stdafx.hpp"
|
||||
#include "iw8.hpp"
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
auto disassembler::output() -> std::vector<gsc::function_ptr>
|
||||
{
|
||||
return std::move(functions_);
|
||||
}
|
||||
|
||||
auto disassembler::output_data() -> std::vector<std::uint8_t>
|
||||
{
|
||||
output_ = std::make_unique<utils::byte_buffer>(0x100000);
|
||||
|
||||
output_->write_string("// IW8 PC GSCASM\n");
|
||||
output_->write_string("// Disassembled by https://github.com/xensik/gsc-tool\n");
|
||||
|
||||
for (auto& func : functions_)
|
||||
{
|
||||
this->print_function(func);
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> output;
|
||||
|
||||
output.resize(output_->pos());
|
||||
memcpy(output.data(), output_->buffer().data(), output.size());
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void disassembler::disassemble(const std::string& file, std::vector<std::uint8_t>& script, std::vector<std::uint8_t>& stack)
|
||||
{
|
||||
filename_ = file;
|
||||
script_ = std::make_unique<utils::byte_buffer>(script);
|
||||
stack_ = std::make_unique<utils::byte_buffer>(stack);
|
||||
functions_.clear();
|
||||
|
||||
script_->seek(1);
|
||||
|
||||
while (stack_->is_avail() && script_->is_avail())
|
||||
{
|
||||
functions_.push_back(std::make_unique<gsc::function>());
|
||||
auto& func = functions_.back();
|
||||
|
||||
func->index = static_cast<std::uint32_t>(script_->pos());
|
||||
func->size = stack_->read<std::uint32_t>();
|
||||
func->id = stack_->read<std::uint32_t>();
|
||||
func->name = "sub_"s + (func->id == 0 ? stack_->read_c_string() : resolver::token_name(func->id));
|
||||
|
||||
this->dissasemble_function(func);
|
||||
|
||||
func->labels = labels_;
|
||||
labels_.clear();
|
||||
}
|
||||
|
||||
this->resolve_local_functions();
|
||||
}
|
||||
|
||||
void disassembler::dissasemble_function(const gsc::function_ptr& func)
|
||||
{
|
||||
auto size = func->size;
|
||||
|
||||
while (size > 0)
|
||||
{
|
||||
func->instructions.push_back(std::make_unique<gsc::instruction>());
|
||||
|
||||
auto& inst = func->instructions.back();
|
||||
inst->index = static_cast<std::uint32_t>(script_->pos());
|
||||
inst->opcode = script_->read<std::uint8_t>();
|
||||
inst->size = opcode_size(inst->opcode);
|
||||
|
||||
this->dissasemble_instruction(inst);
|
||||
|
||||
size -= inst->size;
|
||||
}
|
||||
}
|
||||
|
||||
void disassembler::dissasemble_instruction(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
switch (opcode(inst->opcode))
|
||||
{
|
||||
case opcode::OP_CastFieldObject:
|
||||
case opcode::OP_plus:
|
||||
case opcode::OP_GetGameRef:
|
||||
case opcode::OP_GetThisthread:
|
||||
case opcode::OP_greater:
|
||||
case opcode::OP_shift_right:
|
||||
case opcode::OP_dec:
|
||||
case opcode::OP_bit_or:
|
||||
case opcode::OP_equality:
|
||||
case opcode::OP_ClearLocalVariableFieldCached0:
|
||||
case opcode::OP_notify:
|
||||
case opcode::OP_PreScriptCall:
|
||||
case opcode::OP_GetUndefined:
|
||||
case opcode::OP_SetLocalVariableFieldCached0:
|
||||
case opcode::OP_GetLevel:
|
||||
case opcode::OP_size:
|
||||
case opcode::OP_AddArray:
|
||||
case opcode::OP_endon:
|
||||
case opcode::OP_shift_left:
|
||||
case opcode::OP_EvalLocalArrayRefCached0:
|
||||
case opcode::OP_Return:
|
||||
case opcode::OP_SafeSetVariableFieldCached0:
|
||||
case opcode::OP_GetSelfObject:
|
||||
case opcode::OP_GetGame:
|
||||
case opcode::OP_EvalArray:
|
||||
case opcode::OP_GetSelf:
|
||||
case opcode::OP_End:
|
||||
case opcode::OP_less_equal:
|
||||
case opcode::OP_EvalLocalVariableCached0:
|
||||
case opcode::OP_EvalLocalVariableCached1:
|
||||
case opcode::OP_EvalLocalVariableCached2:
|
||||
case opcode::OP_EvalLocalVariableCached3:
|
||||
case opcode::OP_EvalLocalVariableCached4:
|
||||
case opcode::OP_EvalLocalVariableCached5:
|
||||
case opcode::OP_ScriptMethodCallPointer:
|
||||
case opcode::OP_checkclearparams:
|
||||
case opcode::OP_waittillmatch2:
|
||||
case opcode::OP_minus:
|
||||
case opcode::OP_greater_equal:
|
||||
case opcode::OP_vector:
|
||||
case opcode::OP_ClearArray:
|
||||
case opcode::OP_DecTop:
|
||||
case opcode::OP_CastBool:
|
||||
case opcode::OP_EvalArrayRef:
|
||||
case opcode::OP_GetZero:
|
||||
case opcode::OP_wait:
|
||||
case opcode::OP_waittill:
|
||||
case opcode::OP_GetAnimObject:
|
||||
case opcode::OP_mod:
|
||||
case opcode::OP_clearparams:
|
||||
case opcode::OP_ScriptFunctionCallPointer:
|
||||
case opcode::OP_EmptyArray:
|
||||
case opcode::OP_ClearVariableField:
|
||||
case opcode::OP_EvalNewLocalVariableRefCached0:
|
||||
case opcode::OP_BoolComplement:
|
||||
case opcode::OP_less:
|
||||
case opcode::OP_BoolNot:
|
||||
case opcode::OP_waittillFrameEnd:
|
||||
case opcode::OP_waitframe:
|
||||
case opcode::OP_GetLevelObject:
|
||||
case opcode::OP_inc:
|
||||
case opcode::OP_GetAnim:
|
||||
case opcode::OP_SetVariableField:
|
||||
case opcode::OP_divide:
|
||||
case opcode::OP_multiply:
|
||||
case opcode::OP_EvalLocalVariableRefCached0:
|
||||
case opcode::OP_bit_and:
|
||||
case opcode::OP_voidCodepos:
|
||||
case opcode::OP_inequality:
|
||||
case opcode::OP_bit_ex_or:
|
||||
// case opcode::OP_NOP:
|
||||
// case opcode::OP_abort:
|
||||
// case opcode::OP_object:
|
||||
// case opcode::OP_thread_object:
|
||||
case opcode::OP_EvalLocalVariable:
|
||||
case opcode::OP_EvalLocalVariableRef:
|
||||
// case opcode::OP_breakpoint:
|
||||
// case opcode::OP_assignmentBreakpoint:
|
||||
// case opcode::OP_manualAndAssignmentBreakpoint:
|
||||
case opcode::OP_BoolNotAfterAnd:
|
||||
case opcode::OP_IsDefined:
|
||||
case opcode::OP_IsTrue:
|
||||
break;
|
||||
case opcode::OP_GetByte:
|
||||
case opcode::OP_GetNegByte:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
break;
|
||||
case opcode::OP_GetUnsignedShort:
|
||||
case opcode::OP_GetNegUnsignedShort:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint16_t>()));
|
||||
break;
|
||||
case opcode::OP_GetInteger:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::int32_t>()));
|
||||
break;
|
||||
case opcode::OP_GetFloat:
|
||||
{
|
||||
auto val = script_->read<float>();
|
||||
inst->data.push_back(utils::string::va("%g%s", val, val == int(val) ? ".0" : ""));
|
||||
}
|
||||
break;
|
||||
case opcode::OP_GetVector:
|
||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
||||
inst->data.push_back(utils::string::va("%g", script_->read<float>()));
|
||||
break;
|
||||
case opcode::OP_GetString:
|
||||
case opcode::OP_GetIString:
|
||||
script_->seek(4);
|
||||
inst->data.push_back(utils::string::to_literal(stack_->read_c_string()));
|
||||
break;
|
||||
case opcode::OP_GetAnimation:
|
||||
script_->seek(8);
|
||||
inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false));
|
||||
inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false));
|
||||
break;
|
||||
case opcode::OP_GetAnimTree:
|
||||
script_->seek(1);
|
||||
inst->data.push_back(utils::string::quote(stack_->read_c_string().data(), false));
|
||||
break;
|
||||
case opcode::OP_waittillmatch:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint16_t>()));
|
||||
break;
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0:
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0:
|
||||
case opcode::OP_SafeCreateVariableFieldCached:
|
||||
case opcode::OP_ClearLocalVariableFieldCached:
|
||||
case opcode::OP_SetLocalVariableFieldCached:
|
||||
case opcode::OP_RemoveLocalVariables:
|
||||
case opcode::OP_EvalLocalVariableRefCached:
|
||||
case opcode::OP_EvalLocalArrayRefCached:
|
||||
case opcode::OP_SafeSetVariableFieldCached:
|
||||
case opcode::OP_EvalLocalVariableCached:
|
||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||
case opcode::OP_CreateLocalVariable:
|
||||
case opcode::OP_EvalLocalVariableObjectCached:
|
||||
case opcode::OP_EvalLocalArrayCached:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
break;
|
||||
case opcode::OP_EvalSelfFieldVariable:
|
||||
case opcode::OP_SetLevelFieldVariableField:
|
||||
case opcode::OP_ClearFieldVariable:
|
||||
case opcode::OP_EvalFieldVariable:
|
||||
case opcode::OP_EvalFieldVariableRef:
|
||||
case opcode::OP_EvalLevelFieldVariable:
|
||||
case opcode::OP_SetAnimFieldVariableField:
|
||||
case opcode::OP_SetSelfFieldVariableField:
|
||||
case opcode::OP_EvalAnimFieldVariableRef:
|
||||
case opcode::OP_EvalLevelFieldVariableRef:
|
||||
case opcode::OP_EvalAnimFieldVariable:
|
||||
case opcode::OP_EvalSelfFieldVariableRef:
|
||||
this->disassemble_field_variable(inst);
|
||||
break;
|
||||
case opcode::OP_CallBuiltinPointer:
|
||||
case opcode::OP_CallBuiltinMethodPointer:
|
||||
case opcode::OP_ScriptThreadCallPointer:
|
||||
case opcode::OP_ScriptChildThreadCallPointer:
|
||||
case opcode::OP_ScriptMethodThreadCallPointer:
|
||||
case opcode::OP_ScriptMethodChildThreadCallPointer:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
break;
|
||||
case opcode::OP_GetLocalFunction:
|
||||
case opcode::OP_ScriptLocalFunctionCall2:
|
||||
case opcode::OP_ScriptLocalFunctionCall:
|
||||
case opcode::OP_ScriptLocalMethodCall:
|
||||
this->disassemble_local_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_ScriptLocalThreadCall:
|
||||
case opcode::OP_ScriptLocalChildThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodChildThreadCall:
|
||||
this->disassemble_local_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_GetFarFunction:
|
||||
case opcode::OP_ScriptFarFunctionCall2:
|
||||
case opcode::OP_ScriptFarFunctionCall:
|
||||
case opcode::OP_ScriptFarMethodCall:
|
||||
this->disassemble_far_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_ScriptFarThreadCall:
|
||||
case opcode::OP_ScriptFarChildThreadCall:
|
||||
case opcode::OP_ScriptFarMethodThreadCall:
|
||||
case opcode::OP_ScriptFarMethodChildThreadCall:
|
||||
this->disassemble_far_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_CallBuiltin:
|
||||
this->disassemble_builtin_call(inst, false, true);
|
||||
break;
|
||||
case opcode::OP_CallBuiltinMethod:
|
||||
this->disassemble_builtin_call(inst, true, true);
|
||||
break;
|
||||
case opcode::OP_GetBuiltinFunction:
|
||||
case opcode::OP_CallBuiltin0:
|
||||
case opcode::OP_CallBuiltin1:
|
||||
case opcode::OP_CallBuiltin2:
|
||||
case opcode::OP_CallBuiltin3:
|
||||
case opcode::OP_CallBuiltin4:
|
||||
case opcode::OP_CallBuiltin5:
|
||||
this->disassemble_builtin_call(inst, false, false);
|
||||
break;
|
||||
case opcode::OP_GetBuiltinMethod:
|
||||
case opcode::OP_CallBuiltinMethod0:
|
||||
case opcode::OP_CallBuiltinMethod1:
|
||||
case opcode::OP_CallBuiltinMethod2:
|
||||
case opcode::OP_CallBuiltinMethod3:
|
||||
case opcode::OP_CallBuiltinMethod4:
|
||||
case opcode::OP_CallBuiltinMethod5:
|
||||
this->disassemble_builtin_call(inst, true, false);
|
||||
break;
|
||||
case opcode::OP_JumpOnFalse:
|
||||
case opcode::OP_JumpOnTrue:
|
||||
case opcode::OP_JumpOnFalseExpr:
|
||||
case opcode::OP_JumpOnTrueExpr:
|
||||
this->disassemble_jump(inst, true, false);
|
||||
break;
|
||||
case opcode::OP_jumpback:
|
||||
this->disassemble_jump(inst, false, true);
|
||||
break;
|
||||
case opcode::OP_jump:
|
||||
this->disassemble_jump(inst, false, false);
|
||||
break;
|
||||
case opcode::OP_switch:
|
||||
this->disassemble_switch(inst);
|
||||
break;
|
||||
case opcode::OP_endswitch:
|
||||
this->disassemble_end_switch(inst);
|
||||
break;
|
||||
/*
|
||||
case opcode::OP_prof_begin:
|
||||
script_->seek(5); // TODO: skipped data
|
||||
break;
|
||||
case opcode::OP_prof_end:
|
||||
script_->seek(1); // TODO: skipped data
|
||||
break;
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled:
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled:
|
||||
case opcode::OP_CreateLocalVariable_Precompiled:
|
||||
case opcode::OP_SafeCreateVariableFieldCached_Precompiled:
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
break;
|
||||
*/
|
||||
case opcode::OP_FormalParams:
|
||||
case opcode::OP_FormalParams_Precompiled:
|
||||
this->disassemble_formal_params(inst);
|
||||
break;
|
||||
/* case opcode::OP_NativeGetLocalFunction:
|
||||
case opcode::OP_NativeLocalFunctionCall:
|
||||
case opcode::OP_NativeLocalFunctionCall2:
|
||||
case opcode::OP_NativeLocalMethodCall:
|
||||
this->disassemble_local_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_NativeGetFarFunction:
|
||||
case opcode::OP_NativeFarFunctionCall:
|
||||
case opcode::OP_NativeFarFunctionCall2:
|
||||
case opcode::OP_NativeFarMethodCall:
|
||||
this->disassemble_far_call(inst, false);
|
||||
break;
|
||||
case opcode::OP_NativeLocalFunctionThreadCall:
|
||||
case opcode::OP_NativeLocalMethodThreadCall:
|
||||
case opcode::OP_NativeLocalFunctionChildThreadCall:
|
||||
case opcode::OP_NativeLocalMethodChildThreadCall:
|
||||
this->disassemble_local_call(inst, true);
|
||||
break;
|
||||
case opcode::OP_NativeFarFunctionThreadCall:
|
||||
case opcode::OP_NativeFarMethodThreadCall:
|
||||
case opcode::OP_NativeFarFunctionChildThreadCall:
|
||||
case opcode::OP_NativeFarMethodChildThreadCall:
|
||||
this->disassemble_far_call(inst, true);
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
throw gsc::disasm_error(utils::string::va("Unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index));
|
||||
}
|
||||
}
|
||||
|
||||
void disassembler::disassemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num)
|
||||
{
|
||||
if (arg_num)
|
||||
{
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
}
|
||||
|
||||
if (method)
|
||||
{
|
||||
inst->data.push_back(resolver::method_name(script_->read<std::uint16_t>()));
|
||||
}
|
||||
else
|
||||
{
|
||||
inst->data.push_back(resolver::function_name(script_->read<std::uint16_t>()));
|
||||
}
|
||||
}
|
||||
|
||||
void disassembler::disassemble_local_call(const gsc::instruction_ptr& inst, bool thread)
|
||||
{
|
||||
std::int32_t offset = this->disassemble_offset();
|
||||
|
||||
inst->data.push_back(utils::string::va("%X", offset + inst->index + 1));
|
||||
|
||||
if (thread)
|
||||
{
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
}
|
||||
}
|
||||
|
||||
void disassembler::disassemble_far_call(const gsc::instruction_ptr& inst, bool thread)
|
||||
{
|
||||
script_->seek(3);
|
||||
|
||||
if (thread)
|
||||
{
|
||||
inst->data.push_back(utils::string::va("%i", script_->read<std::uint8_t>()));
|
||||
}
|
||||
|
||||
auto file_id = stack_->read<std::uint32_t>();
|
||||
auto file_name = file_id == 0 ? stack_->read_c_string() : resolver::file_name(file_id);
|
||||
auto func_id = stack_->read<std::uint32_t>();
|
||||
auto func_name = func_id == 0 ? stack_->read_c_string() : resolver::token_name(func_id);
|
||||
|
||||
inst->data.push_back(file_name != "" ? file_name : utils::string::va("_ID%i", file_id));
|
||||
inst->data.push_back(func_name != "" ? func_name : utils::string::va("_ID%i", func_id));
|
||||
}
|
||||
|
||||
void disassembler::disassemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back)
|
||||
{
|
||||
std::int32_t addr;
|
||||
std::string label;
|
||||
|
||||
if (expr)
|
||||
{
|
||||
addr = inst->index + 3 + script_->read<std::int16_t>();
|
||||
label = utils::string::va("loc_%X", addr);
|
||||
inst->data.push_back(label);
|
||||
}
|
||||
else if (back)
|
||||
{
|
||||
addr = inst->index + 3 - script_->read<std::uint16_t>();
|
||||
label = utils::string::va("loc_%X", addr);
|
||||
inst->data.push_back(label);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = inst->index + 5 + script_->read<std::int32_t>();
|
||||
label = utils::string::va("loc_%X", addr);
|
||||
inst->data.push_back(label);
|
||||
}
|
||||
|
||||
labels_.insert({addr, label});
|
||||
}
|
||||
|
||||
void disassembler::disassemble_field_variable(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
std::uint32_t field_id = script_->read<std::uint32_t>();
|
||||
std::string field_name;
|
||||
|
||||
if(field_id > 0x13160) // 0xE2C0 or 0x13160
|
||||
{
|
||||
auto temp = stack_->read<std::uint32_t>();
|
||||
field_name = temp == 0 ? stack_->read_c_string() : std::to_string(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
field_name = resolver::token_name(field_id);
|
||||
}
|
||||
|
||||
inst->data.push_back(field_name != "" ? field_name : utils::string::va("_ID%i", field_id));
|
||||
}
|
||||
|
||||
void disassembler::disassemble_formal_params(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
auto size = script_->read<std::uint8_t>();
|
||||
|
||||
inst->size += size;
|
||||
inst->data.push_back(utils::string::va("%i", size));
|
||||
|
||||
while(size > 0)
|
||||
{
|
||||
inst->data.push_back(utils::string::va("%d", script_->read<std::uint8_t>()));
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
void disassembler::disassemble_switch(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
std::int32_t addr = inst->index + 4 + script_->read<std::int32_t>();
|
||||
std::string label = utils::string::va("loc_%X", addr);
|
||||
|
||||
inst->data.push_back(label);
|
||||
labels_.insert({addr, label});
|
||||
}
|
||||
|
||||
void disassembler::disassemble_end_switch(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
std::uint16_t case_num = script_->read<std::uint16_t>();
|
||||
inst->data.push_back(utils::string::va("%i", case_num));
|
||||
|
||||
std::uint32_t internal_index = inst->index + 3;
|
||||
|
||||
if (case_num)
|
||||
{
|
||||
for (auto i = case_num; i > 0; i--)
|
||||
{
|
||||
std::uint32_t case_label = script_->read<std::uint32_t>();
|
||||
|
||||
if (case_label < 0x80000 && case_label > 0)
|
||||
{
|
||||
inst->data.push_back("case");
|
||||
inst->data.push_back(utils::string::quote(stack_->read_c_string(), false));
|
||||
}
|
||||
else if (case_label == 0)
|
||||
{
|
||||
inst->data.push_back("default");
|
||||
stack_->read<std::uint16_t>();
|
||||
}
|
||||
else
|
||||
{
|
||||
inst->data.push_back("case");
|
||||
inst->data.push_back(utils::string::va("%i", (case_label - 0x800000) & 0xFFFFFF));
|
||||
}
|
||||
|
||||
inst->size += 4;
|
||||
internal_index += 4;
|
||||
|
||||
auto addr = this->disassemble_offset() + internal_index;
|
||||
std::string label = utils::string::va("loc_%X", addr);
|
||||
inst->data.push_back(label);
|
||||
|
||||
labels_.insert({addr, label});
|
||||
|
||||
inst->size += 3;
|
||||
internal_index += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto disassembler::disassemble_offset() -> std::int32_t
|
||||
{
|
||||
std::array<std::uint8_t, 4> bytes = {};
|
||||
|
||||
for (auto i = 0; i < 3; i++)
|
||||
{
|
||||
bytes[i] = script_->read<std::uint8_t>();
|
||||
}
|
||||
|
||||
std::int32_t offset = *reinterpret_cast<std::int32_t*>(bytes.data());
|
||||
|
||||
offset = (offset << 8) >> 8;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
void disassembler::resolve_local_functions()
|
||||
{
|
||||
for (auto& func : functions_)
|
||||
{
|
||||
for (auto& inst : func->instructions)
|
||||
{
|
||||
switch (opcode(inst->opcode))
|
||||
{
|
||||
case opcode::OP_GetLocalFunction:
|
||||
case opcode::OP_ScriptLocalFunctionCall:
|
||||
case opcode::OP_ScriptLocalFunctionCall2:
|
||||
case opcode::OP_ScriptLocalMethodCall:
|
||||
case opcode::OP_ScriptLocalThreadCall:
|
||||
case opcode::OP_ScriptLocalChildThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodThreadCall:
|
||||
case opcode::OP_ScriptLocalMethodChildThreadCall:
|
||||
inst->data.at(0) = this->resolve_function(inst->data[0]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto disassembler::resolve_function(const std::string& index) -> std::string
|
||||
{
|
||||
if (utils::string::is_hex_number(index))
|
||||
{
|
||||
std::uint32_t idx = std::stoul(index, nullptr, 16);
|
||||
|
||||
for (auto& func : functions_)
|
||||
{
|
||||
if (func->index == idx)
|
||||
{
|
||||
return func->name;
|
||||
}
|
||||
}
|
||||
|
||||
throw gsc::disasm_error(utils::string::va("Couldn't resolve function name at index '0x%04X'!", idx));
|
||||
}
|
||||
|
||||
throw gsc::disasm_error(utils::string::va("\"%s\" is not valid function address!", index.data()));
|
||||
}
|
||||
|
||||
void disassembler::print_function(const gsc::function_ptr& func)
|
||||
{
|
||||
output_->write_string("\n");
|
||||
output_->write_string(utils::string::va("%s\n", func->name.data()));
|
||||
|
||||
for (auto& inst : func->instructions)
|
||||
{
|
||||
const auto itr = func->labels.find(inst->index);
|
||||
|
||||
if (itr != func->labels.end())
|
||||
{
|
||||
output_->write_string(utils::string::va("\t%s\n", itr->second.data()));
|
||||
}
|
||||
|
||||
this->print_instruction(inst);
|
||||
}
|
||||
|
||||
output_->write_string("\n");
|
||||
output_->write_string(utils::string::va("end_%s\n", func->name.substr(4).data()));
|
||||
}
|
||||
|
||||
void disassembler::print_instruction(const gsc::instruction_ptr& inst)
|
||||
{
|
||||
switch (opcode(inst->opcode))
|
||||
{
|
||||
case opcode::OP_endswitch:
|
||||
output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data()));
|
||||
output_->write_string(utils::string::va(" %s\n", inst->data[0].data()));
|
||||
{
|
||||
std::uint32_t totalcase = std::stoul(inst->data[0]);
|
||||
auto index = 0;
|
||||
for (auto casenum = 0u; casenum < totalcase; casenum++)
|
||||
{
|
||||
if (inst->data[1 + index] == "case")
|
||||
{
|
||||
output_->write_string(utils::string::va("\t\t\t%s %s %s", inst->data[1 + index].data(), inst->data[1 + index + 1].data(), inst->data[1 + index + 2].data()));
|
||||
index += 3;
|
||||
}
|
||||
else if (inst->data[1 + index] == "default")
|
||||
{
|
||||
output_->write_string(utils::string::va("\t\t\t%s %s", inst->data[1 + index].data(), inst->data[1 + index + 1].data()));
|
||||
index += 2;
|
||||
}
|
||||
if (casenum != totalcase - 1)
|
||||
{
|
||||
output_->write_string("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
output_->write_string(utils::string::va("\t\t%s", resolver::opcode_name(inst->opcode).data()));
|
||||
for (auto& d : inst->data)
|
||||
{
|
||||
output_->write_string(utils::string::va(" %s", d.data()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
output_->write_string("\n");
|
||||
}
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
43
src/iw8/xsk/disassembler.hpp
Normal file
43
src/iw8/xsk/disassembler.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
class disassembler : public gsc::disassembler
|
||||
{
|
||||
std::string filename_;
|
||||
utils::byte_buffer_ptr script_;
|
||||
utils::byte_buffer_ptr stack_;
|
||||
utils::byte_buffer_ptr output_;
|
||||
std::vector<gsc::function_ptr> functions_;
|
||||
std::unordered_map<std::uint32_t, std::string> labels_;
|
||||
|
||||
public:
|
||||
auto output() -> std::vector<gsc::function_ptr>;
|
||||
auto output_data() -> std::vector<std::uint8_t>;
|
||||
void disassemble(const std::string& file, std::vector<std::uint8_t>& script, std::vector<std::uint8_t>& stack);
|
||||
|
||||
private:
|
||||
void dissasemble_function(const gsc::function_ptr& func);
|
||||
void dissasemble_instruction(const gsc::instruction_ptr& inst);
|
||||
void disassemble_builtin_call(const gsc::instruction_ptr& inst, bool method, bool arg_num);
|
||||
void disassemble_local_call(const gsc::instruction_ptr& inst, bool thread);
|
||||
void disassemble_far_call(const gsc::instruction_ptr& inst, bool thread);
|
||||
void disassemble_jump(const gsc::instruction_ptr& inst, bool expr, bool back);
|
||||
void disassemble_field_variable(const gsc::instruction_ptr& inst);
|
||||
void disassemble_formal_params(const gsc::instruction_ptr& inst);
|
||||
void disassemble_switch(const gsc::instruction_ptr& inst);
|
||||
void disassemble_end_switch(const gsc::instruction_ptr& inst);
|
||||
auto disassemble_offset() -> std::int32_t;
|
||||
void resolve_local_functions();
|
||||
auto resolve_function(const std::string& index) -> std::string;
|
||||
void print_function(const gsc::function_ptr& func);
|
||||
void print_instruction(const gsc::instruction_ptr& inst);
|
||||
};
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
229
src/iw8/xsk/iw8.cpp
Normal file
229
src/iw8/xsk/iw8.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#include "stdafx.hpp"
|
||||
#include "iw8.hpp"
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
auto opcode_size(std::uint8_t id) -> std::uint32_t
|
||||
{
|
||||
switch (opcode(id))
|
||||
{
|
||||
case opcode::OP_CastFieldObject:
|
||||
case opcode::OP_plus:
|
||||
case opcode::OP_GetGameRef:
|
||||
case opcode::OP_GetThisthread:
|
||||
case opcode::OP_greater:
|
||||
case opcode::OP_shift_right:
|
||||
case opcode::OP_dec:
|
||||
case opcode::OP_bit_or:
|
||||
case opcode::OP_equality:
|
||||
case opcode::OP_ClearLocalVariableFieldCached0:
|
||||
case opcode::OP_notify:
|
||||
case opcode::OP_PreScriptCall:
|
||||
case opcode::OP_GetUndefined:
|
||||
case opcode::OP_SetLocalVariableFieldCached0:
|
||||
case opcode::OP_GetLevel:
|
||||
case opcode::OP_size:
|
||||
case opcode::OP_AddArray:
|
||||
case opcode::OP_endon:
|
||||
case opcode::OP_shift_left:
|
||||
case opcode::OP_EvalLocalArrayRefCached0:
|
||||
case opcode::OP_Return:
|
||||
case opcode::OP_SafeSetVariableFieldCached0:
|
||||
case opcode::OP_GetSelfObject:
|
||||
case opcode::OP_GetGame:
|
||||
case opcode::OP_EvalArray:
|
||||
case opcode::OP_GetSelf:
|
||||
case opcode::OP_End:
|
||||
case opcode::OP_less_equal:
|
||||
case opcode::OP_EvalLocalVariableCached0:
|
||||
case opcode::OP_EvalLocalVariableCached1:
|
||||
case opcode::OP_EvalLocalVariableCached2:
|
||||
case opcode::OP_EvalLocalVariableCached3:
|
||||
case opcode::OP_EvalLocalVariableCached4:
|
||||
case opcode::OP_EvalLocalVariableCached5:
|
||||
case opcode::OP_ScriptMethodCallPointer:
|
||||
case opcode::OP_checkclearparams:
|
||||
case opcode::OP_waittillmatch2:
|
||||
case opcode::OP_minus:
|
||||
case opcode::OP_greater_equal:
|
||||
case opcode::OP_vector:
|
||||
case opcode::OP_ClearArray:
|
||||
case opcode::OP_DecTop:
|
||||
case opcode::OP_CastBool:
|
||||
case opcode::OP_EvalArrayRef:
|
||||
case opcode::OP_GetZero:
|
||||
case opcode::OP_wait:
|
||||
case opcode::OP_waittill:
|
||||
case opcode::OP_GetAnimObject:
|
||||
case opcode::OP_mod:
|
||||
case opcode::OP_clearparams:
|
||||
case opcode::OP_ScriptFunctionCallPointer:
|
||||
case opcode::OP_EmptyArray:
|
||||
case opcode::OP_ClearVariableField:
|
||||
case opcode::OP_EvalNewLocalVariableRefCached0:
|
||||
case opcode::OP_BoolComplement:
|
||||
case opcode::OP_less:
|
||||
case opcode::OP_BoolNot:
|
||||
case opcode::OP_waittillFrameEnd:
|
||||
case opcode::OP_waitframe:
|
||||
case opcode::OP_GetLevelObject:
|
||||
case opcode::OP_inc:
|
||||
case opcode::OP_GetAnim:
|
||||
case opcode::OP_SetVariableField:
|
||||
case opcode::OP_divide:
|
||||
case opcode::OP_multiply:
|
||||
case opcode::OP_EvalLocalVariableRefCached0:
|
||||
case opcode::OP_bit_and:
|
||||
case opcode::OP_voidCodepos:
|
||||
case opcode::OP_inequality:
|
||||
case opcode::OP_bit_ex_or:
|
||||
/*
|
||||
case opcode::OP_NOP:
|
||||
case opcode::OP_abort:
|
||||
case opcode::OP_object:
|
||||
case opcode::OP_thread_object:
|
||||
case opcode::OP_EvalLocalVariable:
|
||||
case opcode::OP_EvalLocalVariableRef:
|
||||
case opcode::OP_breakpoint:
|
||||
case opcode::OP_assignmentBreakpoint:
|
||||
case opcode::OP_manualAndAssignmentBreakpoint:
|
||||
*/
|
||||
case opcode::OP_BoolNotAfterAnd:
|
||||
case opcode::OP_IsDefined:
|
||||
case opcode::OP_IsTrue:
|
||||
return 1;
|
||||
case opcode::OP_SetLocalVariableFieldCached:
|
||||
case opcode::OP_RemoveLocalVariables:
|
||||
case opcode::OP_ScriptMethodChildThreadCallPointer:
|
||||
case opcode::OP_GetByte:
|
||||
case opcode::OP_SafeSetWaittillVariableFieldCached:
|
||||
case opcode::OP_CreateLocalVariable:
|
||||
case opcode::OP_CallBuiltinMethodPointer:
|
||||
case opcode::OP_EvalLocalVariableCached:
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0:
|
||||
case opcode::OP_ScriptChildThreadCallPointer:
|
||||
case opcode::OP_EvalLocalVariableObjectCached:
|
||||
case opcode::OP_GetNegByte:
|
||||
case opcode::OP_SafeCreateVariableFieldCached:
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0:
|
||||
case opcode::OP_GetAnimTree:
|
||||
case opcode::OP_EvalLocalArrayCached:
|
||||
case opcode::OP_ScriptMethodThreadCallPointer:
|
||||
case opcode::OP_SafeSetVariableFieldCached:
|
||||
case opcode::OP_EvalLocalVariableRefCached:
|
||||
case opcode::OP_ScriptThreadCallPointer:
|
||||
case opcode::OP_ClearLocalVariableFieldCached:
|
||||
case opcode::OP_EvalLocalArrayRefCached:
|
||||
case opcode::OP_CallBuiltinPointer:
|
||||
// case opcode::OP_prof_end:
|
||||
case opcode::OP_FormalParams:
|
||||
/*
|
||||
case opcode::OP_EvalNewLocalArrayRefCached0_Precompiled:
|
||||
case opcode::OP_SetNewLocalVariableFieldCached0_Precompiled:
|
||||
case opcode::OP_CreateLocalVariable_Precompiled:
|
||||
case opcode::OP_SafeCreateVariableFieldCached_Precompiled:
|
||||
case opcode::OP_FormalParams_Precompiled:
|
||||
*/
|
||||
return 2;
|
||||
case opcode::OP_waittillmatch:
|
||||
case opcode::OP_JumpOnTrue:
|
||||
case opcode::OP_JumpOnFalseExpr:
|
||||
case opcode::OP_jumpback:
|
||||
case opcode::OP_JumpOnTrueExpr:
|
||||
case opcode::OP_CallBuiltin0:
|
||||
case opcode::OP_CallBuiltin1:
|
||||
case opcode::OP_CallBuiltin2:
|
||||
case opcode::OP_CallBuiltin3:
|
||||
case opcode::OP_CallBuiltin4:
|
||||
case opcode::OP_CallBuiltin5:
|
||||
case opcode::OP_GetBuiltinFunction:
|
||||
case opcode::OP_GetNegUnsignedShort:
|
||||
case opcode::OP_GetBuiltinMethod:
|
||||
case opcode::OP_endswitch:
|
||||
case opcode::OP_GetUnsignedShort:
|
||||
case opcode::OP_JumpOnFalse:
|
||||
case opcode::OP_CallBuiltinMethod0:
|
||||
case opcode::OP_CallBuiltinMethod1:
|
||||
case opcode::OP_CallBuiltinMethod2:
|
||||
case opcode::OP_CallBuiltinMethod3:
|
||||
case opcode::OP_CallBuiltinMethod4:
|
||||
case opcode::OP_CallBuiltinMethod5:
|
||||
return 3;
|
||||
case opcode::OP_CallBuiltin:
|
||||
case opcode::OP_ScriptLocalMethodCall:
|
||||
case opcode::OP_ScriptLocalFunctionCall2:
|
||||
case opcode::OP_ScriptFarFunctionCall:
|
||||
case opcode::OP_ScriptFarFunctionCall2:
|
||||
case opcode::OP_CallBuiltinMethod:
|
||||
case opcode::OP_GetLocalFunction:
|
||||
case opcode::OP_GetFarFunction:
|
||||
case opcode::OP_ScriptFarMethodCall:
|
||||
case opcode::OP_ScriptLocalFunctionCall:
|
||||
/*
|
||||
case opcode::OP_NativeGetLocalFunction:
|
||||
case opcode::OP_NativeLocalFunctionCall:
|
||||
case opcode::OP_NativeLocalFunctionCall2:
|
||||
case opcode::OP_NativeLocalMethodCall:
|
||||
case opcode::OP_NativeGetFarFunction:
|
||||
case opcode::OP_NativeFarFunctionCall:
|
||||
case opcode::OP_NativeFarFunctionCall2:
|
||||
case opcode::OP_NativeFarMethodCall:
|
||||
*/
|
||||
return 4;
|
||||
case opcode::OP_EvalSelfFieldVariableRef:
|
||||
case opcode::OP_ScriptFarMethodChildThreadCall:
|
||||
case opcode::OP_EvalAnimFieldVariable:
|
||||
case opcode::OP_EvalLevelFieldVariableRef:
|
||||
case opcode::OP_ScriptFarThreadCall:
|
||||
case opcode::OP_SetSelfFieldVariableField:
|
||||
case opcode::OP_ClearFieldVariable:
|
||||
case opcode::OP_ScriptLocalMethodThreadCall:
|
||||
case opcode::OP_EvalFieldVariable:
|
||||
case opcode::OP_ScriptLocalChildThreadCall:
|
||||
case opcode::OP_SetLevelFieldVariableField:
|
||||
case opcode::OP_EvalSelfFieldVariable:
|
||||
case opcode::OP_ScriptLocalThreadCall:
|
||||
case opcode::OP_GetInteger:
|
||||
case opcode::OP_SetAnimFieldVariableField:
|
||||
case opcode::OP_GetIString:
|
||||
case opcode::OP_ScriptFarMethodThreadCall:
|
||||
case opcode::OP_EvalFieldVariableRef:
|
||||
case opcode::OP_ScriptLocalMethodChildThreadCall:
|
||||
case opcode::OP_GetFloat:
|
||||
case opcode::OP_GetString:
|
||||
case opcode::OP_EvalLevelFieldVariable:
|
||||
case opcode::OP_switch:
|
||||
case opcode::OP_ScriptFarChildThreadCall:
|
||||
case opcode::OP_EvalAnimFieldVariableRef:
|
||||
case opcode::OP_jump:
|
||||
/*
|
||||
case opcode::OP_NativeLocalFunctionThreadCall:
|
||||
case opcode::OP_NativeLocalMethodThreadCall:
|
||||
case opcode::OP_NativeLocalFunctionChildThreadCall:
|
||||
case opcode::OP_NativeLocalMethodChildThreadCall:
|
||||
case opcode::OP_NativeFarFunctionThreadCall:
|
||||
case opcode::OP_NativeFarMethodThreadCall:
|
||||
case opcode::OP_NativeFarFunctionChildThreadCall:
|
||||
case opcode::OP_NativeFarMethodChildThreadCall:
|
||||
*/
|
||||
return 5;
|
||||
/*
|
||||
case opcode::OP_prof_begin:
|
||||
return 6;
|
||||
*/
|
||||
case opcode::OP_GetAnimation:
|
||||
return 9;
|
||||
case opcode::OP_GetVector:
|
||||
return 13;
|
||||
default:
|
||||
throw std::runtime_error("Couldn't resolve instruction size for " + std::to_string(id));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
216
src/iw8/xsk/iw8.hpp
Normal file
216
src/iw8/xsk/iw8.hpp
Normal file
@ -0,0 +1,216 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utils/xsk/utils.hpp"
|
||||
|
||||
#include "assembler.hpp"
|
||||
#include "disassembler.hpp"
|
||||
#include "compiler.hpp"
|
||||
#include "decompiler.hpp"
|
||||
#include "resolver.hpp"
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
enum class opcode : std::uint8_t
|
||||
{
|
||||
OP_CastFieldObject = 0x0,
|
||||
OP_SetLocalVariableFieldCached = 0x1,
|
||||
OP_plus = 0x2,
|
||||
OP_RemoveLocalVariables = 0x3,
|
||||
OP_EvalSelfFieldVariableRef = 0x4,
|
||||
OP_ScriptFarMethodChildThreadCall = 0x5,
|
||||
OP_GetGameRef = 0x6,
|
||||
OP_EvalAnimFieldVariable = 0x7,
|
||||
OP_EvalLevelFieldVariableRef = 0x8,
|
||||
OP_GetThisthread = 0x9,
|
||||
OP_greater = 0xA,
|
||||
OP_waittillmatch = 0xB,
|
||||
OP_shift_right = 0xC,
|
||||
OP_dec = 0xD,
|
||||
OP_JumpOnTrue = 0xE,
|
||||
OP_bit_or = 0xF,
|
||||
OP_equality = 0x10,
|
||||
OP_ClearLocalVariableFieldCached0 = 0x11,
|
||||
OP_notify = 0x12,
|
||||
OP_GetVector = 0x13,
|
||||
OP_ScriptMethodChildThreadCallPointer = 0x14,
|
||||
OP_PreScriptCall = 0x15,
|
||||
OP_GetByte = 0x16,
|
||||
OP_ScriptFarThreadCall = 0x17,
|
||||
OP_SetSelfFieldVariableField = 0x18,
|
||||
OP_JumpOnFalseExpr = 0x19,
|
||||
OP_GetUndefined = 0x1A,
|
||||
OP_jumpback = 0x1B,
|
||||
OP_JumpOnTrueExpr = 0x1C,
|
||||
OP_CallBuiltin0 = 0x1D,
|
||||
OP_CallBuiltin1 = 0x1E,
|
||||
OP_CallBuiltin2 = 0x1F,
|
||||
OP_CallBuiltin3 = 0x20,
|
||||
OP_CallBuiltin4 = 0x21,
|
||||
OP_CallBuiltin5 = 0x22,
|
||||
OP_CallBuiltin = 0x23,
|
||||
OP_SetLocalVariableFieldCached0 = 0x24,
|
||||
OP_ClearFieldVariable = 0x25,
|
||||
OP_GetLevel = 0x26,
|
||||
OP_size = 0x27,
|
||||
OP_SafeSetWaittillVariableFieldCached = 0x28,
|
||||
OP_ScriptLocalMethodThreadCall = 0x29,
|
||||
OP_AddArray = 0x2A,
|
||||
OP_endon = 0x2B,
|
||||
OP_EvalFieldVariable = 0x2C,
|
||||
OP_shift_left = 0x2D,
|
||||
OP_EvalLocalArrayRefCached0 = 0x2E,
|
||||
OP_Return = 0x2F,
|
||||
OP_CreateLocalVariable = 0x30,
|
||||
OP_SafeSetVariableFieldCached0 = 0x31,
|
||||
OP_GetBuiltinFunction = 0x32,
|
||||
OP_ScriptLocalMethodCall = 0x33,
|
||||
OP_CallBuiltinMethodPointer = 0x34,
|
||||
OP_ScriptLocalChildThreadCall = 0x35,
|
||||
OP_GetSelfObject = 0x36,
|
||||
OP_GetGame = 0x37,
|
||||
OP_SetLevelFieldVariableField = 0x38,
|
||||
OP_EvalArray = 0x39,
|
||||
OP_GetSelf = 0x3A,
|
||||
OP_End = 0x3B,
|
||||
OP_EvalSelfFieldVariable = 0x3C,
|
||||
OP_less_equal = 0x3D,
|
||||
OP_EvalLocalVariableCached0 = 0x3E,
|
||||
OP_EvalLocalVariableCached1 = 0x3F,
|
||||
OP_EvalLocalVariableCached2 = 0x40,
|
||||
OP_EvalLocalVariableCached3 = 0x41,
|
||||
OP_EvalLocalVariableCached4 = 0x42,
|
||||
OP_EvalLocalVariableCached5 = 0x43,
|
||||
OP_EvalLocalVariableCached = 0x44,
|
||||
OP_EvalNewLocalArrayRefCached0 = 0x45,
|
||||
OP_ScriptChildThreadCallPointer = 0x46,
|
||||
OP_EvalLocalVariableObjectCached = 0x47,
|
||||
OP_ScriptLocalThreadCall = 0x48,
|
||||
OP_GetInteger = 0x49,
|
||||
OP_ScriptMethodCallPointer = 0x4A,
|
||||
OP_checkclearparams = 0x4B,
|
||||
OP_SetAnimFieldVariableField = 0x4C,
|
||||
OP_waittillmatch2 = 0x4D,
|
||||
OP_minus = 0x4E,
|
||||
OP_ScriptLocalFunctionCall2 = 0x4F,
|
||||
OP_GetNegUnsignedShort = 0x50,
|
||||
OP_GetNegByte = 0x51,
|
||||
OP_SafeCreateVariableFieldCached = 0x52,
|
||||
OP_greater_equal = 0x53,
|
||||
OP_vector = 0x54,
|
||||
OP_GetBuiltinMethod = 0x55,
|
||||
OP_endswitch = 0x56,
|
||||
OP_ClearArray = 0x57,
|
||||
OP_DecTop = 0x58,
|
||||
OP_CastBool = 0x59,
|
||||
OP_EvalArrayRef = 0x5A,
|
||||
OP_SetNewLocalVariableFieldCached0 = 0x5B,
|
||||
OP_GetZero = 0x5C,
|
||||
OP_wait = 0x5D,
|
||||
OP_waittill = 0x5E,
|
||||
OP_GetIString = 0x5F,
|
||||
OP_ScriptFarFunctionCall = 0x60,
|
||||
OP_GetAnimObject = 0x61,
|
||||
OP_GetAnimTree = 0x62,
|
||||
OP_EvalLocalArrayCached = 0x63,
|
||||
OP_mod = 0x64,
|
||||
OP_ScriptFarMethodThreadCall = 0x65,
|
||||
OP_GetUnsignedShort = 0x66,
|
||||
OP_clearparams = 0x67,
|
||||
OP_ScriptMethodThreadCallPointer = 0x68,
|
||||
OP_ScriptFunctionCallPointer = 0x69,
|
||||
OP_EmptyArray = 0x6A,
|
||||
OP_SafeSetVariableFieldCached = 0x6B,
|
||||
OP_ClearVariableField = 0x6C,
|
||||
OP_EvalFieldVariableRef = 0x6D,
|
||||
OP_ScriptLocalMethodChildThreadCall = 0x6E,
|
||||
OP_EvalNewLocalVariableRefCached0 = 0x6F,
|
||||
OP_GetFloat = 0x70,
|
||||
OP_EvalLocalVariableRefCached = 0x71,
|
||||
OP_JumpOnFalse = 0x72,
|
||||
OP_BoolComplement = 0x73,
|
||||
OP_ScriptThreadCallPointer = 0x74,
|
||||
OP_ScriptFarFunctionCall2 = 0x75,
|
||||
OP_less = 0x76,
|
||||
OP_BoolNot = 0x77,
|
||||
OP_waittillFrameEnd = 0x78,
|
||||
OP_waitframe = 0x79,
|
||||
OP_GetString = 0x7A,
|
||||
OP_EvalLevelFieldVariable = 0x7B,
|
||||
OP_GetLevelObject = 0x7C,
|
||||
OP_inc = 0x7D,
|
||||
OP_CallBuiltinMethod0 = 0x7E,
|
||||
OP_CallBuiltinMethod1 = 0x7F,
|
||||
OP_CallBuiltinMethod2 = 0x80,
|
||||
OP_CallBuiltinMethod3 = 0x81,
|
||||
OP_CallBuiltinMethod4 = 0x82,
|
||||
OP_CallBuiltinMethod5 = 0x83,
|
||||
OP_CallBuiltinMethod = 0x84,
|
||||
OP_GetAnim = 0x85,
|
||||
OP_switch = 0x86,
|
||||
OP_SetVariableField = 0x87,
|
||||
OP_divide = 0x88,
|
||||
OP_GetLocalFunction = 0x89,
|
||||
OP_ScriptFarChildThreadCall = 0x8A,
|
||||
OP_multiply = 0x8B,
|
||||
OP_ClearLocalVariableFieldCached = 0x8C,
|
||||
OP_EvalAnimFieldVariableRef = 0x8D,
|
||||
OP_EvalLocalArrayRefCached = 0x8E,
|
||||
OP_EvalLocalVariableRefCached0 = 0x8F,
|
||||
OP_bit_and = 0x90,
|
||||
OP_GetAnimation = 0x91,
|
||||
OP_GetFarFunction = 0x92,
|
||||
OP_CallBuiltinPointer = 0x93,
|
||||
OP_jump = 0x94,
|
||||
OP_voidCodepos = 0x95,
|
||||
OP_ScriptFarMethodCall = 0x96,
|
||||
OP_inequality = 0x97,
|
||||
OP_ScriptLocalFunctionCall = 0x98,
|
||||
OP_bit_ex_or = 0x99,
|
||||
OP_NOP = 0x9A,
|
||||
OP_abort = 0x9B,
|
||||
OP_object = 0x9C,
|
||||
OP_thread_object = 0x9D,
|
||||
OP_EvalLocalVariable = 0x9E,
|
||||
OP_EvalLocalVariableRef = 0x9F,
|
||||
OP_prof_begin = 0xA0,
|
||||
OP_prof_end = 0xA1,
|
||||
OP_breakpoint = 0xA2,
|
||||
OP_assignmentBreakpoint = 0xA3,
|
||||
OP_manualAndAssignmentBreakpoint = 0xA4,
|
||||
OP_BoolNotAfterAnd = 0xA5,
|
||||
OP_FormalParams = 0xA6,
|
||||
OP_IsDefined = 0xA7,
|
||||
OP_IsTrue = 0xA8,
|
||||
OP_NativeGetLocalFunction = 0xA9,
|
||||
OP_NativeLocalFunctionCall = 0xAA,
|
||||
OP_NativeLocalFunctionCall2 = 0xAB,
|
||||
OP_NativeLocalMethodCall = 0xAC,
|
||||
OP_NativeLocalFunctionThreadCall = 0xAD,
|
||||
OP_NativeLocalMethodThreadCall = 0xAE,
|
||||
OP_NativeLocalFunctionChildThreadCall = 0xAF,
|
||||
OP_NativeLocalMethodChildThreadCall = 0xB0,
|
||||
OP_NativeGetFarFunction = 0xB1,
|
||||
OP_NativeFarFunctionCall = 0xB2,
|
||||
OP_NativeFarFunctionCall2 = 0xB3,
|
||||
OP_NativeFarMethodCall = 0xB4,
|
||||
OP_NativeFarFunctionThreadCall = 0xB5,
|
||||
OP_NativeFarMethodThreadCall = 0xB6,
|
||||
OP_NativeFarFunctionChildThreadCall = 0xB7,
|
||||
OP_NativeFarMethodChildThreadCall = 0xB8,
|
||||
OP_EvalNewLocalArrayRefCached0_Precompiled = 0xB9,
|
||||
OP_SetNewLocalVariableFieldCached0_Precompiled = 0xBA,
|
||||
OP_CreateLocalVariable_Precompiled = 0xBB,
|
||||
OP_SafeCreateVariableFieldCached_Precompiled = 0xBC,
|
||||
OP_FormalParams_Precompiled = 0xBD,
|
||||
OP_count = 0xBE,
|
||||
};
|
||||
|
||||
auto opcode_size(std::uint8_t op) -> std::uint32_t;
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
2882
src/iw8/xsk/lexer.cpp
Normal file
2882
src/iw8/xsk/lexer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
708
src/iw8/xsk/lexer.hpp
Normal file
708
src/iw8/xsk/lexer.hpp
Normal file
@ -0,0 +1,708 @@
|
||||
#ifndef iw8_HEADER_H
|
||||
#define iw8_HEADER_H 1
|
||||
#define iw8_IN_HEADER 1
|
||||
|
||||
#line 5 "lexer.hpp"
|
||||
#include "stdafx.hpp"
|
||||
#include "iw8.hpp"
|
||||
#include "parser.hpp"
|
||||
using namespace xsk::gsc;
|
||||
|
||||
#line 11 "lexer.hpp"
|
||||
|
||||
#define YY_INT_ALIGNED short int
|
||||
|
||||
/* A lexical scanner generated by flex */
|
||||
|
||||
#define FLEX_SCANNER
|
||||
#define YY_FLEX_MAJOR_VERSION 2
|
||||
#define YY_FLEX_MINOR_VERSION 6
|
||||
#define YY_FLEX_SUBMINOR_VERSION 4
|
||||
#if YY_FLEX_SUBMINOR_VERSION > 0
|
||||
#define FLEX_BETA
|
||||
#endif
|
||||
|
||||
#ifdef yy_create_buffer
|
||||
#define iw8__create_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_create_buffer iw8__create_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yy_delete_buffer
|
||||
#define iw8__delete_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_delete_buffer iw8__delete_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yy_scan_buffer
|
||||
#define iw8__scan_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_scan_buffer iw8__scan_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yy_scan_string
|
||||
#define iw8__scan_string_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_scan_string iw8__scan_string
|
||||
#endif
|
||||
|
||||
#ifdef yy_scan_bytes
|
||||
#define iw8__scan_bytes_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_scan_bytes iw8__scan_bytes
|
||||
#endif
|
||||
|
||||
#ifdef yy_init_buffer
|
||||
#define iw8__init_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_init_buffer iw8__init_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yy_flush_buffer
|
||||
#define iw8__flush_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_flush_buffer iw8__flush_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yy_load_buffer_state
|
||||
#define iw8__load_buffer_state_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_load_buffer_state iw8__load_buffer_state
|
||||
#endif
|
||||
|
||||
#ifdef yy_switch_to_buffer
|
||||
#define iw8__switch_to_buffer_ALREADY_DEFINED
|
||||
#else
|
||||
#define yy_switch_to_buffer iw8__switch_to_buffer
|
||||
#endif
|
||||
|
||||
#ifdef yypush_buffer_state
|
||||
#define iw8_push_buffer_state_ALREADY_DEFINED
|
||||
#else
|
||||
#define yypush_buffer_state iw8_push_buffer_state
|
||||
#endif
|
||||
|
||||
#ifdef yypop_buffer_state
|
||||
#define iw8_pop_buffer_state_ALREADY_DEFINED
|
||||
#else
|
||||
#define yypop_buffer_state iw8_pop_buffer_state
|
||||
#endif
|
||||
|
||||
#ifdef yyensure_buffer_stack
|
||||
#define iw8_ensure_buffer_stack_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyensure_buffer_stack iw8_ensure_buffer_stack
|
||||
#endif
|
||||
|
||||
#ifdef yylex
|
||||
#define iw8_lex_ALREADY_DEFINED
|
||||
#else
|
||||
#define yylex iw8_lex
|
||||
#endif
|
||||
|
||||
#ifdef yyrestart
|
||||
#define iw8_restart_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyrestart iw8_restart
|
||||
#endif
|
||||
|
||||
#ifdef yylex_init
|
||||
#define iw8_lex_init_ALREADY_DEFINED
|
||||
#else
|
||||
#define yylex_init iw8_lex_init
|
||||
#endif
|
||||
|
||||
#ifdef yylex_init_extra
|
||||
#define iw8_lex_init_extra_ALREADY_DEFINED
|
||||
#else
|
||||
#define yylex_init_extra iw8_lex_init_extra
|
||||
#endif
|
||||
|
||||
#ifdef yylex_destroy
|
||||
#define iw8_lex_destroy_ALREADY_DEFINED
|
||||
#else
|
||||
#define yylex_destroy iw8_lex_destroy
|
||||
#endif
|
||||
|
||||
#ifdef yyget_debug
|
||||
#define iw8_get_debug_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_debug iw8_get_debug
|
||||
#endif
|
||||
|
||||
#ifdef yyset_debug
|
||||
#define iw8_set_debug_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_debug iw8_set_debug
|
||||
#endif
|
||||
|
||||
#ifdef yyget_extra
|
||||
#define iw8_get_extra_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_extra iw8_get_extra
|
||||
#endif
|
||||
|
||||
#ifdef yyset_extra
|
||||
#define iw8_set_extra_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_extra iw8_set_extra
|
||||
#endif
|
||||
|
||||
#ifdef yyget_in
|
||||
#define iw8_get_in_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_in iw8_get_in
|
||||
#endif
|
||||
|
||||
#ifdef yyset_in
|
||||
#define iw8_set_in_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_in iw8_set_in
|
||||
#endif
|
||||
|
||||
#ifdef yyget_out
|
||||
#define iw8_get_out_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_out iw8_get_out
|
||||
#endif
|
||||
|
||||
#ifdef yyset_out
|
||||
#define iw8_set_out_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_out iw8_set_out
|
||||
#endif
|
||||
|
||||
#ifdef yyget_leng
|
||||
#define iw8_get_leng_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_leng iw8_get_leng
|
||||
#endif
|
||||
|
||||
#ifdef yyget_text
|
||||
#define iw8_get_text_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_text iw8_get_text
|
||||
#endif
|
||||
|
||||
#ifdef yyget_lineno
|
||||
#define iw8_get_lineno_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_lineno iw8_get_lineno
|
||||
#endif
|
||||
|
||||
#ifdef yyset_lineno
|
||||
#define iw8_set_lineno_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_lineno iw8_set_lineno
|
||||
#endif
|
||||
|
||||
#ifdef yyget_column
|
||||
#define iw8_get_column_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyget_column iw8_get_column
|
||||
#endif
|
||||
|
||||
#ifdef yyset_column
|
||||
#define iw8_set_column_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyset_column iw8_set_column
|
||||
#endif
|
||||
|
||||
#ifdef yywrap
|
||||
#define iw8_wrap_ALREADY_DEFINED
|
||||
#else
|
||||
#define yywrap iw8_wrap
|
||||
#endif
|
||||
|
||||
#ifdef yyalloc
|
||||
#define iw8_alloc_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyalloc iw8_alloc
|
||||
#endif
|
||||
|
||||
#ifdef yyrealloc
|
||||
#define iw8_realloc_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyrealloc iw8_realloc
|
||||
#endif
|
||||
|
||||
#ifdef yyfree
|
||||
#define iw8_free_ALREADY_DEFINED
|
||||
#else
|
||||
#define yyfree iw8_free
|
||||
#endif
|
||||
|
||||
/* First, we deal with platform-specific or compiler-specific issues. */
|
||||
|
||||
/* begin standard C headers. */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* end standard C headers. */
|
||||
|
||||
/* flex integer type definitions */
|
||||
|
||||
#ifndef FLEXINT_H
|
||||
#define FLEXINT_H
|
||||
|
||||
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
|
||||
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
|
||||
/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
|
||||
* if you want the limit (max/min) macros for int types.
|
||||
*/
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
typedef int8_t flex_int8_t;
|
||||
typedef uint8_t flex_uint8_t;
|
||||
typedef int16_t flex_int16_t;
|
||||
typedef uint16_t flex_uint16_t;
|
||||
typedef int32_t flex_int32_t;
|
||||
typedef uint32_t flex_uint32_t;
|
||||
#else
|
||||
typedef signed char flex_int8_t;
|
||||
typedef short int flex_int16_t;
|
||||
typedef int flex_int32_t;
|
||||
typedef unsigned char flex_uint8_t;
|
||||
typedef unsigned short int flex_uint16_t;
|
||||
typedef unsigned int flex_uint32_t;
|
||||
|
||||
/* Limits of integral types. */
|
||||
#ifndef INT8_MIN
|
||||
#define INT8_MIN (-128)
|
||||
#endif
|
||||
#ifndef INT16_MIN
|
||||
#define INT16_MIN (-32767-1)
|
||||
#endif
|
||||
#ifndef INT32_MIN
|
||||
#define INT32_MIN (-2147483647-1)
|
||||
#endif
|
||||
#ifndef INT8_MAX
|
||||
#define INT8_MAX (127)
|
||||
#endif
|
||||
#ifndef INT16_MAX
|
||||
#define INT16_MAX (32767)
|
||||
#endif
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (2147483647)
|
||||
#endif
|
||||
#ifndef UINT8_MAX
|
||||
#define UINT8_MAX (255U)
|
||||
#endif
|
||||
#ifndef UINT16_MAX
|
||||
#define UINT16_MAX (65535U)
|
||||
#endif
|
||||
#ifndef UINT32_MAX
|
||||
#define UINT32_MAX (4294967295U)
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX (~(size_t)0)
|
||||
#endif
|
||||
|
||||
#endif /* ! C99 */
|
||||
|
||||
#endif /* ! FLEXINT_H */
|
||||
|
||||
/* begin standard C++ headers. */
|
||||
|
||||
/* TODO: this is always defined, so inline it */
|
||||
#define yyconst const
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
#define yynoreturn __attribute__((__noreturn__))
|
||||
#else
|
||||
#define yynoreturn
|
||||
#endif
|
||||
|
||||
/* An opaque pointer. */
|
||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
||||
#define YY_TYPEDEF_YY_SCANNER_T
|
||||
typedef void* yyscan_t;
|
||||
#endif
|
||||
|
||||
/* For convenience, these vars (plus the bison vars far below)
|
||||
are macros in the reentrant scanner. */
|
||||
#define yyin yyg->yyin_r
|
||||
#define yyout yyg->yyout_r
|
||||
#define yyextra yyg->yyextra_r
|
||||
#define yyleng yyg->yyleng_r
|
||||
#define yytext yyg->yytext_r
|
||||
#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
|
||||
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
|
||||
#define yy_flex_debug yyg->yy_flex_debug_r
|
||||
|
||||
/* Size of default input buffer. */
|
||||
#ifndef YY_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k.
|
||||
* Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
|
||||
* Ditto for the __ia64__ case accordingly.
|
||||
*/
|
||||
#define YY_BUF_SIZE 32768
|
||||
#else
|
||||
#define YY_BUF_SIZE 16384
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
|
||||
#define YY_TYPEDEF_YY_BUFFER_STATE
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
#endif
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_SIZE_T
|
||||
#define YY_TYPEDEF_YY_SIZE_T
|
||||
typedef size_t yy_size_t;
|
||||
#endif
|
||||
|
||||
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
||||
#define YY_STRUCT_YY_BUFFER_STATE
|
||||
struct yy_buffer_state
|
||||
{
|
||||
FILE *yy_input_file;
|
||||
|
||||
char *yy_ch_buf; /* input buffer */
|
||||
char *yy_buf_pos; /* current position in input buffer */
|
||||
|
||||
/* Size of input buffer in bytes, not including room for EOB
|
||||
* characters.
|
||||
*/
|
||||
int yy_buf_size;
|
||||
|
||||
/* Number of characters read into yy_ch_buf, not including EOB
|
||||
* characters.
|
||||
*/
|
||||
int yy_n_chars;
|
||||
|
||||
/* Whether we "own" the buffer - i.e., we know we created it,
|
||||
* and can realloc() it to grow it, and should free() it to
|
||||
* delete it.
|
||||
*/
|
||||
int yy_is_our_buffer;
|
||||
|
||||
/* Whether this is an "interactive" input source; if so, and
|
||||
* if we're using stdio for input, then we want to use getc()
|
||||
* instead of fread(), to make sure we stop fetching input after
|
||||
* each newline.
|
||||
*/
|
||||
int yy_is_interactive;
|
||||
|
||||
/* Whether we're considered to be at the beginning of a line.
|
||||
* If so, '^' rules will be active on the next match, otherwise
|
||||
* not.
|
||||
*/
|
||||
int yy_at_bol;
|
||||
|
||||
int yy_bs_lineno; /**< The line count. */
|
||||
int yy_bs_column; /**< The column count. */
|
||||
|
||||
/* Whether to try to fill the input buffer when we reach the
|
||||
* end of it.
|
||||
*/
|
||||
int yy_fill_buffer;
|
||||
|
||||
int yy_buffer_status;
|
||||
|
||||
};
|
||||
#endif /* !YY_STRUCT_YY_BUFFER_STATE */
|
||||
|
||||
void yyrestart ( FILE *input_file , yyscan_t yyscanner );
|
||||
void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
|
||||
void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
|
||||
void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
|
||||
void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
|
||||
void yypop_buffer_state ( yyscan_t yyscanner );
|
||||
|
||||
YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t yyscanner );
|
||||
|
||||
void *yyalloc ( yy_size_t , yyscan_t yyscanner );
|
||||
void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
|
||||
void yyfree ( void * , yyscan_t yyscanner );
|
||||
|
||||
/* Begin user sect3 */
|
||||
|
||||
#define iw8_wrap(yyscanner) (/*CONSTCOND*/1)
|
||||
#define YY_SKIP_YYWRAP
|
||||
|
||||
#define yytext_ptr yytext_r
|
||||
|
||||
#ifdef YY_HEADER_EXPORT_START_CONDITIONS
|
||||
#define INITIAL 0
|
||||
#define COMMENT_BLOCK_STATE 1
|
||||
#define DEVELOPER_BLOCK_STATE 2
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_UNISTD_H
|
||||
/* Special case for "unistd.h", since it is non-ANSI. We include it way
|
||||
* down here because we want the user's section 1 to have been scanned first.
|
||||
* The user has a chance to override it with an option.
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef YY_EXTRA_TYPE
|
||||
#define YY_EXTRA_TYPE void *
|
||||
#endif
|
||||
|
||||
int yylex_init (yyscan_t* scanner);
|
||||
|
||||
int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
|
||||
|
||||
/* Accessor methods to globals.
|
||||
These are made visible to non-reentrant scanners for convenience. */
|
||||
|
||||
int yylex_destroy ( yyscan_t yyscanner );
|
||||
|
||||
int yyget_debug ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_debug ( int debug_flag , yyscan_t yyscanner );
|
||||
|
||||
YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
|
||||
|
||||
FILE *yyget_in ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_in ( FILE * _in_str , yyscan_t yyscanner );
|
||||
|
||||
FILE *yyget_out ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_out ( FILE * _out_str , yyscan_t yyscanner );
|
||||
|
||||
int yyget_leng ( yyscan_t yyscanner );
|
||||
|
||||
char *yyget_text ( yyscan_t yyscanner );
|
||||
|
||||
int yyget_lineno ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_lineno ( int _line_number , yyscan_t yyscanner );
|
||||
|
||||
int yyget_column ( yyscan_t yyscanner );
|
||||
|
||||
void yyset_column ( int _column_no , yyscan_t yyscanner );
|
||||
|
||||
/* Macros after this point can all be overridden by user definitions in
|
||||
* section 1.
|
||||
*/
|
||||
|
||||
#ifndef YY_SKIP_YYWRAP
|
||||
#ifdef __cplusplus
|
||||
extern "C" int yywrap ( yyscan_t yyscanner );
|
||||
#else
|
||||
extern int yywrap ( yyscan_t yyscanner );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef yytext_ptr
|
||||
static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifdef YY_NEED_STRLEN
|
||||
static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#ifndef YY_NO_INPUT
|
||||
|
||||
#endif
|
||||
|
||||
/* Amount of stuff to slurp up with each read. */
|
||||
#ifndef YY_READ_BUF_SIZE
|
||||
#ifdef __ia64__
|
||||
/* On IA-64, the buffer size is 16k, not 8k */
|
||||
#define YY_READ_BUF_SIZE 16384
|
||||
#else
|
||||
#define YY_READ_BUF_SIZE 8192
|
||||
#endif /* __ia64__ */
|
||||
#endif
|
||||
|
||||
/* Number of entries by which start-condition stack grows. */
|
||||
#ifndef YY_START_STACK_INCR
|
||||
#define YY_START_STACK_INCR 25
|
||||
#endif
|
||||
|
||||
/* Default declaration of generated scanner - a define so the user can
|
||||
* easily add parameters.
|
||||
*/
|
||||
#ifndef YY_DECL
|
||||
#define YY_DECL_IS_OURS 1
|
||||
|
||||
extern int yylex (yyscan_t yyscanner);
|
||||
|
||||
#define YY_DECL int yylex (yyscan_t yyscanner)
|
||||
#endif /* !YY_DECL */
|
||||
|
||||
/* yy_get_previous_state - get the state just before the EOB char was reached */
|
||||
|
||||
#undef YY_NEW_FILE
|
||||
#undef YY_FLUSH_BUFFER
|
||||
#undef yy_set_bol
|
||||
#undef yy_new_buffer
|
||||
#undef yy_set_interactive
|
||||
#undef YY_DO_BEFORE_ACTION
|
||||
|
||||
#ifdef YY_DECL_IS_OURS
|
||||
#undef YY_DECL_IS_OURS
|
||||
#undef YY_DECL
|
||||
#endif
|
||||
|
||||
#ifndef iw8__create_buffer_ALREADY_DEFINED
|
||||
#undef yy_create_buffer
|
||||
#endif
|
||||
#ifndef iw8__delete_buffer_ALREADY_DEFINED
|
||||
#undef yy_delete_buffer
|
||||
#endif
|
||||
#ifndef iw8__scan_buffer_ALREADY_DEFINED
|
||||
#undef yy_scan_buffer
|
||||
#endif
|
||||
#ifndef iw8__scan_string_ALREADY_DEFINED
|
||||
#undef yy_scan_string
|
||||
#endif
|
||||
#ifndef iw8__scan_bytes_ALREADY_DEFINED
|
||||
#undef yy_scan_bytes
|
||||
#endif
|
||||
#ifndef iw8__init_buffer_ALREADY_DEFINED
|
||||
#undef yy_init_buffer
|
||||
#endif
|
||||
#ifndef iw8__flush_buffer_ALREADY_DEFINED
|
||||
#undef yy_flush_buffer
|
||||
#endif
|
||||
#ifndef iw8__load_buffer_state_ALREADY_DEFINED
|
||||
#undef yy_load_buffer_state
|
||||
#endif
|
||||
#ifndef iw8__switch_to_buffer_ALREADY_DEFINED
|
||||
#undef yy_switch_to_buffer
|
||||
#endif
|
||||
#ifndef iw8_push_buffer_state_ALREADY_DEFINED
|
||||
#undef yypush_buffer_state
|
||||
#endif
|
||||
#ifndef iw8_pop_buffer_state_ALREADY_DEFINED
|
||||
#undef yypop_buffer_state
|
||||
#endif
|
||||
#ifndef iw8_ensure_buffer_stack_ALREADY_DEFINED
|
||||
#undef yyensure_buffer_stack
|
||||
#endif
|
||||
#ifndef iw8_lex_ALREADY_DEFINED
|
||||
#undef yylex
|
||||
#endif
|
||||
#ifndef iw8_restart_ALREADY_DEFINED
|
||||
#undef yyrestart
|
||||
#endif
|
||||
#ifndef iw8_lex_init_ALREADY_DEFINED
|
||||
#undef yylex_init
|
||||
#endif
|
||||
#ifndef iw8_lex_init_extra_ALREADY_DEFINED
|
||||
#undef yylex_init_extra
|
||||
#endif
|
||||
#ifndef iw8_lex_destroy_ALREADY_DEFINED
|
||||
#undef yylex_destroy
|
||||
#endif
|
||||
#ifndef iw8_get_debug_ALREADY_DEFINED
|
||||
#undef yyget_debug
|
||||
#endif
|
||||
#ifndef iw8_set_debug_ALREADY_DEFINED
|
||||
#undef yyset_debug
|
||||
#endif
|
||||
#ifndef iw8_get_extra_ALREADY_DEFINED
|
||||
#undef yyget_extra
|
||||
#endif
|
||||
#ifndef iw8_set_extra_ALREADY_DEFINED
|
||||
#undef yyset_extra
|
||||
#endif
|
||||
#ifndef iw8_get_in_ALREADY_DEFINED
|
||||
#undef yyget_in
|
||||
#endif
|
||||
#ifndef iw8_set_in_ALREADY_DEFINED
|
||||
#undef yyset_in
|
||||
#endif
|
||||
#ifndef iw8_get_out_ALREADY_DEFINED
|
||||
#undef yyget_out
|
||||
#endif
|
||||
#ifndef iw8_set_out_ALREADY_DEFINED
|
||||
#undef yyset_out
|
||||
#endif
|
||||
#ifndef iw8_get_leng_ALREADY_DEFINED
|
||||
#undef yyget_leng
|
||||
#endif
|
||||
#ifndef iw8_get_text_ALREADY_DEFINED
|
||||
#undef yyget_text
|
||||
#endif
|
||||
#ifndef iw8_get_lineno_ALREADY_DEFINED
|
||||
#undef yyget_lineno
|
||||
#endif
|
||||
#ifndef iw8_set_lineno_ALREADY_DEFINED
|
||||
#undef yyset_lineno
|
||||
#endif
|
||||
#ifndef iw8_get_column_ALREADY_DEFINED
|
||||
#undef yyget_column
|
||||
#endif
|
||||
#ifndef iw8_set_column_ALREADY_DEFINED
|
||||
#undef yyset_column
|
||||
#endif
|
||||
#ifndef iw8_wrap_ALREADY_DEFINED
|
||||
#undef yywrap
|
||||
#endif
|
||||
#ifndef iw8_get_lval_ALREADY_DEFINED
|
||||
#undef yyget_lval
|
||||
#endif
|
||||
#ifndef iw8_set_lval_ALREADY_DEFINED
|
||||
#undef yyset_lval
|
||||
#endif
|
||||
#ifndef iw8_get_lloc_ALREADY_DEFINED
|
||||
#undef yyget_lloc
|
||||
#endif
|
||||
#ifndef iw8_set_lloc_ALREADY_DEFINED
|
||||
#undef yyset_lloc
|
||||
#endif
|
||||
#ifndef iw8_alloc_ALREADY_DEFINED
|
||||
#undef yyalloc
|
||||
#endif
|
||||
#ifndef iw8_realloc_ALREADY_DEFINED
|
||||
#undef yyrealloc
|
||||
#endif
|
||||
#ifndef iw8_free_ALREADY_DEFINED
|
||||
#undef yyfree
|
||||
#endif
|
||||
#ifndef iw8_text_ALREADY_DEFINED
|
||||
#undef yytext
|
||||
#endif
|
||||
#ifndef iw8_leng_ALREADY_DEFINED
|
||||
#undef yyleng
|
||||
#endif
|
||||
#ifndef iw8_in_ALREADY_DEFINED
|
||||
#undef yyin
|
||||
#endif
|
||||
#ifndef iw8_out_ALREADY_DEFINED
|
||||
#undef yyout
|
||||
#endif
|
||||
#ifndef iw8__flex_debug_ALREADY_DEFINED
|
||||
#undef yy_flex_debug
|
||||
#endif
|
||||
#ifndef iw8_lineno_ALREADY_DEFINED
|
||||
#undef yylineno
|
||||
#endif
|
||||
#ifndef iw8_tables_fload_ALREADY_DEFINED
|
||||
#undef yytables_fload
|
||||
#endif
|
||||
#ifndef iw8_tables_destroy_ALREADY_DEFINED
|
||||
#undef yytables_destroy
|
||||
#endif
|
||||
#ifndef iw8_TABLES_NAME_ALREADY_DEFINED
|
||||
#undef yyTABLES_NAME
|
||||
#endif
|
||||
|
||||
#line 155 "lexer.lpp"
|
||||
|
||||
|
||||
#line 706 "lexer.hpp"
|
||||
#undef iw8_IN_HEADER
|
||||
#endif /* iw8_HEADER_H */
|
4116
src/iw8/xsk/parser.cpp
Normal file
4116
src/iw8/xsk/parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4918
src/iw8/xsk/parser.hpp
Normal file
4918
src/iw8/xsk/parser.hpp
Normal file
File diff suppressed because it is too large
Load Diff
75544
src/iw8/xsk/resolver.cpp
Normal file
75544
src/iw8/xsk/resolver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
33
src/iw8/xsk/resolver.hpp
Normal file
33
src/iw8/xsk/resolver.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2021 xensik. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a GNU GPLv3 license
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace xsk::gsc::iw8
|
||||
{
|
||||
|
||||
class resolver
|
||||
{
|
||||
public:
|
||||
static auto opcode_id(const std::string& name) -> std::uint8_t;
|
||||
static auto opcode_name(std::uint8_t id) -> std::string;
|
||||
|
||||
static auto function_id(const std::string& name) -> std::uint16_t;
|
||||
static auto function_name(std::uint16_t id) -> std::string;
|
||||
|
||||
static auto method_id(const std::string& name) -> std::uint16_t;
|
||||
static auto method_name(std::uint16_t id) -> std::string;
|
||||
|
||||
static auto file_id(const std::string& name) -> std::uint32_t;
|
||||
static auto file_name(std::uint32_t id) -> std::string;
|
||||
|
||||
static auto token_id(const std::string& name) -> std::uint32_t;
|
||||
static auto token_name(std::uint32_t id) -> std::string;
|
||||
|
||||
static auto find_function(const std::string& name) -> bool;
|
||||
static auto find_method(const std::string& name) -> bool;
|
||||
};
|
||||
|
||||
} // namespace xsk::gsc::iw8
|
@ -8,6 +8,7 @@
|
||||
#include "iw5/xsk/iw5.hpp"
|
||||
#include "iw6/xsk/iw6.hpp"
|
||||
#include "iw7/xsk/iw7.hpp"
|
||||
#include "iw8/xsk/iw8.hpp"
|
||||
#include "s1/xsk/s1.hpp"
|
||||
#include "s2/xsk/s2.hpp"
|
||||
#include "h1/xsk/h1.hpp"
|
||||
@ -17,7 +18,7 @@ namespace xsk::gsc
|
||||
{
|
||||
|
||||
enum class mode { __, ASM, DISASM, COMP, DECOMP };
|
||||
enum class game { __, IW5, IW6, IW7, S1, S2, H1, H2 };
|
||||
enum class game { __, IW5, IW6, IW7, IW8, S1, S2, H1, H2 };
|
||||
|
||||
std::map<std::string, mode> modes =
|
||||
{
|
||||
@ -32,6 +33,7 @@ std::map<std::string, game> games =
|
||||
{ "-iw5", game::IW5 },
|
||||
{ "-iw6", game::IW6 },
|
||||
{ "-iw7", game::IW7 },
|
||||
{ "-iw8", game::IW8 },
|
||||
{ "-s1", game::S1 },
|
||||
{ "-s2", game::S2 },
|
||||
{ "-h1", game::H1 },
|
||||
@ -71,6 +73,7 @@ auto choose_resolver_file_name(uint32_t id, game& game) -> std::string
|
||||
case game::IW5: return iw5::resolver::file_name(static_cast<std::uint16_t>(id));
|
||||
case game::IW6: return iw6::resolver::file_name(static_cast<std::uint16_t>(id));
|
||||
case game::IW7: return iw7::resolver::file_name(id);
|
||||
case game::IW8: return iw8::resolver::file_name(id);
|
||||
case game::S1: return s1::resolver::file_name(static_cast<std::uint16_t>(id));
|
||||
case game::S2: return s2::resolver::file_name(static_cast<std::uint16_t>(id));
|
||||
case game::H1: return h1::resolver::file_name(static_cast<std::uint16_t>(id));
|
||||
@ -417,6 +420,11 @@ std::uint32_t main(std::uint32_t argc, char** argv)
|
||||
iw7::assembler assembler;
|
||||
assemble_file(assembler, file, zonetool);
|
||||
}
|
||||
else if (game == game::IW8)
|
||||
{
|
||||
iw8::assembler assembler;
|
||||
assemble_file(assembler, file, zonetool);
|
||||
}
|
||||
else if (game == game::S1)
|
||||
{
|
||||
s1::assembler assembler;
|
||||
@ -455,6 +463,11 @@ std::uint32_t main(std::uint32_t argc, char** argv)
|
||||
iw7::disassembler disassembler;
|
||||
disassemble_file(disassembler, file, game, zonetool);
|
||||
}
|
||||
else if (game == game::IW8)
|
||||
{
|
||||
iw8::disassembler disassembler;
|
||||
disassemble_file(disassembler, file, game, zonetool);
|
||||
}
|
||||
else if (game == game::S1)
|
||||
{
|
||||
s1::disassembler disassembler;
|
||||
@ -496,6 +509,12 @@ std::uint32_t main(std::uint32_t argc, char** argv)
|
||||
iw7::compiler compiler;
|
||||
compile_file(assembler, compiler, file ,zonetool);
|
||||
}
|
||||
else if (game == game::IW8)
|
||||
{
|
||||
iw8::assembler assembler;
|
||||
iw8::compiler compiler;
|
||||
compile_file(assembler, compiler, file ,zonetool);
|
||||
}
|
||||
else if (game == game::S1)
|
||||
{
|
||||
s1::assembler assembler;
|
||||
@ -541,6 +560,12 @@ std::uint32_t main(std::uint32_t argc, char** argv)
|
||||
iw7::decompiler decompiler;
|
||||
decompile_file(disassembler, decompiler, file, game, zonetool);
|
||||
}
|
||||
else if (game == game::IW8)
|
||||
{
|
||||
iw8::disassembler disassembler;
|
||||
iw8::decompiler decompiler;
|
||||
decompile_file(disassembler, decompiler, file, game, zonetool);
|
||||
}
|
||||
else if (game == game::S1)
|
||||
{
|
||||
s1::disassembler disassembler;
|
||||
|
Reference in New Issue
Block a user