mirror of
https://github.com/open-goal/jak-project.git
synced 2026-11-09 03:59:49 -10:00
Compare commits
43
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e307c8a9e | ||
|
|
3a67f40098 | ||
|
|
cbfa65c78a | ||
|
|
681c419f17 | ||
|
|
a4e108cca6 | ||
|
|
f1ee25c640 | ||
|
|
af6de539b5 | ||
|
|
c72a086e49 | ||
|
|
a66d832b2f | ||
|
|
d29ab77892 | ||
|
|
e975eab15a | ||
|
|
441952186c | ||
|
|
d819d6da05 | ||
|
|
ce978638fe | ||
|
|
9d0009715e | ||
|
|
3856ae505a | ||
|
|
92c4390f0a | ||
|
|
a7c9151c6c | ||
|
|
82a23c747e | ||
|
|
f0b46ff2e5 | ||
|
|
9d80ada016 | ||
|
|
e81431bd21 | ||
|
|
57772c59a0 | ||
|
|
edae60d58d | ||
|
|
365fae4913 | ||
|
|
3d04ac958c | ||
|
|
849ba391d4 | ||
|
|
c8fbe26c7d | ||
|
|
fbab87b0fe | ||
|
|
1c170b741c | ||
|
|
b8f1ee5289 | ||
|
|
bdded9ad8c | ||
|
|
08a23793c8 | ||
|
|
291c89a851 | ||
|
|
b4113dda67 | ||
|
|
a485c236d6 | ||
|
|
73ff53f01d | ||
|
|
495a8bc26f | ||
|
|
90c11bde8f | ||
|
|
c2cccc48cd | ||
|
|
c5effb2395 | ||
|
|
5f3671b8a3 | ||
|
|
26bfac8555 |
No files matched your search
@@ -58,6 +58,11 @@ custom_assets/jak1/texture_replacements/*
|
||||
custom_assets/jak2/texture_replacements/*
|
||||
custom_assets/jak3/texture_replacements/*
|
||||
|
||||
# merc replacements
|
||||
custom_assets/jak1/merc_replacements/*
|
||||
custom_assets/jak2/merc_replacements/*
|
||||
custom_assets/jak3/merc_replacements/*
|
||||
|
||||
# generated cmake files
|
||||
svnrev.h
|
||||
common/versions/revision.h
|
||||
|
||||
@@ -145,7 +145,6 @@
|
||||
"name": "Game - Jak 1 - Runtime (boot)",
|
||||
"args": [
|
||||
"-v",
|
||||
"--portable",
|
||||
"--game",
|
||||
"jak1",
|
||||
"--",
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
std::string DmaTag::print() {
|
||||
std::string DmaTag::print() const {
|
||||
std::string result;
|
||||
const char* mode_names[8] = {"refe", "cnt", "next", "ref", "refs", "call", "ret", "end"};
|
||||
result += fmt::format("TAG: 0x{:08x} {:4s} qwc 0x{:04x}", addr, mode_names[(int)kind], qwc);
|
||||
@@ -15,7 +15,7 @@ std::string DmaTag::print() {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string VifCode::print() {
|
||||
std::string VifCode::print() const {
|
||||
std::string result;
|
||||
|
||||
switch (kind) {
|
||||
|
||||
+2
-2
@@ -52,7 +52,7 @@ struct DmaTag {
|
||||
|
||||
bool operator!=(const DmaTag& other) const { return !((*this) == other); }
|
||||
|
||||
std::string print();
|
||||
std::string print() const;
|
||||
};
|
||||
|
||||
inline void emulate_dma(const void* source_base, void* dest_base, u32 tadr, u32 dadr) {
|
||||
@@ -148,7 +148,7 @@ struct VifCode {
|
||||
u16 num;
|
||||
u16 immediate;
|
||||
|
||||
std::string print();
|
||||
std::string print() const;
|
||||
};
|
||||
|
||||
struct VifCodeStcycl {
|
||||
|
||||
@@ -240,6 +240,7 @@ static FormFormattingConfig new_top_level_inline_form(bool elide_new_line) {
|
||||
|
||||
const std::unordered_map<std::string, FormFormattingConfig> opengoal_form_config = {
|
||||
{"case", new_pair_rule(true)},
|
||||
{"case-str", new_pair_rule(true)},
|
||||
{"cond", new_pair_rule(false)},
|
||||
{"#cond", new_pair_rule(false)},
|
||||
{"in-package", new_top_level_inline_form(true)},
|
||||
|
||||
@@ -26,6 +26,8 @@ u64 get_current_tid() {
|
||||
}
|
||||
#endif
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/compress.h"
|
||||
#include "common/util/string_util.h"
|
||||
// clang-format on
|
||||
|
||||
u64 get_current_ts() {
|
||||
@@ -34,12 +36,12 @@ u64 get_current_ts() {
|
||||
|
||||
GlobalProfiler::GlobalProfiler() {
|
||||
m_t0 = get_current_ts();
|
||||
set_max_events(65536);
|
||||
m_nodes.resize(m_max_events);
|
||||
}
|
||||
|
||||
void GlobalProfiler::set_max_events(size_t event_count) {
|
||||
ASSERT(!m_enabled);
|
||||
m_nodes.resize(event_count);
|
||||
void GlobalProfiler::update_event_buffer_size(size_t new_size) {
|
||||
m_max_events = new_size;
|
||||
m_nodes.resize(m_max_events);
|
||||
}
|
||||
|
||||
void GlobalProfiler::set_waiting_for_event(const std::string& event_name) {
|
||||
@@ -72,6 +74,10 @@ void GlobalProfiler::root_event() {
|
||||
instant_event("ROOT");
|
||||
}
|
||||
|
||||
size_t GlobalProfiler::get_next_idx() {
|
||||
return (m_next_idx % m_nodes.size());
|
||||
}
|
||||
|
||||
void GlobalProfiler::begin_event(const char* name) {
|
||||
event(name, ProfNode::BEGIN);
|
||||
}
|
||||
@@ -96,8 +102,10 @@ void GlobalProfiler::set_enable(bool en) {
|
||||
m_enabled = en;
|
||||
}
|
||||
|
||||
void GlobalProfiler::dump_to_json(const std::string& path) {
|
||||
ASSERT(!m_enabled);
|
||||
void GlobalProfiler::dump_to_json() {
|
||||
if (m_enabled) {
|
||||
set_enable(false);
|
||||
}
|
||||
|
||||
nlohmann::json json;
|
||||
auto& trace_events = json["traceEvents"];
|
||||
@@ -185,7 +193,20 @@ void GlobalProfiler::dump_to_json(const std::string& path) {
|
||||
t.second.highest_at_target);
|
||||
}
|
||||
|
||||
file_util::write_text_file(path, json.dump());
|
||||
if (m_enable_compression) {
|
||||
const auto json_str = json.dump();
|
||||
const auto compressed_data =
|
||||
compression::compress_zstd_no_header(json_str.data(), json_str.size());
|
||||
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
|
||||
fmt::format("prof-{}.json.zst", str_util::current_local_timestamp_no_colons());
|
||||
file_util::create_dir_if_needed_for_file(file_path);
|
||||
file_util::write_binary_file(file_path, compressed_data.data(), compressed_data.size());
|
||||
} else {
|
||||
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
|
||||
fmt::format("prof-{}.json", str_util::current_local_timestamp_no_colons());
|
||||
file_util::create_dir_if_needed_for_file(file_path);
|
||||
file_util::write_text_file(file_path, json.dump());
|
||||
}
|
||||
}
|
||||
|
||||
GlobalProfiler gprof;
|
||||
|
||||
@@ -17,7 +17,8 @@ struct ProfNode {
|
||||
class GlobalProfiler {
|
||||
public:
|
||||
GlobalProfiler();
|
||||
void set_max_events(size_t event_count);
|
||||
size_t get_max_events() { return m_max_events; }
|
||||
void update_event_buffer_size(size_t new_size);
|
||||
void set_waiting_for_event(const std::string& event_name);
|
||||
void instant_event(const char* name);
|
||||
void begin_event(const char* name);
|
||||
@@ -25,11 +26,16 @@ class GlobalProfiler {
|
||||
void end_event();
|
||||
void clear();
|
||||
void set_enable(bool en);
|
||||
void dump_to_json(const std::string& path);
|
||||
void dump_to_json();
|
||||
void root_event();
|
||||
bool is_enabled() { return m_enabled; }
|
||||
size_t get_next_idx();
|
||||
|
||||
bool m_enable_compression = false;
|
||||
|
||||
private:
|
||||
std::atomic_bool m_enabled = false;
|
||||
size_t m_max_events = 65536;
|
||||
u64 m_t0 = 0;
|
||||
std::atomic_size_t m_next_idx = 0;
|
||||
std::vector<ProfNode> m_nodes;
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ void printstd(const char* format, va_list arg_list) {
|
||||
internal::log_vprintf(format, arg_list);
|
||||
}
|
||||
|
||||
// how many extra log files for a single program should be kept?
|
||||
// how many extra log files for a single program should be kept
|
||||
constexpr int LOG_ROTATE_MAX = 10;
|
||||
|
||||
void set_file(const std::string& filename,
|
||||
|
||||
@@ -29,8 +29,11 @@ class Wrapper {
|
||||
Wrapper(const std::string& _username,
|
||||
const Config& config,
|
||||
const StartupFile& startup,
|
||||
bool nrepl_alive)
|
||||
: username(_username), repl_config(config), startup_file(startup), nrepl_alive(nrepl_alive) {}
|
||||
bool _nrepl_alive)
|
||||
: username(_username),
|
||||
repl_config(config),
|
||||
startup_file(startup),
|
||||
nrepl_alive(_nrepl_alive) {}
|
||||
replxx::Replxx& get_repl() { return repl; }
|
||||
void init_settings();
|
||||
void reload_startup_file();
|
||||
|
||||
@@ -43,7 +43,151 @@ std::vector<std::string> jak2_slots = {
|
||||
};
|
||||
|
||||
std::vector<std::string> jak3_slots = {
|
||||
"skull-gem-dest", "jakc-arm", "jakc-eyebrow", "jakc-face", "jakc-finger", "jakc-hair",
|
||||
"skull-gem-dest",
|
||||
"jakc-arm",
|
||||
"jakc-eyebrow",
|
||||
"jakc-face",
|
||||
"jakc-finger",
|
||||
"jakc-hair",
|
||||
"jakchires-arm",
|
||||
"jakchires-eye",
|
||||
"jakchires-eyebrow",
|
||||
"jakchires-eyelid",
|
||||
"jakchires-facelft",
|
||||
"jakchires-facert",
|
||||
"jakchires-hair",
|
||||
// default-water
|
||||
"bomb-gradient",
|
||||
"blue-beam-dest",
|
||||
"lightjak-wings",
|
||||
"mushroom-dest",
|
||||
// default-warp
|
||||
"shield-env-rim-dest",
|
||||
// templea-water
|
||||
"templea-waterfall-dest",
|
||||
// templea-warp
|
||||
"holograph-env-rim-dest",
|
||||
// hanga-sprite
|
||||
"glider-ring-dest2",
|
||||
"glider-ring-dest",
|
||||
// foresta-water
|
||||
"fora-water-dest",
|
||||
"fora-waterfall-01-dest",
|
||||
"fora-water-wave-01-dest",
|
||||
// forestb-water
|
||||
"forb-water-dest",
|
||||
"forb-waterfall-01-dest",
|
||||
"forb-water-wave-01-dest",
|
||||
// lforplnt-pris
|
||||
"mh-gem-dest",
|
||||
// lmhcitya-tfrag
|
||||
"mhcitya-base-goo-01-dest",
|
||||
// lmhcityb-tfrag
|
||||
"mhcityb-base-goo-01-dest",
|
||||
// mhcitya-pris
|
||||
// "mhcity-de-door-skin-01-dest",
|
||||
// templec-water
|
||||
"tplc-water-dest",
|
||||
// sewc-water
|
||||
"sewer-water-01-c-dest",
|
||||
"sewer-waterfall-01-c-dest",
|
||||
"sewer-waterfall-02-c-dest",
|
||||
"sewer-water-wave-01-c-dest",
|
||||
"sewer-water-highlight-01-c-dest",
|
||||
// sewd-water
|
||||
"sewer-water-01-d-dest",
|
||||
"sewer-waterfall-02-d-dest",
|
||||
"sewer-water-highlight-01-d-dest",
|
||||
"sewer-water-wave-01-d-dest",
|
||||
"sewer-water-wave-02-d-dest",
|
||||
"sewer-water-still-01-d-dest",
|
||||
// sewe-water
|
||||
"sewer-water-01-e-dest",
|
||||
"sewer-waterfall-01-e-dest",
|
||||
"sewer-waterfall-02-e-dest",
|
||||
"sewer-water-highlight-01-e-dest",
|
||||
// sewg-water
|
||||
"sewer-water-01-g-dest",
|
||||
"sewer-waterfall-02-g-dest",
|
||||
"sewer-water-wave-01-g-dest",
|
||||
// sewh-water
|
||||
"sewer-water-01-h-dest",
|
||||
"sewer-waterfall-02-h-dest",
|
||||
"sewer-water-wave-02-h-dest",
|
||||
"sewer-watefall-froth-01-h-dest",
|
||||
// sewi-water
|
||||
"sewer-water-still-01-i-dest",
|
||||
"sewer-waterfall-02-i-dest",
|
||||
"sewer-water-wave-01-i-dest",
|
||||
// sewj-water
|
||||
"sewer-waterfall-02-j-dest",
|
||||
"sewer-watefall-froth-01-j-dest",
|
||||
// sewl-water
|
||||
"sewer-waterfall-02-l-dest",
|
||||
"sewer-watefall-froth-01-l-dest",
|
||||
// sewm-water
|
||||
"sewer-water-01-m-dest",
|
||||
"sewer-waterfall-01-m-dest",
|
||||
"sewer-waterfall-02-m-dest",
|
||||
"sewer-water-highlight-01-m-dest",
|
||||
"sewer-water-wave-01-m-dest",
|
||||
"sewer-water-still-01-m-dest",
|
||||
"sewer-watefall-froth-01-m-dest",
|
||||
// sewn-water
|
||||
"sewer-waterfall-01-n-dest",
|
||||
"sewer-waterfall-02-n-dest",
|
||||
// "sewer-water-highlight-01-n-dest",
|
||||
"sewer-water-wave-01-n-dest",
|
||||
"sewer-water-still-01-n-dest",
|
||||
// hanga-water
|
||||
// "des-thermal-01-dest",
|
||||
// desresc-warp
|
||||
"sat-shield-dest",
|
||||
// security
|
||||
"security-env-dest",
|
||||
"security-dot-dest",
|
||||
// lgunnorm-water
|
||||
"kg-target-c-forcefield-01-dest",
|
||||
// templex-water
|
||||
"temple-waterfall-dest",
|
||||
// desertd-water
|
||||
"des-waterfall-dest",
|
||||
// towerb-water
|
||||
"tow-energy-bridge-dest",
|
||||
// factoryb-water
|
||||
"hemi-gradient-dest",
|
||||
"hemi-gradient-flames-dest",
|
||||
// factoryc-alpha
|
||||
"facc-convey-dest",
|
||||
"facc-convey-02-dest",
|
||||
// waspal-water
|
||||
"waspala-water-dest",
|
||||
"waspala-waterfall-dest",
|
||||
// rubblea-water
|
||||
"rub-water-dest",
|
||||
// rubblea2-water
|
||||
"rub-water-desta2",
|
||||
// rubbleb-water
|
||||
"rub-water-destb",
|
||||
// rubblec-water
|
||||
"rub-water-destc",
|
||||
// nstb-quicksand
|
||||
"nstb-quicksand-dest",
|
||||
// ctyslumb-water
|
||||
"ctyslumb-water-dest",
|
||||
"ctyslumb-fountain-fall-dest",
|
||||
// ctyslumc-water
|
||||
"ctyslumc-water-dest",
|
||||
"ctyslumc-fountain-fall-dest",
|
||||
// mined-tfrag
|
||||
"mined-pillar-side-dest",
|
||||
"mined-pillar-top2side-dest",
|
||||
"mined-pillar-top-dest",
|
||||
// volcanoa-alpha
|
||||
"vola-lava-01-dest",
|
||||
"vola-lava-fall-dest",
|
||||
// wasstada-alpha
|
||||
"wstd-lava-base-dest",
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -46,4 +46,17 @@ std::vector<u8> decompress_zstd(const void* data, size_t size) {
|
||||
ASSERT(decomp_size == decompressed_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<u8> compress_zstd_no_header(const void* data, size_t size) {
|
||||
size_t max_compressed = ZSTD_compressBound(size);
|
||||
std::vector<u8> result(max_compressed);
|
||||
|
||||
size_t compressed_size = ZSTD_compress(result.data(), max_compressed, data, size, 1);
|
||||
if (ZSTD_isError(compressed_size)) {
|
||||
ASSERT_MSG(false, fmt::format("ZSTD error: {}", ZSTD_getErrorName(compressed_size)));
|
||||
}
|
||||
|
||||
result.resize(compressed_size);
|
||||
return result;
|
||||
}
|
||||
} // namespace compression
|
||||
@@ -8,4 +8,5 @@ namespace compression {
|
||||
// compress and decompress data with zstd
|
||||
std::vector<u8> compress_zstd(const void* data, size_t size);
|
||||
std::vector<u8> decompress_zstd(const void* data, size_t size);
|
||||
} // namespace compression
|
||||
std::vector<u8> compress_zstd_no_header(const void* data, size_t size);
|
||||
} // namespace compression
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
inline u64 fnv64(const void* data, u64 len) {
|
||||
u64 ret = 0xcbf29ce484222325;
|
||||
const auto* ptr = (const u8*)data;
|
||||
for (u64 i = 0; i < len; i++) {
|
||||
ret = 1099511628211 * (((u64)*ptr) ^ ret);
|
||||
ptr++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u64 fnv64(const std::string& str) {
|
||||
return fnv64(str.data(), str.length());
|
||||
}
|
||||
@@ -27,11 +27,11 @@ Range<int> parse_json_optional_integer_range(const nlohmann::json& json);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void json_get_optional(const nlohmann::json& json,
|
||||
void json_get_optional(const nlohmann::json& j,
|
||||
const std::string& key,
|
||||
std::optional<T>& optionalValue) {
|
||||
if (json.contains(key) && !json[key].is_null()) {
|
||||
optionalValue = json[key].get<T>();
|
||||
if (j.contains(key) && !j[key].is_null()) {
|
||||
optionalValue = j[key].get<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-8
@@ -3,20 +3,29 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/log/log.h"
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#ifdef _WIN32
|
||||
// clang-format off
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <psapi.h>
|
||||
// clang-format on
|
||||
size_t get_peak_rss() {
|
||||
HANDLE hProcess = GetCurrentProcess();
|
||||
PROCESS_MEMORY_COUNTERS pmc;
|
||||
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
|
||||
return pmc.PeakWorkingSetSize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#include <sys/resource.h>
|
||||
|
||||
size_t get_peak_rss() {
|
||||
rusage x;
|
||||
getrusage(RUSAGE_SELF, &x);
|
||||
return x.ru_maxrss * 1024;
|
||||
}
|
||||
|
||||
#else
|
||||
size_t get_peak_rss() {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
// Note: these are not implemented on windows and will return zero.
|
||||
size_t get_peak_rss();
|
||||
void setup_cpu_info();
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
// Note: You will still have to add them to your level's .gd file.
|
||||
// "art_groups": ["plat-ag"],
|
||||
|
||||
// If you have any custom models in the "custom_assets/jak1/models" folder that you want to use in your level, add them to this list.
|
||||
// If you have any custom models in the "custom_assets/jak1/models/custom_levels" folder that you want to use in your level, add them to this list.
|
||||
// Note: Like with art groups, these should also be added to your level's .gd file.
|
||||
"custom_models": ["test-actor"],
|
||||
|
||||
|
||||
File renamed without changes.
@@ -68,6 +68,7 @@ add_library(
|
||||
level_extractor/fr3_to_gltf.cpp
|
||||
level_extractor/MercData.cpp
|
||||
level_extractor/tfrag_tie_fixup.cpp
|
||||
level_extractor/merc_replacement.cpp
|
||||
|
||||
ObjectFile/LinkedObjectFile.cpp
|
||||
ObjectFile/LinkedObjectFileCreation.cpp
|
||||
@@ -89,7 +90,8 @@ add_library(
|
||||
VuDisasm/VuDisassembler.cpp
|
||||
VuDisasm/VuInstruction.cpp
|
||||
|
||||
config.cpp)
|
||||
config.cpp
|
||||
decompilation_process.cpp)
|
||||
|
||||
target_link_libraries(decomp
|
||||
lzokay
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace decompiler {
|
||||
*/
|
||||
class LinkedObjectFile {
|
||||
public:
|
||||
LinkedObjectFile(GameVersion version) : version(version){};
|
||||
LinkedObjectFile(GameVersion _version) : version(_version) {}
|
||||
void set_segment_count(int n_segs);
|
||||
void push_back_word_to_segment(uint32_t word, int segment);
|
||||
int get_label_id_for(int seg, int offset);
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
#include "ObjectFileDB.h"
|
||||
|
||||
#include "common/formatter/formatter.h"
|
||||
#include "common/goos/PrettyPrinter.h"
|
||||
#include "common/link_types.h"
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "common/util/string_util.h"
|
||||
#include <common/formatter/formatter.h>
|
||||
|
||||
#include "decompiler/IR2/Form.h"
|
||||
#include "decompiler/analysis/analyze_inspect_method.h"
|
||||
|
||||
@@ -54,12 +54,8 @@ void append_body_to_function_definition(goos::Object* top_form,
|
||||
body_elements.insert(body_elements.end(), inline_body.begin(), inline_body.end());
|
||||
// If the first element in the body is a docstring, add it first
|
||||
if (body_elements.size() > 0 && body_elements.at(0).is_string()) {
|
||||
if (version > GameVersion::Jak2) {
|
||||
initial_top_level_forms.push_back(
|
||||
goos::StringObject::make_new(fix_docstring_indent(inline_body.at(0).as_string()->data)));
|
||||
} else {
|
||||
initial_top_level_forms.push_back(inline_body.at(0));
|
||||
}
|
||||
initial_top_level_forms.push_back(
|
||||
goos::StringObject::make_new(fix_docstring_indent(inline_body.at(0).as_string()->data)));
|
||||
body_elements.erase(body_elements.begin());
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ Config make_config_via_json(nlohmann::json& json) {
|
||||
inputs_json.at("str_art_file_names").get<std::vector<std::string>>();
|
||||
}
|
||||
|
||||
config.audio_dir_file_name = inputs_json.at("audio_dir_file_name").get<std::string>();
|
||||
config.streamed_audio_file_names =
|
||||
inputs_json.at("streamed_audio_file_names").get<std::vector<std::string>>();
|
||||
|
||||
@@ -321,6 +320,9 @@ Config make_config_via_json(nlohmann::json& json) {
|
||||
if (json.contains("save_texture_pngs")) {
|
||||
config.save_texture_pngs = json.at("save_texture_pngs").get<bool>();
|
||||
}
|
||||
if (json.contains("rip_streamed_audio")) {
|
||||
config.rip_streamed_audio = json.at("rip_streamed_audio").get<bool>();
|
||||
}
|
||||
|
||||
if (inputs_json.contains("animated_textures")) {
|
||||
config.animated_textures =
|
||||
|
||||
+1
-2
@@ -102,8 +102,6 @@ struct Config {
|
||||
std::vector<std::string> str_file_names;
|
||||
std::vector<std::string> str_texture_file_names;
|
||||
std::vector<std::string> str_art_file_names;
|
||||
|
||||
std::string audio_dir_file_name;
|
||||
std::vector<std::string> streamed_audio_file_names;
|
||||
|
||||
std::string obj_file_name_map_file;
|
||||
@@ -175,6 +173,7 @@ struct Config {
|
||||
std::vector<std::string> levels_to_extract;
|
||||
bool levels_extract;
|
||||
bool save_texture_pngs = false;
|
||||
bool rip_streamed_audio = false;
|
||||
|
||||
DecompileHacks hacks;
|
||||
|
||||
|
||||
@@ -21102,7 +21102,7 @@
|
||||
:size-assert #x94
|
||||
:flag-assert #xf00300094
|
||||
(:methods
|
||||
(dumb-15 (_type_) none))
|
||||
(spawn-particles! (_type_) none))
|
||||
(:states
|
||||
hud-normal
|
||||
hud-coming-in
|
||||
|
||||
@@ -122,6 +122,9 @@
|
||||
// save game textures as .png files to decompiler_out/<game>/textures
|
||||
"save_texture_pngs": false,
|
||||
|
||||
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
|
||||
"rip_streamed_audio": false,
|
||||
|
||||
////////////////////////////
|
||||
// PATCHING OPTIONS
|
||||
////////////////////////////
|
||||
|
||||
@@ -258,10 +258,6 @@
|
||||
"TEXT/6COMMON.TXT"
|
||||
],
|
||||
|
||||
// uncomment the next line to extract audio to wave files.
|
||||
//"audio_dir_file_name": "jak1/VAG",
|
||||
"audio_dir_file_name": "",
|
||||
|
||||
"streamed_audio_file_names": [
|
||||
"VAGWAD.ENG",
|
||||
"VAGWAD.FRE",
|
||||
|
||||
@@ -228,9 +228,5 @@
|
||||
"TEXT/6COMMON.TXT"
|
||||
],
|
||||
|
||||
// uncomment the next line to extract audio to wave files.
|
||||
//"audio_dir_file_name": "jak1/VAG",
|
||||
"audio_dir_file_name": "",
|
||||
|
||||
"streamed_audio_file_names": ["VAGWAD.ENG", "VAGWAD.JAP"]
|
||||
}
|
||||
@@ -2515,6 +2515,7 @@
|
||||
(iop-mem 48)
|
||||
(cancel-dgo 49)
|
||||
(set-stereo-mode 50) ;; sound-rpc-set-stereo-mode
|
||||
(set-mirror 201)
|
||||
)
|
||||
|
||||
(defenum sound-group
|
||||
@@ -2829,6 +2830,17 @@
|
||||
:flag-assert #x900000004
|
||||
)
|
||||
|
||||
; added
|
||||
(defenum sound-mirror-mode
|
||||
:type uint8
|
||||
(normal)
|
||||
(mirrored)
|
||||
)
|
||||
|
||||
; added for mirror mode
|
||||
(deftype sound-rpc-set-mirror-mode (sound-rpc-cmd)
|
||||
((mirror sound-mirror-mode)))
|
||||
|
||||
(deftype sound-rpc-union (structure)
|
||||
((data uint32 20 :offset-assert 0)
|
||||
(load-bank sound-rpc-load-bank :offset 0)
|
||||
@@ -2852,6 +2864,7 @@
|
||||
(shutdown sound-rpc-shutdown :offset 0)
|
||||
(list-sounds sound-rpc-list-sounds :offset 0)
|
||||
(unload-music sound-rpc-unload-music :offset 0)
|
||||
(mirror-mode sound-rpc-set-mirror-mode :overlay-at (-> data 0))
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x50
|
||||
@@ -8774,6 +8787,7 @@ Unlike [[engine]], users can use [[engine-pers]] as a parent class."
|
||||
(progress-graphics-ps2-lod-dist #x1337)
|
||||
(progress-graphics-msaa-off #x1338)
|
||||
(progress-graphics-display #x1339)
|
||||
(language-name-finnish #x133a)
|
||||
)
|
||||
;; ---text-id-h:text-id
|
||||
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
"rip_collision": false,
|
||||
// save game textures as .png files to decompiler_out/<game>/textures
|
||||
"save_texture_pngs": false,
|
||||
|
||||
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
|
||||
"rip_streamed_audio": false,
|
||||
|
||||
////////////////////////////
|
||||
// PATCHING OPTIONS
|
||||
|
||||
@@ -441,10 +441,6 @@
|
||||
"TEXT/7COMMON.TXT"
|
||||
],
|
||||
|
||||
// uncomment the next line to extract audio to wave files.
|
||||
// "audio_dir_file_name": "jak2/VAG",
|
||||
"audio_dir_file_name": "",
|
||||
|
||||
"streamed_audio_file_names": [
|
||||
"VAGWAD.ENG",
|
||||
"VAGWAD.FRE",
|
||||
|
||||
+177
-108
@@ -15147,8 +15147,8 @@
|
||||
:size-assert #x4
|
||||
:flag-assert #xb00000004
|
||||
(:methods
|
||||
(init! (_type_) int) ;; 9
|
||||
(cloth-base-method-10 (_type_ cloth-params handle) int) ;; 10
|
||||
(update! (_type_) int) ;; 9
|
||||
(setup-from-params! (_type_ cloth-params handle) int) ;; 10
|
||||
)
|
||||
)
|
||||
|
||||
@@ -25908,8 +25908,33 @@
|
||||
:flag-assert #xe00000010
|
||||
)
|
||||
|
||||
;; doesn't exist, but referenced by type ref in the entity table.
|
||||
(deftype sail-boat-a (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype cty-window-a (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype city-window-a (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype cty-guard-turret (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype cty-fruit-stand (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype torn (process-drawable-reserved)
|
||||
()
|
||||
)
|
||||
|
||||
(deftype entity-info (basic)
|
||||
((ptype type :offset-assert 4) ;; guessed by decompiler
|
||||
((ptype object :offset-assert 4) ;; guessed by decompiler
|
||||
(pool symbol :offset-assert 8) ;; guessed by decompiler
|
||||
(heap-size int32 :offset-assert 12)
|
||||
)
|
||||
@@ -33950,7 +33975,7 @@
|
||||
)
|
||||
|
||||
(deftype particle-array (inline-array-class)
|
||||
((data verlet-particle :dynamic :inline :offset-assert 16)
|
||||
((data verlet-particle :dynamic :inline :offset-assert 16 :score 1)
|
||||
)
|
||||
:method-count-assert 14
|
||||
:size-assert #x10
|
||||
@@ -34017,12 +34042,12 @@
|
||||
:size-assert #x40
|
||||
:flag-assert #x1000000040
|
||||
(:methods
|
||||
(calculate-wind!
|
||||
(accumulate-external-forces!
|
||||
"If this cloth system has the wind flag, calculate the wind force."
|
||||
(_type_) none) ;; 11
|
||||
(verlet-particle-system-method-12 (_type_ float) none) ;; 12
|
||||
(verlet-particle-system-method-13 (_type_) none) ;; 13
|
||||
(verlet-particle-system-method-14 (_type_) none) ;; 14
|
||||
(compute-verlet-step (_type_ float) none) ;; 12
|
||||
(run-one-iteration "Run one iteration of the system." (_type_) none) ;; 13
|
||||
(reset! "Reset to stationary/default state." (_type_) none) ;; 14
|
||||
(debug-draw (_type_) none) ;; 15
|
||||
)
|
||||
)
|
||||
@@ -34082,9 +34107,9 @@
|
||||
"Set up this cloth system with the given [[cloth-params]]."
|
||||
(_type_ cloth-params) none) ;; 16
|
||||
(debug-draw-spheres (_type_) none) ;; 17
|
||||
(cloth-system-method-18 (_type_) int) ;; 18
|
||||
(cloth-system-method-19 (_type_) none) ;; 19
|
||||
(cloth-system-method-20 (_type_) none) ;; 20
|
||||
(post-physics-update (_type_) int) ;; 18
|
||||
(enforce-constraints-1 (_type_) none) ;; 19
|
||||
(enforce-constraints-2 (_type_) none) ;; 20
|
||||
(cloth-system-method-21 (_type_) none) ;; 21
|
||||
(cloth-system-method-22 (_type_) none) ;; 22
|
||||
(cloth-system-method-23 (_type_) none) ;; 23
|
||||
@@ -34098,9 +34123,9 @@
|
||||
(cloth-system-method-31 (_type_ current-position-info) none) ;; 31
|
||||
(cloth-system-method-32 (_type_ vector int int current-position-info) none) ;; 32
|
||||
(cloth-system-method-33 (_type_ vu-lights) none) ;; 33
|
||||
(cloth-system-method-34 (_type_) none) ;; 34
|
||||
(cloth-system-method-35 (_type_) none) ;; 35
|
||||
(cloth-system-method-36 (_type_) none) ;; 36
|
||||
(hide! (_type_) none) ;; 34
|
||||
(reset-locations (_type_) none) ;; 35
|
||||
(pre-physics-update "Callback to update prior to running verlet integration. Can handle movement of the entire system in the world, for example" (_type_) none) ;; 36
|
||||
(cloth-system-cmd-handler (_type_ pair) none) ;; 37
|
||||
)
|
||||
)
|
||||
@@ -34122,8 +34147,8 @@
|
||||
;; cloth ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern get-neighboring-faces (function vector int int int int int))
|
||||
(define-extern *normal-array* (pointer vector))
|
||||
(define-extern get-neighboring-faces (function vector4w int int int int int))
|
||||
(define-extern *normal-array* (inline-array vector))
|
||||
(define-extern light-vertex (function current-position-info vector rgba))
|
||||
(define-extern *once* symbol)
|
||||
(define-extern *cloth-fade-alpha* gs-alpha)
|
||||
@@ -34196,7 +34221,17 @@
|
||||
;; curves ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defenum loop-behavior
|
||||
:type uint64
|
||||
:bitfield #f
|
||||
(wrap)
|
||||
(clamp)
|
||||
(b2)
|
||||
(use-default)
|
||||
)
|
||||
|
||||
(deftype float-pair (structure)
|
||||
"Two floats. Specifies one point on a piecewise linear curve."
|
||||
((first float :offset-assert 0)
|
||||
(second float :offset-assert 4)
|
||||
(x float :offset 0)
|
||||
@@ -34208,6 +34243,7 @@
|
||||
)
|
||||
|
||||
(deftype float-pair-array (inline-array-class)
|
||||
"Array of points used to make a piecewise linear curve."
|
||||
((data float-pair :dynamic :inline :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 14
|
||||
@@ -34216,39 +34252,50 @@
|
||||
)
|
||||
|
||||
(deftype curve2d (basic)
|
||||
"Interface for evaluating a 2d curve.
|
||||
The input is a float (x-position) and the output is a float (y-position).
|
||||
The curve is over (0, 1). Values outside of the range are either clamped
|
||||
or wrapped depending on the loop-behavior flag."
|
||||
()
|
||||
:method-count-assert 10
|
||||
:size-assert #x4
|
||||
:flag-assert #xa00000004
|
||||
(:methods
|
||||
(curve2d-method-9 (_type_ float int) float) ;; 9
|
||||
(evaluate "Compute value of curve at the given position." (_type_ float loop-behavior) float) ;; 9
|
||||
)
|
||||
)
|
||||
|
||||
(deftype curve-color (basic)
|
||||
"Interface for evaluating a color curve. The input is a float, representing
|
||||
progress through the curve, and the result is a floating point rgba color."
|
||||
()
|
||||
:method-count-assert 10
|
||||
:size-assert #x4
|
||||
:flag-assert #xa00000004
|
||||
(:methods
|
||||
(curve-color-method-9 (_type_ float rgbaf int) rgbaf) ;; 9
|
||||
(evaluate "Compute value of curve at the given position." (_type_ float rgbaf loop-behavior) rgbaf) ;; 9
|
||||
)
|
||||
)
|
||||
|
||||
(deftype curve2d-piecewise (curve2d)
|
||||
"Implementation of 2d-curve for a piecewise linear curve.
|
||||
Not particularly efficient - each evaluation needs to check each point."
|
||||
((pts float-pair-array :offset-assert 4)
|
||||
(default-loop-behavior uint64 :offset-assert 8)
|
||||
(default-loop-behavior loop-behavior :offset-assert 8)
|
||||
)
|
||||
:method-count-assert 12
|
||||
:size-assert #x10
|
||||
:flag-assert #xc00000010
|
||||
(:methods
|
||||
(curve2d-piecewise-method-10 (_type_ int symbol int) none) ;; 10
|
||||
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
|
||||
(curve2d-piecewise-method-11 (_type_) none) ;; 11
|
||||
)
|
||||
)
|
||||
|
||||
(deftype curve2d-fast (curve2d)
|
||||
"Implementation of 2d piecewise linear curve which tries to be faster.
|
||||
While it is faster, it places the huge restriction that you can only have 4 points.
|
||||
Note that the xs should be negative here."
|
||||
((xs vector :inline :offset-assert 16)
|
||||
(ys vector :inline :offset-assert 32)
|
||||
(one-over-x-deltas vector :inline :offset-assert 48)
|
||||
@@ -34259,6 +34306,9 @@
|
||||
)
|
||||
|
||||
(deftype curve-color-fast (curve-color)
|
||||
"Implementation of color curve which tries to be faster.
|
||||
While it is faster, it again has the restriction that you only
|
||||
get 4 piecewise sections."
|
||||
((xs vector :inline :offset-assert 16)
|
||||
(ys vector 4 :inline :offset-assert 32)
|
||||
(one-over-x-deltas vector :inline :offset-assert 96)
|
||||
@@ -34269,6 +34319,8 @@
|
||||
)
|
||||
|
||||
(deftype color-pair (structure)
|
||||
"Single section of a piecewise linear color curve.
|
||||
Unlike the fast version, this stores x values exactly like you'd expect."
|
||||
((first float :offset-assert 0)
|
||||
(second rgbaf :inline :offset-assert 16)
|
||||
(x float :offset 0)
|
||||
@@ -34280,6 +34332,7 @@
|
||||
)
|
||||
|
||||
(deftype color-pair-array (inline-array-class)
|
||||
"Array of points for piecewise linear color curve."
|
||||
((data color-pair :dynamic :inline :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 14
|
||||
@@ -34288,21 +34341,22 @@
|
||||
)
|
||||
|
||||
(deftype curve-color-piecewise (curve-color)
|
||||
"Implementation of curve-color."
|
||||
((pts color-pair-array :offset-assert 4)
|
||||
(default-loop-behavior uint64 :offset-assert 8)
|
||||
(default-loop-behavior loop-behavior :offset-assert 8)
|
||||
)
|
||||
:method-count-assert 11
|
||||
:size-assert #x10
|
||||
:flag-assert #xb00000010
|
||||
(:methods
|
||||
(curve-color-piecewise-method-10 (_type_ int symbol uint) none) ;; 10
|
||||
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
|
||||
)
|
||||
)
|
||||
|
||||
(define-extern rgbaf-lerp! (function rgbaf rgbaf rgbaf float rgbaf))
|
||||
(define-extern evaluate-curve-fast (function curve2d-fast rgbaf rgbaf float))
|
||||
(define-extern evaluate-color-curve-fast (function curve-color-fast rgbaf rgbaf rgbaf))
|
||||
(define-extern rgba<-rgbaf (function rgba rgbaf int))
|
||||
(define-extern rgbaf-lerp! "Lerp all four components of rgba." (function rgbaf rgbaf rgbaf float rgbaf))
|
||||
(define-extern evaluate-curve-fast "Evaluate a curve2d-fast at the given value." (function curve2d-fast float float))
|
||||
(define-extern evaluate-color-curve-fast "Evaluate a color-curve-fast at the given value." (function curve-color-fast float rgbaf rgbaf))
|
||||
(define-extern rgba<-rgbaf "Convert rgbaf to rgba. Seems like the input rgba's value is not used in any way." (function rgba rgbaf rgba))
|
||||
(define-extern *curve-unity* curve2d-fast)
|
||||
(define-extern *curve-linear-up* curve2d-fast)
|
||||
(define-extern *curve-linear-down* curve2d-fast)
|
||||
@@ -34679,6 +34733,14 @@
|
||||
:flag-assert #xe00000010
|
||||
)
|
||||
|
||||
(defenum lie-mode
|
||||
:type uint64
|
||||
(appearance0)
|
||||
(appearance1)
|
||||
(appearance2)
|
||||
(use-two-strips 3)
|
||||
)
|
||||
|
||||
(deftype light-trail-composition (structure)
|
||||
((color-mode uint64 :offset-assert 0)
|
||||
(color-curve curve-color-piecewise :offset-assert 8)
|
||||
@@ -34696,8 +34758,8 @@
|
||||
(uv-mode uint64 :offset-assert 72)
|
||||
(uv-repeat-dist float :offset-assert 80)
|
||||
(max-age time-frame :offset-assert 88)
|
||||
(tex-id uint32 :offset-assert 96)
|
||||
(lie-mode uint64 :offset-assert 104)
|
||||
(tex-id texture-id :offset-assert 96)
|
||||
(lie-mode lie-mode :offset-assert 104)
|
||||
(lie-vector vector :inline :offset-assert 112)
|
||||
(zbuffer? symbol :offset-assert 128)
|
||||
(use-tape-mode? symbol :offset-assert 132)
|
||||
@@ -34711,7 +34773,7 @@
|
||||
|
||||
(deftype light-trail-breadcrumb (structure)
|
||||
((pos vector :inline :offset-assert 0)
|
||||
(birth-time uint32 :offset 12 :decomp-as time-frame)
|
||||
(birth-time uint32 :offset 12 :decomp-as time-frame :score 1)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x10
|
||||
@@ -34726,15 +34788,22 @@
|
||||
:flag-assert #xe00000010
|
||||
)
|
||||
|
||||
(defenum light-trail-decision
|
||||
:type uint64
|
||||
(added 0)
|
||||
(not-added 1)
|
||||
(reset 2)
|
||||
)
|
||||
|
||||
(deftype light-trail (basic)
|
||||
((crumb-array (array light-trail-breadcrumb) :offset-assert 4)
|
||||
((crumb-array (array uint8) :offset-assert 4)
|
||||
(crumb-size uint8 :offset-assert 8)
|
||||
(crumb-count int16 :offset-assert 10)
|
||||
(max-crumb-count int16 :offset-assert 12)
|
||||
(appearance light-trail-composition :offset-assert 16)
|
||||
(start-marker uint64 :offset-assert 24)
|
||||
(end-marker uint64 :offset-assert 32)
|
||||
(decision uint64 :offset-assert 40)
|
||||
(decision light-trail-decision :offset-assert 40)
|
||||
(total-distance-traveled float :offset-assert 48)
|
||||
(strip prim-strip :offset-assert 52)
|
||||
(strip2 prim-strip :offset-assert 56)
|
||||
@@ -34744,19 +34813,19 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1600000080
|
||||
(:methods
|
||||
(light-trail-method-9 (_type_ light-trail-composition int) none) ;; 9
|
||||
(light-trail-method-10 (_type_) none) ;; 10
|
||||
(light-trail-method-11 (_type_ vector time-frame) int) ;; 11
|
||||
(light-trail-method-12 (_type_) none) ;; 12
|
||||
(light-trail-method-13 (_type_) int) ;; 13
|
||||
(light-trail-method-14 (_type_) none) ;; 14
|
||||
(setup! "Initialize, including allocation of crumbs and strips on the process heap." (_type_ light-trail-composition int) none) ;; 9
|
||||
(reset! "Clear all tracked crumbs." (_type_) none) ;; 10
|
||||
(add-crumb! "Try adding a crumb, kicking out the oldest if there's not enough room. This may reject if it's too close to the previous." (_type_ vector time-frame) int) ;; 11
|
||||
(build-prim-strip! "Build the mesh for this light trail." (_type_) none) ;; 12
|
||||
(common-trans! "Call this on each frame to handle max-age." (_type_) int) ;; 13
|
||||
(expire-old-points! "Internal function to kill off points that are too old." (_type_) none) ;; 14
|
||||
(light-trail-method-15 (_type_) none) ;; 15
|
||||
(add-vert! (_type_ prim-strip vector float float float) none) ;; 16
|
||||
(light-trail-method-17 (_type_ vector float float vector float) symbol) ;; 17
|
||||
(light-trail-method-18 (_type_ light-trail-breadcrumb int vector vector) none) ;; 18
|
||||
(light-trail-method-19 (_type_ float int) none) ;; 19
|
||||
(add-vert-to-prim-strip! "Add a single vertex to the prim." (_type_ prim-strip vector rgba float float) none) ;; 16
|
||||
(add-tri-pair-to-prim! "Add two vertices to the prim strip to add two triangles" (_type_ vector rgba float vector float) symbol) ;; 17
|
||||
(calc-vertex-pos! (_type_ light-trail-breadcrumb int vector vector) none) ;; 18
|
||||
(crumb-age-out-callback "To be implemented by the user to smoothly interpolate out non-default entries in their crumb type." (_type_ float int) none) ;; 19
|
||||
(reset-crumbs! (_type_) none) ;; 20
|
||||
(light-trail-method-21 (_type_ vector) none) ;; 21
|
||||
(replace-last-crumb! "Similar to add-crumb, but will modify the last crumb instead of advancing." (_type_ vector) none) ;; 21
|
||||
)
|
||||
)
|
||||
|
||||
@@ -34774,7 +34843,7 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(weapon-trail-method-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
|
||||
(add-crumb-with-offset "Given two points, add the first and offset to a crumb." (_type_ vector vector) light-trail-breadcrumb) ;; 22
|
||||
(weapon-trail-method-23 (_type_ vector vector) none) ;; 23
|
||||
)
|
||||
)
|
||||
@@ -34793,8 +34862,8 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(tread-trail-method-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
|
||||
(tread-trail-method-23 (_type_ vector vector) light-trail-breadcrumb) ;; 23
|
||||
(add-crumb-with-offset (_type_ vector vector) none) ;; 22
|
||||
(tread-trail-method-23 (_type_ vector vector) none) ;; 23
|
||||
)
|
||||
)
|
||||
|
||||
@@ -34834,11 +34903,11 @@
|
||||
die ;; 15
|
||||
)
|
||||
(:methods
|
||||
(light-trail-tracker-method-16 (_type_ process-focusable vector) vector) ;; 16
|
||||
(light-trail-tracker-method-17 (_type_ process-focusable) symbol) ;; 17
|
||||
(light-trail-tracker-method-18 (_type_ process-focusable) symbol) ;; 18
|
||||
(light-trail-tracker-method-19 (_type_) symbol) ;; 19
|
||||
(light-trail-tracker-method-20 (_type_ vector) none) ;; 20
|
||||
(get-tracked-object-pos (_type_ process-focusable vector) vector) ;; 16
|
||||
(should-track? (_type_ process-focusable) symbol) ;; 17
|
||||
(should-end? (_type_ process-focusable) symbol) ;; 18
|
||||
(should-draw? (_type_) symbol) ;; 19
|
||||
(add-crumb! (_type_ vector) none) ;; 20
|
||||
)
|
||||
)
|
||||
|
||||
@@ -42779,7 +42848,7 @@
|
||||
:size-assert #xfc
|
||||
:flag-assert #x22008000fc
|
||||
(:methods
|
||||
(task-manager-desert-bbush-ring-method-32 (_type_) none) ;; 32
|
||||
(get-mgr-name (_type_) string) ;; 32
|
||||
(task-manager-desert-bbush-ring-method-33 (_type_) none) ;; 33
|
||||
)
|
||||
)
|
||||
@@ -44496,12 +44565,12 @@
|
||||
;; templea-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *templea-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *templea-warp-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern templea-warp-texture-anim-func function)
|
||||
;; (define-extern *templeb-warp-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern templeb-warp-texture-anim-func function)
|
||||
;; (define-extern *templec-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *templea-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *templea-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern templea-warp-texture-anim-func (function none))
|
||||
(define-extern *templeb-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern templeb-warp-texture-anim-func (function none))
|
||||
(define-extern *templec-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; hover-training ;;
|
||||
@@ -46284,16 +46353,16 @@
|
||||
;; sewer-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *sewc-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewd-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewe-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewg-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewh-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewi-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewj-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewl-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewm-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *sewn-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *sewc-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewd-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewe-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewg-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewh-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewi-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewj-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewl-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewm-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *sewn-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; kg-hopper ;;
|
||||
@@ -50287,7 +50356,7 @@
|
||||
;; desresc-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *desresc-warp-texture-anim-array* texture-anim-array)
|
||||
(define-extern *desresc-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; desert-rescue ;;
|
||||
@@ -50984,7 +51053,7 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern check-drop-level-ctyslumb-drop-userdata (function sparticle-system sparticle-cpuinfo vector none))
|
||||
(define-extern *ctyslumb-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *ctyslumb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; mech-part ;;
|
||||
@@ -51090,7 +51159,7 @@
|
||||
;; nstb-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *nstb-quicksand-anim-array* texture-anim-array)
|
||||
(define-extern *nstb-quicksand-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; nst-mood ;;
|
||||
@@ -51733,7 +51802,7 @@
|
||||
)
|
||||
)
|
||||
|
||||
(define-extern *ctyslumc-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *ctyslumc-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern ctyslumc-flag-init-by-other (function vector entity-actor object :behavior ctyslumc-flag))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -51908,8 +51977,8 @@
|
||||
;; factoryc-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *factoryc-alpha-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern set-facc-conveyor-speed! function)
|
||||
(define-extern *factoryc-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern set-facc-conveyor-speed! (function float float))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; conveyor ;;
|
||||
@@ -52558,7 +52627,7 @@
|
||||
|
||||
(define-extern wang-texture-anim-init (function texture-anim none))
|
||||
(define-extern real-wang-texture-anim-func (function texture-anim texture-anim none))
|
||||
(define-extern wang-texture-anim-func (function none))
|
||||
(define-extern wang-texture-anim-func (function texture-anim texture-anim none))
|
||||
(define-extern *hfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -54182,7 +54251,7 @@
|
||||
;; glider-ring-part ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *hanga-sprite-texture-anim-array* texture-anim-array)
|
||||
(define-extern *hanga-sprite-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern cloud-shadow-find-ground (function vector matrix vector vector float))
|
||||
(define-extern birth-func-fader (function sparticle-system sparticle-cpuinfo sparticle-launchinfo none))
|
||||
(define-extern sparticle-fader (function sparticle-system sparticle-cpuinfo sparticle-launchinfo none))
|
||||
@@ -54385,7 +54454,7 @@
|
||||
(define-extern hanga-login (function level none))
|
||||
(define-extern hanga-activate (function level none))
|
||||
(define-extern hanga-deactivate (function level none))
|
||||
(define-extern *hanga-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *hanga-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; elec-gate ;;
|
||||
@@ -57037,7 +57106,7 @@
|
||||
;; desertd-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *desertd-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *desertd-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctyfarm-obs ;;
|
||||
@@ -57861,7 +57930,7 @@
|
||||
|
||||
(deftype tire-trail-crumb (light-trail-breadcrumb)
|
||||
((offset vector :inline :offset-assert 16)
|
||||
(uu float :offset 28)
|
||||
(uu float :offset 28 :score 1)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
@@ -57874,13 +57943,13 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(tire-trail-method-22 (_type_) none) ;; 22
|
||||
(tire-trail-method-23 (_type_) none) ;; 23
|
||||
(add-crumb-with-offset-and-uu (_type_ vector vector float) none) ;; 22
|
||||
(tire-trail-method-23 (_type_ vector vector float) none) ;; 23
|
||||
)
|
||||
)
|
||||
|
||||
(deftype tire-trail-tracker (light-trail-tracker)
|
||||
()
|
||||
((trail tire-trail :override))
|
||||
:method-count-assert 21
|
||||
:size-assert #xac
|
||||
:flag-assert #x15003000ac
|
||||
@@ -60281,7 +60350,7 @@
|
||||
;; mhcityb-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *lmhcityb-tfrag-texture-anim-array* texture-anim-array)
|
||||
(define-extern *lmhcityb-tfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; rublcst-scenes ;;
|
||||
@@ -61291,7 +61360,7 @@
|
||||
(define-extern init-mood-tower (function mood-context float))
|
||||
(define-extern update-tower-lights (function mood-context none))
|
||||
(define-extern update-mood-tower (function mood-context float int none :behavior time-of-day-proc))
|
||||
(define-extern *towerb-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *towerb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; tower-scenes ;;
|
||||
@@ -63331,7 +63400,7 @@
|
||||
;; wasstada-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *wasstada-alpha-texture-anim-array* texture-anim-array)
|
||||
(define-extern *wasstada-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; wasstada-mood ;;
|
||||
@@ -63355,7 +63424,7 @@
|
||||
;; factorya-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *factoryb-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *factoryb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; factoryb-init ;;
|
||||
@@ -63367,9 +63436,9 @@
|
||||
;; mhcitya-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *lmhcitya-tfrag-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *mhcitya-pris-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern set-mhcity-de-door-skin! function)
|
||||
(define-extern *lmhcitya-tfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *mhcitya-pris-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern set-mhcity-de-door-skin! (function float float))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctyinda-part ;;
|
||||
@@ -63677,10 +63746,10 @@
|
||||
;; rubble-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *rubblea-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *rubblea2-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *rubbleb-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *rubblec-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *rubblea-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *rubblea2-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *rubbleb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *rubblec-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; stadiuma-part ;;
|
||||
@@ -65151,9 +65220,9 @@
|
||||
;; forest-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *foresta-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *forestb-water-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern *lforplnt-pris-texture-anim-array* texture-anim-array)
|
||||
(define-extern *foresta-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *forestb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *lforplnt-pris-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; forest-ring-chase ;;
|
||||
@@ -65410,8 +65479,8 @@
|
||||
;; ltnfxhip-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *ltnfxhip-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern ltnfxhip-texture-anim-func function)
|
||||
(define-extern *ltnfxhip-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern ltnfxhip-texture-anim-func (function none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctygenb-part ;;
|
||||
@@ -67812,7 +67881,7 @@
|
||||
;; gungame-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *lgunnorm-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *lgunnorm-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; gungame-obs ;;
|
||||
@@ -68092,8 +68161,8 @@
|
||||
;; ljkdxvin-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *ljkdxvin-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern ljkdxvin-texture-anim-func function)
|
||||
(define-extern *ljkdxvin-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern ljkdxvin-texture-anim-func (function none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; target-tube ;;
|
||||
@@ -71489,7 +71558,7 @@
|
||||
;; waspal-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *waspal-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *waspal-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; throne-scenes ;;
|
||||
@@ -72665,7 +72734,7 @@
|
||||
;; mined-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *mined-tfrag-texture-anim-array* texture-anim-array)
|
||||
(define-extern *mined-tfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern set-mined-pillar-texture! (function float none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -73051,8 +73120,8 @@
|
||||
;; volcanox-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *volcanox-warp-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern volcanox-warp-texture-anim-func function)
|
||||
(define-extern *volcanox-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern volcanox-warp-texture-anim-func (function none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; volcanox-mood ;;
|
||||
@@ -73252,7 +73321,7 @@
|
||||
;; templex-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *templex-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern *templex-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; templex-scenes ;;
|
||||
@@ -73635,7 +73704,7 @@
|
||||
;; volcano-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *volcanoa-alpha-texture-anim-array* texture-anim-array)
|
||||
(define-extern *volcanoa-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; spiky-frog ;;
|
||||
@@ -74348,8 +74417,8 @@
|
||||
;; deshover-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; (define-extern *deshover-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern deshover-texture-anim-func function)
|
||||
(define-extern *deshover-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern deshover-texture-anim-func (function none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; terraformer-head ;;
|
||||
|
||||
@@ -127,6 +127,9 @@
|
||||
// save game textures as .png files to decompiler_out/<game>/textures
|
||||
"save_texture_pngs": false,
|
||||
|
||||
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
|
||||
"rip_streamed_audio": false,
|
||||
|
||||
////////////////////////////
|
||||
// PATCHING OPTIONS
|
||||
////////////////////////////
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
[7, "(function none)"],
|
||||
[3, "(function symbol :behavior process)"]
|
||||
],
|
||||
"scene": [[4, "(function none :behavior scene-player)"]],
|
||||
"scene": [[4, "(function symbol :behavior scene-player)"]],
|
||||
"pov-camera": [
|
||||
[
|
||||
7,
|
||||
|
||||
@@ -333,10 +333,6 @@
|
||||
"TEXT/11COMMON.TXT"
|
||||
],
|
||||
|
||||
// uncomment the next line to extract audio to wave files.
|
||||
// "audio_dir_file_name": "jak3/VAG",
|
||||
"audio_dir_file_name": "",
|
||||
|
||||
"streamed_audio_file_names": [
|
||||
"VAGWAD.ENG",
|
||||
"VAGWAD.FRE",
|
||||
@@ -365,11 +361,315 @@
|
||||
"jakc-finger-dark",
|
||||
"jakc-hair-dark",
|
||||
|
||||
// darkjak-highres
|
||||
"jakchires-arm",
|
||||
"jakchires-arm-norm",
|
||||
"jakchires-arm-dark",
|
||||
"jakchires-eye",
|
||||
"jakchires-eye-norm",
|
||||
"jakchires-eye-dark",
|
||||
"jakchires-eyebrow",
|
||||
"jakchires-eyebrow-norm",
|
||||
"jakchires-eyebrow-dark",
|
||||
"jakchires-eyelid",
|
||||
"jakchires-eyelid-norm",
|
||||
"jakchires-eyelid-dark",
|
||||
"jakchires-facelft",
|
||||
"jakchires-facelft-norm",
|
||||
"jakchires-facelft-dark",
|
||||
"jakchires-facert",
|
||||
"jakchires-facert-norm",
|
||||
"jakchires-facert-dark",
|
||||
"jakchires-hair",
|
||||
"jakchires-hair-norm",
|
||||
"jakchires-hair-dark",
|
||||
|
||||
// Skull Gem
|
||||
"skull-gem-dest",
|
||||
"skull-gem-alpha-00",
|
||||
"skull-gem-alpha-01",
|
||||
"skull-gem-alpha-02"
|
||||
"skull-gem-alpha-02",
|
||||
|
||||
// default-water
|
||||
"bomb-gradient",
|
||||
"bomb-gradient-rim",
|
||||
"bomb-gradient-flames",
|
||||
"lightjak-wings",
|
||||
"lighjak-wings-u-src",
|
||||
"lightjak-wings-v-src",
|
||||
"mushroom-dest",
|
||||
"mushroom-src",
|
||||
|
||||
// default-warp
|
||||
"shield-env-rim-dest",
|
||||
"common-white",
|
||||
"shield-env-uscroll",
|
||||
"shield-env-rim-src",
|
||||
|
||||
// hanga-sprite
|
||||
"glider-ring-dest2",
|
||||
"glider-ring-dest",
|
||||
"splash-foam",
|
||||
"racegate",
|
||||
|
||||
// templea-water
|
||||
"templea-waterfall-dest",
|
||||
"templea-waterfall",
|
||||
|
||||
// templea-warp
|
||||
"holograph-env-rim-dest",
|
||||
"holograph-env-noise",
|
||||
"holograph-env-scan",
|
||||
"holograph-env-rim",
|
||||
"environment-phong-rim",
|
||||
|
||||
// foresta-water
|
||||
"fora-water-dest",
|
||||
"fora-water",
|
||||
"fora-waterfall-01-dest",
|
||||
"fora-waterfall-01",
|
||||
"fora-water-wave-01-dest",
|
||||
"fora-water-wave-01",
|
||||
|
||||
// forestb-water
|
||||
"forb-water-dest",
|
||||
"forb-water",
|
||||
"forb-waterfall-01-dest",
|
||||
"forb-waterfall-01",
|
||||
"forb-water-wave-01-dest",
|
||||
"forb-water-wave-01",
|
||||
|
||||
// lforplnt-pris
|
||||
"mh-gem-dest",
|
||||
"mh-gem",
|
||||
"mh-gem-alpha-01",
|
||||
"mh-gem-alpha-02",
|
||||
|
||||
// lmhcitya-tfrag
|
||||
"mhcitya-base-goo-01-dest",
|
||||
"mhcitya-base-goo-01",
|
||||
|
||||
// lmhcityb-tfrag
|
||||
"mhcityb-base-goo-01-dest",
|
||||
"mhcityb-base-goo-01",
|
||||
|
||||
// mhcitya-pris
|
||||
// "mhcity-de-door-skin-01-dest",
|
||||
// "mhcity-de-door-skin-01",
|
||||
// "mhcity-de-door-skin-02"
|
||||
|
||||
// templec-water
|
||||
"tplc-water-dest",
|
||||
"tplc-water",
|
||||
|
||||
// sewc-water
|
||||
"sewer-water-01-c-dest",
|
||||
"sewer-water-01-c",
|
||||
"sewer-waterfall-01-c-dest",
|
||||
"sewer-waterfall-01-c",
|
||||
"sewer-waterfall-02-c-dest",
|
||||
"sewer-waterfall-02-c",
|
||||
"sewer-water-wave-01-c-dest",
|
||||
"sewer-water-wave-01-c",
|
||||
"sewer-water-highlight-01-c-dest",
|
||||
"sewer-water-highlight-01-c",
|
||||
|
||||
// sewd-water
|
||||
"sewer-water-01-d-dest",
|
||||
"sewer-water-01-d",
|
||||
"sewer-waterfall-02-d-dest",
|
||||
"sewer-waterfall-02-d",
|
||||
"sewer-water-highlight-01-d-dest",
|
||||
"sewer-water-highlight-01-d",
|
||||
"sewer-water-wave-01-d-dest",
|
||||
"sewer-water-wave-01-d",
|
||||
"sewer-water-wave-02-d-dest",
|
||||
"sewer-water-wave-02-d",
|
||||
"sewer-water-still-01-d-dest",
|
||||
"sewer-water-still-01-d",
|
||||
|
||||
// sewe-water
|
||||
"sewer-water-01-e-dest",
|
||||
"sewer-water-01-e",
|
||||
"sewer-waterfall-01-e-dest",
|
||||
"sewer-waterfall-01-e",
|
||||
"sewer-waterfall-02-e-dest",
|
||||
"sewer-waterfall-02-e",
|
||||
"sewer-water-highlight-01-e-dest",
|
||||
"sewer-water-highlight-01-e",
|
||||
|
||||
// sewg-water
|
||||
"sewer-water-01-g-dest",
|
||||
"sewer-water-01-g",
|
||||
"sewer-waterfall-02-g-dest",
|
||||
"sewer-waterfall-02-g",
|
||||
"sewer-water-wave-01-g-dest",
|
||||
"sewer-water-wave-01-g",
|
||||
|
||||
// sewh-water
|
||||
"sewer-water-01-h-dest",
|
||||
"sewer-water-01-h",
|
||||
"sewer-waterfall-02-h-dest",
|
||||
"sewer-waterfall-02-h",
|
||||
"sewer-water-wave-02-h-dest",
|
||||
"sewer-water-wave-02-h",
|
||||
"sewer-watefall-froth-01-h-dest",
|
||||
"sewer-watefall-froth-01-h",
|
||||
|
||||
// sewi-water
|
||||
"sewer-water-still-01-i-dest",
|
||||
"sewer-water-still-01-i",
|
||||
"sewer-waterfall-02-i-dest",
|
||||
"sewer-waterfall-02-i",
|
||||
"sewer-water-wave-01-i-dest",
|
||||
"sewer-water-wave-01-i",
|
||||
|
||||
// sewj-water
|
||||
"sewer-waterfall-02-j-dest",
|
||||
"sewer-waterfall-02-j",
|
||||
"sewer-watefall-froth-01-j-dest",
|
||||
"sewer-watefall-froth-01-j",
|
||||
|
||||
// sewl-water
|
||||
"sewer-waterfall-02-l-dest",
|
||||
"sewer-waterfall-02-l",
|
||||
"sewer-watefall-froth-01-l-dest",
|
||||
"sewer-watefall-froth-01-l",
|
||||
|
||||
// sewm-water
|
||||
"sewer-water-01-m-dest",
|
||||
"sewer-water-01-m",
|
||||
"sewer-waterfall-01-m-dest",
|
||||
"sewer-waterfall-01-m",
|
||||
"sewer-waterfall-02-m-dest",
|
||||
"sewer-waterfall-02-m",
|
||||
"sewer-water-highlight-01-m-dest",
|
||||
"sewer-water-highlight-01-m",
|
||||
"sewer-water-wave-01-m-dest",
|
||||
"sewer-water-wave-01-m",
|
||||
"sewer-water-still-01-m-dest",
|
||||
"sewer-water-still-01-m",
|
||||
"sewer-watefall-froth-01-m-dest",
|
||||
"sewer-watefall-froth-01-m",
|
||||
|
||||
// sewn-water
|
||||
"sewer-waterfall-01-n-dest",
|
||||
"sewer-waterfall-01-n",
|
||||
"sewer-waterfall-02-n-dest",
|
||||
"sewer-waterfall-02-n",
|
||||
// "sewer-water-highlight-01-n-dest",
|
||||
// "sewer-water-highlight-01-n",
|
||||
"sewer-water-wave-01-n-dest",
|
||||
"sewer-water-wave-01-n",
|
||||
"sewer-water-still-01-n-dest",
|
||||
"sewer-water-still-01-n",
|
||||
|
||||
// hanga-water
|
||||
// "des-thermal-01-dest",
|
||||
// "des-thermal-01"
|
||||
|
||||
// desresc-warp
|
||||
"sat-shield-dest",
|
||||
"sat-shield-env-uvscroll",
|
||||
"sat-shield",
|
||||
|
||||
// security
|
||||
"security-env-dest",
|
||||
"security-env-uscroll",
|
||||
"security-dot-dest",
|
||||
"security-dot-src",
|
||||
|
||||
// lgunnorm-water
|
||||
"kg-target-c-forcefield-01-dest",
|
||||
"kg-target-c-forcefield-01",
|
||||
|
||||
// templex-water
|
||||
"temple-waterfall-dest",
|
||||
"temple-waterfall",
|
||||
|
||||
// desertd-water
|
||||
"des-waterfall-dest",
|
||||
"des-waterfall",
|
||||
|
||||
// towerb-water
|
||||
"tow-energy-bridge-dest",
|
||||
"tow-energy-bridge",
|
||||
|
||||
// factoryb-water
|
||||
"hemi-gradient-dest",
|
||||
"hemi-gradient-rim",
|
||||
"hemi-gradient-flames-dest",
|
||||
"hemi-gradient-flames",
|
||||
|
||||
// factoryc-alpha
|
||||
"facc-convey-dest",
|
||||
"facc-convey",
|
||||
"facc-convey-02-dest",
|
||||
"facc-convey-02",
|
||||
|
||||
// waspal-water
|
||||
"waspala-water-dest",
|
||||
"waspala-water",
|
||||
"waspala-waterfall-dest",
|
||||
"waspala-waterfall",
|
||||
|
||||
// rubblea-water
|
||||
"rub-water-dest",
|
||||
"rub-water",
|
||||
|
||||
// rubblea2-water
|
||||
"rub-water-desta2",
|
||||
"rub-watera2",
|
||||
|
||||
// rubbleb-water
|
||||
"rub-water-destb",
|
||||
"rub-waterb",
|
||||
|
||||
// rubblec-water
|
||||
"rub-water-destc",
|
||||
"rub-waterc",
|
||||
|
||||
// nstb-quicksand
|
||||
"nstb-quicksand-dest",
|
||||
"nstb-quicksand-scroll",
|
||||
|
||||
// ctyslumb-water
|
||||
"ctyslumb-water-dest",
|
||||
"ctyslumb-water",
|
||||
"ctyslumb-fountain-fall-dest",
|
||||
"ctyslumb-fountain-fall",
|
||||
|
||||
// ctyslumc-water
|
||||
"ctyslumc-water-dest",
|
||||
"ctyslumc-water",
|
||||
"ctyslumc-fountain-fall-dest",
|
||||
"ctyslumc-fountain-fall",
|
||||
|
||||
// mined-tfrag
|
||||
"mined-pillar-side-dest",
|
||||
"mined-pillar-side-cold",
|
||||
"mined-pillar-side-cooling",
|
||||
"mined-pillar-side-hot",
|
||||
"mined-pillar-molten",
|
||||
"mined-pillar-top2side-dest",
|
||||
"mined-pillar-top2side-cold",
|
||||
"mined-pillar-top2side-cooling",
|
||||
"mined-pillar-top2side-hot",
|
||||
"mined-pillar-top-dest",
|
||||
"mined-pillar-top-cold",
|
||||
"mined-pillar-top-cooling",
|
||||
"mined-pillar-top-hot",
|
||||
"mined-pillar-molten-top",
|
||||
|
||||
// volcanoa-alpha
|
||||
"vola-lava-01-dest",
|
||||
"vola-lava-01",
|
||||
"vola-lava-fall-dest",
|
||||
"vola-lava-fall",
|
||||
|
||||
// wasstada-alpha
|
||||
"wstd-lava-base-dest",
|
||||
"wstd-lava-base"
|
||||
],
|
||||
|
||||
"levels_to_extract": [
|
||||
|
||||
@@ -1850,6 +1850,8 @@
|
||||
["_stack_", 148, "float"],
|
||||
["_stack_", 152, "float"],
|
||||
["_stack_", 156, "float"],
|
||||
[25, "a1", "light-trail-breadcrumb"],
|
||||
[178, "s4", "light-trail-breadcrumb"],
|
||||
[556, "a0", "vector"]
|
||||
],
|
||||
"compute-trail-scaled-t": [[17, "v1", "float"]],
|
||||
@@ -2683,8 +2685,13 @@
|
||||
[[21, 25], "a0", "prim-strip"]
|
||||
],
|
||||
"(event tracking light-trail-tracker)": [[55, "v1", "float"]],
|
||||
"(method 21 light-trail)": [[50, "v1", "light-trail-breadcrumb"]],
|
||||
"(method 14 light-trail)": [[47, "a0", "uint"]],
|
||||
"(method 21 light-trail)": [[[18, 64], "gp", "light-trail-breadcrumb"]],
|
||||
"(method 14 light-trail)": [
|
||||
[47, "a0", "uint"],
|
||||
[[10, 32], "a1", "light-trail-breadcrumb"],
|
||||
[[34, 60], "s3", "light-trail-breadcrumb"],
|
||||
[[34, 73], "s2", "light-trail-breadcrumb"]
|
||||
],
|
||||
"debug-menu-item-var-update-display-str": [
|
||||
[48, "v1", "int"],
|
||||
[63, "v1", "int"],
|
||||
@@ -2735,16 +2742,12 @@
|
||||
[27, "gp", "process-drawable"],
|
||||
[30, "gp", "process-drawable"]
|
||||
],
|
||||
"(method 23 weapon-trail)": [
|
||||
[62, "v1", "light-trail-breadcrumb"],
|
||||
[65, "v1", "light-trail-breadcrumb"]
|
||||
],
|
||||
"(method 23 weapon-trail)": [[[0, 100], "gp", "weapon-trail-crumb"]],
|
||||
"(method 22 weapon-trail)": [[32, "v0", "light-trail-breadcrumb"]],
|
||||
"(method 22 tread-trail)": [[19, "v0", "light-trail-breadcrumb"]],
|
||||
"(method 23 tread-trail)": [
|
||||
[51, "v1", "light-trail-breadcrumb"],
|
||||
[67, "v0", "light-trail-breadcrumb"]
|
||||
],
|
||||
"(method 23 tread-trail)": [[[0, 100], "s5", "tread-trail-crumb"]],
|
||||
"(method 23 tire-trail)": [[[0, 74], "s5", "tire-trail-crumb"]],
|
||||
"(method 22 tire-trail)": [[[18, 24], "v1", "tire-trail-crumb"]],
|
||||
"(trans idle fma-sphere)": [[39, "a2", "process-drawable"]],
|
||||
"part-water-splash-callback": [[3, "v1", "float"]],
|
||||
"(method 15 water-control)": [[48, "v1", "float"]],
|
||||
@@ -6428,11 +6431,11 @@
|
||||
],
|
||||
"cshape-reaction-scorp-shot": [[15, "v1", "v-scorp-shot"]],
|
||||
"(method 78 wvehicle)": [
|
||||
[262, "s1", "process-focusable"],
|
||||
[271, "s1", "process-focusable"],
|
||||
[287, "s1", "process-focusable"],
|
||||
[309, "s1", "process-focusable"],
|
||||
[322, "s1", "process-focusable"],
|
||||
[262, "s1", "tire-trail-tracker"],
|
||||
[271, "s1", "tire-trail-tracker"],
|
||||
[287, "s1", "tire-trail-tracker"],
|
||||
[309, "s1", "tire-trail-tracker"],
|
||||
[322, "s1", "tire-trail-tracker"],
|
||||
[358, "v1", "collide-shape-prim-group"]
|
||||
],
|
||||
"(method 97 wvehicle)": [
|
||||
@@ -6551,7 +6554,10 @@
|
||||
[15, "v1", "process-drawable"],
|
||||
[22, "v1", "process-drawable"]
|
||||
],
|
||||
"(method 19 tire-trail)": [],
|
||||
"(method 19 tire-trail)": [
|
||||
[[5, 28], "s5", "tire-trail-crumb"],
|
||||
[[5, 28], "s4", "tire-trail-crumb"]
|
||||
],
|
||||
"vehicle-spawn": [[93, "gp", "vehicle"]],
|
||||
"vehicle-spawn-hack": [[41, "gp", "vehicle"]],
|
||||
"(method 11 w-parking-spot)": [[42, "v0", "vector"]],
|
||||
|
||||
@@ -515,8 +515,44 @@ TPageResultStats process_tpage(ObjectFileData& data,
|
||||
// currently not needed.
|
||||
break;
|
||||
case int(PSM::PSMT8):
|
||||
ASSERT(tex.clutpsm == int(CPSM::PSMCT32));
|
||||
{
|
||||
if (tex.clutpsm == (int)CPSM::PSMCT16) {
|
||||
// will store output pixels, rgba (8888)
|
||||
std::vector<u8> index_out;
|
||||
|
||||
// width is like the TEX0 register, in 64 texel units.
|
||||
// not sure what the other widths are yet.
|
||||
int read_width = 64 * tex.width[0];
|
||||
|
||||
// loop over pixels in output texture image
|
||||
for (int y = 0; y < tex.h; y++) {
|
||||
for (int x = 0; x < tex.w; x++) {
|
||||
// read as the PSMT8 type. The dest field tells us a block offset.
|
||||
auto addr8 = psmt8_addr(x, y, read_width) + tex.dest[0] * 256;
|
||||
u8 value = *(u8*)(vram.data() + addr8);
|
||||
index_out.push_back(value);
|
||||
}
|
||||
}
|
||||
std::array<math::Vector4<u8>, 256> unscrambled_clut{};
|
||||
for (int i = 0; i < 256; i++) {
|
||||
u32 clut_chunk = i / 16;
|
||||
u32 off_in_chunk = i % 16;
|
||||
u8 clx = 0, cly = 0;
|
||||
if (clut_chunk & 1) {
|
||||
clx = 8;
|
||||
}
|
||||
cly = (clut_chunk >> 1) * 2;
|
||||
if (off_in_chunk >= 8) {
|
||||
off_in_chunk -= 8;
|
||||
cly++;
|
||||
}
|
||||
clx += off_in_chunk;
|
||||
u32 clut_addr = psmct16_addr(clx, cly, 64) + tex.clutdest * 256;
|
||||
memcpy(&unscrambled_clut[i], vram.data() + clut_addr, 4);
|
||||
}
|
||||
texture_db.add_index_texture(texture_page.id, tex_id, index_out, unscrambled_clut,
|
||||
tex.w, tex.h, tex.name, texture_page.name, level_names);
|
||||
stats.successful_textures++;
|
||||
} else if (tex.clutpsm == (int)PSM::PSMCT32) {
|
||||
// will store output pixels, index (u8)
|
||||
std::vector<u8> index_out;
|
||||
|
||||
@@ -555,10 +591,12 @@ TPageResultStats process_tpage(ObjectFileData& data,
|
||||
texture_db.add_index_texture(texture_page.id, tex_id, index_out, unscrambled_clut,
|
||||
tex.w, tex.h, tex.name, texture_page.name, level_names);
|
||||
stats.successful_textures++;
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lg::die("Animated texture {} format {}\n", tex.name, tex.psm);
|
||||
lg::die("Animated texture {} format {} clut {}\n", tex.name, tex.psm, tex.clutpsm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
#include "decompilation_process.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "common/util/os.h"
|
||||
|
||||
#include "Disasm/OpcodeInfo.h"
|
||||
#include "ObjectFile/ObjectFileDB.h"
|
||||
#include "data/streamed_audio.h"
|
||||
#include "level_extractor/extract_level.h"
|
||||
|
||||
int run_decompilation_process(decompiler::Config config,
|
||||
const fs::path& in_folder,
|
||||
const fs::path& out_folder,
|
||||
const bool minimal_for_extractor) {
|
||||
using namespace decompiler;
|
||||
Timer decomp_timer;
|
||||
|
||||
lg::info("[Mem] Top of main: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
init_opcode_info();
|
||||
|
||||
lg::info("[Mem] After init: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
std::vector<fs::path> dgos, objs, strs, tex_strs, art_strs;
|
||||
if (minimal_for_extractor) {
|
||||
// TODO - does this even matter, or can we just make the DGOs lazily loaded (does it already
|
||||
// happen?)
|
||||
for (const auto& dgo_name : config.dgo_names) {
|
||||
std::string common_name = "GAME.CGO";
|
||||
if (dgo_name.length() > 3 && dgo_name.substr(dgo_name.length() - 3) == "DGO") {
|
||||
// ends in DGO, it's a level
|
||||
dgos.push_back(in_folder / dgo_name);
|
||||
} else if (dgo_name.length() >= common_name.length() &&
|
||||
dgo_name.substr(dgo_name.length() - common_name.length()) == common_name) {
|
||||
// it's COMMON.CGO, we need that too.
|
||||
dgos.push_back(in_folder / dgo_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& dgo_name : config.dgo_names) {
|
||||
dgos.push_back(in_folder / dgo_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (minimal_for_extractor) {
|
||||
// TODO - does this even matter, or can we just make the DGOs lazily loaded (does it already
|
||||
// happen?)
|
||||
for (const auto& obj_name : config.object_file_names) {
|
||||
if (obj_name.length() > 3 && obj_name.substr(obj_name.length() - 3) == "TXT") {
|
||||
// ends in TXT
|
||||
objs.push_back(in_folder / obj_name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const auto& obj_name : config.object_file_names) {
|
||||
objs.push_back(in_folder / obj_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!minimal_for_extractor) {
|
||||
for (const auto& str_name : config.str_file_names) {
|
||||
strs.push_back(in_folder / str_name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_texture_file_names) {
|
||||
tex_strs.push_back(in_folder / str_name);
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_art_file_names) {
|
||||
art_strs.push_back(in_folder / str_name);
|
||||
}
|
||||
|
||||
lg::info("[Mem] After config read: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// build file database
|
||||
lg::info("Setting up object file DB...");
|
||||
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, art_strs,
|
||||
config);
|
||||
|
||||
// Explicitly fail if a file in the 'allowed_objects' list wasn't found in the DB
|
||||
// as this is another silent error that can be confusing
|
||||
if (!config.allowed_objects.empty()) {
|
||||
for (const auto& expected_obj : config.allowed_objects) {
|
||||
if (db.obj_files_by_name.count(expected_obj) == 0) {
|
||||
// TODO - this is wrong for jak1, fix eventually as this is now done in 3 places
|
||||
lg::error(
|
||||
"Expected to find '{}' in the ObjectFileDB but did not. Check "
|
||||
"./decompiler/config/{}/inputs.jsonc",
|
||||
expected_obj, config.game_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lg::info("[Mem] After DB setup: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// write out DGO file info
|
||||
file_util::create_dir_if_needed(out_folder);
|
||||
file_util::write_text_file(out_folder / "dgo.txt", db.generate_dgo_listing());
|
||||
// write out object file map (used for future decompilations, if desired)
|
||||
file_util::write_text_file(out_folder / "obj.txt",
|
||||
db.generate_obj_listing(config.merged_objects));
|
||||
|
||||
// dump raw objs
|
||||
if (config.dump_objs) {
|
||||
auto path = out_folder / "raw_obj";
|
||||
file_util::create_dir_if_needed(path);
|
||||
db.dump_raw_objects(path);
|
||||
}
|
||||
|
||||
// process files (required for all analysis)
|
||||
db.process_link_data(config);
|
||||
lg::info("[Mem] After link data: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
db.find_code(config);
|
||||
db.process_labels();
|
||||
lg::info("[Mem] After code: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// top level decompile (do this before printing asm so we get function names)
|
||||
if (config.find_functions) {
|
||||
db.ir2_top_level_pass(config);
|
||||
}
|
||||
|
||||
// print disassembly
|
||||
if (config.disassemble_code || config.disassemble_data) {
|
||||
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
|
||||
config.write_hex_near_instructions);
|
||||
}
|
||||
|
||||
if (config.process_art_groups) {
|
||||
db.extract_art_info();
|
||||
// dump art info to json if requested
|
||||
if (config.dump_art_group_info) {
|
||||
auto ag_file_name = out_folder / "dump" / "art-group-info.min.json";
|
||||
nlohmann::json ag_json = db.dts.art_group_info;
|
||||
file_util::create_dir_if_needed_for_file(ag_file_name);
|
||||
file_util::write_text_file(ag_file_name, ag_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped art group info to {}", ag_file_name.string());
|
||||
}
|
||||
if (config.dump_joint_geo_info) {
|
||||
auto jg_file_name = out_folder / "dump" / "joint-node-info.min.json";
|
||||
nlohmann::json jg_json = db.dts.jg_info;
|
||||
file_util::create_dir_if_needed_for_file(jg_file_name);
|
||||
file_util::write_text_file(jg_file_name, jg_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped joint node info to {}", jg_file_name.string());
|
||||
}
|
||||
} else if (!config.art_group_info_dump.empty() || !config.jg_info_dump.empty()) {
|
||||
// process art groups (used in decompilation)
|
||||
// - if the config has a path to the art info dump, just use that
|
||||
// - otherwise (or if we want to dump it fresh) extract it
|
||||
if (!config.art_group_info_dump.empty()) {
|
||||
db.dts.art_group_info = config.art_group_info_dump;
|
||||
}
|
||||
if (!config.jg_info_dump.empty()) {
|
||||
db.dts.jg_info = config.jg_info_dump;
|
||||
}
|
||||
} else {
|
||||
lg::error("`process_art_groups` was false and no art-group-info dump was provided!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config.process_tpages && !config.texture_info_dump.empty()) {
|
||||
db.dts.textures = config.texture_info_dump;
|
||||
}
|
||||
|
||||
// main decompile.
|
||||
if (config.decompile_code) {
|
||||
db.analyze_functions_ir2(out_folder, config, {}, {}, {});
|
||||
}
|
||||
|
||||
if (config.generate_all_types) {
|
||||
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
|
||||
db.ir2_analyze_all_types(out_folder / "new-all-types.gc", config.old_all_types_file,
|
||||
config.hacks.types_with_bad_inspect_methods);
|
||||
}
|
||||
|
||||
lg::info("[Mem] After decomp: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// write out all symbols
|
||||
file_util::write_text_file(out_folder / "all-syms.gc", db.dts.dump_symbol_types());
|
||||
|
||||
// write art groups
|
||||
if (config.process_art_groups) {
|
||||
db.dump_art_info(out_folder);
|
||||
}
|
||||
|
||||
if (config.hexdump_code || config.hexdump_data) {
|
||||
db.write_object_file_words(out_folder, config.hexdump_data, config.hexdump_code);
|
||||
}
|
||||
|
||||
// data stuff
|
||||
if (config.write_scripts) {
|
||||
db.find_and_write_scripts(out_folder);
|
||||
}
|
||||
|
||||
// ensure asset dir exists
|
||||
file_util::create_dir_if_needed(out_folder / "assets");
|
||||
|
||||
if (config.process_game_text) {
|
||||
auto result = db.process_game_text_files(config);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
lg::info("[Mem] After text: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
if (config.process_subtitle_text || config.process_subtitle_images) {
|
||||
auto result = db.process_all_spool_subtitles(
|
||||
config, config.process_subtitle_images ? out_folder / "assets" / "subtitle-images" : "");
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_subs.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
lg::info("[Mem] After spool handling: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
TextureDB tex_db;
|
||||
if (config.process_tpages || config.levels_extract) {
|
||||
auto textures_out = out_folder / "textures";
|
||||
auto dump_out = out_folder / "import";
|
||||
file_util::create_dir_if_needed(textures_out);
|
||||
auto result = db.process_tpages(tex_db, textures_out, config, dump_out);
|
||||
if (!result.empty() && config.process_tpages) {
|
||||
file_util::write_text_file(textures_out / "tpage-dir.txt", result);
|
||||
file_util::write_text_file(textures_out / "tex-remap.txt",
|
||||
tex_db.generate_texture_dest_adjustment_table());
|
||||
}
|
||||
if (config.dump_tex_info) {
|
||||
auto texture_file_name = out_folder / "dump" / "tex-info.min.json";
|
||||
nlohmann::json texture_json = db.dts.textures;
|
||||
file_util::create_dir_if_needed_for_file(texture_file_name);
|
||||
file_util::write_text_file(texture_file_name, texture_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped texture info to {}", texture_file_name.string());
|
||||
}
|
||||
}
|
||||
|
||||
lg::info("[Mem] After textures: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// Merge textures before replacing them, in other words, replacements take priority
|
||||
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
|
||||
game_version_names[config.game_version] / "texture_merges";
|
||||
if (fs::exists(texture_merge_path)) {
|
||||
tex_db.merge_textures(texture_merge_path);
|
||||
}
|
||||
|
||||
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
|
||||
game_version_names[config.game_version] / "texture_replacements";
|
||||
if (fs::exists(replacements_path)) {
|
||||
tex_db.replace_textures(replacements_path);
|
||||
}
|
||||
|
||||
if (config.process_game_count) {
|
||||
auto result = db.process_game_count_file();
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.levels_extract) {
|
||||
auto level_out_path =
|
||||
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
|
||||
file_util::create_dir_if_needed(level_out_path);
|
||||
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
|
||||
}
|
||||
|
||||
lg::info("[Mem] After extraction: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
if (config.rip_streamed_audio) {
|
||||
auto streaming_audio_out = out_folder / "audio";
|
||||
file_util::create_dir_if_needed(streaming_audio_out);
|
||||
process_streamed_audio(config, streaming_audio_out, in_folder,
|
||||
config.streamed_audio_file_names);
|
||||
}
|
||||
|
||||
lg::info("Decompiler has finished successfully in {:.2f} seconds.", decomp_timer.getSeconds());
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
int run_decompilation_process(decompiler::Config config,
|
||||
const fs::path& in_folder,
|
||||
const fs::path& out_folder,
|
||||
const bool minimal_for_extractor);
|
||||
+26
-110
@@ -5,10 +5,9 @@
|
||||
#include "common/util/term_util.h"
|
||||
#include "common/util/unicode_util.h"
|
||||
|
||||
#include "decompiler/ObjectFile/ObjectFileDB.h"
|
||||
#include "decompiler/config.h"
|
||||
#include "decompiler/decompilation_process.h"
|
||||
#include "decompiler/extractor/extractor_util.h"
|
||||
#include "decompiler/level_extractor/extract_level.h"
|
||||
#include "goalc/compiler/Compiler.h"
|
||||
|
||||
#include "third-party/CLI11.hpp"
|
||||
@@ -102,116 +101,24 @@ std::tuple<std::optional<ISOMetadata>, ExtractorErrorCode> validate(
|
||||
};
|
||||
}
|
||||
|
||||
// TODO - remove code duplication, most of this is copying what happens in decompiler's `main.cpp`
|
||||
void decompile(const fs::path& iso_data_path,
|
||||
const std::string& data_subfolder,
|
||||
const std::string& config_override) {
|
||||
using namespace decompiler;
|
||||
|
||||
ExtractorErrorCode decompile(const fs::path& in_folder,
|
||||
const std::string& data_subfolder,
|
||||
const std::string& config_override) {
|
||||
// Determine which config to use from the database
|
||||
const auto version_info = get_version_info_or_default(iso_data_path);
|
||||
const auto version_info = get_version_info_or_default(in_folder);
|
||||
|
||||
Config config = read_config_file(file_util::get_jak_project_dir() / "decompiler" / "config" /
|
||||
version_info.game_name /
|
||||
fmt::format("{}_config.jsonc", version_info.game_name),
|
||||
version_info.decomp_config_version, config_override);
|
||||
decompiler::Config config = decompiler::read_config_file(
|
||||
file_util::get_jak_project_dir() / "decompiler" / "config" / version_info.game_name /
|
||||
fmt::format("{}_config.jsonc", version_info.game_name),
|
||||
version_info.decomp_config_version, config_override);
|
||||
|
||||
std::vector<fs::path> dgos, objs, tex_strs, art_strs;
|
||||
|
||||
// grab all DGOS we need (level + common)
|
||||
// TODO - Jak 2 - jak 1 specific code?
|
||||
for (const auto& dgo_name : config.dgo_names) {
|
||||
std::string common_name = "GAME.CGO";
|
||||
if (dgo_name.length() > 3 && dgo_name.substr(dgo_name.length() - 3) == "DGO") {
|
||||
// ends in DGO, it's a level
|
||||
dgos.push_back(iso_data_path / dgo_name);
|
||||
} else if (dgo_name.length() >= common_name.length() &&
|
||||
dgo_name.substr(dgo_name.length() - common_name.length()) == common_name) {
|
||||
// it's COMMON.CGO, we need that too.
|
||||
dgos.push_back(iso_data_path / dgo_name);
|
||||
}
|
||||
}
|
||||
|
||||
// grab all the object files we need (just text)
|
||||
for (const auto& obj_name : config.object_file_names) {
|
||||
if (obj_name.length() > 3 && obj_name.substr(obj_name.length() - 3) == "TXT") {
|
||||
// ends in TXT
|
||||
objs.push_back(iso_data_path / obj_name);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_texture_file_names) {
|
||||
tex_strs.push_back(iso_data_path / str_name);
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_art_file_names) {
|
||||
art_strs.push_back(iso_data_path / str_name);
|
||||
}
|
||||
|
||||
// set up objects
|
||||
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, tex_strs, art_strs,
|
||||
config);
|
||||
|
||||
// save object files
|
||||
auto out_folder = file_util::get_jak_project_dir() / "decompiler_out" / data_subfolder;
|
||||
auto raw_obj_folder = out_folder / "raw_obj";
|
||||
file_util::create_dir_if_needed(raw_obj_folder);
|
||||
db.dump_raw_objects(raw_obj_folder);
|
||||
|
||||
// analyze object file link data
|
||||
db.process_link_data(config);
|
||||
db.find_code(config);
|
||||
db.process_labels();
|
||||
|
||||
// ensure asset dir exists
|
||||
file_util::create_dir_if_needed(out_folder / "assets");
|
||||
|
||||
// text files
|
||||
{
|
||||
auto result = db.process_game_text_files(config);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
// textures
|
||||
decompiler::TextureDB tex_db;
|
||||
auto textures_out = out_folder / "textures";
|
||||
auto dump_out = out_folder / "import";
|
||||
file_util::create_dir_if_needed(textures_out);
|
||||
file_util::write_text_file(textures_out / "tpage-dir.txt",
|
||||
db.process_tpages(tex_db, textures_out, config, dump_out));
|
||||
|
||||
// texture merges
|
||||
// TODO - put all this stuff in somewhere common
|
||||
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
|
||||
game_version_names[config.game_version] / "texture_merges";
|
||||
if (fs::exists(texture_merge_path)) {
|
||||
tex_db.merge_textures(texture_merge_path);
|
||||
}
|
||||
|
||||
// texture replacements
|
||||
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
|
||||
game_version_names[config.game_version] / "texture_replacements";
|
||||
if (fs::exists(replacements_path)) {
|
||||
tex_db.replace_textures(replacements_path);
|
||||
}
|
||||
|
||||
// game count
|
||||
{
|
||||
auto result = db.process_game_count_file();
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
// levels
|
||||
{
|
||||
auto level_out_path =
|
||||
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
|
||||
file_util::create_dir_if_needed(level_out_path);
|
||||
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
|
||||
const auto result = run_decompilation_process(config, in_folder, out_folder, true);
|
||||
if (result != 0) {
|
||||
return ExtractorErrorCode::DECOMPILATION_GENERIC_ERROR;
|
||||
}
|
||||
return ExtractorErrorCode::SUCCESS;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, GameIsoFlags> game_iso_flag_names = {
|
||||
@@ -315,7 +222,6 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// - SETUP
|
||||
decompiler::init_opcode_info();
|
||||
if (!project_path_override.empty()) {
|
||||
if (!fs::exists(project_path_override)) {
|
||||
lg::error("Error: project path override '{}' does not exist", project_path_override.string());
|
||||
@@ -426,7 +332,11 @@ int main(int argc, char** argv) {
|
||||
// Get hash and file count
|
||||
const auto [hash, file_count] = calculate_extraction_hash(iso_data_path);
|
||||
// Validate
|
||||
auto [version_info, code] = validate(iso_data_path, hash, file_count);
|
||||
auto [version_info, validate_code] = validate(iso_data_path, hash, file_count);
|
||||
if (validate_code == ExtractorErrorCode::VALIDATION_BAD_EXTRACTION ||
|
||||
(flag_fail_on_validation && validate_code != ExtractorErrorCode::SUCCESS)) {
|
||||
return static_cast<int>(validate_code);
|
||||
}
|
||||
}
|
||||
|
||||
// write out a json file with some metadata for the game
|
||||
@@ -455,7 +365,10 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (flag_decompile) {
|
||||
try {
|
||||
decompile(iso_data_path, data_subfolder, decomp_config_override);
|
||||
const auto status_code = decompile(iso_data_path, data_subfolder, decomp_config_override);
|
||||
if (status_code != ExtractorErrorCode::SUCCESS) {
|
||||
return static_cast<int>(status_code);
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
lg::error("Error during decompile: {}", e.what());
|
||||
return static_cast<int>(ExtractorErrorCode::DECOMPILATION_GENERIC_ERROR);
|
||||
@@ -463,7 +376,10 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (flag_compile) {
|
||||
compile(iso_data_path, data_subfolder);
|
||||
const auto status_code = compile(iso_data_path, data_subfolder);
|
||||
if (status_code != ExtractorErrorCode::SUCCESS) {
|
||||
return static_cast<int>(status_code);
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_play) {
|
||||
|
||||
@@ -322,7 +322,8 @@ void extract_common(const ObjectFileDB& db,
|
||||
compressed.data(), compressed.size());
|
||||
|
||||
if (config.rip_levels) {
|
||||
auto file_path = file_util::get_jak_project_dir() / "glb_out" / "common.glb";
|
||||
auto file_path = file_util::get_jak_project_dir() / "glb_out" /
|
||||
game_version_names[config.game_version] / "common.glb";
|
||||
file_util::create_dir_if_needed_for_file(file_path);
|
||||
save_level_foreground_as_gltf(tfrag_level, art_group_data, file_path);
|
||||
}
|
||||
@@ -360,15 +361,17 @@ void extract_from_level(const ObjectFileDB& db,
|
||||
|
||||
if (config.rip_levels) {
|
||||
auto back_file_path = file_util::get_jak_project_dir() / "glb_out" /
|
||||
fmt::format("{}_background.glb", level_data.level_name);
|
||||
game_version_names[config.game_version] /
|
||||
fmt::format("{}-background.glb", level_data.level_name);
|
||||
file_util::create_dir_if_needed_for_file(back_file_path);
|
||||
save_level_background_as_gltf(level_data, back_file_path);
|
||||
auto fore_file_path = file_util::get_jak_project_dir() / "glb_out" /
|
||||
fmt::format("{}_foreground.glb", level_data.level_name);
|
||||
game_version_names[config.game_version] /
|
||||
fmt::format("{}-foreground.glb", level_data.level_name);
|
||||
file_util::create_dir_if_needed_for_file(fore_file_path);
|
||||
save_level_foreground_as_gltf(level_data, art_group_data, fore_file_path);
|
||||
}
|
||||
file_util::write_text_file(entities_folder / fmt::format("{}_actors.json", level_data.level_name),
|
||||
file_util::write_text_file(entities_folder / fmt::format("{}-actors.json", level_data.level_name),
|
||||
extract_actors_to_json(bsp_header.actors));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "extract_merc.h"
|
||||
|
||||
#include "merc_replacement.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/BitUtils.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
@@ -1597,6 +1599,60 @@ void create_modifiable_vertex_data(
|
||||
}
|
||||
}
|
||||
|
||||
void replace_model(tfrag3::Level& lvl, tfrag3::MercModel& model, const fs::path& mdl_path) {
|
||||
if (model.max_bones < 100) {
|
||||
auto lvl_name = lvl.level_name == "" ? "common" : lvl.level_name;
|
||||
lg::info("Replacing {} for {}: {} effects, {} max bones, {} max draws\n", model.name, lvl_name,
|
||||
model.effects.size(), model.max_bones, model.max_draws);
|
||||
|
||||
std::vector<tfrag3::MercVertex> old_verts;
|
||||
for (auto& e : model.effects) {
|
||||
for (auto& d : e.all_draws) {
|
||||
for (size_t i = 0; i < d.index_count; i++) {
|
||||
auto idx = lvl.merc_data.indices.at(i + d.first_index);
|
||||
if (idx != UINT32_MAX) {
|
||||
old_verts.push_back(lvl.merc_data.vertices[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto swap_info = load_replacement_merc_model(model.name, lvl.merc_data.indices.size(),
|
||||
lvl.merc_data.vertices.size(), lvl.textures.size(),
|
||||
mdl_path.string(), old_verts, false);
|
||||
model = swap_info.new_model;
|
||||
size_t old_start = lvl.merc_data.vertices.size();
|
||||
for (auto& ind : swap_info.new_indices) {
|
||||
ASSERT(ind >= old_start);
|
||||
}
|
||||
lvl.merc_data.indices.insert(lvl.merc_data.indices.end(), swap_info.new_indices.begin(),
|
||||
swap_info.new_indices.end());
|
||||
lvl.merc_data.vertices.insert(lvl.merc_data.vertices.end(), swap_info.new_vertices.begin(),
|
||||
swap_info.new_vertices.end());
|
||||
lvl.textures.insert(lvl.textures.end(), swap_info.new_textures.begin(),
|
||||
swap_info.new_textures.end());
|
||||
}
|
||||
}
|
||||
|
||||
void add_custom_model_to_level(tfrag3::Level& lvl,
|
||||
const std::string& name,
|
||||
const fs::path& mdl_path) {
|
||||
auto lvl_name = lvl.level_name == "" ? "common" : lvl.level_name;
|
||||
lg::info("Adding custom model {} to {}", name, lvl_name);
|
||||
auto merc_data =
|
||||
load_replacement_merc_model(name, lvl.merc_data.indices.size(), lvl.merc_data.vertices.size(),
|
||||
lvl.textures.size(), mdl_path.string(), {}, true);
|
||||
for (auto& idx : merc_data.new_indices) {
|
||||
lvl.merc_data.indices.push_back(idx);
|
||||
}
|
||||
for (auto& vert : merc_data.new_vertices) {
|
||||
lvl.merc_data.vertices.push_back(vert);
|
||||
}
|
||||
lvl.merc_data.models.push_back(merc_data.new_model);
|
||||
lvl.textures.insert(lvl.textures.end(), merc_data.new_textures.begin(),
|
||||
merc_data.new_textures.end());
|
||||
}
|
||||
|
||||
/*!
|
||||
* Top-level merc extraction
|
||||
*/
|
||||
@@ -1731,5 +1787,33 @@ void extract_merc(const ObjectFileData& ag_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do model replacements if present
|
||||
auto merc_replacement_folder = file_util::get_jak_project_dir() / "custom_assets" /
|
||||
game_version_names[version] / "merc_replacements";
|
||||
if (file_util::file_exists(merc_replacement_folder.string())) {
|
||||
auto merc_replacements =
|
||||
file_util::find_files_in_dir(merc_replacement_folder, std::regex(".*\\.glb"));
|
||||
for (auto& path : merc_replacements) {
|
||||
auto name = path.stem().string();
|
||||
auto it = std::find_if(out.merc_data.models.begin(), out.merc_data.models.end(),
|
||||
[&](const auto& m) { return m.name == name; });
|
||||
if (it != out.merc_data.models.end()) {
|
||||
auto& model = *it;
|
||||
replace_model(out, model, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add custom models if present
|
||||
auto lvl_name = out.level_name == "" ? "common" : out.level_name;
|
||||
auto models_folder = file_util::get_jak_project_dir() / "custom_assets" /
|
||||
game_version_names[version] / "models" / lvl_name;
|
||||
if (file_util::file_exists(models_folder.string())) {
|
||||
auto custom_models = file_util::find_files_in_dir(models_folder, std::regex(".*\\.glb"));
|
||||
for (auto& mdl : custom_models) {
|
||||
add_custom_model_to_level(out, mdl.stem().string(), mdl);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -0,0 +1,211 @@
|
||||
#include "merc_replacement.h"
|
||||
|
||||
using namespace gltf_util;
|
||||
|
||||
namespace decompiler {
|
||||
void extract(const std::string& name,
|
||||
MercExtractData& out,
|
||||
const tinygltf::Model& model,
|
||||
const std::vector<NodeWithTransform>& all_nodes,
|
||||
u32 index_offset,
|
||||
u32 vertex_offset,
|
||||
u32 tex_offset) {
|
||||
ASSERT(out.new_vertices.empty());
|
||||
|
||||
std::map<int, tfrag3::MercDraw> draw_by_material;
|
||||
int mesh_count = 0;
|
||||
int prim_count = 0;
|
||||
|
||||
for (const auto& n : all_nodes) {
|
||||
const auto& node = model.nodes[n.node_idx];
|
||||
if (node.extras.Has("set_invisible") && node.extras.Get("set_invisible").Get<int>()) {
|
||||
continue;
|
||||
}
|
||||
if (node.mesh >= 0) {
|
||||
const auto& mesh = model.meshes[node.mesh];
|
||||
mesh_count++;
|
||||
for (const auto& prim : mesh.primitives) {
|
||||
prim_count++;
|
||||
// extract index buffer
|
||||
std::vector<u32> prim_indices = gltf_util::gltf_index_buffer(
|
||||
model, prim.indices, out.new_vertices.size() + vertex_offset);
|
||||
ASSERT_MSG(prim.mode == TINYGLTF_MODE_TRIANGLES, "Unsupported triangle mode");
|
||||
// extract vertices
|
||||
auto verts =
|
||||
gltf_util::gltf_vertices(model, prim.attributes, n.w_T_node, true, true, mesh.name);
|
||||
out.new_vertices.insert(out.new_vertices.end(), verts.vtx.begin(), verts.vtx.end());
|
||||
out.new_colors.insert(out.new_colors.end(), verts.vtx_colors.begin(),
|
||||
verts.vtx_colors.end());
|
||||
out.normals.insert(out.normals.end(), verts.normals.begin(), verts.normals.end());
|
||||
ASSERT(out.new_colors.size() == out.new_vertices.size());
|
||||
|
||||
// TODO: just putting it all in one material
|
||||
auto& draw = draw_by_material[prim.material];
|
||||
draw.mode = gltf_util::make_default_draw_mode(); // todo rm
|
||||
draw.tree_tex_id = 0; // todo rm
|
||||
draw.num_triangles += prim_indices.size() / 3;
|
||||
draw.no_strip = true;
|
||||
draw.index_count = prim_indices.size();
|
||||
draw.first_index = index_offset + out.new_indices.size();
|
||||
|
||||
out.new_indices.insert(out.new_indices.end(), prim_indices.begin(), prim_indices.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tfrag3::MercEffect e;
|
||||
out.new_model.name = name;
|
||||
out.new_model.max_bones = 120;
|
||||
out.new_model.max_draws = 200;
|
||||
for (const auto& [mat_idx, d_] : draw_by_material) {
|
||||
e.all_draws.push_back(d_);
|
||||
auto& draw = e.all_draws.back();
|
||||
draw.mode = make_default_draw_mode();
|
||||
|
||||
if (mat_idx == -1) {
|
||||
lg::warn("Draw had a material index of -1, using default texture.");
|
||||
draw.tree_tex_id = 0;
|
||||
continue;
|
||||
}
|
||||
const auto& mat = model.materials[mat_idx];
|
||||
int tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index;
|
||||
if (tex_idx == -1) {
|
||||
lg::warn("Material {} has no texture, using default texture.", mat.name);
|
||||
draw.tree_tex_id = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& tex = model.textures[tex_idx];
|
||||
ASSERT(tex.sampler >= 0);
|
||||
ASSERT(tex.source >= 0);
|
||||
draw.mode = draw_mode_from_sampler(model.samplers.at(tex.sampler));
|
||||
|
||||
const auto& img = model.images[tex.source];
|
||||
draw.tree_tex_id = tex_offset + texture_pool_add_texture(&out.tex_pool, img);
|
||||
}
|
||||
lg::info("total of {} unique materials", e.all_draws.size());
|
||||
e.has_mod_draw = false;
|
||||
out.new_model.effects.push_back(e);
|
||||
out.new_model.effects.push_back(e);
|
||||
out.new_model.effects.push_back(e);
|
||||
out.new_model.effects.push_back(e);
|
||||
|
||||
lg::info("Merged {} meshes and {} prims into {} vertices", mesh_count, prim_count,
|
||||
out.new_vertices.size());
|
||||
}
|
||||
|
||||
const tfrag3::MercVertex& find_closest(const std::vector<tfrag3::MercVertex>& old,
|
||||
float x,
|
||||
float y,
|
||||
float z) {
|
||||
float best_dist = 1e10;
|
||||
int best_idx = 0;
|
||||
|
||||
for (int i = 0; i < old.size(); i++) {
|
||||
auto& v = old[i];
|
||||
float dx = v.pos[0] - x;
|
||||
float dy = v.pos[1] - y;
|
||||
float dz = v.pos[2] - z;
|
||||
float dist = (dx * dx) + (dy * dy) + (dz * dz);
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return old[best_idx];
|
||||
}
|
||||
|
||||
void merc_convert_replacement(MercSwapData& out,
|
||||
const MercExtractData& in,
|
||||
const std::vector<tfrag3::MercVertex>& old_verts) {
|
||||
out.new_model = in.new_model;
|
||||
out.new_indices = in.new_indices;
|
||||
out.new_textures = in.tex_pool.textures_by_idx;
|
||||
|
||||
// convert vertices
|
||||
for (size_t i = 0; i < in.new_vertices.size(); i++) {
|
||||
const auto& y = in.new_vertices[i];
|
||||
const auto& copy_from = find_closest(old_verts, y.x, y.y, y.z);
|
||||
auto& x = out.new_vertices.emplace_back();
|
||||
x.pos[0] = y.x;
|
||||
x.pos[1] = y.y;
|
||||
x.pos[2] = y.z;
|
||||
x.normal[0] = copy_from.normal[0];
|
||||
x.normal[1] = copy_from.normal[1];
|
||||
x.normal[2] = copy_from.normal[2];
|
||||
x.weights[0] = copy_from.weights[0];
|
||||
x.weights[1] = copy_from.weights[1];
|
||||
x.weights[2] = copy_from.weights[2];
|
||||
x.st[0] = y.s;
|
||||
x.st[1] = y.t;
|
||||
x.rgba[0] = in.new_colors[i][0];
|
||||
x.rgba[1] = in.new_colors[i][1];
|
||||
x.rgba[2] = in.new_colors[i][2];
|
||||
x.rgba[3] = in.new_colors[i][3];
|
||||
x.mats[0] = copy_from.mats[0];
|
||||
x.mats[1] = copy_from.mats[1];
|
||||
x.mats[2] = copy_from.mats[2];
|
||||
}
|
||||
}
|
||||
|
||||
void merc_convert_custom(MercSwapData& out, const MercExtractData& in) {
|
||||
out.new_model = in.new_model;
|
||||
out.new_indices = in.new_indices;
|
||||
out.new_textures = in.tex_pool.textures_by_idx;
|
||||
|
||||
// convert vertices
|
||||
for (size_t i = 0; i < in.new_vertices.size(); i++) {
|
||||
const auto& y = in.new_vertices[i];
|
||||
auto& x = out.new_vertices.emplace_back();
|
||||
x.pos[0] = y.x;
|
||||
x.pos[1] = y.y;
|
||||
x.pos[2] = y.z;
|
||||
x.normal[0] = in.normals.at(i).x();
|
||||
x.normal[1] = in.normals.at(i).y();
|
||||
x.normal[2] = in.normals.at(i).z();
|
||||
x.weights[0] = 1.0f;
|
||||
x.weights[1] = 0.0f;
|
||||
x.weights[2] = 0.0f;
|
||||
x.st[0] = y.s;
|
||||
x.st[1] = y.t;
|
||||
x.rgba[0] = in.new_colors[i][0];
|
||||
x.rgba[1] = in.new_colors[i][1];
|
||||
x.rgba[2] = in.new_colors[i][2];
|
||||
x.rgba[3] = in.new_colors[i][3];
|
||||
x.mats[0] = 3;
|
||||
x.mats[1] = 0;
|
||||
x.mats[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MercSwapData load_replacement_merc_model(const std::string& name,
|
||||
u32 current_idx_count,
|
||||
u32 current_vtx_count,
|
||||
u32 current_tex_count,
|
||||
const std::string& path,
|
||||
const std::vector<tfrag3::MercVertex>& old_verts,
|
||||
bool custom_mdl) {
|
||||
MercSwapData result;
|
||||
lg::info("Reading gltf mesh: {}", path);
|
||||
tinygltf::TinyGLTF loader;
|
||||
tinygltf::Model model;
|
||||
std::string err, warn;
|
||||
bool res = loader.LoadBinaryFromFile(&model, &err, &warn, path);
|
||||
ASSERT_MSG(warn.empty(), warn.c_str());
|
||||
ASSERT_MSG(err.empty(), err.c_str());
|
||||
ASSERT_MSG(res, "Failed to load GLTF file!");
|
||||
auto all_nodes = flatten_nodes_from_all_scenes(model);
|
||||
|
||||
MercExtractData extract_data;
|
||||
extract(name, extract_data, model, all_nodes, current_idx_count, current_vtx_count,
|
||||
current_tex_count);
|
||||
if (custom_mdl) {
|
||||
merc_convert_custom(result, extract_data);
|
||||
} else {
|
||||
merc_convert_replacement(result, extract_data, old_verts);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace decompiler
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/gltf_util.h"
|
||||
|
||||
namespace decompiler {
|
||||
struct MercExtractData {
|
||||
gltf_util::TexturePool tex_pool;
|
||||
std::vector<u32> new_indices;
|
||||
std::vector<tfrag3::PreloadedVertex> new_vertices;
|
||||
std::vector<math::Vector<u8, 4>> new_colors;
|
||||
std::vector<math::Vector3f> normals;
|
||||
|
||||
tfrag3::MercModel new_model;
|
||||
};
|
||||
|
||||
// Data produced by loading a replacement model
|
||||
struct MercSwapData {
|
||||
std::vector<u32> new_indices;
|
||||
std::vector<tfrag3::MercVertex> new_vertices;
|
||||
std::vector<tfrag3::Texture> new_textures;
|
||||
tfrag3::MercModel new_model;
|
||||
};
|
||||
|
||||
MercSwapData load_replacement_merc_model(const std::string& name,
|
||||
u32 current_idx_count,
|
||||
u32 current_vtx_count,
|
||||
u32 current_tex_count,
|
||||
const std::string& path,
|
||||
const std::vector<tfrag3::MercVertex>& old_verts,
|
||||
bool custom_mdl);
|
||||
} // namespace decompiler
|
||||
+5
-255
@@ -1,33 +1,15 @@
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "config.h"
|
||||
#include "decompilation_process.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/Timer.h"
|
||||
#include "common/util/diff.h"
|
||||
#include "common/util/os.h"
|
||||
#include "common/util/set_util.h"
|
||||
#include "common/util/term_util.h"
|
||||
#include "common/util/unicode_util.h"
|
||||
#include "common/versions/versions.h"
|
||||
|
||||
#include "ObjectFile/ObjectFileDB.h"
|
||||
#include "decompiler/data/TextureDB.h"
|
||||
#include "decompiler/data/streamed_audio.h"
|
||||
#include "decompiler/level_extractor/extract_level.h"
|
||||
|
||||
#include "third-party/CLI11.hpp"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
template <typename... Args>
|
||||
static void mem_log(const std::string& format, Args&&... args) {
|
||||
#ifndef _WIN32
|
||||
lg::info("[Mem] " + format, std::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ArgumentGuard u8_guard(argc, argv);
|
||||
@@ -81,11 +63,9 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
using namespace decompiler;
|
||||
|
||||
Config config;
|
||||
decompiler::Config config;
|
||||
try {
|
||||
config = read_config_file(config_path, config_game_version, config_override);
|
||||
config = decompiler::read_config_file(config_path, config_game_version, config_override);
|
||||
} catch (const std::exception& e) {
|
||||
lg::error("Failed to parse config: {}", e.what());
|
||||
return 1;
|
||||
@@ -115,7 +95,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Warning message if expected ELF isn't found, user could be using bad assets / didn't extract
|
||||
// the ISO properly
|
||||
if (!config.expected_elf_name.empty() && !exists(in_folder / config.expected_elf_name)) {
|
||||
if (!config.expected_elf_name.empty() && !fs::exists(in_folder / config.expected_elf_name)) {
|
||||
lg::error(
|
||||
"WARNING - '{}' does not contain the expected ELF file '{}'. Was the ISO extracted "
|
||||
"properly or is there a version mismatch?",
|
||||
@@ -123,235 +103,5 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
// -- Begin the Decompilation!
|
||||
|
||||
Timer decomp_timer;
|
||||
|
||||
mem_log("Top of main: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
init_opcode_info();
|
||||
|
||||
mem_log("After init: {} MB\n", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
std::vector<fs::path> dgos, objs, strs, tex_strs, art_strs;
|
||||
for (const auto& dgo_name : config.dgo_names) {
|
||||
dgos.push_back(in_folder / dgo_name);
|
||||
}
|
||||
|
||||
for (const auto& obj_name : config.object_file_names) {
|
||||
objs.push_back(in_folder / obj_name);
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_file_names) {
|
||||
strs.push_back(in_folder / str_name);
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_texture_file_names) {
|
||||
tex_strs.push_back(in_folder / str_name);
|
||||
}
|
||||
|
||||
for (const auto& str_name : config.str_art_file_names) {
|
||||
art_strs.push_back(in_folder / str_name);
|
||||
}
|
||||
|
||||
mem_log("After config read: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// build file database
|
||||
lg::info("Setting up object file DB...");
|
||||
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, art_strs,
|
||||
config);
|
||||
|
||||
// Explicitly fail if a file in the 'allowed_objects' list wasn't found in the DB
|
||||
// as this is another silent error that can be confusing
|
||||
if (!config.allowed_objects.empty()) {
|
||||
for (const auto& expected_obj : config.allowed_objects) {
|
||||
if (db.obj_files_by_name.count(expected_obj) == 0) {
|
||||
// TODO - this is wrong for jak1, fix eventually as this is now done in 3 places
|
||||
lg::error(
|
||||
"Expected to find '{}' in the ObjectFileDB but did not. Check "
|
||||
"./decompiler/config/{}/inputs.jsonc",
|
||||
expected_obj, config.game_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mem_log("After DB setup: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// write out DGO file info
|
||||
file_util::write_text_file(out_folder / "dgo.txt", db.generate_dgo_listing());
|
||||
// write out object file map (used for future decompilations, if desired)
|
||||
file_util::write_text_file(out_folder / "obj.txt",
|
||||
db.generate_obj_listing(config.merged_objects));
|
||||
|
||||
// dump raw objs
|
||||
if (config.dump_objs) {
|
||||
auto path = out_folder / "raw_obj";
|
||||
file_util::create_dir_if_needed(path);
|
||||
db.dump_raw_objects(path);
|
||||
}
|
||||
|
||||
// process files (required for all analysis)
|
||||
db.process_link_data(config);
|
||||
mem_log("After link data: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
db.find_code(config);
|
||||
db.process_labels();
|
||||
mem_log("After code: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// top level decompile (do this before printing asm so we get function names)
|
||||
if (config.find_functions) {
|
||||
db.ir2_top_level_pass(config);
|
||||
}
|
||||
|
||||
// print disassembly
|
||||
if (config.disassemble_code || config.disassemble_data) {
|
||||
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
|
||||
config.write_hex_near_instructions);
|
||||
}
|
||||
|
||||
if (config.process_art_groups) {
|
||||
db.extract_art_info();
|
||||
// dump art info to json if requested
|
||||
if (config.dump_art_group_info) {
|
||||
auto ag_file_name = out_folder / "dump" / "art-group-info.min.json";
|
||||
nlohmann::json ag_json = db.dts.art_group_info;
|
||||
file_util::create_dir_if_needed_for_file(ag_file_name);
|
||||
file_util::write_text_file(ag_file_name, ag_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped art group info to {}", ag_file_name.string());
|
||||
}
|
||||
if (config.dump_joint_geo_info) {
|
||||
auto jg_file_name = out_folder / "dump" / "joint-node-info.min.json";
|
||||
nlohmann::json jg_json = db.dts.jg_info;
|
||||
file_util::create_dir_if_needed_for_file(jg_file_name);
|
||||
file_util::write_text_file(jg_file_name, jg_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped joint node info to {}", jg_file_name.string());
|
||||
}
|
||||
} else if (!config.art_group_info_dump.empty() || !config.jg_info_dump.empty()) {
|
||||
// process art groups (used in decompilation)
|
||||
// - if the config has a path to the art info dump, just use that
|
||||
// - otherwise (or if we want to dump it fresh) extract it
|
||||
if (!config.art_group_info_dump.empty()) {
|
||||
db.dts.art_group_info = config.art_group_info_dump;
|
||||
}
|
||||
if (!config.jg_info_dump.empty()) {
|
||||
db.dts.jg_info = config.jg_info_dump;
|
||||
}
|
||||
} else {
|
||||
lg::error("`process_art_groups` was false and no art-group-info dump was provided!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config.process_tpages && !config.texture_info_dump.empty()) {
|
||||
db.dts.textures = config.texture_info_dump;
|
||||
}
|
||||
|
||||
// main decompile.
|
||||
if (config.decompile_code) {
|
||||
db.analyze_functions_ir2(out_folder, config, {}, {}, {});
|
||||
}
|
||||
|
||||
if (config.generate_all_types) {
|
||||
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
|
||||
db.ir2_analyze_all_types(out_folder / "new-all-types.gc", config.old_all_types_file,
|
||||
config.hacks.types_with_bad_inspect_methods);
|
||||
}
|
||||
|
||||
mem_log("After decomp: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// write out all symbols
|
||||
file_util::write_text_file(out_folder / "all-syms.gc", db.dts.dump_symbol_types());
|
||||
|
||||
// write art groups
|
||||
if (config.process_art_groups) {
|
||||
db.dump_art_info(out_folder);
|
||||
}
|
||||
|
||||
if (config.hexdump_code || config.hexdump_data) {
|
||||
db.write_object_file_words(out_folder, config.hexdump_data, config.hexdump_code);
|
||||
}
|
||||
|
||||
// data stuff
|
||||
if (config.write_scripts) {
|
||||
db.find_and_write_scripts(out_folder);
|
||||
}
|
||||
|
||||
if (config.process_game_text) {
|
||||
auto result = db.process_game_text_files(config);
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
mem_log("After text: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
if (config.process_subtitle_text || config.process_subtitle_images) {
|
||||
auto result = db.process_all_spool_subtitles(
|
||||
config, config.process_subtitle_images ? out_folder / "assets" / "subtitle-images" : "");
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_subs.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
mem_log("After spool handling: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
TextureDB tex_db;
|
||||
if (config.process_tpages || config.levels_extract) {
|
||||
auto textures_out = out_folder / "textures";
|
||||
auto dump_out = out_folder / "import";
|
||||
file_util::create_dir_if_needed(textures_out);
|
||||
auto result = db.process_tpages(tex_db, textures_out, config, dump_out);
|
||||
if (!result.empty() && config.process_tpages) {
|
||||
file_util::write_text_file(textures_out / "tpage-dir.txt", result);
|
||||
file_util::write_text_file(textures_out / "tex-remap.txt",
|
||||
tex_db.generate_texture_dest_adjustment_table());
|
||||
}
|
||||
if (config.dump_tex_info) {
|
||||
auto texture_file_name = out_folder / "dump" / "tex-info.min.json";
|
||||
nlohmann::json texture_json = db.dts.textures;
|
||||
file_util::create_dir_if_needed_for_file(texture_file_name);
|
||||
file_util::write_text_file(texture_file_name, texture_json.dump(-1));
|
||||
lg::info("[DUMP] Dumped texture info to {}", texture_file_name.string());
|
||||
}
|
||||
}
|
||||
|
||||
mem_log("After textures: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
// Merge textures before replacing them, in other words, replacements take priority
|
||||
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
|
||||
game_version_names[config.game_version] / "texture_merges";
|
||||
if (fs::exists(texture_merge_path)) {
|
||||
tex_db.merge_textures(texture_merge_path);
|
||||
}
|
||||
|
||||
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
|
||||
game_version_names[config.game_version] / "texture_replacements";
|
||||
if (fs::exists(replacements_path)) {
|
||||
tex_db.replace_textures(replacements_path);
|
||||
}
|
||||
|
||||
if (config.process_game_count) {
|
||||
auto result = db.process_game_count_file();
|
||||
if (!result.empty()) {
|
||||
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.levels_extract) {
|
||||
auto level_out_path =
|
||||
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
|
||||
file_util::create_dir_if_needed(level_out_path);
|
||||
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
|
||||
}
|
||||
|
||||
mem_log("After extraction: {} MB", get_peak_rss() / (1024 * 1024));
|
||||
|
||||
if (!config.audio_dir_file_name.empty()) {
|
||||
auto streaming_audio_in = in_folder / "VAG";
|
||||
auto streaming_audio_out = out_folder / "assets" / "streaming_audio";
|
||||
file_util::create_dir_if_needed(streaming_audio_out);
|
||||
process_streamed_audio(config, streaming_audio_out, in_folder,
|
||||
config.streamed_audio_file_names);
|
||||
}
|
||||
|
||||
lg::info("Decompiler has finished successfully in {:.2f} seconds.", decomp_timer.getSeconds());
|
||||
return 0;
|
||||
return run_decompilation_process(config, in_folder, out_folder, false);
|
||||
}
|
||||
@@ -2576,7 +2576,6 @@ void CallOp::propagate_types2(types2::Instruction& instr,
|
||||
|
||||
if (can_use_call_parent) {
|
||||
out_types[Register(Reg::GPR, Reg::V0)]->type = TP_Type::make_from_ts(call_parent_result_type);
|
||||
lg::print("used special {}\n", call_parent_result_type.print());
|
||||
use_normal_last_arg = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,7 @@ set(RUNTIME_SOURCE
|
||||
mips2c/jak3_functions/sky.cpp
|
||||
mips2c/jak3_functions/texture.cpp
|
||||
mips2c/jak3_functions/particle_curves.cpp
|
||||
mips2c/jak3_functions/cloth.cpp
|
||||
mips2c/jak3_functions/collide_cache.cpp
|
||||
mips2c/jak3_functions/collide_hash.cpp
|
||||
mips2c/jak3_functions/collide_edge_grab.cpp
|
||||
@@ -254,6 +255,29 @@ set(RUNTIME_SOURCE
|
||||
overlord/jak2/streamlfo.cpp
|
||||
overlord/jak2/streamlist.cpp
|
||||
overlord/jak2/vag.cpp
|
||||
overlord/jak3/overlord.cpp
|
||||
overlord/jak3/pagemanager.cpp
|
||||
overlord/jak3/iso_cd.cpp
|
||||
overlord/jak3/dma.cpp
|
||||
overlord/jak3/iso.cpp
|
||||
overlord/jak3/iso_queue.cpp
|
||||
overlord/jak3/srpc.cpp
|
||||
overlord/jak3/vag.cpp
|
||||
overlord/jak3/ssound.cpp
|
||||
overlord/jak3/iso_api.cpp
|
||||
overlord/jak3/spustreams.cpp
|
||||
overlord/jak3/list.cpp
|
||||
overlord/jak3/vblank_handler.cpp
|
||||
overlord/jak3/dvd_driver.cpp
|
||||
overlord/jak3/basefile.cpp
|
||||
overlord/jak3/basefilesystem.cpp
|
||||
overlord/jak3/ramdisk.cpp
|
||||
overlord/jak3/isocommon.cpp
|
||||
overlord/jak3/init.cpp
|
||||
overlord/jak3/stream.cpp
|
||||
overlord/jak3/sbank.cpp
|
||||
overlord/jak3/soundcommon.cpp
|
||||
overlord/jak3/streamlist.cpp
|
||||
runtime.cpp
|
||||
sce/deci2.cpp
|
||||
sce/iop.cpp
|
||||
|
||||
@@ -54,4 +54,11 @@
|
||||
:lines "game/assets/jak2/subtitle/subtitle_lines_en-GB.json"
|
||||
:meta "game/assets/jak2/subtitle/subtitle_meta_en-GB.json"
|
||||
:lines-base "game/assets/jak2/subtitle/subtitle_lines_en-US.json"
|
||||
:meta-base "game/assets/jak2/subtitle/subtitle_meta_en-US.json")
|
||||
(file-json
|
||||
:language-id 9
|
||||
:text-version "jak2"
|
||||
:lines "game/assets/jak2/subtitle/subtitle_lines_fi-FI.json"
|
||||
:meta "game/assets/jak2/subtitle/subtitle_meta_fi-FI.json"
|
||||
:lines-base "game/assets/jak2/subtitle/subtitle_lines_en-US.json"
|
||||
:meta-base "game/assets/jak2/subtitle/subtitle_meta_en-US.json"))
|
||||
@@ -21,7 +21,8 @@
|
||||
(file-json 7 jak2 "common" '("game/assets/jak2/text/game_custom_text_en-GB.json"))
|
||||
;; custom languages
|
||||
(file-json 8 jak2 "common" '("game/assets/jak2/text/game_custom_text_pt-PT.json"))
|
||||
(file-json 9 jak2 "common" '("game/assets/jak2/text/game_custom_text_fi-FI.json"))
|
||||
(file-json 9 jak2 "common" '("game/assets/jak2/text/game_custom_text_fi-FI.json"
|
||||
"game/assets/jak2/text/game_base_text_fi-FI.json"))
|
||||
(file-json 10 jak2 "common" '("game/assets/jak2/text/game_custom_text_sv-SE.json"))
|
||||
(file-json 11 jak2 "common" '("game/assets/jak2/text/game_custom_text_da-DK.json"))
|
||||
(file-json 12 jak2 "common" '("game/assets/jak2/text/game_custom_text_no-NO.json"))
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"1a3": "138",
|
||||
"1b5": "161",
|
||||
"133a": "1113",
|
||||
"1200": "1031",
|
||||
"1201": "1032",
|
||||
"1202": "1034",
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
{
|
||||
"0100": "Lopeta",
|
||||
"0101": "Tauko~",
|
||||
"0102": "Tekstityksen kieli",
|
||||
"0103": "Ääniformaatti",
|
||||
"0104": "Mono",
|
||||
"0105": "Stereo",
|
||||
"0106": "Surround",
|
||||
"0107": "Äänitehosteet",
|
||||
"0108": "Musiikki",
|
||||
"0109": "Puhe",
|
||||
"010a": "Kieli",
|
||||
"010b": "Värinätoiminto",
|
||||
"010c": "Vinkit",
|
||||
"010d": "Keskitä ruutu",
|
||||
"010e": "Päällä",
|
||||
"010f": "Pois",
|
||||
"0110": "Käytä suuntanäppäimiä",
|
||||
"0111": "<FLAG_USA> English",
|
||||
"0112": "<FLAG_FRANCE> Fran,cais",
|
||||
"0113": "<FLAG_GERMAN> Deutsch",
|
||||
"0114": "<FLAG_SPAIN> Español",
|
||||
"0115": "<FLAG_ITALIAN> Italiano",
|
||||
"0116": "<FLAG_KOREA> ~Y~Z<K32e>~Z<K31a>~Z<K3c8>~Y~Z<K35e>~Z<K36b>~Z<K3de>~Y~Z<K30f>~Z<K31d>",
|
||||
"0117": "<FLAG_JAPAN> にほんご",
|
||||
"0118": "Kuvasuhde",
|
||||
"0119": "Progressiivinen skannaus",
|
||||
"011a": "Videotila",
|
||||
"011b": "Peliasetukset",
|
||||
"011c": "Grafiikan asetukset",
|
||||
"011d": "Ääniasetukset",
|
||||
"011e": "4x3",
|
||||
"011f": "16x9",
|
||||
"0120": "60Hz",
|
||||
"0121": "50Hz",
|
||||
"0122": "Jak II",
|
||||
"0123": "Poistu demosta",
|
||||
"0124": "Kyllä",
|
||||
"0125": "Ei",
|
||||
"0126": "Takaisin",
|
||||
"0127": "OK",
|
||||
"0128": "Seuraava",
|
||||
"0129": "Edellinen",
|
||||
"012a": "Jatka tallentamatta",
|
||||
"012b": "Valitse tallennuspaikka",
|
||||
"012c": "Valitse ladattava tallennus",
|
||||
"012d": "Lataa peli",
|
||||
"012e": "Tallenna peli",
|
||||
"012f": "Tyhjä",
|
||||
"0130": "Asetukset",
|
||||
"0131": "Uusi peli",
|
||||
"0132": "Paina START-näppäintä",
|
||||
"0133": "Lopeta peli",
|
||||
"0134": "Kartta",
|
||||
"0135": "Valitse aloitus",
|
||||
"0136": "Ennätykset",
|
||||
"0137": "1. sija",
|
||||
"0138": "2. sija",
|
||||
"0139": "3. sija",
|
||||
"013a": "4. sija",
|
||||
"013b": "5. sija",
|
||||
"013c": "6. sija",
|
||||
"013d": "7. sija",
|
||||
"013e": "8. sija",
|
||||
"013f": "NYFE-leijuri",
|
||||
"0140": "Luokka 1",
|
||||
"0141": "Luokka 2",
|
||||
"0142": "Luokka 3",
|
||||
"0143": "Harjoitusrata",
|
||||
"0144": "Haulikko",
|
||||
"0145": "Läjäytin",
|
||||
"0146": "Vulkanus-piippu",
|
||||
"0147": "Rauhantekijä",
|
||||
"0148": "Oninin haaste",
|
||||
"0149": "Metallipää-mäiskintä",
|
||||
"014a": "JET-lauta-haaste",
|
||||
"014b": "Oninin teltta",
|
||||
"014c": "Sikahevon saluuna",
|
||||
"014d": "Stadion",
|
||||
"014e": "Luokka 1 - käänteinen",
|
||||
"014f": "Luokka 2 - käänteinen",
|
||||
"0150": "Luokka 3 - käänteinen",
|
||||
"0151": "Sataman kisa",
|
||||
"0152": "Kaupungin kisa",
|
||||
"0153": "Salaisuudet",
|
||||
"0154": "Avattu",
|
||||
"0155": "Poista Jakin pukinparta",
|
||||
"0156": "Käänteinen maailma",
|
||||
"0157": "Loputtomat ammukset",
|
||||
"0158": "Haavoittumattomuus",
|
||||
"0159": "Sankaritila",
|
||||
"015a": "Välinäytösten 1. näytös",
|
||||
"015b": "Välinäytösten 2. näytös",
|
||||
"015c": "Välinäytösten 3. näytös",
|
||||
"015d": "Leikekirja",
|
||||
"015e": "Mega-leikekirja",
|
||||
"015f": "Leikekirja 3",
|
||||
"0160": "Tehtävän valinta",
|
||||
"0161": "Loputon Raivo-Jak",
|
||||
"0162": "Vulkanus-tykin harjoitusrata",
|
||||
"0163": "Rauhantekijän harjoitusrata",
|
||||
"0164": "Käänteiset kisat",
|
||||
"0165": "Isopäinen Jak",
|
||||
"0166": "Pienipäinen Jak",
|
||||
"0167": "Saatavilla",
|
||||
"0168": "Kerätty",
|
||||
"0169": "Tehtävät",
|
||||
"016a": "Valitse esialoitus",
|
||||
"016b": "Valitse kioski-aloitus",
|
||||
"016c": "Valitse kohtaus",
|
||||
"016d": "Tekstitys",
|
||||
"016e": "Aloita uudelleen",
|
||||
"016f": "<ICON_MISSION_TODO>",
|
||||
"0170": "<ICON_MISSION_COMPLETE>",
|
||||
"0171": "Ei mitään",
|
||||
"0172": "Peli",
|
||||
"0173": "Aloita/lopeta",
|
||||
"0174": "Osta",
|
||||
"0175": "Voitto",
|
||||
"0176": "Häviö",
|
||||
"0177": "Kokonaisaika",
|
||||
"0178": "Kierros ",
|
||||
"0179": "Palauta painamalla <PAD_SQUARE>",
|
||||
"017a": "Kiireinen",
|
||||
"017b": "Jatka painamalla <PAD_X>",
|
||||
"017c": "____~%Suoritetut tehtävät",
|
||||
"017d": "Suorittamattomat tehtävät",
|
||||
"017e": "Yritä uudelleen?",
|
||||
"017f": "Salaisuus saatavilla päävalikosta",
|
||||
"0180": "<PAD_X> = Kyllä, <PAD_TRIANGLE> = Ei",
|
||||
"0181": "Paina <PAD_TRIANGLE> puhuaksesi.",
|
||||
"0182": "Paina <PAD_TRIANGLE> käyttääksesi.",
|
||||
"0183": "Paina <PAD_TRIANGLE> matkustaaksesi.",
|
||||
"0184": "Valitse taso suuntanäppäimellä",
|
||||
"0185": "Paina <PAD_TRIANGLE> poistuaksesi.",
|
||||
"0186": "Paina <PAD_TRIANGLE> pelataksesi.",
|
||||
"0187": "Halutako pelata uudelleen?",
|
||||
"0188": "Tehtävä suoritettu",
|
||||
"0189": "Tehtävä epäonnistui",
|
||||
"018a": "Yritä uudelleen?",
|
||||
"018b": "Ruutu ottaa nyt käyttöön 60Hz-tilan",
|
||||
"018c": "Ruutu ottaa nyt käyttöön progressiivisen skannauksen",
|
||||
"018d": "Jos kuva näkyy virheellisenä, televisiosi ei tue tätä tilaa",
|
||||
"018e": "Jos niin käy, odota 10 sekuntia, niin ruutu palautuu takaisin",
|
||||
"018f": "Ruutu on nyt 60Hz-tilassa",
|
||||
"0190": "Ruutu on nyt Progresiivinen skannaus -tilassa",
|
||||
"0191": "Haluatko pitää tämän tilan käytössä?",
|
||||
"0192": "Levy poistettiin",
|
||||
"0193": "Syötä Jak II -levy sisään, jotta voit jatkaa pelaamista",
|
||||
"0194": "Virhe tietojen lukemisessa",
|
||||
"0195": "Tarkista Jak II -levysi ja yritä uudelleen",
|
||||
"0196": "Haluatko varmasti lopettaa?",
|
||||
"0197": "Haluatko aloittaa pelin?",
|
||||
"0198": "Ei tarpeeksi tilaa muistikortilla Memory__Card__(PS2) paikassa Memory__Card__Slot__~D",
|
||||
"0199": "Ei Memory__Card__(PS2) liitettynä paikassa Memory__Card__slot__~D",
|
||||
"019a": "Memory__Card__(PS2) paikassa Memory__Card__slot__~D on alustamaton",
|
||||
"019b": "Jak II vaatii ~D Kt vapaata tilaa",
|
||||
"019c": "Syötä Jak II -pelitietoja sisältävä Memory__Card__(PS2) paikkaan Memory__Card__slot__~D",
|
||||
"019d": "Syötä Memory__Card__(PS2) jossa on tarpeeksi tilaa, muuten pelitietojasi ei voida tallentaa",
|
||||
"019e": "Ilman alustamista pelitietoja ei voida tallentaa",
|
||||
"019f": "Tallennetaan tietoja",
|
||||
"01a0": "Ladataan tietoja",
|
||||
"01a1": "Alustetaan",
|
||||
"01a2": "Luodaan tallennustiedostoa",
|
||||
"01a3": "Älä poista Memory__Card__(PS2) paikassa Memory__Card__slot__~D tai sammuta laitettasi",
|
||||
"01a4": "Jak II -tallennus on jo olemassa valitsemassasi tiedostossa",
|
||||
"01a5": "Haluatko korvata tämän?",
|
||||
"01a6": "Alusta?",
|
||||
"01a7": "Jatka?",
|
||||
"01a8": "Takaisin?",
|
||||
"01a9": "Virhe ladattaessa",
|
||||
"01aa": "virhe tallentaessa",
|
||||
"01ab": "Virhe alustaessa",
|
||||
"01ac": "Virhe luodessa tallennustiedostoa",
|
||||
"01ad": "Tarkista Memory__Card__(PS2) paikassa Memory__Card__slot__~D",
|
||||
"01ae": "Tarkista Memory__Card__(PS2) paikassa Memory__Card__slot__~D ja yritä uudelleen",
|
||||
"01af": "Memory__Card__(PS2) paikasta Memory__Card__slot__~D poistettiin",
|
||||
"01b0": "Automaattinen tallennus on poistettu käytöstä",
|
||||
"01b1": "Tallenna pelisi manuaalisesti, niin automaattinen tallennus palautetaan käyttöön",
|
||||
"01b2": "Jak II -tallennustietoja ei löytynyt kortilta Memory__Card__(PS2) paikassa Memory__Card__slot__~D",
|
||||
"01b3": "Haluatko luoda uuden Jak II -tallennuksen?",
|
||||
"01b4": "Kun oheinen kuvake ilmestyy, edistykesi tallennetaan",
|
||||
"01b5": "Kun tämä kuvake on ruudulla, älä irrota Memory__Card__(PS2) tai sammuta laitettasi",
|
||||
"01b6": "Pakene <COLOR_WHITE>linnoituksesta",
|
||||
"01b7": "Suojele Koria ja lasta",
|
||||
"01b8": "Nouda lippu <COLOR_WHITE>aavekaupungista",
|
||||
"01b9": "Etsi <COLOR_WHITE>pumppaamon<COLOR_PROGRESS> venttiili",
|
||||
"01ba": "Räjäytä ammukset <COLOR_WHITE>linnoituksessa",
|
||||
"01bb": "Kuljeta toimitus <COLOR_WHITE>Sikahevon saluunaan",
|
||||
"01bc": "Läpäise haulikon <COLOR_WHITE>harjoitusrata",
|
||||
"01bd": "Suojele Sigiä <COLOR_WHITE>pumppaamolla",
|
||||
"01be": "Tuhoa tykit <COLOR_WHITE>viemärissä",
|
||||
"01bf": "Etsi <COLOR_WHITE>läjäytin<COLOR_PROGRESS>-modi",
|
||||
"01c0": "Pelasta Vin <COLOR_WHITE>avolouhoksella",
|
||||
"01c1": "Voita aika <COLOR_WHITE>kisatalliin",
|
||||
"01c2": "Läpäise läjäyttimen <COLOR_WHITE>harjoitusrata",
|
||||
"01c3": "Tuhoa munat <COLOR_WHITE>poralautalla",
|
||||
"01c4": "Etsi <COLOR_WHITE>pumppaamon<COLOR_PROGRESS> partio",
|
||||
"01c5": "Nouda rahat Krewille",
|
||||
"01c6": "Voita JET-lauta-haaste <COLOR_WHITE>stadionilla",
|
||||
"01c7": "Etsi Linssi <COLOR_WHITE>vuoristotemppelissä",
|
||||
"01c8": "Etsi Siru <COLOR_WHITE>vuoristotemppelissä",
|
||||
"01c9": "Etsi Ratas <COLOR_WHITE>vuoristotemppelissä",
|
||||
"01ca": "Käynnistä 5 virtakytkintä",
|
||||
"01cb": "Nouse hissillä <COLOR_WHITE>palatsiin",
|
||||
"01cc": "Päihitä paroni <COLOR_WHITE>palatsissa",
|
||||
"01cd": "Kuljeta Vastarinnan jäsenet",
|
||||
"01ce": "Suojele paikkaa <COLOR_WHITE>aavekaupungissa",
|
||||
"01cf": "Nappaa tarkkailijat <COLOR_WHITE>Havenin metsässä",
|
||||
"01d0": "Saata lapsi <COLOR_WHITE>voimalaan",
|
||||
"01d1": "Pelasta vaanijoita Brutterille",
|
||||
"01d2": "Tuhoa lasti <COLOR_WHITE>satamalla",
|
||||
"01d3": "Pysäytä tankkeri",
|
||||
"01d4": "Tuhoa välineistö <COLOR_WHITE>kaivannolla",
|
||||
"01d5": "Räjäytä ecokaivot <COLOR_WHITE>avolouhoksella",
|
||||
"01d6": "Tyhjennä <COLOR_WHITE>viemäri<COLOR_PROGRESS> löytääksesi patsaan",
|
||||
"01d7": "Tuhoa alus <COLOR_WHITE>poralautalla",
|
||||
"01d8": "Pelasta vaanijat <COLOR_WHITE>kaivannolla",
|
||||
"01d9": "Tapa Metallipäät <COLOR_WHITE>Havenin metsässä",
|
||||
"01da": "Voita luokan 3 kisa <COLOR_WHITE>stadionilla",
|
||||
"01db": "Nouda sinetin pala <COLOR_WHITE>kaivannolla",
|
||||
"01dc": "Nouda sinetin pala <COLOR_WHITE>vesislummeilla",
|
||||
"01dd": "Tuhoa 5 Villikissa-leijuria",
|
||||
"01de": "Voita Oninin haaste",
|
||||
"01df": "Käytä esineitä <COLOR_WHITE>Ei-kenenkään-kanjonissa",
|
||||
"01e0": "Kohtaa testit <COLOR_WHITE>Marin haudassa",
|
||||
"01e1": "Avaa holvin ovi <COLOR_WHITE>Marin haudassa",
|
||||
"01e2": "Läpäise ensimmäinen <COLOR_WHITE>miehuuden testi",
|
||||
"01e3": "Läpäise toinen <COLOR_WHITE>miehuuden testi",
|
||||
"01e4": "Päihitä paroni <COLOR_WHITE>Marin haudassa",
|
||||
"01e5": "Pelasta ystävät <COLOR_WHITE>linnoituksesta",
|
||||
"01e6": "Saata miehet <COLOR_WHITE>viemärien<COLOR_PROGRESS> läpi",
|
||||
"01e7": "Etsi <COLOR_WHITE>Rauhantekijä",
|
||||
"01e8": "Voita luokan 2 kisa <COLOR_WHITE>stadionilla",
|
||||
"01e9": "Suojele piilopaikkaa pommiboteilta",
|
||||
"01ea": "Tutki <COLOR_WHITE>rakennustyömaa",
|
||||
"01eb": "Kiipeä <COLOR_WHITE>rakennustyömaata",
|
||||
"01ec": "Voita Erol kisahaasteessa",
|
||||
"01ed": "Tuhoa munat <COLOR_WHITE>avolouhoksella",
|
||||
"01ee": "Nouda Elämän siemen <COLOR_WHITE>aavekaupungissa",
|
||||
"01ef": "Vie Elämän siemen <COLOR_WHITE>Havenin metsään",
|
||||
"01f0": "Suojele Samosia <COLOR_WHITE>Havenin metsässä",
|
||||
"01f1": "Tuhoa <COLOR_WHITE>poralautan<COLOR_PROGRESS> torni",
|
||||
"01f2": "Voita luokan 1 kisa <COLOR_WHITE>stadionilla",
|
||||
"01f3": "Tutki <COLOR_WHITE>palatsia",
|
||||
"01f4": "Hanki Marin sydän <COLOR_WHITE>asetehtaalla",
|
||||
"01f5": "Päihitä Krew <COLOR_WHITE>asetehtaalla",
|
||||
"01f6": "Voita peli <COLOR_WHITE>Sikahevon saluunassa",
|
||||
"01f7": "Etsi Sig <COLOR_WHITE>satamanpohjalla",
|
||||
"01f8": "Saata Sig <COLOR_WHITE>satamanpohjan<COLOR_PROGRESS> läpi",
|
||||
"01f9": "Puolusta <COLOR_WHITE>stadionia",
|
||||
"01fa": "Puolusta vaanijapalloa",
|
||||
"01fb": "Tuhoa tunnelit <COLOR_WHITE>satamanpohjalla",
|
||||
"01fc": "Taistele tiesi <COLOR_WHITE>pesän muurille",
|
||||
"01fd": "Löydä Paroni <COLOR_WHITE>rakennustyömaalla",
|
||||
"01fe": "Tuhoa <COLOR_WHITE>pesän muuri",
|
||||
"01ff": "Tuhoa Metalli-Kor <COLOR_WHITE>pesällä",
|
||||
"0200": "Puhu <COLOR_WHITE>Korille",
|
||||
"0201": "Puhu <COLOR_WHITE>Tornille",
|
||||
"0202": "Puhu <COLOR_WHITE>Krewille",
|
||||
"0203": "Puhu <COLOR_WHITE>Oninille",
|
||||
"0204": "Puhu <COLOR_WHITE>Vinille",
|
||||
"0205": "Puhu <COLOR_WHITE>Varjolle",
|
||||
"0206": "Puhu <COLOR_WHITE>Sigille",
|
||||
"0207": "Puhu <COLOR_WHITE>Mekaanikolle",
|
||||
"0208": "Puhu <COLOR_WHITE>Keiralle",
|
||||
"0209": "Puhu <COLOR_WHITE>Brutterille",
|
||||
"020a": "Tarkista <COLOR_WHITE>basaari",
|
||||
"020b": "Tarkista <COLOR_WHITE>vesislummit",
|
||||
"020c": "Mene <COLOR_WHITE>Ei-kenenkään-kanjonille",
|
||||
"020d": "Mene <COLOR_WHITE>Marin hautaan",
|
||||
"020e": "Voita <COLOR_WHITE>Metallipää-mäiskintä",
|
||||
"020f": "Puolusta <COLOR_WHITE>sataman muuria",
|
||||
"0210": "Tarkista <COLOR_WHITE>rakennustyömaa",
|
||||
"0211": "Hyökkää <COLOR_WHITE>Metallipäiden pesään",
|
||||
"0212": "Käy <COLOR_WHITE>Oraakkelin<COLOR_PROGRESS> luona",
|
||||
"0213": "Haven City",
|
||||
"0214": "Linnoitus",
|
||||
"0215": "Laskeutumisalusta",
|
||||
"0216": "Palatsin katto",
|
||||
"0217": "Palatsi",
|
||||
"0218": "Asetehdas",
|
||||
"0219": "Aavekaupunki",
|
||||
"021a": "Pumppaamo",
|
||||
"021b": "Viemäri",
|
||||
"021c": "Avolouhos",
|
||||
"021d": "Vuoristotemppeli",
|
||||
"021e": "Havenin metsä",
|
||||
"021f": "Poralautta",
|
||||
"0220": "Marin hauta",
|
||||
"0221": "Kaivanto",
|
||||
"0222": "Satamanpohja",
|
||||
"0223": "Pesä",
|
||||
"0224": "Hyppää painamalla <PAD_X>",
|
||||
"0225": "Kieri painamalla <PAD_L1> liikkeessä",
|
||||
"0226": "Paina <PAD_X> ja sitten <PAD_X> uudelleen ilmassa",
|
||||
"0227": "Hyökkää painamalla <PAD_SQUARE> tai <PAD_CIRCLE>",
|
||||
"0228": "Kieri ja paina sitten <PAD_X> syöksyhyppyyn",
|
||||
"0229": "Hyppää ja paina <PAD_SQUARE> ilmassa",
|
||||
"022a": "Paina <PAD_L1> ja sitten <PAD_X> korkeaan hyppyyn",
|
||||
"022b": "Ammu painamalla <PAD_R1>",
|
||||
"022c": "<PAD_DPAD_UP> laittaa aseen pois",
|
||||
"022d": "<PAD_DPAD_UP> tai <PAD_R1> tuo aseen esiin",
|
||||
"022e": "Pelaa haulikon harjoitusrata painamalla <PAD_X>",
|
||||
"022f": "<PAD_X> = Haulikon harjoitus~%<PAD_SQUARE> = Vulkanus-tykin harjoitus",
|
||||
"0230": "Vaihda asetta painamalla <PAD_DPAD_DOWN>",
|
||||
"0231": "Pelaa läjäyttimen harjoitusrata painamalla <PAD_X>",
|
||||
"0232": "<PAD_X> = Läjäyttimen harjoitus~%<PAD_SQUARE> = Rauhantekijän harjoitus",
|
||||
"0233": "Potkaise kohdetta ja paina <PAD_R1> tehdäksesi pikatulisarjan",
|
||||
"0234": "Ammu laatikoita",
|
||||
"0235": "Tavoite",
|
||||
"0236": "Kulta",
|
||||
"0237": "Hopea",
|
||||
"0238": "Pronssi",
|
||||
"0239": "Käytä lautaa painamalla <PAD_R2>",
|
||||
"023a": "Hyppy: Paina <PAD_X>",
|
||||
"023b": "Kyykkyhyppy: Paina <PAD_L1> ja sitten <PAD_X>",
|
||||
"023c": "Voimahyppy: Paina <PAD_X> hieman laskeuduttuasi hypystä",
|
||||
"023d": "Kaideliuku: Paina <PAD_SQUARE> ja <PAD_ANALOG_ANY>",
|
||||
"023e": "Pyörähdys: Paina <PAD_X> ja sitten <PAD_R1> ja <PAD_ANALOG_LEFT_RIGHT>",
|
||||
"023f": "Voltti: Paina <PAD_X> ja sitten <PAD_R1> ja <PAD_ANALOG_UP_DOWN>",
|
||||
"0240": "Temppu: Paina <PAD_X> ja sitten <PAD_L1> ja <PAD_ANALOG_ANY>",
|
||||
"0241": "Saat paljon pisteitä, jos liu'ut ja teet tempun liukuaksesi uudestaan",
|
||||
"0242": "Aloita haaste aktivoimalla tuomari",
|
||||
"0243": "Yritä uudelleen!",
|
||||
"0244": "Palaa talliin",
|
||||
"0245": "Tehtävä suoritettu: Palaa Krewin luo",
|
||||
"0246": "Vaihda leijuvyöhykettä painamalla <PAD_R2>",
|
||||
"0247": "Sukella painamalla <PAD_CIRCLE> pohjassa uidessasi",
|
||||
"0248": "<PAD_CIRCLE> = Turbo~%<PAD_R1> tai <PAD_L1> = Hyppy",
|
||||
"0249": "Iske Titaaniasulla painamalla <PAD_SQUARE>",
|
||||
"024a": "Tartu Titaaniasulla lohkareisiin painamalla <PAD_R1>",
|
||||
"024b": "Heitä nostetut esineet painamalla <PAD_SQUARE>",
|
||||
"024c": "Paina <PAD_X> rampin yläpäässä",
|
||||
"024d": "Liu'u kaidetta JET-laudalla painamalla <PAD_SQUARE> tai <PAD_CIRCLE>",
|
||||
"024e": "Käytä <PAD_DPAD_ANY> ja <PAD_X> <PAD_CIRCLE> <PAD_SQUARE> <PAD_TRIANGLE>",
|
||||
"024f": "Pumppaamo",
|
||||
"0250": "Avolouhos",
|
||||
"0251": "Katso traileri",
|
||||
"0252": "<PAD_R2> mennäksesi laudan päälle tai pois",
|
||||
"0253": "Käytä pimeää voimaa painamalla <PAD_L2>",
|
||||
"0254": "Sony Computer Entertainment America~%presents",
|
||||
"0255": "Sony Computer Entertainment Europe~%presents",
|
||||
"0256": "Sony Computer Entertainment Korea~%presents",
|
||||
"0257": "Sony Computer Entertainment Inc.~%presents",
|
||||
"0258": "A game by",
|
||||
"0259": "Jak II",
|
||||
"025a": "Kaksi vuotta myöhemmin...",
|
||||
"025b": "Viikko myöhemmin...",
|
||||
"025c": "Asepäivitys hankittu",
|
||||
"025d": "Haulikko hankittu",
|
||||
"025e": "Läjäytin-modi mankittu",
|
||||
"025f": "Vulkanus-piippu hankittu",
|
||||
"0260": "Rauhantekijä hankittu",
|
||||
"0261": "Haulikon tulinopeus päivitetty",
|
||||
"0262": "Aseiden ammuskapasiteetti päivitetty",
|
||||
"0263": "Aseiden vahinkoa päivitetty",
|
||||
"0264": "Tehtävä suoritettu",
|
||||
"0265": "Punainen turvapassi hankittu",
|
||||
"0266": "Vihreä turvapassi hankittu",
|
||||
"0267": "Keltainen turvapassi hankittu",
|
||||
"0268": "Palatsin turvapassi hankittu",
|
||||
"0269": "Musta turvapassi hankittu",
|
||||
"026a": "Linssi hankittu",
|
||||
"026b": "Ratas hankittu",
|
||||
"026c": "Siru hankittu",
|
||||
"026d": "Tuo 25 metallipäiden kallohelmeä",
|
||||
"026e": "Tuo 200 metallipäiden kallohelmeä",
|
||||
"026f": "Tuo 25 metallipäiden kallohelmeä",
|
||||
"0270": "Tuo 200 metallipäiden kallohelmeä",
|
||||
"0271": "Tuo 200 metallipäiden kallohelmeä",
|
||||
"0272": "Tuo 100 metallipäiden kallohelmeä",
|
||||
"0273": "Raivopommi: Paina <PAD_X> ja sitten <PAD_SQUARE>",
|
||||
"0274": "Raivopurkaus: Paina <PAD_SQUARE> ja sitten <PAD_X>",
|
||||
"0275": "Raivo-Jak on nyt haavoittumaton!",
|
||||
"0276": "Raivojätti: Paina <PAD_L2> raivotilassa",
|
||||
"0277": "Ohi",
|
||||
"0278": "Valitse tapahtuma",
|
||||
"0279": "Skeittipuisto",
|
||||
"027a": "Luokan 3 kisa",
|
||||
"027b": "Luokan 2 kisa",
|
||||
"027c": "Luokan 1 kisa",
|
||||
"027d": "Käänteinen luokan 3 kisa",
|
||||
"027e": "Käänteinen luokan 2 kisa",
|
||||
"027f": "Käänteinen luokan 1 kisa",
|
||||
"0280": "Daxter saa suupalan",
|
||||
"0281": "Tavataan Torn",
|
||||
"0282": "Noutamassa lippua",
|
||||
"0283": "Suojele pyhää paikkaa",
|
||||
"0284": "Meidän maailmamme!",
|
||||
"0285": "Vanhoja muistoja",
|
||||
"0286": "Vin tarvitsee apua",
|
||||
"0287": "Tavataan Vin",
|
||||
"0288": "Hyviä ja huonoja uutisia",
|
||||
"0289": "Suuri murskaus",
|
||||
"028a": "Meillä on yhä ongelmia",
|
||||
"028b": "Kaivot posahtavat!",
|
||||
"028c": "Tavataan Kor ja lapsi",
|
||||
"028d": "Vastarinta",
|
||||
"028e": "Villikissa-tehtävä",
|
||||
"028f": "Tornin toimitus",
|
||||
"0290": "Tavataan Krew ja Sig",
|
||||
"0291": "Yllätyshyökkäys!",
|
||||
"0292": "Ashelin on huolissaan",
|
||||
"0293": "Vin, kamu. Tarvitsemme palveluksen.",
|
||||
"0294": "Kuka on verhojen takana?",
|
||||
"0295": "Tiedonjyvä",
|
||||
"0296": "Iloinen jälleennäkeminen",
|
||||
"0297": "Kissatappelu",
|
||||
"0298": "Jak poistuu paikalta",
|
||||
"0299": "Daxterin suuri voitto",
|
||||
"029a": "Keira paljastaa suunnitelmansa",
|
||||
"029b": "Suuri kilpailu",
|
||||
"029c": "Voittajan piiri",
|
||||
"029d": "Tavataan Oraakkeli",
|
||||
"029e": "Jak saa pimeän voiman",
|
||||
"029f": "Jak saa toisen pimeän voiman",
|
||||
"02a0": "Jak saa kolmannen pimeän voiman",
|
||||
"02a1": "Jak saa neljännen pimeän voiman",
|
||||
"02a2": "Valitus, naiset, ja laulu",
|
||||
"02a3": "Rahankerääjät",
|
||||
"02a4": "Mikä tämän lapsen tarina on?",
|
||||
"02a5": "Krewilla on uusi keikka",
|
||||
"02a6": "Tavataan Brutter",
|
||||
"02a7": "Krewin kilpailusopimus",
|
||||
"02a8": "Mitä te kaksi oikein teitte?",
|
||||
"02a9": "Oninin haaste",
|
||||
"02aa": "Marin sinetti on valmis",
|
||||
"02ab": "Pelasta lisää vaanijoita",
|
||||
"02ac": "Suojele piilopaikkaa",
|
||||
"02ad": "Krew uhkailee",
|
||||
"02ae": "Pelaaja astelee esiin",
|
||||
"02af": "Saadaan aikakartta",
|
||||
"02b0": "Brutter pelastaa päivän",
|
||||
"02b1": "Leijutaan pois",
|
||||
"02b2": "Saadaan keltainen ase",
|
||||
"02b3": "Saadaan JET-lauta",
|
||||
"02b4": "Jak laittaa JET-laudan pois",
|
||||
"02b5": "Ihka oma Rauhantekijämme!",
|
||||
"02b6": "Ulosmeno",
|
||||
"02b7": "Jak matkaa pesään",
|
||||
"02b8": "Paluu",
|
||||
"02b9": "Ashelin kuljettaa Jakin",
|
||||
"02ba": "Pala sinettiä",
|
||||
"02bb": "Erol inhoaa häviötä",
|
||||
"02bc": "Torn ja ammusvarasto",
|
||||
"02bd": "Metallipäitä kaupungissa?",
|
||||
"02be": "Nyt räjähtää!",
|
||||
"02bf": "Torn myöntää petoksensa",
|
||||
"02c0": "Aikakaksoset",
|
||||
"02c1": "Krewin viemärikeikka",
|
||||
"02c2": "Mikä on tuo löyhkä?",
|
||||
"02c3": "Taiteenkeräilijä",
|
||||
"02c4": "Että kaipaankin housuja!",
|
||||
"02c5": "Sig paljastaa sielunsa",
|
||||
"02c6": "Patsaanposauttelua",
|
||||
"02c7": "Se on ansa!",
|
||||
"02c8": "Daxter saa suupalan",
|
||||
"02c9": "Daxter matkustaa putkea",
|
||||
"02ca": "Työtarjous",
|
||||
"02cb": "Torn tarjoaa tehtävän",
|
||||
"02cc": "Tavataan Ashelin",
|
||||
"02cd": "Daxter tekee siirtonsa",
|
||||
"02ce": "Tästä tulee hauskaa!",
|
||||
"02cf": "Boom, beibi!",
|
||||
"02d0": "Peukut alas",
|
||||
"02d1": "Heihei",
|
||||
"02d2": "Temppu",
|
||||
"02d3": "Hyvää yötä",
|
||||
"02d4": "Toimit hienosti, tulokas",
|
||||
"02d5": "Vin tahtoo munakokkelia",
|
||||
"02d6": "Kor on huolissaan",
|
||||
"02d7": "Poika on kadoksissa",
|
||||
"02d8": "Ohjaustorni räjähtää",
|
||||
"02d9": "Tavataan Onin ja Pecker",
|
||||
"02da": "Vekotin romahtaa",
|
||||
"02db": "Hyvät fiilikset",
|
||||
"02dc": "Daxter kärventyy",
|
||||
"02dd": "Salatapaaminen",
|
||||
"02de": "Paroni kohtaa Jakin",
|
||||
"02df": "Minä tuhoan sinut!",
|
||||
"02e0": "Takaisin mistä aloitimme",
|
||||
"02e1": "Salaisuus pommin rakentamiseen",
|
||||
"02e2": "Krewin kaunotar",
|
||||
"02e3": "Oi voi...",
|
||||
"02e4": "Lentoon",
|
||||
"02e5": "Laskeutumisalusta",
|
||||
"02e6": "Jak löytää Marin haudan!",
|
||||
"02e7": "tomb-open-door-res",
|
||||
"02e8": "tomb-open-door-2-res",
|
||||
"02e9": "Haudan ovet",
|
||||
"02ea": "Ensimmäinen säde",
|
||||
"02eb": "Toinen säde",
|
||||
"02ec": "Ovet avautuvat",
|
||||
"02ed": "Edeltäjäkivi!",
|
||||
"02ee": "Paroni varastaa show'n",
|
||||
"02ef": "Daxter ojentaa auttavan kätensä",
|
||||
"02f0": "Daxterin karvainen takaa-ajo",
|
||||
"02f1": "Tavataan Varjo",
|
||||
"02f2": "Daxterin pöhkötarina",
|
||||
"02f3": "Pecker haastaa riitaa",
|
||||
"02f4": "Samos ja siemen",
|
||||
"02f5": "Näky",
|
||||
"02f6": "Kor ja lapsi",
|
||||
"02f7": "Pelasta lisää vaanijoita",
|
||||
"02f8": "Marin haudan legenda",
|
||||
"02f9": "Se on kirous, eikö vain?",
|
||||
"02fa": "Pora romahtaa",
|
||||
"02fb": "Valotorni nousee",
|
||||
"02fc": "Sinetti avaa portin",
|
||||
"02fd": "Sig on ongelmissa",
|
||||
"02fe": "Juokse!",
|
||||
"02ff": "Sigin vahva käsi",
|
||||
"0300": "Sieltä se taas tulee!",
|
||||
"0301": "Sigin viimeinen hetki",
|
||||
"0302": "Kivi... ase... pesä!",
|
||||
"0303": "Jak matkaa pesään",
|
||||
"0304": "Poistutaan pesästä",
|
||||
"0305": "Kor hyppää esiin",
|
||||
"0306": "Etkö tunnista häntä?",
|
||||
"0307": "Outo uusi maailma",
|
||||
"0308": "Juhlinta",
|
||||
"0309": "<ICON_MISSION_COMPLETE>",
|
||||
"030a": "<ICON_MISSION_TODO>",
|
||||
"030b": "<FLAG_UK> English",
|
||||
"030c": "Ota tekstitys käyttöön painamalla <PAD_SQUARE>",
|
||||
"030d": "Tekstitys käytössä",
|
||||
"030e": "Tekstitys ei käytössä",
|
||||
"030f": "JET-lauta",
|
||||
"0310": "Jatka"
|
||||
}
|
||||
@@ -232,5 +232,6 @@
|
||||
"1336": "Fast Progress Menu",
|
||||
"1337": "PS2 LOD Distance",
|
||||
"1338": "Off",
|
||||
"1339": "Display"
|
||||
"1339": "Display",
|
||||
"133a": "Suomi"
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"1101": "Pelataan bonustehtävää",
|
||||
"1102": "Haulikon harjoitusrata",
|
||||
"1103": "Läjäyttimen harjoitusrata",
|
||||
"1104": "Vulkanusraivon harjoitusrata",
|
||||
"1104": "Vulkanus-tykin harjoitusrata",
|
||||
"1105": "Rauhantekijän harjoitusrata",
|
||||
"1106": "Oninin haaste",
|
||||
"1107": "Metallipää-mäiskintä",
|
||||
@@ -18,8 +18,8 @@
|
||||
"1206": "4x3 (PS2)",
|
||||
"1207": "16x9 (PS2)",
|
||||
"1208": "Valitse leveys- ja korkeussuhde",
|
||||
"1209": "Paina <PAD_X> vahvistaaksesi ja poistuaksesi.",
|
||||
"120a": "Paina <PAD_CIRCLE> vahvistaaksesi ja poistuaksesi.",
|
||||
"1209": "Vahvista ja poistu painamalla <PAD_X>.",
|
||||
"120a": "Vahvista ja poistu painamalla <PAD_CIRCLE>.",
|
||||
"120b": "Kuvasuhde ei saa olla pienempi kuin 4x3!",
|
||||
"120c": "Musiikkisoitin",
|
||||
"120d": "Pystytahdistus",
|
||||
@@ -34,7 +34,7 @@
|
||||
"1216": "Muuntoase",
|
||||
"1217": "JET-lauta",
|
||||
"1218": "Titaaniasu",
|
||||
"1219": "Pimeä Jak",
|
||||
"1219": "Raivo-Jak",
|
||||
"121a": "Ajoneuvo",
|
||||
"121b": "Vaara",
|
||||
"121c": "Ei mikään",
|
||||
@@ -85,10 +85,10 @@
|
||||
"124a": "Ohjaimen LED-asetukset",
|
||||
"124b": "Näytä pelaajan tila",
|
||||
"124c": "Näytä terveyden määrä",
|
||||
"124d": "Lopeta auto-tallennus",
|
||||
"124e": "Auto-tallennus pois päältä",
|
||||
"124d": "Lopeta autom. tallennus",
|
||||
"124e": "Autom. tallennus pois",
|
||||
"124f": "Haluatko varmasti lopettaa automaattisen tallentamisen?",
|
||||
"1250": "Turbo JET-lauta Haven Cityssä",
|
||||
"1250": "Turbo-JET-lauta Haven Cityssä",
|
||||
"1251": "Vihollisten terveyspalkit",
|
||||
"1252": "Ajoneuvojen terveyspalkit",
|
||||
"1253": "Ajoneuvojen haavoittumattomuus",
|
||||
@@ -96,13 +96,13 @@
|
||||
"1255": "Kerää kerättävät automaattisesti",
|
||||
"1256": "Musiikkisoitin",
|
||||
"1257": "Tekstuuriton tila",
|
||||
"1258": "Nopeat välianimaatiot",
|
||||
"1259": "Hitaat välianimaatiot",
|
||||
"1258": "Nopeat välinäytökset",
|
||||
"1259": "Hitaat välinäytökset",
|
||||
"125a": "Nopea pelattavuus",
|
||||
"125b": "Hidas pelattavuus",
|
||||
"125c": "Pikamatkustus Haven Cityssä",
|
||||
"125d": "Edeltäjähelmien seuranta",
|
||||
"125e": "Todellinen vuorokauden aika",
|
||||
"125e": "Todellinen vuorokaudenaika",
|
||||
"125f": "Tyyni Haven City",
|
||||
"1260": "Näytä JET-laudan temput",
|
||||
"1261": "Huono sää",
|
||||
@@ -112,14 +112,14 @@
|
||||
"1265": "Käännä kaikki 3 venttiiliä ja löydä Marin patsas tehtävässä \"~S\" alle ~D sekunnissa",
|
||||
"1266": "Vähennä Haven Cityn asukaslukua ~D kappaleella",
|
||||
"1267": "Vähennä Haven Cityn ajoneuvojen määrää ~D kappaleella",
|
||||
"1268": "Metsästä jokaista Metallipäälajia",
|
||||
"1268": "Metsästä jokaista metallipää-lajia",
|
||||
"1269": "Käytä JET-lautaa rikkoaksesi säiliöt auki",
|
||||
"126a": "Siirrä repeämäkuljetin jättäen Samos ja nuori Samos vaurioitta",
|
||||
"1280": "Kuvakulma-asetukset",
|
||||
"1281": "Vasen/oikea (ensimmäinen persoona)",
|
||||
"1282": "Ylös/alas (ensimmäinen persoona)",
|
||||
"1283": "Vasen/oikea (kolmas persoona)",
|
||||
"1284": "Ylös/alas (kolmas persoona)",
|
||||
"1281": "Vasen/oikea (1. persoona)",
|
||||
"1282": "Ylös/alas (1. persoona)",
|
||||
"1283": "Vasen/oikea (3. persoona)",
|
||||
"1284": "Ylös/alas (3. persoona)",
|
||||
"1285": "Palauta oletukset",
|
||||
"1286": "Normaali",
|
||||
"1287": "Käänteinen",
|
||||
@@ -137,15 +137,15 @@
|
||||
"1293": "Ohjainasetukset",
|
||||
"1294": "Valitse ohjain",
|
||||
"1295": "Analogisauvan katvealue",
|
||||
"1296": "Älä huomioi, kun ikkuna ei aktiivinen",
|
||||
"1296": "Älä huomioi työpöydällä",
|
||||
"1297": "Ohjaimen LED terveydelle",
|
||||
"1298": "Ohjaimen LED muihin tiloihin",
|
||||
"1299": "Salli näppäimistö",
|
||||
"129a": "Salli hiiri",
|
||||
"129b": "Hiiriasetukset",
|
||||
"129c": "Kameran ohjaus hiirellä",
|
||||
"129d": "Vaakasuuntainen herkkyys",
|
||||
"129e": "Pystysuuntainen herkkyys",
|
||||
"129d": "Herkkyys (vaakasuunta)",
|
||||
"129e": "Herkkyys (pystysuunta)",
|
||||
"129f": "Pelaajan ohjaus hiirellä",
|
||||
"12a0": "Objektien varjot",
|
||||
"12a1": "Normaali",
|
||||
@@ -156,25 +156,25 @@
|
||||
"12a6": "Muut tilastot",
|
||||
"12a7": "Tappoja yhteensä",
|
||||
"12a8": "Jakin tappamia",
|
||||
"12a9": "Pimeän Jakin tappamia",
|
||||
"12a9": "Raivo-Jakin tappamia",
|
||||
"12aa": "Daxterin tappamia",
|
||||
"12ab": "Muiden tappamia",
|
||||
"12ac": "Läjäytin",
|
||||
"12ad": "Haulikko",
|
||||
"12ae": "Vulkanusraivo",
|
||||
"12ae": "Vulkanus-tykki",
|
||||
"12af": "Rauhantekijä",
|
||||
"12b0": "JET-lauta",
|
||||
"12b1": "JET-lautatemppu",
|
||||
"12b1": "JET-lauta-temppu",
|
||||
"12b2": "Titaaniasun isku",
|
||||
"12b3": "Titaaniasun runko",
|
||||
"12b4": "Tykki",
|
||||
"12b5": "Isku",
|
||||
"12b6": "Lyyhistyi",
|
||||
"12b6": "Maaisku",
|
||||
"12b7": "Kohokoukku",
|
||||
"12b8": "Pyörähdys",
|
||||
"12b9": "Kierintä",
|
||||
"12bf": "Pimeä pommi",
|
||||
"12c0": "Pimeä purkaus",
|
||||
"12bf": "Raivopommi",
|
||||
"12c0": "Raivopurkaus",
|
||||
"12c3": "Karmiinivartija",
|
||||
"12c4": "Sig",
|
||||
"12c5": "Ashelin",
|
||||
@@ -208,24 +208,24 @@
|
||||
"1315": "Tämä asetus on erittäin kokeellinen. Kun peliä ei pelata 60 Hz:n kuvataajuudella, visuaalisia sekä pelattavuuden ongelmia voi ilmaantua sen seurauksena.",
|
||||
"1316": "Paikallinen tulos",
|
||||
"1320": "Ei mitään",
|
||||
"1321": "Spin",
|
||||
"1322": "Buusti",
|
||||
"1321": "Pyörähdys",
|
||||
"1322": "Nopeuslisä",
|
||||
"1323": "Voltti",
|
||||
"1324": "Kaideliuku",
|
||||
"1325": "Kaidehyppy",
|
||||
"1326": "Nosegrab",
|
||||
"1327": "Method",
|
||||
"1328": "Board Spin",
|
||||
"1329": "Board Flip",
|
||||
"1328": "Lautapyörähdys",
|
||||
"1329": "Lautavoltti",
|
||||
"132a": "Noseflip",
|
||||
"132b": "Kickflip",
|
||||
"132c": "Hyppy",
|
||||
"132d": "Kyykkyhyppy",
|
||||
"132e": "Pikahyppy",
|
||||
"132f": "Pimeä Jak",
|
||||
"1330": "Pimeä pommi",
|
||||
"1331": "Pimeä purkaus",
|
||||
"1332": "Pimeä jätti",
|
||||
"132f": "Raivo-Jak",
|
||||
"1330": "Raivopommi",
|
||||
"1331": "Raivopurkaus",
|
||||
"1332": "Raivojätti",
|
||||
"1333": "PS2-asetukset",
|
||||
"1334": "Objektien vähennys",
|
||||
"1335": "Pakota ympäristökartoitus",
|
||||
|
||||
@@ -484,7 +484,7 @@
|
||||
03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -873,6 +873,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:MacOSX
|
||||
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1080,7 +1081,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b10,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
|
||||
030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -1090,6 +1091,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -1388,6 +1390,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux,
|
||||
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1465,7 +1468,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1687,6 +1690,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050082795e040000e002000003090000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
@@ -1694,7 +1698,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -31,19 +31,3 @@ struct RPC_Dgo_Cmd {
|
||||
// a buffer.
|
||||
uint8_t pad[32];
|
||||
};
|
||||
|
||||
namespace jak3 {
|
||||
struct RPC_Dgo_Cmd {
|
||||
uint16_t rsvd;
|
||||
uint16_t result;
|
||||
uint32_t buffer1;
|
||||
uint32_t buffer2;
|
||||
uint32_t buffer_heap_top;
|
||||
char name[16];
|
||||
uint16_t cgo_id;
|
||||
uint8_t pad[30];
|
||||
};
|
||||
static_assert(sizeof(RPC_Dgo_Cmd) == 0x40);
|
||||
} // namespace jak3
|
||||
|
||||
static_assert(sizeof(RPC_Dgo_Cmd) == sizeof(jak3::RPC_Dgo_Cmd));
|
||||
@@ -3,6 +3,10 @@
|
||||
#include "fmt/core.h"
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
std::string BucketRenderer::name() const {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string BucketRenderer::name_and_id() const {
|
||||
return fmt::format("[{:2d}] {}", (int)m_my_id, m_name);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ class EyeRenderer;
|
||||
struct SharedRenderState {
|
||||
explicit SharedRenderState(std::shared_ptr<TexturePool> _texture_pool,
|
||||
std::shared_ptr<Loader> _loader,
|
||||
GameVersion version)
|
||||
: shaders(version), texture_pool(_texture_pool), loader(_loader) {}
|
||||
GameVersion _version)
|
||||
: shaders(_version), texture_pool(_texture_pool), loader(_loader), version(_version) {}
|
||||
ShaderLibrary shaders;
|
||||
std::shared_ptr<TexturePool> texture_pool;
|
||||
std::shared_ptr<Loader> loader;
|
||||
@@ -98,6 +98,7 @@ class BucketRenderer {
|
||||
virtual void render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) = 0;
|
||||
std::string name() const;
|
||||
std::string name_and_id() const;
|
||||
virtual ~BucketRenderer() = default;
|
||||
bool& enabled() { return m_enabled; }
|
||||
@@ -158,4 +159,4 @@ class PrintRenderer : public BucketRenderer {
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
bool empty() const override { return true; }
|
||||
void draw_debug_window() override {}
|
||||
};
|
||||
};
|
||||
@@ -579,6 +579,7 @@ u32 get_direct_qwc_or_nop(const VifCode& code) {
|
||||
return code.immediate;
|
||||
}
|
||||
default:
|
||||
printf("expected direct, got %s\n", code.print().c_str());
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ EyeRenderer::SpriteInfo decode_sprite(const DmaTransfer& dma) {
|
||||
memcpy(&result.a, dma.data + 16 + 12, 1); // a
|
||||
|
||||
// uv0
|
||||
memcpy(&result.uv0[0], &dma.data[32], 8);
|
||||
memcpy(&result.uv0, &dma.data[32], 8);
|
||||
|
||||
// xyz0
|
||||
memcpy(&result.xyz0[0], &dma.data[48], 12);
|
||||
@@ -236,8 +236,11 @@ std::vector<EyeRenderer::SingleEyeDraws> EyeRenderer::get_draws(DmaFollower& dma
|
||||
bool using_64 = false;
|
||||
{
|
||||
auto draw0 = read_eye_draw(dma);
|
||||
ASSERT(draw0.sprite.uv0[0] == 0);
|
||||
ASSERT(draw0.sprite.uv0[1] == 0);
|
||||
// ASSERT(draw0.sprite.uv0[0] == 0);
|
||||
// ASSERT(draw0.sprite.uv0[1] == 0);
|
||||
// printf("hashed name is 0x%x 0x%x\n", draw0.sprite.uv0[0], draw0.sprite.uv0[1]);
|
||||
l_draw.fnv_name_hash = draw0.sprite.uv0;
|
||||
r_draw.fnv_name_hash = draw0.sprite.uv0;
|
||||
ASSERT(draw0.sprite.uv1[0] == 0);
|
||||
ASSERT(draw0.sprite.uv1[1] == 0);
|
||||
if (draw0.scissor.y1 - draw0.scissor.y0 == 63) {
|
||||
@@ -509,7 +512,9 @@ void EyeRenderer::run_gpu(const std::vector<SingleEyeDraws>& draws,
|
||||
buffer_idx = 0;
|
||||
for (size_t draw_idx = 0; draw_idx < draws.size(); draw_idx++) {
|
||||
const auto& draw = draws[draw_idx];
|
||||
const auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
|
||||
auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
|
||||
out_tex.fnv_name_hash = draw.fnv_name_hash;
|
||||
out_tex.lr = draw.lr;
|
||||
|
||||
// first, the clear
|
||||
float clear[4] = {0, 0, 0, 0};
|
||||
@@ -574,15 +579,30 @@ std::optional<u64> EyeRenderer::lookup_eye_texture(u8 eye_id) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<u64> EyeRenderer::lookup_eye_texture_hash(u64 hash, bool lr) {
|
||||
for (auto& slot : m_gpu_eye_textures) {
|
||||
if (slot.fnv_name_hash == hash && slot.lr == lr) {
|
||||
auto* gpu_tex = slot.gpu_tex;
|
||||
if (gpu_tex) {
|
||||
return gpu_tex->gpu_textures.at(0).gl;
|
||||
} else {
|
||||
fmt::print("lookup eye failed for {} (1)\n", hash);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt::print("lookup eye failed for {} (2)\n", hash);
|
||||
return {};
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// DMA Decode
|
||||
//////////////////////
|
||||
|
||||
std::string EyeRenderer::SpriteInfo::print() const {
|
||||
std::string result;
|
||||
result +=
|
||||
fmt::format("a: {:x} uv: ({}, {}), ({}, {}) xyz: ({}, {}, {}), ({}, {}, {})", a, uv0[0],
|
||||
uv0[1], uv1[0], uv1[1], xyz0[0], xyz0[1], xyz0[2], xyz1[0], xyz1[1], xyz1[2]);
|
||||
result += fmt::format("a: {:x} uv: ({}), ({}, {}) xyz: ({}, {}, {}), ({}, {}, {})", a, uv0,
|
||||
uv1[0], uv1[1], xyz0[0], xyz0[1], xyz0[2], xyz1[0], xyz1[1], xyz1[2]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,11 @@ class EyeRenderer : public BucketRenderer {
|
||||
|
||||
void handle_eye_dma2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
std::optional<u64> lookup_eye_texture(u8 eye_id);
|
||||
std::optional<u64> lookup_eye_texture_hash(u64 hash, bool lr);
|
||||
|
||||
struct SpriteInfo {
|
||||
u8 a;
|
||||
u32 uv0[2];
|
||||
u64 uv0; // stores hashed name of merc-ctrl that reads this eye.
|
||||
u32 uv1[2];
|
||||
u32 xyz0[3];
|
||||
u32 xyz1[3];
|
||||
@@ -53,6 +54,8 @@ class EyeRenderer : public BucketRenderer {
|
||||
GpuTexture* gpu_tex = nullptr;
|
||||
u32 tbp;
|
||||
FramebufferTexturePair fb;
|
||||
u64 fnv_name_hash = 0;
|
||||
bool lr = false;
|
||||
|
||||
// note: eye texture increased to 128x128 (originally 32x32) here.
|
||||
GpuEyeTex() : fb(128, 128, GL_UNSIGNED_INT_8_8_8_8_REV) {}
|
||||
@@ -65,6 +68,7 @@ class EyeRenderer : public BucketRenderer {
|
||||
GLuint m_gl_vertex_buffer;
|
||||
|
||||
struct SingleEyeDraws {
|
||||
u64 fnv_name_hash = 0;
|
||||
int lr;
|
||||
int pair;
|
||||
bool using_64 = false;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "game/graphics/pipelines/opengl.h"
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
#include "third-party/imgui/imgui_stdlib.h"
|
||||
|
||||
// for the vif callback
|
||||
#include "game/kernel/common/kmachine.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include "common/util/string_util.h"
|
||||
|
||||
namespace {
|
||||
std::string g_current_renderer;
|
||||
@@ -84,7 +86,11 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
|
||||
&gl_error_ignores_api_other[0], GL_FALSE);
|
||||
#endif
|
||||
|
||||
lg::debug("OpenGL context information: {}", (const char*)glGetString(GL_VERSION));
|
||||
lg::info("OpenGL context version: {}", (const char*)glGetString(GL_VERSION));
|
||||
lg::info("OpenGL context renderer: {}", (const char*)glGetString(GL_RENDERER));
|
||||
lg::info("OpenGL context vendor: {}", (const char*)glGetString(GL_VENDOR));
|
||||
lg::info("OpenGL context shading language version: {}",
|
||||
(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
const tfrag3::Level* common_level = nullptr;
|
||||
{
|
||||
@@ -263,6 +269,11 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC_L0_PRIS, BucketId::GMERC_L1_PRIS, i), m_generic2,
|
||||
Generic2::Mode::NORMAL);
|
||||
|
||||
init_bucket_renderer<Generic2BucketRenderer>(
|
||||
fmt::format("gmerc2-l{}-pris", i), BucketCategory::GENERIC,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_PRIS, BucketId::GMERC2_L1_PRIS, i), m_generic2,
|
||||
Generic2::Mode::PRIM);
|
||||
|
||||
init_bucket_renderer<Merc2BucketRenderer>(
|
||||
fmt::format("merc-l{}-pris2", i), BucketCategory::MERC,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::MERC_L0_PRIS2, BucketId::MERC_L1_PRIS2, i), m_merc2);
|
||||
@@ -270,6 +281,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
|
||||
fmt::format("gmerc-l{}-pris2", i), BucketCategory::GENERIC,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC_L0_PRIS2, BucketId::GMERC_L1_PRIS2, i), m_generic2,
|
||||
Generic2::Mode::NORMAL);
|
||||
init_bucket_renderer<Generic2BucketRenderer>(
|
||||
fmt::format("gmerc2-l{}-pris2", i), BucketCategory::GENERIC,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_PRIS2, BucketId::GMERC2_L1_PRIS2, i),
|
||||
m_generic2, Generic2::Mode::PRIM);
|
||||
}
|
||||
|
||||
// 401
|
||||
@@ -281,6 +296,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
|
||||
BucketId::GMERC_LCOM_PRIS, m_generic2,
|
||||
Generic2::Mode::NORMAL);
|
||||
|
||||
init_bucket_renderer<Generic2BucketRenderer>("gmerc2-lcom-pris", BucketCategory::GENERIC,
|
||||
BucketId::GMERC2_LCOM_PRIS, m_generic2,
|
||||
Generic2::Mode::PRIM);
|
||||
|
||||
// 461
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-lcom-sky-post", BucketCategory::TEX,
|
||||
BucketId::TEX_LCOM_SKY_POST, m_texture_animator);
|
||||
@@ -306,6 +325,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
|
||||
fmt::format("tfrag-l{}-water", i), BucketCategory::TFRAG,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::TFRAG_L0_WATER, BucketId::TFRAG_L1_WATER, i),
|
||||
std::vector{tfrag3::TFragmentTreeKind::WATER}, false, i, anim_slot_array());
|
||||
init_bucket_renderer<Generic2BucketRenderer>(
|
||||
fmt::format("gmerc2-l{}-water", i), BucketCategory::GENERIC,
|
||||
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_WATER, BucketId::GMERC2_L1_WATER, i),
|
||||
m_generic2, Generic2::Mode::PRIM);
|
||||
}
|
||||
|
||||
// 563
|
||||
@@ -313,11 +336,20 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
|
||||
BucketId::TEX_LCOM_WATER, m_texture_animator);
|
||||
init_bucket_renderer<Merc2BucketRenderer>("merc-lcom-water", BucketCategory::MERC,
|
||||
BucketId::MERC_LCOM_WATER, m_merc2);
|
||||
init_bucket_renderer<Generic2BucketRenderer>("generic2-lcom-water", BucketCategory::GENERIC,
|
||||
BucketId::GMERC2_LCOM_WATER, m_generic2,
|
||||
Generic2::Mode::PRIM);
|
||||
|
||||
// 568
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-sprite", BucketCategory::TEX,
|
||||
BucketId::TEX_SPRITE, m_texture_animator);
|
||||
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-1", BucketCategory::GENERIC,
|
||||
BucketId::GENERIC_SPRITE_1, m_generic2,
|
||||
Generic2::Mode::PRIM);
|
||||
init_bucket_renderer<Sprite3>("particles", BucketCategory::SPRITE, BucketId::PARTICLES);
|
||||
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-2", BucketCategory::GENERIC,
|
||||
BucketId::GENERIC_SPRITE_2, m_generic2,
|
||||
Generic2::Mode::PRIM);
|
||||
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-3", BucketCategory::OTHER,
|
||||
BucketId::GENERIC_SPRITE_3, m_generic2,
|
||||
Generic2::Mode::LIGHTNING);
|
||||
@@ -1078,8 +1110,13 @@ void OpenGLRenderer::draw_renderer_selection_window() {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
ImGui::InputText("Renderer Filter", &m_renderer_filter);
|
||||
|
||||
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
|
||||
auto renderer = m_bucket_renderers[i].get();
|
||||
if (!m_renderer_filter.empty() && !str_util::contains(renderer->name(), m_renderer_filter)) {
|
||||
continue;
|
||||
}
|
||||
if (renderer && !renderer->empty()) {
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::TreeNode(renderer->name_and_id().c_str())) {
|
||||
|
||||
@@ -123,6 +123,7 @@ class OpenGLRenderer {
|
||||
|
||||
float m_last_pmode_alp = 1.;
|
||||
bool m_enable_fast_blackout_loads = true;
|
||||
std::string m_renderer_filter = "";
|
||||
|
||||
struct FboState {
|
||||
struct {
|
||||
|
||||
@@ -60,23 +60,48 @@
|
||||
* A simple list of preallocated textures by size. If a texture needs to be resized, it's faster
|
||||
* to swap to a different OpenGL texture from this pool than glTexImage2D with a different size.
|
||||
*/
|
||||
OpenGLTexturePool::OpenGLTexturePool() {
|
||||
OpenGLTexturePool::OpenGLTexturePool(GameVersion version) {
|
||||
struct Alloc {
|
||||
u64 w, h, n;
|
||||
};
|
||||
// list of sizes to preallocate: {width, height, count}.
|
||||
for (const auto& a : std::vector<Alloc>{{4, 4, 2},
|
||||
{4, 64, 2},
|
||||
{16, 16, 5},
|
||||
{32, 16, 1},
|
||||
{32, 32, 10},
|
||||
{32, 64, 1},
|
||||
{64, 32, 6},
|
||||
{64, 64, 30},
|
||||
{64, 128, 4},
|
||||
{128, 128, 10},
|
||||
{256, 1, 2},
|
||||
{256, 256, 7}}) {
|
||||
PerGameVersion<std::vector<Alloc>> tex_allocs{{{4, 4, 2},
|
||||
{4, 64, 2},
|
||||
{16, 16, 5},
|
||||
{32, 16, 1},
|
||||
{32, 32, 10},
|
||||
{32, 64, 1},
|
||||
{64, 32, 6},
|
||||
{64, 64, 30},
|
||||
{64, 128, 4},
|
||||
{128, 128, 10},
|
||||
{256, 1, 2},
|
||||
{256, 256, 7}},
|
||||
{{4, 4, 2},
|
||||
{4, 64, 2},
|
||||
{16, 16, 5},
|
||||
{32, 16, 1},
|
||||
{32, 32, 10},
|
||||
{32, 64, 1},
|
||||
{64, 32, 6},
|
||||
{64, 64, 30},
|
||||
{64, 128, 4},
|
||||
{128, 128, 10},
|
||||
{256, 1, 2},
|
||||
{256, 256, 7}},
|
||||
{{4, 4, 3},
|
||||
{4, 64, 6},
|
||||
{16, 16, 5},
|
||||
{32, 16, 1},
|
||||
{32, 32, 20},
|
||||
{32, 64, 1},
|
||||
{64, 32, 15},
|
||||
{64, 64, 85},
|
||||
{64, 128, 4},
|
||||
{128, 128, 185},
|
||||
{256, 1, 2},
|
||||
{256, 256, 7}}};
|
||||
for (const auto& a : tex_allocs[version]) {
|
||||
auto& l = textures[(a.w << 32) | a.h];
|
||||
l.resize(a.n);
|
||||
glGenTextures(a.n, l.data());
|
||||
@@ -370,6 +395,7 @@ TextureAnimator::TextureAnimator(ShaderLibrary& shaders,
|
||||
const tfrag3::Level* common_level,
|
||||
GameVersion version)
|
||||
: m_common_level(common_level),
|
||||
m_opengl_texture_pool(version),
|
||||
m_psm32_to_psm8_8_8(8, 8, 8, 64),
|
||||
m_psm32_to_psm8_16_16(16, 16, 16, 64),
|
||||
m_psm32_to_psm8_32_32(32, 32, 16, 64),
|
||||
@@ -420,6 +446,7 @@ TextureAnimator::TextureAnimator(ShaderLibrary& shaders,
|
||||
m_shader_id = shader.id();
|
||||
m_uniforms.rgba = glGetUniformLocation(shader.id(), "rgba");
|
||||
m_uniforms.enable_tex = glGetUniformLocation(shader.id(), "enable_tex");
|
||||
m_uniforms.set_alpha = glGetUniformLocation(shader.id(), "set_alpha");
|
||||
m_uniforms.positions = glGetUniformLocation(shader.id(), "positions");
|
||||
m_uniforms.uvs = glGetUniformLocation(shader.id(), "uvs");
|
||||
m_uniforms.channel_scramble = glGetUniformLocation(shader.id(), "channel_scramble");
|
||||
@@ -642,7 +669,7 @@ GLuint TextureAnimator::get_by_slot(int idx) {
|
||||
}
|
||||
|
||||
// IDs sent from GOAL telling us what texture operation to perform.
|
||||
enum PcTextureAnimCodes {
|
||||
enum class PcTextureAnimCodesJak2 : u16 {
|
||||
FINISH_ARRAY = 13,
|
||||
ERASE_DEST_TEXTURE = 14,
|
||||
UPLOAD_CLUT_16_16 = 15,
|
||||
@@ -673,6 +700,361 @@ enum PcTextureAnimCodes {
|
||||
CLOUDS_HIRES = 43,
|
||||
};
|
||||
|
||||
struct FixedAnimInfoJak2 {
|
||||
PcTextureAnimCodesJak2 code = (PcTextureAnimCodesJak2)0;
|
||||
std::string name;
|
||||
int anim_array_idx = -1;
|
||||
};
|
||||
|
||||
FixedAnimInfoJak2 anim_code_to_info(PcTextureAnimCodesJak2 code, const TextureAnimator& animator) {
|
||||
ASSERT(code > (PcTextureAnimCodesJak2)0);
|
||||
FixedAnimInfoJak2 anim;
|
||||
anim.code = code;
|
||||
switch (code) {
|
||||
case PcTextureAnimCodesJak2::SKULL_GEM: {
|
||||
anim.name = "skull-gem";
|
||||
anim.anim_array_idx = animator.m_skull_gem_fixed_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::BOMB: {
|
||||
anim.name = "bomb";
|
||||
anim.anim_array_idx = animator.m_bomb_fixed_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::CAS_CONVEYOR: {
|
||||
anim.name = "cas-conveyor";
|
||||
anim.anim_array_idx = animator.m_cas_conveyor_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::SECURITY: {
|
||||
anim.name = "security";
|
||||
anim.anim_array_idx = animator.m_security_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::WATERFALL: {
|
||||
anim.name = "waterfall";
|
||||
anim.anim_array_idx = animator.m_waterfall_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::WATERFALL_B: {
|
||||
anim.name = "waterfall-b";
|
||||
anim.anim_array_idx = animator.m_waterfall_b_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::LAVA: {
|
||||
anim.name = "lava";
|
||||
anim.anim_array_idx = animator.m_lava_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::LAVA_B: {
|
||||
anim.name = "lava-b";
|
||||
anim.anim_array_idx = animator.m_lava_b_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::STADIUMB: {
|
||||
anim.name = "stadiumb";
|
||||
anim.anim_array_idx = animator.m_stadiumb_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::FORTRESS_PRIS: {
|
||||
anim.name = "fort-pris";
|
||||
anim.anim_array_idx = animator.m_fortress_pris_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::FORTRESS_WARP: {
|
||||
anim.name = "fort-warp";
|
||||
anim.anim_array_idx = animator.m_fortress_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::METKOR: {
|
||||
anim.name = "metkor";
|
||||
anim.anim_array_idx = animator.m_metkor_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::SHIELD: {
|
||||
anim.name = "shield";
|
||||
anim.anim_array_idx = animator.m_shield_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::KREW_HOLO: {
|
||||
anim.name = "krew-holo";
|
||||
anim.anim_array_idx = animator.m_krew_holo_anim_array_idx;
|
||||
} break;
|
||||
default:
|
||||
anim.name = "unknown";
|
||||
lg::error("Unknown texture anim code {}", (int)code);
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
enum class PcTextureAnimCodesJak3 : u16 {
|
||||
FINISH_ARRAY = 13,
|
||||
ERASE_DEST_TEXTURE = 14,
|
||||
UPLOAD_CLUT_16_16 = 15,
|
||||
GENERIC_UPLOAD = 16,
|
||||
SET_SHADER = 17,
|
||||
DRAW = 18,
|
||||
DARKJAK = 22,
|
||||
DARKJAK_HIGHRES = 23,
|
||||
SKULL_GEM = 27,
|
||||
DEFAULT_WATER = 28,
|
||||
DEFAULT_WARP = 29,
|
||||
TEMPLEA_WATER = 30,
|
||||
TEMPLEA_WARP = 31,
|
||||
TEMPLEB_WARP = 32,
|
||||
TEMPLEC_WATER = 33,
|
||||
SEWC_WATER = 34,
|
||||
SEWD_WATER = 35,
|
||||
SEWE_WATER = 36,
|
||||
SEWG_WATER = 37,
|
||||
SEWH_WATER = 38,
|
||||
SEWI_WATER = 39,
|
||||
SEWJ_WATER = 40,
|
||||
SEWL_WATER = 41,
|
||||
SEWM_WATER = 42,
|
||||
SEWN_WATER = 43,
|
||||
DESRESC_WARP = 44,
|
||||
CTYSLUMB_WATER = 45,
|
||||
NSTB_QUICKSAND = 46,
|
||||
CTYSLUMC_WATER = 47,
|
||||
FACTORYC_ALPHA = 48,
|
||||
HFRAG = 49,
|
||||
HANGA_SPRITE = 50,
|
||||
HANGA_WATER = 51,
|
||||
DESERTD_WATER = 52,
|
||||
LMHCITYB_TFRAG = 53,
|
||||
TOWERB_WATER = 54,
|
||||
COMB_FIELD = 55,
|
||||
WASSTADA_ALPHA = 56,
|
||||
FACTORYB_WATER = 57,
|
||||
LMHCITYA_TFRAG = 58,
|
||||
MHCITYA_PRIS = 59,
|
||||
RUBBLEA_WATER = 60,
|
||||
RUBBLEA2_WATER = 61,
|
||||
RUBBLEB_WATER = 62,
|
||||
RUBBLEC_WATER = 63,
|
||||
FORESTA_WATER = 64,
|
||||
FORESTB_WATER = 65,
|
||||
LFORPLNT_PRIS = 66,
|
||||
LTNFXHIP = 67,
|
||||
LGUNNORM_WATER = 68,
|
||||
LJKDXVIN = 69,
|
||||
SECURITY = 70,
|
||||
WASPAL_WATER = 71,
|
||||
MINED_TFRAG = 72,
|
||||
VOLCANOX_WARP = 73,
|
||||
TEMPLEX_WATER = 74,
|
||||
VOLCANOA_WATER = 75,
|
||||
DESHOVER = 76,
|
||||
CLOUDS_AND_FOG = 77,
|
||||
CLOUDS_HIRES = 78,
|
||||
};
|
||||
|
||||
struct FixedAnimInfoJak3 {
|
||||
PcTextureAnimCodesJak3 code = (PcTextureAnimCodesJak3)0;
|
||||
std::string name;
|
||||
int anim_array_idx = -1;
|
||||
};
|
||||
|
||||
FixedAnimInfoJak3 anim_code_to_info(PcTextureAnimCodesJak3 code, const TextureAnimator& animator) {
|
||||
ASSERT(code > (PcTextureAnimCodesJak3)0);
|
||||
FixedAnimInfoJak3 anim;
|
||||
anim.code = code;
|
||||
switch (code) {
|
||||
case PcTextureAnimCodesJak3::SKULL_GEM: {
|
||||
anim.name = "skull-gem";
|
||||
anim.anim_array_idx = animator.m_skull_gem_fixed_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DEFAULT_WATER: {
|
||||
anim.name = "default-water";
|
||||
anim.anim_array_idx = animator.m_default_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DEFAULT_WARP: {
|
||||
anim.name = "default-warp";
|
||||
anim.anim_array_idx = animator.m_default_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TEMPLEA_WATER: {
|
||||
anim.name = "templea-water";
|
||||
anim.anim_array_idx = animator.m_templea_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TEMPLEA_WARP: {
|
||||
anim.name = "templea-warp";
|
||||
anim.anim_array_idx = animator.m_templea_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TEMPLEB_WARP: {
|
||||
anim.name = "templeb-warp";
|
||||
anim.anim_array_idx = animator.m_templeb_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TEMPLEC_WATER: {
|
||||
anim.name = "templec-water";
|
||||
anim.anim_array_idx = animator.m_templec_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWC_WATER: {
|
||||
anim.name = "sewc-water";
|
||||
anim.anim_array_idx = animator.m_sewc_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWD_WATER: {
|
||||
anim.name = "sewd-water";
|
||||
anim.anim_array_idx = animator.m_sewd_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWE_WATER: {
|
||||
anim.name = "sewe-water";
|
||||
anim.anim_array_idx = animator.m_sewe_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWG_WATER: {
|
||||
anim.name = "sewg-water";
|
||||
anim.anim_array_idx = animator.m_sewg_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWH_WATER: {
|
||||
anim.name = "sewh-water";
|
||||
anim.anim_array_idx = animator.m_sewh_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWI_WATER: {
|
||||
anim.name = "sewi-water";
|
||||
anim.anim_array_idx = animator.m_sewi_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWJ_WATER: {
|
||||
anim.name = "sewj-water";
|
||||
anim.anim_array_idx = animator.m_sewj_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWL_WATER: {
|
||||
anim.name = "sewl-water";
|
||||
anim.anim_array_idx = animator.m_sewl_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWM_WATER: {
|
||||
anim.name = "sewm-water";
|
||||
anim.anim_array_idx = animator.m_sewm_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SEWN_WATER: {
|
||||
anim.name = "sewn-water";
|
||||
anim.anim_array_idx = animator.m_sewn_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DESRESC_WARP: {
|
||||
anim.name = "desresc-warp";
|
||||
anim.anim_array_idx = animator.m_desresc_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::CTYSLUMB_WATER: {
|
||||
anim.name = "ctyslumb-water";
|
||||
anim.anim_array_idx = animator.m_ctyslumb_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::NSTB_QUICKSAND: {
|
||||
anim.name = "nstb-quicksand";
|
||||
anim.anim_array_idx = animator.m_nstb_quicksand_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::CTYSLUMC_WATER: {
|
||||
anim.name = "ctyslumc-water";
|
||||
anim.anim_array_idx = animator.m_ctyslumc_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::FACTORYC_ALPHA: {
|
||||
anim.name = "factoryc-alpha";
|
||||
anim.anim_array_idx = animator.m_factoryc_alpha_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::HFRAG: {
|
||||
anim.name = "hfrag";
|
||||
anim.anim_array_idx = animator.m_hfrag_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::HANGA_SPRITE: {
|
||||
anim.name = "hanga-sprite";
|
||||
anim.anim_array_idx = animator.m_hanga_sprite_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::HANGA_WATER: {
|
||||
anim.name = "hanga-water";
|
||||
anim.anim_array_idx = animator.m_hanga_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DESERTD_WATER: {
|
||||
anim.name = "desertd-water";
|
||||
anim.anim_array_idx = animator.m_desertd_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LMHCITYB_TFRAG: {
|
||||
anim.name = "lmhcityb-tfrag";
|
||||
anim.anim_array_idx = animator.m_lmhcityb_tfrag_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TOWERB_WATER: {
|
||||
anim.name = "towerb-water";
|
||||
anim.anim_array_idx = animator.m_towerb_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::COMB_FIELD: {
|
||||
anim.name = "comb-field";
|
||||
anim.anim_array_idx = animator.m_comb_field_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::WASSTADA_ALPHA: {
|
||||
anim.name = "wasstada-alpha";
|
||||
anim.anim_array_idx = animator.m_wasstada_alpha_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::FACTORYB_WATER: {
|
||||
anim.name = "factoryb-water";
|
||||
anim.anim_array_idx = animator.m_factoryb_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LMHCITYA_TFRAG: {
|
||||
anim.name = "lmhcitya-tfrag";
|
||||
anim.anim_array_idx = animator.m_lmhcitya_tfrag_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::MHCITYA_PRIS: {
|
||||
anim.name = "mhcitya-pris";
|
||||
anim.anim_array_idx = animator.m_mhcitya_pris_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::RUBBLEA_WATER: {
|
||||
anim.name = "rubblea-water";
|
||||
anim.anim_array_idx = animator.m_rubblea_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::RUBBLEA2_WATER: {
|
||||
anim.name = "rubblea2-water";
|
||||
anim.anim_array_idx = animator.m_rubblea2_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::RUBBLEB_WATER: {
|
||||
anim.name = "rubbleb-water";
|
||||
anim.anim_array_idx = animator.m_rubbleb_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::RUBBLEC_WATER: {
|
||||
anim.name = "rubblec-water";
|
||||
anim.anim_array_idx = animator.m_rubblec_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::FORESTA_WATER: {
|
||||
anim.name = "foresta-water";
|
||||
anim.anim_array_idx = animator.m_foresta_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::FORESTB_WATER: {
|
||||
anim.name = "forestb-water";
|
||||
anim.anim_array_idx = animator.m_forestb_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LFORPLNT_PRIS: {
|
||||
anim.name = "lforplnt-pris";
|
||||
anim.anim_array_idx = animator.m_lforplnt_pris_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LTNFXHIP: {
|
||||
anim.name = "ltnfxhip";
|
||||
anim.anim_array_idx = animator.m_ltnfxhip_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LGUNNORM_WATER: {
|
||||
anim.name = "lgunnorm-water";
|
||||
anim.anim_array_idx = animator.m_lgunnorm_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::LJKDXVIN: {
|
||||
anim.name = "ljkdxvin";
|
||||
anim.anim_array_idx = animator.m_ljkdxvin_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SECURITY: {
|
||||
anim.name = "security";
|
||||
anim.anim_array_idx = animator.m_security_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::WASPAL_WATER: {
|
||||
anim.name = "waspal-water";
|
||||
anim.anim_array_idx = animator.m_waspal_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::MINED_TFRAG: {
|
||||
anim.name = "mined-tfrag";
|
||||
anim.anim_array_idx = animator.m_mined_tfrag_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::VOLCANOX_WARP: {
|
||||
anim.name = "volcanox-warp";
|
||||
anim.anim_array_idx = animator.m_volcanox_warp_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::TEMPLEX_WATER: {
|
||||
anim.name = "templex-water";
|
||||
anim.anim_array_idx = animator.m_templex_water_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::VOLCANOA_WATER: {
|
||||
anim.name = "volcanoa-water";
|
||||
anim.anim_array_idx = animator.m_volcanoa_anim_array_idx;
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DESHOVER: {
|
||||
anim.name = "deshover";
|
||||
anim.anim_array_idx = animator.m_deshover_anim_array_idx;
|
||||
} break;
|
||||
default:
|
||||
anim.name = "unknown";
|
||||
lg::error("Unknown texture anim code {}", (int)code);
|
||||
}
|
||||
return anim;
|
||||
}
|
||||
|
||||
// metadata for an upload from GOAL memory
|
||||
struct TextureAnimPcUpload {
|
||||
u32 data; // goal pointer
|
||||
@@ -726,117 +1108,191 @@ void TextureAnimator::handle_texture_anim_data(DmaFollower& dma,
|
||||
auto tf = dma.read_and_advance();
|
||||
auto vif0 = tf.vifcode0();
|
||||
if (vif0.kind == VifCode::Kind::PC_PORT) {
|
||||
switch (vif0.immediate) {
|
||||
case UPLOAD_CLUT_16_16: {
|
||||
auto p = scoped_prof("clut-16-16");
|
||||
handle_upload_clut_16_16(tf, ee_mem);
|
||||
} break;
|
||||
case ERASE_DEST_TEXTURE: {
|
||||
auto p = scoped_prof("erase");
|
||||
handle_erase_dest(dma);
|
||||
} break;
|
||||
case GENERIC_UPLOAD: {
|
||||
auto p = scoped_prof("generic-upload");
|
||||
handle_generic_upload(tf, ee_mem);
|
||||
} break;
|
||||
case SET_SHADER: {
|
||||
auto p = scoped_prof("set-shader");
|
||||
handle_set_shader(dma);
|
||||
} break;
|
||||
case DRAW: {
|
||||
auto p = scoped_prof("draw");
|
||||
handle_draw(dma, *texture_pool);
|
||||
} break;
|
||||
case FINISH_ARRAY:
|
||||
done = true;
|
||||
switch (this->m_version) {
|
||||
case GameVersion::Jak2:
|
||||
switch (static_cast<PcTextureAnimCodesJak2>(vif0.immediate)) {
|
||||
case PcTextureAnimCodesJak2::UPLOAD_CLUT_16_16: {
|
||||
auto p = scoped_prof("clut-16-16");
|
||||
handle_upload_clut_16_16(tf, ee_mem);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::ERASE_DEST_TEXTURE: {
|
||||
auto p = scoped_prof("erase");
|
||||
handle_erase_dest(dma);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::GENERIC_UPLOAD: {
|
||||
auto p = scoped_prof("generic-upload");
|
||||
handle_generic_upload(tf, ee_mem);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::SET_SHADER: {
|
||||
auto p = scoped_prof("set-shader");
|
||||
handle_set_shader(dma);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::DRAW: {
|
||||
auto p = scoped_prof("draw");
|
||||
handle_draw(dma, *texture_pool);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::FINISH_ARRAY:
|
||||
done = true;
|
||||
break;
|
||||
case PcTextureAnimCodesJak2::DARKJAK: {
|
||||
auto p = scoped_prof("darkjak");
|
||||
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::PRISON_JAK: {
|
||||
auto p = scoped_prof("prisonjak");
|
||||
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::ORACLE_JAK: {
|
||||
auto p = scoped_prof("oraclejak");
|
||||
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::NEST_JAK: {
|
||||
auto p = scoped_prof("nestjak");
|
||||
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::KOR_TRANSFORM: {
|
||||
auto p = scoped_prof("kor");
|
||||
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::SKULL_GEM:
|
||||
case PcTextureAnimCodesJak2::BOMB:
|
||||
case PcTextureAnimCodesJak2::CAS_CONVEYOR:
|
||||
case PcTextureAnimCodesJak2::SECURITY:
|
||||
case PcTextureAnimCodesJak2::WATERFALL:
|
||||
case PcTextureAnimCodesJak2::WATERFALL_B:
|
||||
case PcTextureAnimCodesJak2::LAVA:
|
||||
case PcTextureAnimCodesJak2::LAVA_B:
|
||||
case PcTextureAnimCodesJak2::STADIUMB:
|
||||
case PcTextureAnimCodesJak2::FORTRESS_PRIS:
|
||||
case PcTextureAnimCodesJak2::FORTRESS_WARP:
|
||||
case PcTextureAnimCodesJak2::METKOR:
|
||||
case PcTextureAnimCodesJak2::SHIELD:
|
||||
case PcTextureAnimCodesJak2::KREW_HOLO: {
|
||||
auto anim =
|
||||
anim_code_to_info(static_cast<PcTextureAnimCodesJak2>(vif0.immediate), *this);
|
||||
auto p = scoped_prof(anim.name.c_str());
|
||||
run_fixed_animation_array(anim.anim_array_idx, tf, texture_pool);
|
||||
break;
|
||||
}
|
||||
case PcTextureAnimCodesJak2::CLOUDS_AND_FOG:
|
||||
case PcTextureAnimCodesJak2::CLOUDS_HIRES: {
|
||||
auto p = scoped_prof("clouds-and-fog");
|
||||
handle_clouds_and_fog(tf, texture_pool,
|
||||
vif0.immediate == (u16)PcTextureAnimCodesJak2::CLOUDS_HIRES);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak2::SLIME: {
|
||||
auto p = scoped_prof("slime");
|
||||
handle_slime(tf, texture_pool);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
lg::print("bad imm: {}\n", vif0.immediate);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
case GameVersion::Jak3:
|
||||
switch (static_cast<PcTextureAnimCodesJak3>(vif0.immediate)) {
|
||||
case PcTextureAnimCodesJak3::UPLOAD_CLUT_16_16: {
|
||||
auto p = scoped_prof("clut-16-16");
|
||||
handle_upload_clut_16_16(tf, ee_mem);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::ERASE_DEST_TEXTURE: {
|
||||
auto p = scoped_prof("erase");
|
||||
handle_erase_dest(dma);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::GENERIC_UPLOAD: {
|
||||
auto p = scoped_prof("generic-upload");
|
||||
handle_generic_upload(tf, ee_mem);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SET_SHADER: {
|
||||
auto p = scoped_prof("set-shader");
|
||||
handle_set_shader(dma);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DRAW: {
|
||||
auto p = scoped_prof("draw");
|
||||
handle_draw(dma, *texture_pool);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::FINISH_ARRAY:
|
||||
done = true;
|
||||
break;
|
||||
case PcTextureAnimCodesJak3::DARKJAK: {
|
||||
auto p = scoped_prof("darkjak");
|
||||
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::DARKJAK_HIGHRES: {
|
||||
auto p = scoped_prof("darkjak-highres");
|
||||
run_clut_blender_group(tf, m_darkjak_highres_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PcTextureAnimCodesJak3::SKULL_GEM:
|
||||
case PcTextureAnimCodesJak3::DEFAULT_WATER:
|
||||
case PcTextureAnimCodesJak3::DEFAULT_WARP:
|
||||
case PcTextureAnimCodesJak3::TEMPLEA_WATER:
|
||||
case PcTextureAnimCodesJak3::TEMPLEA_WARP:
|
||||
case PcTextureAnimCodesJak3::TEMPLEB_WARP:
|
||||
case PcTextureAnimCodesJak3::TEMPLEC_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWC_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWD_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWE_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWG_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWH_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWI_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWJ_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWL_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWM_WATER:
|
||||
case PcTextureAnimCodesJak3::SEWN_WATER:
|
||||
case PcTextureAnimCodesJak3::DESRESC_WARP:
|
||||
case PcTextureAnimCodesJak3::CTYSLUMB_WATER:
|
||||
case PcTextureAnimCodesJak3::NSTB_QUICKSAND:
|
||||
case PcTextureAnimCodesJak3::CTYSLUMC_WATER:
|
||||
case PcTextureAnimCodesJak3::FACTORYC_ALPHA:
|
||||
case PcTextureAnimCodesJak3::HFRAG:
|
||||
case PcTextureAnimCodesJak3::HANGA_SPRITE:
|
||||
case PcTextureAnimCodesJak3::HANGA_WATER:
|
||||
case PcTextureAnimCodesJak3::DESERTD_WATER:
|
||||
case PcTextureAnimCodesJak3::LMHCITYB_TFRAG:
|
||||
case PcTextureAnimCodesJak3::TOWERB_WATER:
|
||||
case PcTextureAnimCodesJak3::COMB_FIELD:
|
||||
case PcTextureAnimCodesJak3::WASSTADA_ALPHA:
|
||||
case PcTextureAnimCodesJak3::FACTORYB_WATER:
|
||||
case PcTextureAnimCodesJak3::LMHCITYA_TFRAG:
|
||||
case PcTextureAnimCodesJak3::MHCITYA_PRIS:
|
||||
case PcTextureAnimCodesJak3::RUBBLEA_WATER:
|
||||
case PcTextureAnimCodesJak3::RUBBLEA2_WATER:
|
||||
case PcTextureAnimCodesJak3::RUBBLEB_WATER:
|
||||
case PcTextureAnimCodesJak3::RUBBLEC_WATER:
|
||||
case PcTextureAnimCodesJak3::FORESTA_WATER:
|
||||
case PcTextureAnimCodesJak3::FORESTB_WATER:
|
||||
case PcTextureAnimCodesJak3::LFORPLNT_PRIS:
|
||||
case PcTextureAnimCodesJak3::LTNFXHIP:
|
||||
case PcTextureAnimCodesJak3::LGUNNORM_WATER:
|
||||
case PcTextureAnimCodesJak3::LJKDXVIN:
|
||||
case PcTextureAnimCodesJak3::SECURITY:
|
||||
case PcTextureAnimCodesJak3::WASPAL_WATER:
|
||||
case PcTextureAnimCodesJak3::MINED_TFRAG:
|
||||
case PcTextureAnimCodesJak3::VOLCANOX_WARP:
|
||||
case PcTextureAnimCodesJak3::TEMPLEX_WATER:
|
||||
case PcTextureAnimCodesJak3::VOLCANOA_WATER:
|
||||
case PcTextureAnimCodesJak3::DESHOVER: {
|
||||
auto anim =
|
||||
anim_code_to_info(static_cast<PcTextureAnimCodesJak3>(vif0.immediate), *this);
|
||||
auto p = scoped_prof(anim.name.c_str());
|
||||
run_fixed_animation_array(anim.anim_array_idx, tf, texture_pool);
|
||||
break;
|
||||
}
|
||||
case PcTextureAnimCodesJak3::CLOUDS_AND_FOG:
|
||||
case PcTextureAnimCodesJak3::CLOUDS_HIRES: {
|
||||
auto p = scoped_prof("clouds-and-fog");
|
||||
handle_clouds_and_fog(tf, texture_pool,
|
||||
vif0.immediate == (u16)PcTextureAnimCodesJak3::CLOUDS_HIRES);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
lg::print("bad imm: {}\n", vif0.immediate);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
break;
|
||||
case DARKJAK: {
|
||||
auto p = scoped_prof("darkjak");
|
||||
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case PRISON_JAK: {
|
||||
auto p = scoped_prof("prisonjak");
|
||||
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case ORACLE_JAK: {
|
||||
auto p = scoped_prof("oraclejak");
|
||||
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case NEST_JAK: {
|
||||
auto p = scoped_prof("nestjak");
|
||||
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case KOR_TRANSFORM: {
|
||||
auto p = scoped_prof("kor");
|
||||
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx, frame_idx);
|
||||
} break;
|
||||
case SKULL_GEM: {
|
||||
auto p = scoped_prof("skull-gem");
|
||||
run_fixed_animation_array(m_skull_gem_fixed_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case BOMB: {
|
||||
auto p = scoped_prof("bomb");
|
||||
run_fixed_animation_array(m_bomb_fixed_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case CAS_CONVEYOR: {
|
||||
auto p = scoped_prof("cas-conveyor");
|
||||
run_fixed_animation_array(m_cas_conveyor_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case SECURITY: {
|
||||
auto p = scoped_prof("security");
|
||||
run_fixed_animation_array(m_security_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case WATERFALL: {
|
||||
auto p = scoped_prof("waterfall");
|
||||
run_fixed_animation_array(m_waterfall_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case WATERFALL_B: {
|
||||
auto p = scoped_prof("waterfall-b");
|
||||
run_fixed_animation_array(m_waterfall_b_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case LAVA: {
|
||||
auto p = scoped_prof("lava");
|
||||
run_fixed_animation_array(m_lava_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case LAVA_B: {
|
||||
auto p = scoped_prof("lava-b");
|
||||
run_fixed_animation_array(m_lava_b_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case STADIUMB: {
|
||||
auto p = scoped_prof("stadiumb");
|
||||
run_fixed_animation_array(m_stadiumb_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case FORTRESS_PRIS: {
|
||||
auto p = scoped_prof("fort-pris");
|
||||
run_fixed_animation_array(m_fortress_pris_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case FORTRESS_WARP: {
|
||||
auto p = scoped_prof("fort-warp");
|
||||
run_fixed_animation_array(m_fortress_warp_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case METKOR: {
|
||||
auto p = scoped_prof("metkor");
|
||||
run_fixed_animation_array(m_metkor_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case SHIELD: {
|
||||
auto p = scoped_prof("shield");
|
||||
run_fixed_animation_array(m_shield_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case KREW_HOLO: {
|
||||
auto p = scoped_prof("krew-holo");
|
||||
run_fixed_animation_array(m_krew_holo_anim_array_idx, tf, texture_pool);
|
||||
} break;
|
||||
case CLOUDS_AND_FOG:
|
||||
case CLOUDS_HIRES: {
|
||||
auto p = scoped_prof("clouds-and-fog");
|
||||
handle_clouds_and_fog(tf, texture_pool, vif0.immediate == CLOUDS_HIRES);
|
||||
} break;
|
||||
case SLIME: {
|
||||
auto p = scoped_prof("slime");
|
||||
handle_slime(tf, texture_pool);
|
||||
} break;
|
||||
default:
|
||||
lg::print("bad imm: {}\n", vif0.immediate);
|
||||
lg::print("unsupported game version {}\n", (int)this->m_version);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
} else {
|
||||
@@ -1818,6 +2274,21 @@ void TextureAnimator::set_up_opengl_for_fixed(const FixedLayerDef& def,
|
||||
blend_c == GsAlpha::BlendMode::SOURCE && blend_d == GsAlpha::BlendMode::DEST) {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
} else if (blend_a == GsAlpha::BlendMode::SOURCE &&
|
||||
blend_b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
blend_c == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
blend_d == GsAlpha::BlendMode::ZERO_OR_FIXED && def.blend_fix == 128) {
|
||||
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
|
||||
} else if (blend_a == GsAlpha::BlendMode::SOURCE &&
|
||||
blend_b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
blend_c == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
blend_d == GsAlpha::BlendMode::DEST) {
|
||||
// 0, 2, 2, 1
|
||||
// (Cs - 0) * FIX / 128 + Cd
|
||||
// So source is fix / 128, and dest is 1
|
||||
float color = (float)def.blend_fix / 128.f;
|
||||
glBlendColor(color, color, color, color);
|
||||
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE, GL_ONE, GL_ZERO);
|
||||
} else {
|
||||
lg::print("unhandled blend: {} {} {} {}\n", (int)blend_a, (int)blend_b, (int)blend_c,
|
||||
(int)blend_d);
|
||||
@@ -1958,14 +2429,23 @@ void TextureAnimator::set_draw_data_from_interpolated(DrawData* result,
|
||||
const LayerVals& vals,
|
||||
int w,
|
||||
int h) {
|
||||
ASSERT(vals.rot == 0);
|
||||
result->color = (vals.color * 128.f).cast<u32>();
|
||||
math::Vector2f pos_scale(vals.scale.x() * w, vals.scale.y() * h);
|
||||
math::Vector2f pos_offset(2048.f + (vals.offset.x() * w), 2048.f + (vals.offset.y() * h));
|
||||
math::Vector2f st_scale = vals.st_scale;
|
||||
math::Vector2f st_offset = vals.st_offset;
|
||||
const math::Vector2f corners[4] = {math::Vector2f{-0.5, -0.5}, math::Vector2f{0.5, -0.5},
|
||||
math::Vector2f{-0.5, 0.5}, math::Vector2f{0.5, 0.5}};
|
||||
math::Vector2f corners[4] = {math::Vector2f{-0.5, -0.5}, math::Vector2f{0.5, -0.5},
|
||||
math::Vector2f{-0.5, 0.5}, math::Vector2f{0.5, 0.5}};
|
||||
if (vals.rot) {
|
||||
const float rotation_radians = 2.f * M_PI * vals.rot / 65536.f;
|
||||
const float sine = std::sin(rotation_radians);
|
||||
const float cosine = std::cos(rotation_radians);
|
||||
math::Vector2f vx(sine, cosine);
|
||||
math::Vector2f vy(cosine, -sine);
|
||||
for (auto& corner : corners) {
|
||||
corner = vx * corner.x() + vy * corner.y();
|
||||
}
|
||||
}
|
||||
math::Vector2f sts[4];
|
||||
math::Vector2<u32> poss[4];
|
||||
|
||||
@@ -2056,8 +2536,14 @@ void TextureAnimator::run_fixed_animation(FixedAnim& anim, float time) {
|
||||
if (true) { // todo
|
||||
glColorMask(true, true, true, false);
|
||||
glUniform1f(m_uniforms.alpha_multiply, 2.f);
|
||||
glUniform1i(m_uniforms.set_alpha, 0);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glColorMask(false, false, false, true);
|
||||
if (anim.def.set_alpha) {
|
||||
glUniform1i(m_uniforms.set_alpha, 1);
|
||||
glUniform4f(m_uniforms.rgba, draw_data.color.x(), draw_data.color.x(),
|
||||
draw_data.color.x(), 128.f);
|
||||
}
|
||||
glUniform1f(m_uniforms.alpha_multiply, 1.f);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,7 @@ struct ShaderContext {
|
||||
};
|
||||
|
||||
struct OpenGLTexturePool {
|
||||
OpenGLTexturePool();
|
||||
OpenGLTexturePool(GameVersion version);
|
||||
~OpenGLTexturePool();
|
||||
GLuint allocate(u64 w, u64 h);
|
||||
void free(GLuint texture, u64 w, u64 h);
|
||||
@@ -148,6 +148,18 @@ struct FixedLayerDef {
|
||||
GsAlpha::BlendMode blend_modes[4]; // abcd
|
||||
u8 blend_fix = 0;
|
||||
|
||||
void set_blend(GsAlpha::BlendMode a,
|
||||
GsAlpha::BlendMode b,
|
||||
GsAlpha::BlendMode c,
|
||||
GsAlpha::BlendMode d,
|
||||
u8 fix) {
|
||||
blend_modes[0] = a;
|
||||
blend_modes[1] = b;
|
||||
blend_modes[2] = c;
|
||||
blend_modes[3] = d;
|
||||
blend_fix = fix;
|
||||
}
|
||||
|
||||
void set_blend_b2_d1() {
|
||||
blend_modes[0] = GsAlpha::BlendMode::SOURCE;
|
||||
blend_modes[1] = GsAlpha::BlendMode::ZERO_OR_FIXED;
|
||||
@@ -181,6 +193,15 @@ struct FixedAnimDef {
|
||||
// alpha blend off, so alpha doesn't matter i think.
|
||||
std::vector<FixedLayerDef> layers;
|
||||
bool move_to_pool = false;
|
||||
bool set_alpha = false;
|
||||
void set_times(std::vector<std::pair<float, float>> times) {
|
||||
ASSERT(layers.size() >= times.size());
|
||||
for (size_t i = 0; i < layers.size(); i++) {
|
||||
auto& layer = layers.at(i);
|
||||
layer.start_time = times.at(i).first;
|
||||
layer.end_time = times.at(i).second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct DynamicLayerData {
|
||||
@@ -343,6 +364,7 @@ class TextureAnimator {
|
||||
GLuint tcc;
|
||||
GLuint alpha_multiply;
|
||||
GLuint minimum, maximum;
|
||||
GLuint set_alpha;
|
||||
} m_uniforms;
|
||||
|
||||
struct {
|
||||
@@ -396,6 +418,8 @@ class TextureAnimator {
|
||||
m_psm32_to_psm8_64_64;
|
||||
ClutReader m_clut_table;
|
||||
|
||||
public:
|
||||
// jak 2
|
||||
int m_skull_gem_fixed_anim_array_idx = -1;
|
||||
int m_bomb_fixed_anim_array_idx = -1;
|
||||
int m_cas_conveyor_anim_array_idx = -1;
|
||||
@@ -411,9 +435,59 @@ class TextureAnimator {
|
||||
int m_shield_anim_array_idx = -1;
|
||||
int m_krew_holo_anim_array_idx = -1;
|
||||
|
||||
// jak 3
|
||||
int m_default_water_anim_array_idx = -1;
|
||||
int m_default_warp_anim_array_idx = -1;
|
||||
int m_templea_water_anim_array_idx = -1;
|
||||
int m_templea_warp_anim_array_idx = -1;
|
||||
int m_templeb_warp_anim_array_idx = -1;
|
||||
int m_templec_water_anim_array_idx = -1;
|
||||
int m_sewc_water_anim_array_idx = -1;
|
||||
int m_sewd_water_anim_array_idx = -1;
|
||||
int m_sewe_water_anim_array_idx = -1;
|
||||
int m_sewg_water_anim_array_idx = -1;
|
||||
int m_sewh_water_anim_array_idx = -1;
|
||||
int m_sewi_water_anim_array_idx = -1;
|
||||
int m_sewj_water_anim_array_idx = -1;
|
||||
int m_sewl_water_anim_array_idx = -1;
|
||||
int m_sewm_water_anim_array_idx = -1;
|
||||
int m_sewn_water_anim_array_idx = -1;
|
||||
int m_desresc_warp_anim_array_idx = -1;
|
||||
int m_ctyslumb_water_anim_array_idx = -1;
|
||||
int m_nstb_quicksand_anim_array_idx = -1;
|
||||
int m_ctyslumc_water_anim_array_idx = -1;
|
||||
int m_factoryc_alpha_anim_array_idx = -1;
|
||||
int m_hfrag_anim_array_idx = -1;
|
||||
int m_hanga_sprite_anim_array_idx = -1;
|
||||
int m_hanga_water_anim_array_idx = -1;
|
||||
int m_desertd_water_anim_array_idx = -1;
|
||||
int m_lmhcityb_tfrag_anim_array_idx = -1;
|
||||
int m_towerb_water_anim_array_idx = -1;
|
||||
int m_comb_field_anim_array_idx = -1;
|
||||
int m_wasstada_alpha_anim_array_idx = -1;
|
||||
int m_factoryb_water_anim_array_idx = -1;
|
||||
int m_lmhcitya_tfrag_anim_array_idx = -1;
|
||||
int m_mhcitya_pris_anim_array_idx = -1;
|
||||
int m_rubblea_water_anim_array_idx = -1;
|
||||
int m_rubblea2_water_anim_array_idx = -1;
|
||||
int m_rubbleb_water_anim_array_idx = -1;
|
||||
int m_rubblec_water_anim_array_idx = -1;
|
||||
int m_foresta_water_anim_array_idx = -1;
|
||||
int m_forestb_water_anim_array_idx = -1;
|
||||
int m_lforplnt_pris_anim_array_idx = -1;
|
||||
int m_ltnfxhip_anim_array_idx = -1;
|
||||
int m_lgunnorm_water_anim_array_idx = -1;
|
||||
int m_ljkdxvin_anim_array_idx = -1;
|
||||
int m_waspal_water_anim_array_idx = -1;
|
||||
int m_mined_tfrag_anim_array_idx = -1;
|
||||
int m_volcanox_warp_anim_array_idx = -1;
|
||||
int m_templex_water_anim_array_idx = -1;
|
||||
int m_volcanoa_anim_array_idx = -1;
|
||||
int m_deshover_anim_array_idx = -1;
|
||||
int m_darkjak_highres_clut_blender_idx = -1;
|
||||
|
||||
std::vector<FixedAnimArray> m_fixed_anim_arrays;
|
||||
|
||||
public:
|
||||
// note: for now these can't be easily changed because each layer has its own hand-tuned
|
||||
// parameters from the original game. If you want to change it, you'll need to make up parameters
|
||||
// for those new layers.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -119,3 +119,7 @@ void TextureUploadHandler::draw_debug_window() {
|
||||
m_direct->draw_debug_window();
|
||||
}
|
||||
}
|
||||
|
||||
bool TextureUploadHandler::empty() const {
|
||||
return m_upload_count == 0;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ class TextureUploadHandler : public BucketRenderer {
|
||||
bool add_direct = false);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
bool empty() const override;
|
||||
|
||||
private:
|
||||
struct TextureUpload {
|
||||
|
||||
@@ -129,8 +129,8 @@ Hfrag::HfragLevel* Hfrag::get_hfrag_level(const std::string& name,
|
||||
// first, see if this level is loaded. If not, there's nothing we can do.
|
||||
auto lev_data = render_state->loader->get_tfrag3_level(name);
|
||||
if (!lev_data) {
|
||||
printf("[hfrag] can't display %s because it's not loaded.\n", name.c_str());
|
||||
render_state->loader->debug_print_loaded_levels();
|
||||
// printf("[hfrag] can't display %s because it's not loaded.\n", name.c_str());
|
||||
// render_state->loader->debug_print_loaded_levels();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
#include "debug_gui.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/global_profiler/GlobalProfiler.h"
|
||||
#include "common/util/string_util.h"
|
||||
|
||||
#include "game/graphics/display.h"
|
||||
#include "game/graphics/gfx.h"
|
||||
@@ -164,10 +162,27 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Event Profiler")) {
|
||||
if (ImGui::Checkbox("Record", &record_events)) {
|
||||
if (ImGui::Checkbox("Record Events", &record_events)) {
|
||||
prof().set_enable(record_events);
|
||||
}
|
||||
ImGui::MenuItem("Dump to file", nullptr, &dump_events);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(fmt::format("({}/{})", prof().get_next_idx(), prof().get_max_events()).c_str());
|
||||
ImGui::InputInt("Event Buffer Size", &max_event_buffer_size);
|
||||
if (ImGui::Button("Resize")) {
|
||||
prof().update_event_buffer_size(max_event_buffer_size);
|
||||
}
|
||||
if (ImGui::Button("Reset Events")) {
|
||||
prof().clear();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Enable Compression", &prof().m_enable_compression);
|
||||
if (ImGui::Button("Dump to File")) {
|
||||
record_events = false;
|
||||
prof().dump_to_json();
|
||||
}
|
||||
// if (ImGui::Button("Open dump folder")) {
|
||||
// // TODO - https://github.com/mlabbe/nativefiledialog
|
||||
// }
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class OpenGlDebugGui {
|
||||
|
||||
bool small_profiler = false;
|
||||
bool record_events = false;
|
||||
bool dump_events = false;
|
||||
int max_event_buffer_size = 65536;
|
||||
bool want_reboot_in_debug = false;
|
||||
|
||||
bool screenshot_hotkey_enabled = true;
|
||||
|
||||
@@ -70,11 +70,16 @@ void Generic2::render_in_mode(DmaFollower& dma,
|
||||
case Mode::LIGHTNING:
|
||||
process_dma_lightning(dma, render_state->next_bucket);
|
||||
break;
|
||||
case Mode::PRIM:
|
||||
process_dma_prim(dma, render_state->next_bucket);
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
m_empty = m_next_free_vert == 0;
|
||||
|
||||
{
|
||||
// the next pass is to look at all of that data, and figure out the best order to draw it
|
||||
// using OpenGL
|
||||
@@ -84,6 +89,7 @@ void Generic2::render_in_mode(DmaFollower& dma,
|
||||
setup_draws(true, true);
|
||||
break;
|
||||
case Mode::LIGHTNING:
|
||||
case Mode::PRIM:
|
||||
setup_draws(false, true);
|
||||
break;
|
||||
case Mode::WARP:
|
||||
|
||||
@@ -11,7 +11,7 @@ class Generic2 {
|
||||
u32 num_buckets = 800);
|
||||
~Generic2();
|
||||
|
||||
enum class Mode { NORMAL, LIGHTNING, WARP };
|
||||
enum class Mode { NORMAL, LIGHTNING, WARP, PRIM };
|
||||
|
||||
void render_in_mode(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
@@ -19,6 +19,7 @@ class Generic2 {
|
||||
Mode mode);
|
||||
|
||||
void draw_debug_window();
|
||||
bool empty() { return m_empty; }
|
||||
|
||||
struct Vertex {
|
||||
math::Vector<float, 3> xyz;
|
||||
@@ -42,6 +43,7 @@ class Generic2 {
|
||||
void process_dma_jak1(DmaFollower& dma, u32 next_bucket);
|
||||
void process_dma_lightning(DmaFollower& dma, u32 next_bucket);
|
||||
void process_dma_jak2(DmaFollower& dma, u32 next_bucket);
|
||||
void process_dma_prim(DmaFollower& dma, u32 next_bucket);
|
||||
void setup_draws(bool enable_at, bool default_fog);
|
||||
void do_draws(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void do_draws_for_alpha(SharedRenderState* render_state,
|
||||
@@ -84,6 +86,8 @@ class Generic2 {
|
||||
float hud_mat_23, hud_mat_32, hud_mat_33;
|
||||
|
||||
bool uses_hud = false;
|
||||
bool uses_full_matrix = false;
|
||||
math::Vector4f full_matrix[4];
|
||||
} m_drawing_config;
|
||||
|
||||
struct GsState {
|
||||
@@ -198,8 +202,10 @@ class Generic2 {
|
||||
GLuint vertex_buffer;
|
||||
GLuint index_buffer;
|
||||
GLuint alpha_reject, color_mult, fog_color, scale, mat_23, mat_32, mat_33, fog_consts,
|
||||
hvdf_offset;
|
||||
hvdf_offset, use_full_matrix, full_matrix;
|
||||
GLuint gfx_hack_no_tex;
|
||||
GLuint warp_sample_mode;
|
||||
} m_ogl;
|
||||
|
||||
bool m_empty = false;
|
||||
};
|
||||
@@ -22,4 +22,9 @@ void Generic2BucketRenderer::render(DmaFollower& dma,
|
||||
return;
|
||||
}
|
||||
m_generic->render_in_mode(dma, render_state, prof, m_mode);
|
||||
m_empty = m_generic->empty();
|
||||
}
|
||||
|
||||
bool Generic2BucketRenderer::empty() const {
|
||||
return m_empty;
|
||||
}
|
||||
@@ -11,8 +11,10 @@ class Generic2BucketRenderer : public BucketRenderer {
|
||||
Generic2::Mode mode);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
bool empty() const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Generic2> m_generic;
|
||||
Generic2::Mode m_mode;
|
||||
bool m_empty = false;
|
||||
};
|
||||
@@ -190,6 +190,16 @@ void Generic2::determine_draw_modes(bool enable_at, bool default_fog) {
|
||||
current_mode.set_alpha_fail(reg.afail());
|
||||
current_mode.set_zt(reg.zte());
|
||||
current_mode.set_depth_test(reg.ztest());
|
||||
|
||||
// detect a strange way of disabling z writes by light-trail.
|
||||
// we don't actually handle alpha_fail later on in Direct - it doesn't map well to modern
|
||||
// graphics and would require a draw call per primitive.
|
||||
if (current_mode.get_alpha_fail() == GsTest::AlphaFail::FB_ONLY &&
|
||||
current_mode.get_aref() == 0x80 &&
|
||||
current_mode.get_alpha_test() == DrawMode::AlphaTest::GEQUAL) {
|
||||
current_mode.set_alpha_test(DrawMode::AlphaTest::ALWAYS);
|
||||
current_mode.disable_depth_write();
|
||||
}
|
||||
}
|
||||
|
||||
m_adgifs[i].mode = current_mode;
|
||||
@@ -271,6 +281,10 @@ void Generic2::process_matrices() {
|
||||
bool found_proj_matrix = false;
|
||||
std::array<math::Vector4f, 4> projection_matrix, hud_matrix;
|
||||
for (u32 i = 0; i < m_next_free_frag; i++) {
|
||||
if (m_drawing_config.uses_full_matrix) {
|
||||
memcpy(&m_drawing_config.full_matrix, m_fragments[i].header, 64);
|
||||
break;
|
||||
}
|
||||
float mat_33;
|
||||
memcpy(&mat_33, m_fragments[i].header + 15 * sizeof(float), sizeof(float));
|
||||
if (mat_33 == 0) {
|
||||
|
||||
@@ -550,6 +550,83 @@ void unpack_vertex(Generic2::Vertex* out, const u8* in, int count) {
|
||||
}
|
||||
}
|
||||
|
||||
void Generic2::process_dma_prim(DmaFollower& dma, u32 next_bucket) {
|
||||
reset_buffers();
|
||||
auto first_data = dma.read_and_advance();
|
||||
|
||||
// handle the stuff at the beginning.
|
||||
// if the engine didn't run the generic renderer setup function, this bucket will end here.
|
||||
if (is_nop_zero(first_data) && next_bucket == dma.current_tag_offset()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// MARK NOP (for profiling)
|
||||
auto v0k = first_data.vifcode0().kind;
|
||||
ASSERT((v0k == VifCode::Kind::MARK || v0k == VifCode::Kind::NOP) &&
|
||||
first_data.vifcode1().kind == VifCode::Kind::NOP);
|
||||
|
||||
// NOP DIRECT (set up GS, from generic setup)
|
||||
auto direct_setup = dma.read_and_advance();
|
||||
ASSERT(direct_setup.size_bytes == 32 && direct_setup.vifcode0().kind == VifCode::Kind::NOP &&
|
||||
direct_setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
m_drawing_config.zmsk = false;
|
||||
m_drawing_config.uses_full_matrix = true;
|
||||
|
||||
// STYCYCL to set up generic VU1 constants
|
||||
auto constants = dma.read_and_advance();
|
||||
ASSERT(constants.size_bytes == 128);
|
||||
ASSERT(constants.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(constants.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
memcpy(&m_drawing_config.pfog0, constants.data + 0, 4);
|
||||
memcpy(&m_drawing_config.fog_min, constants.data + 4, 4);
|
||||
memcpy(&m_drawing_config.fog_max, constants.data + 8, 4);
|
||||
memcpy(m_drawing_config.hvdf_offset.data(), constants.data + 32, 16);
|
||||
|
||||
// 32: MSCALF 0x0 STMOD 0b0 init generic VU1
|
||||
auto mscalf = dma.read_and_advance();
|
||||
ASSERT(mscalf.vifcode0().kind == VifCode::Kind::MSCALF &&
|
||||
mscalf.vifcode1().kind == VifCode::Kind::STMOD);
|
||||
|
||||
// 0: NOP NOP
|
||||
// auto another_nop = dma.read_and_advance();
|
||||
// ASSERT(is_nop_zero(another_nop));
|
||||
|
||||
while (dma.current_tag_offset() != next_bucket) {
|
||||
auto up1 = dma.read_and_advance();
|
||||
while (up1.vifcode0().kind == VifCode::Kind::NOP && up1.vifcode1().kind == VifCode::Kind::NOP) {
|
||||
up1 = dma.read_and_advance();
|
||||
}
|
||||
if (up1.vifcode0().kind == VifCode::Kind::FLUSHA) {
|
||||
while (dma.current_tag_offset() != next_bucket) {
|
||||
auto it = dma.read_and_advance();
|
||||
}
|
||||
break;
|
||||
}
|
||||
auto up2 = dma.read_and_advance();
|
||||
auto call = dma.read_and_advance();
|
||||
|
||||
// up1 is a 12 qw upload for control:
|
||||
// up2 is vertex upload.
|
||||
|
||||
auto* frag = &next_frag();
|
||||
ASSERT(up1.size_bytes == Generic2::FRAG_HEADER_SIZE + 5 * 16); // header + adgif
|
||||
memcpy(frag->header, up1.data, Generic2::FRAG_HEADER_SIZE);
|
||||
frag->adgif_idx = m_next_free_adgif;
|
||||
frag->adgif_count = 1;
|
||||
frag->mscal_addr = 6;
|
||||
frag->uses_hud = false;
|
||||
auto* adgif = &next_adgif();
|
||||
memcpy(&adgif->data, up1.data + Generic2::FRAG_HEADER_SIZE, sizeof(AdGifData));
|
||||
// (new 'static 'gif-tag-regs-32 :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2
|
||||
// (gif-reg-id xyzf2))
|
||||
int num_vtx = up2.size_bytes / (16 * 3);
|
||||
frag->vtx_count = num_vtx;
|
||||
frag->vtx_idx = m_next_free_vert;
|
||||
alloc_vtx(num_vtx);
|
||||
unpack_vertex(&m_verts[frag->vtx_idx], up2.data, num_vtx);
|
||||
}
|
||||
}
|
||||
|
||||
void Generic2::process_dma_lightning(DmaFollower& dma, u32 next_bucket) {
|
||||
reset_buffers();
|
||||
auto first_data = dma.read_and_advance();
|
||||
|
||||
@@ -74,6 +74,8 @@ void Generic2::opengl_setup(ShaderLibrary& shaders) {
|
||||
m_ogl.hvdf_offset = glGetUniformLocation(id, "hvdf_offset");
|
||||
m_ogl.gfx_hack_no_tex = glGetUniformLocation(id, "gfx_hack_no_tex");
|
||||
m_ogl.warp_sample_mode = glGetUniformLocation(id, "warp_sample_mode");
|
||||
m_ogl.use_full_matrix = glGetUniformLocation(id, "use_full_matrix");
|
||||
m_ogl.full_matrix = glGetUniformLocation(id, "full_matrix");
|
||||
}
|
||||
|
||||
void Generic2::opengl_cleanup() {
|
||||
@@ -307,6 +309,12 @@ void Generic2::do_draws(SharedRenderState* render_state, ScopedProfilerNode& pro
|
||||
glPrimitiveRestartIndex(UINT32_MAX);
|
||||
|
||||
opengl_bind_and_setup_proj(render_state);
|
||||
if (m_drawing_config.uses_full_matrix) {
|
||||
glUniform1i(m_ogl.use_full_matrix, 1);
|
||||
glUniformMatrix4fv(m_ogl.full_matrix, 1, GL_FALSE, m_drawing_config.full_matrix[0].data());
|
||||
} else {
|
||||
glUniform1i(m_ogl.use_full_matrix, 0);
|
||||
}
|
||||
constexpr DrawMode::AlphaBlend alpha_order[ALPHA_MODE_COUNT] = {
|
||||
DrawMode::AlphaBlend::SRC_0_FIX_DST, DrawMode::AlphaBlend::SRC_SRC_SRC_SRC,
|
||||
DrawMode::AlphaBlend::SRC_DST_SRC_DST, DrawMode::AlphaBlend::SRC_0_SRC_DST,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#endif
|
||||
|
||||
#include "common/global_profiler/GlobalProfiler.h"
|
||||
#include "common/util/fnv.h"
|
||||
|
||||
#include "game/graphics/opengl_renderer/EyeRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/background/background_common.h"
|
||||
@@ -54,6 +55,8 @@ std::mutex g_merc_data_mutex;
|
||||
|
||||
Merc2::Merc2(ShaderLibrary& shaders, const std::vector<GLuint>* anim_slot_array)
|
||||
: m_anim_slot_array(anim_slot_array) {
|
||||
ASSERT(fnv64("the quick brown fox jumps over the lazy dog") == 0x7404cea13ff89bb0);
|
||||
|
||||
// Set up main vertex array. This will point to the data stored in the .FR3 level file, and will
|
||||
// be uploaded to the GPU by the Loader.
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
@@ -535,11 +538,14 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
|
||||
auto* flags = (const PcMercFlags*)input_data;
|
||||
int num_effects = flags->effect_count; // mostly just a sanity check
|
||||
ASSERT(num_effects < kMaxEffect);
|
||||
// hack for custom models to disable blerc/mod draws
|
||||
bool is_custom_model = model->effects.at(0).all_draws.at(0).no_strip;
|
||||
u64 current_ignore_alpha_bits = flags->ignore_alpha_mask; // shader settings
|
||||
u64 current_effect_enable_bits = flags->enable_mask; // mask for game to disable an effect
|
||||
bool model_uses_mod = flags->bitflags & 1; // if we should update vertices from game.
|
||||
bool model_uses_mod =
|
||||
flags->bitflags & 1 && !is_custom_model; // if we should update vertices from game.
|
||||
bool model_disables_fog = flags->bitflags & 2;
|
||||
bool model_uses_pc_blerc = flags->bitflags & 4;
|
||||
bool model_uses_pc_blerc = flags->bitflags & 4 && !is_custom_model;
|
||||
bool model_disables_envmap = flags->bitflags & 8;
|
||||
input_data += 32;
|
||||
|
||||
@@ -609,6 +615,8 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
|
||||
u32 lights = alloc_lights(current_lights);
|
||||
stats->num_lights++;
|
||||
|
||||
u64 hash = fnv64(model->name);
|
||||
|
||||
// loop over effects, creating draws for each
|
||||
for (size_t ei = 0; ei < model->effects.size(); ei++) {
|
||||
// game has disabled it?
|
||||
@@ -633,7 +641,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
|
||||
// do fixed draws:
|
||||
for (auto& fdraw : effect.mod.fix_draw) {
|
||||
alloc_normal_draw(fdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
|
||||
model_disables_fog);
|
||||
model_disables_fog, hash);
|
||||
if (should_envmap) {
|
||||
try_alloc_envmap_draw(fdraw, effect.envmap_mode, effect.envmap_texture, lev_bucket,
|
||||
fade_buffer + 4 * ei, first_bone, lights, uses_water);
|
||||
@@ -643,7 +651,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
|
||||
// do mod draws
|
||||
for (auto& mdraw : effect.mod.mod_draw) {
|
||||
auto n = alloc_normal_draw(mdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
|
||||
model_disables_fog);
|
||||
model_disables_fog, hash);
|
||||
// modify the draw, set the mod flag and point it to the opengl buffer
|
||||
n->flags |= MOD_VTX;
|
||||
n->mod_vtx_buffer = mod_opengl_buffers[ei];
|
||||
@@ -665,7 +673,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
|
||||
fade_buffer + 4 * ei, first_bone, lights, uses_water);
|
||||
}
|
||||
alloc_normal_draw(draw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
|
||||
model_disables_fog);
|
||||
model_disables_fog, hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -761,7 +769,9 @@ void Merc2::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof,
|
||||
MercDebugStats* stats) {
|
||||
bool hack = stats->collect_debug_model_list;
|
||||
*stats = {};
|
||||
stats->collect_debug_model_list = hack;
|
||||
if (stats->collect_debug_model_list) {
|
||||
stats->model_list.clear();
|
||||
}
|
||||
@@ -1053,6 +1063,7 @@ Merc2::Draw* Merc2::try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw,
|
||||
draw->first_index = mdraw.first_index;
|
||||
draw->index_count = mdraw.index_count;
|
||||
draw->mode = envmap_mode;
|
||||
draw->hash = 0;
|
||||
if (jak1_water_mode) {
|
||||
draw->mode.enable_ab();
|
||||
draw->mode.disable_depth_write();
|
||||
@@ -1073,12 +1084,14 @@ Merc2::Draw* Merc2::alloc_normal_draw(const tfrag3::MercDraw& mdraw,
|
||||
u32 first_bone,
|
||||
u32 lights,
|
||||
bool jak1_water_mode,
|
||||
bool disable_fog) {
|
||||
bool disable_fog,
|
||||
u64 hash) {
|
||||
Draw* draw = &lev_bucket->draws[lev_bucket->next_free_draw++];
|
||||
draw->flags = 0;
|
||||
draw->first_index = mdraw.first_index;
|
||||
draw->index_count = mdraw.index_count;
|
||||
draw->mode = mdraw.mode;
|
||||
draw->hash = hash;
|
||||
if (jak1_water_mode) {
|
||||
draw->mode.set_ab(true);
|
||||
draw->mode.disable_depth_write();
|
||||
@@ -1205,7 +1218,7 @@ void Merc2::do_draws(const Draw* draw_array,
|
||||
bool set_fade,
|
||||
SharedRenderState* render_state) {
|
||||
glBindVertexArray(m_vao);
|
||||
int last_tex = -1;
|
||||
s32 last_tex = INT32_MIN;
|
||||
int last_light = -1;
|
||||
bool normal_vtx_buffer_bound = true;
|
||||
|
||||
@@ -1244,10 +1257,19 @@ void Merc2::do_draws(const Draw* draw_array,
|
||||
if (draw.texture < (int)lev->textures.size() && draw.texture >= 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, lev->textures.at(draw.texture));
|
||||
} else if ((draw.texture & 0xffffff00) == 0xefffff00) {
|
||||
auto maybe_eye = render_state->eye_renderer->lookup_eye_texture(draw.texture & 0xff);
|
||||
if (maybe_eye) {
|
||||
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
|
||||
if (render_state->version >= GameVersion::Jak3) {
|
||||
auto maybe_eye =
|
||||
render_state->eye_renderer->lookup_eye_texture_hash(draw.hash, (draw.texture & 1));
|
||||
if (maybe_eye) {
|
||||
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
|
||||
}
|
||||
} else {
|
||||
auto maybe_eye = render_state->eye_renderer->lookup_eye_texture(draw.texture & 0xff);
|
||||
if (maybe_eye) {
|
||||
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
|
||||
}
|
||||
}
|
||||
|
||||
use_mipmaps_for_filtering = false;
|
||||
} else if (draw.texture < 0) {
|
||||
int slot = -(draw.texture + 1);
|
||||
|
||||
@@ -192,6 +192,7 @@ class Merc2 {
|
||||
u8 fade[4];
|
||||
// no strip hack for custom models
|
||||
u8 no_strip;
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
struct LevelDrawBucket {
|
||||
@@ -213,7 +214,8 @@ class Merc2 {
|
||||
u32 first_bone,
|
||||
u32 lights,
|
||||
bool jak1_water_mode,
|
||||
bool disable_fog);
|
||||
bool disable_fog,
|
||||
u64 hash);
|
||||
|
||||
Draw* try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw,
|
||||
const DrawMode& envmap_mode,
|
||||
|
||||
@@ -17,8 +17,14 @@ void Merc2BucketRenderer::render(DmaFollower& dma,
|
||||
}
|
||||
|
||||
m_renderer->render(dma, render_state, prof, &m_debug_stats);
|
||||
|
||||
m_empty = m_debug_stats.num_predicted_draws == 0;
|
||||
}
|
||||
|
||||
void Merc2BucketRenderer::draw_debug_window() {
|
||||
m_renderer->draw_debug_window(&m_debug_stats);
|
||||
}
|
||||
|
||||
bool Merc2BucketRenderer::empty() const {
|
||||
return m_empty;
|
||||
}
|
||||
@@ -8,8 +8,10 @@ class Merc2BucketRenderer : public BucketRenderer {
|
||||
Merc2BucketRenderer(const std::string& name, int my_id, std::shared_ptr<Merc2> merc);
|
||||
void draw_debug_window() override;
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
bool empty() const override;
|
||||
|
||||
private:
|
||||
bool m_empty = false;
|
||||
std::shared_ptr<Merc2> m_renderer;
|
||||
MercDebugStats m_debug_stats;
|
||||
};
|
||||
@@ -10,6 +10,8 @@ uniform vec3 fog_constants;
|
||||
uniform vec4 scale;
|
||||
uniform float mat_23;
|
||||
uniform float mat_33;
|
||||
uniform bool use_full_matrix;
|
||||
uniform mat4 full_matrix;
|
||||
uniform vec4 hvdf_offset;
|
||||
uniform uint warp_sample_mode;
|
||||
|
||||
@@ -38,11 +40,17 @@ void main() {
|
||||
|
||||
// maddax.xyzw ACC, vf08, vf16 matrix multiply X
|
||||
// vu.acc.madda(Mask::xyzw, gen.mat0, gen.vtx_load0.x());
|
||||
transformed.xyz = position_in * scale.xyz;
|
||||
transformed.z += mat_32;
|
||||
transformed.w = mat_23 * position_in.z + mat_33;
|
||||
|
||||
transformed *= -1; // todo?
|
||||
if (use_full_matrix) {
|
||||
transformed = -full_matrix[3];
|
||||
transformed -= full_matrix[0] * position_in.x ;
|
||||
transformed -= full_matrix[1] * position_in.y;
|
||||
transformed -= full_matrix[2] * position_in.z ;
|
||||
} else {
|
||||
transformed.xyz = position_in * scale.xyz;
|
||||
transformed.z += mat_32;
|
||||
transformed.w = mat_23 * position_in.z + mat_33;
|
||||
transformed *= -1;
|
||||
}
|
||||
|
||||
|
||||
// div Q, vf01.x, vf12.w perspective divide
|
||||
|
||||
@@ -4,6 +4,7 @@ out vec4 color;
|
||||
|
||||
uniform vec4 rgba;
|
||||
uniform int enable_tex;
|
||||
uniform int set_alpha;
|
||||
uniform int tcc;
|
||||
uniform ivec4 channel_scramble;
|
||||
uniform float alpha_multiply;
|
||||
@@ -57,5 +58,9 @@ void main() {
|
||||
} else {
|
||||
color = (rgba / 128.);
|
||||
}
|
||||
color.a *= alpha_multiply;
|
||||
if (set_alpha == 1) {
|
||||
color.a = 0.5;
|
||||
} else {
|
||||
color.a *= alpha_multiply;
|
||||
}
|
||||
}
|
||||
@@ -448,23 +448,6 @@ void render_game_frame(int game_width,
|
||||
}
|
||||
}
|
||||
|
||||
void update_global_profiler() {
|
||||
if (g_gfx_data->debug_gui.dump_events) {
|
||||
prof().set_enable(false);
|
||||
g_gfx_data->debug_gui.dump_events = false;
|
||||
|
||||
// TODO - the file rotation code had an infinite loop here if it couldn't find anything
|
||||
// matching the format
|
||||
//
|
||||
// Does the existing log rotation code have that problem?
|
||||
|
||||
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
|
||||
fmt::format("prof-{}.json", str_util::current_local_timestamp_no_colons());
|
||||
file_util::create_dir_if_needed_for_file(file_path);
|
||||
prof().dump_to_json(file_path.string());
|
||||
}
|
||||
}
|
||||
|
||||
void GLDisplay::process_sdl_events() {
|
||||
SDL_Event evt;
|
||||
while (SDL_PollEvent(&evt) != 0) {
|
||||
@@ -603,7 +586,6 @@ void GLDisplay::render() {
|
||||
// Start timing for the next frame.
|
||||
g_gfx_data->debug_gui.start_frame();
|
||||
prof().instant_event("ROOT");
|
||||
update_global_profiler();
|
||||
|
||||
// toggle even odd and wake up engine waiting on vsync.
|
||||
// TODO: we could play with moving this earlier, right after the final bucket renderer.
|
||||
|
||||
@@ -125,7 +125,6 @@ struct link_control {
|
||||
}
|
||||
};
|
||||
|
||||
void klink_init_globals();
|
||||
Ptr<u8> c_symlink2(Ptr<u8> objData, Ptr<u8> linkObj, Ptr<u8> relocTable);
|
||||
|
||||
extern link_control saved_link_control;
|
||||
|
||||
@@ -448,6 +448,19 @@ u64 pc_get_mips2c(u32 name) {
|
||||
return Mips2C::gLinkedFunctionTable.get(n);
|
||||
}
|
||||
|
||||
u64 pc_get_display_id() {
|
||||
if (Display::GetMainDisplay()) {
|
||||
return Display::GetMainDisplay()->get_display_manager()->get_active_display_id();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pc_set_display_id(u64 display_id) {
|
||||
if (Display::GetMainDisplay()) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_display_id(display_id);
|
||||
}
|
||||
}
|
||||
|
||||
u64 pc_get_display_name(u32 id, u32 str_dest_ptr) {
|
||||
std::string name = "";
|
||||
if (Display::GetMainDisplay()) {
|
||||
@@ -469,17 +482,16 @@ u64 pc_get_display_name(u32 id, u32 str_dest_ptr) {
|
||||
}
|
||||
|
||||
u32 pc_get_display_mode() {
|
||||
auto display_mode = WindowDisplayMode::Windowed;
|
||||
auto display_mode = game_settings::DisplaySettings::DisplayMode::Windowed;
|
||||
if (Display::GetMainDisplay()) {
|
||||
display_mode = Display::GetMainDisplay()->get_display_manager()->get_window_display_mode();
|
||||
display_mode = Display::GetMainDisplay()->get_display_manager()->get_display_mode();
|
||||
}
|
||||
switch (display_mode) {
|
||||
case WindowDisplayMode::Borderless:
|
||||
case game_settings::DisplaySettings::DisplayMode::Borderless:
|
||||
return g_pc_port_funcs.intern_from_c("borderless").offset;
|
||||
case WindowDisplayMode::Fullscreen:
|
||||
case game_settings::DisplaySettings::DisplayMode::Fullscreen:
|
||||
return g_pc_port_funcs.intern_from_c("fullscreen").offset;
|
||||
default:
|
||||
case WindowDisplayMode::Windowed:
|
||||
return g_pc_port_funcs.intern_from_c("windowed").offset;
|
||||
}
|
||||
}
|
||||
@@ -490,13 +502,13 @@ void pc_set_display_mode(u32 symptr) {
|
||||
}
|
||||
if (symptr == g_pc_port_funcs.intern_from_c("windowed").offset || symptr == s7.offset) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
|
||||
WindowDisplayMode::Windowed);
|
||||
game_settings::DisplaySettings::DisplayMode::Windowed);
|
||||
} else if (symptr == g_pc_port_funcs.intern_from_c("borderless").offset) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
|
||||
WindowDisplayMode::Borderless);
|
||||
game_settings::DisplaySettings::DisplayMode::Borderless);
|
||||
} else if (symptr == g_pc_port_funcs.intern_from_c("fullscreen").offset) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
|
||||
WindowDisplayMode::Fullscreen);
|
||||
game_settings::DisplaySettings::DisplayMode::Fullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,12 +580,6 @@ void pc_get_window_scale(u32 x_ptr, u32 y_ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
void pc_get_fullscreen_display(u64 display_id) {
|
||||
if (Display::GetMainDisplay()) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_fullscreen_display_id(display_id);
|
||||
}
|
||||
}
|
||||
|
||||
void pc_set_window_size(u64 width, u64 height) {
|
||||
if (Display::GetMainDisplay()) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_size(width, height);
|
||||
@@ -601,6 +607,14 @@ void pc_get_resolution(u32 id, u32 w_ptr, u32 h_ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
u64 pc_is_supported_resolution(u64 width, u64 height) {
|
||||
if (Display::GetMainDisplay()) {
|
||||
return bool_to_symbol(
|
||||
Display::GetMainDisplay()->get_display_manager()->is_supported_resolution(width, height));
|
||||
}
|
||||
return bool_to_symbol(false);
|
||||
}
|
||||
|
||||
u64 pc_get_controller_name(u32 id, u32 str_dest_ptr) {
|
||||
std::string name = "";
|
||||
if (Display::GetMainDisplay()) {
|
||||
@@ -912,9 +926,11 @@ void init_common_pc_port_functions(
|
||||
|
||||
// -- DISPLAY RELATED --
|
||||
// Returns the name of the display with the given id or #f if not found / empty
|
||||
make_func_symbol_func("pc-get-display-id", (void*)pc_get_display_id);
|
||||
make_func_symbol_func("pc-set-display-id!", (void*)pc_set_display_id);
|
||||
make_func_symbol_func("pc-get-display-name", (void*)pc_get_display_name);
|
||||
make_func_symbol_func("pc-get-display-mode", (void*)pc_get_display_mode);
|
||||
make_func_symbol_func("pc-set-display-mode", (void*)pc_set_display_mode);
|
||||
make_func_symbol_func("pc-set-display-mode!", (void*)pc_set_display_mode);
|
||||
make_func_symbol_func("pc-get-display-count", (void*)pc_get_display_count);
|
||||
// Returns resolution of the monitor's current display mode
|
||||
make_func_symbol_func("pc-get-active-display-size", (void*)pc_get_active_display_size);
|
||||
@@ -925,10 +941,10 @@ void init_common_pc_port_functions(
|
||||
make_func_symbol_func("pc-get-window-size", (void*)pc_get_window_size);
|
||||
// Returns scale of window. This is for DPI stuff.
|
||||
make_func_symbol_func("pc-get-window-scale", (void*)pc_get_window_scale);
|
||||
make_func_symbol_func("pc-set-fullscreen-display", (void*)pc_get_fullscreen_display);
|
||||
make_func_symbol_func("pc-set-window-size", (void*)pc_set_window_size);
|
||||
make_func_symbol_func("pc-set-window-size!", (void*)pc_set_window_size);
|
||||
make_func_symbol_func("pc-get-num-resolutions", (void*)pc_get_num_resolutions);
|
||||
make_func_symbol_func("pc-get-resolution", (void*)pc_get_resolution);
|
||||
make_func_symbol_func("pc-is-supported-resolution?", (void*)pc_is_supported_resolution);
|
||||
|
||||
// -- INPUT RELATED --
|
||||
// Returns the name of the display with the given id or #f if not found / empty
|
||||
|
||||
@@ -16,7 +16,6 @@ void load_and_link_dgo_from_c_fast(const char* name,
|
||||
Ptr<kheapinfo> heap,
|
||||
u32 linkFlag,
|
||||
s32 bufferSize);
|
||||
void load_and_link_dgo(u64 name_gstr, u64 heap_info, u64 flag, u64 buffer_size);
|
||||
void kdgo_init_globals();
|
||||
extern RPC_Dgo_Cmd sMsg[2];
|
||||
extern RPC_Dgo_Cmd* sLastMsg;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "game/kernel/common/kdgo.h"
|
||||
#include "game/kernel/common/kmalloc.h"
|
||||
#include "game/kernel/jak3/klink.h"
|
||||
#include "game/overlord/jak3/rpc_interface.h"
|
||||
|
||||
namespace jak3 {
|
||||
|
||||
@@ -39,7 +40,7 @@ void BeginLoadingDGO(const char* name, Ptr<u8> buffer1, Ptr<u8> buffer2, Ptr<u8>
|
||||
RpcSync(DGO_RPC_CHANNEL); // make sure old RPC is finished
|
||||
|
||||
// put a dummy value here just to make sure the IOP overwrites it.
|
||||
sMsg[msgID].result = DGO_RPC_RESULT_INIT; // !! this is 666
|
||||
sMsg[msgID].status = DGO_RPC_RESULT_INIT; // !! this is 666
|
||||
|
||||
// inform IOP of buffers
|
||||
sMsg[msgID].buffer1 = buffer1.offset;
|
||||
@@ -78,13 +79,13 @@ Ptr<u8> GetNextDGO(u32* lastObjectFlag) {
|
||||
Ptr<u8> buffer(0);
|
||||
if (sLastMsg) {
|
||||
// if we got a good result, get pointer to object
|
||||
if ((sLastMsg->result == DGO_RPC_RESULT_MORE) || (sLastMsg->result == DGO_RPC_RESULT_DONE)) {
|
||||
if ((sLastMsg->status == DGO_RPC_RESULT_MORE) || (sLastMsg->status == DGO_RPC_RESULT_DONE)) {
|
||||
buffer.offset =
|
||||
sLastMsg->buffer1; // buffer 1 always contains location of most recently loaded object.
|
||||
}
|
||||
|
||||
// not the last one, so don't set the flag.
|
||||
if (sLastMsg->result == DGO_RPC_RESULT_MORE) {
|
||||
if (sLastMsg->status == DGO_RPC_RESULT_MORE) {
|
||||
*lastObjectFlag = 0;
|
||||
}
|
||||
|
||||
@@ -111,7 +112,7 @@ void ContinueLoadingDGO(Ptr<u8> b1, Ptr<u8> b2, Ptr<u8> heapPtr) {
|
||||
u32 msgID = sMsgNum;
|
||||
jak3::RPC_Dgo_Cmd* sendBuff = sMsg + sMsgNum;
|
||||
sMsgNum = sMsgNum ^ 1;
|
||||
sendBuff->result = DGO_RPC_RESULT_INIT;
|
||||
sendBuff->status = DGO_RPC_RESULT_INIT;
|
||||
sMsg[msgID].buffer1 = b1.offset;
|
||||
sMsg[msgID].buffer2 = b2.offset;
|
||||
sMsg[msgID].buffer_heap_top = heapPtr.offset;
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
//--------------------------MIPS2C---------------------
|
||||
// clang-format off
|
||||
#include "game/mips2c/mips2c_private.h"
|
||||
#include "game/kernel/jak3/kscheme.h"
|
||||
using ::jak3::intern_from_c;
|
||||
namespace Mips2C::jak3 {
|
||||
namespace method_21_cloth_system {
|
||||
u64 execute(void* ctxt) {
|
||||
auto* c = (ExecutionContext*)ctxt;
|
||||
bool bc = false;
|
||||
u32 call_addr = 0;
|
||||
c->daddiu(sp, sp, -80); // daddiu sp, sp, -80
|
||||
c->daddiu(a3, sp, 16); // daddiu a3, sp, 16
|
||||
c->daddiu(t0, sp, 32); // daddiu t0, sp, 32
|
||||
c->lwu(v1, 68, a0); // lwu v1, 68(a0)
|
||||
c->lw(v1, 0, v1); // lw v1, 0(v1)
|
||||
c->lw(a1, 96, a0); // lw a1, 96(a0)
|
||||
c->daddiu(a1, a1, -1); // daddiu a1, a1, -1
|
||||
c->lw(a2, 100, a0); // lw a2, 100(a0)
|
||||
c->daddiu(a2, a2, -1); // daddiu a2, a2, -1
|
||||
c->addiu(t1, r0, 0); // addiu t1, r0, 0
|
||||
c->addiu(t1, r0, 0); // addiu t1, r0, 0
|
||||
c->mov64(t1, a3); // or t1, a3, r0
|
||||
c->lui(t2, 16000); // lui t2, 16000
|
||||
c->mtc1(f0, t2); // mtc1 f0, t2
|
||||
c->swc1(f0, 0, t1); // swc1 f0, 0(t1)
|
||||
c->lui(t2, 16000); // lui t2, 16000
|
||||
c->mtc1(f0, t2); // mtc1 f0, t2
|
||||
c->swc1(f0, 4, t1); // swc1 f0, 4(t1)
|
||||
c->lui(t2, 16000); // lui t2, 16000
|
||||
c->mtc1(f0, t2); // mtc1 f0, t2
|
||||
c->swc1(f0, 8, t1); // swc1 f0, 8(t1)
|
||||
c->lui(t2, 16000); // lui t2, 16000
|
||||
c->mtc1(f0, t2); // mtc1 f0, t2
|
||||
c->swc1(f0, 12, t1); // swc1 f0, 12(t1)
|
||||
c->mov64(t1, t0); // or t1, t0, r0
|
||||
c->mtc1(f0, r0); // mtc1 f0, r0
|
||||
c->swc1(f0, 0, t1); // swc1 f0, 0(t1)
|
||||
c->mtc1(f0, r0); // mtc1 f0, r0
|
||||
c->swc1(f0, 4, t1); // swc1 f0, 4(t1)
|
||||
c->mtc1(f0, r0); // mtc1 f0, r0
|
||||
c->swc1(f0, 8, t1); // swc1 f0, 8(t1)
|
||||
c->lwc1(f0, 144, a0); // lwc1 f0, 144(a0)
|
||||
c->swc1(f0, 12, t1); // swc1 f0, 12(t1)
|
||||
c->vmax_bc(DEST::xyzw, BC::w, vf1, vf0, vf0); // vmaxw.xyzw vf1, vf0, vf0
|
||||
c->lqc2(vf10, 0, a3); // lqc2 vf10, 0(a3)
|
||||
c->lqc2(vf15, 0, t0); // lqc2 vf15, 0(t0)
|
||||
c->sd(r0, 48, sp); // sd r0, 48(sp)
|
||||
c->addiu(a3, r0, 0); // addiu a3, r0, 0
|
||||
//beq r0, r0, L187 // beq r0, r0, L187
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_10; // branch always
|
||||
|
||||
|
||||
block_1:
|
||||
c->addiu(t0, r0, 0); // addiu t0, r0, 0
|
||||
//beq r0, r0, L186 // beq r0, r0, L186
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_8; // branch always
|
||||
|
||||
|
||||
block_2:
|
||||
c->addiu(t1, r0, 48); // addiu t1, r0, 48
|
||||
c->ld(t2, 48, sp); // ld t2, 48(sp)
|
||||
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
|
||||
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
|
||||
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
|
||||
c->daddu(t1, t1, t2); // daddu t1, t1, t2
|
||||
c->sw(t1, 56, sp); // sw t1, 56(sp)
|
||||
c->addiu(t1, r0, 48); // addiu t1, r0, 48
|
||||
c->ld(t2, 48, sp); // ld t2, 48(sp)
|
||||
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
|
||||
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
|
||||
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
|
||||
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
|
||||
c->daddu(t1, t1, t2); // daddu t1, t1, t2
|
||||
c->sw(t1, 60, sp); // sw t1, 60(sp)
|
||||
c->addiu(t1, r0, 48); // addiu t1, r0, 48
|
||||
c->ld(t2, 48, sp); // ld t2, 48(sp)
|
||||
c->lw(t3, 96, a0); // lw t3, 96(a0)
|
||||
c->daddu(t2, t2, t3); // daddu t2, t2, t3
|
||||
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
|
||||
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
|
||||
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
|
||||
c->daddu(t1, t1, t2); // daddu t1, t1, t2
|
||||
c->sw(t1, 64, sp); // sw t1, 64(sp)
|
||||
c->addiu(t1, r0, 48); // addiu t1, r0, 48
|
||||
c->lw(t2, 96, a0); // lw t2, 96(a0)
|
||||
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
|
||||
c->ld(t3, 48, sp); // ld t3, 48(sp)
|
||||
c->daddu(t2, t2, t3); // daddu t2, t2, t3
|
||||
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
|
||||
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
|
||||
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
|
||||
c->daddu(t1, t1, t2); // daddu t1, t1, t2
|
||||
c->sw(t1, 68, sp); // sw t1, 68(sp)
|
||||
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
|
||||
c->lqc2(vf2, 0, t1); // lqc2 vf2, 0(t1)
|
||||
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
|
||||
c->lqc2(vf5, 0, t1); // lqc2 vf5, 0(t1)
|
||||
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
|
||||
c->lqc2(vf3, 0, t1); // lqc2 vf3, 0(t1)
|
||||
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
|
||||
c->lqc2(vf4, 0, t1); // lqc2 vf4, 0(t1)
|
||||
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
|
||||
c->lqc2(vf20, 32, t1); // lqc2 vf20, 32(t1)
|
||||
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
|
||||
c->lqc2(vf23, 32, t1); // lqc2 vf23, 32(t1)
|
||||
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
|
||||
c->lqc2(vf21, 32, t1); // lqc2 vf21, 32(t1)
|
||||
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
|
||||
c->lqc2(vf22, 32, t1); // lqc2 vf22, 32(t1)
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf2, vf20); // vmulax.xyzw acc, vf2, vf20
|
||||
c->vmadda_bc(DEST::xyzw, BC::x, vf3, vf21); // vmaddax.xyzw acc, vf3, vf21
|
||||
c->vmadda_bc(DEST::xyzw, BC::x, vf5, vf23); // vmaddax.xyzw acc, vf5, vf23
|
||||
c->vmadd_bc(DEST::xyzw, BC::x, vf8, vf4, vf22); // vmaddx.xyzw vf8, vf4, vf22
|
||||
c->vmul_bc(DEST::xyzw, BC::x, vf8, vf8, vf10); // vmulx.xyzw vf8, vf8, vf10
|
||||
c->lwu(t1, 68, a0); // lwu t1, 68(a0)
|
||||
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
|
||||
c->addiu(t2, r0, 0); // addiu t2, r0, 0
|
||||
//beq r0, r0, L185 // beq r0, r0, L185
|
||||
// nop // sll r0, r0, 0
|
||||
goto block_6; // branch always
|
||||
|
||||
|
||||
block_3:
|
||||
c->lqc2(vf11, 0, t1); // lqc2 vf11, 0(t1)
|
||||
c->vsub(DEST::xyzw, vf13, vf8, vf11); // vsub.xyzw vf13, vf8, vf11
|
||||
c->vmul(DEST::xyzw, vf9, vf13, vf13); // vmul.xyzw vf9, vf13, vf13
|
||||
c->vmula_bc(DEST::xyzw, BC::x, vf1, vf9); // vmulax.xyzw acc, vf1, vf9
|
||||
c->vmadda_bc(DEST::xyzw, BC::y, vf1, vf9); // vmadday.xyzw acc, vf1, vf9
|
||||
c->vmadd_bc(DEST::xyzw, BC::z, vf14, vf1, vf9); // vmaddz.xyzw vf14, vf1, vf9
|
||||
c->vadd_bc(DEST::w, BC::w, vf11, vf11, vf15); // vaddw.w vf11, vf11, vf15
|
||||
c->vmul(DEST::xyzw, vf12, vf11, vf11); // vmul.xyzw vf12, vf11, vf11
|
||||
c->vsub_bc(DEST::xyzw, BC::w, vf9, vf14, vf12); // vsubw.xyzw vf9, vf14, vf12
|
||||
c->mov128_gpr_vf(t3, vf9); // qmfc2.i t3, vf9
|
||||
bc = ((s64)c->sgpr64(t3)) >= 0; // bgez t3, L184
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_5;} // branch non-likely
|
||||
|
||||
c->vrsqrt(vf11, BC::w, vf14, BC::x); // vrsqrt Q, vf11.w, vf14.x
|
||||
c->vmax_bc(DEST::xyz, BC::x, vf20, vf0, vf20); // vmaxx.xyz vf20, vf0, vf20
|
||||
c->vmax_bc(DEST::xyz, BC::x, vf21, vf0, vf21); // vmaxx.xyz vf21, vf0, vf21
|
||||
c->vmax_bc(DEST::xyz, BC::x, vf22, vf0, vf22); // vmaxx.xyz vf22, vf0, vf22
|
||||
c->vmax_bc(DEST::xyz, BC::x, vf23, vf0, vf23); // vmaxx.xyz vf23, vf0, vf23
|
||||
c->vwaitq(); // vwaitq
|
||||
// Unknown instr: vmulaq.xyzw acc, vf13, Q
|
||||
c->vmula_q(DEST::xyzw, vf13);
|
||||
c->vmsuba(DEST::xyzw, vf1, vf13); // vmsuba.xyzw acc, vf1, vf13
|
||||
c->vmadd(DEST::xyzw, vf2, vf1, vf2); // vmadd.xyzw vf2, vf1, vf2
|
||||
c->vmadd(DEST::xyzw, vf3, vf1, vf3); // vmadd.xyzw vf3, vf1, vf3
|
||||
c->vmadd(DEST::xyzw, vf5, vf1, vf5); // vmadd.xyzw vf5, vf1, vf5
|
||||
c->vmadd(DEST::xyzw, vf4, vf1, vf4); // vmadd.xyzw vf4, vf1, vf4
|
||||
c->vmadd(DEST::xyzw, vf8, vf1, vf8); // vmadd.xyzw vf8, vf1, vf8
|
||||
|
||||
block_5:
|
||||
c->daddiu(t1, t1, 16); // daddiu t1, t1, 16
|
||||
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
|
||||
|
||||
block_6:
|
||||
c->slt(t3, t2, v1); // slt t3, t2, v1
|
||||
bc = c->sgpr64(t3) != 0; // bne t3, r0, L183
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_3;} // branch non-likely
|
||||
|
||||
c->mov64(t1, s7); // or t1, s7, r0
|
||||
c->mov64(t1, s7); // or t1, s7, r0
|
||||
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
|
||||
c->sqc2(vf2, 0, t1); // sqc2 vf2, 0(t1)
|
||||
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
|
||||
c->sqc2(vf5, 0, t1); // sqc2 vf5, 0(t1)
|
||||
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
|
||||
c->sqc2(vf3, 0, t1); // sqc2 vf3, 0(t1)
|
||||
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
|
||||
c->sqc2(vf4, 0, t1); // sqc2 vf4, 0(t1)
|
||||
c->mov128_gpr_vf(t1, vf4); // qmfc2.i t1, vf4
|
||||
c->ld(t1, 48, sp); // ld t1, 48(sp)
|
||||
c->daddiu(t1, t1, 1); // daddiu t1, t1, 1
|
||||
c->sd(t1, 48, sp); // sd t1, 48(sp)
|
||||
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
|
||||
|
||||
block_8:
|
||||
c->slt(t1, t0, a1); // slt t1, t0, a1
|
||||
bc = c->sgpr64(t1) != 0; // bne t1, r0, L182
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_2;} // branch non-likely
|
||||
|
||||
c->mov64(t0, s7); // or t0, s7, r0
|
||||
c->mov64(t0, s7); // or t0, s7, r0
|
||||
c->ld(t0, 48, sp); // ld t0, 48(sp)
|
||||
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
|
||||
c->sd(t0, 48, sp); // sd t0, 48(sp)
|
||||
c->daddiu(a3, a3, 1); // daddiu a3, a3, 1
|
||||
|
||||
block_10:
|
||||
c->slt(t0, a3, a2); // slt t0, a3, a2
|
||||
bc = c->sgpr64(t0) != 0; // bne t0, r0, L181
|
||||
// nop // sll r0, r0, 0
|
||||
if (bc) {goto block_1;} // branch non-likely
|
||||
|
||||
c->mov64(v1, s7); // or v1, s7, r0
|
||||
c->mov64(v0, s7); // or v0, s7, r0
|
||||
//jr ra // jr ra
|
||||
c->daddiu(sp, sp, 80); // daddiu sp, sp, 80
|
||||
goto end_of_function; // return
|
||||
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
// nop // sll r0, r0, 0
|
||||
end_of_function:
|
||||
return c->gprs[v0].du64[0];
|
||||
}
|
||||
|
||||
void link() {
|
||||
gLinkedFunctionTable.reg("(method 21 cloth-system)", execute, 256);
|
||||
}
|
||||
|
||||
} // namespace method_21_cloth_system
|
||||
} // namespace Mips2C
|
||||
|
||||
@@ -905,6 +905,16 @@ struct ExecutionContext {
|
||||
}
|
||||
}
|
||||
|
||||
void vmula_q(DEST mask, int src0) {
|
||||
auto s0 = vf_src(src0);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if ((u64)mask & (1 << i)) {
|
||||
acc.f[i] = s0.f[i] * Q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vadda_bc(DEST mask, BC bc, int src0, int src1) {
|
||||
auto s0 = vf_src(src0);
|
||||
auto s1 = vf_src(src1);
|
||||
|
||||
@@ -393,6 +393,7 @@ namespace shadow_add_double_edges { extern void link(); }
|
||||
namespace shadow_add_single_tris { extern void link(); }
|
||||
namespace shadow_add_double_tris { extern void link(); }
|
||||
namespace shadow_execute { extern void link(); }
|
||||
namespace method_21_cloth_system { extern void link(); }
|
||||
|
||||
}
|
||||
// clang-format on
|
||||
@@ -654,7 +655,8 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
|
||||
jak3::shadow_find_single_edges::link, jak3::shadow_find_double_edges::link,
|
||||
jak3::shadow_add_verts::link, jak3::shadow_add_facing_single_tris::link,
|
||||
jak3::shadow_add_single_edges::link, jak3::shadow_add_double_edges::link,
|
||||
jak3::shadow_add_single_tris::link, jak3::shadow_add_double_tris::link}}}};
|
||||
jak3::shadow_add_single_tris::link, jak3::shadow_add_double_tris::link}},
|
||||
{"cloth", {jak3::method_21_cloth_system::link}}}};
|
||||
|
||||
void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 stack_size) {
|
||||
const auto& it = m_executes.insert({name, {exec, Ptr<u8>()}});
|
||||
|
||||
@@ -460,6 +460,9 @@ void* RPC_Loader(unsigned int /*fno*/, void* data, int size) {
|
||||
snd_SetPlayBackMode(0);
|
||||
}
|
||||
} break;
|
||||
case Jak2SoundCommand::mirror_mode: {
|
||||
gMirrorMode = cmd->mirror.value;
|
||||
} break;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("Unhandled RPC Loader command {}", int(cmd->j2command)));
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ enum class Jak2SoundCommand : u16 {
|
||||
iop_mem = 48,
|
||||
cancel_dgo = 49,
|
||||
set_stereo_mode = 50,
|
||||
mirror_mode = 201,
|
||||
};
|
||||
|
||||
struct SoundRpcCommand {
|
||||
|
||||
@@ -30,7 +30,7 @@ void StopVAG(VagCmd* cmd, int /*param_2*/);
|
||||
enum VolumeCategory {
|
||||
DIALOGUE = 2, // VAG streams. Copied "dialogue" name from jak 1.
|
||||
};
|
||||
int MasterVolume[17];
|
||||
int MasterVolume[32];
|
||||
|
||||
void vag_init_globals() {
|
||||
memset(VagCmds, 0, sizeof(VagCmds));
|
||||
|
||||
@@ -113,7 +113,7 @@ extern int TrapSRAM[N_VAG_CMDS];
|
||||
extern int StreamVoice[N_VAG_CMDS];
|
||||
|
||||
extern int ActiveVagStreams;
|
||||
extern int MasterVolume[17];
|
||||
extern int MasterVolume[32];
|
||||
|
||||
void vag_init_globals();
|
||||
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
#include "basefile.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "game/overlord/jak3/overlord.h"
|
||||
#include "game/overlord/jak3/pagemanager.h"
|
||||
#include "game/overlord/jak3/vag.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_basefile() {}
|
||||
|
||||
/*!
|
||||
* Construct a CBaseFile in an unused state.
|
||||
*/
|
||||
CBaseFile::CBaseFile() {
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_pPageList = nullptr;
|
||||
m_Buffer.m_pIsoCmd = nullptr;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
|
||||
|
||||
m_ProcessDataSemaphore = -1;
|
||||
m_FileDef = nullptr;
|
||||
m_FileKind = Kind::UNKNOWN;
|
||||
m_Status = EIsoStatus::NONE_0;
|
||||
m_ReadRate = 0;
|
||||
m_LengthPages = 0;
|
||||
m_PageOffset = 0;
|
||||
m_nNumPages = kDefaultBufferPageCount;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Construct a CBaseFile for a given file, but keep it in the "idle" state, with no buffer
|
||||
* allocated.
|
||||
*/
|
||||
CBaseFile::CBaseFile(const jak3::ISOFileDef* file, int semaphore) {
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_Buffer.m_pPageList = nullptr;
|
||||
m_Buffer.m_pIsoCmd = nullptr;
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
|
||||
|
||||
m_nNumPages = kDefaultBufferPageCount;
|
||||
m_FileDef = file;
|
||||
m_ProcessDataSemaphore = semaphore;
|
||||
m_FileKind = Kind::UNKNOWN;
|
||||
m_Status = EIsoStatus::IDLE_1;
|
||||
m_ReadRate = 0;
|
||||
m_LengthPages = 0;
|
||||
m_PageOffset = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Update our buffer to handle crossing page boundaries, return pointer to next data.
|
||||
*/
|
||||
uint8_t* CBaseFile::CheckPageBoundary() {
|
||||
// Can't check page boundary if the buffer is not allocated.
|
||||
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
|
||||
|
||||
// Can't check page boundary if there is no manager
|
||||
ASSERT(m_Buffer.m_pPageList);
|
||||
|
||||
CPageList* page_list = m_Buffer.m_pPageList;
|
||||
CPage* page = page_list->m_pCurrentActivePage;
|
||||
|
||||
// can only return data if there's an active page
|
||||
if (!page || page_list->m_nNumActivePages <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// buffer doesn't know the current page, just reset it to the start of the active page.
|
||||
if (m_Buffer.m_pCurrentPageStart == nullptr) {
|
||||
m_Buffer.m_pCurrentData = page->m_pPageMemStart;
|
||||
m_Buffer.m_pCurrentPageStart = page->m_pPageMemStart;
|
||||
} else {
|
||||
uint8_t* end_ptr = page->m_pPageMemEnd;
|
||||
// check if our data pointer crossed the page boundary
|
||||
if (end_ptr <= m_Buffer.m_pCurrentData) {
|
||||
// it did!
|
||||
uint8_t* past_boundary_ptr = m_Buffer.m_pCurrentData;
|
||||
|
||||
// get the next active page
|
||||
CPage* next_page = page_list->StepActivePage();
|
||||
if (!next_page) {
|
||||
// no more active pages, no data to process
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
ovrld_log(LogCategory::PAGING, "File {} ran out of pages in CheckPageBoundary",
|
||||
m_FileDef->name.data);
|
||||
} else {
|
||||
// this is a little weird, but if we went past the end of the previous page, we actually
|
||||
// start at an offset into the next page - perhaps the user could know that pages are
|
||||
// consecutive in memory?
|
||||
uint8_t* new_page_mem = next_page->m_pPageMemStart;
|
||||
m_Buffer.m_pCurrentData = new_page_mem + (end_ptr + 1 - past_boundary_ptr);
|
||||
m_Buffer.m_pCurrentPageStart = new_page_mem;
|
||||
ovrld_log(LogCategory::PAGING, "File {} advanced to next page (wrapped {} bytes)",
|
||||
m_FileDef->name.data, (end_ptr + 1 - past_boundary_ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_Buffer.m_pCurrentData;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate pages and set up the CBuffer for the given ISO Msg and type.
|
||||
*/
|
||||
int CBaseFile::InitBuffer(CBuffer::BufferType type, jak3::ISO_Hdr* msg) {
|
||||
ASSERT(msg);
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
m_Buffer.m_pPageList = nullptr;
|
||||
m_Buffer.m_pIsoCmd = msg;
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
|
||||
m_nNumPages = 4;
|
||||
|
||||
// adjust size based on the request buffer type
|
||||
switch (type) {
|
||||
case CBuffer::BufferType::REQUEST_NORMAL: { // 3
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_Buffer.m_nMaxNumPages = 4;
|
||||
m_nNumPages = 4;
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::NORMAL; // 1
|
||||
|
||||
// and the iso msg request.
|
||||
switch (msg->msg_type) {
|
||||
case ISO_Hdr::MsgType::LOAD_EE:
|
||||
case ISO_Hdr::MsgType::LOAD_IOP:
|
||||
case ISO_Hdr::MsgType::LOAD_EE_CHUNK:
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_nNumPages = 4;
|
||||
m_Buffer.m_nMaxNumPages = 4;
|
||||
break;
|
||||
case ISO_Hdr::MsgType::LOAD_SOUNDBANK:
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_Buffer.m_nMaxNumPages = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} break;
|
||||
case CBuffer::BufferType::REQUEST_VAG: {
|
||||
m_Buffer.m_pCurrentData = nullptr;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::VAG;
|
||||
m_Buffer.m_nMinNumPages = 1;
|
||||
m_nNumPages = 0x10;
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_pCurrentPageStart = nullptr;
|
||||
m_Buffer.m_nMaxNumPages = 0x10;
|
||||
} break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED(); // bad buffer type
|
||||
}
|
||||
|
||||
ovrld_log(LogCategory::PAGING, "File {} initializing buffer ({} pages {} min {} max)",
|
||||
m_FileDef->name.data, m_nNumPages, m_Buffer.m_nMinNumPages, m_Buffer.m_nMaxNumPages);
|
||||
|
||||
// Actual allocation of page data
|
||||
CPageList* page_list = AllocPages();
|
||||
if (page_list) {
|
||||
// set up the current pointers of the buffer.
|
||||
m_Buffer.m_pCurrentPageStart = page_list->m_pFirstPage->m_pPageMemStart;
|
||||
m_Buffer.m_pCurrentData = m_Buffer.m_pCurrentPageStart;
|
||||
return 1;
|
||||
} else {
|
||||
ovrld_log(LogCategory::WARN, "File {} failed to allocate a page list.", m_FileDef->name.data);
|
||||
// if it failed, terminate the buffer
|
||||
TerminateBuffer();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free page memory, clear event flags for cpages.
|
||||
*/
|
||||
void CBaseFile::TerminateBuffer() {
|
||||
ovrld_log(LogCategory::PAGING, "File {} terminating buffer.", m_FileDef->name.data);
|
||||
|
||||
auto buffer_type = m_Buffer.m_eBufferType;
|
||||
if (buffer_type != CBuffer::BufferType::EBT_FREE) {
|
||||
// clean up our pages
|
||||
auto* page_list = m_Buffer.m_pPageList;
|
||||
if (page_list) {
|
||||
// stop try to load
|
||||
page_list->CancelActivePages();
|
||||
}
|
||||
|
||||
switch (buffer_type) {
|
||||
case CBuffer::BufferType::EBT_FREE:
|
||||
case CBuffer::BufferType::NORMAL:
|
||||
case CBuffer::BufferType::VAG:
|
||||
case CBuffer::BufferType::REQUEST_NORMAL:
|
||||
case CBuffer::BufferType::REQUEST_VAG:
|
||||
// return memory
|
||||
FreePages();
|
||||
|
||||
// reset our buffer
|
||||
m_Buffer.m_nDataLength = 0;
|
||||
m_Buffer.m_pCurrentPageStart = 0;
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
|
||||
|
||||
// reset our command
|
||||
if (buffer_type != CBuffer::BufferType::EBT_FREE) {
|
||||
ASSERT(m_Buffer.m_pIsoCmd);
|
||||
m_Buffer.m_pIsoCmd = nullptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED(); // Invalid buffer type
|
||||
}
|
||||
} else {
|
||||
ASSERT_NOT_REACHED(); // Buffer already terminated, shouldn't happen again.
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate CPage and CPageList as needed to reach the target number of pages.
|
||||
*/
|
||||
CPageList* CBaseFile::AllocPages() {
|
||||
// should have picked a buffer type
|
||||
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
|
||||
|
||||
if (m_Buffer.m_eBufferType == CBuffer::BufferType::EBT_FREE) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We might have a PageList or not
|
||||
auto* old_plist = m_Buffer.m_pPageList;
|
||||
int old_unstepped_pages = 0;
|
||||
bool have_plist = old_plist != nullptr;
|
||||
CPageList* ret_plist = nullptr;
|
||||
|
||||
// if we do have a pagelist, we'll reuse it and any unstepped pages.
|
||||
if (have_plist) {
|
||||
old_unstepped_pages = old_plist->m_nNumUnsteppedPages;
|
||||
ret_plist = old_plist;
|
||||
}
|
||||
|
||||
int page_alloc_count = 0;
|
||||
|
||||
// to increase unstepped pages to the target m_nNumPages, we need to allocate this many more.
|
||||
page_alloc_count = m_nNumPages - old_unstepped_pages;
|
||||
// lg::warn("page counts in AllocPages: {} {}", m_nNumPages, old_unstepped_pages);
|
||||
if (old_plist) {
|
||||
// lg::warn(" {} {}", old_plist->m_nNumPages, old_plist->m_nNumActivePages);
|
||||
}
|
||||
|
||||
if (old_unstepped_pages < (int)m_nNumPages) {
|
||||
// alloc count will be positive.
|
||||
|
||||
// reduce allocation count to at most the number of free pages
|
||||
if (get_page_manager()->m_CCache.m_nNumFreePages < page_alloc_count) {
|
||||
page_alloc_count = get_page_manager()->m_CCache.m_nNumFreePages;
|
||||
}
|
||||
|
||||
} else {
|
||||
// alloc count would be negative, don't allocate
|
||||
page_alloc_count = 0;
|
||||
}
|
||||
|
||||
switch (m_Buffer.m_eBufferType) {
|
||||
case CBuffer::BufferType::NORMAL:
|
||||
case CBuffer::BufferType::REQUEST_NORMAL: {
|
||||
// don't do anything special
|
||||
} break;
|
||||
case CBuffer::BufferType::VAG:
|
||||
case CBuffer::BufferType::REQUEST_VAG: {
|
||||
// for VAG commands, we don't bother buffering more than the DMA transfer size
|
||||
int dma_xfer_size = ((ISO_VAGCommand*)m_Buffer.m_pIsoCmd)->xfer_size;
|
||||
if (dma_xfer_size) {
|
||||
ASSERT(dma_xfer_size > 0);
|
||||
int limit = (dma_xfer_size + 0x7fff) >> 0xf;
|
||||
if (page_alloc_count > limit) {
|
||||
ovrld_log(LogCategory::WARN, "File {} wants {} pages, but VAG DMA sizes limit us to ",
|
||||
m_FileDef->name.data, page_alloc_count, limit);
|
||||
lg::info("page count dma limit {} -> {}\n", page_alloc_count, limit);
|
||||
page_alloc_count = limit;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED(); // bad buffer type.
|
||||
}
|
||||
|
||||
if (page_alloc_count == 0) {
|
||||
return ret_plist;
|
||||
}
|
||||
|
||||
ovrld_log(LogCategory::PAGING, "File {} wants {} more pages in AllocPages.", m_FileDef->name.data,
|
||||
page_alloc_count);
|
||||
if (have_plist) {
|
||||
ret_plist = get_page_manager()->GrowPageList(m_Buffer.m_pPageList, page_alloc_count);
|
||||
} else {
|
||||
ret_plist = get_page_manager()->AllocPageList(page_alloc_count, 0);
|
||||
}
|
||||
|
||||
if (ret_plist) {
|
||||
m_Buffer.m_pPageList = ret_plist;
|
||||
if (!have_plist) {
|
||||
m_Buffer.m_pCurrentData = ret_plist->m_pFirstPage->m_pPageMemStart;
|
||||
}
|
||||
} else {
|
||||
ASSERT_NOT_REACHED(); // might be ok.
|
||||
}
|
||||
return ret_plist;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Free all pages and the page list.
|
||||
*/
|
||||
void CBaseFile::FreePages() {
|
||||
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
|
||||
if (m_Buffer.m_pPageList) {
|
||||
get_page_manager()->FreePageList(m_Buffer.m_pPageList);
|
||||
}
|
||||
m_Buffer.m_pPageList = nullptr;
|
||||
}
|
||||
|
||||
} // namespace jak3
|
||||
@@ -0,0 +1,76 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
#include "game/overlord/jak3/pagemanager.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_basefile();
|
||||
|
||||
struct CPageList;
|
||||
struct ISOFileDef;
|
||||
struct ISO_Hdr;
|
||||
|
||||
constexpr int kDefaultBufferPageCount = 4;
|
||||
|
||||
/*!
|
||||
* Base class for a file that the ISO system is processing.
|
||||
* This represents an "open" file, and contains references to the buffer holding this file's data
|
||||
*/
|
||||
struct CBaseFile {
|
||||
CBaseFile();
|
||||
CBaseFile(const ISOFileDef* file, int semaphore);
|
||||
virtual ~CBaseFile() = default;
|
||||
|
||||
uint8_t* CheckPageBoundary();
|
||||
int InitBuffer(CBuffer::BufferType type, ISO_Hdr* msg);
|
||||
CPageList* AllocPages();
|
||||
void TerminateBuffer();
|
||||
void FreePages();
|
||||
|
||||
// buffer that stores some contents of this file
|
||||
CBuffer m_Buffer;
|
||||
|
||||
// the number of pages that were allocated for reading this file.
|
||||
u32 m_nNumPages;
|
||||
|
||||
// Metadata about the file
|
||||
const ISOFileDef* m_FileDef;
|
||||
|
||||
// The compression format used on the file
|
||||
enum class Kind {
|
||||
UNKNOWN = 0,
|
||||
NORMAL = 1,
|
||||
LZO_COMPRESSED = 2,
|
||||
} m_FileKind = Kind::UNKNOWN;
|
||||
|
||||
EIsoStatus m_Status = EIsoStatus::NONE_0;
|
||||
|
||||
// The expected read rate for streaming, used to prioritize CD reads. Can be 0 if unknown/not
|
||||
// applicable.
|
||||
int m_ReadRate = 0;
|
||||
|
||||
// Number of sectors that we should read in total, decided based on the file size and request from
|
||||
// user when they opened this file.
|
||||
int m_LengthPages = 0; // really, in pages...
|
||||
|
||||
// The current offset. (todo: is this for data we read, processed?)
|
||||
int m_PageOffset = 0;
|
||||
|
||||
// Semaphore that we should wait on before handing new data to the process callback.
|
||||
// Set to -1 if there is no semaphore.
|
||||
// (this is a bit of hack, only used for VAG streaming).
|
||||
int m_ProcessDataSemaphore = 0;
|
||||
|
||||
// virtual methods
|
||||
virtual EIsoStatus BeginRead() = 0;
|
||||
virtual EIsoStatus SyncRead() = 0;
|
||||
virtual void Close() = 0;
|
||||
virtual int RecoverPages(int num_pages) = 0;
|
||||
virtual int GetSector() = 0;
|
||||
// ??
|
||||
// ??
|
||||
// ??
|
||||
};
|
||||
} // namespace jak3
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "basefilesystem.h"
|
||||
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "game/sce/iop.h"
|
||||
|
||||
using namespace iop;
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_basefilesystem() {}
|
||||
|
||||
CBaseFileSystem::CBaseFileSystem() {
|
||||
for (auto& sema : m_Sema) {
|
||||
sema = -1;
|
||||
|
||||
SemaParam param;
|
||||
param.max_count = 1;
|
||||
param.attr = 0;
|
||||
param.init_count = 1;
|
||||
param.option = 0;
|
||||
sema = CreateSema(¶m);
|
||||
if (sema < 0) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace jak3
|
||||
Loaded 100 of 621 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user