feat(jup): jup template (#192)
This commit is contained in:
parent
fdd052dad9
commit
2caaf75128
@ -1,5 +1,5 @@
|
|||||||
[![build](https://github.com/xensik/gsc-tool/workflows/Build/badge.svg)](https://github.com/xensik/gsc-tool/actions)
|
|
||||||
[![sonar](https://sonarcloud.io/api/project_badges/measure?project=xensik_gsc-tool&metric=alert_status)](https://sonarcloud.io/summary/overall?id=xensik_gsc-tool)
|
[![sonar](https://sonarcloud.io/api/project_badges/measure?project=xensik_gsc-tool&metric=alert_status)](https://sonarcloud.io/summary/overall?id=xensik_gsc-tool)
|
||||||
|
[![build](https://github.com/xensik/gsc-tool/workflows/Build/badge.svg)](https://github.com/xensik/gsc-tool/actions)
|
||||||
[![issues](https://img.shields.io/github/issues/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/issues)
|
[![issues](https://img.shields.io/github/issues/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/issues)
|
||||||
[![license](https://img.shields.io/github/license/xensik/gsc-tool.svg)](https://github.com/xensik/gsc-tool/blob/dev/LICENSE)
|
[![license](https://img.shields.io/github/license/xensik/gsc-tool.svg)](https://github.com/xensik/gsc-tool/blob/dev/LICENSE)
|
||||||
[![releases](https://img.shields.io/github/v/release/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/releases)
|
[![releases](https://img.shields.io/github/v/release/xensik/gsc-tool)](https://github.com/xensik/gsc-tool/releases)
|
||||||
@ -23,6 +23,7 @@ A utility to compile & decompile IW engine game scripts.
|
|||||||
- **T7** *(Call of Duty: Black Ops III)* `PC` *(Decompiler)*
|
- **T7** *(Call of Duty: Black Ops III)* `PC` *(Decompiler)*
|
||||||
- **T8** *(Call of Duty: Black Ops 4)* ***\*WIP\****
|
- **T8** *(Call of Duty: Black Ops 4)* ***\*WIP\****
|
||||||
- **T9** *(Call of Duty: Black Ops Cold War)* ***\*WIP\****
|
- **T9** *(Call of Duty: Black Ops Cold War)* ***\*WIP\****
|
||||||
|
- **JUP** *(Call of Duty: Modern Warfare III (2023)* ***\*WIP\****
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
``gsc-tool [OPTIONS..] <path>``
|
``gsc-tool [OPTIONS..] <path>``
|
||||||
@ -33,11 +34,11 @@ A utility to compile & decompile IW engine game scripts.
|
|||||||
|
|
||||||
``-m, --mode <mode>`` [REQUIRED] one of: `asm`, `disasm`, `comp`, `decomp`, `parse`
|
``-m, --mode <mode>`` [REQUIRED] one of: `asm`, `disasm`, `comp`, `decomp`, `parse`
|
||||||
|
|
||||||
``-g, --game <game>`` [REQUIRED] one of: `iw5`, `iw6`, `iw7`, `iw8`, `iw9`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6` `t7` `t8` `t9`
|
``-g, --game <game>`` [REQUIRED] one of: `iw5`, `iw6`, `iw7`, `iw8`, `iw9`, `s1`, `s2`, `s4`, `h1`, `h2`, `t6` `t7` `t8` `t9` `jup`
|
||||||
|
|
||||||
``-s, --system <system>`` [REQUIRED] one of: `pc`, `ps3`, `ps4`, `ps5`, `xb2` (*360*), `xb3` (*One*), `xb4` (*Series X|S*), `wiiu`
|
``-s, --system <system>`` [REQUIRED] one of: `pc`, `ps3`, `ps4`, `ps5`, `xb2` (*360*), `xb3` (*One*), `xb4` (*Series X|S*), `wiiu`
|
||||||
|
|
||||||
``-d, --dev`` Enable developer mode (generate bytecode map).
|
``-d, --dev`` Enable developer mode (dev blocks & generate bytecode map).
|
||||||
|
|
||||||
``-z, --zonetool`` Enable zonetool mode (use .cgsc files).
|
``-z, --zonetool`` Enable zonetool mode (use .cgsc files).
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ enum class engine : u8
|
|||||||
t7,
|
t7,
|
||||||
t8,
|
t8,
|
||||||
t9,
|
t9,
|
||||||
|
jup
|
||||||
};
|
};
|
||||||
|
|
||||||
struct props
|
struct props
|
||||||
|
24
include/xsk/arc/engine/jup.hpp
Normal file
24
include/xsk/arc/engine/jup.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Copyright 2024 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::jup
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr usize code_count = 0;
|
||||||
|
constexpr usize hash_count = 0;
|
||||||
|
constexpr u64 header_magic = 0x38000A0D43534780;
|
||||||
|
|
||||||
|
class context : public arc::context
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
context();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace xsk::arc::jup
|
32
src/arc/engine/jup.cpp
Normal file
32
src/arc/engine/jup.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2024 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "xsk/arc/engine/jup.hpp"
|
||||||
|
|
||||||
|
namespace xsk::arc::jup
|
||||||
|
{
|
||||||
|
|
||||||
|
extern std::array<std::pair<u16, opcode>, code_count> const code_list;
|
||||||
|
// extern std::array<std::pair<u32, char const*>, hash_count> const hash_list;
|
||||||
|
|
||||||
|
context::context() : arc::context(props::v3, engine::jup, endian::little, system::pc, header_magic)
|
||||||
|
{
|
||||||
|
code_map_.reserve(code_list.size());
|
||||||
|
code_map_rev_.reserve(code_list.size());
|
||||||
|
// hash_map_.reserve(hash_list.size());
|
||||||
|
|
||||||
|
for (auto const& entry : code_list)
|
||||||
|
{
|
||||||
|
code_map_.insert({ entry.first, entry.second });
|
||||||
|
code_map_rev_.insert({ entry.second, entry.first });
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (auto const& entry : hash_list)
|
||||||
|
// {
|
||||||
|
// hash_map_.insert({ entry.first, entry.second });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace xsk::arc::jup
|
15
src/arc/engine/jup_code.cpp
Normal file
15
src/arc/engine/jup_code.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// Copyright 2024 xensik. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a GNU GPLv3 license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "xsk/arc/engine/jup.hpp"
|
||||||
|
|
||||||
|
namespace xsk::arc::jup
|
||||||
|
{
|
||||||
|
|
||||||
|
extern std::array<std::pair<u16, opcode>, code_count> const code_list
|
||||||
|
{{
|
||||||
|
}};
|
||||||
|
|
||||||
|
} // namespace xsk::arc::jup
|
@ -30,6 +30,7 @@
|
|||||||
#include "xsk/arc/engine/t7.hpp"
|
#include "xsk/arc/engine/t7.hpp"
|
||||||
#include "xsk/arc/engine/t8.hpp"
|
#include "xsk/arc/engine/t8.hpp"
|
||||||
#include "xsk/arc/engine/t9.hpp"
|
#include "xsk/arc/engine/t9.hpp"
|
||||||
|
#include "xsk/arc/engine/jup.hpp"
|
||||||
#include "xsk/version.hpp"
|
#include "xsk/version.hpp"
|
||||||
#include "cxxopts.hpp"
|
#include "cxxopts.hpp"
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ namespace xsk
|
|||||||
enum class result : i32 { success = 0, failure = 1 };
|
enum class result : i32 { success = 0, failure = 1 };
|
||||||
enum class fenc { _, source, assembly, binary, src_bin };
|
enum class fenc { _, source, assembly, binary, src_bin };
|
||||||
enum class mode { _, assemble, disassemble, compile, decompile, parse, rename };
|
enum class mode { _, assemble, disassemble, compile, decompile, parse, rename };
|
||||||
enum class game { _, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6, t7, t8, t9 };
|
enum class game { _, iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6, t7, t8, t9, jup };
|
||||||
enum class mach { _, pc, ps3, ps4, ps5, xb2, xb3, xb4, wiiu };
|
enum class mach { _, pc, ps3, ps4, ps5, xb2, xb3, xb4, wiiu };
|
||||||
|
|
||||||
std::unordered_map<std::string_view, fenc> const gsc_exts =
|
std::unordered_map<std::string_view, fenc> const gsc_exts =
|
||||||
@ -92,6 +93,7 @@ std::unordered_map<std::string_view, game> const games =
|
|||||||
{ "t7", game::t7 },
|
{ "t7", game::t7 },
|
||||||
{ "t8", game::t8 },
|
{ "t8", game::t8 },
|
||||||
{ "t9", game::t9 },
|
{ "t9", game::t9 },
|
||||||
|
{ "jup", game::jup },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<game, std::string_view> const games_rev =
|
std::map<game, std::string_view> const games_rev =
|
||||||
@ -110,6 +112,7 @@ std::map<game, std::string_view> const games_rev =
|
|||||||
{ game::t7, "t7" },
|
{ game::t7, "t7" },
|
||||||
{ game::t8, "t8" },
|
{ game::t8, "t8" },
|
||||||
{ game::t9, "t9" },
|
{ game::t9, "t9" },
|
||||||
|
{ game::jup, "jup" },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<std::string_view, mach> const machs =
|
std::unordered_map<std::string_view, mach> const machs =
|
||||||
@ -763,6 +766,9 @@ auto disassemble_file(game game, mach mach, fs::path const& file, fs::path rel)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (game > game::t7)
|
||||||
|
throw std::runtime_error("not implemented");
|
||||||
|
|
||||||
rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension().string().starts_with(".gsc") ? ".gscasm" : ".cscasm"));
|
rel = fs::path{ games_rev.at(game) } / rel / file.filename().replace_extension((file.extension().string().starts_with(".gsc") ? ".gscasm" : ".cscasm"));
|
||||||
|
|
||||||
auto data = utils::file::read(file.string());
|
auto data = utils::file::read(file.string());
|
||||||
@ -822,6 +828,9 @@ auto decompile_file(game game, mach mach, fs::path const& file, fs::path rel) ->
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (game > game::t7)
|
||||||
|
throw std::runtime_error("not implemented");
|
||||||
|
|
||||||
rel = fs::path{ games_rev.at(game) } / rel / file.filename();
|
rel = fs::path{ games_rev.at(game) } / rel / file.filename();
|
||||||
|
|
||||||
auto data = utils::file::read(file);
|
auto data = utils::file::read(file);
|
||||||
@ -841,11 +850,34 @@ auto decompile_file(game game, mach mach, fs::path const& file, fs::path rel) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto parse_file(game, mach, fs::path const&, fs::path) -> result
|
auto parse_file(game game, mach mach, fs::path file, fs::path rel) -> result
|
||||||
{
|
{
|
||||||
std::cerr << std::format("not implemented for treyarch\n");
|
try
|
||||||
|
{
|
||||||
|
if (game != game::t6)
|
||||||
|
throw std::runtime_error("not implemented");
|
||||||
|
|
||||||
|
rel = fs::path{ games_rev.at(game) } / rel / file.filename();
|
||||||
|
|
||||||
|
auto data = utils::file::read(file);
|
||||||
|
|
||||||
|
if (!std::memcmp(&data[0], "\x80GSC", 4))
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} at {}\n", "already compiled", file.generic_string());
|
||||||
|
return result::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prog = contexts[game][mach]->source().parse_program(file.string(), data);
|
||||||
|
utils::file::save(fs::path{ "parsed" } / rel, contexts[game][mach]->source().dump(*prog));
|
||||||
|
std::cout << std::format("parsed {}\n", rel.generic_string());
|
||||||
|
return result::success;
|
||||||
|
}
|
||||||
|
catch (std::exception const& e)
|
||||||
|
{
|
||||||
|
std::cerr << std::format("{} at {}\n", e.what(), file.generic_string());
|
||||||
return result::failure;
|
return result::failure;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto rename_file(game, mach, fs::path const&, fs::path) -> result
|
auto rename_file(game, mach, fs::path const&, fs::path) -> result
|
||||||
{
|
{
|
||||||
@ -910,42 +942,55 @@ auto init_t7(mach mach, bool dev) -> void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto init_t8(mach /*mach*/, bool /*dev*/) -> void
|
auto init_t8(mach mach, bool dev) -> void
|
||||||
{
|
{
|
||||||
|
if (contexts[game::t8].contains(mach)) return;
|
||||||
|
|
||||||
|
switch (mach)
|
||||||
|
{
|
||||||
|
case mach::pc:
|
||||||
|
{
|
||||||
|
contexts[game::t8][mach] = std::make_unique<t8::context>();
|
||||||
|
contexts[game::t8][mach]->init(dev ? build::dev : build::prod, fs_read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
throw std::runtime_error("not implemented");
|
throw std::runtime_error("not implemented");
|
||||||
|
}
|
||||||
// if (contexts[game::t8].contains(mach)) return;
|
|
||||||
|
|
||||||
// switch (mach)
|
|
||||||
// {
|
|
||||||
// case mach::pc:
|
|
||||||
// {
|
|
||||||
// contexts[game::t8][mach] = std::make_unique<t8::context>();
|
|
||||||
// contexts[game::t8][mach]->init(build::prod, fs_read);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// default:
|
|
||||||
// throw std::runtime_error("not implemented");
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto init_t9(mach /*mach*/, bool /*dev*/) -> void
|
auto init_t9(mach mach, bool dev) -> void
|
||||||
{
|
{
|
||||||
|
if (contexts[game::t9].contains(mach)) return;
|
||||||
|
|
||||||
|
switch (mach)
|
||||||
|
{
|
||||||
|
case mach::pc:
|
||||||
|
{
|
||||||
|
contexts[game::t9][mach] = std::make_unique<t9::context>();
|
||||||
|
contexts[game::t9][mach]->init(dev ? build::dev : build::prod, fs_read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
throw std::runtime_error("not implemented");
|
throw std::runtime_error("not implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if (contexts[game::t9].contains(mach)) return;
|
auto init_jup(mach mach, bool dev) -> void
|
||||||
|
{
|
||||||
|
if (contexts[game::jup].contains(mach)) return;
|
||||||
|
|
||||||
// switch (mach)
|
switch (mach)
|
||||||
// {
|
{
|
||||||
// case mach::pc:
|
case mach::pc:
|
||||||
// {
|
{
|
||||||
// contexts[game::t9][mach] = std::make_unique<t9::context>();
|
contexts[game::jup][mach] = std::make_unique<jup::context>();
|
||||||
// contexts[game::t9][mach]->init(build::prod, fs_read);
|
contexts[game::jup][mach]->init(dev ? build::dev : build::prod, fs_read);
|
||||||
// break;
|
break;
|
||||||
// }
|
}
|
||||||
// default:
|
default:
|
||||||
// throw std::runtime_error("not implemented");
|
throw std::runtime_error("not implemented");
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto init(game game, mach mach, bool dev) -> void
|
auto init(game game, mach mach, bool dev) -> void
|
||||||
@ -968,6 +1013,7 @@ auto init(game game, mach mach, bool dev) -> void
|
|||||||
case game::t7: init_t7(mach, dev); break;
|
case game::t7: init_t7(mach, dev); break;
|
||||||
case game::t8: init_t8(mach, dev); break;
|
case game::t8: init_t8(mach, dev); break;
|
||||||
case game::t9: init_t9(mach, dev); break;
|
case game::t9: init_t9(mach, dev); break;
|
||||||
|
case game::jup: init_jup(mach, dev); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1102,7 +1148,7 @@ auto main(u32 argc, char** argv) -> result
|
|||||||
|
|
||||||
options.add_options()
|
options.add_options()
|
||||||
("m,mode","[REQUIRED] one of: asm, disasm, comp, decomp, parse, rename", cxxopts::value<std::string>(), "<mode>")
|
("m,mode","[REQUIRED] one of: asm, disasm, comp, decomp, parse, rename", cxxopts::value<std::string>(), "<mode>")
|
||||||
("g,game", "[REQUIRED] one of: iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6, t7, t8, t9", cxxopts::value<std::string>(), "<game>")
|
("g,game", "[REQUIRED] one of: iw5, iw6, iw7, iw8, iw9, s1, s2, s4, h1, h2, t6, t7, t8, t9, jup", cxxopts::value<std::string>(), "<game>")
|
||||||
("s,system", "[REQUIRED] one of: pc, ps3, ps4, ps5, xb2 (360), xb3 (One), xb4 (Series X|S), wiiu", cxxopts::value<std::string>(), "<system>")
|
("s,system", "[REQUIRED] one of: pc, ps3, ps4, ps5, xb2 (360), xb3 (One), xb4 (Series X|S), wiiu", cxxopts::value<std::string>(), "<system>")
|
||||||
("p,path", "File or directory to process.", cxxopts::value<std::string>())
|
("p,path", "File or directory to process.", cxxopts::value<std::string>())
|
||||||
("d,dev", "Enable developer mode (dev blocks & generate bytecode map).", cxxopts::value<bool>()->implicit_value("true"))
|
("d,dev", "Enable developer mode (dev blocks & generate bytecode map).", cxxopts::value<bool>()->implicit_value("true"))
|
||||||
|
Loading…
Reference in New Issue
Block a user