refactor(global): headers & arc module (#86)

This commit is contained in:
Xenxo Espasandín
2023-03-02 16:41:32 +01:00
committed by GitHub
parent 1bca247808
commit f6ae955f34
214 changed files with 201183 additions and 906 deletions

View File

@ -0,0 +1,208 @@
// Copyright 2023 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::arc
{
constexpr usize opcode_count = 143;
enum class opcode : u8
{
OP_Invalid,
OP_End,
OP_Return,
OP_GetUndefined,
OP_GetZero,
OP_GetByte,
OP_GetNegByte,
OP_GetUnsignedShort,
OP_GetNegUnsignedShort,
OP_GetInteger,
OP_GetFloat,
OP_GetString,
OP_GetIString,
OP_GetVector,
OP_GetLevelObject,
OP_GetAnimObject,
OP_GetSelf,
OP_GetLevel,
OP_GetGame,
OP_GetAnim,
OP_GetAnimation,
OP_GetGameRef,
OP_GetFunction,
OP_CreateLocalVariable,
OP_SafeCreateLocalVariables,
OP_RemoveLocalVariables,
OP_EvalLocalVariableCached,
OP_EvalArray,
OP_EvalLocalArrayRefCached,
OP_EvalArrayRef,
OP_ClearArray,
OP_EmptyArray,
OP_GetSelfObject,
OP_EvalFieldVariable,
OP_EvalFieldVariableRef,
OP_ClearFieldVariable,
OP_SafeSetVariableFieldCached,
OP_SafeSetWaittillVariableFieldCached,
OP_ClearParams,
OP_CheckClearParams,
OP_EvalLocalVariableRefCached,
OP_SetVariableField,
OP_CallBuiltin,
OP_CallBuiltinMethod,
OP_Wait,
OP_WaitTillFrameEnd,
OP_PreScriptCall,
OP_ScriptFunctionCall,
OP_ScriptFunctionCallPointer,
OP_ScriptMethodCall,
OP_ScriptMethodCallPointer,
OP_ScriptThreadCall,
OP_ScriptThreadCallPointer,
OP_ScriptMethodThreadCall,
OP_ScriptMethodThreadCallPointer,
OP_DecTop,
OP_CastFieldObject,
OP_CastBool,
OP_BoolNot,
OP_BoolComplement,
OP_JumpOnFalse,
OP_JumpOnTrue,
OP_JumpOnFalseExpr,
OP_JumpOnTrueExpr,
OP_Jump,
OP_JumpBack,
OP_Inc,
OP_Dec,
OP_Bit_Or,
OP_Bit_Xor,
OP_Bit_And,
OP_Equal,
OP_NotEqual,
OP_LessThan,
OP_GreaterThan,
OP_LessThanOrEqualTo,
OP_GreaterThanOrEqualTo,
OP_ShiftLeft,
OP_ShiftRight,
OP_Plus,
OP_Minus,
OP_Multiply,
OP_Divide,
OP_Modulus,
OP_SizeOf,
OP_WaitTillMatch,
OP_WaitTill,
OP_Notify,
OP_EndOn,
OP_VoidCodePos,
OP_Switch,
OP_EndSwitch,
OP_Vector,
OP_GetHash,
OP_RealWait,
OP_VectorConstant,
OP_IsDefined,
OP_VectorScale,
OP_AnglesToUp,
OP_AnglesToRight,
OP_AnglesToForward,
OP_AngleClamp180,
OP_VectorToAngles,
OP_Abs,
OP_GetTime,
OP_GetDvar,
OP_GetDvarInt,
OP_GetDvarFloat,
OP_GetDvarVector,
OP_GetDvarColorRed,
OP_GetDvarColorGreen,
OP_GetDvarColorBlue,
OP_GetDvarColorAlpha,
OP_FirstArrayKey,
OP_NextArrayKey,
OP_ProfileStart,
OP_ProfileStop,
OP_SafeDecTop,
OP_Nop,
OP_Abort,
OP_Object,
OP_ThreadObject,
OP_EvalLocalVariable,
OP_EvalLocalVariableRef,
OP_DevblockBegin,
OP_DevblockEnd,
OP_EvalLocalVariableCachedDebug,
OP_EvalLocalVariableRefCachedDebug,
OP_LevelEvalFieldVariable,
OP_LevelEvalFieldVariableRef,
OP_SelfEvalFieldVariable,
OP_SelfEvalFieldVariableRef,
OP_GetWorld,
OP_GetWorldObject,
OP_GetClasses,
OP_GetClassesObject,
OP_New,
OP_ScriptFunctionCallClass,
OP_ScriptThreadCallClass,
OP_GetUintptr,
OP_SuperEqual,
OP_SuperNotEqual,
OP_GetAPIFunction,
OP_Count,
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
u32 index;
u32 size;
opcode opcode;
std::vector<std::string> data;
};
struct function
{
using ptr = std::unique_ptr<function>;
u32 index;
u32 size;
u8 params;
u8 flags;
std::string name;
std::string space;
std::vector<instruction::ptr> instructions;
std::unordered_map<u32, std::string> labels;
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<std::string> includes;
std::vector<function::ptr> functions;
};
inline auto make_instruction() -> std::unique_ptr<instruction>
{
return std::unique_ptr<instruction>(new instruction);
}
inline auto make_function() -> std::unique_ptr<function>
{
return std::unique_ptr<function>(new function);
}
inline auto make_assembly() -> std::unique_ptr<assembly>
{
return std::unique_ptr<assembly>(new assembly);
}
} // namespace xsk::arc

View File

@ -0,0 +1,119 @@
// Copyright 2023 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::arc
{
constexpr usize header_size_32 = 64;
constexpr usize header_size_64 = 72;
struct header
{
u64 magic;
u32 source_crc;
u32 include_offset;
u32 animtree_offset;
u32 cseg_offset;
u32 stringtablefixup_offset;
u32 devblock_stringtablefixup_offset;
u32 exports_offset;
u32 imports_offset;
u32 fixup_offset;
u32 profile_offset;
u32 cseg_size;
u32 name;
u16 stringtablefixup_count;
u16 exports_count;
u16 imports_count;
u16 fixup_count;
u16 profile_count;
u16 devblock_stringtablefixup_count;
u8 include_count;
u8 animtree_count;
u8 flags;
};
enum class import_flags : u8
{
none = 0,
func_reference = 1,
func_call = 2,
func_call_thread = 3,
meth_call = 4,
meth_call_thread = 5,
developer = 0x10,
unk = 0x20, // T7, T8, T9
};
struct import_ref
{
using ptr = std::shared_ptr<import_ref>;
std::string space;
std::string name;
u8 params;
u8 flags;
std::vector<u32> refs;
};
enum class export_flags : u8
{
export_none = 0x00,
export_public = 0x01,
export_autoexec = 0x02,
export_private = 0x04,
export_codecall = 0x08,
export_private2 = 0x10,
export_varargs = 0x20,
};
struct export_ref
{
using ptr = std::shared_ptr<export_ref>;
std::string space;
std::string name;
u32 checksum;
u32 offset;
u32 size;
u8 params;
u8 flags;
};
enum class string_type : u8
{
literal = 0,
canonical = 1,
};
struct string_ref
{
using ptr = std::shared_ptr<string_ref>;
std::string name;
u8 type;
std::vector<u32> refs;
};
struct animation_ref
{
using ptr = std::shared_ptr<animation_ref>;
std::string name;
u32 ref;
};
struct animtree_ref
{
using ptr = std::shared_ptr<animtree_ref>;
std::string name;
std::vector<u32> refs;
std::vector<animation_ref> anims;
};
} // namespace xsk::arc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
// Copyright 2023 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::arc
{
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
} // namespace xsk::arc

View File

@ -0,0 +1,47 @@
// Copyright 2023 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::arc
{
class error : public std::runtime_error
{
public:
error(std::string const& what);
};
class asm_error : public std::runtime_error
{
public:
asm_error(std::string const& what);
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(std::string const& what);
};
class ppr_error : public std::runtime_error
{
public:
ppr_error(location const& loc, std::string const& what);
};
class comp_error : public std::runtime_error
{
public:
comp_error(location const& loc, std::string const& what);
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(std::string const& what);
};
} // namespace xsk::arc

View File

@ -0,0 +1,177 @@
// Copyright 2023 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::arc
{
class position
{
public:
typedef const std::string filename_type;
typedef int counter_type;
filename_type *filename;
counter_type line;
counter_type column;
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
line = l;
column = c;
}
void lines(counter_type count = 1)
{
if (count)
{
column = 1;
line = add_(line, count, 1);
}
}
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
private:
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
class location
{
public:
typedef position::filename_type filename_type;
typedef position::counter_type counter_type;
position begin;
position end;
location(const position &b, const position &e)
: begin(b), end(e) {}
explicit location(const position &p = position())
: begin(p), end(p) {}
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
void step()
{
begin = end;
}
void columns(counter_type count = 1)
{
end += count;
}
void lines(counter_type count = 1)
{
end.lines(count);
}
auto print() const -> std::string
{
return fmt::format("{}:{}:{}", *begin.filename, begin.line, begin.column);
}
auto label() const -> std::string
{
return fmt::format("loc_{:X}", begin.line);
}
};
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
inline location operator+(location res, const location &end)
{
return res += end;
}
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // namespace xsk::arc

View File

@ -0,0 +1,97 @@
// Copyright 2023 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 "asset.hpp"
#include "assembly.hpp"
#include "buffer.hpp"
#include "location.hpp"
#include "exception.hpp"
#include "ast.hpp"
namespace xsk::arc
{
enum class instance : u8
{
server,
client,
};
enum class build : u8
{
dev,
prod,
};
enum class endian : u8
{
little,
big,
};
enum class system : u8
{
pc,
ps3,
xb2,
};
enum class engine : u8
{
t6,
t7,
t8,
t9,
};
struct props
{
enum values : u32
{
none = 0 << 0,
version2 = 1 << 0,
};
props(values value) : value_(value) {}
operator values() { return value_; }
operator bool() { return value_ != values::none; }
props::values operator|(props::values rhs) const { return static_cast<props::values>(value_ | rhs); }
props::values operator&(props::values rhs) const { return static_cast<props::values>(value_ & rhs); }
friend props::values operator|(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) | static_cast<std::underlying_type<props::values>::type>(rhs));
}
friend props::values operator&(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) & static_cast<std::underlying_type<props::values>::type>(rhs));
}
private:
values value_;
};
enum class switch_type
{
none,
integer,
string,
};
struct locjmp
{
std::string end;
std::string cnt;
std::string brk;
bool is_dev;
};
// fordward decl for modules ref
class context;
} // namespace xsk::arc

View File

@ -0,0 +1,69 @@
// Copyright 2023 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 "common/types.hpp"
#include "source.hpp"
#include "disassembler.hpp"
#include "decompiler.hpp"
namespace xsk::arc
{
class context
{
public:
using fs_callback = std::function<std::vector<u8>(std::string const&)>;
context(props props, engine engine, endian endian, system system, u64 magic);
auto props() const -> props { return props_; }
auto build() const -> build { return build_; }
auto engine() const -> engine { return engine_; }
auto endian() const -> endian { return endian_; }
auto system() const -> system { return system_; }
auto instance() const -> instance { return instance_; }
auto magic() const -> u64 { return magic_; }
auto source() -> source& { return source_; }
auto disassembler() -> disassembler& { return disassembler_; }
auto decompiler() -> decompiler& { return decompiler_; }
auto init(arc::build build, fs_callback callback) -> void;
auto cleanup() -> void;
auto engine_name() const -> std::string_view;
auto opcode_size(opcode op) const -> u32;
auto opcode_id(opcode op) const -> u8;
auto opcode_name(opcode op) const -> std::string;
auto opcode_enum(std::string const& name) const -> opcode;
auto opcode_enum(u16 id) const -> opcode;
auto dvar_id(std::string const& name) const -> u32;
auto dvar_name(u32 id) const -> std::string;
auto hash_id(std::string const& name) const -> u32;
auto hash_name(u32 id) const -> std::string;
protected:
arc::props props_;
arc::build build_;
arc::engine engine_;
arc::endian endian_;
arc::system system_;
arc::instance instance_;
u64 magic_;
arc::source source_;
arc::disassembler disassembler_;
arc::decompiler decompiler_;
fs_callback fs_callback_;
std::unordered_map<opcode, std::string_view> opcode_map_;
std::unordered_map<std::string_view, opcode> opcode_map_rev_;
std::unordered_map<u16, opcode> code_map_;
std::unordered_map<opcode, u8> code_map_rev_;
std::unordered_map<u32, std::string_view> dvar_map_;
std::unordered_map<u32, std::string_view> hash_map_;
};
} // namespace xsk::arc

View File

@ -0,0 +1,107 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::arc
{
class decompiler
{
context const* ctx_;
program::ptr program_;
decl_function::ptr func_;
std::unordered_set<std::string> vars_;
std::unordered_map<u32, std::string> labels_;
std::vector<std::string> expr_labels_;
std::vector<std::string> tern_labels_;
std::vector<std::string> locals_;
std::stack<node::ptr> stack_;
locjmp locs_;
bool in_waittill_;
bool retbool_;
public:
decompiler(context const* ctx);
auto decompile(assembly const& data) -> program::ptr;
private:
auto decompile_function(function const& func) -> void;
auto decompile_instruction(instruction const& inst, bool last) -> void;
auto decompile_expressions(instruction const& inst) -> void;
auto decompile_statements(stmt_list& stm) -> void;
auto decompile_infinites(stmt_list& stm) -> void;
auto decompile_loops(stmt_list& stm) -> void;
auto decompile_switches(stmt_list& stm) -> void;
auto decompile_ifelses(stmt_list& stm) -> void;
auto decompile_aborts(stmt_list& stm) -> void;
auto decompile_devblocks(stmt_list& stm) -> void;
auto decompile_if(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_inf(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_loop(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_while(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_dowhile(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_for(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_foreach(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_switch(stmt_list& stm, usize begin, usize end) -> void;
auto find_location_reference(stmt_list const& stm, usize begin, usize end, std::string const& loc) -> bool;
auto find_location_index(stmt_list const& stm, std::string const& loc) -> usize;
auto last_location_index(stmt_list const& stm, usize index) -> bool;
auto lvalues_match(stmt_assign const& stm1, stmt_assign const& stm2) -> bool;
auto resolve_label(std::string const& name) -> u32;
auto process_function(decl_function& func) -> void;
auto process_stmt(stmt& stm) -> void;
auto process_stmt_list(stmt_list& stm) -> void;
auto process_stmt_comp(stmt_comp& stm) -> void;
auto process_stmt_dev(stmt_dev& stm) -> void;
auto process_stmt_expr(stmt_expr& stm) -> void;
auto process_stmt_call(stmt_call& stm) -> void;
auto process_stmt_assign(stmt_assign& stm) -> void;
auto process_stmt_endon(stmt_endon& stm) -> void;
auto process_stmt_notify(stmt_notify& stm) -> void;
auto process_stmt_realwait(stmt_realwait& stm) -> void;
auto process_stmt_wait(stmt_wait& stm) -> void;
auto process_stmt_waittill(stmt_waittill& stm) -> void;
auto process_stmt_waittillmatch(stmt_waittillmatch& stm) -> void;
auto process_stmt_if(stmt_if& stm) -> void;
auto process_stmt_ifelse(stmt_ifelse& stm) -> void;
auto process_stmt_while(stmt_while& stm) -> void;
auto process_stmt_dowhile(stmt_dowhile& stm) -> void;
auto process_stmt_for(stmt_for& stm) -> void;
auto process_stmt_foreach(stmt_foreach& stm) -> void;
auto process_stmt_switch(stmt_switch& stm) -> void;
auto process_stmt_break(stmt_break& stm) -> void;
auto process_stmt_continue(stmt_continue& stm) -> void;
auto process_stmt_return(stmt_return& stm) -> void;
auto process_expr(expr& exp) -> void;
auto process_expr_assign(expr_assign::ptr& exp) -> void;
auto process_expr_increment(expr_increment& exp) -> void;
auto process_expr_decrement(expr_decrement& exp) -> void;
auto process_expr_ternary(expr_ternary& exp) -> void;
auto process_expr_binary(expr_binary& exp) -> void;
auto process_expr_and(expr_and& exp) -> void;
auto process_expr_or(expr_or& exp) -> void;
auto process_expr_complement(expr_complement& exp) -> void;
auto process_expr_not(expr_not& exp) -> void;
auto process_expr_call(expr_call& exp) -> void;
auto process_expr_method(expr_method& exp) -> void;
auto process_expr_call_member(expr_member& exp) -> void;
auto process_expr_call_pointer(expr_pointer& exp) -> void;
auto process_expr_call_function(expr_function& exp) -> void;
auto process_expr_method_pointer(expr_pointer& exp, expr& obj) -> void;
auto process_expr_method_function(expr_function& exp, expr& obj) -> void;
auto process_expr_parameters(expr_parameters& exp) -> void;
auto process_expr_arguments(expr_arguments& exp) -> void;
auto process_expr_size(expr_size& exp) -> void;
auto process_expr_array(expr_array& exp) -> void;
auto process_expr_field(expr_field& exp) -> void;
auto process_expr_vector(expr_vector& exp) -> void;
auto process_expr_identifier(expr_identifier& exp) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,44 @@
// Copyright 2023 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 "common/types.hpp"
#include "xsk/utils/reader.hpp"
namespace xsk::arc
{
class disassembler
{
context const* ctx_;
function::ptr func_;
assembly::ptr assembly_;
utils::reader script_;
std::map<u32, import_ref::ptr> import_refs_;
std::map<u32, string_ref::ptr> string_refs_;
std::map<u32, animtree_ref::ptr> anim_refs_;
public:
disassembler(context const* ctx);
auto disassemble(buffer const& data) -> assembly::ptr;
auto disassemble(std::vector<u8> const& data) -> assembly::ptr;
auto disassemble(u8 const* data, usize data_size) -> assembly::ptr;
private:
auto disassemble_function(function& func) -> void;
auto disassemble_instruction(instruction& inst) -> void;
auto disassemble_name(instruction& inst) -> void;
auto disassemble_params(instruction& inst) -> void;
auto disassemble_import(instruction& inst) -> void;
auto disassemble_string(instruction& inst) -> void;
auto disassemble_animtree(instruction& inst) -> void;
auto disassemble_animation(instruction& inst) -> void;
auto disassemble_jump(instruction& inst) -> void;
auto disassemble_switch(instruction& inst) -> void;
auto disassemble_end_switch(instruction& inst) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,24 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t6
{
constexpr usize code_count = 125;
constexpr usize dvar_count = 3326;
constexpr u64 header_magic = 0x06000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::gsc::t6

View File

@ -0,0 +1,25 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t7
{
constexpr usize code_count = 8192;
constexpr usize dvar_count = 0;
constexpr usize hash_count = 178717;
constexpr u64 header_magic = 0x1C000A0D43534780;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t7

View File

@ -0,0 +1,25 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t8
{
constexpr usize code_count = 0;
constexpr usize dvar_count = 0;
constexpr usize hash_count = 0;
constexpr u64 header_magic = 0;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t8

View File

@ -0,0 +1,25 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/arc/context.hpp"
namespace xsk::arc::t9
{
constexpr usize code_count = 0;
constexpr usize dvar_count = 0;
constexpr usize hash_count = 0;
constexpr u64 header_magic = 0;
class context : public arc::context
{
public:
context();
};
} // namespace xsk::arc::t9

170
include/xsk/arc/source.hpp Normal file
View File

@ -0,0 +1,170 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::arc
{
class source
{
context* ctx_;
std::vector<u8> buf_;
u32 indent_;
public:
source(context* ctx);
auto dump(assembly const& data) -> std::vector<u8>;
auto dump(program const& data) -> std::vector<u8>;
private:
auto dump_assembly(assembly const& data) -> void;
auto dump_function(function const& func) -> void;
auto dump_instruction(instruction const& inst) -> void;
auto dump_program(program const& data) -> void;
auto dump_include(include const& inc) -> void;
auto dump_decl(decl const& dec) -> void;
auto dump_decl_dev_begin(decl_dev_begin const& dec) -> void;
auto dump_decl_dev_end(decl_dev_end const& dec) -> void;
auto dump_decl_namespace(decl_namespace const& dec) -> void;
auto dump_decl_usingtree(decl_usingtree const& dec) -> void;
auto dump_decl_function(decl_function const& dec) -> void;
auto dump_stmt(stmt const& stm) -> void;
auto dump_stmt_list(stmt_list const& stm) -> void;
auto dump_stmt_comp(stmt_comp const& stm) -> void;
auto dump_stmt_dev(stmt_dev const& stm) -> void;
auto dump_stmt_expr(stmt_expr const& stm) -> void;
auto dump_stmt_call(stmt_call const& stm) -> void;
auto dump_stmt_const(stmt_const const& stm) -> void;
auto dump_stmt_assign(stmt_assign const& stm) -> void;
auto dump_stmt_endon(stmt_endon const& stm) -> void;
auto dump_stmt_notify(stmt_notify const& stm) -> void;
auto dump_stmt_realwait(stmt_realwait const& stm) -> void;
auto dump_stmt_wait(stmt_wait const& stm) -> void;
auto dump_stmt_waittill(stmt_waittill const& stm) -> void;
auto dump_stmt_waittillmatch(stmt_waittillmatch const& stm) -> void;
auto dump_stmt_waittillframeend(stmt_waittillframeend const& stm) -> void;
auto dump_stmt_if(stmt_if const& stm) -> void;
auto dump_stmt_ifelse(stmt_ifelse const& stm) -> void;
auto dump_stmt_while(stmt_while const& stm) -> void;
auto dump_stmt_dowhile(stmt_dowhile const& stm) -> void;
auto dump_stmt_for(stmt_for const& stm) -> void;
auto dump_stmt_foreach(stmt_foreach const& stm) -> void;
auto dump_stmt_switch(stmt_switch const& stm) -> void;
auto dump_stmt_case(stmt_case const& stm) -> void;
auto dump_stmt_default(stmt_default const& stm) -> void;
auto dump_stmt_break(stmt_break const& stm) -> void;
auto dump_stmt_continue(stmt_continue const& stm) -> void;
auto dump_stmt_return(stmt_return const& stm) -> void;
auto dump_stmt_breakpoint(stmt_breakpoint const& stm) -> void;
auto dump_stmt_prof_begin(stmt_prof_begin const& stm) -> void;
auto dump_stmt_prof_end(stmt_prof_end const& stm) -> void;
auto dump_expr(expr const& exp) -> void;
auto dump_expr_increment(expr_increment const& exp) -> void;
auto dump_expr_decrement(expr_decrement const& exp) -> void;
auto dump_expr_assign_equal(expr_assign_equal const& exp) -> void;
auto dump_expr_assign_add(expr_assign_add const& exp) -> void;
auto dump_expr_assign_sub(expr_assign_sub const& exp) -> void;
auto dump_expr_assign_mul(expr_assign_mul const& exp) -> void;
auto dump_expr_assign_div(expr_assign_div const& exp) -> void;
auto dump_expr_assign_mod(expr_assign_mod const& exp) -> void;
auto dump_expr_assign_shift_left(expr_assign_shift_left const& exp) -> void;
auto dump_expr_assign_shift_right(expr_assign_shift_right const& exp) -> void;
auto dump_expr_assign_bitwise_or(expr_assign_bitwise_or const& exp) -> void;
auto dump_expr_assign_bitwise_and(expr_assign_bitwise_and const& exp) -> void;
auto dump_expr_assign_bitwise_exor(expr_assign_bitwise_exor const& exp) -> void;
auto dump_expr_ternary(expr_ternary const& exp) -> void;
auto dump_expr_or(expr_or const& exp) -> void;
auto dump_expr_and(expr_and const& exp) -> void;
auto dump_expr_super_equal(expr_super_equal const& exp) -> void;
auto dump_expr_super_not_equal(expr_super_not_equal const& exp) -> void;
auto dump_expr_equality(expr_equality const& exp) -> void;
auto dump_expr_inequality(expr_inequality const& exp) -> void;
auto dump_expr_less_equal(expr_less_equal const& exp) -> void;
auto dump_expr_greater_equal(expr_greater_equal const& exp) -> void;
auto dump_expr_less(expr_less const& exp) -> void;
auto dump_expr_greater(expr_greater const& exp) -> void;
auto dump_expr_add(expr_add const& exp) -> void;
auto dump_expr_sub(expr_sub const& exp) -> void;
auto dump_expr_mul(expr_mul const& exp) -> void;
auto dump_expr_div(expr_div const& exp) -> void;
auto dump_expr_mod(expr_mod const& exp) -> void;
auto dump_expr_shift_left(expr_shift_left const& exp) -> void;
auto dump_expr_shift_right(expr_shift_right const& exp) -> void;
auto dump_expr_bitwise_or(expr_bitwise_or const& exp) -> void;
auto dump_expr_bitwise_and(expr_bitwise_and const& exp) -> void;
auto dump_expr_bitwise_exor(expr_bitwise_exor const& exp) -> void;
auto dump_expr_not(expr_not const& exp) -> void;
auto dump_expr_negate(expr_negate const& exp) -> void;
auto dump_expr_complement(expr_complement const& exp) -> void;
auto dump_expr_new(expr_new const& exp) -> void;
auto dump_expr_call(expr_call const& exp) -> void;
auto dump_expr_method(expr_method const& exp) -> void;
auto dump_call(call const& exp) -> void;
auto dump_expr_function(expr_function const& exp) -> void;
auto dump_expr_pointer(expr_pointer const& exp) -> void;
auto dump_expr_member(expr_member const& exp) -> void;
auto dump_expr_parameters(expr_parameters const& exp) -> void;
auto dump_expr_arguments(expr_arguments const& exp) -> void;
auto dump_expr_isdefined(expr_isdefined const& exp) -> void;
auto dump_expr_vectorscale(expr_vectorscale const& exp) -> void;
auto dump_expr_anglestoup(expr_anglestoup const& exp) -> void;
auto dump_expr_anglestoright(expr_anglestoright const& exp) -> void;
auto dump_expr_anglestoforward(expr_anglestoforward const& exp) -> void;
auto dump_expr_angleclamp180(expr_angleclamp180 const& exp) -> void;
auto dump_expr_vectortoangles(expr_vectortoangles const& exp) -> void;
auto dump_expr_abs(expr_abs const& exp) -> void;
auto dump_expr_gettime(expr_gettime const& exp) -> void;
auto dump_expr_getdvar(expr_getdvar const& exp) -> void;
auto dump_expr_getdvarint(expr_getdvarint const& exp) -> void;
auto dump_expr_getdvarfloat(expr_getdvarfloat const& exp) -> void;
auto dump_expr_getdvarvector(expr_getdvarvector const& exp) -> void;
auto dump_expr_getdvarcolorred(expr_getdvarcolorred const& exp) -> void;
auto dump_expr_getdvarcolorgreen(expr_getdvarcolorgreen const& exp) -> void;
auto dump_expr_getdvarcolorblue(expr_getdvarcolorblue const& exp) -> void;
auto dump_expr_getdvarcoloralpha(expr_getdvarcoloralpha const& exp) -> void;
auto dump_expr_getfirstarraykey(expr_getfirstarraykey const& exp) -> void;
auto dump_expr_getnextarraykey(expr_getnextarraykey const& exp) -> void;
auto dump_expr_reference(expr_reference const& exp) -> void;
auto dump_expr_array(expr_array const& exp) -> void;
auto dump_expr_field(expr_field const& exp) -> void;
auto dump_expr_size(expr_size const& exp) -> void;
auto dump_expr_paren(expr_paren const& exp) -> void;
auto dump_expr_empty_array(expr_empty_array const& exp) -> void;
auto dump_expr_undefined(expr_undefined const& exp) -> void;
auto dump_expr_game(expr_game const& exp) -> void;
auto dump_expr_self(expr_self const& exp) -> void;
auto dump_expr_anim(expr_anim const& exp) -> void;
auto dump_expr_level(expr_level const& exp) -> void;
auto dump_expr_world(expr_world const& exp) -> void;
auto dump_expr_classes(expr_classes const& exp) -> void;
auto dump_expr_animation(expr_animation const& exp) -> void;
auto dump_expr_animtree(expr_animtree const& exp) -> void;
auto dump_expr_identifier(expr_identifier const& exp) -> void;
auto dump_expr_path(expr_path const& exp) -> void;
auto dump_expr_istring(expr_istring const& exp) -> void;
auto dump_expr_string(expr_string const& exp) -> void;
auto dump_expr_hash(expr_hash const& exp) -> void;
auto dump_expr_vector(expr_vector const& exp) -> void;
auto dump_expr_float(expr_float const& exp) -> void;
auto dump_expr_integer(expr_integer const& exp) -> void;
auto dump_expr_false(expr_false const& exp) -> void;
auto dump_expr_true(expr_true const& exp) -> void;
auto dump_asm_loc(asm_loc const& exp) -> void;
auto dump_asm_jmp(asm_jmp const& exp) -> void;
auto dump_asm_jmp_back(asm_jmp_back const& exp) -> void;
auto dump_asm_jmp_cond(asm_jmp_cond const& exp) -> void;
auto dump_asm_jmp_true(asm_jmp_true const& exp) -> void;
auto dump_asm_jmp_false(asm_jmp_false const& exp) -> void;
auto dump_asm_switch(asm_switch const& exp) -> void;
auto dump_asm_endswitch(asm_endswitch const& exp) -> void;
auto dump_asm_prescriptcall(asm_prescriptcall const& exp) -> void;
auto dump_asm_voidcodepos(asm_voidcodepos const& exp) -> void;
auto dump_asm_dev(asm_dev const& exp) -> void;
};
} // namespace xsk::arc

View File

@ -0,0 +1,43 @@
// Copyright 2023 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 "xsk/utils/writer.hpp"
#include "common/types.hpp"
namespace xsk::gsc
{
class assembler
{
context const* ctx_;
function const* func_;
assembly const* assembly_;
utils::writer script_;
utils::writer stack_;
public:
assembler(context const* ctx);
auto assemble(assembly const& data) -> std::pair<buffer, buffer>;
private:
auto assemble_function(function const& func) -> void;
auto assemble_instruction(instruction const& inst) -> void;
auto assemble_builtin_call(instruction const& inst, bool method, bool args) -> void;
auto assemble_local_call(instruction const& inst, bool thread) -> void;
auto assemble_far_call(instruction const& inst, bool thread) -> void;
auto assemble_switch(instruction const& inst) -> void;
auto assemble_end_switch(instruction const& inst) -> void;
auto assemble_field_variable(instruction const& inst) -> void;
auto assemble_formal_params(instruction const& inst) -> void;
auto assemble_jump(instruction const& inst, bool expr, bool back) -> void;
auto assemble_offset(i32 offs) -> void;
auto resolve_function(std::string const& name) -> i32;
auto resolve_label(std::string const& name) -> i32;
auto encrypt_string(std::string const& str) -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,267 @@
// Copyright 2023 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
{
constexpr usize opcode_count = 205;
enum class opcode : u8
{
vm_invalid,
OP_CastFieldObject,
OP_SetLocalVariableFieldCached,
OP_plus,
OP_RemoveLocalVariables,
OP_EvalSelfFieldVariableRef,
OP_ScriptFarMethodChildThreadCall,
OP_GetGameRef,
OP_EvalAnimFieldVariable,
OP_EvalLevelFieldVariableRef,
OP_GetThisthread,
OP_greater,
OP_waittillmatch,
OP_shift_right,
OP_dec,
OP_JumpOnTrue,
OP_bit_or,
OP_equality,
OP_ClearLocalVariableFieldCached0,
OP_notify,
OP_GetVector,
OP_ScriptMethodChildThreadCallPointer,
OP_PreScriptCall,
OP_GetByte,
OP_ScriptFarThreadCall,
OP_SetSelfFieldVariableField,
OP_JumpOnFalseExpr,
OP_GetUndefined,
OP_jumpback,
OP_JumpOnTrueExpr,
OP_CallBuiltin0,
OP_CallBuiltin1,
OP_CallBuiltin2,
OP_CallBuiltin3,
OP_CallBuiltin4,
OP_CallBuiltin5,
OP_CallBuiltin,
OP_SetLocalVariableFieldCached0,
OP_ClearFieldVariable,
OP_GetLevel,
OP_size,
OP_SafeSetWaittillVariableFieldCached,
OP_ScriptLocalMethodThreadCall,
OP_AddArray,
OP_endon,
OP_EvalFieldVariable,
OP_shift_left,
OP_EvalLocalArrayRefCached0,
OP_Return,
OP_CreateLocalVariable,
OP_SafeSetVariableFieldCached0,
OP_GetBuiltinFunction,
OP_ScriptLocalMethodCall,
OP_CallBuiltinMethodPointer,
OP_ScriptLocalChildThreadCall,
OP_GetSelfObject,
OP_GetGame,
OP_SetLevelFieldVariableField,
OP_EvalArray,
OP_GetSelf,
OP_End,
OP_EvalSelfFieldVariable,
OP_less_equal,
OP_EvalLocalVariableCached0,
OP_EvalLocalVariableCached1,
OP_EvalLocalVariableCached2,
OP_EvalLocalVariableCached3,
OP_EvalLocalVariableCached4,
OP_EvalLocalVariableCached5,
OP_EvalLocalVariableCached,
OP_EvalNewLocalArrayRefCached0,
OP_ScriptChildThreadCallPointer,
OP_EvalLocalVariableObjectCached,
OP_ScriptLocalThreadCall,
OP_GetInteger,
OP_ScriptMethodCallPointer,
OP_checkclearparams,
OP_SetAnimFieldVariableField,
OP_waittillmatch2,
OP_minus,
OP_ScriptLocalFunctionCall2,
OP_GetNegUnsignedShort,
OP_GetNegByte,
OP_SafeCreateVariableFieldCached,
OP_greater_equal,
OP_vector,
OP_GetBuiltinMethod,
OP_endswitch,
OP_ClearArray,
OP_DecTop,
OP_CastBool,
OP_EvalArrayRef,
OP_SetNewLocalVariableFieldCached0,
OP_GetZero,
OP_wait,
OP_waittill,
OP_GetIString,
OP_ScriptFarFunctionCall,
OP_GetAnimObject,
OP_GetAnimTree,
OP_EvalLocalArrayCached,
OP_mod,
OP_ScriptFarMethodThreadCall,
OP_GetUnsignedShort,
OP_clearparams,
OP_ScriptMethodThreadCallPointer,
OP_ScriptFunctionCallPointer,
OP_EmptyArray,
OP_SafeSetVariableFieldCached,
OP_ClearVariableField,
OP_EvalFieldVariableRef,
OP_ScriptLocalMethodChildThreadCall,
OP_EvalNewLocalVariableRefCached0,
OP_GetFloat,
OP_EvalLocalVariableRefCached,
OP_JumpOnFalse,
OP_BoolComplement,
OP_ScriptThreadCallPointer,
OP_ScriptFarFunctionCall2,
OP_less,
OP_BoolNot,
OP_waittillFrameEnd,
OP_waitframe,
OP_GetString,
OP_EvalLevelFieldVariable,
OP_GetLevelObject,
OP_inc,
OP_CallBuiltinMethod0,
OP_CallBuiltinMethod1,
OP_CallBuiltinMethod2,
OP_CallBuiltinMethod3,
OP_CallBuiltinMethod4,
OP_CallBuiltinMethod5,
OP_CallBuiltinMethod,
OP_GetAnim,
OP_switch,
OP_SetVariableField,
OP_divide,
OP_GetLocalFunction,
OP_ScriptFarChildThreadCall,
OP_multiply,
OP_ClearLocalVariableFieldCached,
OP_EvalAnimFieldVariableRef,
OP_EvalLocalArrayRefCached,
OP_EvalLocalVariableRefCached0,
OP_bit_and,
OP_GetAnimation,
OP_GetFarFunction,
OP_CallBuiltinPointer,
OP_jump,
OP_voidCodepos,
OP_ScriptFarMethodCall,
OP_inequality,
OP_ScriptLocalFunctionCall,
OP_bit_ex_or,
OP_NOP,
OP_abort,
OP_object,
OP_thread_object,
OP_EvalLocalVariable,
OP_EvalLocalVariableRef,
OP_prof_begin,
OP_prof_end,
OP_breakpoint,
OP_assignmentBreakpoint,
OP_manualAndAssignmentBreakpoint,
OP_BoolNotAfterAnd,
OP_FormalParams,
OP_IsDefined,
OP_IsTrue,
OP_NativeGetLocalFunction,
OP_NativeLocalFunctionCall,
OP_NativeLocalFunctionCall2,
OP_NativeLocalMethodCall,
OP_NativeLocalFunctionThreadCall,
OP_NativeLocalMethodThreadCall,
OP_NativeLocalFunctionChildThreadCall,
OP_NativeLocalMethodChildThreadCall,
OP_NativeGetFarFunction,
OP_NativeFarFunctionCall,
OP_NativeFarFunctionCall2,
OP_NativeFarMethodCall,
OP_NativeFarFunctionThreadCall,
OP_NativeFarMethodThreadCall,
OP_NativeFarFunctionChildThreadCall,
OP_NativeFarMethodChildThreadCall,
OP_EvalNewLocalArrayRefCached0_Precompiled,
OP_SetNewLocalVariableFieldCached0_Precompiled,
OP_CreateLocalVariable_Precompiled,
OP_SafeCreateVariableFieldCached_Precompiled,
OP_FormalParams_Precompiled,
OP_GetStatHash,
OP_GetUnkxHash,
OP_GetEnumHash,
OP_GetDvarHash,
OP_GetUnsignedInt,
OP_GetNegUnsignedInt,
OP_GetInteger64,
OP_iw9_139,
OP_iw9_140,
OP_iw9_141,
OP_iw9_142,
OP_iw9_143,
OP_iw9_144,
OP_iw9_166,
OP_count,
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
u32 index;
u32 size;
opcode opcode;
std::vector<std::string> data;
};
struct function
{
using ptr = std::unique_ptr<function>;
u32 index;
u32 size;
u32 id;
std::string name;
std::vector<instruction::ptr> instructions;
std::unordered_map<u32, std::string> labels;
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<function::ptr> functions;
};
inline auto make_instruction() -> std::unique_ptr<instruction>
{
return std::unique_ptr<instruction>(new instruction);
}
inline auto make_function() -> std::unique_ptr<function>
{
return std::unique_ptr<function>(new function);
}
inline auto make_assembly() -> std::unique_ptr<assembly>
{
return std::unique_ptr<assembly>(new assembly);
}
} // namespace xsk::gsc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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
{
struct asset
{
using ptr = std::unique_ptr<asset>;
std::string name;
u32 compressedLen;
u32 len;
u32 bytecodeLen;
std::vector<u8> buffer;
std::vector<u8> bytecode;
auto serialize() -> std::vector<u8>;
auto deserialize(std::vector<u8> const& data) -> void;
};
} // namespace xsk::gsc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
// Copyright 2023 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
{
struct buffer
{
u8 const* data;
usize const size;
buffer() : data{ nullptr }, size{ 0 } {}
buffer(u8 const* data, usize size) : data{ data }, size{ size } {}
};
} // namespace xsk::gsc

View File

@ -0,0 +1,21 @@
// Copyright 2023 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
{
struct define
{
enum kind : u8 { PLAIN, BUILTIN, OBJECT, FUNCTION };
kind type;
// bool vararg;
std::vector<token> args;
std::vector<token> exp;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,19 @@
// Copyright 2023 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
{
struct directive
{
enum kind : u8 { IF, IFDEF, IFNDEF, ELIF, ELIFDEF, ELIFNDEF, ELSE, ENDIF, DEFINE, UNDEF, PRAGMA, WARNING, ERROR, LINE, INCLUDE, INLINE, INSERT, USINGTREE };
kind type;
bool skip;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,47 @@
// Copyright 2023 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
{
class error : public std::runtime_error
{
public:
error(std::string const& what);
};
class asm_error : public std::runtime_error
{
public:
asm_error(std::string const& what);
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(std::string const& what);
};
class ppr_error : public std::runtime_error
{
public:
ppr_error(location const& loc, std::string const& what);
};
class comp_error : public std::runtime_error
{
public:
comp_error(location const& loc, std::string const& what);
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(std::string const& what);
};
} // namespace xsk::gsc

View File

@ -0,0 +1,177 @@
// Copyright 2023 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
{
class position
{
public:
typedef const std::string filename_type;
typedef int counter_type;
filename_type *filename;
counter_type line;
counter_type column;
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
line = l;
column = c;
}
void lines(counter_type count = 1)
{
if (count)
{
column = 1;
line = add_(line, count, 1);
}
}
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
private:
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
class location
{
public:
typedef position::filename_type filename_type;
typedef position::counter_type counter_type;
position begin;
position end;
location(const position &b, const position &e)
: begin(b), end(e) {}
explicit location(const position &p = position())
: begin(p), end(p) {}
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
void step()
{
begin = end;
}
void columns(counter_type count = 1)
{
end += count;
}
void lines(counter_type count = 1)
{
end.lines(count);
}
auto print() const -> std::string
{
return fmt::format("{}:{}:{}", *begin.filename, begin.line, begin.column);
}
auto label() const -> std::string
{
return fmt::format("loc_{:X}", begin.line);
}
};
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
inline location operator+(location res, const location &end)
{
return res += end;
}
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
template <typename T>
std::basic_ostream<T>& operator<<(std::basic_ostream<T> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // namespace xsk::gsc

View File

@ -0,0 +1,23 @@
// Copyright 2023 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
{
struct lookahead
{
char const* buffer_pos;
usize available;
char last_byte;
char curr_byte;
lookahead(char const* data, usize size);
auto advance() -> void;
auto ended() { return available == 0; };
};
} // namespace xsk::gsc

View File

@ -0,0 +1,64 @@
// Copyright 2023 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
{
struct locjmp
{
std::string end;
std::string cnt;
std::string brk;
bool last;
};
struct scope
{
using ptr = std::unique_ptr<scope>;
enum abort_type
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
struct var
{
std::string name;
u8 create;
bool init;
};
abort_type abort;
std::string loc_end;
std::string loc_cont;
std::string loc_break;
u32 create_count;
u32 public_count;
std::vector<var> vars;
bool is_last;
scope();
auto transfer_dec(scope::ptr const& child) -> void;
auto transfer(scope::ptr const& child) -> void;
auto copy(scope::ptr const& child) -> void;
auto append_dec(scope::ptr const& child) -> void;
auto append(std::vector<scope*> const& childs) -> void;
auto merge(std::vector<scope*> const& childs) -> void;
auto init(scope::ptr const& child) -> void;
auto init(std::vector<scope*> const& childs) -> void;
auto find(usize start, std::string const& name) -> i32;
};
inline auto make_scope() -> std::unique_ptr<scope>
{
return std::unique_ptr<scope>(new scope);
}
} // namespace xsk::gsc

View File

@ -0,0 +1,19 @@
// Copyright 2023 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
{
enum class spacing : u8
{
none = 0, // no space between tokens
null = 1, // token just after new line
back = 2, // token after space
empty = 4, // token after new line + space
};
} // namespace xsk::gsc

View File

@ -0,0 +1,41 @@
// Copyright 2023 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
{
struct token
{
enum kind : u8
{
PLUS, MINUS, STAR, DIV, MOD, BITOR, BITAND, BITEXOR, SHL, SHR,
ASSIGN, PLUSEQ, MINUSEQ, STAREQ, DIVEQ, MODEQ, BITOREQ, BITANDEQ, BITEXOREQ, SHLEQ, SHREQ,
INC, DEC, GT, LT, GE, LE, NE, EQ, OR, AND, TILDE, BANG, QMARK, COLON, SHARP, COMMA, DOT,
DOUBLEDOT, ELLIPSIS, SEMICOLON, DOUBLECOLON, LBRACKET, RBRACKET, LBRACE, RBRACE, LPAREN, RPAREN,
NAME, PATH, STRING, ISTRING, INT, FLT,
DEVBEGIN, DEVEND, INLINE, INCLUDE, USINGTREE, ANIMTREE, ENDON, NOTIFY, WAIT,
WAITTILL, WAITTILLMATCH, WAITTILLFRAMEEND, WAITFRAME, IF, ELSE, DO, WHILE,
FOR, FOREACH, IN, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, RETURN, BREAKPOINT,
PROFBEGIN, PROFEND, ASSERT, ASSERTEX, ASSERTMSG, THREAD, CHILDTHREAD, THISTHREAD,
CALL, TRUE, FALSE, UNDEFINED, SIZE, GAME, SELF, ANIM, LEVEL, ISDEFINED, ISTRUE,
HASH, NEWLINE, EOS, DEFINED, MACROBEGIN, MACROEND, MACROARG, MACROVAOPT, MACROVAARGS, STRINGIZE, PASTE
};
kind type;
spacing space;
location pos;
std::string data;
token(kind type, spacing space, location pos) : type{ type }, space{ space }, pos{ pos }, data{} {}
token(kind type, spacing space, location pos, std::string data) : type{ type }, space{ space }, pos{ pos }, data{ std::move(data) } {}
auto to_string() -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,111 @@
// Copyright 2023 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 "asset.hpp"
#include "scope.hpp"
#include "buffer.hpp"
#include "assembly.hpp"
#include "location.hpp"
#include "exception.hpp"
#include "lookahead.hpp"
#include "directive.hpp"
#include "space.hpp"
#include "token.hpp"
#include "define.hpp"
#include "ast.hpp"
namespace xsk::gsc
{
enum class instance : u8
{
server,
client,
};
enum class build : u8
{
dev,
prod,
};
enum class endian : u8
{
little,
big,
};
enum class system : u8
{
pc,
ps3,
xb2,
};
enum class engine : u8
{
iw5,
iw6,
iw7,
iw8,
iw9,
s1,
s2,
s4,
h1,
h2,
};
struct props
{
enum values : u32
{
none = 0 << 0,
str4 = 1 << 0, // strings size 4
tok4 = 1 << 1, // tokenid size 4
waitframe = 1 << 2, // waitframe opcode
params = 1 << 3, // packed func params
boolfuncs = 1 << 4, // isdefined, istrue
boolnotand = 1 << 5, // !&& expr opcode
offs8 = 1 << 6, // offset shift by 8
offs9 = 1 << 7, // offset shift by 9
hash = 1 << 9, // iw9 identifiers
farcall = 1 << 9, // iw9 new call system
foreach = 1 << 10, // iw9 foreach
};
props(values value) : value_(value) {}
operator values() { return value_; }
operator bool() { return value_ != values::none; }
props::values operator|(props::values rhs) const { return static_cast<props::values>(value_ | rhs); }
props::values operator&(props::values rhs) const { return static_cast<props::values>(value_ & rhs); }
friend props::values operator|(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) | static_cast<std::underlying_type<props::values>::type>(rhs));
}
friend props::values operator&(props::values lhs, props::values rhs)
{
return static_cast<props::values>(static_cast<std::underlying_type<props::values>::type>(lhs) & static_cast<std::underlying_type<props::values>::type>(rhs));
}
private:
values value_;
};
enum class switch_type
{
none,
integer,
string,
};
// fordward decl for modules ref
class context;
} // namespace xsk::gsc

View File

@ -0,0 +1,159 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::gsc
{
class compiler
{
context* ctx_;
assembly::ptr assembly_;
function::ptr function_;
std::vector<std::string> stackframe_;
std::vector<std::string> localfuncs_;
std::unordered_map<std::string, expr const*> constants_;
std::unordered_map<node*, scope::ptr> scopes_;
std::vector<scope*> break_blks_;
std::vector<scope*> continue_blks_;
std::string animname_;
u32 index_;
u32 label_idx_;
bool can_break_;
bool can_continue_;
bool developer_thread_;
bool animload_;
public:
compiler(context* ctx);
auto compile(program const& data) -> assembly::ptr;
auto compile(std::string const& file, std::vector<u8>& data) -> assembly::ptr;
private:
auto emit_program(program const& prog) -> void;
auto emit_decl(decl const& dec) -> void;
auto emit_decl_usingtree(decl_usingtree const& animtree) -> void;
auto emit_decl_constant(decl_constant const& constant) -> void;
auto emit_decl_function(decl_function const& func) -> void;
auto emit_stmt(stmt const& stm, scope& scp, bool last) -> void;
auto emit_stmt_list(stmt_list const& stm, scope& scp, bool last) -> void;
auto emit_stmt_comp(stmt_comp const& stm, scope& scp, bool last) -> void;
auto emit_stmt_dev(stmt_dev const& stm, scope& scp, bool last) -> void;
auto emit_stmt_expr(stmt_expr const& stm, scope& scp) -> void;
auto emit_stmt_call(stmt_call const& stm, scope& scp) -> void;
auto emit_stmt_assign(stmt_assign const& stm, scope& scp) -> void;
auto emit_stmt_endon(stmt_endon const& stm, scope& scp) -> void;
auto emit_stmt_notify(stmt_notify const& stm, scope& scp) -> void;
auto emit_stmt_wait(stmt_wait const& stm, scope& scp) -> void;
auto emit_stmt_waittill(stmt_waittill const& stm, scope& scp) -> void;
auto emit_stmt_waittillmatch(stmt_waittillmatch const& stm, scope& scp) -> void;
auto emit_stmt_waittillframeend(stmt_waittillframeend const& stm, scope& scp) -> void;
auto emit_stmt_waitframe(stmt_waitframe const& stm, scope& scp) -> void;
auto emit_stmt_if(stmt_if const& stm, scope& scp, bool last) -> void;
auto emit_stmt_ifelse(stmt_ifelse const& stm, scope& scp, bool last) -> void;
auto emit_stmt_while(stmt_while const& stm, scope& scp) -> void;
auto emit_stmt_dowhile(stmt_dowhile const& stm, scope& scp) -> void;
auto emit_stmt_for(stmt_for const& stm, scope& scp) -> void;
auto emit_stmt_foreach(stmt_foreach const& stm, scope& scp) -> void;
auto emit_stmt_switch(stmt_switch const& stm, scope& scp) -> void;
auto emit_stmt_case(stmt_case const& stm, scope& scp) -> void;
auto emit_stmt_default(stmt_default const& stm, scope& scp) -> void;
auto emit_stmt_break(stmt_break const& stm, scope& scp) -> void;
auto emit_stmt_continue(stmt_continue const& stm, scope& scp) -> void;
auto emit_stmt_return(stmt_return const& stm, scope& scp) -> void;
auto emit_stmt_breakpoint(stmt_breakpoint const& stm, scope& scp) -> void;
auto emit_stmt_prof_begin(stmt_prof_begin const& stm, scope& scp) -> void;
auto emit_stmt_prof_end(stmt_prof_end const& stm, scope& scp) -> void;
auto emit_stmt_assert(stmt_assert const& stm, scope& scp) -> void;
auto emit_stmt_assertex(stmt_assertex const& stm, scope& scp) -> void;
auto emit_stmt_assertmsg(stmt_assertmsg const& stm, scope& scp) -> void;
auto emit_expr(expr const& exp, scope& scp) -> void;
auto emit_expr_assign(expr_assign const& exp, scope& scp) -> void;
auto emit_expr_clear(expr const& exp, scope& scp) -> void;
auto emit_expr_clear_local(expr_identifier const& exp, scope& scp) -> void;
auto emit_expr_increment(expr_increment const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_decrement(expr_decrement const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_ternary(expr_ternary const& exp, scope& scp) -> void;
auto emit_expr_binary(expr_binary const& exp, scope& scp) -> void;
auto emit_expr_and(expr_and const& exp, scope& scp) -> void;
auto emit_expr_or(expr_or const& exp, scope& scp) -> void;
auto emit_expr_complement(expr_complement const& exp, scope& scp) -> void;
auto emit_expr_negate(expr_negate const& exp, scope& scp) -> void;
auto emit_expr_not(expr_not const& exp, scope& scp) -> void;
auto emit_expr_call(expr_call const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_call_pointer(expr_pointer const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_call_function(expr_function const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_method(expr_method const& exp, scope& scp, bool is_stmt) -> void;
auto emit_expr_method_pointer(expr_pointer const& exp, expr const& obj, scope& scp, bool is_stmt) -> void;
auto emit_expr_method_function(expr_function const& exp, expr const& obj, scope& scp, bool is_stmt) -> void;
auto emit_expr_add_array(expr_add_array const& exp, scope& scp) -> void;
auto emit_expr_parameters(expr_parameters const& exp, scope& scp) -> void;
auto emit_expr_arguments(expr_arguments const& exp, scope& scp) -> void;
auto emit_expr_isdefined(expr_isdefined const& exp, scope& scp) -> void;
auto emit_expr_istrue(expr_istrue const& exp, scope& scp) -> void;
auto emit_expr_reference(expr_reference const& exp, scope& scp) -> void;
auto emit_expr_size(expr_size const& exp, scope& scp) -> void;
auto emit_expr_tuple(expr_tuple const& exp, scope& scp) -> void;
auto emit_expr_variable_ref(expr const& exp, scope& scp, bool set) -> void;
auto emit_expr_array_ref(expr_array const& exp, scope& scp, bool set) -> void;
auto emit_expr_field_ref(expr_field const& exp, scope& scp, bool set) -> void;
auto emit_expr_local_ref(expr_identifier const& exp, scope& scp, bool set) -> void;
auto emit_expr_variable(expr const& exp, scope& scp) -> void;
auto emit_expr_array(expr_array const& exp, scope& scp) -> void;
auto emit_expr_field(expr_field const& exp, scope& scp) -> void;
auto emit_expr_local(expr_identifier const& exp, scope& scp) -> void;
auto emit_expr_object(expr const& exp, scope& scp) -> void;
auto emit_expr_vector(expr_vector const& exp, scope& scp) -> void;
auto emit_expr_animation(expr_animation const& exp) -> void;
auto emit_expr_animtree(expr_animtree const& exp) -> void;
auto emit_expr_istring(expr_istring const& exp) -> void;
auto emit_expr_string(expr_string const& exp) -> void;
auto emit_expr_float(expr_float const& exp) -> void;
auto emit_expr_integer(expr_integer const& exp) -> void;
auto emit_expr_false(expr_false const& exp) -> void;
auto emit_expr_true(expr_true const& exp) -> void;
auto emit_create_local_vars(scope& scp) -> void;
auto emit_remove_local_vars(scope& scp) -> void;
auto emit_opcode(opcode op) -> void;
auto emit_opcode(opcode op, std::string const& data) -> void;
auto emit_opcode(opcode op, std::vector<std::string> const& data) -> void;
auto process_function(decl_function const& func) -> void;
auto process_stmt(stmt const& stm, scope& scp) -> void;
auto process_stmt_list(stmt_list const& stm, scope& scp) -> void;
auto process_stmt_comp(stmt_comp const& stm, scope& scp) -> void;
auto process_stmt_dev(stmt_dev const& stm, scope& scp) -> void;
auto process_stmt_expr(stmt_expr const& stm, scope& scp) -> void;
auto process_stmt_assign(stmt_assign const& stm, scope& scp) -> void;
auto process_stmt_waittill(stmt_waittill const& stm, scope& scp) -> void;
auto process_stmt_if(stmt_if const& stm, scope& scp) -> void;
auto process_stmt_ifelse(stmt_ifelse const& stm, scope& scp) -> void;
auto process_stmt_while(stmt_while const& stm, scope& scp) -> void;
auto process_stmt_dowhile(stmt_dowhile const& stm, scope& scp) -> void;
auto process_stmt_for(stmt_for const& stm, scope& scp) -> void;
auto process_stmt_foreach(stmt_foreach const& stm, scope& scp) -> void;
auto process_stmt_switch(stmt_switch const& stm, scope& scp) -> void;
auto process_stmt_break(stmt_break const& stm, scope& scp) -> void;
auto process_stmt_continue(stmt_continue const& stm, scope& scp) -> void;
auto process_stmt_return(stmt_return const& stm, scope& scp) -> void;
auto process_expr(expr const& exp, scope& scp) -> void;
auto process_expr_tuple(expr_tuple const& exp, scope& scp) -> void;
auto process_expr_parameters(expr_parameters const& exp, scope& scp) -> void;
auto variable_register(expr_identifier const& exp, scope& scp) -> void;
auto variable_initialized(expr_identifier const& exp, scope& scp) -> bool;
auto variable_initialize(expr_identifier const& exp, scope& scp) -> u8;
auto variable_create(expr_identifier const& exp, scope& scp) -> u8;
auto variable_access(expr_identifier const& exp, scope& scp) -> u8;
auto resolve_function_type(expr_function const& exp, std::string& path) -> call::type;
auto resolve_reference_type(expr_reference const& exp, std::string& path, bool& method) -> call::type;
auto is_constant_condition(expr const& exp) -> bool;
auto insert_label(std::string const& label) -> void;
auto create_label() -> std::string;
auto insert_label() -> std::string;
};
} // namespace xsk::gsc

149
include/xsk/gsc/context.hpp Normal file
View File

@ -0,0 +1,149 @@
// Copyright 2023 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 "common/types.hpp"
#include "source.hpp"
#include "assembler.hpp"
#include "disassembler.hpp"
#include "compiler.hpp"
#include "decompiler.hpp"
namespace xsk::gsc
{
class context
{
public:
using fs_callback = std::function<std::pair<buffer, std::vector<u8>>(std::string const&)>;
context(props props, engine engine, endian endian, system system, u32 str_count);
auto props() const -> props { return props_; }
auto build() const -> build { return build_; }
auto engine() const -> engine { return engine_; }
auto endian() const -> endian { return endian_; }
auto system() const -> system { return system_; }
auto instance() const -> instance { return instance_; }
auto str_count() const -> u32 { return str_count_; }
auto source() -> source& { return source_; }
auto assembler() -> assembler& { return assembler_; }
auto disassembler() -> disassembler& { return disassembler_; }
auto compiler() -> compiler& { return compiler_; }
auto decompiler() -> decompiler& { return decompiler_; }
auto func_map() const -> std::unordered_map<std::string_view, u16> const& { return func_map_rev_; }
auto meth_map() const -> std::unordered_map<std::string_view, u16> const& { return meth_map_rev_; }
auto init(gsc::build build, fs_callback callback) -> void;
auto cleanup() -> void;
auto engine_name() const -> std::string_view;
auto opcode_size(opcode op) const -> u32;
auto opcode_id(opcode op) const -> u8;
auto opcode_name(opcode op) const -> std::string;
auto opcode_enum(std::string const& name) const -> opcode;
auto opcode_enum(u8 id) const -> opcode;
auto func_id(std::string const& name) const -> u16;
auto func_name(u16 id) const -> std::string;
auto func2_id(std::string const& name) const -> u64;
auto func2_name(u64 id) const -> std::string;
auto func_exists(std::string const& name) const -> bool;
auto func_add(std::string const& name, u16 id) -> void;
auto meth_id(std::string const& name) const -> u16;
auto meth_name(u16 id) const -> std::string;
auto meth2_id(std::string const& name) const -> u64;
auto meth2_name(u64 id) const -> std::string;
auto meth_exists(std::string const& name) const -> bool;
auto meth_add(std::string const& name, u16 id) -> void;
auto token_id(std::string const& name) const -> u32;
auto token_name(u32 id) const -> std::string;
auto path_id(std::string const& name) const -> u64;
auto path_name(u64 id) const -> std::string;
auto hash_id(std::string const& name) const -> u64;
auto hash_name(u64 id) const -> std::string;
auto make_token(std::string_view str) const -> std::string;
auto load_header(std::string const& name) -> std::tuple<std::string const*, char const*, usize>;
auto load_include(std::string const& name) -> bool;
auto init_includes() -> void;
auto is_includecall(std::string const& name, std::string& path) -> bool;
protected:
gsc::props props_;
gsc::build build_;
gsc::engine engine_;
gsc::endian endian_;
gsc::system system_;
gsc::instance instance_;
u32 str_count_;
gsc::source source_;
gsc::assembler assembler_;
gsc::disassembler disassembler_;
gsc::compiler compiler_;
gsc::decompiler decompiler_;
fs_callback fs_callback_;
std::unordered_map<opcode, std::string_view> opcode_map_;
std::unordered_map<std::string_view, opcode> opcode_map_rev_;
std::unordered_map<u8, opcode> code_map_;
std::unordered_map<opcode, u8> code_map_rev_;
std::unordered_map<u16, std::string_view> func_map_;
std::unordered_map<std::string_view, u16> func_map_rev_;
std::unordered_map<u16, std::string_view> meth_map_;
std::unordered_map<std::string_view, u16> meth_map_rev_;
std::unordered_map<u32, std::string_view> token_map_;
std::unordered_map<std::string_view, u32> token_map_rev_;
std::unordered_map<u64, std::string_view> func_map2_;
std::unordered_map<u64, std::string_view> meth_map2_;
std::unordered_map<u64, std::string_view> path_map_;
std::unordered_map<u64, std::string_view> hash_map_;
std::unordered_map<std::string, std::vector<u8>> header_files_;
std::unordered_set<std::string_view> includes_;
std::unordered_map<std::string, std::vector<std::string>> include_cache_;
std::unordered_set<std::string> new_func_map_;
std::unordered_set<std::string> new_meth_map_;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,104 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::gsc
{
class decompiler
{
context const* ctx_;
program::ptr program_;
decl_function::ptr func_;
std::unordered_map<u32, std::string> labels_;
std::vector<std::string> expr_labels_;
std::vector<std::string> tern_labels_;
std::stack<node::ptr> stack_;
bool in_waittill_;
locjmp locs_;
public:
decompiler(context const* ctx);
auto decompile(assembly const& data) -> program::ptr;
private:
auto decompile_function(function const& func) -> void;
auto decompile_instruction(instruction const& inst) -> void;
auto decompile_expressions(instruction const& inst) -> void;
auto decompile_statements(stmt_list& stm) -> void;
auto decompile_loops(stmt_list& stm) -> void;
auto decompile_switches(stmt_list& stm) -> void;
auto decompile_ifelses(stmt_list& stm) -> void;
auto decompile_aborts(stmt_list& stm) -> void;
auto decompile_tuples(stmt_list& stm) -> void;
auto decompile_if(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_ifelse_end(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_inf(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_loop(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_while(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_dowhile(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_for(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_foreach(stmt_list& stm, usize begin, usize end) -> void;
auto decompile_switch(stmt_list& stm, usize begin, usize end) -> void;
auto find_location_reference(stmt_list const& stm, usize begin, usize end, std::string const& loc) -> bool;
auto find_location_index(stmt_list const& stm, std::string const& loc) -> usize;
auto last_location_index(stmt_list const& stm, usize index) -> bool;
auto process_function(decl_function& func) -> void;
auto process_stmt(stmt& stm, scope& scp) -> void;
auto process_stmt_list(stmt_list& stm, scope& scp) -> void;
auto process_stmt_comp(stmt_comp& stm, scope& scp) -> void;
auto process_stmt_dev(stmt_dev& stm, scope& scp) -> void;
auto process_stmt_expr(stmt_expr& stm, scope& scp) -> void;
auto process_stmt_call(stmt_call& stm, scope& scp) -> void;
auto process_stmt_assign(stmt_assign& stm, scope& scp) -> void;
auto process_stmt_endon(stmt_endon& stm, scope& scp) -> void;
auto process_stmt_notify(stmt_notify& stm, scope& scp) -> void;
auto process_stmt_wait(stmt_wait& stm, scope& scp) -> void;
auto process_stmt_waittill(stmt_waittill& stm, scope& scp) -> void;
auto process_stmt_waittillmatch(stmt_waittillmatch& stm, scope& scp) -> void;
auto process_stmt_if(stmt_if& stm, scope& scp) -> void;
auto process_stmt_ifelse(stmt_ifelse& stm, scope& scp) -> void;
auto process_stmt_while(stmt_while& stm, scope& scp) -> void;
auto process_stmt_dowhile(stmt_dowhile& stm, scope& scp) -> void;
auto process_stmt_for(stmt_for& stm, scope& scp) -> void;
auto process_stmt_foreach(stmt_foreach& stm, scope& scp) -> void;
auto process_stmt_switch(stmt_switch& stm, scope& scp) -> void;
auto process_stmt_break(stmt_break& stm, scope& scp) -> void;
auto process_stmt_continue(stmt_continue& stm, scope& scp) -> void;
auto process_stmt_return(stmt_return& stm, scope& scp) -> void;
auto process_stmt_asm_create(asm_create& stm, scope& scp) -> void;
auto process_stmt_asm_remove(asm_remove& stm, scope& scp) -> void;
auto process_expr(expr& exp, scope& scp) -> void;
auto process_expr_assign(expr_assign::ptr& exp, scope& scp) -> void;
auto process_expr_increment(expr_increment& exp, scope& scp) -> void;
auto process_expr_decrement(expr_decrement& exp, scope& scp) -> void;
auto process_expr_ternary(expr_ternary& exp, scope& scp) -> void;
auto process_expr_binary(expr_binary& exp, scope& scp) -> void;
auto process_expr_and(expr_and& exp, scope& scp) -> void;
auto process_expr_or(expr_or& exp, scope& scp) -> void;
auto process_expr_complement(expr_complement& exp, scope& scp) -> void;
auto process_expr_not(expr_not& exp, scope& scp) -> void;
auto process_expr_call(expr_call& exp, scope& scp) -> void;
auto process_expr_method(expr_method& exp, scope& scp) -> void;
auto process_expr_call_pointer(expr_pointer& exp, scope& scp) -> void;
auto process_expr_call_function(expr_function& exp, scope& scp) -> void;
auto process_expr_method_pointer(expr_pointer& exp, expr& obj, scope& scp) -> void;
auto process_expr_method_function(expr_function& exp, expr& obj, scope& scp) -> void;
auto process_expr_arguments(expr_arguments& exp, scope& scp) -> void;
auto process_expr_add_array(expr_add_array& exp, scope& scp) -> void;
auto process_expr_size(expr_size& exp, scope& scp) -> void;
auto process_expr_tuple(expr_tuple& exp, scope& scp) -> void;
auto process_expr_array(expr_array& exp, scope& scp) -> void;
auto process_expr_field(expr_field& exp, scope& scp) -> void;
auto process_expr_vector(expr_vector& exp, scope& scp) -> void;
auto process_expr_asm_create(expr& exp, scope& scp) -> void;
auto process_expr_asm_access(expr& exp, scope& scp) -> void;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,45 @@
// Copyright 2023 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 "xsk/utils/reader.hpp"
#include "common/types.hpp"
namespace xsk::gsc
{
class disassembler
{
context const* ctx_;
function::ptr func_;
assembly::ptr assembly_;
utils::reader script_;
utils::reader stack_;
public:
disassembler(context const* ctx);
auto disassemble(buffer const& script, buffer const& stack) -> assembly::ptr;
auto disassemble(std::vector<u8> const& script, std::vector<u8> const& stack) -> assembly::ptr;
auto disassemble(u8 const* script, usize script_size, u8 const* stack, usize stack_size) -> assembly::ptr;
private:
auto dissasemble_function(function& func) -> void;
auto dissasemble_instruction(instruction& inst) -> void;
auto disassemble_builtin_call(instruction& inst, bool method, bool args) -> void;
auto disassemble_local_call(instruction& inst, bool thread) -> void;
auto disassemble_far_call(instruction& inst, bool thread) -> void;
auto disassemble_switch(instruction& inst) -> void;
auto disassemble_end_switch(instruction& inst) -> void;
auto disassemble_field_variable(instruction& inst) -> void;
auto disassemble_formal_params(instruction& inst) -> void;
auto disassemble_jump(instruction& inst, bool expr, bool back) -> void;
auto disassemble_offset() -> i32;
auto resolve_functions() -> void;
auto resolve_function(std::string const& index) -> std::string;
auto decrypt_string(std::string const& str) -> std::string;
};
} // namespace xsk::gsc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::h1
{
// H1 PC 1.15.1251288
constexpr usize code_count = 154;
constexpr usize func_count = 778;
constexpr usize meth_count = 1415;
constexpr usize token_count = 42947;
constexpr u32 max_string_id = 42989;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::h1

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::h2
{
// H2 PC 1.0.1280159
constexpr usize code_count = 154;
constexpr usize func_count = 800;
constexpr usize meth_count = 1491;
constexpr usize token_count = 42524;
constexpr u32 max_string_id = 54743;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::h2

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_pc
{
// IW5 PC 1.9.388110
constexpr usize code_count = 153;
constexpr usize func_count = 455;
constexpr usize meth_count = 780;
constexpr usize token_count = 6306;
constexpr u32 max_string_id = 33386;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_ps
{
// IW5 PS
constexpr usize code_count = 153;
constexpr usize func_count = 452;
constexpr usize meth_count = 777;
constexpr usize token_count = 14221;
constexpr u32 max_string_id = 33360;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw5_xb
{
// IW5 XB 1.8.388110
constexpr usize code_count = 153;
constexpr usize func_count = 455;
constexpr usize meth_count = 779;
constexpr usize token_count = 14221;
constexpr u32 max_string_id = 33386;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw5_xb

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_pc
{
// IW6 PC 3.15.146
constexpr usize code_count = 153;
constexpr usize func_count = 605;
constexpr usize meth_count = 1066;
constexpr usize token_count = 17657;
constexpr u32 max_string_id = 38305;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_ps
{
constexpr usize code_count = 153;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0x95A1;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw6_xb
{
constexpr usize code_count = 153;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0x8EFA;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw6_xb

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw7
{
constexpr usize code_count = 153;
constexpr usize func_count = 807;
constexpr usize meth_count = 1500;
constexpr usize token_count = 682;
constexpr u32 max_string_id = 0x13FCC;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw7

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw8
{
constexpr usize code_count = 190;
constexpr usize func_count = 1065;
constexpr usize meth_count = 2032;
constexpr usize token_count = 72014;
constexpr u32 max_string_id = 0x1472F;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw8

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::iw9
{
constexpr usize code_count = 167;
constexpr usize func_count = 905;
constexpr usize meth_count = 1469;
constexpr usize path_count = 1467;
constexpr usize hash_count = 73500;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::iw9

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_pc
{
constexpr usize code_count = 154;
constexpr usize func_count = 735;
constexpr usize meth_count = 1389;
constexpr usize token_count = 42942;
constexpr u32 max_string_id = 0xA7DC;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_pc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_ps
{
constexpr usize code_count = 154;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0xA51D; // TODO
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_ps

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s1_xb
{
constexpr usize code_count = 154;
constexpr usize func_count = 3;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0xA51D;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s1_xb

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s2
{
constexpr usize code_count = 155;
constexpr usize func_count = 1000;
constexpr usize meth_count = 1700;
constexpr usize token_count = 5;
constexpr u32 max_string_id = 0xACEE;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s2

View File

@ -0,0 +1,26 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::s4
{
constexpr usize code_count = 190;
constexpr usize func_count = 4;
constexpr usize meth_count = 0;
constexpr usize token_count = 0;
constexpr u32 max_string_id = 0x110F3;
class context : public gsc::context
{
public:
context();
};
} // namespace xsk::gsc::s4

View File

@ -0,0 +1,157 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::t4
{
enum class opcode : std::uint8_t
{
OP_End = 0x0,
OP_Return = 0x1,
OP_GetUndefined = 0x2,
OP_GetZero = 0x3,
OP_GetByte = 0x4,
OP_GetNegByte = 0x5,
OP_GetUnsignedShort = 0x6,
OP_GetNegUnsignedShort = 0x7,
OP_GetInteger = 0x8,
OP_GetFloat = 0x9,
OP_GetString = 0xA,
OP_GetIString = 0xB,
OP_GetVector = 0xC,
OP_GetLevelObject = 0xD,
OP_GetAnimObject = 0xE,
OP_GetSelf = 0xF,
OP_GetLevel = 0x10,
OP_GetGame = 0x11,
OP_GetAnim = 0x12,
OP_GetAnimation = 0x13,
OP_GetGameRef = 0x14,
OP_GetFunction = 0x15,
OP_CreateLocalVariable = 0x16,
OP_RemoveLocalVariables = 0x17,
OP_EvalLocalVariableCached0 = 0x18,
OP_EvalLocalVariableCached1 = 0x19,
OP_EvalLocalVariableCached2 = 0x1A,
OP_EvalLocalVariableCached3 = 0x1B,
OP_EvalLocalVariableCached4 = 0x1C,
OP_EvalLocalVariableCached5 = 0x1D,
OP_EvalLocalVariableCached = 0x1E,
OP_EvalLocalArrayCached = 0x1F,
OP_EvalArray = 0x20,
OP_EvalLocalArrayRefCached0 = 0x21,
OP_EvalLocalArrayRefCached = 0x22,
OP_EvalArrayRef = 0x23,
OP_ClearArray = 0x24,
OP_EmptyArray = 0x25,
OP_GetSelfObject = 0x26,
OP_EvalLevelFieldVariable = 0x27,
OP_EvalAnimFieldVariable = 0x28,
OP_EvalSelfFieldVariable = 0x29,
OP_EvalFieldVariable = 0x2A,
OP_EvalLevelFieldVariableRef = 0x2B,
OP_EvalAnimFieldVariableRef = 0x2C,
OP_EvalSelfFieldVariableRef = 0x2D,
OP_EvalFieldVariableRef = 0x2E,
OP_ClearFieldVariable = 0x2F,
OP_SafeCreateVariableFieldCached = 0x30,
OP_SafeSetVariableFieldCached0 = 0x31,
OP_SafeSetVariableFieldCached = 0x32,
OP_SafeSetWaittillVariableFieldCached = 0x33,
OP_clearparams = 0x34,
OP_checkclearparams = 0x35,
OP_EvalLocalVariableRefCached0 = 0x36,
OP_EvalLocalVariableRefCached = 0x37,
OP_SetLevelFieldVariableField = 0x38,
OP_SetVariableField = 0x39,
OP_SetAnimFieldVariableField = 0x3A,
OP_SetSelfFieldVariableField = 0x3B,
OP_SetLocalVariableFieldCached0 = 0x3C,
OP_SetLocalVariableFieldCached = 0x3D,
OP_CallBuiltin0 = 0x3E,
OP_CallBuiltin1 = 0x3F,
OP_CallBuiltin2 = 0x40,
OP_CallBuiltin3 = 0x41,
OP_CallBuiltin4 = 0x42,
OP_CallBuiltin5 = 0x43,
OP_CallBuiltin = 0x44,
OP_CallBuiltinMethod0 = 0x45,
OP_CallBuiltinMethod1 = 0x46,
OP_CallBuiltinMethod2 = 0x47,
OP_CallBuiltinMethod3 = 0x48,
OP_CallBuiltinMethod4 = 0x49,
OP_CallBuiltinMethod5 = 0x4A,
OP_CallBuiltinMethod = 0x4B,
OP_wait = 0x4C,
OP_waittillFrameEnd = 0x4D,
OP_PreScriptCall = 0x4E,
OP_ScriptFunctionCall2 = 0x4F,
OP_ScriptFunctionCall = 0x50,
OP_ScriptFunctionCallPointer = 0x51,
OP_ScriptMethodCall = 0x52,
OP_ScriptMethodCallPointer = 0x53,
OP_ScriptThreadCall = 0x54,
OP_ScriptThreadCallPointer = 0x55,
OP_ScriptMethodThreadCall = 0x56,
OP_ScriptMethodThreadCallPointer = 0x57,
OP_DecTop = 0x58,
OP_CastFieldObject = 0x59,
OP_EvalLocalVariableObjectCached = 0x5A,
OP_CastBool = 0x5B,
OP_BoolNot = 0x5C,
OP_BoolComplement = 0x5D,
OP_JumpOnFalse = 0x5E,
OP_JumpOnTrue = 0x5F,
OP_JumpOnFalseExpr = 0x60,
OP_JumpOnTrueExpr = 0x61,
OP_jump = 0x62,
OP_jumpback = 0x63,
OP_inc = 0x64,
OP_dec = 0x65,
OP_bit_or = 0x66,
OP_bit_ex_or = 0x67,
OP_bit_and = 0x68,
OP_equality = 0x69,
OP_inequality = 0x6A,
OP_less = 0x6B,
OP_greater = 0x6C,
OP_less_equal = 0x6D,
OP_greater_equal = 0x6E,
OP_shift_left = 0x6F,
OP_shift_right = 0x70,
OP_plus = 0x71,
OP_minus = 0x72,
OP_multiply = 0x73,
OP_divide = 0x74,
OP_mod = 0x75,
OP_size = 0x76,
OP_waittillmatch = 0x77,
OP_waittill = 0x78,
OP_notify = 0x79,
OP_endon = 0x7A,
OP_voidCodepos = 0x7B,
OP_switch = 0x7C,
OP_endswitch = 0x7D,
OP_vector = 0x7E,
OP_NOP = 0x7F,
OP_abort = 0x80,
OP_object = 0x81,
OP_thread_object = 0x82,
OP_EvalLocalVariable = 0x83,
OP_EvalLocalVariableRef = 0x84,
OP_prof_begin = 0x85,
OP_prof_end = 0x86,
OP_breakpoint = 0x87,
OP_assignmentBreakpoint = 0x88,
OP_manualAndAssignmentBreakpoint = 0x89,
OP_count = 0x8A,
};
} // namespace xsk::gsc::t4

View File

@ -0,0 +1,157 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/gsc/context.hpp"
namespace xsk::gsc::t5
{
enum class opcode : std::uint8_t
{
OP_End = 0x0,
OP_Return = 0x1,
OP_GetUndefined = 0x2,
OP_GetZero = 0x3,
OP_GetByte = 0x4,
OP_GetNegByte = 0x5,
OP_GetUnsignedShort = 0x6,
OP_GetNegUnsignedShort = 0x7,
OP_GetInteger = 0x8,
OP_GetFloat = 0x9,
OP_GetString = 0xA,
OP_GetIString = 0xB,
OP_GetVector = 0xC,
OP_GetLevelObject = 0xD,
OP_GetAnimObject = 0xE,
OP_GetSelf = 0xF,
OP_GetLevel = 0x10,
OP_GetGame = 0x11,
OP_GetAnim = 0x12,
OP_GetAnimation = 0x13,
OP_GetGameRef = 0x14,
OP_GetFunction = 0x15,
OP_CreateLocalVariable = 0x16,
OP_RemoveLocalVariables = 0x17,
OP_EvalLocalVariableCached0 = 0x18,
OP_EvalLocalVariableCached1 = 0x19,
OP_EvalLocalVariableCached2 = 0x1A,
OP_EvalLocalVariableCached3 = 0x1B,
OP_EvalLocalVariableCached4 = 0x1C,
OP_EvalLocalVariableCached5 = 0x1D,
OP_EvalLocalVariableCached = 0x1E,
OP_EvalLocalArrayCached = 0x1F,
OP_EvalArray = 0x20,
OP_EvalLocalArrayRefCached0 = 0x21,
OP_EvalLocalArrayRefCached = 0x22,
OP_EvalArrayRef = 0x23,
OP_ClearArray = 0x24,
OP_EmptyArray = 0x25,
OP_GetSelfObject = 0x26,
OP_EvalLevelFieldVariable = 0x27,
OP_EvalAnimFieldVariable = 0x28,
OP_EvalSelfFieldVariable = 0x29,
OP_EvalFieldVariable = 0x2A,
OP_EvalLevelFieldVariableRef = 0x2B,
OP_EvalAnimFieldVariableRef = 0x2C,
OP_EvalSelfFieldVariableRef = 0x2D,
OP_EvalFieldVariableRef = 0x2E,
OP_ClearFieldVariable = 0x2F,
OP_SafeCreateVariableFieldCached = 0x30,
OP_SafeSetVariableFieldCached0 = 0x31,
OP_SafeSetVariableFieldCached = 0x32,
OP_SafeSetWaittillVariableFieldCached = 0x33,
OP_clearparams = 0x34,
OP_checkclearparams = 0x35,
OP_EvalLocalVariableRefCached0 = 0x36,
OP_EvalLocalVariableRefCached = 0x37,
OP_SetLevelFieldVariableField = 0x38,
OP_SetVariableField = 0x39,
OP_SetAnimFieldVariableField = 0x3A,
OP_SetSelfFieldVariableField = 0x3B,
OP_SetLocalVariableFieldCached0 = 0x3C,
OP_SetLocalVariableFieldCached = 0x3D,
OP_CallBuiltin0 = 0x3E,
OP_CallBuiltin1 = 0x3F,
OP_CallBuiltin2 = 0x40,
OP_CallBuiltin3 = 0x41,
OP_CallBuiltin4 = 0x42,
OP_CallBuiltin5 = 0x43,
OP_CallBuiltin = 0x44,
OP_CallBuiltinMethod0 = 0x45,
OP_CallBuiltinMethod1 = 0x46,
OP_CallBuiltinMethod2 = 0x47,
OP_CallBuiltinMethod3 = 0x48,
OP_CallBuiltinMethod4 = 0x49,
OP_CallBuiltinMethod5 = 0x4A,
OP_CallBuiltinMethod = 0x4B,
OP_wait = 0x4C,
OP_waittillFrameEnd = 0x4D,
OP_PreScriptCall = 0x4E,
OP_ScriptFunctionCall2 = 0x4F,
OP_ScriptFunctionCall = 0x50,
OP_ScriptFunctionCallPointer = 0x51,
OP_ScriptMethodCall = 0x52,
OP_ScriptMethodCallPointer = 0x53,
OP_ScriptThreadCall = 0x54,
OP_ScriptThreadCallPointer = 0x55,
OP_ScriptMethodThreadCall = 0x56,
OP_ScriptMethodThreadCallPointer = 0x57,
OP_DecTop = 0x58,
OP_CastFieldObject = 0x59,
OP_EvalLocalVariableObjectCached = 0x5A,
OP_CastBool = 0x5B,
OP_BoolNot = 0x5C,
OP_BoolComplement = 0x5D,
OP_JumpOnFalse = 0x5E,
OP_JumpOnTrue = 0x5F,
OP_JumpOnFalseExpr = 0x60,
OP_JumpOnTrueExpr = 0x61,
OP_jump = 0x62,
OP_jumpback = 0x63,
OP_inc = 0x64,
OP_dec = 0x65,
OP_bit_or = 0x66,
OP_bit_ex_or = 0x67,
OP_bit_and = 0x68,
OP_equality = 0x69,
OP_inequality = 0x6A,
OP_less = 0x6B,
OP_greater = 0x6C,
OP_less_equal = 0x6D,
OP_greater_equal = 0x6E,
OP_shift_left = 0x6F,
OP_shift_right = 0x70,
OP_plus = 0x71,
OP_minus = 0x72,
OP_multiply = 0x73,
OP_divide = 0x74,
OP_mod = 0x75,
OP_size = 0x76,
OP_waittillmatch = 0x77,
OP_waittill = 0x78,
OP_notify = 0x79,
OP_endon = 0x7A,
OP_voidCodepos = 0x7B,
OP_switch = 0x7C,
OP_endswitch = 0x7D,
OP_vector = 0x7E,
OP_NOP = 0x7F,
OP_abort = 0x80,
OP_object = 0x81,
OP_thread_object = 0x82,
OP_EvalLocalVariable = 0x83,
OP_EvalLocalVariableRef = 0x84,
OP_prof_begin = 0x85,
OP_prof_end = 0x86,
OP_breakpoint = 0x87,
OP_assignmentBreakpoint = 0x88,
OP_manualAndAssignmentBreakpoint = 0x89,
OP_count = 0x8A,
};
} // namespace xsk::gsc::t5

33
include/xsk/gsc/lexer.hpp Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::gsc
{
class lexer
{
context const* ctx_;
lookahead reader_;
location loc_;
usize buflen_;
spacing spacing_;
bool indev_;
std::array<char, 0x1000> buffer_;
public:
lexer(context const* ctx, std::string const& name, char const* data, usize size);
auto lex() -> token;
private:
auto push(char c) -> void;
auto advance() -> void;
auto linewrap() -> void;
};
} // namespace xsk::gsc

5801
include/xsk/gsc/parser.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
// Copyright 2023 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 "common/types.hpp"
#include "lexer.hpp"
namespace xsk::gsc
{
class preprocessor
{
context* ctx_;
std::stack<lexer> lexer_;
std::stack<directive> indents_;
std::vector<std::string> includes_;
std::unordered_map<std::string_view, directive::kind> directives_;
std::unordered_map<std::string, define> defines_;
std::set<std::string> reject_;
std::deque<token> tokens_;
std::vector<token> expr_;
usize curr_expr_;
u32 expand_;
u32 skip_;
public:
preprocessor(context* ctx, std::string const& name, char const* data, usize size);
auto process() -> token;
auto push_header(std::string const& file) -> void;
auto pop_header() -> void;
auto ban_header(location const& loc) -> void;
private:
auto skip_line() -> void;
auto next_token() -> token;
auto read_token() -> token;
auto read_directive(token& tok) -> void;
auto read_directive_if(token& tok) -> void;
auto read_directive_ifdef(token& tok) -> void;
auto read_directive_ifndef(token& tok) -> void;
auto read_directive_elif(token& tok) -> void;
auto read_directive_elifdef(token& tok) -> void;
auto read_directive_elifndef(token& tok) -> void;
auto read_directive_else(token& tok) -> void;
auto read_directive_endif(token& tok) -> void;
auto read_directive_define(token& tok) -> void;
auto read_directive_undef(token& tok) -> void;
auto read_directive_pragma(token& tok) -> void;
auto read_directive_warning(token& tok) -> void;
auto read_directive_error(token& tok) -> void;
auto read_directive_line(token& tok) -> void;
auto read_directive_include(token& hash, token& name) -> void;
auto read_directive_inline(token& hash, token& name) -> void;
auto read_directive_usingtree(token& hash, token& name) -> void;
auto read_hashtoken(token& hash) -> void;
auto read_hashtoken_animtree(token& hash, token& name) -> void;
auto expand(token& tok, define& def) -> void;
auto expand_params(token& tok, define& def) -> std::vector<std::vector<token>>;
auto expect(token& tok, token::kind expected, spacing space = spacing::none) -> void;
auto evaluate() -> bool;
auto eval_next() -> token&;
auto eval_peek() -> token&;
auto eval_prev() -> token&;
auto eval_atend() -> bool;
auto eval_check(token::kind type) -> bool;
auto eval_match(token::kind type) -> bool;
auto eval_consume(token::kind type, std::string_view msg);
auto eval_expr() -> i32;
auto eval_expr_or() -> i32;
auto eval_expr_and() -> i32;
auto eval_expr_bwor() -> i32;
auto eval_expr_bwexor() -> i32;
auto eval_expr_bwand() -> i32;
auto eval_expr_eq() -> i32;
auto eval_expr_lge() -> i32;
auto eval_expr_shift() -> i32;
auto eval_expr_add() -> i32;
auto eval_expr_factor() -> i32;
auto eval_expr_unary() -> i32;
auto eval_expr_primary() -> i32;
};
} // namespace xsk::gsc

159
include/xsk/gsc/source.hpp Normal file
View File

@ -0,0 +1,159 @@
// Copyright 2023 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 "common/types.hpp"
namespace xsk::gsc
{
class source
{
context* ctx_;
std::vector<u8> buf_;
u32 indent_;
public:
source(context* ctx);
auto parse_assembly(buffer const& data) -> assembly::ptr;
auto parse_assembly(std::vector<u8> const& data) -> assembly::ptr;
auto parse_assembly(u8 const* data, usize size) -> assembly::ptr;
auto parse_program(std::string const& name, buffer const& data) -> program::ptr;
auto parse_program(std::string const& name, std::vector<u8> const& data) -> program::ptr;
auto parse_program(std::string const& name, u8 const* data, usize size) -> program::ptr;
auto dump(assembly const& data) -> std::vector<u8>;
auto dump(program const& data) -> std::vector<u8>;
private:
auto dump_assembly(assembly const& data) -> void;
auto dump_function(function const& func) -> void;
auto dump_instruction(instruction const& inst) -> void;
auto dump_program(program const& data) -> void;
auto dump_include(include const& inc) -> void;
auto dump_decl(decl const& dec) -> void;
auto dump_decl_dev_begin(decl_dev_begin const& dec) -> void;
auto dump_decl_dev_end(decl_dev_end const& dec) -> void;
auto dump_decl_usingtree(decl_usingtree const& dec) -> void;
auto dump_decl_constant(decl_constant const& dec) -> void;
auto dump_decl_function(decl_function const& dec) -> void;
auto dump_stmt(stmt const& stm) -> void;
auto dump_stmt_list(stmt_list const& stm) -> void;
auto dump_stmt_comp(stmt_comp const& stm) -> void;
auto dump_stmt_dev(stmt_dev const& stm) -> void;
auto dump_stmt_expr(stmt_expr const& stm) -> void;
auto dump_stmt_call(stmt_call const& stm) -> void;
auto dump_stmt_assign(stmt_assign const& stm) -> void;
auto dump_stmt_endon(stmt_endon const& stm) -> void;
auto dump_stmt_notify(stmt_notify const& stm) -> void;
auto dump_stmt_wait(stmt_wait const& stm) -> void;
auto dump_stmt_waittill(stmt_waittill const& stm) -> void;
auto dump_stmt_waittillmatch(stmt_waittillmatch const& stm) -> void;
auto dump_stmt_waittillframeend(stmt_waittillframeend const& stm) -> void;
auto dump_stmt_waitframe(stmt_waitframe const& stm) -> void;
auto dump_stmt_if(stmt_if const& stm) -> void;
auto dump_stmt_ifelse(stmt_ifelse const& stm) -> void;
auto dump_stmt_while(stmt_while const& stm) -> void;
auto dump_stmt_dowhile(stmt_dowhile const& stm) -> void;
auto dump_stmt_for(stmt_for const& stm) -> void;
auto dump_stmt_foreach(stmt_foreach const& stm) -> void;
auto dump_stmt_switch(stmt_switch const& stm) -> void;
auto dump_stmt_case(stmt_case const& stm) -> void;
auto dump_stmt_default(stmt_default const& stm) -> void;
auto dump_stmt_break(stmt_break const& stm) -> void;
auto dump_stmt_continue(stmt_continue const& stm) -> void;
auto dump_stmt_return(stmt_return const& stm) -> void;
auto dump_stmt_breakpoint(stmt_breakpoint const& stm) -> void;
auto dump_stmt_prof_begin(stmt_prof_begin const& stm) -> void;
auto dump_stmt_prof_end(stmt_prof_end const& stm) -> void;
auto dump_stmt_assert(stmt_assert const& stm) -> void;
auto dump_stmt_assertex(stmt_assertex const& stm) -> void;
auto dump_stmt_assertmsg(stmt_assertmsg const& stm) -> void;
auto dump_expr(expr const& exp) -> void;
auto dump_expr_increment(expr_increment const& exp) -> void;
auto dump_expr_decrement(expr_decrement const& exp) -> void;
auto dump_expr_assign_equal(expr_assign_equal const& exp) -> void;
auto dump_expr_assign_add(expr_assign_add const& exp) -> void;
auto dump_expr_assign_sub(expr_assign_sub const& exp) -> void;
auto dump_expr_assign_mul(expr_assign_mul const& exp) -> void;
auto dump_expr_assign_div(expr_assign_div const& exp) -> void;
auto dump_expr_assign_mod(expr_assign_mod const& exp) -> void;
auto dump_expr_assign_shift_left(expr_assign_shift_left const& exp) -> void;
auto dump_expr_assign_shift_right(expr_assign_shift_right const& exp) -> void;
auto dump_expr_assign_bitwise_or(expr_assign_bitwise_or const& exp) -> void;
auto dump_expr_assign_bitwise_and(expr_assign_bitwise_and const& exp) -> void;
auto dump_expr_assign_bitwise_exor(expr_assign_bitwise_exor const& exp) -> void;
auto dump_expr_ternary(expr_ternary const& exp) -> void;
auto dump_expr_or(expr_or const& exp) -> void;
auto dump_expr_and(expr_and const& exp) -> void;
auto dump_expr_equality(expr_equality const& exp) -> void;
auto dump_expr_inequality(expr_inequality const& exp) -> void;
auto dump_expr_less_equal(expr_less_equal const& exp) -> void;
auto dump_expr_greater_equal(expr_greater_equal const& exp) -> void;
auto dump_expr_less(expr_less const& exp) -> void;
auto dump_expr_greater(expr_greater const& exp) -> void;
auto dump_expr_add(expr_add const& exp) -> void;
auto dump_expr_sub(expr_sub const& exp) -> void;
auto dump_expr_mul(expr_mul const& exp) -> void;
auto dump_expr_div(expr_div const& exp) -> void;
auto dump_expr_mod(expr_mod const& exp) -> void;
auto dump_expr_shift_left(expr_shift_left const& exp) -> void;
auto dump_expr_shift_right(expr_shift_right const& exp) -> void;
auto dump_expr_bitwise_or(expr_bitwise_or const& exp) -> void;
auto dump_expr_bitwise_and(expr_bitwise_and const& exp) -> void;
auto dump_expr_bitwise_exor(expr_bitwise_exor const& exp) -> void;
auto dump_expr_not(expr_not const& exp) -> void;
auto dump_expr_negate(expr_negate const& exp) -> void;
auto dump_expr_complement(expr_complement const& exp) -> void;
auto dump_expr_call(expr_call const& exp) -> void;
auto dump_expr_method(expr_method const& exp) -> void;
auto dump_call(call const& exp) -> void;
auto dump_expr_function(expr_function const& exp) -> void;
auto dump_expr_pointer(expr_pointer const& exp) -> void;
auto dump_expr_add_array(expr_add_array const& exp) -> void;
auto dump_expr_parameters(expr_parameters const& exp) -> void;
auto dump_expr_arguments(expr_arguments const& exp) -> void;
auto dump_expr_isdefined(expr_isdefined const& exp) -> void;
auto dump_expr_istrue(expr_istrue const& exp) -> void;
auto dump_expr_reference(expr_reference const& exp) -> void;
auto dump_expr_tuple(expr_tuple const& exp) -> void;
auto dump_expr_array(expr_array const& exp) -> void;
auto dump_expr_field(expr_field const& exp) -> void;
auto dump_expr_size(expr_size const& exp) -> void;
auto dump_expr_paren(expr_paren const& exp) -> void;
auto dump_expr_thisthread(expr_thisthread const& exp) -> void;
auto dump_expr_empty_array(expr_empty_array const& exp) -> void;
auto dump_expr_undefined(expr_undefined const& exp) -> void;
auto dump_expr_game(expr_game const& exp) -> void;
auto dump_expr_self(expr_self const& exp) -> void;
auto dump_expr_anim(expr_anim const& exp) -> void;
auto dump_expr_level(expr_level const& exp) -> void;
auto dump_expr_animation(expr_animation const& exp) -> void;
auto dump_expr_animtree(expr_animtree const& exp) -> void;
auto dump_expr_identifier(expr_identifier const& exp) -> void;
auto dump_expr_path(expr_path const& exp) -> void;
auto dump_expr_istring(expr_istring const& exp) -> void;
auto dump_expr_string(expr_string const& exp) -> void;
auto dump_expr_vector(expr_vector const& exp) -> void;
auto dump_expr_float(expr_float const& exp) -> void;
auto dump_expr_integer(expr_integer const& exp) -> void;
auto dump_expr_false(expr_false const& exp) -> void;
auto dump_expr_true(expr_true const& exp) -> void;
auto dump_asm_jmp(asm_jmp const& exp) -> void;
auto dump_asm_jmp_back(asm_jmp_back const& exp) -> void;
auto dump_asm_jmp_cond(asm_jmp_cond const& exp) -> void;
auto dump_asm_jmp_true(asm_jmp_true const& exp) -> void;
auto dump_asm_jmp_false(asm_jmp_false const& exp) -> void;
auto dump_asm_switch(asm_switch const& exp) -> void;
auto dump_asm_endswitch(asm_endswitch const& exp) -> void;
auto dump_asm_prescriptcall(asm_prescriptcall const& exp) -> void;
auto dump_asm_voidcodepos(asm_voidcodepos const& exp) -> void;
auto dump_asm_create(asm_create const& exp) -> void;
auto dump_asm_access(asm_access const& exp) -> void;
auto dump_asm_remove(asm_remove const& exp) -> void;
auto dump_asm_clear(asm_clear const& exp) -> void;
};
} // namespace xsk::gsc

62
include/xsk/stdinc.hpp Normal file
View File

@ -0,0 +1,62 @@
// Copyright 2023 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 <cstdio>
#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <deque>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#if _WIN32
#include <format>
namespace fmt = std;
#else
#include <fmt/core.h>
#endif
#ifdef _WINDOWS_
#undef ERROR
#undef IN
#undef TRUE
#undef FALSE
#undef far
#endif
using namespace std::literals;
namespace xsk
{
using usize = std::size_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using i8 = std::int8_t;
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using f32 = float;
using f64 = double;
};

View File

@ -0,0 +1,47 @@
// Copyright 2023 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::arc::t6
{
class assembler : public arc::assembler
{
std::string filename_;
utils::writer::ptr script_;
assembly::ptr assembly_;
std::unordered_map<std::uint32_t, std::string> labels_;
std::unordered_map<std::string, std::uint16_t> stringlist_;
std::vector<export_ref> exports_;
std::vector<import_ref> imports_;
std::vector<animtree_ref> animtrees_;
std::vector<string_ref> stringtables_;
header header_;
public:
auto output() -> std::vector<std::uint8_t>;
void assemble(const std::string& file, std::vector<std::uint8_t>& data);
void assemble(const std::string& file, assembly::ptr& data);
private:
void assemble_function(const function::ptr& func);
void assemble_instruction(const instruction::ptr& inst);
void assemble_localvars(const instruction::ptr& inst);
void assemble_jump(const instruction::ptr& inst);
void assemble_switch(const instruction::ptr& inst);
void assemble_end_switch(const instruction::ptr& inst);
void process_string(const std::string& data);
void process_function(const function::ptr& func);
void process_instruction(const instruction::ptr& inst);
void align_instruction(const instruction::ptr& inst);
auto resolve_label(const std::string& name) -> std::int32_t;
auto string_offset(const std::string& data) -> std::uint16_t;
void add_string_reference(const std::string& str, string_type type, std::uint32_t ref);
void add_import_reference(const std::vector<std::string>& data, std::uint32_t ref);
void add_anim_reference(const std::vector<std::string>& data, std::uint32_t ref);
};
} // namespace xsk::arc::t6

View File

@ -0,0 +1,18 @@
// Copyright 2023 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 "location.hpp"
#include "types.hpp"
#include "block.hpp"
#include "nodetree.hpp"
#include "interfaces/exception.hpp"
#include "interfaces/assembler.hpp"
#include "interfaces/disassembler.hpp"
#include "interfaces/compiler.hpp"
#include "interfaces/decompiler.hpp"
#include "interfaces/context.hpp"

View File

@ -0,0 +1,25 @@
// Copyright 2023 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::arc
{
struct block
{
using ptr = std::unique_ptr<block>;
std::string loc_end;
std::string loc_break;
std::string loc_continue;
abort_t abort;
bool is_dev;
block() : abort(abort_t::abort_none), is_dev(false) {}
block(const std::string& lbreak, const std::string& lcont) : loc_break(lbreak), loc_continue(lcont), abort(abort_t::abort_none), is_dev(false) {}
};
} // namespace xsk::arc

View File

@ -0,0 +1,22 @@
// Copyright 2023 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::arc
{
class assembler
{
public:
using ptr = std::unique_ptr<assembler>;
virtual ~assembler() = default;
virtual auto output() -> std::vector<std::uint8_t> = 0;
virtual void assemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
virtual void assemble(const std::string& file, assembly::ptr& data) = 0;
};
} // namespace xsk::arc

View File

@ -0,0 +1,22 @@
// Copyright 2023 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::arc
{
class compiler
{
public:
using ptr = std::unique_ptr<compiler>;
virtual ~compiler() = default;
virtual auto output() -> assembly::ptr = 0;
virtual auto output_raw() -> std::vector<std::uint8_t> = 0;
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
};
} // namespace xsk::arc

View File

@ -0,0 +1,26 @@
// Copyright 2023 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::arc
{
class context
{
public:
using ptr = std::unique_ptr<context>;
virtual ~context() = default;
virtual void init(build mode, read_cb_type callback) = 0;
virtual void cleanup() = 0;
virtual auto assembler() -> assembler& = 0;
virtual auto disassembler() -> disassembler& = 0;
virtual auto compiler() -> compiler& = 0;
virtual auto decompiler() -> decompiler& = 0;
};
} // namespace xsk::arc

View File

@ -0,0 +1,21 @@
// Copyright 2023 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::arc
{
class decompiler
{
public:
using ptr = std::unique_ptr<decompiler>;
virtual ~decompiler() = default;
virtual auto output() -> std::vector<std::uint8_t> = 0;
virtual void decompile(const std::string& file, const assembly::ptr& data) = 0;
};
} // namespace xsk::arc

View File

@ -0,0 +1,22 @@
// Copyright 2023 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::arc
{
class disassembler
{
public:
using ptr = std::unique_ptr<disassembler>;
virtual ~disassembler() = default;
virtual auto output() -> assembly::ptr = 0;
virtual auto output_raw() -> std::vector<std::uint8_t> = 0;
virtual void disassemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
};
} // namespace xsk::arc

View File

@ -0,0 +1,46 @@
// Copyright 2023 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::arc
{
class error : public std::runtime_error
{
public:
error(const std::string& what)
: std::runtime_error("[ERROR]: "s + what) {}
};
class asm_error : public std::runtime_error
{
public:
asm_error(const std::string& what)
: std::runtime_error("[ERROR]:assembler: "s + what) {}
};
class disasm_error : public std::runtime_error
{
public:
disasm_error(const std::string& what)
: std::runtime_error("[ERROR]:disassembler: "s + what) {}
};
class comp_error : public std::runtime_error
{
public:
comp_error(const location& loc, const std::string& what)
: std::runtime_error("[ERROR]:compiler:" + loc.print() + ": " + what) {}
};
class decomp_error : public std::runtime_error
{
public:
decomp_error(const std::string& what)
: std::runtime_error("[ERROR]:decompiler: "s + what) {}
};
} // namespace xsk::arc

View File

@ -0,0 +1,229 @@
// Copyright 2023 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::arc
{
/// A point in a source file.
class position
{
public:
/// Type for file name.
typedef const std::string filename_type;
/// Type for line and column numbers.
typedef int counter_type;
/// Construct a position.
explicit position(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
: filename(f), line(l), column(c) {}
/// Initialization.
void initialize(filename_type *fn = nullptr, counter_type l = 1, counter_type c = 1)
{
filename = fn;
line = l;
column = c;
}
/** \name Line and Column related manipulators
** \{ */
/// (line related) Advance to the COUNT next lines.
void lines(counter_type count = 1)
{
if (count)
{
column = 1;
line = add_(line, count, 1);
}
}
/// (column related) Advance to the COUNT next columns.
void columns(counter_type count = 1)
{
column = add_(column, count, 1);
}
/** \} */
/// File name to which this position refers.
filename_type *filename;
/// Current line number.
counter_type line;
/// Current column number.
counter_type column;
private:
/// Compute max (min, lhs+rhs).
static counter_type add_(counter_type lhs, counter_type rhs, counter_type min)
{
return lhs + rhs < min ? min : lhs + rhs;
}
};
/// Add \a width columns, in place.
inline position& operator+=(position &res, position::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns.
inline position operator+(position res, position::counter_type width)
{
return res += width;
}
/// Subtract \a width columns, in place.
inline position& operator-=(position &res, position::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns.
inline position operator-(position res, position::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param pos a reference to the position to redirect
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const position &pos)
{
if (pos.filename)
ostr << *pos.filename << ':';
return ostr << pos.line << '.' << pos.column;
}
/// Two points in a source file.
class location
{
public:
/// Type for file name.
typedef position::filename_type filename_type;
/// Type for line and column numbers.
typedef position::counter_type counter_type;
/// Construct a location from \a b to \a e.
location(const position &b, const position &e)
: begin(b), end(e) {}
/// Construct a 0-width location in \a p.
explicit location(const position &p = position())
: begin(p), end(p) {}
/// Construct a 0-width location in \a f, \a l, \a c.
explicit location(filename_type *f, counter_type l = 1, counter_type c = 1)
: begin(f, l, c), end(f, l, c) {}
/// Initialization.
void initialize(filename_type *f = nullptr, counter_type l = 1, counter_type c = 1)
{
begin.initialize(f, l, c);
end = begin;
}
/** \name Line and Column related manipulators
** \{ */
public:
/// Reset initial location to final location.
void step()
{
begin = end;
}
/// Extend the current location to the COUNT next columns.
void columns(counter_type count = 1)
{
end += count;
}
/// Extend the current location to the COUNT next lines.
void lines(counter_type count = 1)
{
end.lines(count);
}
/** \} */
public:
auto print() const -> std::string
{
return *begin.filename + ":" + std::to_string(begin.line) + ":" + std::to_string(begin.column);
}
auto label() const -> std::string
{
return fmt::format("loc_{:X}", begin.line);
}
public:
/// Beginning of the located region.
position begin;
/// End of the located region.
position end;
};
/// Join two locations, in place.
inline location& operator+=(location &res, const location &end)
{
res.end = end.end;
return res;
}
/// Join two locations.
inline location operator+(location res, const location &end)
{
return res += end;
}
/// Add \a width columns to the end position, in place.
inline location& operator+=(location &res, location::counter_type width)
{
res.columns(width);
return res;
}
/// Add \a width columns to the end position.
inline location operator+(location res, location::counter_type width)
{
return res += width;
}
/// Subtract \a width columns to the end position, in place.
inline location& operator-=(location &res, location::counter_type width)
{
return res += -width;
}
/// Subtract \a width columns to the end position.
inline location operator-(location res, location::counter_type width)
{
return res -= width;
}
/** \brief Intercept output stream redirection.
** \param ostr the destination output stream
** \param loc a reference to the location to redirect
**
** Avoid duplicate information.
*/
template <typename YYChar>
std::basic_ostream<YYChar>& operator<<(std::basic_ostream<YYChar> &ostr, const location &loc)
{
location::counter_type end_col = 0 < loc.end.column ? loc.end.column - 1 : 0;
ostr << loc.begin;
if (loc.end.filename && (!loc.begin.filename || *loc.begin.filename != *loc.end.filename))
ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
else if (loc.begin.line < loc.end.line)
ostr << '-' << loc.end.line << '.' << end_col;
else if (loc.begin.column < end_col)
ostr << '-' << end_col;
return ostr;
}
} // namespace xsk::arc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
// Copyright 2023 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::arc
{
using read_cb_type = std::function<std::vector<std::uint8_t>(const std::string&)>;
enum class build
{
prod,
dev,
};
enum class abort_t
{
abort_none = 0,
abort_continue = 1,
abort_break = 2,
abort_return = 3,
};
struct include_t
{
std::string name;
std::vector<std::string> funcs;
include_t(const std::string& name, const std::vector<std::string>& funcs) : name(name), funcs(funcs) {}
};
struct animtree_t
{
std::string name;
bool loaded;
};
struct instruction
{
using ptr = std::unique_ptr<instruction>;
std::uint32_t index;
std::uint32_t size;
std::uint8_t opcode;
std::vector<std::string> data;
instruction() : index(0), size(0), opcode(0xFF) {}
};
struct function
{
using ptr = std::unique_ptr<function>;
std::uint32_t index;
std::uint32_t size;
std::uint8_t params;
std::uint8_t flags;
std::string name;
std::vector<instruction::ptr> instructions;
std::unordered_map<std::uint32_t, std::string> labels;
function() : index(0), size(0), params(0), flags(0) {}
};
struct animation_ref
{
using ptr = std::shared_ptr<animation_ref>;
std::string name;
std::uint32_t ref;
};
struct animtree_ref
{
using ptr = std::shared_ptr<animtree_ref>;
std::string name;
std::vector<std::uint32_t> refs;
std::vector<animation_ref> anims;
};
enum class string_type : std::uint8_t
{
literal = 0,
canonical = 1,
};
struct string_ref
{
using ptr = std::shared_ptr<string_ref>;
std::string name;
std::uint8_t type;
std::vector<std::uint32_t> refs;
};
enum class export_flags : std::uint8_t
{
export_none = 0x00,
export_public = 0x01,
export_autoexec = 0x02,
export_private = 0x04,
export_codecall = 0x08,
export_private2 = 0x10,
export_varargs = 0x20,
};
struct export_ref
{
using ptr = std::shared_ptr<export_ref>;
std::uint32_t checksum;
std::uint32_t offset;
std::string name;
std::string space;
std::uint8_t params;
std::uint8_t flags;
std::uint32_t size;
};
enum class import_flags : std::uint8_t
{
none = 0,
func_reference = 1,
func_call = 2,
func_call_thread = 3,
meth_call = 4,
meth_call_thread = 5,
developer = 0x10,
unk = 0x20, // T7, T8, T9
};
struct import_ref
{
using ptr = std::shared_ptr<import_ref>;
std::string space;
std::string name;
std::uint8_t params;
std::uint8_t flags;
std::vector<std::uint32_t> refs;
};
struct header
{
std::uint64_t magic;
std::uint32_t source_crc;
std::uint32_t include_offset;
std::uint32_t animtree_offset;
std::uint32_t cseg_offset;
std::uint32_t stringtablefixup_offset;
std::uint32_t exports_offset;
std::uint32_t imports_offset;
std::uint32_t fixup_offset;
std::uint32_t profile_offset;
std::uint32_t cseg_size;
std::uint16_t name;
std::uint16_t stringtablefixup_count;
std::uint16_t exports_count;
std::uint16_t imports_count;
std::uint16_t fixup_count;
std::uint16_t profile_count;
std::uint8_t include_count;
std::uint8_t animtree_count;
std::uint8_t flags;
// char[1] pad;
};
struct assembly
{
using ptr = std::unique_ptr<assembly>;
std::vector<function::ptr> functions;
std::vector<std::string> includes;
std::vector<animtree_ref> animtrees;
};
} // namespace xsk::arc

164
include/xsk/t6/compiler.hpp Normal file
View File

@ -0,0 +1,164 @@
// Copyright 2023 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::arc::t6
{
enum class opcode : std::uint8_t;
class compiler : public arc::compiler
{
std::string filename_;
assembly::ptr assembly_;
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<std::string> animtrees_;
std::unordered_map<std::string, ast::expr> constants_;
std::vector<block> blocks_;
bool can_break_;
bool can_continue_;
bool developer_thread_;
build mode_;
utils::writer::ptr output_;
public:
auto output() -> assembly::ptr;
auto output_raw() -> std::vector<std::uint8_t>;
void compile(const std::string& file, std::vector<std::uint8_t>& data);
void mode(build mode);
private:
auto parse_buffer(const std::string& file, const char* data, size_t size) -> ast::program::ptr;
auto parse_file(const std::string& file) -> ast::program::ptr;
void compile_program(const ast::program::ptr& program);
void emit_include(const ast::include::ptr& include);
void emit_declaration(const ast::decl& decl);
void emit_decl_usingtree(const ast::decl_usingtree::ptr& animtree);
void emit_decl_thread(const ast::decl_thread::ptr& thread);
void emit_stmt(const ast::stmt& stmt);
void emit_stmt_list(const ast::stmt_list::ptr& stmt);
void emit_stmt_dev(const ast::stmt_dev::ptr& stmt);
void emit_stmt_expr(const ast::stmt_expr::ptr& stmt);
void emit_stmt_call(const ast::stmt_call::ptr& stmt);
void emit_stmt_const(const ast::stmt_const::ptr& stmt);
void emit_stmt_assign(const ast::stmt_assign::ptr& stmt);
void emit_stmt_endon(const ast::stmt_endon::ptr& stmt);
void emit_stmt_notify(const ast::stmt_notify::ptr& stmt);
void emit_stmt_wait(const ast::stmt_wait::ptr& stmt);
void emit_stmt_waittill(const ast::stmt_waittill::ptr& stmt);
void emit_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt);
void emit_stmt_waittillframeend(const ast::stmt_waittillframeend::ptr& stmt);
void emit_stmt_if(const ast::stmt_if::ptr& stmt);
void emit_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt);
void emit_stmt_while(const ast::stmt_while::ptr& stmt);
void emit_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt);
void emit_stmt_for(const ast::stmt_for::ptr& stmt);
void emit_stmt_foreach(const ast::stmt_foreach::ptr& stmt);
void emit_stmt_switch(const ast::stmt_switch::ptr& stmt);
void emit_stmt_case(const ast::stmt_case::ptr& stmt);
void emit_stmt_default(const ast::stmt_default::ptr& stmt);
void emit_stmt_break(const ast::stmt_break::ptr& stmt);
void emit_stmt_continue(const ast::stmt_continue::ptr& stmt);
void emit_stmt_return(const ast::stmt_return::ptr& stmt);
void emit_stmt_prof_begin(const ast::stmt_prof_begin::ptr& stmt);
void emit_stmt_prof_end(const ast::stmt_prof_end::ptr& stmt);
void emit_expr(const ast::expr& expr);
void emit_expr_assign(const ast::expr_assign::ptr& expr);
void emit_expr_clear(const ast::expr& expr);
void emit_expr_increment(const ast::expr_increment::ptr& expr, bool is_stmt);
void emit_expr_decrement(const ast::expr_decrement::ptr& expr, bool is_stmt);
void emit_expr_ternary(const ast::expr_ternary::ptr& expr);
void emit_expr_binary(const ast::expr_binary::ptr& expr);
void emit_expr_and(const ast::expr_and::ptr& expr);
void emit_expr_or(const ast::expr_or::ptr& expr);
void emit_expr_complement(const ast::expr_complement::ptr& expr);
void emit_expr_negate(const ast::expr_negate::ptr& expr);
void emit_expr_not(const ast::expr_not::ptr& expr);
void emit_expr_call(const ast::expr_call::ptr& expr, bool is_stmt);
void emit_expr_call_pointer(const ast::expr_pointer::ptr& expr, bool is_stmt);
void emit_expr_call_function(const ast::expr_function::ptr& expr, bool is_stmt);
void emit_expr_method(const ast::expr_method::ptr& expr, bool is_stmt);
void emit_expr_method_pointer(const ast::expr_pointer::ptr& expr, const ast::expr& obj, bool is_stmt);
void emit_expr_method_function(const ast::expr_function::ptr& expr, const ast::expr& obj, bool is_stmt);
void emit_expr_parameters(const ast::expr_parameters::ptr& expr);
void emit_expr_arguments(const ast::expr_arguments::ptr& expr);
void emit_expr_isdefined(const ast::expr_isdefined::ptr& expr);
void emit_expr_vectorscale(const ast::expr_vectorscale::ptr& expr);
void emit_expr_anglestoup(const ast::expr_anglestoup::ptr& expr);
void emit_expr_anglestoright(const ast::expr_anglestoright::ptr& expr);
void emit_expr_anglestoforward(const ast::expr_anglestoforward::ptr& expr);
void emit_expr_angleclamp180(const ast::expr_angleclamp180::ptr& expr);
void emit_expr_vectortoangles(const ast::expr_vectortoangles::ptr& expr);
void emit_expr_abs(const ast::expr_abs::ptr& expr);
void emit_expr_gettime(const ast::expr_gettime::ptr& expr);
void emit_expr_getdvar(const ast::expr_getdvar::ptr& expr);
void emit_expr_getdvarint(const ast::expr_getdvarint::ptr& expr);
void emit_expr_getdvarfloat(const ast::expr_getdvarfloat::ptr& expr);
void emit_expr_getdvarvector(const ast::expr_getdvarvector::ptr& expr);
void emit_expr_getdvarcolorred(const ast::expr_getdvarcolorred::ptr& expr);
void emit_expr_getdvarcolorgreen(const ast::expr_getdvarcolorgreen::ptr& expr);
void emit_expr_getdvarcolorblue(const ast::expr_getdvarcolorblue::ptr& expr);
void emit_expr_getdvarcoloralpha(const ast::expr_getdvarcoloralpha::ptr& expr);
void emit_expr_getfirstarraykey(const ast::expr_getfirstarraykey::ptr& expr);
void emit_expr_getnextarraykey(const ast::expr_getnextarraykey::ptr& expr);
void emit_expr_reference(const ast::expr_reference::ptr& expr);
void emit_expr_size(const ast::expr_size::ptr& expr);
void emit_expr_variable_ref(const ast::expr& expr, bool set);
void emit_expr_array_ref(const ast::expr_array::ptr& expr, bool set);
void emit_expr_field_ref(const ast::expr_field::ptr& expr, bool set);
void emit_expr_local_ref(const ast::expr_identifier::ptr& expr, bool set);
void emit_expr_variable(const ast::expr& expr);
void emit_expr_array(const ast::expr_array::ptr& expr);
void emit_expr_field(const ast::expr_field::ptr& expr);
void emit_expr_local(const ast::expr_identifier::ptr& expr);
void emit_expr_object(const ast::expr& expr);
void emit_expr_vector(const ast::expr_vector::ptr& expr);
void emit_expr_animation(const ast::expr_animation::ptr& expr);
void emit_expr_animtree(const ast::expr_animtree::ptr& expr);
void emit_expr_istring(const ast::expr_istring::ptr& expr);
void emit_expr_string(const ast::expr_string::ptr& expr);
void emit_expr_hash(const ast::expr_hash::ptr& expr);
void emit_expr_float(const ast::expr_float::ptr& expr);
void emit_expr_integer(const ast::expr_integer::ptr& expr);
void emit_expr_false(const ast::expr_false::ptr& expr);
void emit_expr_true(const ast::expr_true::ptr& expr);
void emit_opcode(opcode op);
void emit_opcode(opcode op, const std::string& data);
void emit_opcode(opcode op, const std::vector<std::string>& data);
void process_thread(const ast::decl_thread::ptr& decl);
void process_stmt(const ast::stmt& stmt);
void process_stmt_list(const ast::stmt_list::ptr& stmt);
void process_stmt_dev(const ast::stmt_dev::ptr& stmt);
void process_stmt_expr(const ast::stmt_expr::ptr& stmt);
void process_stmt_assign(const ast::stmt_assign::ptr& stmt);
void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt);
void process_stmt_if(const ast::stmt_if::ptr& stmt);
void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt);
void process_stmt_while(const ast::stmt_while::ptr& stmt);
void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt);
void process_stmt_for(const ast::stmt_for::ptr& stmt);
void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt);
void process_stmt_switch(const ast::stmt_switch::ptr& stmt);
void process_expr(const ast::expr& expr);
void process_expr_parameters(const ast::expr_parameters::ptr& expr);
void variable_register(const std::string& name);
auto variable_access(const ast::expr_identifier::ptr& name) -> std::string;
auto is_constant_condition(const ast::expr& 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;
void print_function(const function::ptr& func);
void print_instruction(const instruction::ptr& inst);
};
} // namespace xsk::arc::t6

View File

@ -0,0 +1,28 @@
// Copyright 2023 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::arc::t6
{
class context : public arc::context
{
t6::assembler assembler_;
t6::disassembler disassembler_;
t6::compiler compiler_;
t6::decompiler decompiler_;
public:
void init(build mode, read_cb_type callback);
void cleanup();
auto assembler() -> arc::assembler& { return assembler_; }
auto disassembler() -> arc::disassembler& { return disassembler_; }
auto compiler() -> arc::compiler& { return compiler_; }
auto decompiler() -> arc::decompiler& { return decompiler_; }
};
} // namespace xsk::arc::t6

View File

@ -0,0 +1,100 @@
// Copyright 2023 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::arc::t6
{
class decompiler : public arc::decompiler
{
std::string filename_;
ast::program::ptr program_;
ast::decl_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<ast::node::ptr> stack_;
std::vector<std::string> locals_;
std::vector<block> blocks_;
bool in_waittill_;
bool retbool_;
int retnum_;
public:
auto output() -> std::vector<std::uint8_t>;
void decompile(const std::string& file, const assembly::ptr& data);
private:
void decompile_function(const function::ptr& func);
void decompile_instruction(const instruction::ptr& inst, bool last);
void decompile_expressions(const instruction::ptr& inst);
void decompile_statements(const ast::stmt_list::ptr& stmt);
void decompile_infinites(const ast::stmt_list::ptr& stmt);
void decompile_loops(const ast::stmt_list::ptr& stmt);
void decompile_switches(const ast::stmt_list::ptr& stmt);
void decompile_ifelses(const ast::stmt_list::ptr& stmt);
void decompile_aborts(const ast::stmt_list::ptr& stmt);
void decompile_devblocks(const ast::stmt_list::ptr& stmt);
void decompile_if(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_ifelse(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_inf(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_loop(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_while(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_dowhile(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_for(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_foreach(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end);
void decompile_switch(const ast::stmt_list::ptr& stmt, std::size_t begin);
auto find_location_reference(const ast::stmt_list::ptr& stmt, std::size_t begin, std::size_t end, const std::string& location) -> bool;
auto find_location_index(const ast::stmt_list::ptr& stmt, const std::string& location) -> std::size_t;
auto last_location_index(const ast::stmt_list::ptr& stmt, std::size_t index) -> bool;
auto lvalues_match(const ast::stmt_assign::ptr& stmt1, const ast::stmt_assign::ptr& stmt2) -> bool;
auto resolve_label(const std::string& name) -> std::uint32_t;
void process_thread(const ast::decl_thread::ptr& thread);
void process_stmt(const ast::stmt& stmt);
void process_stmt_list(const ast::stmt_list::ptr& stmt);
void process_stmt_dev(const ast::stmt_dev::ptr& stmt);
void process_stmt_expr(const ast::stmt_expr::ptr& stmt);
void process_stmt_call(const ast::stmt_call::ptr& stmt);
void process_stmt_assign(const ast::stmt_assign::ptr& stmt);
void process_stmt_endon(const ast::stmt_endon::ptr& stmt);
void process_stmt_notify(const ast::stmt_notify::ptr& stmt);
void process_stmt_wait(const ast::stmt_wait::ptr& stmt);
void process_stmt_waittill(const ast::stmt_waittill::ptr& stmt);
void process_stmt_waittillmatch(const ast::stmt_waittillmatch::ptr& stmt);
void process_stmt_if(const ast::stmt_if::ptr& stmt);
void process_stmt_ifelse(const ast::stmt_ifelse::ptr& stmt);
void process_stmt_while(const ast::stmt_while::ptr& stmt);
void process_stmt_dowhile(const ast::stmt_dowhile::ptr& stmt);
void process_stmt_for(const ast::stmt_for::ptr& stmt);
void process_stmt_foreach(const ast::stmt_foreach::ptr& stmt);
void process_stmt_switch(const ast::stmt_switch::ptr& stmt);
void process_stmt_cases(const ast::stmt_list::ptr& stmt);
void process_stmt_return(const ast::stmt_return::ptr& stmt);
void process_expr(const ast::expr& expr);
void process_expr_assign(ast::expr_assign::ptr& expr);
void process_expr_increment(const ast::expr_increment::ptr& expr);
void process_expr_decrement(const ast::expr_decrement::ptr& expr);
void process_expr_ternary(const ast::expr_ternary::ptr& expr);
void process_expr_binary(const ast::expr_binary::ptr& expr);
void process_expr_and(const ast::expr_and::ptr& expr);
void process_expr_or(const ast::expr_or::ptr& expr);
void process_expr_complement(const ast::expr_complement::ptr& expr);
void process_expr_not(const ast::expr_not::ptr& expr);
void process_expr_call(const ast::expr_call::ptr& expr);
void process_expr_method(const ast::expr_method::ptr& expr);
void process_expr_call_pointer(const ast::expr_pointer::ptr& expr);
void process_expr_call_function(const ast::expr_function::ptr& expr);
void process_expr_method_pointer(const ast::expr_pointer::ptr& expr, ast::expr& obj);
void process_expr_method_function(const ast::expr_function::ptr& expr, ast::expr& obj);
void process_expr_arguments(const ast::expr_arguments::ptr& expr);
void process_expr_size(const ast::expr_size::ptr& expr);
void process_array_variable(const ast::expr_array::ptr& expr);
void process_field_variable(const ast::expr_field::ptr& expr);
void process_expr_vector(const ast::expr_vector::ptr& expr);
void process_expr_parameters(const ast::expr_parameters::ptr& expr);
};
} // namespace xsk::arc::t6

View File

@ -0,0 +1,48 @@
// Copyright 2023 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::arc::t6
{
class disassembler : public arc::disassembler
{
std::string filename_;
utils::reader::ptr script_;
utils::writer::ptr output_;
assembly::ptr assembly_;
std::vector<export_ref::ptr> exports_;
std::vector<import_ref::ptr> imports_;
std::vector<string_ref::ptr> strings_;
std::vector<animtree_ref::ptr> animtrees_;
std::map<std::uint32_t, std::string> stringlist_;
std::map<std::uint32_t, import_ref::ptr> import_refs_;
std::map<std::uint32_t, string_ref::ptr> string_refs_;
std::map<std::uint32_t, animtree_ref::ptr> anim_refs_;
std::unordered_map<std::uint32_t, std::string> labels_;
header header_;
public:
auto output() -> assembly::ptr;
auto output_raw() -> std::vector<std::uint8_t>;
void disassemble(const std::string& file, std::vector<std::uint8_t>& data);
private:
void disassemble_function(const function::ptr& func);
void disassemble_instruction(const instruction::ptr& inst);
void disassemble_string(const instruction::ptr& inst);
void disassemble_animtree(const instruction::ptr& inst);
void disassemble_animation(const instruction::ptr& inst);
void disassemble_localvars(const instruction::ptr& inst);
void disassemble_import(const instruction::ptr& inst);
void disassemble_jump(const instruction::ptr& inst);
void disassemble_switch(const instruction::ptr& inst);
void disassemble_end_switch(const instruction::ptr& inst);
void print_function(const function::ptr& func);
void print_instruction(const instruction::ptr& inst);
};
} // namespace xsk::arc::t6

78
include/xsk/t6/lexer.hpp Normal file
View File

@ -0,0 +1,78 @@
// Copyright 2023 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::arc::t6
{
constexpr size_t max_buf_size = 0x2000;
struct buffer
{
char* data;
size_t length;
buffer();
~buffer();
bool push(char c);
};
struct reader
{
enum state_type : std::uint8_t { end, ok };
const char* buffer_pos;
std::uint32_t bytes_remaining;
char last_byte;
char current_byte;
state_type state;
reader();
reader(const reader& obj)
{
std::memcpy(this, &obj, sizeof(reader));
}
reader& operator=(const reader& obj)
{
std::memcpy(this, &obj, sizeof(reader));
return *this;
}
void init(const char* data, size_t size);
void advance();
};
class lexer
{
enum class state : std::uint8_t { start, string, localize, preprocessor };
reader reader_;
buffer buffer_;
location loc_;
std::stack<location> locs_;
std::stack<reader> readers_;
std::uint32_t header_top_;
state state_;
build mode_;
bool indev_;
bool clean_;
public:
lexer(build mode, const std::string& name, const char* data, size_t size);
auto lex() -> parser::symbol_type;
void push_header(const std::string& file);
void pop_header();
void ban_header(const location& loc);
private:
void advance();
void preprocessor_wrap();
void preprocessor_run(parser::token::token_kind_type token);
};
} // namespace xsk::arc::t6

6416
include/xsk/t6/parser.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
// Copyright 2023 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::arc::t6
{
class resolver
{
public:
static void init(read_cb_type callback);
static void cleanup();
static auto opcode_id(const std::string& name) -> std::uint8_t;
static auto opcode_name(std::uint8_t id) -> std::string;
static auto dvar_name(std::uint32_t id) -> std::string;
static auto make_token(std::string_view str) -> std::string;
static auto file_data(const std::string& name) -> std::tuple<const std::string*, const char*, size_t>;
static auto fs_to_game_path(const std::filesystem::path& file) -> std::filesystem::path;
};
} // namespace xsk::arc::t6

157
include/xsk/t6/t6.hpp Normal file
View File

@ -0,0 +1,157 @@
// Copyright 2023 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 "xsk/stdinc.hpp"
#include "xsk/utils/string.hpp"
#include "xsk/utils/reader.hpp"
#include "xsk/utils/writer.hpp"
#include "common/arc.hpp"
#include "assembler.hpp"
#include "disassembler.hpp"
#include "compiler.hpp"
#include "decompiler.hpp"
#include "resolver.hpp"
#include "context.hpp"
namespace xsk::arc::t6
{
constexpr std::uint64_t magic = 0x06000A0D43534780;
enum class opcode : std::uint8_t
{
OP_End = 0x0,
OP_Return = 0x1,
OP_GetUndefined = 0x2,
OP_GetZero = 0x3,
OP_GetByte = 0x4,
OP_GetNegByte = 0x5,
OP_GetUnsignedShort = 0x6,
OP_GetNegUnsignedShort = 0x7,
OP_GetInteger = 0x8,
OP_GetFloat = 0x9,
OP_GetString = 0xA,
OP_GetIString = 0xB,
OP_GetVector = 0xC,
OP_GetLevelObject = 0xD,
OP_GetAnimObject = 0xE,
OP_GetSelf = 0xF,
OP_GetLevel = 0x10,
OP_GetGame = 0x11,
OP_GetAnim = 0x12,
OP_GetAnimation = 0x13,
OP_GetGameRef = 0x14,
OP_GetFunction = 0x15,
OP_CreateLocalVariable = 0x16,
OP_SafeCreateLocalVariables = 0x17,
OP_RemoveLocalVariables = 0x18,
OP_EvalLocalVariableCached = 0x19,
OP_EvalArray = 0x1A,
OP_EvalLocalArrayRefCached = 0x1B,
OP_EvalArrayRef = 0x1C,
OP_ClearArray = 0x1D,
OP_EmptyArray = 0x1E,
OP_GetSelfObject = 0x1F,
OP_EvalFieldVariable = 0x20,
OP_EvalFieldVariableRef = 0x21,
OP_ClearFieldVariable = 0x22,
OP_SafeSetVariableFieldCached = 0x23,
OP_SafeSetWaittillVariableFieldCached = 0x24,
OP_ClearParams = 0x25,
OP_CheckClearParams = 0x26,
OP_EvalLocalVariableRefCached = 0x27,
OP_SetVariableField = 0x28,
OP_CallBuiltin = 0x29,
OP_CallBuiltinMethod = 0x2A,
OP_Wait = 0x2B,
OP_WaitTillFrameEnd = 0x2C,
OP_PreScriptCall = 0x2D,
OP_ScriptFunctionCall = 0x2E,
OP_ScriptFunctionCallPointer = 0x2F,
OP_ScriptMethodCall = 0x30,
OP_ScriptMethodCallPointer = 0x31,
OP_ScriptThreadCall = 0x32,
OP_ScriptThreadCallPointer = 0x33,
OP_ScriptMethodThreadCall = 0x34,
OP_ScriptMethodThreadCallPointer = 0x35,
OP_DecTop = 0x36,
OP_CastFieldObject = 0x37,
OP_CastBool = 0x38,
OP_BoolNot = 0x39,
OP_BoolComplement = 0x3A,
OP_JumpOnFalse = 0x3B,
OP_JumpOnTrue = 0x3C,
OP_JumpOnFalseExpr = 0x3D,
OP_JumpOnTrueExpr = 0x3E,
OP_Jump = 0x3F,
OP_JumpBack = 0x40,
OP_Inc = 0x41,
OP_Dec = 0x42,
OP_Bit_Or = 0x43,
OP_Bit_Xor = 0x44,
OP_Bit_And = 0x45,
OP_Equal = 0x46,
OP_NotEqual = 0x47,
OP_LessThan = 0x48,
OP_GreaterThan = 0x49,
OP_LessThanOrEqualTo = 0x4A,
OP_GreaterThanOrEqualTo = 0x4B,
OP_ShiftLeft = 0x4C,
OP_ShiftRight = 0x4D,
OP_Plus = 0x4E,
OP_Minus = 0x4F,
OP_Multiply = 0x50,
OP_Divide = 0x51,
OP_Modulus = 0x52,
OP_SizeOf = 0x53,
OP_WaitTillMatch = 0x54,
OP_WaitTill = 0x55,
OP_Notify = 0x56,
OP_EndOn = 0x57,
OP_VoidCodePos = 0x58,
OP_Switch = 0x59,
OP_EndSwitch = 0x5A,
OP_Vector = 0x5B,
OP_GetHash = 0x5C,
OP_RealWait = 0x5D,
OP_VectorConstant = 0x5E,
OP_IsDefined = 0x5F,
OP_VectorScale = 0x60,
OP_AnglesToUp = 0x61,
OP_AnglesToRight = 0x62,
OP_AnglesToForward = 0x63,
OP_AngleClamp180 = 0x64,
OP_VectorToAngles = 0x65,
OP_Abs = 0x66,
OP_GetTime = 0x67,
OP_GetDvar = 0x68,
OP_GetDvarInt = 0x69,
OP_GetDvarFloat = 0x6A,
OP_GetDvarVector = 0x6B,
OP_GetDvarColorRed = 0x6C,
OP_GetDvarColorGreen = 0x6D,
OP_GetDvarColorBlue = 0x6E,
OP_GetDvarColorAlpha = 0x6F,
OP_FirstArrayKey = 0x70,
OP_NextArrayKey = 0x71,
OP_ProfileStart = 0x72,
OP_ProfileStop = 0x73,
OP_SafeDecTop = 0x74,
OP_Nop = 0x75,
OP_Abort = 0x76,
OP_Object = 0x77,
OP_ThreadObject = 0x78,
OP_EvalLocalVariable = 0x79,
OP_EvalLocalVariableRef = 0x7A,
OP_DevblockBegin = 0x7B,
OP_DevblockEnd = 0x7C,
OP_Count = 0x7D,
};
auto opcode_size(std::uint8_t id) -> std::uint32_t;
} // namespace xsk::arc::t6

View File

@ -0,0 +1,21 @@
// Copyright 2023 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::utils
{
class file
{
public:
static auto read(std::filesystem::path const& file) -> std::vector<u8>;
static auto save(std::filesystem::path const& file, std::vector<u8> const& data) -> void;
static auto save(std::filesystem::path const& file, u8 const* data, usize size) -> void;
static auto length(std::filesystem::path const& file) -> usize;
static auto exists(std::filesystem::path const& file) -> bool;
};
} // namespace xsk::utils

View File

@ -0,0 +1,40 @@
// Copyright 2023 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::utils
{
class reader
{
public:
using ptr = std::unique_ptr<reader>;
private:
u8 const* data_;
u32 size_;
u32 pos_;
bool swap_;
public:
reader(bool swap = false);
reader(std::vector<u8> const& data, bool swap = false);
reader(u8 const* data, u32 size, bool swap = false);
template <typename T>
auto read() -> T;
auto read_cstr() -> std::string;
auto read_bytes(u32 pos, u32 count) -> std::string;
auto is_avail() -> bool;
auto seek(u32 size) -> void;
auto seek_neg(u32 size) -> void;
auto align(u32 size) -> u32;
auto data() -> u8 const*;
auto size() -> u32;
auto pos() -> u32;
auto pos(u32 pos) -> void;
};
} // namespace xsk::utils

View File

@ -0,0 +1,43 @@
// Copyright 2023 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::utils
{
class string
{
public:
template <typename ... Args>
static auto va(std::string const& format, Args ... args) -> std::string
{
usize size = snprintf(nullptr, 0, format.data(), args ...) + 1;
std::vector<char> buf;
buf.resize(size);
snprintf(buf.data(), size, format.data(), args ...);
return std::string(buf.data(), buf.data() + size - 1);
}
static auto oct_to_dec(char const* str) -> std::string;
static auto bin_to_dec(char const* str) -> std::string;
static auto hex_to_dec(char const* str) -> std::string;
static auto iequals(std::string const& a, std::string const& b) -> bool;
static auto is_number(std::string const& s) -> bool;
static auto is_hex_number(std::string const& s) -> bool;
static auto to_lower(std::string const& input) -> std::string;
static auto to_code(std::string const& input) -> std::string;
static auto to_literal(std::string const& input) -> std::string;
static auto fordslash(std::string const& s) -> std::string;
static auto backslash(std::string const& s) -> std::string;
static auto quote(std::string const& s, bool single = true) -> std::string;
static auto unquote(std::string const& s) -> std::string;
static auto split(std::string& str, char delimiter) -> std::vector<std::string>;
static auto clean_buffer_lines(std::vector<u8>& buffer) -> std::vector<std::string>;
static auto parse_code(std::string& line) -> std::vector<std::string>;
static auto float_string(float value, bool toint = false) -> std::string;
};
} // namespace xsk::utils

View File

@ -0,0 +1,41 @@
// Copyright 2023 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::utils
{
class writer
{
public:
using ptr = std::unique_ptr<writer>;
private:
u8* data_;
u32 size_;
u32 pos_;
bool swap_;
public:
writer(bool swap = false);
writer(u32 size, bool swap = false);
~writer();
auto clear() -> void;
template <typename T>
auto write(T data) -> void;
auto write_string(std::string const& data) -> void;
auto write_cstr(std::string const& data) -> void;
auto is_avail() -> bool;
auto seek(u32 size) -> void;
auto seek_neg(u32 size) -> void;
auto align(u32 size) -> u32;
auto data() -> u8 const*;
auto size() -> u32;
auto pos() -> u32;
auto pos(u32 pos) -> void;
};
} // namespace xsk::utils

View File

@ -0,0 +1,18 @@
// Copyright 2023 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::utils
{
class zlib
{
public:
static auto compress(std::vector<u8> const& data) -> std::vector<u8>;
static auto decompress(std::vector<u8> const& data, u32 length) -> std::vector<u8>;
};
} // namespace xsk::utils