blackops2 implementation
This commit is contained in:
24
src/utils/xsk/arc/block.hpp
Normal file
24
src/utils/xsk/arc/block.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2022 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() : is_dev(false), abort(abort_t::abort_none) {}
|
||||
};
|
||||
|
||||
} // namespace xsk::arc
|
22
src/utils/xsk/arc/interfaces/assembler.hpp
Normal file
22
src/utils/xsk/arc/interfaces/assembler.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 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
|
23
src/utils/xsk/arc/interfaces/compiler.hpp
Normal file
23
src/utils/xsk/arc/interfaces/compiler.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2022 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_data() -> std::vector<std::uint8_t> = 0;
|
||||
virtual void compile(const std::string& file, std::vector<std::uint8_t>& data) = 0;
|
||||
virtual void read_callback(std::function<std::vector<std::uint8_t>(const std::string&)> func) = 0;
|
||||
};
|
||||
|
||||
} // namespace xsk::arc
|
21
src/utils/xsk/arc/interfaces/decompiler.hpp
Normal file
21
src/utils/xsk/arc/interfaces/decompiler.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2022 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
|
22
src/utils/xsk/arc/interfaces/disassembler.hpp
Normal file
22
src/utils/xsk/arc/interfaces/disassembler.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2022 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_data() -> std::vector<std::uint8_t> = 0;
|
||||
virtual void disassemble(const std::string& file, std::vector<std::uint8_t>& data) = 0;
|
||||
};
|
||||
|
||||
} // namespace xsk::arc
|
46
src/utils/xsk/arc/interfaces/exception.hpp
Normal file
46
src/utils/xsk/arc/interfaces/exception.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2022 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
|
229
src/utils/xsk/arc/location.hpp
Normal file
229
src/utils/xsk/arc/location.hpp
Normal file
@ -0,0 +1,229 @@
|
||||
// Copyright 2022 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 utils::string::va("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
|
1917
src/utils/xsk/arc/nodetree.cpp
Normal file
1917
src/utils/xsk/arc/nodetree.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1924
src/utils/xsk/arc/nodetree.hpp
Normal file
1924
src/utils/xsk/arc/nodetree.hpp
Normal file
File diff suppressed because it is too large
Load Diff
179
src/utils/xsk/arc/types.hpp
Normal file
179
src/utils/xsk/arc/types.hpp
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright 2022 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
|
||||
{
|
||||
|
||||
enum class build
|
||||
{
|
||||
dev,
|
||||
prod,
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
none = 0x00,
|
||||
vis_public = 0x01,
|
||||
vis_autoexec = 0x02,
|
||||
vis_private = 0x04,
|
||||
unk1 = 0x08, // never seen
|
||||
unk2 = 0x10, // inside dev /##/ ?
|
||||
varargs_may = 0x20, // T7, T8, T9
|
||||
};
|
||||
|
||||
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
|
@ -131,7 +131,7 @@ auto node::precedence() -> std::uint8_t
|
||||
case kind::expr_shift_right: return 8;
|
||||
case kind::expr_add: return 9;
|
||||
case kind::expr_sub: return 9;
|
||||
case kind::expr_mul: return 10;
|
||||
case kind::expr_mul: return 10;
|
||||
case kind::expr_div: return 10;
|
||||
case kind::expr_mod: return 10;
|
||||
default: return 0;
|
||||
|
@ -24,3 +24,16 @@
|
||||
#include "gsc/interfaces/disassembler.hpp"
|
||||
#include "gsc/interfaces/compiler.hpp"
|
||||
#include "gsc/interfaces/decompiler.hpp"
|
||||
|
||||
// ARC Types
|
||||
#include "arc/location.hpp"
|
||||
#include "arc/types.hpp"
|
||||
#include "arc/block.hpp"
|
||||
#include "arc/nodetree.hpp"
|
||||
|
||||
// ARC Interfaces
|
||||
#include "arc/interfaces/exception.hpp"
|
||||
#include "arc/interfaces/assembler.hpp"
|
||||
#include "arc/interfaces/disassembler.hpp"
|
||||
#include "arc/interfaces/compiler.hpp"
|
||||
#include "arc/interfaces/decompiler.hpp"
|
||||
|
Reference in New Issue
Block a user