mirror of
https://github.com/open-goal/jak-project.git
synced 2026-11-09 03:59:49 -10:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55204e6996 | ||
|
|
b2cfefb669 | ||
|
|
bc586f0cca | ||
|
|
13e7a28c08 | ||
|
|
17665a4615 | ||
|
|
d209766078 |
No files matched your search
@@ -58,11 +58,6 @@ 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,6 +145,7 @@
|
||||
"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() const {
|
||||
std::string DmaTag::print() {
|
||||
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() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string VifCode::print() const {
|
||||
std::string VifCode::print() {
|
||||
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() const;
|
||||
std::string print();
|
||||
};
|
||||
|
||||
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() const;
|
||||
std::string print();
|
||||
};
|
||||
|
||||
struct VifCodeStcycl {
|
||||
|
||||
@@ -240,7 +240,6 @@ 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,8 +26,6 @@ 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() {
|
||||
@@ -36,12 +34,12 @@ u64 get_current_ts() {
|
||||
|
||||
GlobalProfiler::GlobalProfiler() {
|
||||
m_t0 = get_current_ts();
|
||||
m_nodes.resize(m_max_events);
|
||||
set_max_events(65536);
|
||||
}
|
||||
|
||||
void GlobalProfiler::update_event_buffer_size(size_t new_size) {
|
||||
m_max_events = new_size;
|
||||
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::set_waiting_for_event(const std::string& event_name) {
|
||||
@@ -74,10 +72,6 @@ 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);
|
||||
}
|
||||
@@ -102,10 +96,8 @@ void GlobalProfiler::set_enable(bool en) {
|
||||
m_enabled = en;
|
||||
}
|
||||
|
||||
void GlobalProfiler::dump_to_json() {
|
||||
if (m_enabled) {
|
||||
set_enable(false);
|
||||
}
|
||||
void GlobalProfiler::dump_to_json(const std::string& path) {
|
||||
ASSERT(!m_enabled);
|
||||
|
||||
nlohmann::json json;
|
||||
auto& trace_events = json["traceEvents"];
|
||||
@@ -193,20 +185,7 @@ void GlobalProfiler::dump_to_json() {
|
||||
t.second.highest_at_target);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
file_util::write_text_file(path, json.dump());
|
||||
}
|
||||
|
||||
GlobalProfiler gprof;
|
||||
|
||||
@@ -17,8 +17,7 @@ struct ProfNode {
|
||||
class GlobalProfiler {
|
||||
public:
|
||||
GlobalProfiler();
|
||||
size_t get_max_events() { return m_max_events; }
|
||||
void update_event_buffer_size(size_t new_size);
|
||||
void set_max_events(size_t event_count);
|
||||
void set_waiting_for_event(const std::string& event_name);
|
||||
void instant_event(const char* name);
|
||||
void begin_event(const char* name);
|
||||
@@ -26,16 +25,11 @@ class GlobalProfiler {
|
||||
void end_event();
|
||||
void clear();
|
||||
void set_enable(bool en);
|
||||
void dump_to_json();
|
||||
void dump_to_json(const std::string& path);
|
||||
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,11 +29,8 @@ 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,151 +43,7 @@ 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",
|
||||
"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",
|
||||
"skull-gem-dest", "jakc-arm", "jakc-eyebrow", "jakc-face", "jakc-finger", "jakc-hair",
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -46,17 +46,4 @@ 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,5 +8,4 @@ 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);
|
||||
std::vector<u8> compress_zstd_no_header(const void* data, size_t size);
|
||||
} // namespace compression
|
||||
} // namespace compression
|
||||
@@ -1,19 +0,0 @@
|
||||
#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& j,
|
||||
void json_get_optional(const nlohmann::json& json,
|
||||
const std::string& key,
|
||||
std::optional<T>& optionalValue) {
|
||||
if (j.contains(key) && !j[key].is_null()) {
|
||||
optionalValue = j[key].get<T>();
|
||||
if (json.contains(key) && !json[key].is_null()) {
|
||||
optionalValue = json[key].get<T>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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/custom_levels" 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" 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,7 +68,6 @@ 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -54,8 +54,12 @@ 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()) {
|
||||
initial_top_level_forms.push_back(
|
||||
goos::StringObject::make_new(fix_docstring_indent(inline_body.at(0).as_string()->data)));
|
||||
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));
|
||||
}
|
||||
body_elements.erase(body_elements.begin());
|
||||
}
|
||||
|
||||
|
||||
@@ -21102,7 +21102,7 @@
|
||||
:size-assert #x94
|
||||
:flag-assert #xf00300094
|
||||
(:methods
|
||||
(spawn-particles! (_type_) none))
|
||||
(dumb-15 (_type_) none))
|
||||
(:states
|
||||
hud-normal
|
||||
hud-coming-in
|
||||
|
||||
@@ -2515,7 +2515,6 @@
|
||||
(iop-mem 48)
|
||||
(cancel-dgo 49)
|
||||
(set-stereo-mode 50) ;; sound-rpc-set-stereo-mode
|
||||
(set-mirror 201)
|
||||
)
|
||||
|
||||
(defenum sound-group
|
||||
@@ -2830,17 +2829,6 @@
|
||||
: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)
|
||||
@@ -2864,7 +2852,6 @@
|
||||
(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
|
||||
@@ -8787,7 +8774,6 @@ 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
|
||||
|
||||
|
||||
+108
-177
@@ -15147,8 +15147,8 @@
|
||||
:size-assert #x4
|
||||
:flag-assert #xb00000004
|
||||
(:methods
|
||||
(update! (_type_) int) ;; 9
|
||||
(setup-from-params! (_type_ cloth-params handle) int) ;; 10
|
||||
(init! (_type_) int) ;; 9
|
||||
(cloth-base-method-10 (_type_ cloth-params handle) int) ;; 10
|
||||
)
|
||||
)
|
||||
|
||||
@@ -25908,33 +25908,8 @@
|
||||
: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 object :offset-assert 4) ;; guessed by decompiler
|
||||
((ptype type :offset-assert 4) ;; guessed by decompiler
|
||||
(pool symbol :offset-assert 8) ;; guessed by decompiler
|
||||
(heap-size int32 :offset-assert 12)
|
||||
)
|
||||
@@ -33975,7 +33950,7 @@
|
||||
)
|
||||
|
||||
(deftype particle-array (inline-array-class)
|
||||
((data verlet-particle :dynamic :inline :offset-assert 16 :score 1)
|
||||
((data verlet-particle :dynamic :inline :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 14
|
||||
:size-assert #x10
|
||||
@@ -34042,12 +34017,12 @@
|
||||
:size-assert #x40
|
||||
:flag-assert #x1000000040
|
||||
(:methods
|
||||
(accumulate-external-forces!
|
||||
(calculate-wind!
|
||||
"If this cloth system has the wind flag, calculate the wind force."
|
||||
(_type_) none) ;; 11
|
||||
(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
|
||||
(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
|
||||
(debug-draw (_type_) none) ;; 15
|
||||
)
|
||||
)
|
||||
@@ -34107,9 +34082,9 @@
|
||||
"Set up this cloth system with the given [[cloth-params]]."
|
||||
(_type_ cloth-params) none) ;; 16
|
||||
(debug-draw-spheres (_type_) none) ;; 17
|
||||
(post-physics-update (_type_) int) ;; 18
|
||||
(enforce-constraints-1 (_type_) none) ;; 19
|
||||
(enforce-constraints-2 (_type_) none) ;; 20
|
||||
(cloth-system-method-18 (_type_) int) ;; 18
|
||||
(cloth-system-method-19 (_type_) none) ;; 19
|
||||
(cloth-system-method-20 (_type_) none) ;; 20
|
||||
(cloth-system-method-21 (_type_) none) ;; 21
|
||||
(cloth-system-method-22 (_type_) none) ;; 22
|
||||
(cloth-system-method-23 (_type_) none) ;; 23
|
||||
@@ -34123,9 +34098,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
|
||||
(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-method-34 (_type_) none) ;; 34
|
||||
(cloth-system-method-35 (_type_) none) ;; 35
|
||||
(cloth-system-method-36 (_type_) none) ;; 36
|
||||
(cloth-system-cmd-handler (_type_ pair) none) ;; 37
|
||||
)
|
||||
)
|
||||
@@ -34147,8 +34122,8 @@
|
||||
;; cloth ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern get-neighboring-faces (function vector4w int int int int int))
|
||||
(define-extern *normal-array* (inline-array vector))
|
||||
(define-extern get-neighboring-faces (function vector int int int int int))
|
||||
(define-extern *normal-array* (pointer vector))
|
||||
(define-extern light-vertex (function current-position-info vector rgba))
|
||||
(define-extern *once* symbol)
|
||||
(define-extern *cloth-fade-alpha* gs-alpha)
|
||||
@@ -34221,17 +34196,7 @@
|
||||
;; 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)
|
||||
@@ -34243,7 +34208,6 @@
|
||||
)
|
||||
|
||||
(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
|
||||
@@ -34252,50 +34216,39 @@
|
||||
)
|
||||
|
||||
(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
|
||||
(evaluate "Compute value of curve at the given position." (_type_ float loop-behavior) float) ;; 9
|
||||
(curve2d-method-9 (_type_ float int) 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
|
||||
(evaluate "Compute value of curve at the given position." (_type_ float rgbaf loop-behavior) rgbaf) ;; 9
|
||||
(curve-color-method-9 (_type_ float rgbaf int) 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 loop-behavior :offset-assert 8)
|
||||
(default-loop-behavior uint64 :offset-assert 8)
|
||||
)
|
||||
:method-count-assert 12
|
||||
:size-assert #x10
|
||||
:flag-assert #xc00000010
|
||||
(:methods
|
||||
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
|
||||
(curve2d-piecewise-method-10 (_type_ int symbol int) 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)
|
||||
@@ -34306,9 +34259,6 @@
|
||||
)
|
||||
|
||||
(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)
|
||||
@@ -34319,8 +34269,6 @@
|
||||
)
|
||||
|
||||
(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)
|
||||
@@ -34332,7 +34280,6 @@
|
||||
)
|
||||
|
||||
(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
|
||||
@@ -34341,22 +34288,21 @@
|
||||
)
|
||||
|
||||
(deftype curve-color-piecewise (curve-color)
|
||||
"Implementation of curve-color."
|
||||
((pts color-pair-array :offset-assert 4)
|
||||
(default-loop-behavior loop-behavior :offset-assert 8)
|
||||
(default-loop-behavior uint64 :offset-assert 8)
|
||||
)
|
||||
:method-count-assert 11
|
||||
:size-assert #x10
|
||||
:flag-assert #xb00000010
|
||||
(:methods
|
||||
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
|
||||
(curve-color-piecewise-method-10 (_type_ int symbol uint) none) ;; 10
|
||||
)
|
||||
)
|
||||
|
||||
(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 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 *curve-unity* curve2d-fast)
|
||||
(define-extern *curve-linear-up* curve2d-fast)
|
||||
(define-extern *curve-linear-down* curve2d-fast)
|
||||
@@ -34733,14 +34679,6 @@
|
||||
: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)
|
||||
@@ -34758,8 +34696,8 @@
|
||||
(uv-mode uint64 :offset-assert 72)
|
||||
(uv-repeat-dist float :offset-assert 80)
|
||||
(max-age time-frame :offset-assert 88)
|
||||
(tex-id texture-id :offset-assert 96)
|
||||
(lie-mode lie-mode :offset-assert 104)
|
||||
(tex-id uint32 :offset-assert 96)
|
||||
(lie-mode uint64 :offset-assert 104)
|
||||
(lie-vector vector :inline :offset-assert 112)
|
||||
(zbuffer? symbol :offset-assert 128)
|
||||
(use-tape-mode? symbol :offset-assert 132)
|
||||
@@ -34773,7 +34711,7 @@
|
||||
|
||||
(deftype light-trail-breadcrumb (structure)
|
||||
((pos vector :inline :offset-assert 0)
|
||||
(birth-time uint32 :offset 12 :decomp-as time-frame :score 1)
|
||||
(birth-time uint32 :offset 12 :decomp-as time-frame)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x10
|
||||
@@ -34788,22 +34726,15 @@
|
||||
:flag-assert #xe00000010
|
||||
)
|
||||
|
||||
(defenum light-trail-decision
|
||||
:type uint64
|
||||
(added 0)
|
||||
(not-added 1)
|
||||
(reset 2)
|
||||
)
|
||||
|
||||
(deftype light-trail (basic)
|
||||
((crumb-array (array uint8) :offset-assert 4)
|
||||
((crumb-array (array light-trail-breadcrumb) :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 light-trail-decision :offset-assert 40)
|
||||
(decision uint64 :offset-assert 40)
|
||||
(total-distance-traveled float :offset-assert 48)
|
||||
(strip prim-strip :offset-assert 52)
|
||||
(strip2 prim-strip :offset-assert 56)
|
||||
@@ -34813,19 +34744,19 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1600000080
|
||||
(:methods
|
||||
(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-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
|
||||
(light-trail-method-15 (_type_) none) ;; 15
|
||||
(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
|
||||
(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
|
||||
(reset-crumbs! (_type_) none) ;; 20
|
||||
(replace-last-crumb! "Similar to add-crumb, but will modify the last crumb instead of advancing." (_type_ vector) none) ;; 21
|
||||
(light-trail-method-21 (_type_ vector) none) ;; 21
|
||||
)
|
||||
)
|
||||
|
||||
@@ -34843,7 +34774,7 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(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-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
|
||||
(weapon-trail-method-23 (_type_ vector vector) none) ;; 23
|
||||
)
|
||||
)
|
||||
@@ -34862,8 +34793,8 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(add-crumb-with-offset (_type_ vector vector) none) ;; 22
|
||||
(tread-trail-method-23 (_type_ vector vector) none) ;; 23
|
||||
(tread-trail-method-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
|
||||
(tread-trail-method-23 (_type_ vector vector) light-trail-breadcrumb) ;; 23
|
||||
)
|
||||
)
|
||||
|
||||
@@ -34903,11 +34834,11 @@
|
||||
die ;; 15
|
||||
)
|
||||
(:methods
|
||||
(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
|
||||
(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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -42848,7 +42779,7 @@
|
||||
:size-assert #xfc
|
||||
:flag-assert #x22008000fc
|
||||
(:methods
|
||||
(get-mgr-name (_type_) string) ;; 32
|
||||
(task-manager-desert-bbush-ring-method-32 (_type_) none) ;; 32
|
||||
(task-manager-desert-bbush-ring-method-33 (_type_) none) ;; 33
|
||||
)
|
||||
)
|
||||
@@ -44565,12 +44496,12 @@
|
||||
;; templea-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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))
|
||||
;; (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)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; hover-training ;;
|
||||
@@ -46353,16 +46284,16 @@
|
||||
;; sewer-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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))
|
||||
;; (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)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; kg-hopper ;;
|
||||
@@ -50356,7 +50287,7 @@
|
||||
;; desresc-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *desresc-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *desresc-warp-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; desert-rescue ;;
|
||||
@@ -51053,7 +50984,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 texture-anim))
|
||||
(define-extern *ctyslumb-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; mech-part ;;
|
||||
@@ -51159,7 +51090,7 @@
|
||||
;; nstb-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *nstb-quicksand-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *nstb-quicksand-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; nst-mood ;;
|
||||
@@ -51802,7 +51733,7 @@
|
||||
)
|
||||
)
|
||||
|
||||
(define-extern *ctyslumc-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *ctyslumc-water-texture-anim-array* texture-anim-array)
|
||||
(define-extern ctyslumc-flag-init-by-other (function vector entity-actor object :behavior ctyslumc-flag))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -51977,8 +51908,8 @@
|
||||
;; factoryc-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *factoryc-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern set-facc-conveyor-speed! (function float float))
|
||||
;; (define-extern *factoryc-alpha-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern set-facc-conveyor-speed! function)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; conveyor ;;
|
||||
@@ -52627,7 +52558,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 texture-anim texture-anim none))
|
||||
(define-extern wang-texture-anim-func (function none))
|
||||
(define-extern *hfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -54251,7 +54182,7 @@
|
||||
;; glider-ring-part ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *hanga-sprite-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *hanga-sprite-texture-anim-array* texture-anim-array)
|
||||
(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))
|
||||
@@ -54454,7 +54385,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 texture-anim))
|
||||
(define-extern *hanga-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; elec-gate ;;
|
||||
@@ -57106,7 +57037,7 @@
|
||||
;; desertd-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *desertd-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *desertd-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctyfarm-obs ;;
|
||||
@@ -57930,7 +57861,7 @@
|
||||
|
||||
(deftype tire-trail-crumb (light-trail-breadcrumb)
|
||||
((offset vector :inline :offset-assert 16)
|
||||
(uu float :offset 28 :score 1)
|
||||
(uu float :offset 28)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
@@ -57943,13 +57874,13 @@
|
||||
:size-assert #x80
|
||||
:flag-assert #x1800000080
|
||||
(:methods
|
||||
(add-crumb-with-offset-and-uu (_type_ vector vector float) none) ;; 22
|
||||
(tire-trail-method-23 (_type_ vector vector float) none) ;; 23
|
||||
(tire-trail-method-22 (_type_) none) ;; 22
|
||||
(tire-trail-method-23 (_type_) none) ;; 23
|
||||
)
|
||||
)
|
||||
|
||||
(deftype tire-trail-tracker (light-trail-tracker)
|
||||
((trail tire-trail :override))
|
||||
()
|
||||
:method-count-assert 21
|
||||
:size-assert #xac
|
||||
:flag-assert #x15003000ac
|
||||
@@ -60350,7 +60281,7 @@
|
||||
;; mhcityb-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *lmhcityb-tfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *lmhcityb-tfrag-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; rublcst-scenes ;;
|
||||
@@ -61360,7 +61291,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 texture-anim))
|
||||
(define-extern *towerb-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; tower-scenes ;;
|
||||
@@ -63400,7 +63331,7 @@
|
||||
;; wasstada-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *wasstada-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *wasstada-alpha-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; wasstada-mood ;;
|
||||
@@ -63424,7 +63355,7 @@
|
||||
;; factorya-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *factoryb-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *factoryb-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; factoryb-init ;;
|
||||
@@ -63436,9 +63367,9 @@
|
||||
;; mhcitya-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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))
|
||||
;; (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)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctyinda-part ;;
|
||||
@@ -63746,10 +63677,10 @@
|
||||
;; rubble-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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))
|
||||
;; (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)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; stadiuma-part ;;
|
||||
@@ -65220,9 +65151,9 @@
|
||||
;; forest-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(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))
|
||||
;; (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)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; forest-ring-chase ;;
|
||||
@@ -65479,8 +65410,8 @@
|
||||
;; ltnfxhip-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *ltnfxhip-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern ltnfxhip-texture-anim-func (function none))
|
||||
;; (define-extern *ltnfxhip-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern ltnfxhip-texture-anim-func function)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ctygenb-part ;;
|
||||
@@ -67881,7 +67812,7 @@
|
||||
;; gungame-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *lgunnorm-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *lgunnorm-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; gungame-obs ;;
|
||||
@@ -68161,8 +68092,8 @@
|
||||
;; ljkdxvin-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *ljkdxvin-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern ljkdxvin-texture-anim-func (function none))
|
||||
;; (define-extern *ljkdxvin-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern ljkdxvin-texture-anim-func function)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; target-tube ;;
|
||||
@@ -71558,7 +71489,7 @@
|
||||
;; waspal-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *waspal-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *waspal-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; throne-scenes ;;
|
||||
@@ -72734,7 +72665,7 @@
|
||||
;; mined-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *mined-tfrag-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern *mined-tfrag-texture-anim-array* texture-anim-array)
|
||||
(define-extern set-mined-pillar-texture! (function float none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -73120,8 +73051,8 @@
|
||||
;; volcanox-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *volcanox-warp-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern volcanox-warp-texture-anim-func (function none))
|
||||
;; (define-extern *volcanox-warp-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern volcanox-warp-texture-anim-func function)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; volcanox-mood ;;
|
||||
@@ -73321,7 +73252,7 @@
|
||||
;; templex-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *templex-water-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *templex-water-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; templex-scenes ;;
|
||||
@@ -73704,7 +73635,7 @@
|
||||
;; volcano-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *volcanoa-alpha-texture-anim-array* (texture-anim-array texture-anim))
|
||||
;; (define-extern *volcanoa-alpha-texture-anim-array* texture-anim-array)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; spiky-frog ;;
|
||||
@@ -74417,8 +74348,8 @@
|
||||
;; deshover-texture ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define-extern *deshover-texture-anim-array* (texture-anim-array texture-anim))
|
||||
(define-extern deshover-texture-anim-func (function none))
|
||||
;; (define-extern *deshover-texture-anim-array* texture-anim-array)
|
||||
;; (define-extern deshover-texture-anim-func function)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; terraformer-head ;;
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
[7, "(function none)"],
|
||||
[3, "(function symbol :behavior process)"]
|
||||
],
|
||||
"scene": [[4, "(function symbol :behavior scene-player)"]],
|
||||
"scene": [[4, "(function none :behavior scene-player)"]],
|
||||
"pov-camera": [
|
||||
[
|
||||
7,
|
||||
|
||||
@@ -361,315 +361,11 @@
|
||||
"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",
|
||||
|
||||
// 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"
|
||||
"skull-gem-alpha-02"
|
||||
],
|
||||
|
||||
"levels_to_extract": [
|
||||
|
||||
@@ -1850,8 +1850,6 @@
|
||||
["_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"]],
|
||||
@@ -2685,13 +2683,8 @@
|
||||
[[21, 25], "a0", "prim-strip"]
|
||||
],
|
||||
"(event tracking light-trail-tracker)": [[55, "v1", "float"]],
|
||||
"(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"]
|
||||
],
|
||||
"(method 21 light-trail)": [[50, "v1", "light-trail-breadcrumb"]],
|
||||
"(method 14 light-trail)": [[47, "a0", "uint"]],
|
||||
"debug-menu-item-var-update-display-str": [
|
||||
[48, "v1", "int"],
|
||||
[63, "v1", "int"],
|
||||
@@ -2742,12 +2735,16 @@
|
||||
[27, "gp", "process-drawable"],
|
||||
[30, "gp", "process-drawable"]
|
||||
],
|
||||
"(method 23 weapon-trail)": [[[0, 100], "gp", "weapon-trail-crumb"]],
|
||||
"(method 23 weapon-trail)": [
|
||||
[62, "v1", "light-trail-breadcrumb"],
|
||||
[65, "v1", "light-trail-breadcrumb"]
|
||||
],
|
||||
"(method 22 weapon-trail)": [[32, "v0", "light-trail-breadcrumb"]],
|
||||
"(method 22 tread-trail)": [[19, "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"]],
|
||||
"(method 23 tread-trail)": [
|
||||
[51, "v1", "light-trail-breadcrumb"],
|
||||
[67, "v0", "light-trail-breadcrumb"]
|
||||
],
|
||||
"(trans idle fma-sphere)": [[39, "a2", "process-drawable"]],
|
||||
"part-water-splash-callback": [[3, "v1", "float"]],
|
||||
"(method 15 water-control)": [[48, "v1", "float"]],
|
||||
@@ -6431,11 +6428,11 @@
|
||||
],
|
||||
"cshape-reaction-scorp-shot": [[15, "v1", "v-scorp-shot"]],
|
||||
"(method 78 wvehicle)": [
|
||||
[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"],
|
||||
[262, "s1", "process-focusable"],
|
||||
[271, "s1", "process-focusable"],
|
||||
[287, "s1", "process-focusable"],
|
||||
[309, "s1", "process-focusable"],
|
||||
[322, "s1", "process-focusable"],
|
||||
[358, "v1", "collide-shape-prim-group"]
|
||||
],
|
||||
"(method 97 wvehicle)": [
|
||||
@@ -6554,10 +6551,7 @@
|
||||
[15, "v1", "process-drawable"],
|
||||
[22, "v1", "process-drawable"]
|
||||
],
|
||||
"(method 19 tire-trail)": [
|
||||
[[5, 28], "s5", "tire-trail-crumb"],
|
||||
[[5, 28], "s4", "tire-trail-crumb"]
|
||||
],
|
||||
"(method 19 tire-trail)": [],
|
||||
"vehicle-spawn": [[93, "gp", "vehicle"]],
|
||||
"vehicle-spawn-hack": [[41, "gp", "vehicle"]],
|
||||
"(method 11 w-parking-spot)": [[42, "v0", "vector"]],
|
||||
|
||||
@@ -515,44 +515,8 @@ TPageResultStats process_tpage(ObjectFileData& data,
|
||||
// currently not needed.
|
||||
break;
|
||||
case int(PSM::PSMT8):
|
||||
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) {
|
||||
ASSERT(tex.clutpsm == int(CPSM::PSMCT32));
|
||||
{
|
||||
// will store output pixels, index (u8)
|
||||
std::vector<u8> index_out;
|
||||
|
||||
@@ -591,12 +555,10 @@ 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 {} clut {}\n", tex.name, tex.psm, tex.clutpsm);
|
||||
lg::die("Animated texture {} format {}\n", tex.name, tex.psm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -322,8 +322,7 @@ 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" /
|
||||
game_version_names[config.game_version] / "common.glb";
|
||||
auto file_path = file_util::get_jak_project_dir() / "glb_out" / "common.glb";
|
||||
file_util::create_dir_if_needed_for_file(file_path);
|
||||
save_level_foreground_as_gltf(tfrag_level, art_group_data, file_path);
|
||||
}
|
||||
@@ -361,17 +360,15 @@ void extract_from_level(const ObjectFileDB& db,
|
||||
|
||||
if (config.rip_levels) {
|
||||
auto back_file_path = file_util::get_jak_project_dir() / "glb_out" /
|
||||
game_version_names[config.game_version] /
|
||||
fmt::format("{}-background.glb", level_data.level_name);
|
||||
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" /
|
||||
game_version_names[config.game_version] /
|
||||
fmt::format("{}-foreground.glb", level_data.level_name);
|
||||
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,7 +1,5 @@
|
||||
#include "extract_merc.h"
|
||||
|
||||
#include "merc_replacement.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/BitUtils.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
@@ -1599,60 +1597,6 @@ 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
|
||||
*/
|
||||
@@ -1787,33 +1731,5 @@ 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
|
||||
@@ -1,211 +0,0 @@
|
||||
#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
|
||||
@@ -1,32 +0,0 @@
|
||||
#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
|
||||
@@ -2576,6 +2576,7 @@ 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,7 +201,6 @@ 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
|
||||
@@ -255,29 +254,6 @@ 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,11 +54,4 @@
|
||||
: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,8 +21,7 @@
|
||||
(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"
|
||||
"game/assets/jak2/text/game_base_text_fi-FI.json"))
|
||||
(file-json 9 jak2 "common" '("game/assets/jak2/text/game_custom_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,7 +1,6 @@
|
||||
{
|
||||
"1a3": "138",
|
||||
"1b5": "161",
|
||||
"133a": "1113",
|
||||
"1200": "1031",
|
||||
"1201": "1032",
|
||||
"1202": "1034",
|
||||
|
||||
@@ -1,531 +0,0 @@
|
||||
{
|
||||
"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,6 +232,5 @@
|
||||
"1336": "Fast Progress Menu",
|
||||
"1337": "PS2 LOD Distance",
|
||||
"1338": "Off",
|
||||
"1339": "Display",
|
||||
"133a": "Suomi"
|
||||
"1339": "Display"
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
"1101": "Pelataan bonustehtävää",
|
||||
"1102": "Haulikon harjoitusrata",
|
||||
"1103": "Läjäyttimen harjoitusrata",
|
||||
"1104": "Vulkanus-tykin harjoitusrata",
|
||||
"1104": "Vulkanusraivon 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": "Vahvista ja poistu painamalla <PAD_X>.",
|
||||
"120a": "Vahvista ja poistu painamalla <PAD_CIRCLE>.",
|
||||
"1209": "Paina <PAD_X> vahvistaaksesi ja poistuaksesi.",
|
||||
"120a": "Paina <PAD_CIRCLE> vahvistaaksesi ja poistuaksesi.",
|
||||
"120b": "Kuvasuhde ei saa olla pienempi kuin 4x3!",
|
||||
"120c": "Musiikkisoitin",
|
||||
"120d": "Pystytahdistus",
|
||||
@@ -34,7 +34,7 @@
|
||||
"1216": "Muuntoase",
|
||||
"1217": "JET-lauta",
|
||||
"1218": "Titaaniasu",
|
||||
"1219": "Raivo-Jak",
|
||||
"1219": "Pimeä 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 autom. tallennus",
|
||||
"124e": "Autom. tallennus pois",
|
||||
"124d": "Lopeta auto-tallennus",
|
||||
"124e": "Auto-tallennus pois päältä",
|
||||
"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älinäytökset",
|
||||
"1259": "Hitaat välinäytökset",
|
||||
"1258": "Nopeat välianimaatiot",
|
||||
"1259": "Hitaat välianimaatiot",
|
||||
"125a": "Nopea pelattavuus",
|
||||
"125b": "Hidas pelattavuus",
|
||||
"125c": "Pikamatkustus Haven Cityssä",
|
||||
"125d": "Edeltäjähelmien seuranta",
|
||||
"125e": "Todellinen vuorokaudenaika",
|
||||
"125e": "Todellinen vuorokauden aika",
|
||||
"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 (1. persoona)",
|
||||
"1282": "Ylös/alas (1. persoona)",
|
||||
"1283": "Vasen/oikea (3. persoona)",
|
||||
"1284": "Ylös/alas (3. persoona)",
|
||||
"1281": "Vasen/oikea (ensimmäinen persoona)",
|
||||
"1282": "Ylös/alas (ensimmäinen persoona)",
|
||||
"1283": "Vasen/oikea (kolmas persoona)",
|
||||
"1284": "Ylös/alas (kolmas persoona)",
|
||||
"1285": "Palauta oletukset",
|
||||
"1286": "Normaali",
|
||||
"1287": "Käänteinen",
|
||||
@@ -137,15 +137,15 @@
|
||||
"1293": "Ohjainasetukset",
|
||||
"1294": "Valitse ohjain",
|
||||
"1295": "Analogisauvan katvealue",
|
||||
"1296": "Älä huomioi työpöydällä",
|
||||
"1296": "Älä huomioi, kun ikkuna ei aktiivinen",
|
||||
"1297": "Ohjaimen LED terveydelle",
|
||||
"1298": "Ohjaimen LED muihin tiloihin",
|
||||
"1299": "Salli näppäimistö",
|
||||
"129a": "Salli hiiri",
|
||||
"129b": "Hiiriasetukset",
|
||||
"129c": "Kameran ohjaus hiirellä",
|
||||
"129d": "Herkkyys (vaakasuunta)",
|
||||
"129e": "Herkkyys (pystysuunta)",
|
||||
"129d": "Vaakasuuntainen herkkyys",
|
||||
"129e": "Pystysuuntainen herkkyys",
|
||||
"129f": "Pelaajan ohjaus hiirellä",
|
||||
"12a0": "Objektien varjot",
|
||||
"12a1": "Normaali",
|
||||
@@ -156,25 +156,25 @@
|
||||
"12a6": "Muut tilastot",
|
||||
"12a7": "Tappoja yhteensä",
|
||||
"12a8": "Jakin tappamia",
|
||||
"12a9": "Raivo-Jakin tappamia",
|
||||
"12a9": "Pimeän Jakin tappamia",
|
||||
"12aa": "Daxterin tappamia",
|
||||
"12ab": "Muiden tappamia",
|
||||
"12ac": "Läjäytin",
|
||||
"12ad": "Haulikko",
|
||||
"12ae": "Vulkanus-tykki",
|
||||
"12ae": "Vulkanusraivo",
|
||||
"12af": "Rauhantekijä",
|
||||
"12b0": "JET-lauta",
|
||||
"12b1": "JET-lauta-temppu",
|
||||
"12b1": "JET-lautatemppu",
|
||||
"12b2": "Titaaniasun isku",
|
||||
"12b3": "Titaaniasun runko",
|
||||
"12b4": "Tykki",
|
||||
"12b5": "Isku",
|
||||
"12b6": "Maaisku",
|
||||
"12b6": "Lyyhistyi",
|
||||
"12b7": "Kohokoukku",
|
||||
"12b8": "Pyörähdys",
|
||||
"12b9": "Kierintä",
|
||||
"12bf": "Raivopommi",
|
||||
"12c0": "Raivopurkaus",
|
||||
"12bf": "Pimeä pommi",
|
||||
"12c0": "Pimeä purkaus",
|
||||
"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": "Pyörähdys",
|
||||
"1322": "Nopeuslisä",
|
||||
"1321": "Spin",
|
||||
"1322": "Buusti",
|
||||
"1323": "Voltti",
|
||||
"1324": "Kaideliuku",
|
||||
"1325": "Kaidehyppy",
|
||||
"1326": "Nosegrab",
|
||||
"1327": "Method",
|
||||
"1328": "Lautapyörähdys",
|
||||
"1329": "Lautavoltti",
|
||||
"1328": "Board Spin",
|
||||
"1329": "Board Flip",
|
||||
"132a": "Noseflip",
|
||||
"132b": "Kickflip",
|
||||
"132c": "Hyppy",
|
||||
"132d": "Kyykkyhyppy",
|
||||
"132e": "Pikahyppy",
|
||||
"132f": "Raivo-Jak",
|
||||
"1330": "Raivopommi",
|
||||
"1331": "Raivopurkaus",
|
||||
"1332": "Raivojätti",
|
||||
"132f": "Pimeä Jak",
|
||||
"1330": "Pimeä pommi",
|
||||
"1331": "Pimeä purkaus",
|
||||
"1332": "Pimeä jä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 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,
|
||||
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,
|
||||
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,7 +873,6 @@ 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,
|
||||
@@ -1081,7 +1080,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,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,
|
||||
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,
|
||||
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,
|
||||
@@ -1091,7 +1090,6 @@ 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,
|
||||
@@ -1390,7 +1388,6 @@ 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,
|
||||
@@ -1468,7 +1465,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 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,
|
||||
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,
|
||||
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,
|
||||
@@ -1690,7 +1687,6 @@ 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,
|
||||
@@ -1698,8 +1694,7 @@ 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: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,
|
||||
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,
|
||||
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,3 +31,19 @@ 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,10 +3,6 @@
|
||||
#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), version(_version) {}
|
||||
GameVersion version)
|
||||
: shaders(version), texture_pool(_texture_pool), loader(_loader) {}
|
||||
ShaderLibrary shaders;
|
||||
std::shared_ptr<TexturePool> texture_pool;
|
||||
std::shared_ptr<Loader> loader;
|
||||
@@ -98,7 +98,6 @@ 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; }
|
||||
@@ -159,4 +158,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,7 +579,6 @@ 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, &dma.data[32], 8);
|
||||
memcpy(&result.uv0[0], &dma.data[32], 8);
|
||||
|
||||
// xyz0
|
||||
memcpy(&result.xyz0[0], &dma.data[48], 12);
|
||||
@@ -236,11 +236,8 @@ 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);
|
||||
// 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.uv0[0] == 0);
|
||||
ASSERT(draw0.sprite.uv0[1] == 0);
|
||||
ASSERT(draw0.sprite.uv1[0] == 0);
|
||||
ASSERT(draw0.sprite.uv1[1] == 0);
|
||||
if (draw0.scissor.y1 - draw0.scissor.y0 == 63) {
|
||||
@@ -512,9 +509,7 @@ 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];
|
||||
auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
|
||||
out_tex.fnv_name_hash = draw.fnv_name_hash;
|
||||
out_tex.lr = draw.lr;
|
||||
const auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
|
||||
|
||||
// first, the clear
|
||||
float clear[4] = {0, 0, 0, 0};
|
||||
@@ -579,30 +574,15 @@ 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,
|
||||
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[0],
|
||||
uv0[1], uv1[0], uv1[1], xyz0[0], xyz0[1], xyz0[2], xyz1[0], xyz1[1], xyz1[2]);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,10 @@ 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;
|
||||
u64 uv0; // stores hashed name of merc-ctrl that reads this eye.
|
||||
u32 uv0[2];
|
||||
u32 uv1[2];
|
||||
u32 xyz0[3];
|
||||
u32 xyz1[3];
|
||||
@@ -54,8 +53,6 @@ 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) {}
|
||||
@@ -68,7 +65,6 @@ 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,7 +28,6 @@
|
||||
#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"
|
||||
@@ -37,7 +36,6 @@
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include "common/util/string_util.h"
|
||||
|
||||
namespace {
|
||||
std::string g_current_renderer;
|
||||
@@ -86,11 +84,7 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
|
||||
&gl_error_ignores_api_other[0], GL_FALSE);
|
||||
#endif
|
||||
|
||||
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));
|
||||
lg::debug("OpenGL context information: {}", (const char*)glGetString(GL_VERSION));
|
||||
|
||||
const tfrag3::Level* common_level = nullptr;
|
||||
{
|
||||
@@ -269,11 +263,6 @@ 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);
|
||||
@@ -281,10 +270,6 @@ 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
|
||||
@@ -296,10 +281,6 @@ 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);
|
||||
@@ -325,10 +306,6 @@ 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
|
||||
@@ -336,20 +313,11 @@ 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);
|
||||
@@ -1110,13 +1078,8 @@ 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,7 +123,6 @@ class OpenGLRenderer {
|
||||
|
||||
float m_last_pmode_alp = 1.;
|
||||
bool m_enable_fast_blackout_loads = true;
|
||||
std::string m_renderer_filter = "";
|
||||
|
||||
struct FboState {
|
||||
struct {
|
||||
|
||||
@@ -60,48 +60,23 @@
|
||||
* 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(GameVersion version) {
|
||||
OpenGLTexturePool::OpenGLTexturePool() {
|
||||
struct Alloc {
|
||||
u64 w, h, n;
|
||||
};
|
||||
// list of sizes to preallocate: {width, height, count}.
|
||||
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]) {
|
||||
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}}) {
|
||||
auto& l = textures[(a.w << 32) | a.h];
|
||||
l.resize(a.n);
|
||||
glGenTextures(a.n, l.data());
|
||||
@@ -395,7 +370,6 @@ 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),
|
||||
@@ -446,7 +420,6 @@ 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");
|
||||
@@ -669,7 +642,7 @@ GLuint TextureAnimator::get_by_slot(int idx) {
|
||||
}
|
||||
|
||||
// IDs sent from GOAL telling us what texture operation to perform.
|
||||
enum class PcTextureAnimCodesJak2 : u16 {
|
||||
enum PcTextureAnimCodes {
|
||||
FINISH_ARRAY = 13,
|
||||
ERASE_DEST_TEXTURE = 14,
|
||||
UPLOAD_CLUT_16_16 = 15,
|
||||
@@ -700,361 +673,6 @@ enum class PcTextureAnimCodesJak2 : u16 {
|
||||
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
|
||||
@@ -1108,191 +726,117 @@ 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 (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();
|
||||
}
|
||||
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;
|
||||
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("unsupported game version {}\n", (int)this->m_version);
|
||||
lg::print("bad imm: {}\n", vif0.immediate);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
} else {
|
||||
@@ -2274,21 +1818,6 @@ 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);
|
||||
@@ -2429,23 +1958,14 @@ 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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
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 sts[4];
|
||||
math::Vector2<u32> poss[4];
|
||||
|
||||
@@ -2536,14 +2056,8 @@ 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(GameVersion version);
|
||||
OpenGLTexturePool();
|
||||
~OpenGLTexturePool();
|
||||
GLuint allocate(u64 w, u64 h);
|
||||
void free(GLuint texture, u64 w, u64 h);
|
||||
@@ -148,18 +148,6 @@ 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;
|
||||
@@ -193,15 +181,6 @@ 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 {
|
||||
@@ -364,7 +343,6 @@ class TextureAnimator {
|
||||
GLuint tcc;
|
||||
GLuint alpha_multiply;
|
||||
GLuint minimum, maximum;
|
||||
GLuint set_alpha;
|
||||
} m_uniforms;
|
||||
|
||||
struct {
|
||||
@@ -418,8 +396,6 @@ 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;
|
||||
@@ -435,59 +411,9 @@ 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,7 +119,3 @@ void TextureUploadHandler::draw_debug_window() {
|
||||
m_direct->draw_debug_window();
|
||||
}
|
||||
}
|
||||
|
||||
bool TextureUploadHandler::empty() const {
|
||||
return m_upload_count == 0;
|
||||
}
|
||||
@@ -18,7 +18,6 @@ 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,7 +1,9 @@
|
||||
|
||||
#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"
|
||||
@@ -162,27 +164,10 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Event Profiler")) {
|
||||
if (ImGui::Checkbox("Record Events", &record_events)) {
|
||||
if (ImGui::Checkbox("Record", &record_events)) {
|
||||
prof().set_enable(record_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::MenuItem("Dump to file", nullptr, &dump_events);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class OpenGlDebugGui {
|
||||
|
||||
bool small_profiler = false;
|
||||
bool record_events = false;
|
||||
int max_event_buffer_size = 65536;
|
||||
bool dump_events = false;
|
||||
bool want_reboot_in_debug = false;
|
||||
|
||||
bool screenshot_hotkey_enabled = true;
|
||||
|
||||
@@ -70,16 +70,11 @@ 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
|
||||
@@ -89,7 +84,6 @@ 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, PRIM };
|
||||
enum class Mode { NORMAL, LIGHTNING, WARP };
|
||||
|
||||
void render_in_mode(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
@@ -19,7 +19,6 @@ class Generic2 {
|
||||
Mode mode);
|
||||
|
||||
void draw_debug_window();
|
||||
bool empty() { return m_empty; }
|
||||
|
||||
struct Vertex {
|
||||
math::Vector<float, 3> xyz;
|
||||
@@ -43,7 +42,6 @@ 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,
|
||||
@@ -86,8 +84,6 @@ 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 {
|
||||
@@ -202,10 +198,8 @@ 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, use_full_matrix, full_matrix;
|
||||
hvdf_offset;
|
||||
GLuint gfx_hack_no_tex;
|
||||
GLuint warp_sample_mode;
|
||||
} m_ogl;
|
||||
|
||||
bool m_empty = false;
|
||||
};
|
||||
@@ -22,9 +22,4 @@ 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,10 +11,8 @@ 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,16 +190,6 @@ 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;
|
||||
@@ -281,10 +271,6 @@ 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,83 +550,6 @@ 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,8 +74,6 @@ 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() {
|
||||
@@ -309,12 +307,6 @@ 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,7 +7,6 @@
|
||||
#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"
|
||||
@@ -55,8 +54,6 @@ 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);
|
||||
@@ -538,14 +535,11 @@ 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 && !is_custom_model; // if we should update vertices from game.
|
||||
bool model_uses_mod = flags->bitflags & 1; // if we should update vertices from game.
|
||||
bool model_disables_fog = flags->bitflags & 2;
|
||||
bool model_uses_pc_blerc = flags->bitflags & 4 && !is_custom_model;
|
||||
bool model_uses_pc_blerc = flags->bitflags & 4;
|
||||
bool model_disables_envmap = flags->bitflags & 8;
|
||||
input_data += 32;
|
||||
|
||||
@@ -615,8 +609,6 @@ 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?
|
||||
@@ -641,7 +633,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, hash);
|
||||
model_disables_fog);
|
||||
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);
|
||||
@@ -651,7 +643,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, hash);
|
||||
model_disables_fog);
|
||||
// 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];
|
||||
@@ -673,7 +665,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, hash);
|
||||
model_disables_fog);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -769,9 +761,7 @@ 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();
|
||||
}
|
||||
@@ -1063,7 +1053,6 @@ 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();
|
||||
@@ -1084,14 +1073,12 @@ Merc2::Draw* Merc2::alloc_normal_draw(const tfrag3::MercDraw& mdraw,
|
||||
u32 first_bone,
|
||||
u32 lights,
|
||||
bool jak1_water_mode,
|
||||
bool disable_fog,
|
||||
u64 hash) {
|
||||
bool disable_fog) {
|
||||
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();
|
||||
@@ -1218,7 +1205,7 @@ void Merc2::do_draws(const Draw* draw_array,
|
||||
bool set_fade,
|
||||
SharedRenderState* render_state) {
|
||||
glBindVertexArray(m_vao);
|
||||
s32 last_tex = INT32_MIN;
|
||||
int last_tex = -1;
|
||||
int last_light = -1;
|
||||
bool normal_vtx_buffer_bound = true;
|
||||
|
||||
@@ -1257,19 +1244,10 @@ 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) {
|
||||
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);
|
||||
}
|
||||
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,7 +192,6 @@ class Merc2 {
|
||||
u8 fade[4];
|
||||
// no strip hack for custom models
|
||||
u8 no_strip;
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
struct LevelDrawBucket {
|
||||
@@ -214,8 +213,7 @@ class Merc2 {
|
||||
u32 first_bone,
|
||||
u32 lights,
|
||||
bool jak1_water_mode,
|
||||
bool disable_fog,
|
||||
u64 hash);
|
||||
bool disable_fog);
|
||||
|
||||
Draw* try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw,
|
||||
const DrawMode& envmap_mode,
|
||||
|
||||
@@ -17,14 +17,8 @@ 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,10 +8,8 @@ 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,8 +10,6 @@ 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;
|
||||
|
||||
@@ -40,17 +38,11 @@ void main() {
|
||||
|
||||
// maddax.xyzw ACC, vf08, vf16 matrix multiply X
|
||||
// vu.acc.madda(Mask::xyzw, gen.mat0, gen.vtx_load0.x());
|
||||
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;
|
||||
}
|
||||
transformed.xyz = position_in * scale.xyz;
|
||||
transformed.z += mat_32;
|
||||
transformed.w = mat_23 * position_in.z + mat_33;
|
||||
|
||||
transformed *= -1; // todo?
|
||||
|
||||
|
||||
// div Q, vf01.x, vf12.w perspective divide
|
||||
|
||||
@@ -4,7 +4,6 @@ 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;
|
||||
@@ -58,9 +57,5 @@ void main() {
|
||||
} else {
|
||||
color = (rgba / 128.);
|
||||
}
|
||||
if (set_alpha == 1) {
|
||||
color.a = 0.5;
|
||||
} else {
|
||||
color.a *= alpha_multiply;
|
||||
}
|
||||
color.a *= alpha_multiply;
|
||||
}
|
||||
@@ -448,6 +448,23 @@ 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) {
|
||||
@@ -586,6 +603,7 @@ 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,6 +125,7 @@ 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,19 +448,6 @@ 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()) {
|
||||
@@ -482,16 +469,17 @@ u64 pc_get_display_name(u32 id, u32 str_dest_ptr) {
|
||||
}
|
||||
|
||||
u32 pc_get_display_mode() {
|
||||
auto display_mode = game_settings::DisplaySettings::DisplayMode::Windowed;
|
||||
auto display_mode = WindowDisplayMode::Windowed;
|
||||
if (Display::GetMainDisplay()) {
|
||||
display_mode = Display::GetMainDisplay()->get_display_manager()->get_display_mode();
|
||||
display_mode = Display::GetMainDisplay()->get_display_manager()->get_window_display_mode();
|
||||
}
|
||||
switch (display_mode) {
|
||||
case game_settings::DisplaySettings::DisplayMode::Borderless:
|
||||
case WindowDisplayMode::Borderless:
|
||||
return g_pc_port_funcs.intern_from_c("borderless").offset;
|
||||
case game_settings::DisplaySettings::DisplayMode::Fullscreen:
|
||||
case WindowDisplayMode::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;
|
||||
}
|
||||
}
|
||||
@@ -502,13 +490,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(
|
||||
game_settings::DisplaySettings::DisplayMode::Windowed);
|
||||
WindowDisplayMode::Windowed);
|
||||
} else if (symptr == g_pc_port_funcs.intern_from_c("borderless").offset) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
|
||||
game_settings::DisplaySettings::DisplayMode::Borderless);
|
||||
WindowDisplayMode::Borderless);
|
||||
} else if (symptr == g_pc_port_funcs.intern_from_c("fullscreen").offset) {
|
||||
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
|
||||
game_settings::DisplaySettings::DisplayMode::Fullscreen);
|
||||
WindowDisplayMode::Fullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,6 +568,12 @@ 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);
|
||||
@@ -607,14 +601,6 @@ 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()) {
|
||||
@@ -926,11 +912,9 @@ 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);
|
||||
@@ -941,10 +925,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-window-size!", (void*)pc_set_window_size);
|
||||
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-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,6 +16,7 @@ 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,7 +8,6 @@
|
||||
#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 {
|
||||
|
||||
@@ -40,7 +39,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].status = DGO_RPC_RESULT_INIT; // !! this is 666
|
||||
sMsg[msgID].result = DGO_RPC_RESULT_INIT; // !! this is 666
|
||||
|
||||
// inform IOP of buffers
|
||||
sMsg[msgID].buffer1 = buffer1.offset;
|
||||
@@ -79,13 +78,13 @@ Ptr<u8> GetNextDGO(u32* lastObjectFlag) {
|
||||
Ptr<u8> buffer(0);
|
||||
if (sLastMsg) {
|
||||
// if we got a good result, get pointer to object
|
||||
if ((sLastMsg->status == DGO_RPC_RESULT_MORE) || (sLastMsg->status == DGO_RPC_RESULT_DONE)) {
|
||||
if ((sLastMsg->result == DGO_RPC_RESULT_MORE) || (sLastMsg->result == 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->status == DGO_RPC_RESULT_MORE) {
|
||||
if (sLastMsg->result == DGO_RPC_RESULT_MORE) {
|
||||
*lastObjectFlag = 0;
|
||||
}
|
||||
|
||||
@@ -112,7 +111,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->status = DGO_RPC_RESULT_INIT;
|
||||
sendBuff->result = DGO_RPC_RESULT_INIT;
|
||||
sMsg[msgID].buffer1 = b1.offset;
|
||||
sMsg[msgID].buffer2 = b2.offset;
|
||||
sMsg[msgID].buffer_heap_top = heapPtr.offset;
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
//--------------------------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,16 +905,6 @@ 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,7 +393,6 @@ 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
|
||||
@@ -655,8 +654,7 @@ 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}},
|
||||
{"cloth", {jak3::method_21_cloth_system::link}}}};
|
||||
jak3::shadow_add_single_tris::link, jak3::shadow_add_double_tris::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,9 +460,6 @@ 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,7 +58,6 @@ 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[32];
|
||||
int MasterVolume[17];
|
||||
|
||||
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[32];
|
||||
extern int MasterVolume[17];
|
||||
|
||||
void vag_init_globals();
|
||||
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
#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
|
||||
@@ -1,76 +0,0 @@
|
||||
#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
|
||||
@@ -1,26 +0,0 @@
|
||||
#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
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_basefilesystem();
|
||||
|
||||
struct ISOFileDef;
|
||||
struct ISOName;
|
||||
struct CBaseFile;
|
||||
struct VagDirEntry;
|
||||
|
||||
constexpr int kMaxOpenFiles = 16;
|
||||
|
||||
/*!
|
||||
* Base class for "FileSystem", which supports finding and opening files.
|
||||
* The only implementation we have is CISOCDFileSystem
|
||||
*/
|
||||
struct CBaseFileSystem {
|
||||
CBaseFileSystem();
|
||||
virtual ~CBaseFileSystem() = default;
|
||||
|
||||
// semaphores for processing open files
|
||||
int m_Sema[kMaxOpenFiles];
|
||||
|
||||
virtual int Init() = 0;
|
||||
// polldrive
|
||||
virtual ISOFileDef* Find(const char* name) = 0;
|
||||
virtual ISOFileDef* FindIN(const ISOName* name) = 0;
|
||||
virtual int GetLength(const ISOFileDef* file) = 0;
|
||||
virtual CBaseFile* Open(const ISOFileDef* file_def, int sector_offset, int file_kind) = 0;
|
||||
virtual CBaseFile* OpenWAD(const ISOFileDef* file_def, int page_offset) = 0;
|
||||
virtual VagDirEntry* FindVAGFile(const char* name) = 0;
|
||||
};
|
||||
} // namespace jak3
|
||||
@@ -1,526 +0,0 @@
|
||||
#include "dma.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "game/overlord/jak3/basefile.h"
|
||||
#include "game/overlord/jak3/overlord.h"
|
||||
#include "game/overlord/jak3/vag.h"
|
||||
#include "game/sce/iop.h"
|
||||
#include "game/sound/sdshim.h"
|
||||
#include "game/sound/sndshim.h"
|
||||
|
||||
#define VOICE_BIT(voice) (1 << ((voice) >> 1))
|
||||
|
||||
namespace jak3 {
|
||||
using namespace iop;
|
||||
namespace {
|
||||
|
||||
// most recent call to voice_trans_wrapper's arguments
|
||||
u32 g_voiceTransMode = 0;
|
||||
u32 g_voiceTransSize = 0;
|
||||
s16 g_voiceTransChannel = 0;
|
||||
const void* g_voiceTransAddr = nullptr;
|
||||
u32 g_voiceTransSpuAddr = 0;
|
||||
|
||||
// if we've started a transfer recently
|
||||
bool g_voiceTransRunning = false;
|
||||
// when that transfer was started
|
||||
u32 g_voiceTransTime = 0;
|
||||
|
||||
// despite the name, this is really an indicator that the SPU streaming system is waiting
|
||||
// for a SPU interrupt on completion.
|
||||
bool g_bSpuDmaBusy = false;
|
||||
int g_nSpuDmaChannel = 0;
|
||||
|
||||
ISO_VAGCommand* g_pDmaVagCmd = nullptr;
|
||||
ISO_VAGCommand* g_pDmaStereoVagCmd = nullptr;
|
||||
|
||||
int g_nSpuDmaChunks = 0;
|
||||
|
||||
std::array<DmaQueueEntry, 16> g_aSpuDmaQueue;
|
||||
int g_nSpuDmaQueueHead = 0;
|
||||
int g_nSpuDmaQueueTail = 0;
|
||||
int g_nSpuDmaQueueCount = 0;
|
||||
|
||||
struct DmaInterruptHandlerHack {
|
||||
s32 chan = 0;
|
||||
sceSdTransIntrHandler cb = nullptr;
|
||||
void* data;
|
||||
int countdown = 0;
|
||||
} g_DmaInterruptHack;
|
||||
|
||||
} // namespace
|
||||
|
||||
void jak3_overlord_init_globals_dma() {
|
||||
g_voiceTransMode = 0;
|
||||
g_voiceTransSize = 0;
|
||||
g_voiceTransChannel = 0;
|
||||
g_voiceTransAddr = nullptr;
|
||||
g_voiceTransSpuAddr = 0;
|
||||
g_voiceTransRunning = false;
|
||||
g_voiceTransTime = 0;
|
||||
g_bSpuDmaBusy = false;
|
||||
g_nSpuDmaChannel = 0;
|
||||
g_pDmaVagCmd = nullptr;
|
||||
g_pDmaStereoVagCmd = nullptr;
|
||||
g_nSpuDmaChunks = 0;
|
||||
g_aSpuDmaQueue = {};
|
||||
g_nSpuDmaQueueHead = 0;
|
||||
g_nSpuDmaQueueCount = 0;
|
||||
g_nSpuDmaQueueTail = 0;
|
||||
g_DmaInterruptHack = {};
|
||||
}
|
||||
|
||||
// The DMA callback hack below is used to defer dma completion "interrupts" until the next run
|
||||
// of the ISO Thread. This avoids re-entry type problems where the original design would set off
|
||||
// a dma transfer in the completion handler of the previous transfer, and expect a few instructions
|
||||
// to run after.
|
||||
|
||||
void uninstall_dma_intr() {
|
||||
g_DmaInterruptHack = {};
|
||||
}
|
||||
|
||||
void set_dma_intr_handler_hack(s32 chan, sceSdTransIntrHandler cb, void* data) {
|
||||
ASSERT(!g_DmaInterruptHack.cb);
|
||||
g_DmaInterruptHack.chan = chan;
|
||||
g_DmaInterruptHack.cb = cb;
|
||||
g_DmaInterruptHack.data = data;
|
||||
g_DmaInterruptHack.countdown = 10;
|
||||
}
|
||||
|
||||
int SPUDmaIntr(int channel, void* userdata);
|
||||
|
||||
void dma_intr_hack() {
|
||||
if (g_DmaInterruptHack.countdown) {
|
||||
g_DmaInterruptHack.countdown--;
|
||||
if (g_DmaInterruptHack.countdown == 0) {
|
||||
int chan = g_DmaInterruptHack.chan;
|
||||
void* data = g_DmaInterruptHack.data;
|
||||
g_DmaInterruptHack = {};
|
||||
SPUDmaIntr(chan, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* This function is used to set up a DMA transfer to SPU DMA.
|
||||
*
|
||||
* This wrapper was added very close to the end of Jak 3's development.
|
||||
*
|
||||
* I believe it basically checks for dma transfers that are somehow "dropped", and retries them.
|
||||
* Since I don't think our IOP framework will ever do this, we have an assert if the dropped logic
|
||||
* ever goes off.
|
||||
*/
|
||||
int voice_trans_wrapper(s16 chan, u32 mode, const void* iop_addr, u32 spu_addr, u32 size) {
|
||||
// remember the transfer settings. If there's a transfer in progress, so we can't start here,
|
||||
// we'll use these to start the transfer later.
|
||||
g_voiceTransMode = mode;
|
||||
g_voiceTransSize = size;
|
||||
g_voiceTransChannel = chan;
|
||||
g_voiceTransAddr = iop_addr;
|
||||
g_voiceTransSpuAddr = spu_addr;
|
||||
|
||||
if (g_voiceTransRunning) {
|
||||
// I claim this should never happen, and this is their workaround for a bug.
|
||||
ASSERT_NOT_REACHED();
|
||||
return -0xd2; // busy
|
||||
} else {
|
||||
g_voiceTransRunning = true;
|
||||
g_voiceTransTime = GetSystemTimeLow();
|
||||
return sceSdVoiceTrans(chan, mode, iop_addr, spu_addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
u32 read_rate_calc(u32 pitch) {
|
||||
u64 pitch1 = (pitch >> 3);
|
||||
u64 mult_result = pitch1 * 0x2492'4925ull;
|
||||
return mult_result >> 32;
|
||||
}
|
||||
|
||||
/*!
|
||||
* The worst function of all time - the SPU DMA completion interrupt.
|
||||
*/
|
||||
int SPUDmaIntr(int channel, void* userdata) {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr enter! {} 0x{:x}", channel, (u64)userdata);
|
||||
|
||||
if (!g_bSpuDmaBusy) {
|
||||
// we got an interrupt, but weren't expecting it, or no longer have the need for the data.
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - not busy");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (channel != g_nSpuDmaChannel) {
|
||||
// interrupt was for the wrong channel, somehow.
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - not our channel ??");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// since we're in the completion handler, we know that there is no voice trans (SPU DMA) running.
|
||||
g_voiceTransRunning = false;
|
||||
|
||||
// This next block will handle updating the playback command that triggered this dma:
|
||||
if (g_pDmaVagCmd) {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDma for cmd {}", g_pDmaVagCmd->name);
|
||||
if (!g_pDmaStereoVagCmd) {
|
||||
// non-stereo audio
|
||||
|
||||
// set a flag to indicate even/odd number of chunks have been dma'd
|
||||
if ((g_nSpuDmaChunks & 1) == 0) {
|
||||
g_pDmaVagCmd->flags.dma_complete_even_chunk_count = 1;
|
||||
} else {
|
||||
g_pDmaVagCmd->flags.dma_complete_odd_chunk_count = 1;
|
||||
}
|
||||
} else {
|
||||
// stereo audio. This requires two uploads, one for left/right audio. If we've finished the
|
||||
// first, start the second one here:
|
||||
if (g_pDmaStereoVagCmd->xfer_size) {
|
||||
// parameters for second upload
|
||||
int chan = g_pDmaVagCmd->dma_chan;
|
||||
const u8* iop_addr = g_pDmaStereoVagCmd->dma_iop_mem_ptr;
|
||||
int size = g_pDmaStereoVagCmd->xfer_size;
|
||||
|
||||
// SPU addr - toggle the buffer based on stereo side:
|
||||
// TODO: better explanation of why this picks the correct buffer.
|
||||
int spu_addr;
|
||||
if ((g_nSpuDmaChunks & 1) == 0) {
|
||||
spu_addr = g_pDmaStereoVagCmd->stream_sram;
|
||||
} else {
|
||||
spu_addr = g_pDmaStereoVagCmd->stream_sram + 0x2000;
|
||||
}
|
||||
|
||||
// these lines reordered to possibly support immediate dma completion callback??
|
||||
|
||||
// clear flag so we know not to transfer the next part
|
||||
g_pDmaStereoVagCmd->xfer_size = 0;
|
||||
g_pDmaStereoVagCmd->dma_iop_mem_ptr = nullptr;
|
||||
|
||||
// start next transfer
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr starting stereo sibling transfer");
|
||||
set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, userdata);
|
||||
voice_trans_wrapper(chan, 0, iop_addr, spu_addr, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// second stereo upload completed - update double-buffering flags
|
||||
if ((g_nSpuDmaChunks & 1) == 0) {
|
||||
g_pDmaVagCmd->flags.dma_complete_even_chunk_count = 1;
|
||||
g_pDmaStereoVagCmd->flags.dma_complete_even_chunk_count = 1;
|
||||
} else {
|
||||
g_pDmaVagCmd->flags.dma_complete_odd_chunk_count = 1;
|
||||
g_pDmaStereoVagCmd->flags.dma_complete_odd_chunk_count = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is the first chunk, we'll start the actual audio here:
|
||||
// lg::warn("----------> interrupt with chunks {}\n", g_nSpuDmaChunks);
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks count {}", g_nSpuDmaChunks);
|
||||
|
||||
if (g_nSpuDmaChunks == 0) {
|
||||
// compute pitch/playback rate
|
||||
int pitch = CalculateVAGPitch(g_pDmaVagCmd->pitch1, g_pDmaVagCmd->pitch_cmd);
|
||||
ASSERT(pitch == (pitch & 0xffff));
|
||||
|
||||
// inform the ISO system how fast we're reading
|
||||
if (g_pDmaVagCmd->m_pBaseFile) {
|
||||
// unlike actual playback, this is done with the pitch1 value from the file itself - so if
|
||||
// we speed up/slow down stuff in debug, it won't change streaming modes
|
||||
const int pitch_from_file =
|
||||
CalculateVAGPitch(g_pDmaVagCmd->pitch1_file, g_pDmaVagCmd->pitch_cmd);
|
||||
int rate = g_pDmaStereoVagCmd ? pitch_from_file * 0x2ee : pitch_from_file * 0x177;
|
||||
g_pDmaVagCmd->m_pBaseFile->m_ReadRate = read_rate_calc(rate);
|
||||
}
|
||||
|
||||
// start!
|
||||
u32 voice_mask = 0;
|
||||
if (!g_pDmaStereoVagCmd) {
|
||||
// forget any previous spu address
|
||||
g_pDmaVagCmd->current_spu_address = 0;
|
||||
|
||||
static_assert(SD_VA_SSA == 0x2040);
|
||||
static_assert(SD_S_KOFF == 0x1600);
|
||||
static_assert(SD_S_KON == 0x1500);
|
||||
|
||||
static_assert(SD_VP_ADSR1 == 0x300);
|
||||
static_assert(SD_VP_ADSR2 == 0x400);
|
||||
static_assert(SD_VP_PITCH == 0x200);
|
||||
|
||||
// before touching SPU2 hardware, wait for voice safety:
|
||||
BlockUntilVoiceSafe(g_pDmaVagCmd->voice, 0x900);
|
||||
|
||||
// set address and ADSR settings
|
||||
sceSdSetAddr(g_pDmaVagCmd->voice | SD_VA_SSA, g_pDmaVagCmd->stream_sram + 0x30);
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR1, 0xff);
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
|
||||
if (g_pDmaVagCmd->flags.paused) {
|
||||
pitch = 0;
|
||||
}
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, pitch);
|
||||
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice);
|
||||
} else {
|
||||
// forget any previous spu address
|
||||
g_pDmaVagCmd->current_spu_address = 0;
|
||||
g_pDmaStereoVagCmd->current_spu_address = 0;
|
||||
|
||||
// wait for voices to be safe to adjust
|
||||
BlockUntilVoiceSafe(g_pDmaVagCmd->voice, 0x900);
|
||||
BlockUntilVoiceSafe(g_pDmaStereoVagCmd->voice, 0x900);
|
||||
|
||||
// set voice params
|
||||
sceSdSetAddr(g_pDmaVagCmd->voice | SD_VA_SSA, g_pDmaVagCmd->stream_sram + 0x30);
|
||||
sceSdSetAddr(g_pDmaStereoVagCmd->voice | SD_VA_SSA, g_pDmaStereoVagCmd->stream_sram + 0x30);
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR1, 0xff);
|
||||
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_ADSR1, 0xff);
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
|
||||
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
|
||||
if (g_pDmaVagCmd->flags.paused) {
|
||||
pitch = 0;
|
||||
}
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, pitch);
|
||||
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_PITCH, pitch);
|
||||
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice) | VOICE_BIT(g_pDmaStereoVagCmd->voice);
|
||||
}
|
||||
|
||||
// do key-on or key-off
|
||||
if (g_pDmaVagCmd->flags.paused) {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 0, key off");
|
||||
BlockUntilAllVoicesSafe();
|
||||
sceSdSetSwitch(SD_S_KOFF | (g_pDmaVagCmd->voice & 1), voice_mask);
|
||||
} else {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 0, key on");
|
||||
BlockUntilAllVoicesSafe();
|
||||
sceSdSetSwitch(SD_S_KON | (g_pDmaVagCmd->voice & 1), voice_mask);
|
||||
}
|
||||
|
||||
// remember the time of the key-on/off. This is used to avoid sending voice commands
|
||||
// quickly, which somehow confuses the sound hardware.
|
||||
auto sys_time = GetSystemTimeLow();
|
||||
MarkVoiceKeyedOnOff(g_pDmaVagCmd->voice, sys_time);
|
||||
if (g_pDmaStereoVagCmd) {
|
||||
MarkVoiceKeyedOnOff(g_pDmaStereoVagCmd->voice, sys_time);
|
||||
}
|
||||
} else if (g_nSpuDmaChunks == 1) {
|
||||
g_pDmaVagCmd->flags.saw_chunks1 = 1;
|
||||
if (g_pDmaStereoVagCmd) {
|
||||
g_pDmaStereoVagCmd->flags.saw_chunks1 = 1;
|
||||
}
|
||||
|
||||
if (g_pDmaVagCmd->flags.paused) {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 1, pausing");
|
||||
u32 voice_mask = 0;
|
||||
if (!g_pDmaStereoVagCmd) {
|
||||
// pause by setting pitches to 0
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, 0);
|
||||
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaVagCmd->voice), 0x900);
|
||||
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice);
|
||||
} else {
|
||||
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_PITCH, 0);
|
||||
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, 0);
|
||||
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaVagCmd->voice), 0x900);
|
||||
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaStereoVagCmd->voice), 0x900);
|
||||
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice) | VOICE_BIT(g_pDmaStereoVagCmd->voice);
|
||||
}
|
||||
|
||||
// switch off
|
||||
BlockUntilAllVoicesSafe();
|
||||
sceSdSetSwitch(SD_S_KOFF | (g_pDmaVagCmd->voice & 1), voice_mask);
|
||||
auto sys_time = GetSystemTimeLow();
|
||||
MarkVoiceKeyedOnOff(g_pDmaVagCmd->voice, sys_time);
|
||||
if (g_pDmaStereoVagCmd) {
|
||||
MarkVoiceKeyedOnOff(g_pDmaStereoVagCmd->voice, sys_time);
|
||||
}
|
||||
} else {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 1, unpausing by call to UnPauseVAG");
|
||||
g_pDmaVagCmd->flags.paused = 1;
|
||||
UnPauseVAG(g_pDmaVagCmd);
|
||||
}
|
||||
}
|
||||
|
||||
// now that we've processed the command from this interrupt, mark it as safe to modify
|
||||
g_pDmaVagCmd->safe_to_modify_dma = 1;
|
||||
if (g_pDmaStereoVagCmd) {
|
||||
g_pDmaStereoVagCmd->safe_to_modify_dma = 1;
|
||||
}
|
||||
// and forget it!
|
||||
g_pDmaVagCmd = nullptr;
|
||||
g_pDmaStereoVagCmd = nullptr;
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr dma handling of VAG cmd is complete");
|
||||
}
|
||||
|
||||
// release ref on this page. (interestingly, not a dma ref...)
|
||||
if (userdata) {
|
||||
CPage* page = (CPage*)userdata;
|
||||
int ret = page->ReleaseRef();
|
||||
ASSERT(ret >= 0);
|
||||
}
|
||||
|
||||
// now - see if we have another queued dma transfer
|
||||
ASSERT(g_nSpuDmaQueueCount >= 0);
|
||||
if (g_nSpuDmaQueueCount == 0) {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr dma queue is empty, disabling interrupt");
|
||||
// we're done!
|
||||
// set_dma_intr_handler_hack(channel, nullptr, nullptr);
|
||||
uninstall_dma_intr();
|
||||
// if (-1 < channel) {
|
||||
// snd_FreeSPUDMA(channel);
|
||||
// }
|
||||
g_bSpuDmaBusy = false;
|
||||
} else {
|
||||
ovrld_log(LogCategory::SPU_DMA_STR,
|
||||
"SPUDmaIntr dma queue is not empty, preparing to run {} ({} pending)",
|
||||
g_nSpuDmaQueueHead, g_nSpuDmaQueueCount);
|
||||
// nope, more dma to run
|
||||
auto* next_xfer = &g_aSpuDmaQueue[g_nSpuDmaQueueHead];
|
||||
|
||||
// set up the next interrupt handler
|
||||
set_dma_intr_handler_hack(channel, SPUDmaIntr, next_xfer->user_data);
|
||||
|
||||
// args for the dma transfer
|
||||
int next_chan = channel;
|
||||
int next_mode = 0;
|
||||
const void* next_iop = next_xfer->iop_mem;
|
||||
u32 next_spu = next_xfer->spu_addr;
|
||||
u32 next_length = next_xfer->length;
|
||||
|
||||
// load up the commands to handle
|
||||
g_pDmaVagCmd = next_xfer->command;
|
||||
g_pDmaStereoVagCmd = nullptr;
|
||||
if (g_pDmaVagCmd) {
|
||||
g_pDmaStereoVagCmd = g_pDmaVagCmd->stereo_sibling;
|
||||
}
|
||||
g_nSpuDmaChunks = next_xfer->num_isobuffered_chunks;
|
||||
|
||||
// advance the queue!
|
||||
g_nSpuDmaQueueCount = g_nSpuDmaQueueCount + -1;
|
||||
g_nSpuDmaQueueHead = g_nSpuDmaQueueHead + 1;
|
||||
if (0xf < g_nSpuDmaQueueHead) {
|
||||
g_nSpuDmaQueueHead = 0;
|
||||
}
|
||||
|
||||
// start the next one!
|
||||
// set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, userdata);
|
||||
voice_trans_wrapper(next_chan, next_mode, next_iop, next_spu, next_length);
|
||||
}
|
||||
|
||||
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - end of function");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start DMA to EE.
|
||||
*/
|
||||
void DMA_SendToEE(void* ee_dest,
|
||||
const void* iop_src,
|
||||
u32 length,
|
||||
void callback(void*),
|
||||
void* callback_arg) {
|
||||
ASSERT(iop_src);
|
||||
ASSERT(ee_dest);
|
||||
ASSERT(((uintptr_t)iop_src & 3) == 0);
|
||||
ASSERT(((uintptr_t)ee_dest & 0xf) == 0);
|
||||
ASSERT(length < 0xffff0);
|
||||
sceSifDmaData cmd; // DMA settings
|
||||
|
||||
// setup command
|
||||
cmd.mode = 0;
|
||||
cmd.data = iop_src;
|
||||
cmd.addr = ee_dest;
|
||||
cmd.size = length;
|
||||
|
||||
// instant DMA
|
||||
// ovrld_log(LogCategory::EE_DMA, "DMA_SendToEE: 0x{:x}, size {}", (u64)ee_dest, length);
|
||||
sceSifSetDma(&cmd, 1);
|
||||
|
||||
// for now, we'll do the callback here, but I bet it will cause problems
|
||||
if (callback) {
|
||||
callback(callback_arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Start DMA transfer to SPU. Despite the name, this does not actually "sync" - the transfer will
|
||||
* be ongoing. If there is an ongoing transfer when this is called, the transfer will be queued.
|
||||
*/
|
||||
int DMA_SendToSPUAndSync(const u8* iop_mem,
|
||||
int length,
|
||||
int spu_addr,
|
||||
ISO_VAGCommand* cmd,
|
||||
void* user_data) {
|
||||
// CpuSuspendIntr(local_28);
|
||||
int ret = 1;
|
||||
bool defer = false;
|
||||
|
||||
ovrld_log(LogCategory::SPU_DMA_STR,
|
||||
"DMA to SPU requested for {}, {} bytes to 0x{:x}, currently busy? {}",
|
||||
cmd ? cmd->name : "NO-CMD", length, spu_addr, g_bSpuDmaBusy);
|
||||
if (g_bSpuDmaBusy == 0) {
|
||||
// not busy, we can actually start dma now.
|
||||
g_nSpuDmaChannel = snd_GetFreeSPUDMA();
|
||||
if (g_nSpuDmaChannel == -1) {
|
||||
return 0;
|
||||
}
|
||||
// set globals for DMA processing
|
||||
if (cmd) {
|
||||
g_nSpuDmaChunks = cmd->num_isobuffered_chunks;
|
||||
g_pDmaStereoVagCmd = cmd->stereo_sibling;
|
||||
g_pDmaVagCmd = cmd;
|
||||
}
|
||||
|
||||
} else {
|
||||
// busy, need to queue the dma
|
||||
ASSERT(g_nSpuDmaQueueCount <= (int)g_aSpuDmaQueue.size());
|
||||
|
||||
// set values:
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].length = length;
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].spu_addr = spu_addr;
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].user_data = user_data;
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].num_isobuffered_chunks =
|
||||
cmd ? cmd->num_isobuffered_chunks : 0;
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].command = cmd;
|
||||
g_aSpuDmaQueue[g_nSpuDmaQueueTail].iop_mem = iop_mem;
|
||||
g_nSpuDmaQueueCount = g_nSpuDmaQueueCount + 1;
|
||||
g_nSpuDmaQueueTail = g_nSpuDmaQueueTail + 1;
|
||||
if (0xf < g_nSpuDmaQueueTail) {
|
||||
g_nSpuDmaQueueTail = 0;
|
||||
}
|
||||
defer = true;
|
||||
}
|
||||
|
||||
// set up the stereo command
|
||||
if (cmd) {
|
||||
cmd->safe_to_modify_dma = 0;
|
||||
auto* stereo = cmd->stereo_sibling;
|
||||
if (stereo) {
|
||||
stereo->num_isobuffered_chunks = cmd->num_isobuffered_chunks;
|
||||
stereo->dma_iop_mem_ptr = iop_mem + length;
|
||||
cmd->dma_chan = g_nSpuDmaChannel;
|
||||
stereo->xfer_size = length;
|
||||
}
|
||||
}
|
||||
|
||||
// kick off dma, if we decided not to queue.
|
||||
if (!defer) {
|
||||
g_bSpuDmaBusy = true;
|
||||
set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, user_data);
|
||||
voice_trans_wrapper(g_nSpuDmaChannel, 0, iop_mem, spu_addr, length);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Run a dma transfer that was delayed or dropped.
|
||||
*/
|
||||
void RunDeferredVoiceTrans() {
|
||||
// only if there's a currently happening transfer.
|
||||
if (g_voiceTransRunning) {
|
||||
if (GetSystemTimeLow() - g_voiceTransTime > 0x384000) {
|
||||
ovrld_log(LogCategory::WARN, "DeferredVoiceTrans has detected hung dma... expect problems.");
|
||||
// original game also check sceSdVoiceTransStatus here, we'll possibly need to mess with this
|
||||
// if we delay dma completion interrupts...
|
||||
g_voiceTransRunning = false;
|
||||
voice_trans_wrapper(g_voiceTransChannel, g_voiceTransMode, g_voiceTransAddr,
|
||||
g_voiceTransSpuAddr, g_voiceTransSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace jak3
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_dma();
|
||||
struct ISO_VAGCommand;
|
||||
|
||||
int voice_trans_wrapper(s16 chan, u32 mode, const void* iop_addr, u32 spu_addr, u32 size);
|
||||
void DMA_SendToEE(void* ee_dest,
|
||||
const void* iop_src,
|
||||
u32 length,
|
||||
void callback(void*),
|
||||
void* callback_arg);
|
||||
int DMA_SendToSPUAndSync(const u8* iop_mem,
|
||||
int length,
|
||||
int spu_addr,
|
||||
ISO_VAGCommand* cmd,
|
||||
void* user_data);
|
||||
void RunDeferredVoiceTrans();
|
||||
struct ISO_VAGCommand;
|
||||
|
||||
struct DmaQueueEntry {
|
||||
ISO_VAGCommand* command = nullptr;
|
||||
const void* iop_mem = nullptr;
|
||||
u32 spu_addr = 0;
|
||||
u32 length = 0;
|
||||
void* user_data = nullptr;
|
||||
u32 num_isobuffered_chunks = 0;
|
||||
};
|
||||
void dma_intr_hack();
|
||||
} // namespace jak3
|
||||
@@ -1,583 +0,0 @@
|
||||
#include "dvd_driver.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
#include "game/overlord/jak3/overlord.h"
|
||||
#include "game/sce/iop.h"
|
||||
|
||||
namespace jak3 {
|
||||
using namespace iop;
|
||||
std::unique_ptr<CDvdDriver> g_DvdDriver;
|
||||
s32 g_nDvdDriverThread = -1;
|
||||
|
||||
void jak3_overlord_init_globals_dvd_driver() {
|
||||
g_DvdDriver = std::make_unique<CDvdDriver>();
|
||||
g_nDvdDriverThread = -1;
|
||||
}
|
||||
|
||||
CDvdDriver* get_driver() {
|
||||
return g_DvdDriver.get();
|
||||
}
|
||||
|
||||
CMsg::CMsg(jak3::CMsg::MsgKind msg) : m_msg(msg) {
|
||||
m_ret = 1;
|
||||
m_thread = GetThreadId();
|
||||
}
|
||||
|
||||
int CMsg::send() {
|
||||
// note: changed from passing data
|
||||
// and removed corresponding -4 to skip back past the vtable in DVD thread
|
||||
// (what were they thinking?)
|
||||
s32 ret = SendMbx(get_driver()->msgbox, this);
|
||||
if (ret == 0) {
|
||||
get_driver()->KickDvdThread();
|
||||
SleepThread();
|
||||
return m_ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// CMsgLock::CMsgLock() : CMsg(CMsg::MsgKind::LOCK) {}
|
||||
//
|
||||
// void CMsgLock::handler() {
|
||||
// get_driver()->Lock();
|
||||
// m_ret = 0;
|
||||
// }
|
||||
|
||||
// CMsgReadRaw::CMsgReadRaw(jak3::BlockParams* params) : CMsg(CMsg::MsgKind::READ_RAW) {
|
||||
// m_block_params = *params;
|
||||
// }
|
||||
//
|
||||
// void CMsgReadRaw::handler() {
|
||||
// m_ret = get_driver()->ReadDirect(&m_block_params);
|
||||
// }
|
||||
|
||||
CMsgCancelRead::CMsgCancelRead(jak3::CDescriptor* desc) : CMsg(CMsg::MsgKind::CANCEL_READ) {
|
||||
m_desc = desc;
|
||||
}
|
||||
|
||||
void CMsgCancelRead::handler() {
|
||||
get_driver()->CancelRead(m_desc);
|
||||
m_ret = 0;
|
||||
}
|
||||
|
||||
u32 DvdThread();
|
||||
|
||||
CDvdDriver::CDvdDriver() {
|
||||
fifo_entry_sema = -1;
|
||||
current_thread_priority = 0x13;
|
||||
disk_type = 5;
|
||||
tray_flag = 1;
|
||||
// m_nLockCount = 0;
|
||||
event_flag = -1;
|
||||
fifo_access_sema = -1;
|
||||
tray_flag2 = 1;
|
||||
initialized = 0;
|
||||
m_nNumFifoEntries = 0;
|
||||
ring_head = 0;
|
||||
ring_tail = 0;
|
||||
read_in_progress = 0;
|
||||
callback = nullptr;
|
||||
// locked = false;
|
||||
trayflag3 = 0;
|
||||
m_nDvdThreadAccessSemaCount = 0;
|
||||
memset(ring, 0, sizeof(Block) * 16);
|
||||
}
|
||||
|
||||
void CDvdDriver::Initialize() {
|
||||
if (!initialized) {
|
||||
*this = {};
|
||||
ThreadParam thread_param;
|
||||
thread_param.attr = 0x2000000;
|
||||
// mbox_param.option = gDvdDriverThreadOptions; // ???
|
||||
thread_param.entry = DvdThread;
|
||||
thread_param.stackSize = 0x800;
|
||||
thread_param.initPriority = 0x13;
|
||||
thread_param.option = 0;
|
||||
strcpy(thread_param.name, "dvd");
|
||||
// mbox_param.attr = (int)PTR_DvdThread_00015c98; // ???
|
||||
g_nDvdDriverThread = CreateThread(&thread_param);
|
||||
ASSERT(g_nDvdDriverThread >= 0);
|
||||
|
||||
SemaParam sema_param;
|
||||
sema_param.attr = 0;
|
||||
sema_param.init_count = 1;
|
||||
sema_param.max_count = 1;
|
||||
sema_param.option = 0;
|
||||
fifo_access_sema = CreateSema(&sema_param);
|
||||
ASSERT(fifo_access_sema >= 0);
|
||||
sema_param.max_count = 0x10;
|
||||
sema_param.attr = 0;
|
||||
sema_param.init_count = 0x10;
|
||||
sema_param.option = 0;
|
||||
fifo_entry_sema = CreateSema(&sema_param);
|
||||
ASSERT(fifo_entry_sema >= 0);
|
||||
MbxParam mbox_param;
|
||||
mbox_param.attr = 0;
|
||||
mbox_param.option = 0;
|
||||
msgbox = CreateMbx(&mbox_param);
|
||||
ASSERT(msgbox >= 0);
|
||||
|
||||
EventFlagParam param;
|
||||
param.attr = 0;
|
||||
param.option = 0;
|
||||
param.init_pattern = 0;
|
||||
event_flag = CreateEventFlag(¶m);
|
||||
ASSERT(event_flag >= 0);
|
||||
StartThread(g_nDvdDriverThread, 0); // this...
|
||||
}
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
void CDvdDriver::SetDriverCallback(std::function<void(int)> f) {
|
||||
callback = f;
|
||||
}
|
||||
|
||||
// GetDriveCallback
|
||||
|
||||
// Poll - would kick the thread...
|
||||
|
||||
// void CDvdDriver::Lock() {
|
||||
// ASSERT_NOT_REACHED();
|
||||
// if (GetThreadId() == g_nDvdDriverThread) {
|
||||
// m_nLockCount++;
|
||||
// locked = true;
|
||||
// // needs break HACK
|
||||
// needs_break = false;
|
||||
// } else {
|
||||
// CMsgLock lock;
|
||||
// lock.send();
|
||||
// }
|
||||
// }
|
||||
|
||||
// Read
|
||||
|
||||
int CDvdDriver::ReadMultiple(CDescriptor* descriptor,
|
||||
int* pages_read_out,
|
||||
BlockParams* params,
|
||||
int num_blocks,
|
||||
bool block_if_queue_full) {
|
||||
*pages_read_out = 0;
|
||||
s32 ret = 1;
|
||||
|
||||
// check block parameters are reasonable
|
||||
if (ValidateBlockParams(params, num_blocks) != 0) {
|
||||
bool from_dvd_thread = GetThreadId() == g_nDvdDriverThread;
|
||||
if (from_dvd_thread) {
|
||||
// there is a setting to control if this function should block if there are too many
|
||||
// queued reads. If the is called from the DVD thread, then this would deadlock.
|
||||
// the original game ignored the block argument, but I'm asserting
|
||||
block_if_queue_full = 0;
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
ovrld_log(LogCategory::DRIVER, "[driver] ReadMultiple (from our thread? {}) num_blocks {}",
|
||||
from_dvd_thread, num_blocks);
|
||||
|
||||
ret = 0;
|
||||
if (0 < num_blocks) {
|
||||
// loop, until we've done all the requested reads.
|
||||
do {
|
||||
s32 acquired_slots = 0;
|
||||
if (0 < num_blocks) {
|
||||
// loop to try to get up to num_blocks slots in the fifo
|
||||
// but, if we get less, we'll take that too
|
||||
do {
|
||||
if (PollSema(this->fifo_entry_sema) == -0x1a3)
|
||||
break;
|
||||
acquired_slots = acquired_slots + 1;
|
||||
} while (acquired_slots < num_blocks);
|
||||
}
|
||||
ovrld_log(LogCategory::DRIVER, "[driver] ReadMultiple acquired {} slots in ring",
|
||||
acquired_slots);
|
||||
|
||||
// if we are blocking, and we acquired no slots, then we'll wait here until we get one slot.
|
||||
if ((block_if_queue_full != 0) && (acquired_slots < 1)) {
|
||||
ovrld_log(LogCategory::DRIVER, "[driver] ring is full, blocking!");
|
||||
acquired_slots = 1; // the one we'll get from the WaitSema below
|
||||
do {
|
||||
} while (WaitSema(fifo_entry_sema) != 0);
|
||||
}
|
||||
|
||||
// lock, now that we've gotten the slots
|
||||
AcquireFIFOSema(from_dvd_thread);
|
||||
num_blocks = num_blocks - acquired_slots;
|
||||
|
||||
// if we didn't get any slots, bail.
|
||||
if (acquired_slots < 1) {
|
||||
ovrld_log(LogCategory::DRIVER, "[driver] ring is full, bailing!");
|
||||
ReleaseFIFOSema(from_dvd_thread);
|
||||
if (0 < *pages_read_out) {
|
||||
KickDvdThread();
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
// loop, updating the ring for each slot we aquired
|
||||
do {
|
||||
auto* slot = ring + ring_tail;
|
||||
ovrld_log(LogCategory::DRIVER, "[driver] inserting in ring slot {}", ring_tail);
|
||||
|
||||
ring_tail++;
|
||||
if (0xf < ring_tail) {
|
||||
ring_tail = 0;
|
||||
}
|
||||
m_nNumFifoEntries++;
|
||||
|
||||
auto* tail = descriptor->m_pTail;
|
||||
slot->descriptor = descriptor;
|
||||
slot->params = params[*pages_read_out];
|
||||
*pages_read_out = (*pages_read_out) + 1;
|
||||
if (!tail) {
|
||||
descriptor->m_pHead = slot;
|
||||
} else {
|
||||
tail->next = slot;
|
||||
}
|
||||
acquired_slots = acquired_slots + -1;
|
||||
descriptor->m_pTail = slot;
|
||||
slot->next = nullptr;
|
||||
} while (acquired_slots != 0);
|
||||
ReleaseFIFOSema(from_dvd_thread);
|
||||
KickDvdThread();
|
||||
ret = 0;
|
||||
} while (0 < num_blocks);
|
||||
}
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CDvdDriver::CancelRead(jak3::CDescriptor* desc) {
|
||||
if (GetThreadId() == g_nDvdDriverThread) {
|
||||
AcquireFIFOSema(true);
|
||||
if ((read_in_progress != 0) && (ring[ring_head].descriptor == desc)) {
|
||||
// while (iVar1 = sceCdBreak(), iVar1 == 0) {
|
||||
// DelayThread(8000);
|
||||
// sceCdSync(0);
|
||||
// }
|
||||
// sceCdSync(0);
|
||||
read_in_progress = 0;
|
||||
}
|
||||
|
||||
Block* iter = desc->m_pHead;
|
||||
Block* tail = desc->m_pTail;
|
||||
while (iter) {
|
||||
if (iter->descriptor) {
|
||||
CompletionHandler(iter, 6);
|
||||
}
|
||||
iter->descriptor = nullptr;
|
||||
iter->next = nullptr;
|
||||
if (iter == tail)
|
||||
break;
|
||||
iter = desc->m_pHead;
|
||||
}
|
||||
|
||||
if (desc->m_pTail == tail) {
|
||||
desc->m_pTail = nullptr;
|
||||
}
|
||||
ReleaseFIFOSema(true);
|
||||
} else {
|
||||
CMsgCancelRead msg(desc);
|
||||
msg.send();
|
||||
}
|
||||
}
|
||||
|
||||
s32 CDvdDriver::ValidateBlockParams(jak3::BlockParams* params, int num_params) {
|
||||
if (!params) {
|
||||
lg::die("Invalid BlockParams: nullptr");
|
||||
return 0;
|
||||
}
|
||||
if (num_params < 1) {
|
||||
lg::die("Invalid BlockParams: size == 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
auto& p = params[i];
|
||||
if (p.destination == nullptr) {
|
||||
lg::die("Invalid BlockParams: {} had nullptr dest", i);
|
||||
return 0;
|
||||
}
|
||||
int kMaxSector = 1000000;
|
||||
if (p.sector_num > kMaxSector) {
|
||||
// this is just a sanity check - if we ever have larger files this is okay to increase.
|
||||
lg::die("Invalid BlockParams: {} had sector num {}", i, p.sector_num);
|
||||
return 0;
|
||||
}
|
||||
if (p.num_sectors > 0x1d0) {
|
||||
lg::die("Invalid BlockParams: {} had sector count {}", i, p.num_sectors);
|
||||
return 0;
|
||||
}
|
||||
if (!p.file_def) {
|
||||
lg::die("Invalid BlockParams: {} had no file", i);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CDvdDriver::KickDvdThread() {
|
||||
while (SetEventFlag(event_flag, 1)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
int CDvdDriver::AcquireFIFOSema(bool from_dvd_thread) {
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
|
||||
if ((from_dvd_thread != 0) &&
|
||||
(iVar2 = m_nDvdThreadAccessSemaCount, m_nDvdThreadAccessSemaCount = iVar2 + 1, 0 < iVar2)) {
|
||||
return 0;
|
||||
}
|
||||
iVar1 = WaitSema(this->fifo_access_sema);
|
||||
iVar2 = 0;
|
||||
if ((iVar1 != 0) && (iVar2 = iVar1, from_dvd_thread != 0)) {
|
||||
m_nDvdThreadAccessSemaCount = m_nDvdThreadAccessSemaCount + -1;
|
||||
iVar2 = iVar1;
|
||||
}
|
||||
return iVar2;
|
||||
}
|
||||
|
||||
int CDvdDriver::ReleaseFIFOSema(bool from_dvd_thread) {
|
||||
int iVar1;
|
||||
int iVar2;
|
||||
|
||||
if (from_dvd_thread != 0) {
|
||||
iVar2 = m_nDvdThreadAccessSemaCount + -1;
|
||||
if (m_nDvdThreadAccessSemaCount < 1) {
|
||||
return -0x1a4;
|
||||
}
|
||||
m_nDvdThreadAccessSemaCount = iVar2;
|
||||
if (0 < iVar2) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
iVar1 = SignalSema(fifo_access_sema);
|
||||
iVar2 = 0;
|
||||
if ((iVar1 != 0) && (iVar2 = iVar1, from_dvd_thread != 0)) {
|
||||
m_nDvdThreadAccessSemaCount = m_nDvdThreadAccessSemaCount + 1;
|
||||
iVar2 = iVar1;
|
||||
}
|
||||
return iVar2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* PC port added function to actually do a read of a block.
|
||||
*/
|
||||
void CDvdDriver::read_from_file(const jak3::Block* block) {
|
||||
const auto* fd = block->params.file_def;
|
||||
ASSERT(fd);
|
||||
FileCacheEntry* selected_entry = nullptr;
|
||||
|
||||
// get a cache entry
|
||||
for (auto& entry : m_file_cache) {
|
||||
// if we already opened this file, use that
|
||||
if (entry.def == fd) {
|
||||
selected_entry = &entry;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise pick the least recently used
|
||||
if (!selected_entry) {
|
||||
selected_entry = &entry;
|
||||
} else {
|
||||
if (selected_entry->last_use_count > entry.last_use_count) {
|
||||
selected_entry = &entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// open a new file if needed
|
||||
if (selected_entry->def != fd) {
|
||||
lg::debug("CDvdDriver swapping files {} - > {}",
|
||||
selected_entry->def ? selected_entry->def->name.data : "NONE", fd->name.data);
|
||||
if (selected_entry->def) {
|
||||
fclose(selected_entry->fp);
|
||||
}
|
||||
|
||||
selected_entry->def = fd;
|
||||
selected_entry->fp = file_util::open_file(fd->full_path, "rb");
|
||||
if (!selected_entry->fp) {
|
||||
lg::die("Failed to open {} {}", fd->full_path, strerror(errno));
|
||||
}
|
||||
selected_entry->offset_in_file = 0;
|
||||
}
|
||||
|
||||
// increment use counter
|
||||
selected_entry->last_use_count = m_file_cache_counter++;
|
||||
|
||||
const u64 desired_offset = block->params.sector_num * 0x800;
|
||||
|
||||
// see if we're reading entirely past the end of the file
|
||||
if (desired_offset >= fd->length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected_entry->offset_in_file != desired_offset) {
|
||||
lg::debug("CDvdDriver jumping in file {}: {} -> {}", fd->name.data,
|
||||
selected_entry->offset_in_file, desired_offset);
|
||||
if (fseek(selected_entry->fp, desired_offset, SEEK_SET)) {
|
||||
ASSERT_NOT_REACHED_MSG("Failed to fseek");
|
||||
}
|
||||
selected_entry->offset_in_file = desired_offset;
|
||||
}
|
||||
|
||||
// read
|
||||
s64 read_length = block->params.num_sectors * 0x800;
|
||||
s64 extra_length = read_length + desired_offset - fd->length;
|
||||
if (extra_length > 0) {
|
||||
read_length -= extra_length;
|
||||
}
|
||||
auto ret = fread(block->params.destination, read_length, 1, selected_entry->fp);
|
||||
if (ret != 1) {
|
||||
lg::die("Failed to read {} {}, size {} of {} (ret {})", fd->full_path, strerror(errno),
|
||||
read_length, fd->length, ret);
|
||||
}
|
||||
selected_entry->offset_in_file += read_length;
|
||||
}
|
||||
|
||||
u32 DvdThread() {
|
||||
auto* driver = get_driver();
|
||||
|
||||
while (true) {
|
||||
// Poll for messages
|
||||
CMsg* msg = nullptr;
|
||||
while (true) {
|
||||
int poll_status = PollMbx((MsgPacket**)&msg, driver->msgbox);
|
||||
if (poll_status || !msg) {
|
||||
break;
|
||||
}
|
||||
// run message code
|
||||
msg->handler();
|
||||
// wake the waiting thread.
|
||||
WakeupThread(msg->m_thread);
|
||||
}
|
||||
|
||||
bool completed = false;
|
||||
|
||||
// if a read is in progress, wait for it to finish.
|
||||
if (driver->read_in_progress) {
|
||||
// TODO: if we switch to async reads, this is where we'd want to sync.
|
||||
// sceCdSync(0);
|
||||
completed = true;
|
||||
// error checking
|
||||
}
|
||||
|
||||
driver->AcquireFIFOSema(true);
|
||||
// error handling
|
||||
|
||||
// handle ring book-keeping.
|
||||
// note that these are somewhat double-buffered - we'll sync on read i-1, start read i, then
|
||||
// run the completion handler for read i - 1.
|
||||
// the completion is what actually removes stuff from the ring.
|
||||
|
||||
s32 fifo_slots_freed = completed ? 1 : 0;
|
||||
s32 ring_entry = driver->ring_head + (completed ? 1 : 0);
|
||||
if (ring_entry > 15) {
|
||||
ring_entry = 0;
|
||||
}
|
||||
Block* block = driver->ring + ring_entry;
|
||||
s32 fifo_entries = driver->m_nNumFifoEntries - fifo_slots_freed;
|
||||
|
||||
if (fifo_entries) {
|
||||
// start a new read.
|
||||
driver->read_in_progress = 1;
|
||||
ovrld_log(LogCategory::DRIVER, "[driver thread] Reading for slot {}", block - driver->ring);
|
||||
driver->read_from_file(block);
|
||||
|
||||
} else {
|
||||
driver->read_in_progress = 0;
|
||||
}
|
||||
|
||||
// run completion handler for the previous read - not the one we just started!
|
||||
Block sblock;
|
||||
if (completed) {
|
||||
auto* last_block = &driver->ring[driver->ring_head];
|
||||
ovrld_log(LogCategory::DRIVER, "[driver thread] Completion handler for {}",
|
||||
driver->ring_head);
|
||||
sblock = *last_block;
|
||||
|
||||
if (sblock.descriptor && sblock.descriptor->m_pHead) {
|
||||
ASSERT(sblock.descriptor->m_pHead == last_block);
|
||||
}
|
||||
if (((sblock.descriptor)->m_pHead == last_block) &&
|
||||
((sblock.descriptor)->m_pHead = &sblock, (sblock.descriptor)->m_pTail == last_block)) {
|
||||
(sblock.descriptor)->m_pTail = &sblock;
|
||||
}
|
||||
}
|
||||
driver->ring_head = ring_entry;
|
||||
driver->m_nNumFifoEntries = fifo_entries;
|
||||
while (0 < fifo_slots_freed) {
|
||||
fifo_slots_freed = fifo_slots_freed + -1;
|
||||
SignalSema(driver->fifo_entry_sema);
|
||||
}
|
||||
if (completed != 0) {
|
||||
driver->CompletionHandler(&sblock, 0);
|
||||
}
|
||||
driver->ReleaseFIFOSema(true);
|
||||
|
||||
// this logic here was modified - we go to waiting if we have no more reads.
|
||||
if (driver->m_nNumFifoEntries == 0) {
|
||||
ovrld_log(LogCategory::DRIVER, "[driver thread] No work, waiting.");
|
||||
WaitEventFlag(driver->event_flag, 1, 0x11);
|
||||
ovrld_log(LogCategory::DRIVER, "[driver thread] Woken up!");
|
||||
}
|
||||
|
||||
// s32 status;
|
||||
// if ((((driver->locked != false)) ||
|
||||
// ((driver->needs_break == 0 && (driver->m_nNumFifoEntries == 0)))) &&
|
||||
// ((status = WaitEventFlag(driver->event_flag, 1, 0x11),
|
||||
// status != 0 && (status != -0x1a2)))) {
|
||||
// if (status == -0x1a9) {
|
||||
// do {
|
||||
// SleepThread();
|
||||
// } while (true);
|
||||
// }
|
||||
// DelayThread(8000);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void CDvdDriver::CompletionHandler(jak3::Block* block, int code) {
|
||||
// there is some janky thread priority changes here,
|
||||
// but they do not seem to be needed with the changes to the ISO thread.
|
||||
|
||||
// PushPri(this,local_20,0x35);
|
||||
auto* desc = block->descriptor;
|
||||
if (desc && desc->m_pHead) {
|
||||
desc->m_status = code;
|
||||
int thread = desc->m_ThreadID;
|
||||
if (desc->m_Callback) {
|
||||
(desc->m_Callback)(desc->m_File, block, code);
|
||||
}
|
||||
if (0 < thread) {
|
||||
WakeupThread(thread);
|
||||
}
|
||||
|
||||
Block* next;
|
||||
if ((desc->m_pHead == block) && (next = block->next, desc->m_pHead = next, next == nullptr)) {
|
||||
desc->m_pTail = nullptr;
|
||||
}
|
||||
}
|
||||
block->next = nullptr;
|
||||
block->descriptor = nullptr;
|
||||
// PopPri(this, local_20[0]);
|
||||
}
|
||||
|
||||
CDvdDriver::~CDvdDriver() {
|
||||
for (auto& entry : m_file_cache) {
|
||||
if (entry.fp) {
|
||||
fclose(entry.fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace jak3
|
||||
@@ -1,144 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_dvd_driver();
|
||||
|
||||
/*!
|
||||
* The DVD Driver is what actually called the Sony CD library functions.
|
||||
* It also had many special cases for handling errors, open trays, retries, etc that are not
|
||||
* recreated in this port.
|
||||
*
|
||||
* The original DVD driver thread didn't run the actual reads - the Sony CD library had its own
|
||||
* threads for async reads. However, they would call sceCdSync() to wait until a read finished.
|
||||
* It's not clear if sceCdSync would allow other threads to run while waiting on the read to finish.
|
||||
* but if it did, this is a bit of a difference in the blocking behavior.
|
||||
*
|
||||
* This is something that could be revisited, as freads will now essentially block the entire
|
||||
* overlord, including refilling sound RAM.
|
||||
*/
|
||||
|
||||
struct CDescriptor;
|
||||
struct BlockParams;
|
||||
struct CPage;
|
||||
struct ISOFileDef;
|
||||
|
||||
// The CMSG system is used to pass messages from external threads to the driver. It's mostly used
|
||||
// internally by the driver, when functions are called on it from outside threads. In these cases
|
||||
// the Cmsg will get send to the driver thread and handler will run on it here.
|
||||
|
||||
struct CMsg {
|
||||
enum class MsgKind {
|
||||
// LOCK = 0,
|
||||
READ_RAW = 1,
|
||||
CANCEL_READ = 2,
|
||||
};
|
||||
CMsg(MsgKind msg);
|
||||
virtual int send();
|
||||
virtual void handler() = 0;
|
||||
|
||||
u8 data[8];
|
||||
MsgKind m_msg;
|
||||
int m_thread;
|
||||
int m_ret;
|
||||
};
|
||||
|
||||
// struct CMsgLock : public CMsg {
|
||||
// CMsgLock();
|
||||
// void handler() override;
|
||||
// };
|
||||
|
||||
// struct CMsgReadRaw : public CMsg {
|
||||
// explicit CMsgReadRaw(BlockParams* params);
|
||||
// void handler() override;
|
||||
// BlockParams m_block_params;
|
||||
// };
|
||||
|
||||
struct CMsgCancelRead : public CMsg {
|
||||
explicit CMsgCancelRead(CDescriptor* desc);
|
||||
void handler() override;
|
||||
CDescriptor* m_desc;
|
||||
};
|
||||
|
||||
struct CISOCDFile;
|
||||
|
||||
/*!
|
||||
* Reference to an ongoing or requested read at the driver level, possibly made up of multiple
|
||||
* blocks. In this case, the head/tail pointers point to Blocks stored inside the CDvdDriver's
|
||||
* internal FIFO.
|
||||
*/
|
||||
struct CDescriptor {
|
||||
CDescriptor() = default;
|
||||
int m_unk0 = 0;
|
||||
void (*m_Callback)(CISOCDFile*, Block*, s32) = nullptr;
|
||||
int m_ThreadID = 0;
|
||||
int m_status = 0;
|
||||
CISOCDFile* m_File = nullptr;
|
||||
Block* m_pHead = nullptr;
|
||||
Block* m_pTail = nullptr;
|
||||
};
|
||||
|
||||
class CDvdDriver {
|
||||
public:
|
||||
CDvdDriver();
|
||||
~CDvdDriver();
|
||||
void Initialize();
|
||||
void CancelRead(CDescriptor* descriptor);
|
||||
int ReadMultiple(CDescriptor* descriptor,
|
||||
int* pages_read_out,
|
||||
BlockParams* params,
|
||||
int num_pages,
|
||||
bool block_if_queue_full);
|
||||
void SetDriverCallback(std::function<void(int)> f);
|
||||
// int ReadDirect(BlockParams* params);
|
||||
void KickDvdThread();
|
||||
// void Lock();
|
||||
int GetDiskType() const { return disk_type; }
|
||||
s32 ValidateBlockParams(BlockParams* params, int num_params);
|
||||
int ReleaseFIFOSema(bool from_dvd_thread);
|
||||
int AcquireFIFOSema(bool from_dvd_thread);
|
||||
void read_from_file(const Block* block);
|
||||
void CompletionHandler(Block* block, int code);
|
||||
|
||||
u8 initialized = 0;
|
||||
s32 event_flag = -1;
|
||||
s32 fifo_access_sema = -1;
|
||||
s32 fifo_entry_sema = -1;
|
||||
s32 msgbox = -1;
|
||||
s32 m_nNumFifoEntries = 0;
|
||||
s32 ring_head = 0;
|
||||
s32 ring_tail = 0;
|
||||
Block ring[16];
|
||||
u8 read_in_progress; // more likely: read in progress
|
||||
std::function<void(int)> callback;
|
||||
s32 current_thread_priority = 0;
|
||||
// s32 m_nLockCount = 0;
|
||||
// bool locked = false;
|
||||
//
|
||||
s32 disk_type;
|
||||
u8 tray_flag2;
|
||||
u8 trayflag3;
|
||||
u8 tray_flag;
|
||||
s32 m_nDvdThreadAccessSemaCount = 0;
|
||||
|
||||
private:
|
||||
struct FileCacheEntry {
|
||||
const ISOFileDef* def = nullptr;
|
||||
FILE* fp = nullptr;
|
||||
u32 last_use_count = 0;
|
||||
u64 offset_in_file = 0;
|
||||
};
|
||||
u32 m_file_cache_counter = 0;
|
||||
static constexpr int kNumFileCacheEntries = 6;
|
||||
FileCacheEntry m_file_cache[kNumFileCacheEntries];
|
||||
};
|
||||
|
||||
// replacement for g_DvdDriver
|
||||
CDvdDriver* get_driver();
|
||||
|
||||
} // namespace jak3
|
||||
@@ -1,50 +0,0 @@
|
||||
|
||||
#include "game/overlord/jak3/basefile.h"
|
||||
#include "game/overlord/jak3/basefilesystem.h"
|
||||
#include "game/overlord/jak3/dma.h"
|
||||
#include "game/overlord/jak3/dvd_driver.h"
|
||||
#include "game/overlord/jak3/iso.h"
|
||||
#include "game/overlord/jak3/iso_api.h"
|
||||
#include "game/overlord/jak3/iso_cd.h"
|
||||
#include "game/overlord/jak3/iso_queue.h"
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
#include "game/overlord/jak3/list.h"
|
||||
#include "game/overlord/jak3/overlord.h"
|
||||
#include "game/overlord/jak3/pagemanager.h"
|
||||
#include "game/overlord/jak3/ramdisk.h"
|
||||
#include "game/overlord/jak3/sbank.h"
|
||||
#include "game/overlord/jak3/soundcommon.h"
|
||||
#include "game/overlord/jak3/spustreams.h"
|
||||
#include "game/overlord/jak3/srpc.h"
|
||||
#include "game/overlord/jak3/ssound.h"
|
||||
#include "game/overlord/jak3/stream.h"
|
||||
#include "game/overlord/jak3/streamlist.h"
|
||||
#include "game/overlord/jak3/vag.h"
|
||||
#include "game/overlord/jak3/vblank_handler.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_all() {
|
||||
jak3_overlord_init_globals_overlord();
|
||||
jak3_overlord_init_globals_pagemanager();
|
||||
jak3_overlord_init_globals_iso_cd();
|
||||
jak3_overlord_init_globals_dma();
|
||||
jak3_overlord_init_globals_iso();
|
||||
jak3_overlord_init_globals_iso_queue();
|
||||
jak3_overlord_init_globals_srpc();
|
||||
jak3_overlord_init_globals_vag();
|
||||
jak3_overlord_init_globals_ssound();
|
||||
jak3_overlord_init_globals_iso_api();
|
||||
jak3_overlord_init_globals_spustreams();
|
||||
jak3_overlord_init_globals_list();
|
||||
jak3_overlord_init_globals_vblank_handler();
|
||||
jak3_overlord_init_globals_dvd_driver();
|
||||
jak3_overlord_init_globals_basefile();
|
||||
jak3_overlord_init_globals_basefilesystem();
|
||||
jak3_overlord_init_globals_ramdisk();
|
||||
jak3_overlord_init_globals_isocommon();
|
||||
jak3_overlord_init_globals_stream();
|
||||
jak3_overlord_init_globals_sbank();
|
||||
jak3_overlord_init_globals_soundcommon();
|
||||
jak3_overlord_init_globals_streamlist();
|
||||
}
|
||||
} // namespace jak3
|
||||
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_all();
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,92 +0,0 @@
|
||||
#pragma once
|
||||
#include "common/link_types.h"
|
||||
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
|
||||
namespace jak3 {
|
||||
struct ISOFileDef;
|
||||
void jak3_overlord_init_globals_iso();
|
||||
void InitISOFS();
|
||||
|
||||
const ISOFileDef* FindISOFile(const char*);
|
||||
struct ISO_VAGCommand;
|
||||
struct VagStreamData;
|
||||
struct RPC_Dgo_Cmd;
|
||||
|
||||
struct ISO_DGOCommand : public ISO_Hdr {
|
||||
u8* buffer1 = nullptr;
|
||||
u8* buffer2 = nullptr;
|
||||
u8* buffer_top = nullptr;
|
||||
DgoHeader dgo_header; //
|
||||
ObjectHeader obj_header; //
|
||||
u8* ee_dest_buffer = nullptr; // 192
|
||||
int bytes_processed = 0; // 196
|
||||
int objects_loaded = 0; // 200
|
||||
enum class State {
|
||||
INIT = 0,
|
||||
READ_DGO_HEADER = 1,
|
||||
FINISH_OBJ = 2,
|
||||
READ_LAST_OBJ = 3,
|
||||
READ_OBJ_HEADER = 4,
|
||||
READ_OBJ_DATA = 5,
|
||||
FINISH_DGO = 6,
|
||||
FINISH_OBJ_SINGLE_BUFFER = 7,
|
||||
} state = State::INIT; // 204
|
||||
int finished_first_object = 0; // 208
|
||||
int buffer_toggle = 0; // 212
|
||||
u8* selected_buffer = nullptr; // 216
|
||||
int selected_id = 0; // 220
|
||||
int last_id = 0; // 224
|
||||
int acked_cancel_id = 0; // 228
|
||||
u8 nosync_cancel_pending_flag = 0; // 232
|
||||
int request_cancel_id = 0; // 236
|
||||
u8 nosync_cancel_ack = 0; // 240
|
||||
int sync_sent_count = 0; // 244
|
||||
|
||||
// the number of times we looked in the iso thread's sync mbox
|
||||
// I think just used for debugging/asserts.
|
||||
int sync_mbox_wait_count = 0; // 248
|
||||
|
||||
int sync_ret_count = 0; // 252
|
||||
int want_abort = 0; // 256
|
||||
};
|
||||
|
||||
enum class CopyKind {
|
||||
EE = 0,
|
||||
IOP = 1,
|
||||
SBK = 2,
|
||||
};
|
||||
|
||||
void set_active_a(ISO_Hdr* cmd, int val);
|
||||
void set_active_b(ISO_Hdr* cmd, int val);
|
||||
void set_active_c(ISO_Hdr* cmd, int val);
|
||||
void IsoStopVagStream(ISO_VAGCommand* cmd);
|
||||
void IsoPlayVagStream(ISO_VAGCommand* user_cmd);
|
||||
EIsoStatus NullCallback(ISO_Hdr* msg);
|
||||
EIsoStatus CopyDataToIOP(ISO_Hdr* msg);
|
||||
EIsoStatus CopyDataSbkLoad(ISO_Hdr* msg);
|
||||
EIsoStatus CopyDataToEE(ISO_Hdr* msg);
|
||||
EIsoStatus RunDGOStateMachine(ISO_Hdr* msg);
|
||||
void QueueVAGStream(VagStreamData* cmd);
|
||||
void CopyDataDmaCallback(void*);
|
||||
void* RPC_DGO(unsigned int fno, void* msg_ptr, int);
|
||||
void LoadDGO(RPC_Dgo_Cmd* cmd);
|
||||
void CancelDGO(RPC_Dgo_Cmd* cmd);
|
||||
void LoadNextDGO(RPC_Dgo_Cmd* cmd);
|
||||
EIsoStatus CopyData(ISO_LoadCommon* msg, CopyKind kind);
|
||||
void CancelDGONoSync(int id);
|
||||
void IsoPlayMusicStream(ISO_VAGCommand* user_cmd);
|
||||
void IsoQueueVagStream(ISO_VAGCommand* user_cmd);
|
||||
extern int g_nISOThreadID;
|
||||
extern int g_nISOMbx;
|
||||
extern bool g_bMusicPause;
|
||||
extern int g_nMusicSemaphore;
|
||||
extern char g_szTargetMusicName[0x30];
|
||||
extern int g_nActiveMusicStreams;
|
||||
extern bool g_bVagCmdsInitialized;
|
||||
extern bool g_bMusicIsPaused;
|
||||
extern bool g_bAnotherMusicPauseFlag;
|
||||
extern int g_nMusicFade;
|
||||
extern int g_nMusicTweak;
|
||||
extern int g_nMusicFadeDir;
|
||||
} // namespace jak3
|
||||
@@ -1,229 +0,0 @@
|
||||
#include "iso_api.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
#include "game/overlord/jak3/iso.h"
|
||||
#include "game/overlord/jak3/iso_cd.h"
|
||||
#include "game/overlord/jak3/iso_queue.h"
|
||||
#include "game/overlord/jak3/srpc.h"
|
||||
#include "game/overlord/jak3/vag.h"
|
||||
#include "game/sce/iop.h"
|
||||
|
||||
namespace jak3 {
|
||||
using namespace iop;
|
||||
void jak3_overlord_init_globals_iso_api() {}
|
||||
|
||||
/*!
|
||||
* This file is the "API" that implementations of RPCs or other code can use to submit things to the
|
||||
* ISO thread. Note that not all RPCs use this API - for example the DGO RPC just manually submits
|
||||
* messages. Generally, these functions will not return until the actual action is complete, like a
|
||||
* file is loaded.
|
||||
* - except for messages to pause/play audio, those functions will return immediately, but there may
|
||||
* be a delay until they are actually processed.
|
||||
*/
|
||||
|
||||
// PluginVagAndVagWad not ported.
|
||||
|
||||
u32 EEVagAndVagWad(ISO_VAGCommand* cmd, char* name) {
|
||||
ISOName name_buff;
|
||||
if (*name == '$' || strlen(name) < 9) {
|
||||
if (*name == '$') {
|
||||
name++;
|
||||
}
|
||||
MakeISOName(&name_buff, name);
|
||||
} else {
|
||||
file_util::ISONameFromAnimationName(name_buff.data, name);
|
||||
}
|
||||
|
||||
cmd->vag_dir_entry = get_file_system()->FindVAGFile(name_buff.data);
|
||||
if (cmd->vag_dir_entry) {
|
||||
memcpy(name_buff.data, "VAGWAD ", 8);
|
||||
strncpy(name_buff.data + 8, g_pszLanguage, 4);
|
||||
auto* file_def = get_file_system()->FindIN(&name_buff);
|
||||
// piVar1 = g_pFileSystem;
|
||||
cmd->file_def = file_def;
|
||||
|
||||
strncpy(name_buff.data + 8, "INT", 4);
|
||||
|
||||
cmd->vag_file_def = get_file_system()->FindIN(&name_buff);
|
||||
if (cmd->vag_dir_entry && cmd->file_def && cmd->vag_file_def) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
cmd->vag_dir_entry = nullptr;
|
||||
cmd->file_def = nullptr;
|
||||
cmd->vag_file_def = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LoadISOFileToIOP(const ISOFileDef* file_def, void* addr, int length) {
|
||||
ISO_LoadSingle cmd;
|
||||
cmd.msg_type = ISO_Hdr::MsgType::LOAD_IOP;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = GetThreadId();
|
||||
cmd.file_def = file_def;
|
||||
cmd.addr = (u8*)addr;
|
||||
cmd.maxlen = length;
|
||||
lg::warn("--------------- LoadISOFileToIOP START");
|
||||
SendMbx(g_nISOMbx, &cmd);
|
||||
SleepThread();
|
||||
lg::warn("--------------- LoadISOFileToIOP END");
|
||||
if (cmd.status == EIsoStatus::NONE_0) {
|
||||
return cmd.length_to_copy;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int LoadISOFileToEE(const ISOFileDef* file_def, u32 addr, int length) {
|
||||
ISO_LoadSingle cmd;
|
||||
cmd.msg_type = ISO_Hdr::MsgType::LOAD_EE;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = GetThreadId();
|
||||
cmd.file_def = file_def;
|
||||
cmd.addr = (u8*)(u64)addr;
|
||||
cmd.maxlen = length;
|
||||
lg::warn("--------------- LoadISOFileToEE START");
|
||||
SendMbx(g_nISOMbx, &cmd);
|
||||
SleepThread();
|
||||
lg::warn("--------------- LoadISOFileToEE END");
|
||||
if (cmd.status == EIsoStatus::NONE_0) {
|
||||
return cmd.length_to_copy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LoadISOFileChunkToEE(const ISOFileDef* file_def, u32 addr, int max_len, int sector_offset) {
|
||||
ISO_LoadSingle cmd;
|
||||
cmd.msg_type = ISO_Hdr::MsgType::LOAD_EE_CHUNK;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = GetThreadId();
|
||||
cmd.file_def = file_def;
|
||||
cmd.addr = (u8*)(u64)addr;
|
||||
cmd.maxlen = max_len;
|
||||
cmd.sector_offset = sector_offset;
|
||||
lg::warn("--------------- LoadISOFileChunkToEE START");
|
||||
SendMbx(g_nISOMbx, &cmd);
|
||||
SleepThread();
|
||||
lg::warn("--------------- LoadISOFileChunkToEE END");
|
||||
if (cmd.status == EIsoStatus::NONE_0) {
|
||||
return cmd.length_to_copy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 LoadSoundBankToIOP(const char* name, SoundBankInfo* bank, u32 mode) {
|
||||
ISO_LoadSoundbank cmd;
|
||||
cmd.msg_type = ISO_Hdr::MsgType::LOAD_SOUNDBANK;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = GetThreadId();
|
||||
cmd.bank_info = bank;
|
||||
cmd.name = name;
|
||||
cmd.priority = mode;
|
||||
lg::warn("--------------- LoadSoundBankToIOP START");
|
||||
SendMbx(g_nISOMbx, &cmd);
|
||||
SleepThread();
|
||||
lg::warn("--------------- LoadSoundBankToIOP END");
|
||||
|
||||
return (u32)cmd.status;
|
||||
}
|
||||
|
||||
void PlayMusicStream(VagStreamData* stream) {
|
||||
int iVar1;
|
||||
ISO_VAGCommand cmd;
|
||||
|
||||
cmd.msg_type = ISO_Hdr::MsgType::PLAY_MUSIC_STREAM;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = 0;
|
||||
iVar1 = EEVagAndVagWad(&cmd, stream->name);
|
||||
if (iVar1 == 0) {
|
||||
// if (bWarn == 0) {
|
||||
// bWarn = 1;
|
||||
// }
|
||||
} else {
|
||||
cmd.play_volume = 0x400;
|
||||
// bWarn = 0;
|
||||
strncpy(cmd.name, stream->name, 0x30);
|
||||
cmd.id = stream->id;
|
||||
cmd.priority_pq = 9;
|
||||
cmd.music_flag = 1;
|
||||
cmd.maybe_sound_handler = 0;
|
||||
cmd.plugin_id = 0;
|
||||
cmd.art_flag = 0;
|
||||
cmd.movie_flag = 0;
|
||||
cmd.updated_trans = 0;
|
||||
IsoPlayMusicStream(&cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void QueueVAGStream(VagStreamData* stream) {
|
||||
bool bVar1;
|
||||
bool bVar2;
|
||||
ISO_VAGCommand cmd;
|
||||
|
||||
cmd.msg_type = ISO_Hdr::MsgType::VAG_QUEUE;
|
||||
cmd.mbox_reply = 0;
|
||||
cmd.thread_to_wake = 0;
|
||||
if (stream->sound_handler == 0) {
|
||||
EEVagAndVagWad(&cmd, stream->name);
|
||||
cmd.play_volume = 0x400;
|
||||
cmd.play_group = 2;
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
// PluginVagAndVagWad(&cmd,stream);
|
||||
// cmd.play_volume = stream->maybe_volume2;
|
||||
// cmd.oog = stream->maybe_volume_3;
|
||||
// cmd.play_group = stream->group;
|
||||
}
|
||||
strncpy(cmd.name, stream->name, 0x30);
|
||||
cmd.id = stream->id;
|
||||
cmd.plugin_id = stream->plugin_id;
|
||||
cmd.priority_pq = stream->priority;
|
||||
cmd.maybe_sound_handler = stream->sound_handler;
|
||||
bVar1 = stream->movie_art_load != 0;
|
||||
cmd.movie_flag = bVar1;
|
||||
bVar2 = stream->art_load != 0;
|
||||
cmd.art_flag = bVar2;
|
||||
cmd.music_flag = 0;
|
||||
if (bVar2) {
|
||||
cmd.flags.art = 1;
|
||||
}
|
||||
if (bVar1) {
|
||||
cmd.flags.movie = 1;
|
||||
}
|
||||
cmd.updated_trans = 0;
|
||||
IsoQueueVagStream(&cmd);
|
||||
}
|
||||
|
||||
void PauseVAGStreams() {
|
||||
auto* cmd = GetVAGCommand();
|
||||
cmd->msg_type = ISO_Hdr::MsgType::VAG_PAUSE;
|
||||
cmd->mbox_reply = 0;
|
||||
cmd->thread_to_wake = 0;
|
||||
SendMbx(g_nISOMbx, cmd);
|
||||
}
|
||||
|
||||
void UnpauseVAGStreams() {
|
||||
auto* cmd = GetVAGCommand();
|
||||
cmd->msg_type = ISO_Hdr::MsgType::VAG_UNPAUSE;
|
||||
cmd->mbox_reply = 0;
|
||||
cmd->thread_to_wake = 0;
|
||||
SendMbx(g_nISOMbx, cmd);
|
||||
}
|
||||
|
||||
void SetVAGStreamPitch(int id, int pitch) {
|
||||
auto* cmd = GetVAGCommand();
|
||||
cmd->msg_type = ISO_Hdr::MsgType::VAG_SET_PITCH_VOL;
|
||||
cmd->id = id;
|
||||
cmd->pitch_cmd = pitch;
|
||||
cmd->mbox_reply = 0;
|
||||
cmd->thread_to_wake = 0;
|
||||
SendMbx(g_nISOMbx, cmd);
|
||||
}
|
||||
|
||||
} // namespace jak3
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_iso_api();
|
||||
|
||||
struct ISOFileDef;
|
||||
struct VagStreamData;
|
||||
struct SoundBankInfo;
|
||||
|
||||
int LoadISOFileToEE(const ISOFileDef* file_def, u32 addr, int length);
|
||||
int LoadISOFileToIOP(const ISOFileDef* file_def, void* addr, int length);
|
||||
void PlayMusicStream(VagStreamData* data);
|
||||
int LoadISOFileChunkToEE(const ISOFileDef* file_def, u32 addr, int max_len, int sector_offset);
|
||||
void SetVAGStreamPitch(s32 id, s32 pitch);
|
||||
void UnpauseVAGStreams();
|
||||
u32 LoadSoundBankToIOP(const char* name, SoundBankInfo* bank, u32 mode);
|
||||
} // namespace jak3
|
||||
@@ -1,529 +0,0 @@
|
||||
#include "iso_cd.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
|
||||
#include "game/overlord/jak3/iso.h"
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
#include "game/overlord/jak3/overlord.h"
|
||||
#include "game/overlord/jak3/spustreams.h"
|
||||
#include "game/sce/iop.h"
|
||||
|
||||
using namespace iop;
|
||||
|
||||
namespace jak3 {
|
||||
VagDir g_VagDir;
|
||||
MusicTweaks gMusicTweakInfo;
|
||||
CISOCDFile g_CISOCDFiles[kMaxOpenFiles];
|
||||
|
||||
namespace {
|
||||
CISOCDFile* g_pReadInfo = nullptr;
|
||||
std::vector<ISOFileDef> g_FileDefs;
|
||||
std::unique_ptr<CISOCDFileSystem> g_ISOCDFileSystem;
|
||||
} // namespace
|
||||
|
||||
void jak3_overlord_init_globals_iso_cd() {
|
||||
g_pReadInfo = nullptr;
|
||||
for (auto& f : g_CISOCDFiles) {
|
||||
f = CISOCDFile();
|
||||
}
|
||||
g_FileDefs.clear();
|
||||
g_VagDir = {};
|
||||
g_ISOCDFileSystem = std::make_unique<CISOCDFileSystem>();
|
||||
gMusicTweakInfo = {};
|
||||
}
|
||||
|
||||
CBaseFileSystem* get_file_system() {
|
||||
return g_ISOCDFileSystem.get();
|
||||
}
|
||||
|
||||
CISOCDFile::CISOCDFile() {
|
||||
m_nSector = -1;
|
||||
m_nLoaded = 0;
|
||||
m_nLength = 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void ReadPagesCallbackF(CISOCDFile* file, Block* block, s32 error) {
|
||||
file->ReadPagesCallback(block, error);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CISOCDFile::CISOCDFile(const jak3::ISOFileDef* filedef, s32 process_data_semaphore)
|
||||
: CBaseFile(filedef, process_data_semaphore) {
|
||||
m_nSector = -1;
|
||||
m_nLoaded = 0;
|
||||
m_nLength = 0;
|
||||
m_Descriptor.m_File = this;
|
||||
m_Descriptor.m_Callback = ReadPagesCallbackF;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Call ReadPages to read data from this file into its PageList. I believe that the read
|
||||
* is finished after this function returns. Note that this returns COMPLETE enum in many cases, both
|
||||
* if the read succeeds, or if the read is not attempted for some reasons.
|
||||
*/
|
||||
EIsoStatus CISOCDFile::BeginRead() {
|
||||
ASSERT(m_Buffer.m_pPageList);
|
||||
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
|
||||
|
||||
if (m_Status == EIsoStatus::NONE_0) {
|
||||
return EIsoStatus::ERROR_b;
|
||||
}
|
||||
|
||||
if (m_Status == EIsoStatus::OK_2) {
|
||||
return EIsoStatus::OK_2;
|
||||
}
|
||||
|
||||
ASSERT(m_Status == EIsoStatus::IDLE_1);
|
||||
|
||||
auto* plist = m_Buffer.m_pPageList;
|
||||
|
||||
// how many pages are in our list, but not filled?
|
||||
int num_pages_desired = plist->m_nNumPages - plist->m_nNumActivePages;
|
||||
|
||||
if (!num_pages_desired) {
|
||||
// no space to read
|
||||
return EIsoStatus::OK_2;
|
||||
}
|
||||
|
||||
// convert pages to active, indicating that a read will attempt to fill them:
|
||||
auto* first_page = plist->AddActivePages(num_pages_desired);
|
||||
if (!first_page) {
|
||||
lg::warn("Failed to add {} active pages", num_pages_desired);
|
||||
}
|
||||
|
||||
// convert buffer type - ??
|
||||
switch (m_Buffer.m_eBufferType) {
|
||||
case CBuffer::BufferType::EBT_FREE:
|
||||
ASSERT_NOT_REACHED();
|
||||
case CBuffer::BufferType::NORMAL:
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::REQUEST_NORMAL;
|
||||
break;
|
||||
case CBuffer::BufferType::VAG:
|
||||
m_Buffer.m_eBufferType = CBuffer::BufferType::REQUEST_VAG;
|
||||
break;
|
||||
case CBuffer::BufferType::REQUEST_NORMAL:
|
||||
case CBuffer::BufferType::REQUEST_VAG:
|
||||
break;
|
||||
}
|
||||
|
||||
m_Status = EIsoStatus::OK_2;
|
||||
|
||||
// remember this as our currently reading file
|
||||
g_pReadInfo = this;
|
||||
if (m_FileKind != CBaseFile::Kind::LZO_COMPRESSED) {
|
||||
if (m_nLength == 0 || m_nLoaded < m_nLength) {
|
||||
ovrld_log(LogCategory::PAGING, "Calling ReadPages: sector {}, pages {}", m_nSector,
|
||||
num_pages_desired);
|
||||
ReadPages(m_nSector, first_page, num_pages_desired, nullptr, true);
|
||||
int bytes = 0x8000 * num_pages_desired;
|
||||
m_nLoaded += bytes;
|
||||
m_Buffer.AddData(bytes);
|
||||
m_nSector += bytes >> 0xb;
|
||||
}
|
||||
} else {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
return EIsoStatus::OK_2;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Called by ?? to indicate that the read is done.
|
||||
*/
|
||||
EIsoStatus CISOCDFile::SyncRead() {
|
||||
if (m_Status != EIsoStatus::IDLE_1 && g_pReadInfo) {
|
||||
if (m_Status == EIsoStatus::OK_2) {
|
||||
m_Status = EIsoStatus::IDLE_1;
|
||||
}
|
||||
g_pReadInfo = nullptr;
|
||||
return EIsoStatus::OK_2;
|
||||
}
|
||||
return EIsoStatus::ERROR_b;
|
||||
}
|
||||
|
||||
/*!
|
||||
* As soon as possible, stop ongoing reads and free buffers.
|
||||
*/
|
||||
void CISOCDFile::Close() {
|
||||
// cancel ongoing reading in the driver
|
||||
get_driver()->CancelRead(&m_Descriptor);
|
||||
|
||||
ASSERT(m_FileKind != CBaseFile::Kind::LZO_COMPRESSED); // unsupported in pc
|
||||
if (this == g_pReadInfo) {
|
||||
g_pReadInfo = nullptr;
|
||||
}
|
||||
|
||||
if (m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE) {
|
||||
TerminateBuffer();
|
||||
}
|
||||
|
||||
// reset self
|
||||
*this = CISOCDFile();
|
||||
}
|
||||
|
||||
/*!
|
||||
* In the case where we have run out of page memory, take pages that we have loaded, but aren't yet
|
||||
* using, and discard them back to the pool.
|
||||
*/
|
||||
int CISOCDFile::RecoverPages(int num_pages_desired) {
|
||||
// we only allow ourselves to recover pages for VAG streaming.
|
||||
if (!m_Buffer.m_pIsoCmd || m_Buffer.m_pIsoCmd->callback != ProcessVAGData) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lock semaphore for processing
|
||||
ASSERT(m_ProcessDataSemaphore != -1);
|
||||
WaitSema(m_ProcessDataSemaphore);
|
||||
auto* plist = m_Buffer.m_pPageList;
|
||||
int num_removed = 0;
|
||||
if (plist) {
|
||||
int pages_to_ask_for = plist->m_nNumUnsteppedPages;
|
||||
if (pages_to_ask_for > 1) {
|
||||
// don't ask for more than user asked for
|
||||
if (pages_to_ask_for > num_pages_desired) {
|
||||
pages_to_ask_for = num_pages_desired;
|
||||
}
|
||||
num_removed = plist->RemoveActivePages(pages_to_ask_for);
|
||||
if (num_removed) {
|
||||
m_nSector -= 0x10 * num_removed;
|
||||
m_nLoaded -= 0x8000 * num_removed;
|
||||
// suspend intr
|
||||
ASSERT(m_Buffer.m_nDataLength >= 0);
|
||||
if (m_Buffer.m_nDataLength > 0) {
|
||||
m_Buffer.AddData(-num_removed * 0x8000);
|
||||
}
|
||||
// resume intr
|
||||
ASSERT(m_nLoaded >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move our reading pointer back.
|
||||
m_PageOffset -= num_removed;
|
||||
// unlock processing
|
||||
SignalSema(m_ProcessDataSemaphore);
|
||||
return num_removed;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the next sector to read.
|
||||
*/
|
||||
int CISOCDFile::GetSector() {
|
||||
return m_nSector;
|
||||
}
|
||||
|
||||
// WaitForLZOPages - not ported.
|
||||
|
||||
void CISOCDFile::ReadPages(int sector,
|
||||
jak3::CPage* destination_page,
|
||||
int num_pages,
|
||||
char* done_flag_ptr,
|
||||
bool sleep_until_done) {
|
||||
ASSERT(destination_page);
|
||||
ASSERT(num_pages >= 1);
|
||||
|
||||
constexpr int kMaxPages = 24;
|
||||
// I _think_ this might have been an alloca...
|
||||
BlockParams params_array[kMaxPages];
|
||||
ASSERT(num_pages <= kMaxPages);
|
||||
|
||||
// iVar2 = -((num_pages + -1) * 0x14 + 0x1bU & 0xfffffff8);
|
||||
// params = (BlockParams*)((int)local_30 + iVar2);
|
||||
BlockParams* params = params_array;
|
||||
|
||||
// increment our progress in the file - the distributed update of the various progress integers
|
||||
// is somewhat confusing, especially since failures here don't seem to reset it properly.
|
||||
m_PageOffset += num_pages;
|
||||
|
||||
// Set up block params for each page to read
|
||||
CPage* page = destination_page;
|
||||
int pg_remaining = num_pages;
|
||||
do {
|
||||
page->input_state = CPage::State::READING;
|
||||
ClearEventFlag(get_page_manager()->m_CCache.m_PagesFilledEventFlag, ~page->mask);
|
||||
|
||||
params->destination = page->m_pPageMemStart;
|
||||
params->num_sectors = 0x10;
|
||||
params->sector_num = sector;
|
||||
params->file_def = m_FileDef;
|
||||
params->page = page;
|
||||
|
||||
params->flag = nullptr;
|
||||
if (pg_remaining == 1) { // on the last page...
|
||||
params->flag = (char*)0xffffffff; // flag this
|
||||
if (!sleep_until_done) {
|
||||
params->flag = done_flag_ptr;
|
||||
}
|
||||
}
|
||||
ovrld_log(LogCategory::PAGING, "[paging] building block for driver: 0x{:x}, {}, {}, flag: {}",
|
||||
(u64)params->destination, params->sector_num, params->file_def->name.data,
|
||||
(u64)params->flag);
|
||||
page = page->m_pNextPage;
|
||||
pg_remaining = pg_remaining + -1;
|
||||
sector += 0x10;
|
||||
params++;
|
||||
} while (page && pg_remaining > 0);
|
||||
|
||||
if (pg_remaining == 0) {
|
||||
// we set up block params for all the requested pages.
|
||||
int pages_actually_read = -1;
|
||||
|
||||
ovrld_log(LogCategory::PAGING, "[paging] Submitting {} blocks to driver.\n", num_pages);
|
||||
int status = get_driver()->ReadMultiple(&m_Descriptor, &pages_actually_read, params_array,
|
||||
num_pages, true);
|
||||
if ((status == 0) && pages_actually_read == num_pages) {
|
||||
if (!sleep_until_done) {
|
||||
return;
|
||||
}
|
||||
// put us to sleep...
|
||||
ovrld_log(LogCategory::PAGING, "[paging] Sleeping, waiting for driver to read {}",
|
||||
pages_actually_read);
|
||||
SleepThread();
|
||||
ovrld_log(LogCategory::PAGING, "[paging] Driver woke us up!");
|
||||
return;
|
||||
}
|
||||
ASSERT_NOT_REACHED(); // unexpected failure to issue read
|
||||
} else {
|
||||
// ran out of pages....
|
||||
ASSERT_NOT_REACHED(); // this was just a warning.. but I think it shouldn't happen.
|
||||
if (destination_page) {
|
||||
do {
|
||||
destination_page->input_state = CPage::State::ACTIVE;
|
||||
ClearEventFlag(get_page_manager()->m_CCache.m_PagesFilledEventFlag,
|
||||
~destination_page->mask);
|
||||
destination_page = destination_page->m_pNextPage;
|
||||
} while (destination_page);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED();
|
||||
// only get here is we failed.... set the done flag.
|
||||
if (sleep_until_done == 0 && done_flag_ptr) {
|
||||
*done_flag_ptr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Callback run by the dvd driver when a page is finished reading.
|
||||
*/
|
||||
void CISOCDFile::ReadPagesCallback(jak3::Block* block, int error) {
|
||||
if (error == 0) {
|
||||
ASSERT(block->params.page->m_nAllocState == 1);
|
||||
// flag page as done
|
||||
block->params.page->input_state = CPage::State::READ_DONE;
|
||||
// set flag
|
||||
SetEventFlag(get_page_manager()->m_CCache.m_PagesFilledEventFlag, block->params.page->mask);
|
||||
|
||||
// if this block has a notification, process it:
|
||||
if (block->params.flag == (char*)0xffffffff) { // indicates we should wake caller
|
||||
// we assume the caller is the iso thread
|
||||
WakeupThread(g_nISOThreadID);
|
||||
} else if (block->params.flag) {
|
||||
// in this case, it's a pointer.
|
||||
*block->params.flag = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DecompressBlock - not ported
|
||||
|
||||
/*!
|
||||
* Initialize the file system - find all files and set up their definitions.
|
||||
*/
|
||||
int CISOCDFileSystem::Init() {
|
||||
// drive ready event flag - not ported
|
||||
// get disc type - not ported
|
||||
|
||||
// this is mostly not needed... except for some vag pausing nonsense :(
|
||||
get_driver()->SetDriverCallback([&](int a) { DvdDriverCallback(a); });
|
||||
|
||||
// skipped a bunch of lzo pages crap
|
||||
ReadDirectory();
|
||||
LoadMusicTweaks();
|
||||
// skip load Disc ID
|
||||
|
||||
// should already be done in the constructor...
|
||||
for (auto& f : g_CISOCDFiles) {
|
||||
f.m_FileDef = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// PollDrive - not ported
|
||||
|
||||
/*!
|
||||
* Find a file definition by name.
|
||||
*/
|
||||
ISOFileDef* CISOCDFileSystem::Find(const char* name) {
|
||||
ISOName iname;
|
||||
file_util::MakeISOName(iname.data, name);
|
||||
return FindIN(&iname);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Find a file definition by its "ISO Name", a 12-byte name.
|
||||
*/
|
||||
ISOFileDef* CISOCDFileSystem::FindIN(const jak3::ISOName* name) {
|
||||
for (auto& def : g_FileDefs) {
|
||||
if (def.name == *name) {
|
||||
return &def;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the length of a file, in bytes.
|
||||
*/
|
||||
int CISOCDFileSystem::GetLength(const jak3::ISOFileDef* file) {
|
||||
// return file->length;
|
||||
lg::info("getlength");
|
||||
file_util::assert_file_exists(file->full_path.c_str(), "CISOCDFileSystem GetLength");
|
||||
FILE* fp = file_util::open_file(file->full_path.c_str(), "rb");
|
||||
ASSERT(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
uint32_t len = ftell(fp);
|
||||
fclose(fp);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Open a file for reading.
|
||||
*/
|
||||
CBaseFile* CISOCDFileSystem::Open(const jak3::ISOFileDef* file_def,
|
||||
int sector_offset,
|
||||
int file_kind) {
|
||||
auto* file = AllocateFile(file_def);
|
||||
ASSERT(file);
|
||||
|
||||
// file kind must be known to be non-compressed (1). (TODO: remove arg)
|
||||
ASSERT(file_kind == 1);
|
||||
|
||||
file->m_FileKind = CBaseFile::Kind::NORMAL;
|
||||
file->m_nLength = file_def->length;
|
||||
file->m_LengthPages = (0x7fff + file->m_nLength) >> 0xf;
|
||||
if (file->m_LengthPages < 1) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
file->m_nLoaded = 0;
|
||||
file->m_PageOffset = 0;
|
||||
|
||||
// in the original game, this was the sector of the start of the file
|
||||
// we just make it 0, since we don't build up a whole iso file.
|
||||
file->m_nSector = 0;
|
||||
if (sector_offset != -1) {
|
||||
file->m_nSector += sector_offset;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Open a WAD file for reading, given the offset of the data to read, in pages.
|
||||
*/
|
||||
CBaseFile* CISOCDFileSystem::OpenWAD(const jak3::ISOFileDef* file_def, int page_offset) {
|
||||
auto* file = AllocateFile(file_def);
|
||||
ASSERT(file);
|
||||
|
||||
file->m_LengthPages = 1; // this is not really true..
|
||||
file->m_FileKind = CBaseFile::Kind::NORMAL;
|
||||
file->m_PageOffset = 0;
|
||||
file->m_nSector = page_offset * 0x10;
|
||||
file->m_nLoaded = 0;
|
||||
file->m_nLength = 0;
|
||||
return file;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Locate the entry for a VAG file in the VAG directory.
|
||||
*/
|
||||
VagDirEntry* CISOCDFileSystem::FindVAGFile(const char* name) {
|
||||
u32 packed_name[2];
|
||||
PackVAGFileName(packed_name, name);
|
||||
for (int i = 0; i < g_VagDir.num_entries; i++) {
|
||||
auto& entry = g_VagDir.entries[i];
|
||||
if (packed_name[0] == entry.words[0] && packed_name[1] == (entry.words[1] & 0x3ff)) {
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get a CISOCDFile* for a newly opened file.
|
||||
*/
|
||||
CISOCDFile* CISOCDFileSystem::AllocateFile(const jak3::ISOFileDef* file_def) {
|
||||
for (int i = 0; i < kMaxOpenFiles; i++) {
|
||||
auto* file = &g_CISOCDFiles[i];
|
||||
if (!file->m_FileDef) {
|
||||
*file = CISOCDFile(file_def, m_Sema[i]);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Callback from the DVD driver itself into the filesystem. This was originally used for notifying
|
||||
* when the tray is opened or closed.
|
||||
*/
|
||||
void CISOCDFileSystem::DvdDriverCallback(int) {
|
||||
// the only callbacks that do anything are tray open/close, which we don't care about
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
// CheckDiscID - not ported
|
||||
// LoadDiscID - not ported
|
||||
// ReadSectorsNow - not ported
|
||||
|
||||
/*!
|
||||
* Find all the files on the disc and set up their information. This is modified for the PC port to
|
||||
* just search for files in the appropriate out folder.
|
||||
*/
|
||||
void CISOCDFileSystem::ReadDirectory() {
|
||||
for (const auto& f :
|
||||
fs::directory_iterator(file_util::get_jak_project_dir() / "out" / "jak3" / "iso")) {
|
||||
if (f.is_regular_file()) {
|
||||
auto& e = g_FileDefs.emplace_back();
|
||||
std::string file_name = f.path().filename().string();
|
||||
ASSERT(file_name.length() < 16); // should be 8.3.
|
||||
MakeISOName(&e.name, file_name.c_str());
|
||||
e.full_path =
|
||||
fmt::format("{}/out/jak3/iso/{}", file_util::get_jak_project_dir().string(), file_name);
|
||||
auto* fp = file_util::open_file(e.full_path, "rb");
|
||||
ASSERT(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
e.length = ftell(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Load the "Music Tweaks" file, which contains a volume setting per music track.
|
||||
*/
|
||||
void CISOCDFileSystem::LoadMusicTweaks() {
|
||||
ISOName tweakname;
|
||||
MakeISOName(&tweakname, "TWEAKVAL.MUS");
|
||||
auto file = g_ISOCDFileSystem->FindIN(&tweakname);
|
||||
if (file) {
|
||||
auto fp = file_util::open_file(file->full_path, "rb");
|
||||
ASSERT(fp);
|
||||
ASSERT(file->length <= sizeof(gMusicTweakInfo));
|
||||
auto ret = fread(&gMusicTweakInfo, file->length, 1, fp);
|
||||
ASSERT(ret == 1);
|
||||
fclose(fp);
|
||||
} else {
|
||||
lg::warn("Failed to open music tweak file.");
|
||||
gMusicTweakInfo.TweakCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Crc32 - not ported
|
||||
// ReadU32 - not ported
|
||||
|
||||
} // namespace jak3
|
||||
@@ -1,58 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "game/overlord/jak3/basefile.h"
|
||||
#include "game/overlord/jak3/basefilesystem.h"
|
||||
#include "game/overlord/jak3/dvd_driver.h"
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_iso_cd();
|
||||
|
||||
CBaseFileSystem* get_file_system();
|
||||
|
||||
extern VagDir g_VagDir;
|
||||
extern MusicTweaks gMusicTweakInfo;
|
||||
|
||||
struct CISOCDFile : public CBaseFile {
|
||||
CISOCDFile();
|
||||
CISOCDFile(const ISOFileDef* filedef, s32 process_data_semaphore);
|
||||
int m_nLoaded = 0; // bytes loaded so far
|
||||
int m_nSector = 0; // next sector to read.
|
||||
int m_nLength = 0; // bytes that we want to load. 0 for the whole file
|
||||
CDescriptor m_Descriptor;
|
||||
|
||||
EIsoStatus BeginRead() override;
|
||||
|
||||
void ReadPages(int sector,
|
||||
CPage* destination_page,
|
||||
int num_pages,
|
||||
char* done_flag_ptr,
|
||||
bool flag);
|
||||
EIsoStatus SyncRead() override;
|
||||
void Close() override;
|
||||
int RecoverPages(int num_pages) override;
|
||||
int GetSector() override;
|
||||
|
||||
void ReadPagesCallback(Block* block, int error);
|
||||
};
|
||||
|
||||
struct CISOCDFileSystem : public CBaseFileSystem {
|
||||
CISOCDFileSystem() = default;
|
||||
int Init() override;
|
||||
ISOFileDef* Find(const char* name) override;
|
||||
ISOFileDef* FindIN(const ISOName* name) override;
|
||||
int GetLength(const ISOFileDef* file) override;
|
||||
CBaseFile* Open(const ISOFileDef* file_def, int sector_offset, int file_kind) override;
|
||||
CBaseFile* OpenWAD(const ISOFileDef* file_def, int page_offset) override;
|
||||
VagDirEntry* FindVAGFile(const char* name) override;
|
||||
|
||||
void DvdDriverCallback(int a);
|
||||
void ReadDirectory();
|
||||
void LoadMusicTweaks();
|
||||
CISOCDFile* AllocateFile(const ISOFileDef* file);
|
||||
|
||||
// int m_drive_ready_event_flag = -1;
|
||||
};
|
||||
} // namespace jak3
|
||||
@@ -1,732 +0,0 @@
|
||||
#include "iso_queue.h"
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
#include "game/overlord/jak3/basefile.h"
|
||||
#include "game/overlord/jak3/dma.h"
|
||||
#include "game/overlord/jak3/iso.h"
|
||||
#include "game/overlord/jak3/isocommon.h"
|
||||
#include "game/overlord/jak3/pagemanager.h"
|
||||
#include "game/overlord/jak3/spustreams.h"
|
||||
#include "game/overlord/jak3/vag.h"
|
||||
#include "game/sce/iop.h"
|
||||
#include "game/sound/sndshim.h"
|
||||
|
||||
using namespace iop;
|
||||
|
||||
namespace jak3 {
|
||||
s32 g_nPriQueueSema = 0;
|
||||
s32 g_VagCmdSema = 0;
|
||||
u32 g_auStrmSRAM[6];
|
||||
u32 g_auTrapSRAM[6];
|
||||
PriStackEntry gPriStack[2];
|
||||
extern u32 time_of_last_unknown_rate_drive_op;
|
||||
u32 g_cmds_with_speed_total = 0;
|
||||
bool unk_time_mode_flag = false;
|
||||
ISO_Hdr* g_selected_cmd = nullptr;
|
||||
bool unk_time_mflag = 0;
|
||||
s32 unk_sector = 0;
|
||||
u32 vag_cmd_cnt = 0;
|
||||
u32 vag_cmd_used = 0;
|
||||
u32 max_vag_cmd_cnt = 0;
|
||||
ISO_VAGCommand vag_cmds[16];
|
||||
|
||||
static constexpr s32 LOOP_END = 1;
|
||||
static constexpr s32 LOOP_REPEAT = 2;
|
||||
static constexpr s32 LOOP_START = 4;
|
||||
|
||||
// Empty ADPCM block with loop flags
|
||||
|
||||
// clang-format off
|
||||
u8 VAG_SilentLoop[0x60] = {
|
||||
0x0, LOOP_START | LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, LOOP_END | LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void jak3_overlord_init_globals_iso_queue() {
|
||||
g_nPriQueueSema = 0;
|
||||
g_VagCmdSema = 0;
|
||||
for (auto& x : gPriStack) {
|
||||
x = {};
|
||||
}
|
||||
g_cmds_with_speed_total = 0;
|
||||
unk_time_mode_flag = false;
|
||||
g_selected_cmd = nullptr;
|
||||
unk_time_mflag = 0;
|
||||
unk_sector = 0;
|
||||
vag_cmd_cnt = 0;
|
||||
vag_cmd_used = 0;
|
||||
for (auto& x : vag_cmds) {
|
||||
x = {};
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Added function to check if there is a pending DGO load command.
|
||||
* On PC, DOG loads are really the only loading time that users see. If there is a pending
|
||||
* DGO load, we can modify logic to take advantage of PCs being dramatically faster than PS2 and
|
||||
* get much better load times.
|
||||
*/
|
||||
bool DgoCmdWaiting() {
|
||||
for (auto& level : gPriStack) {
|
||||
for (int i = 0; i < level.count; i++) {
|
||||
auto* cmd = level.cmds[i];
|
||||
|
||||
if (cmd && cmd->msg_type == ISO_Hdr::MsgType::DGO_LOAD) {
|
||||
if (cmd->m_pBaseFile) {
|
||||
auto* file = cmd->m_pBaseFile;
|
||||
if (file->m_Buffer.m_nDataLength) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InitBuffers() {
|
||||
SemaParam sema_param;
|
||||
sema_param.max_count = 1;
|
||||
sema_param.init_count = 1;
|
||||
sema_param.attr = 0;
|
||||
sema_param.option = 0;
|
||||
|
||||
g_nPriQueueSema = CreateSema(&sema_param);
|
||||
ASSERT(g_nPriQueueSema >= 0);
|
||||
get_page_manager()->Initialize();
|
||||
|
||||
g_auStrmSRAM[0] = 0x5040;
|
||||
g_auTrapSRAM[0] = 0x9040;
|
||||
snd_SRAMMarkUsed(0x5040, 0x4040);
|
||||
g_auStrmSRAM[1] = 0x9080;
|
||||
g_auTrapSRAM[1] = 0xd080;
|
||||
snd_SRAMMarkUsed(0x9080, 0x4040);
|
||||
g_auStrmSRAM[2] = 0xd0c0;
|
||||
g_auTrapSRAM[2] = 0x110c0;
|
||||
snd_SRAMMarkUsed(0xd0c0, 0x4040);
|
||||
g_auStrmSRAM[3] = 0x11100;
|
||||
g_auTrapSRAM[3] = 0x15100;
|
||||
snd_SRAMMarkUsed(0x11100, 0x4040);
|
||||
g_auStrmSRAM[4] = 0x15140; // 86384 - 48
|
||||
g_auTrapSRAM[4] = 0x19140;
|
||||
snd_SRAMMarkUsed(0x15140, 0x4040);
|
||||
g_auStrmSRAM[5] = 0x019180;
|
||||
g_auTrapSRAM[5] = 0x001d180;
|
||||
snd_SRAMMarkUsed(0x19180, 0x4040);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (!DMA_SendToSPUAndSync(VAG_SilentLoop, 0x30, g_auTrapSRAM[i], nullptr, nullptr)) {
|
||||
DelayThread(1000);
|
||||
ASSERT_NOT_REACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sema_param.max_count = 1;
|
||||
sema_param.attr = 1;
|
||||
sema_param.init_count = 1;
|
||||
sema_param.option = 0;
|
||||
g_VagCmdSema = CreateSema(&sema_param);
|
||||
ASSERT(g_VagCmdSema >= 0);
|
||||
}
|
||||
|
||||
int QueueMessage(ISO_Hdr* msg, int pri) {
|
||||
msg->status = EIsoStatus::OK_2;
|
||||
msg->priority = pri;
|
||||
WaitSema(g_nPriQueueSema);
|
||||
int queue_idx = (pri == 5) ? 1 : 0;
|
||||
bool ok = gPriStack[queue_idx].count != 8;
|
||||
if (ok) {
|
||||
gPriStack[queue_idx].cmds[gPriStack[queue_idx].count] = msg;
|
||||
gPriStack[queue_idx].count++;
|
||||
SignalSema(g_nPriQueueSema);
|
||||
} else {
|
||||
msg->status = EIsoStatus::FAILED_TO_QUEUE_4;
|
||||
SignalSema(g_nPriQueueSema);
|
||||
ReturnMessage(msg);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
int UnqueueMessage(ISO_Hdr* msg) {
|
||||
WaitSema(g_nPriQueueSema);
|
||||
int iVar5 = 0;
|
||||
PriStackEntry* stack = gPriStack;
|
||||
do {
|
||||
int iVar4 = 0;
|
||||
ISO_Hdr** cmd = stack->cmds;
|
||||
if (0 < stack->count) {
|
||||
do {
|
||||
if (*cmd == msg)
|
||||
break;
|
||||
iVar4 = iVar4 + 1;
|
||||
cmd++;
|
||||
} while (iVar4 < stack->count);
|
||||
}
|
||||
iVar5 = iVar5 + 1;
|
||||
if (iVar4 < stack->count) {
|
||||
stack->count = stack->count + -1;
|
||||
if (iVar4 < stack->count) {
|
||||
ISO_Hdr** ppIVar3 = stack->cmds + iVar4;
|
||||
do {
|
||||
iVar4 = iVar4 + 1;
|
||||
*ppIVar3 = ppIVar3[1];
|
||||
ppIVar3 = ppIVar3 + 1;
|
||||
} while (iVar4 < stack->count);
|
||||
}
|
||||
return SignalSema(g_nPriQueueSema);
|
||||
}
|
||||
stack = stack + 1;
|
||||
if (1 < iVar5) {
|
||||
return SignalSema(g_nPriQueueSema);
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Select which command to read for next
|
||||
* This function considers things like seeking time, reading rates of streamed files,
|
||||
* and buffer sizing. To be entirely honest, I don't understand it almost at all, and it's not
|
||||
* clear that it works as expected. It seems to work good enough, and no commands get entirely
|
||||
* starved of data while there are multiple streams.
|
||||
*/
|
||||
ISO_Hdr* GetMessage() {
|
||||
// bool been_a_while;
|
||||
// bool bVar2;
|
||||
// int now;
|
||||
// int iVar3;
|
||||
// int iVar4;
|
||||
// CISOCDFile *file;
|
||||
// CISOCDFile *pCVar5;
|
||||
// int iVar6;
|
||||
// CPageList *plist;
|
||||
// uint uVar7;
|
||||
// int iVar8;
|
||||
// int iVar9;
|
||||
// PriStack *local_t2_216;
|
||||
// PriStack *pri_level;
|
||||
// CISOCDFile *tfile4;
|
||||
// code *pcVar10;
|
||||
// CISOCDFile *tfile2;
|
||||
// CISOCDFile *tfile3;
|
||||
// uint uVar11;
|
||||
// ISO_VAGCommand *cmd;
|
||||
// int idx_on_level;
|
||||
// ISO_VAGCommand **ppIVar12;
|
||||
// int iVar13;
|
||||
// CBaseFile *tfile;
|
||||
// int cmds_total;
|
||||
// int iVar14;
|
||||
// uint uVar15;
|
||||
ISO_Hdr* cmds_array[16];
|
||||
u32 read_rates_array[16];
|
||||
int num_pages_array[16];
|
||||
int unstepped_pages_array[16];
|
||||
int remaining_pages_array[16];
|
||||
// uint its_been_a_while;
|
||||
// int pages_total;
|
||||
// int read_rate_total;
|
||||
// int min_nospeed_pages_total;
|
||||
// int max_pages_total;
|
||||
// int min_speed_pages_total;
|
||||
// ISO_VAGCommand *selected_cmd;
|
||||
// int cmds_with_speed_total;
|
||||
// uint cmd2_read_rate;
|
||||
// int selected_cmd_rem_sectors;
|
||||
// int pri_level_idx;
|
||||
|
||||
// simple logic to select which command to use next.
|
||||
|
||||
u32 now = GetSystemTimeLow();
|
||||
|
||||
bool been_a_while = false;
|
||||
if (unk_time_mode_flag == 0) {
|
||||
been_a_while = 0x384000 < (now - time_of_last_unknown_rate_drive_op);
|
||||
} else {
|
||||
unk_time_mode_flag = 0;
|
||||
time_of_last_unknown_rate_drive_op = now;
|
||||
}
|
||||
|
||||
s32 cmds_total = 0;
|
||||
get_page_manager()->GarbageCollect();
|
||||
s32 pages_total = 0;
|
||||
s32 read_rate_total = 0;
|
||||
s32 min_nospeed_pages_total = 0;
|
||||
s32 max_pages_total = 0;
|
||||
s32 min_speed_pages_total = 0;
|
||||
LAB_000080e4:
|
||||
s32 iVar9 = g_cmds_with_speed_total * 400 + 0x2ee;
|
||||
s32 iVar13 = 0x7fffffff;
|
||||
ISO_Hdr* selected_cmd = nullptr;
|
||||
s32 cmds_with_speed_total = 0;
|
||||
s32 cmd2_read_rate = 0;
|
||||
s32 selected_cmd_rem_sectors = -1;
|
||||
s32 pri_level_idx = 1;
|
||||
PriStackEntry* pri_level = gPriStack + 1;
|
||||
s32 iVar8 = iVar13;
|
||||
|
||||
// loop over priority levels
|
||||
do {
|
||||
s32 idx_on_level = pri_level->count + -1;
|
||||
|
||||
// if any exist on this level
|
||||
if (-1 < idx_on_level) {
|
||||
ISO_Hdr** ppIVar12 = pri_level->cmds + idx_on_level;
|
||||
// iVar14 = cmds_total << 2;
|
||||
// loop over commands on this level
|
||||
do {
|
||||
ISO_Hdr* cmd = *ppIVar12;
|
||||
CBaseFile* file = nullptr;
|
||||
// iVar4 = iVar14;
|
||||
|
||||
// basic check if this command is even valid:
|
||||
if (cmd && (file = cmd->m_pBaseFile, file) && cmd->status == EIsoStatus::OK_2 &&
|
||||
cmd->active_a != 0) {
|
||||
u32 read_rate = file->m_ReadRate;
|
||||
read_rate_total = read_rate_total + read_rate; // maybe this is an inverse rate...
|
||||
|
||||
// build up arrays of info for each command
|
||||
read_rates_array[cmds_total] = read_rate;
|
||||
cmds_array[cmds_total] = cmd;
|
||||
|
||||
if ((int)read_rate < 1) {
|
||||
min_nospeed_pages_total = min_nospeed_pages_total + file->m_Buffer.m_nMinNumPages;
|
||||
max_pages_total = max_pages_total + file->m_Buffer.m_nMaxNumPages;
|
||||
} else {
|
||||
min_speed_pages_total = min_speed_pages_total + file->m_Buffer.m_nMinNumPages;
|
||||
cmds_with_speed_total = cmds_with_speed_total + 1;
|
||||
}
|
||||
|
||||
CPageList* plist = file->m_Buffer.m_pPageList;
|
||||
|
||||
s32 npages = 0;
|
||||
if (plist != (CPageList*)0x0) {
|
||||
npages = plist->m_nNumPages;
|
||||
}
|
||||
pages_total = pages_total + npages;
|
||||
num_pages_array[cmds_total] = npages;
|
||||
|
||||
s32 n_untepped_pages = 0;
|
||||
if (plist != (CPageList*)0x0) {
|
||||
n_untepped_pages = plist->m_nNumUnsteppedPages;
|
||||
}
|
||||
unstepped_pages_array[cmds_total] = n_untepped_pages;
|
||||
|
||||
s32 n_remaining_pages = 4;
|
||||
if (cmd->callback != RunDGOStateMachine) {
|
||||
n_remaining_pages = n_untepped_pages + file->m_LengthPages - file->m_PageOffset;
|
||||
// lg::warn("remaining pages is {} = {} + {} - {}", n_remaining_pages, n_untepped_pages,
|
||||
// file->m_LengthPages, file->m_PageOffset);
|
||||
}
|
||||
remaining_pages_array[cmds_total] = n_remaining_pages;
|
||||
|
||||
if (remaining_pages_array[cmds_total] < 1) {
|
||||
remaining_pages_array[cmds_total] = 1;
|
||||
}
|
||||
|
||||
// careful, this increments in a weird spot.
|
||||
// I use cmds_total - 1 below...
|
||||
int old_cmds_total = cmds_total;
|
||||
cmds_total = cmds_total + 1;
|
||||
|
||||
// iVar4 = iVar14 + 4;
|
||||
|
||||
// next, we'll determine a desired page cutoff and discard commands where
|
||||
// we have enough pages.
|
||||
if (read_rate && plist) {
|
||||
// 3/4 * mNumPages, this is if our allocated buffer is 75% full.
|
||||
s32 desired_pages = (int)(file->m_nNumPages * 0x30) >> 6;
|
||||
|
||||
// but, we want at least min pages
|
||||
if (desired_pages < file->m_Buffer.m_nMinNumPages) {
|
||||
desired_pages = file->m_Buffer.m_nMinNumPages;
|
||||
}
|
||||
|
||||
// and we want at least 2
|
||||
if (desired_pages < 2) {
|
||||
desired_pages = 2;
|
||||
}
|
||||
|
||||
// but, we never want more pages than we plan to eventually read.
|
||||
if (remaining_pages_array[old_cmds_total] < desired_pages) {
|
||||
desired_pages = remaining_pages_array[old_cmds_total];
|
||||
}
|
||||
|
||||
// if we have that many, we can just forget the command - no point in filling it now.
|
||||
if (desired_pages <= unstepped_pages_array[old_cmds_total])
|
||||
goto LAB_00008420;
|
||||
}
|
||||
|
||||
s32 iVar14 = iVar9;
|
||||
if ((0 < (int)read_rate) &&
|
||||
(iVar14 = (int)(file->m_Buffer.m_nDataLength * 1000) / (int)read_rate,
|
||||
read_rate == 0)) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
s32 pri = cmd->priority;
|
||||
|
||||
// really not sure what this is...
|
||||
if (been_a_while) {
|
||||
if ((read_rate == 0) || (iVar14 < 0x2ee)) {
|
||||
been_a_while = false;
|
||||
goto LAB_000080e4;
|
||||
}
|
||||
|
||||
// if this isn't the command we said last time.
|
||||
if (g_selected_cmd != cmd) {
|
||||
s32 current_sector = file->GetSector();
|
||||
current_sector = current_sector - unk_sector;
|
||||
bool sector_ok = false;
|
||||
if (current_sector < 0) {
|
||||
current_sector = -current_sector;
|
||||
if (unk_time_mflag != 0) {
|
||||
LAB_000083ac:
|
||||
current_sector = current_sector + 10000000;
|
||||
}
|
||||
sector_ok = current_sector < iVar13;
|
||||
} else {
|
||||
sector_ok = current_sector < iVar13;
|
||||
if ((0 < current_sector) && (unk_time_mflag == 0))
|
||||
goto LAB_000083ac;
|
||||
}
|
||||
if (sector_ok) {
|
||||
iVar13 = current_sector;
|
||||
iVar8 = iVar14;
|
||||
selected_cmd = cmd;
|
||||
cmd2_read_rate = read_rate;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// normal selection logic???
|
||||
if ((((iVar14 == iVar8) && (selected_cmd_rem_sectors < pri)) || (iVar14 < iVar8)) &&
|
||||
(iVar14 <= iVar9)) {
|
||||
iVar8 = iVar14;
|
||||
selected_cmd = cmd;
|
||||
cmd2_read_rate = read_rate;
|
||||
selected_cmd_rem_sectors = pri;
|
||||
}
|
||||
}
|
||||
}
|
||||
LAB_00008420:
|
||||
idx_on_level = idx_on_level + -1;
|
||||
/* WARNING: ptrarith problems */
|
||||
ppIVar12 = ppIVar12 + -1;
|
||||
// iVar14 = iVar4;
|
||||
} while (-1 < idx_on_level);
|
||||
}
|
||||
pri_level--;
|
||||
pri_level_idx = pri_level_idx + -1;
|
||||
} while (-1 < pri_level_idx);
|
||||
|
||||
if (selected_cmd) {
|
||||
if (cmd2_read_rate == 0) {
|
||||
unk_time_mode_flag = 1;
|
||||
time_of_last_unknown_rate_drive_op = now;
|
||||
}
|
||||
iVar13 = unk_sector;
|
||||
if (selected_cmd->m_pBaseFile) {
|
||||
iVar13 = selected_cmd->m_pBaseFile->GetSector();
|
||||
}
|
||||
if (unk_sector < iVar13) {
|
||||
unk_time_mflag = 1;
|
||||
unk_sector = iVar13;
|
||||
} else {
|
||||
been_a_while = iVar13 != unk_sector;
|
||||
unk_sector = iVar13;
|
||||
if (been_a_while) {
|
||||
unk_time_mflag = 0;
|
||||
unk_sector = iVar13;
|
||||
}
|
||||
}
|
||||
}
|
||||
min_speed_pages_total = min_speed_pages_total + min_nospeed_pages_total;
|
||||
g_cmds_with_speed_total = cmds_with_speed_total;
|
||||
g_selected_cmd = selected_cmd;
|
||||
pages_total = get_page_manager()->m_CCache.m_nNumFreePages + pages_total;
|
||||
if ((0 < min_speed_pages_total) && (0 < pages_total)) {
|
||||
if (min_speed_pages_total == 0) {
|
||||
// trap(0x1c00);
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
min_speed_pages_total = (min_nospeed_pages_total * pages_total) / min_speed_pages_total;
|
||||
if (min_speed_pages_total < min_nospeed_pages_total) {
|
||||
min_speed_pages_total = min_nospeed_pages_total;
|
||||
}
|
||||
if (max_pages_total < min_speed_pages_total) {
|
||||
min_speed_pages_total = max_pages_total;
|
||||
}
|
||||
pages_total = pages_total - min_speed_pages_total;
|
||||
iVar9 = 0;
|
||||
iVar13 = min_speed_pages_total;
|
||||
iVar8 = pages_total;
|
||||
if (0 < cmds_total) {
|
||||
// iVar14 = 0;
|
||||
iVar13 = min_speed_pages_total;
|
||||
iVar8 = pages_total;
|
||||
do {
|
||||
CBaseFile* tfile = cmds_array[iVar9]->m_pBaseFile;
|
||||
if (read_rates_array[iVar9] < 1) {
|
||||
s32 uVar11 = (tfile->m_Buffer).m_nMaxNumPages;
|
||||
if (max_pages_total == 0) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
s32 uVar15 = (tfile->m_Buffer).m_nMinNumPages;
|
||||
s32 uVar7 = (int)(uVar11 * min_speed_pages_total) / max_pages_total;
|
||||
if ((int)uVar7 < (int)uVar15) {
|
||||
uVar7 = uVar15;
|
||||
}
|
||||
|
||||
tfile->m_nNumPages = uVar7;
|
||||
if ((int)uVar11 < (int)uVar7) {
|
||||
uVar7 = uVar11;
|
||||
}
|
||||
tfile->m_nNumPages = uVar7;
|
||||
if (remaining_pages_array[iVar9] < (int)uVar7) {
|
||||
uVar7 = remaining_pages_array[iVar9];
|
||||
}
|
||||
tfile->m_nNumPages = uVar7;
|
||||
// lg::warn("num pages mod {}", uVar7);
|
||||
iVar13 = iVar13 - uVar7;
|
||||
} else {
|
||||
s32 uVar11 = (tfile->m_Buffer).m_nMinNumPages;
|
||||
s32 uVar7 = (tfile->m_Buffer).m_nMaxNumPages;
|
||||
// lg::warn("taking else case: {} {} {}", uVar11, uVar7, tfile->m_nNumPages);
|
||||
|
||||
s32 uVar15 = -1;
|
||||
if (read_rate_total == 0) {
|
||||
LAB_000085e4:
|
||||
// lg::warn("going to min! (rrt is {})", read_rate_total);
|
||||
uVar15 = uVar11;
|
||||
} else {
|
||||
if (read_rate_total == 0) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
uVar15 = (read_rates_array[iVar9] * pages_total) / read_rate_total;
|
||||
// lg::warn("read rate math is {}", uVar15);
|
||||
if ((int)uVar15 < (int)uVar11)
|
||||
goto LAB_000085e4;
|
||||
}
|
||||
|
||||
// lg::warn("vals {} {}", uVar7, uVar15);
|
||||
if ((int)uVar7 < (int)uVar15) {
|
||||
uVar15 = uVar7;
|
||||
}
|
||||
// lg::warn("vals 2 {} {}", remaining_pages_array[iVar9], uVar15);
|
||||
if (remaining_pages_array[iVar9] < (int)uVar15) {
|
||||
uVar15 = remaining_pages_array[iVar9];
|
||||
}
|
||||
iVar8 = iVar8 - uVar15;
|
||||
tfile->m_nNumPages = uVar15;
|
||||
// lg::warn("num pages mod 2 {}", uVar15);
|
||||
}
|
||||
iVar9 = iVar9 + 1;
|
||||
// iVar14 = iVar9 * 4;
|
||||
} while (iVar9 < cmds_total);
|
||||
}
|
||||
while (0 < iVar13) {
|
||||
iVar9 = 0;
|
||||
s32 iVar14 = iVar13;
|
||||
if (0 < cmds_total) {
|
||||
s32 iVar4 = 0;
|
||||
iVar14 = iVar13;
|
||||
while (0 < iVar14) {
|
||||
CBaseFile* tfile2 = cmds_array[iVar4 / 4]->m_pBaseFile;
|
||||
iVar9 = iVar9 + 1;
|
||||
s32 uVar11;
|
||||
if (read_rates_array[iVar4 / 4] == 0 &&
|
||||
(uVar11 = tfile2->m_nNumPages, (int)uVar11 < remaining_pages_array[iVar4 / 4]) &&
|
||||
((int)uVar11 < tfile2->m_Buffer.m_nMaxNumPages)) {
|
||||
tfile2->m_nNumPages = uVar11 + 1;
|
||||
iVar14 = iVar14 + -1;
|
||||
}
|
||||
if (cmds_total <= iVar9)
|
||||
break;
|
||||
iVar4 = iVar9 * 4;
|
||||
}
|
||||
}
|
||||
been_a_while = iVar13 == iVar14;
|
||||
iVar13 = iVar14;
|
||||
if (been_a_while) {
|
||||
iVar8 = iVar8 + iVar14;
|
||||
iVar13 = 0;
|
||||
}
|
||||
}
|
||||
while (0 < iVar8) {
|
||||
iVar13 = 0;
|
||||
iVar9 = iVar8;
|
||||
if (0 < cmds_total) {
|
||||
s32 iVar14 = 0;
|
||||
iVar9 = iVar8;
|
||||
while (0 < iVar9) {
|
||||
CBaseFile* tfile4 = cmds_array[iVar14 / 4]->m_pBaseFile;
|
||||
iVar13 = iVar13 + 1;
|
||||
s32 uVar11;
|
||||
if (((0 < read_rates_array[iVar14 / 4]) &&
|
||||
(uVar11 = tfile4->m_nNumPages, (int)uVar11 < remaining_pages_array[iVar14 / 4])) &&
|
||||
((int)uVar11 < tfile4->m_Buffer.m_nMaxNumPages)) {
|
||||
tfile4->m_nNumPages = uVar11 + 1;
|
||||
iVar9 = iVar9 + -1;
|
||||
}
|
||||
if (cmds_total <= iVar13)
|
||||
break;
|
||||
iVar14 = iVar13 * 4;
|
||||
}
|
||||
}
|
||||
been_a_while = iVar8 == iVar9;
|
||||
iVar8 = iVar9;
|
||||
if (been_a_while) {
|
||||
iVar8 = 0;
|
||||
}
|
||||
}
|
||||
iVar13 = 0;
|
||||
if (0 < cmds_total) {
|
||||
iVar8 = 0;
|
||||
do {
|
||||
CBaseFile* tfile3 = cmds_array[iVar8 / 4]->m_pBaseFile;
|
||||
|
||||
iVar13 = iVar13 + 1;
|
||||
s32 uVar11 = tfile3->m_nNumPages;
|
||||
// lg::warn("mystery values: {} - {} = {} (from {})", num_pages_array[iVar8 / 4],
|
||||
// uVar11,
|
||||
// num_pages_array[iVar8 / 4] - uVar11,
|
||||
// cmds_array[iVar8 / 4]->m_pBaseFile->m_FileDef->name.data);
|
||||
if (((int)uVar11 < num_pages_array[iVar8 / 4]) &&
|
||||
(iVar8 = tfile3->RecoverPages(num_pages_array[iVar8 / 4] - uVar11), 0 < iVar8)) {
|
||||
get_page_manager()->GarbageCollectPageList(tfile3->m_Buffer.m_pPageList);
|
||||
}
|
||||
iVar8 = iVar13 * 4;
|
||||
} while (iVar13 < cmds_total);
|
||||
}
|
||||
}
|
||||
return selected_cmd;
|
||||
}
|
||||
|
||||
int ProcessMessageData(ISO_Hdr* tgt_msg) {
|
||||
EIsoStatus stat;
|
||||
s32 ret = 1;
|
||||
LAB_000088a4:
|
||||
s32 num_remaining = gPriStack[0].count + -1;
|
||||
if (num_remaining < 0) {
|
||||
return ret;
|
||||
}
|
||||
auto* cmd_array = gPriStack[0].cmds + num_remaining;
|
||||
ISO_Hdr* cmd = nullptr;
|
||||
do {
|
||||
EIsoStatus (*cb)(ISO_Hdr*) = nullptr;
|
||||
cmd = *cmd_array;
|
||||
if (cmd && cmd->active_a) {
|
||||
stat = cmd->status;
|
||||
if (stat == EIsoStatus::OK_2) {
|
||||
auto* file = cmd->m_pBaseFile;
|
||||
auto* buffer = &file->m_Buffer;
|
||||
if (!file) {
|
||||
buffer = nullptr;
|
||||
}
|
||||
if ((buffer && (buffer->m_eBufferType != CBuffer::BufferType::EBT_FREE)) &&
|
||||
(cb = cmd->callback, cb != ProcessVAGData)) {
|
||||
stat = (cb)(cmd);
|
||||
}
|
||||
}
|
||||
if (stat != EIsoStatus::OK_2)
|
||||
break;
|
||||
cmd->status = EIsoStatus::OK_2;
|
||||
}
|
||||
num_remaining = num_remaining + -1;
|
||||
cmd_array = cmd_array + -1;
|
||||
if (num_remaining < 0) {
|
||||
return ret;
|
||||
}
|
||||
} while (true);
|
||||
if (cmd == tgt_msg) {
|
||||
ret = 0;
|
||||
}
|
||||
ReleaseMessage(cmd);
|
||||
if (stat != EIsoStatus::IDLE_1) {
|
||||
cmd->status = stat;
|
||||
ReturnMessage(cmd);
|
||||
}
|
||||
goto LAB_000088a4;
|
||||
}
|
||||
|
||||
void ReturnMessage(ISO_Hdr* msg) {
|
||||
if (msg->mbox_reply == 0) {
|
||||
if (msg->thread_to_wake == 0) {
|
||||
FreeVAGCommand((ISO_VAGCommand*)msg);
|
||||
} else {
|
||||
WakeupThread(msg->thread_to_wake);
|
||||
}
|
||||
} else {
|
||||
SendMbx(msg->mbox_reply, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseMessage(ISO_Hdr* msg) {
|
||||
if (GetThreadId() == g_nISOThreadID) {
|
||||
auto* file = msg->m_pBaseFile;
|
||||
if (file && file->m_Status != EIsoStatus::NONE_0) {
|
||||
file->Close();
|
||||
}
|
||||
UnqueueMessage(msg);
|
||||
} else {
|
||||
if (msg->msg_type != ISO_Hdr::MsgType::ABADBABE) {
|
||||
set_active_a(msg, 0);
|
||||
set_active_c(msg, 0);
|
||||
msg->msg_type = ISO_Hdr::MsgType::ABADBABE;
|
||||
SendMbx(g_nISOMbx, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ISO_VAGCommand* GetVAGCommand() {
|
||||
int iVar1;
|
||||
u32 uVar2;
|
||||
u32 uVar3;
|
||||
|
||||
do {
|
||||
while (vag_cmd_cnt == 0x1f) {
|
||||
DelayThread(1000);
|
||||
}
|
||||
do {
|
||||
iVar1 = WaitSema(g_VagCmdSema);
|
||||
uVar2 = 0;
|
||||
} while (iVar1 != 0);
|
||||
do {
|
||||
uVar3 = uVar2 + 1;
|
||||
if (((vag_cmd_used >> (uVar2 & 0x1f) ^ 1U) & 1) != 0) {
|
||||
vag_cmd_cnt = vag_cmd_cnt + 1;
|
||||
vag_cmd_used = vag_cmd_used | 1 << (uVar2 & 0x1f);
|
||||
if (max_vag_cmd_cnt < vag_cmd_cnt) {
|
||||
max_vag_cmd_cnt = vag_cmd_cnt;
|
||||
}
|
||||
SignalSema(g_VagCmdSema);
|
||||
return vag_cmds + uVar2;
|
||||
}
|
||||
uVar2 = uVar3;
|
||||
} while ((int)uVar3 < 0x1f);
|
||||
SignalSema(g_VagCmdSema);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
void FreeVAGCommand(ISO_VAGCommand* param_1) {
|
||||
u32 uVar1;
|
||||
int iVar2;
|
||||
|
||||
uVar1 = param_1 - vag_cmds;
|
||||
ASSERT(uVar1 < 16);
|
||||
if ((uVar1 < 0x1f) && (((vag_cmd_used >> (uVar1 & 0x1f) ^ 1U) & 1) == 0)) {
|
||||
do {
|
||||
iVar2 = WaitSema(g_VagCmdSema);
|
||||
} while (iVar2 != 0);
|
||||
vag_cmd_cnt = vag_cmd_cnt - 1;
|
||||
vag_cmd_used = vag_cmd_used & ~(1 << (uVar1 & 0x1f));
|
||||
SignalSema(g_VagCmdSema);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace jak3
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace jak3 {
|
||||
void jak3_overlord_init_globals_iso_queue();
|
||||
struct ISO_Hdr;
|
||||
struct ISO_VAGCommand;
|
||||
void ReleaseMessage(ISO_Hdr* msg);
|
||||
void FreeVagCmd(ISO_VAGCommand* msg);
|
||||
int QueueMessage(ISO_Hdr* msg, int pri);
|
||||
int UnqueueMessage(ISO_Hdr* msg);
|
||||
void ReturnMessage(ISO_Hdr* msg);
|
||||
void InitBuffers();
|
||||
bool DgoCmdWaiting();
|
||||
ISO_Hdr* GetMessage();
|
||||
int ProcessMessageData(ISO_Hdr* msg);
|
||||
void FreeVAGCommand(ISO_VAGCommand* msg);
|
||||
ISO_VAGCommand* GetVAGCommand();
|
||||
|
||||
struct PriStackEntry {
|
||||
ISO_Hdr* cmds[8];
|
||||
int count = 0;
|
||||
};
|
||||
|
||||
extern u32 g_auTrapSRAM[6];
|
||||
extern u32 g_auStrmSRAM[6];
|
||||
extern s32 g_nPriQueueSema;
|
||||
extern PriStackEntry gPriStack[2];
|
||||
} // namespace jak3
|
||||
Loaded 100 of 606 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user