Compare commits

...
Author SHA1 Message Date
Tyler Wilding 1e307c8a9e i18n: add finnish to menus 2024-07-31 22:34:55 -04:00
Tyler Wilding 3a67f40098 i18n: remove meta line 2024-07-31 22:21:04 -04:00
Aloqas cbfa65c78a Update text-id-h.gc 2024-07-31 23:43:55 +03:00
Aloqas 681c419f17 Update subtitle_meta_fi-FI.json 2024-07-31 23:43:42 +03:00
Aloqas a4e108cca6 city-save-lurkers-intro 2024-07-31 23:41:08 +03:00
Aloqas f1ee25c640 Merge branch 'master' into test2 2024-07-31 18:55:20 +03:00
Tyler Wilding af6de539b5 jak1/jak2: Persist sound settings, play-hints, subtitles and vibration settings in pc-settings instead of the memory card file (#3612)
In the original game, they had no choice but to use the memory card file
as their method of persisting settings. We are not limited by such
things.

It's inconvenient to have to load your save-file when launching the game
to initialize these settings to your liking, it's also confusing
behaviour to even some players that have played the game heavily for
over a decade. We can do better by globally saving these settings to the
`pc-settings` file instead.

Originally I only migrated the volume settings, then i figured it would
be nice to also have play-hints and subtitles settings persisted. More
could debatably be moved (language is a big one...) but these were the
low hanging fruit.

I also reduced the default volumes as that is something else that has
come up a few times.
2024-07-31 00:01:18 -04:00
Tyler Wilding c72a086e49 jak2: support mirror mode (#3616)
Fixes #3210


![image](https://github.com/user-attachments/assets/86bb6a67-bc6a-4169-aa82-d6a46ecd43d7)

TIL that on the PS4/PS5, mirror mode breaks the upscaling
2024-07-30 23:30:53 -04:00
Hat Kid a66d832b2f jak3: add more prim buckets (#3618)
Used by `prebot`
2024-07-30 19:50:00 +02:00
Tyler Wilding d29ab77892 g/j1: fix menu labelling issue in jak1 (#3613)
Fixes #3393
2024-07-29 21:57:26 -04:00
Tyler Wilding e975eab15a decompiler: Apply docstring indentation fix to all game versions (#3614)
Previously was only applying to game versions above Jak 2, Fixes #3342
2024-07-29 21:57:07 -04:00
OpenGOAL BotandOpenGOALBot 441952186c CI: Periodic Controller Database Update (#3615)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-07-29 19:14:02 -04:00
Tyler Wilding d819d6da05 game: cleanup some display settings related code, forbid invalid game-size resolutions (#3601)
Fixes https://github.com/open-goal/jak-project/issues/3563

These users have the following spamming in logs:
> OpenGL error 0x502 S8246 T824C: GL_INVALID_OPERATION error generated.
Source and destination dimensions must be identical with the current
filtering modes.

And the solution is to correctly set their game-size. The way this
change accomplishes that is by confirming whether or not the set
`game-size` is a valid resolution informed by SDL, if not, it defaults
to the monitor's currently set display mode's resolution.

This also moves the selected display id, and the display mode into the
C++ settings -- closer to where it's actually managed and used. I'm
tempted to do this eventually for the resolutions as well but that stuff
is much more burdensome. This hopefully simplifies debugging, reduces
startup flickering, and removes back-and-forth complexity. Hopefully
this makes debugging display related problems easier. It also adds a
bunch more logging to the related code.
2024-07-27 22:29:14 -04:00
Hat Kid ce978638fe jak3: add darkjak highres texture anim (#3611)
Eyes don't work yet
2024-07-28 02:45:00 +02:00
water111 9d0009715e [jak3] Fix alpha for prims, entity-table (#3609)
Fix issue where light-trail is invisible and some actors not spawning
due to out of memory.
2024-07-27 12:46:33 -04:00
water111 3856ae505a [jak3] Some cleanup/fixes around curve and light-trail (#3608)
They still don't work yet, this is just naming/comments to help with
debug.

The vehicle tracks are now at least trying to draw, but like the others,
don't actually show up.
2024-07-27 11:17:39 -04:00
Tyler Wilding 92c4390f0a jak1: Adjust sprite positioning or hide them where appropriate when using non-standard aspect ratios (#3596)
This attempts to do a best-effort quick fix for the sprite alignment in
the menus and first person views on higher aspect ratios. This:
- Hides the binocular borders completely when using a non-standard ratio
![Screenshot 2024-07-20
021430](https://github.com/user-attachments/assets/c56d3a6c-13b0-43e1-b99b-83292993728c)
- Hides the borders in jak's first person view when using a non-standard
ratio
![Screenshot 2024-07-20
021310](https://github.com/user-attachments/assets/fefca993-960b-4741-87b7-6d7c17efe89d)
- Uses a combination of manual alignment and approximation to get the
pause menu closer.
![Screenshot 2024-07-20
151725](https://github.com/user-attachments/assets/2c8aa759-b33a-4fbe-abc6-b5861fc33208)
> 32:9 screenshot.

I accomplished the last one by manually aligning all of the core sprites
and text for the most popular aspect ratios. This means that from a
practical standpoint, things should align "perfectly". However, I then
used all of those values to derive a polynomial for each adjustment
based on the aspect ratio. This allows the game to do a half-decent
approximation/interpolation for every aspect ratio in-between the common
ones. It won't be perfect, but it will be better than this:

![image](https://github.com/user-attachments/assets/420b1e38-6f88-436a-8e8c-21df6b49428e)
2024-07-26 23:15:51 -04:00
zakfaulk a7c9151c6c Jak1: Add Autosplitting options for tasks completed in one level and turned in in another (#3595)
For the FJ Mirrors, Muse, Lightning Moles, and Gambler's race the tasks
are completed in one level, then turned in at the hub. This presents a
spot of confusion for new players with the autosplitter and requires
hacky workarounds for those who want to split on these conditions. This
pull request adds in the necessary code to the autosplit-h.gc and
autosplit.gc files so that the autosplitter can identify these events,
similar to the talk to fisherman and catch fish options in the current
autosplitter.
2024-07-26 23:12:30 -04:00
water111 82a23c747e [jak3] prim rendering for cloth (#3607) 2024-07-26 20:31:32 -04:00
water111 f0b46ff2e5 [jak3] A few bug fixes (#3606)
A few minor fixes:

- Fix crash in overlord3 during final boss
https://github.com/open-goal/jak-project/issues/3605
- Update goal_src for `scene-actor.gc`, which was not updated after a
bug fix for decompiling skelgroups, making some cutscene actors
invisible due to using the wrong joint for culling checks.
- Stop using `-1` as an invalid value for texture id's in Merc.cpp. This
could sometimes cause Merc2.cpp to accidentally skip updating the OpenGL
texture. This fixes the bug where skull gems sometimes didn't have the
animated textures.
2024-07-26 13:48:43 -04:00
water111 9d80ada016 [jak3] Fix eye slot assignment and textures (#3603)
I found two issues with Jak 3 eyes. The first was simple - we were
missing a `-pc` texture upload in `texture.gc` for `pris2` textures,
which has eye textures for a few characters, like torn or damas.

The second was a little more annoying. Unlike jak 2 and jak 1, jak 3 can
dynamically assign eye slots when merc models are loaded. This involves
modifying eye data to tell the eye renderer where to render, and
modifying the merc model's adgif shaders to point to the correct eye
texture. The modification to the merc adgif shader is problematic since
our PC port of merc assumes this slot is constant.

My solution here was to bypass this whole slot system entirely for jak
3. I modified the GOAL eye renderer to tell the c++ eye renderer the
name of the merc-ctrl containing the eye. Then, the PC C++ Merc renderer
can just look up the merc-ctrl by name. To make this fit nicely in the
existing memory layout, I used a 64-bit fnv hash of the name. (which
honestly is how we should have handled a lot of other texture/model
names stuff...)

Unrelated fix to Overlord2 so it handles the case where file size
changes after the game starts, I had this in jak2/jak1 and forgot it for
jak 3.
2024-07-26 11:42:52 -04:00
water111 e81431bd21 [wip] Jak 3 Overlord (#3567) 2024-07-26 09:42:28 -04:00
OpenGOAL BotandOpenGOALBot 57772c59a0 CI: Periodic Controller Database Update (#3600)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-07-23 20:36:54 -04:00
Hat Kid edae60d58d decompiler: support merc model replacements and adding custom actor models to vanilla fr3s (#3597)
This adds support for replacing existing merc models in FR3 files with
custom GLB model files. The replacements go in
`custom_assets/<GAME>/merc_replacements`, similar to texture
replacements. When a `.glb` file with a file name that matches any model
present in an FR3 is detected (e.g. `eichar-lod0` for Jak), all merc
model data is replaced with the given model.

Additionally, models for custom actors can now also be added to vanilla
FR3s. The models for this go in
`custom_assets/<GAME>/models/<LEVEL_NAME>` (e.g.
`custom_assets/jak1/models/jungleb/test-actor-lod0.glb`) and will be
added to the FR3 that has a matching name (exception: to add things to
the common level file, the folder should be named `common` instead of
`GAME`).
For custom levels, these now go in
`custom_assets/<GAME>/models/custom_levels` (previously
`custom_assets/<GAME>/models`).

Another small change: When level ripping is enabled, the resulting model
files will now be stored in game name subfolders inside of `glb_out`.
2024-07-21 01:51:31 +02:00
Hat Kid 365fae4913 jak3: fix bbush rings (#3593)
Fixes #3592
2024-07-17 21:49:07 +02:00
OpenGOAL BotandOpenGOALBot 3d04ac958c CI: Periodic Controller Database Update (#3585)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-07-16 19:45:50 -04:00
Tyler Wilding 849ba391d4 game: log more OpenGL info (#3588)
Logs the OpenGL vendor and renderer, in most cases this helps identify
what GPU the game is using, which is something that comes up from
time-to-time in support.


![image](https://github.com/user-attachments/assets/4d9ca6fa-f3ea-440e-bce2-7d22dab21ec6)
2024-07-16 19:40:50 -04:00
Hat Kid c8fbe26c7d jak3: fix texture anim alpha (#3587) 2024-07-15 21:39:44 +02:00
Hat Kid fbab87b0fe jak3: fix opengl error spam (#3586) 2024-07-15 20:21:52 +02:00
Hat Kid 1c170b741c jak3: fix robo-hover hand cannon nans (#3584)
Fixes #3583.

The callback function for the hand cannon joint mods was initialized
prior to calling `ja-post`, propagating NaNs.
2024-07-15 16:28:28 +02:00
Brent HickeyandHat Kid b8f1ee5289 [high fps] Increase input buffer for jak1 and jak3 (#3578)
Applying https://github.com/open-goal/jak-project/pull/3178 to jak1 and
jak3

This also fixes cloud speed in jak3

---------

Co-authored-by: Hat Kid <[email protected]>
2024-07-15 02:56:10 +02:00
Hat Kid bdded9ad8c jak3: add missing texture animations (#3577)
This refactors some of the texture animation code a bit to better
support multiple games and adds most of the missing texture animations
for Jak 3 with a couple of exceptions/bugs:

- `hanga-sprite`: Despite `move_to_pool` being set for this anim, it's
not showing up in-game, but it does display properly in the ImGUI debug
window.

![image](https://github.com/open-goal/jak-project/assets/6624576/29df8e17-8831-412b-b9b7-7704d6bd7813)
- `factoryc-alpha`: Some conveyors do not have the animation for some
reason.

![image](https://github.com/open-goal/jak-project/assets/6624576/209ef073-2a81-4e2c-b020-dc2ae0b01196)
- This spot in Spargus seems to use texture animations, but it looks
like it maps to the `fora-water-dest` texture/slot, which comes from
`foresta-water`. Because the texture is not initialized, the texture
shows up black on first load, but it does show up after loading
`foresta`.

![image](https://github.com/open-goal/jak-project/assets/6624576/1e54bab2-f97c-47d5-a92a-a98a52c30178)

![image](https://github.com/open-goal/jak-project/assets/6624576/240b0137-1e9e-4e65-8446-0f78df9802dd)
- `hfrag` texture anim is not handled yet. Probably needs some special
casing.
2024-07-15 02:25:18 +02:00
Hat Kid 08a23793c8 jak3: fix some nan bugs (#3581)
Fixes a couple of NaN bugs, making the Arena and Marauder Stronghold
missions, the leaper corralling mission and final boss playable:

- Fixes #3579:
- After catching a leaper, the `flut` that spawns would have a NaN
`world-sphere`
- Fixes #3580:
- `vf0` was being clobbered after a `suspend`, causing them to spawn at
the origin.
- The Terraformer's `world-sphere` would be NaN until an animation
started playing.
2024-07-15 01:54:52 +02:00
ZedB0T 291c89a851 Update volume in sound-group sog3 to sfx-volume (#3574)
Adds a way to override certain sounds that don't respect the settings
that they should...



https://github.com/open-goal/jak-project/assets/89345505/97d9518d-aafd-4227-b25f-82c5d32e811e
2024-07-09 01:24:03 +02:00
Tyler Wilding b4113dda67 decompiler: Cleanup duplication in extractor/decompiler and make it easier to enable streamed audio ripping from CLI (#3560)
This centralizes the code that both `extractor` and the decompiler
executes. In the past this code was partially-duplicated, meaning that
the `extractor` could only do _some_ operations and not others (ie.
could not extract the audio files).

I also simplified the process to enable audio streaming in the
configuration. This is to support a new feature in the launcher that
allows you to enable these options for the decompiler:


![image](https://github.com/open-goal/jak-project/assets/13153231/8e6c20a1-8b5b-46f0-bceb-7644f713989f)
2024-06-29 01:18:39 -04:00
OpenGOAL BotandOpenGOALBot a485c236d6 CI: Periodic Controller Database Update (#3564)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-06-24 14:44:01 -04:00
Tyler Wilding 73ff53f01d debugging: Improve event profiler utility (#3561)
- Can make the event buffer larger or smaller
- UI shows the current event index / size, so you know how fast it's
filling up
- Can save compressed, 10x reduction in filesize and Windows 11 explorer
actually supports ZSTD natively now so this isn't inconvenient at all

![Screenshot 2024-06-22
000343](https://github.com/open-goal/jak-project/assets/13153231/2f7dfa41-d931-4170-a848-840cbed9be9f)
> An example of almost 1 million events.  Results in a 4mb file.
2024-06-22 22:01:33 -04:00
Aloqas 495a8bc26f rewording stuff 2024-06-20 18:26:15 +03:00
OpenGOAL BotandOpenGOALBot 90c11bde8f CI: Periodic Controller Database Update (#3557)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-06-19 19:24:47 -04:00
Aloqas c2cccc48cd another change 2024-05-24 15:35:17 +03:00
Aloqas c5effb2395 small change 2024-05-24 12:14:29 +03:00
Aloqas 5f3671b8a3 small fixes 2024-05-24 11:02:02 +03:00
Aloqas 26bfac8555 Jak 2: Finnish subtitles and game text 2024-05-23 22:54:42 +03:00
621 changed files with 69056 additions and 10076 deletions

No files matched your search

+5
View File
@@ -58,6 +58,11 @@ custom_assets/jak1/texture_replacements/*
custom_assets/jak2/texture_replacements/*
custom_assets/jak3/texture_replacements/*
# merc replacements
custom_assets/jak1/merc_replacements/*
custom_assets/jak2/merc_replacements/*
custom_assets/jak3/merc_replacements/*
# generated cmake files
svnrev.h
common/versions/revision.h
-1
View File
@@ -145,7 +145,6 @@
"name": "Game - Jak 1 - Runtime (boot)",
"args": [
"-v",
"--portable",
"--game",
"jak1",
"--",
+2 -2
View File
@@ -4,7 +4,7 @@
#include "fmt/core.h"
std::string DmaTag::print() {
std::string DmaTag::print() const {
std::string result;
const char* mode_names[8] = {"refe", "cnt", "next", "ref", "refs", "call", "ret", "end"};
result += fmt::format("TAG: 0x{:08x} {:4s} qwc 0x{:04x}", addr, mode_names[(int)kind], qwc);
@@ -15,7 +15,7 @@ std::string DmaTag::print() {
return result;
}
std::string VifCode::print() {
std::string VifCode::print() const {
std::string result;
switch (kind) {
+2 -2
View File
@@ -52,7 +52,7 @@ struct DmaTag {
bool operator!=(const DmaTag& other) const { return !((*this) == other); }
std::string print();
std::string print() const;
};
inline void emulate_dma(const void* source_base, void* dest_base, u32 tadr, u32 dadr) {
@@ -148,7 +148,7 @@ struct VifCode {
u16 num;
u16 immediate;
std::string print();
std::string print() const;
};
struct VifCodeStcycl {
+1
View File
@@ -240,6 +240,7 @@ static FormFormattingConfig new_top_level_inline_form(bool elide_new_line) {
const std::unordered_map<std::string, FormFormattingConfig> opengoal_form_config = {
{"case", new_pair_rule(true)},
{"case-str", new_pair_rule(true)},
{"cond", new_pair_rule(false)},
{"#cond", new_pair_rule(false)},
{"in-package", new_top_level_inline_form(true)},
+28 -7
View File
@@ -26,6 +26,8 @@ u64 get_current_tid() {
}
#endif
#include "common/log/log.h"
#include "common/util/compress.h"
#include "common/util/string_util.h"
// clang-format on
u64 get_current_ts() {
@@ -34,12 +36,12 @@ u64 get_current_ts() {
GlobalProfiler::GlobalProfiler() {
m_t0 = get_current_ts();
set_max_events(65536);
m_nodes.resize(m_max_events);
}
void GlobalProfiler::set_max_events(size_t event_count) {
ASSERT(!m_enabled);
m_nodes.resize(event_count);
void GlobalProfiler::update_event_buffer_size(size_t new_size) {
m_max_events = new_size;
m_nodes.resize(m_max_events);
}
void GlobalProfiler::set_waiting_for_event(const std::string& event_name) {
@@ -72,6 +74,10 @@ void GlobalProfiler::root_event() {
instant_event("ROOT");
}
size_t GlobalProfiler::get_next_idx() {
return (m_next_idx % m_nodes.size());
}
void GlobalProfiler::begin_event(const char* name) {
event(name, ProfNode::BEGIN);
}
@@ -96,8 +102,10 @@ void GlobalProfiler::set_enable(bool en) {
m_enabled = en;
}
void GlobalProfiler::dump_to_json(const std::string& path) {
ASSERT(!m_enabled);
void GlobalProfiler::dump_to_json() {
if (m_enabled) {
set_enable(false);
}
nlohmann::json json;
auto& trace_events = json["traceEvents"];
@@ -185,7 +193,20 @@ void GlobalProfiler::dump_to_json(const std::string& path) {
t.second.highest_at_target);
}
file_util::write_text_file(path, json.dump());
if (m_enable_compression) {
const auto json_str = json.dump();
const auto compressed_data =
compression::compress_zstd_no_header(json_str.data(), json_str.size());
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
fmt::format("prof-{}.json.zst", str_util::current_local_timestamp_no_colons());
file_util::create_dir_if_needed_for_file(file_path);
file_util::write_binary_file(file_path, compressed_data.data(), compressed_data.size());
} else {
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
fmt::format("prof-{}.json", str_util::current_local_timestamp_no_colons());
file_util::create_dir_if_needed_for_file(file_path);
file_util::write_text_file(file_path, json.dump());
}
}
GlobalProfiler gprof;
+8 -2
View File
@@ -17,7 +17,8 @@ struct ProfNode {
class GlobalProfiler {
public:
GlobalProfiler();
void set_max_events(size_t event_count);
size_t get_max_events() { return m_max_events; }
void update_event_buffer_size(size_t new_size);
void set_waiting_for_event(const std::string& event_name);
void instant_event(const char* name);
void begin_event(const char* name);
@@ -25,11 +26,16 @@ class GlobalProfiler {
void end_event();
void clear();
void set_enable(bool en);
void dump_to_json(const std::string& path);
void dump_to_json();
void root_event();
bool is_enabled() { return m_enabled; }
size_t get_next_idx();
bool m_enable_compression = false;
private:
std::atomic_bool m_enabled = false;
size_t m_max_events = 65536;
u64 m_t0 = 0;
std::atomic_size_t m_next_idx = 0;
std::vector<ProfNode> m_nodes;
+1 -1
View File
@@ -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,
+5 -2
View File
@@ -29,8 +29,11 @@ class Wrapper {
Wrapper(const std::string& _username,
const Config& config,
const StartupFile& startup,
bool nrepl_alive)
: username(_username), repl_config(config), startup_file(startup), nrepl_alive(nrepl_alive) {}
bool _nrepl_alive)
: username(_username),
repl_config(config),
startup_file(startup),
nrepl_alive(_nrepl_alive) {}
replxx::Replxx& get_repl() { return repl; }
void init_settings();
void reload_startup_file();
+145 -1
View File
@@ -43,7 +43,151 @@ std::vector<std::string> jak2_slots = {
};
std::vector<std::string> jak3_slots = {
"skull-gem-dest", "jakc-arm", "jakc-eyebrow", "jakc-face", "jakc-finger", "jakc-hair",
"skull-gem-dest",
"jakc-arm",
"jakc-eyebrow",
"jakc-face",
"jakc-finger",
"jakc-hair",
"jakchires-arm",
"jakchires-eye",
"jakchires-eyebrow",
"jakchires-eyelid",
"jakchires-facelft",
"jakchires-facert",
"jakchires-hair",
// default-water
"bomb-gradient",
"blue-beam-dest",
"lightjak-wings",
"mushroom-dest",
// default-warp
"shield-env-rim-dest",
// templea-water
"templea-waterfall-dest",
// templea-warp
"holograph-env-rim-dest",
// hanga-sprite
"glider-ring-dest2",
"glider-ring-dest",
// foresta-water
"fora-water-dest",
"fora-waterfall-01-dest",
"fora-water-wave-01-dest",
// forestb-water
"forb-water-dest",
"forb-waterfall-01-dest",
"forb-water-wave-01-dest",
// lforplnt-pris
"mh-gem-dest",
// lmhcitya-tfrag
"mhcitya-base-goo-01-dest",
// lmhcityb-tfrag
"mhcityb-base-goo-01-dest",
// mhcitya-pris
// "mhcity-de-door-skin-01-dest",
// templec-water
"tplc-water-dest",
// sewc-water
"sewer-water-01-c-dest",
"sewer-waterfall-01-c-dest",
"sewer-waterfall-02-c-dest",
"sewer-water-wave-01-c-dest",
"sewer-water-highlight-01-c-dest",
// sewd-water
"sewer-water-01-d-dest",
"sewer-waterfall-02-d-dest",
"sewer-water-highlight-01-d-dest",
"sewer-water-wave-01-d-dest",
"sewer-water-wave-02-d-dest",
"sewer-water-still-01-d-dest",
// sewe-water
"sewer-water-01-e-dest",
"sewer-waterfall-01-e-dest",
"sewer-waterfall-02-e-dest",
"sewer-water-highlight-01-e-dest",
// sewg-water
"sewer-water-01-g-dest",
"sewer-waterfall-02-g-dest",
"sewer-water-wave-01-g-dest",
// sewh-water
"sewer-water-01-h-dest",
"sewer-waterfall-02-h-dest",
"sewer-water-wave-02-h-dest",
"sewer-watefall-froth-01-h-dest",
// sewi-water
"sewer-water-still-01-i-dest",
"sewer-waterfall-02-i-dest",
"sewer-water-wave-01-i-dest",
// sewj-water
"sewer-waterfall-02-j-dest",
"sewer-watefall-froth-01-j-dest",
// sewl-water
"sewer-waterfall-02-l-dest",
"sewer-watefall-froth-01-l-dest",
// sewm-water
"sewer-water-01-m-dest",
"sewer-waterfall-01-m-dest",
"sewer-waterfall-02-m-dest",
"sewer-water-highlight-01-m-dest",
"sewer-water-wave-01-m-dest",
"sewer-water-still-01-m-dest",
"sewer-watefall-froth-01-m-dest",
// sewn-water
"sewer-waterfall-01-n-dest",
"sewer-waterfall-02-n-dest",
// "sewer-water-highlight-01-n-dest",
"sewer-water-wave-01-n-dest",
"sewer-water-still-01-n-dest",
// hanga-water
// "des-thermal-01-dest",
// desresc-warp
"sat-shield-dest",
// security
"security-env-dest",
"security-dot-dest",
// lgunnorm-water
"kg-target-c-forcefield-01-dest",
// templex-water
"temple-waterfall-dest",
// desertd-water
"des-waterfall-dest",
// towerb-water
"tow-energy-bridge-dest",
// factoryb-water
"hemi-gradient-dest",
"hemi-gradient-flames-dest",
// factoryc-alpha
"facc-convey-dest",
"facc-convey-02-dest",
// waspal-water
"waspala-water-dest",
"waspala-waterfall-dest",
// rubblea-water
"rub-water-dest",
// rubblea2-water
"rub-water-desta2",
// rubbleb-water
"rub-water-destb",
// rubblec-water
"rub-water-destc",
// nstb-quicksand
"nstb-quicksand-dest",
// ctyslumb-water
"ctyslumb-water-dest",
"ctyslumb-fountain-fall-dest",
// ctyslumc-water
"ctyslumc-water-dest",
"ctyslumc-fountain-fall-dest",
// mined-tfrag
"mined-pillar-side-dest",
"mined-pillar-top2side-dest",
"mined-pillar-top-dest",
// volcanoa-alpha
"vola-lava-01-dest",
"vola-lava-fall-dest",
// wasstada-alpha
"wstd-lava-base-dest",
};
} // namespace
+13
View File
@@ -46,4 +46,17 @@ std::vector<u8> decompress_zstd(const void* data, size_t size) {
ASSERT(decomp_size == decompressed_size);
return result;
}
std::vector<u8> compress_zstd_no_header(const void* data, size_t size) {
size_t max_compressed = ZSTD_compressBound(size);
std::vector<u8> result(max_compressed);
size_t compressed_size = ZSTD_compress(result.data(), max_compressed, data, size, 1);
if (ZSTD_isError(compressed_size)) {
ASSERT_MSG(false, fmt::format("ZSTD error: {}", ZSTD_getErrorName(compressed_size)));
}
result.resize(compressed_size);
return result;
}
} // namespace compression
+2 -1
View File
@@ -8,4 +8,5 @@ namespace compression {
// compress and decompress data with zstd
std::vector<u8> compress_zstd(const void* data, size_t size);
std::vector<u8> decompress_zstd(const void* data, size_t size);
} // namespace compression
std::vector<u8> compress_zstd_no_header(const void* data, size_t size);
} // namespace compression
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include "common/common_types.h"
inline u64 fnv64(const void* data, u64 len) {
u64 ret = 0xcbf29ce484222325;
const auto* ptr = (const u8*)data;
for (u64 i = 0; i < len; i++) {
ret = 1099511628211 * (((u64)*ptr) ^ ret);
ptr++;
}
return ret;
}
inline u64 fnv64(const std::string& str) {
return fnv64(str.data(), str.length());
}
+3 -3
View File
@@ -27,11 +27,11 @@ Range<int> parse_json_optional_integer_range(const nlohmann::json& json);
}
template <typename T>
void json_get_optional(const nlohmann::json& json,
void json_get_optional(const nlohmann::json& j,
const std::string& key,
std::optional<T>& optionalValue) {
if (json.contains(key) && !json[key].is_null()) {
optionalValue = json[key].get<T>();
if (j.contains(key) && !j[key].is_null()) {
optionalValue = j[key].get<T>();
}
}
+17 -8
View File
@@ -3,20 +3,29 @@
#include "common/common_types.h"
#include "common/log/log.h"
#ifdef __linux__
#ifdef _WIN32
// clang-format off
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <psapi.h>
// clang-format on
size_t get_peak_rss() {
HANDLE hProcess = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
return pmc.PeakWorkingSetSize;
} else {
return 0;
}
}
#else
#include <sys/resource.h>
size_t get_peak_rss() {
rusage x;
getrusage(RUSAGE_SELF, &x);
return x.ru_maxrss * 1024;
}
#else
size_t get_peak_rss() {
return 0;
}
#endif
#ifdef _WIN32
-1
View File
@@ -3,7 +3,6 @@
#include <cstddef>
#include <string>
// Note: these are not implemented on windows and will return zero.
size_t get_peak_rss();
void setup_cpu_info();
@@ -62,7 +62,7 @@
// Note: You will still have to add them to your level's .gd file.
// "art_groups": ["plat-ag"],
// If you have any custom models in the "custom_assets/jak1/models" folder that you want to use in your level, add them to this list.
// If you have any custom models in the "custom_assets/jak1/models/custom_levels" folder that you want to use in your level, add them to this list.
// Note: Like with art groups, these should also be added to your level's .gd file.
"custom_models": ["test-actor"],
+3 -1
View File
@@ -68,6 +68,7 @@ add_library(
level_extractor/fr3_to_gltf.cpp
level_extractor/MercData.cpp
level_extractor/tfrag_tie_fixup.cpp
level_extractor/merc_replacement.cpp
ObjectFile/LinkedObjectFile.cpp
ObjectFile/LinkedObjectFileCreation.cpp
@@ -89,7 +90,8 @@ add_library(
VuDisasm/VuDisassembler.cpp
VuDisasm/VuInstruction.cpp
config.cpp)
config.cpp
decompilation_process.cpp)
target_link_libraries(decomp
lzokay
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -5,13 +5,13 @@
#include "ObjectFileDB.h"
#include "common/formatter/formatter.h"
#include "common/goos/PrettyPrinter.h"
#include "common/link_types.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/Timer.h"
#include "common/util/string_util.h"
#include <common/formatter/formatter.h>
#include "decompiler/IR2/Form.h"
#include "decompiler/analysis/analyze_inspect_method.h"
+2 -6
View File
@@ -54,12 +54,8 @@ void append_body_to_function_definition(goos::Object* top_form,
body_elements.insert(body_elements.end(), inline_body.begin(), inline_body.end());
// If the first element in the body is a docstring, add it first
if (body_elements.size() > 0 && body_elements.at(0).is_string()) {
if (version > GameVersion::Jak2) {
initial_top_level_forms.push_back(
goos::StringObject::make_new(fix_docstring_indent(inline_body.at(0).as_string()->data)));
} else {
initial_top_level_forms.push_back(inline_body.at(0));
}
initial_top_level_forms.push_back(
goos::StringObject::make_new(fix_docstring_indent(inline_body.at(0).as_string()->data)));
body_elements.erase(body_elements.begin());
}
+3 -1
View File
@@ -64,7 +64,6 @@ Config make_config_via_json(nlohmann::json& json) {
inputs_json.at("str_art_file_names").get<std::vector<std::string>>();
}
config.audio_dir_file_name = inputs_json.at("audio_dir_file_name").get<std::string>();
config.streamed_audio_file_names =
inputs_json.at("streamed_audio_file_names").get<std::vector<std::string>>();
@@ -321,6 +320,9 @@ Config make_config_via_json(nlohmann::json& json) {
if (json.contains("save_texture_pngs")) {
config.save_texture_pngs = json.at("save_texture_pngs").get<bool>();
}
if (json.contains("rip_streamed_audio")) {
config.rip_streamed_audio = json.at("rip_streamed_audio").get<bool>();
}
if (inputs_json.contains("animated_textures")) {
config.animated_textures =
+1 -2
View File
@@ -102,8 +102,6 @@ struct Config {
std::vector<std::string> str_file_names;
std::vector<std::string> str_texture_file_names;
std::vector<std::string> str_art_file_names;
std::string audio_dir_file_name;
std::vector<std::string> streamed_audio_file_names;
std::string obj_file_name_map_file;
@@ -175,6 +173,7 @@ struct Config {
std::vector<std::string> levels_to_extract;
bool levels_extract;
bool save_texture_pngs = false;
bool rip_streamed_audio = false;
DecompileHacks hacks;
+1 -1
View File
@@ -21102,7 +21102,7 @@
:size-assert #x94
:flag-assert #xf00300094
(:methods
(dumb-15 (_type_) none))
(spawn-particles! (_type_) none))
(:states
hud-normal
hud-coming-in
+3
View File
@@ -122,6 +122,9 @@
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
"rip_streamed_audio": false,
////////////////////////////
// PATCHING OPTIONS
////////////////////////////
@@ -258,10 +258,6 @@
"TEXT/6COMMON.TXT"
],
// uncomment the next line to extract audio to wave files.
//"audio_dir_file_name": "jak1/VAG",
"audio_dir_file_name": "",
"streamed_audio_file_names": [
"VAGWAD.ENG",
"VAGWAD.FRE",
@@ -228,9 +228,5 @@
"TEXT/6COMMON.TXT"
],
// uncomment the next line to extract audio to wave files.
//"audio_dir_file_name": "jak1/VAG",
"audio_dir_file_name": "",
"streamed_audio_file_names": ["VAGWAD.ENG", "VAGWAD.JAP"]
}
+14
View File
@@ -2515,6 +2515,7 @@
(iop-mem 48)
(cancel-dgo 49)
(set-stereo-mode 50) ;; sound-rpc-set-stereo-mode
(set-mirror 201)
)
(defenum sound-group
@@ -2829,6 +2830,17 @@
:flag-assert #x900000004
)
; added
(defenum sound-mirror-mode
:type uint8
(normal)
(mirrored)
)
; added for mirror mode
(deftype sound-rpc-set-mirror-mode (sound-rpc-cmd)
((mirror sound-mirror-mode)))
(deftype sound-rpc-union (structure)
((data uint32 20 :offset-assert 0)
(load-bank sound-rpc-load-bank :offset 0)
@@ -2852,6 +2864,7 @@
(shutdown sound-rpc-shutdown :offset 0)
(list-sounds sound-rpc-list-sounds :offset 0)
(unload-music sound-rpc-unload-music :offset 0)
(mirror-mode sound-rpc-set-mirror-mode :overlay-at (-> data 0))
)
:method-count-assert 9
:size-assert #x50
@@ -8774,6 +8787,7 @@ Unlike [[engine]], users can use [[engine-pers]] as a parent class."
(progress-graphics-ps2-lod-dist #x1337)
(progress-graphics-msaa-off #x1338)
(progress-graphics-display #x1339)
(language-name-finnish #x133a)
)
;; ---text-id-h:text-id
+3
View File
@@ -127,6 +127,9 @@
"rip_collision": false,
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
"rip_streamed_audio": false,
////////////////////////////
// PATCHING OPTIONS
@@ -441,10 +441,6 @@
"TEXT/7COMMON.TXT"
],
// uncomment the next line to extract audio to wave files.
// "audio_dir_file_name": "jak2/VAG",
"audio_dir_file_name": "",
"streamed_audio_file_names": [
"VAGWAD.ENG",
"VAGWAD.FRE",
+177 -108
View File
@@ -15147,8 +15147,8 @@
:size-assert #x4
:flag-assert #xb00000004
(:methods
(init! (_type_) int) ;; 9
(cloth-base-method-10 (_type_ cloth-params handle) int) ;; 10
(update! (_type_) int) ;; 9
(setup-from-params! (_type_ cloth-params handle) int) ;; 10
)
)
@@ -25908,8 +25908,33 @@
:flag-assert #xe00000010
)
;; doesn't exist, but referenced by type ref in the entity table.
(deftype sail-boat-a (process-drawable-reserved)
()
)
(deftype cty-window-a (process-drawable-reserved)
()
)
(deftype city-window-a (process-drawable-reserved)
()
)
(deftype cty-guard-turret (process-drawable-reserved)
()
)
(deftype cty-fruit-stand (process-drawable-reserved)
()
)
(deftype torn (process-drawable-reserved)
()
)
(deftype entity-info (basic)
((ptype type :offset-assert 4) ;; guessed by decompiler
((ptype object :offset-assert 4) ;; guessed by decompiler
(pool symbol :offset-assert 8) ;; guessed by decompiler
(heap-size int32 :offset-assert 12)
)
@@ -33950,7 +33975,7 @@
)
(deftype particle-array (inline-array-class)
((data verlet-particle :dynamic :inline :offset-assert 16)
((data verlet-particle :dynamic :inline :offset-assert 16 :score 1)
)
:method-count-assert 14
:size-assert #x10
@@ -34017,12 +34042,12 @@
:size-assert #x40
:flag-assert #x1000000040
(:methods
(calculate-wind!
(accumulate-external-forces!
"If this cloth system has the wind flag, calculate the wind force."
(_type_) none) ;; 11
(verlet-particle-system-method-12 (_type_ float) none) ;; 12
(verlet-particle-system-method-13 (_type_) none) ;; 13
(verlet-particle-system-method-14 (_type_) none) ;; 14
(compute-verlet-step (_type_ float) none) ;; 12
(run-one-iteration "Run one iteration of the system." (_type_) none) ;; 13
(reset! "Reset to stationary/default state." (_type_) none) ;; 14
(debug-draw (_type_) none) ;; 15
)
)
@@ -34082,9 +34107,9 @@
"Set up this cloth system with the given [[cloth-params]]."
(_type_ cloth-params) none) ;; 16
(debug-draw-spheres (_type_) none) ;; 17
(cloth-system-method-18 (_type_) int) ;; 18
(cloth-system-method-19 (_type_) none) ;; 19
(cloth-system-method-20 (_type_) none) ;; 20
(post-physics-update (_type_) int) ;; 18
(enforce-constraints-1 (_type_) none) ;; 19
(enforce-constraints-2 (_type_) none) ;; 20
(cloth-system-method-21 (_type_) none) ;; 21
(cloth-system-method-22 (_type_) none) ;; 22
(cloth-system-method-23 (_type_) none) ;; 23
@@ -34098,9 +34123,9 @@
(cloth-system-method-31 (_type_ current-position-info) none) ;; 31
(cloth-system-method-32 (_type_ vector int int current-position-info) none) ;; 32
(cloth-system-method-33 (_type_ vu-lights) none) ;; 33
(cloth-system-method-34 (_type_) none) ;; 34
(cloth-system-method-35 (_type_) none) ;; 35
(cloth-system-method-36 (_type_) none) ;; 36
(hide! (_type_) none) ;; 34
(reset-locations (_type_) none) ;; 35
(pre-physics-update "Callback to update prior to running verlet integration. Can handle movement of the entire system in the world, for example" (_type_) none) ;; 36
(cloth-system-cmd-handler (_type_ pair) none) ;; 37
)
)
@@ -34122,8 +34147,8 @@
;; cloth ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-extern get-neighboring-faces (function vector int int int int int))
(define-extern *normal-array* (pointer vector))
(define-extern get-neighboring-faces (function vector4w int int int int int))
(define-extern *normal-array* (inline-array vector))
(define-extern light-vertex (function current-position-info vector rgba))
(define-extern *once* symbol)
(define-extern *cloth-fade-alpha* gs-alpha)
@@ -34196,7 +34221,17 @@
;; curves ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defenum loop-behavior
:type uint64
:bitfield #f
(wrap)
(clamp)
(b2)
(use-default)
)
(deftype float-pair (structure)
"Two floats. Specifies one point on a piecewise linear curve."
((first float :offset-assert 0)
(second float :offset-assert 4)
(x float :offset 0)
@@ -34208,6 +34243,7 @@
)
(deftype float-pair-array (inline-array-class)
"Array of points used to make a piecewise linear curve."
((data float-pair :dynamic :inline :offset-assert 16)
)
:method-count-assert 14
@@ -34216,39 +34252,50 @@
)
(deftype curve2d (basic)
"Interface for evaluating a 2d curve.
The input is a float (x-position) and the output is a float (y-position).
The curve is over (0, 1). Values outside of the range are either clamped
or wrapped depending on the loop-behavior flag."
()
:method-count-assert 10
:size-assert #x4
:flag-assert #xa00000004
(:methods
(curve2d-method-9 (_type_ float int) float) ;; 9
(evaluate "Compute value of curve at the given position." (_type_ float loop-behavior) float) ;; 9
)
)
(deftype curve-color (basic)
"Interface for evaluating a color curve. The input is a float, representing
progress through the curve, and the result is a floating point rgba color."
()
:method-count-assert 10
:size-assert #x4
:flag-assert #xa00000004
(:methods
(curve-color-method-9 (_type_ float rgbaf int) rgbaf) ;; 9
(evaluate "Compute value of curve at the given position." (_type_ float rgbaf loop-behavior) rgbaf) ;; 9
)
)
(deftype curve2d-piecewise (curve2d)
"Implementation of 2d-curve for a piecewise linear curve.
Not particularly efficient - each evaluation needs to check each point."
((pts float-pair-array :offset-assert 4)
(default-loop-behavior uint64 :offset-assert 8)
(default-loop-behavior loop-behavior :offset-assert 8)
)
:method-count-assert 12
:size-assert #x10
:flag-assert #xc00000010
(:methods
(curve2d-piecewise-method-10 (_type_ int symbol int) none) ;; 10
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
(curve2d-piecewise-method-11 (_type_) none) ;; 11
)
)
(deftype curve2d-fast (curve2d)
"Implementation of 2d piecewise linear curve which tries to be faster.
While it is faster, it places the huge restriction that you can only have 4 points.
Note that the xs should be negative here."
((xs vector :inline :offset-assert 16)
(ys vector :inline :offset-assert 32)
(one-over-x-deltas vector :inline :offset-assert 48)
@@ -34259,6 +34306,9 @@
)
(deftype curve-color-fast (curve-color)
"Implementation of color curve which tries to be faster.
While it is faster, it again has the restriction that you only
get 4 piecewise sections."
((xs vector :inline :offset-assert 16)
(ys vector 4 :inline :offset-assert 32)
(one-over-x-deltas vector :inline :offset-assert 96)
@@ -34269,6 +34319,8 @@
)
(deftype color-pair (structure)
"Single section of a piecewise linear color curve.
Unlike the fast version, this stores x values exactly like you'd expect."
((first float :offset-assert 0)
(second rgbaf :inline :offset-assert 16)
(x float :offset 0)
@@ -34280,6 +34332,7 @@
)
(deftype color-pair-array (inline-array-class)
"Array of points for piecewise linear color curve."
((data color-pair :dynamic :inline :offset-assert 16)
)
:method-count-assert 14
@@ -34288,21 +34341,22 @@
)
(deftype curve-color-piecewise (curve-color)
"Implementation of curve-color."
((pts color-pair-array :offset-assert 4)
(default-loop-behavior uint64 :offset-assert 8)
(default-loop-behavior loop-behavior :offset-assert 8)
)
:method-count-assert 11
:size-assert #x10
:flag-assert #xb00000010
(:methods
(curve-color-piecewise-method-10 (_type_ int symbol uint) none) ;; 10
(allocate! "Allocate memory for points." (_type_ int symbol symbol) none) ;; 10
)
)
(define-extern rgbaf-lerp! (function rgbaf rgbaf rgbaf float rgbaf))
(define-extern evaluate-curve-fast (function curve2d-fast rgbaf rgbaf float))
(define-extern evaluate-color-curve-fast (function curve-color-fast rgbaf rgbaf rgbaf))
(define-extern rgba<-rgbaf (function rgba rgbaf int))
(define-extern rgbaf-lerp! "Lerp all four components of rgba." (function rgbaf rgbaf rgbaf float rgbaf))
(define-extern evaluate-curve-fast "Evaluate a curve2d-fast at the given value." (function curve2d-fast float float))
(define-extern evaluate-color-curve-fast "Evaluate a color-curve-fast at the given value." (function curve-color-fast float rgbaf rgbaf))
(define-extern rgba<-rgbaf "Convert rgbaf to rgba. Seems like the input rgba's value is not used in any way." (function rgba rgbaf rgba))
(define-extern *curve-unity* curve2d-fast)
(define-extern *curve-linear-up* curve2d-fast)
(define-extern *curve-linear-down* curve2d-fast)
@@ -34679,6 +34733,14 @@
:flag-assert #xe00000010
)
(defenum lie-mode
:type uint64
(appearance0)
(appearance1)
(appearance2)
(use-two-strips 3)
)
(deftype light-trail-composition (structure)
((color-mode uint64 :offset-assert 0)
(color-curve curve-color-piecewise :offset-assert 8)
@@ -34696,8 +34758,8 @@
(uv-mode uint64 :offset-assert 72)
(uv-repeat-dist float :offset-assert 80)
(max-age time-frame :offset-assert 88)
(tex-id uint32 :offset-assert 96)
(lie-mode uint64 :offset-assert 104)
(tex-id texture-id :offset-assert 96)
(lie-mode lie-mode :offset-assert 104)
(lie-vector vector :inline :offset-assert 112)
(zbuffer? symbol :offset-assert 128)
(use-tape-mode? symbol :offset-assert 132)
@@ -34711,7 +34773,7 @@
(deftype light-trail-breadcrumb (structure)
((pos vector :inline :offset-assert 0)
(birth-time uint32 :offset 12 :decomp-as time-frame)
(birth-time uint32 :offset 12 :decomp-as time-frame :score 1)
)
:method-count-assert 9
:size-assert #x10
@@ -34726,15 +34788,22 @@
:flag-assert #xe00000010
)
(defenum light-trail-decision
:type uint64
(added 0)
(not-added 1)
(reset 2)
)
(deftype light-trail (basic)
((crumb-array (array light-trail-breadcrumb) :offset-assert 4)
((crumb-array (array uint8) :offset-assert 4)
(crumb-size uint8 :offset-assert 8)
(crumb-count int16 :offset-assert 10)
(max-crumb-count int16 :offset-assert 12)
(appearance light-trail-composition :offset-assert 16)
(start-marker uint64 :offset-assert 24)
(end-marker uint64 :offset-assert 32)
(decision uint64 :offset-assert 40)
(decision light-trail-decision :offset-assert 40)
(total-distance-traveled float :offset-assert 48)
(strip prim-strip :offset-assert 52)
(strip2 prim-strip :offset-assert 56)
@@ -34744,19 +34813,19 @@
:size-assert #x80
:flag-assert #x1600000080
(:methods
(light-trail-method-9 (_type_ light-trail-composition int) none) ;; 9
(light-trail-method-10 (_type_) none) ;; 10
(light-trail-method-11 (_type_ vector time-frame) int) ;; 11
(light-trail-method-12 (_type_) none) ;; 12
(light-trail-method-13 (_type_) int) ;; 13
(light-trail-method-14 (_type_) none) ;; 14
(setup! "Initialize, including allocation of crumbs and strips on the process heap." (_type_ light-trail-composition int) none) ;; 9
(reset! "Clear all tracked crumbs." (_type_) none) ;; 10
(add-crumb! "Try adding a crumb, kicking out the oldest if there's not enough room. This may reject if it's too close to the previous." (_type_ vector time-frame) int) ;; 11
(build-prim-strip! "Build the mesh for this light trail." (_type_) none) ;; 12
(common-trans! "Call this on each frame to handle max-age." (_type_) int) ;; 13
(expire-old-points! "Internal function to kill off points that are too old." (_type_) none) ;; 14
(light-trail-method-15 (_type_) none) ;; 15
(add-vert! (_type_ prim-strip vector float float float) none) ;; 16
(light-trail-method-17 (_type_ vector float float vector float) symbol) ;; 17
(light-trail-method-18 (_type_ light-trail-breadcrumb int vector vector) none) ;; 18
(light-trail-method-19 (_type_ float int) none) ;; 19
(add-vert-to-prim-strip! "Add a single vertex to the prim." (_type_ prim-strip vector rgba float float) none) ;; 16
(add-tri-pair-to-prim! "Add two vertices to the prim strip to add two triangles" (_type_ vector rgba float vector float) symbol) ;; 17
(calc-vertex-pos! (_type_ light-trail-breadcrumb int vector vector) none) ;; 18
(crumb-age-out-callback "To be implemented by the user to smoothly interpolate out non-default entries in their crumb type." (_type_ float int) none) ;; 19
(reset-crumbs! (_type_) none) ;; 20
(light-trail-method-21 (_type_ vector) none) ;; 21
(replace-last-crumb! "Similar to add-crumb, but will modify the last crumb instead of advancing." (_type_ vector) none) ;; 21
)
)
@@ -34774,7 +34843,7 @@
:size-assert #x80
:flag-assert #x1800000080
(:methods
(weapon-trail-method-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
(add-crumb-with-offset "Given two points, add the first and offset to a crumb." (_type_ vector vector) light-trail-breadcrumb) ;; 22
(weapon-trail-method-23 (_type_ vector vector) none) ;; 23
)
)
@@ -34793,8 +34862,8 @@
:size-assert #x80
:flag-assert #x1800000080
(:methods
(tread-trail-method-22 (_type_ vector vector) light-trail-breadcrumb) ;; 22
(tread-trail-method-23 (_type_ vector vector) light-trail-breadcrumb) ;; 23
(add-crumb-with-offset (_type_ vector vector) none) ;; 22
(tread-trail-method-23 (_type_ vector vector) none) ;; 23
)
)
@@ -34834,11 +34903,11 @@
die ;; 15
)
(:methods
(light-trail-tracker-method-16 (_type_ process-focusable vector) vector) ;; 16
(light-trail-tracker-method-17 (_type_ process-focusable) symbol) ;; 17
(light-trail-tracker-method-18 (_type_ process-focusable) symbol) ;; 18
(light-trail-tracker-method-19 (_type_) symbol) ;; 19
(light-trail-tracker-method-20 (_type_ vector) none) ;; 20
(get-tracked-object-pos (_type_ process-focusable vector) vector) ;; 16
(should-track? (_type_ process-focusable) symbol) ;; 17
(should-end? (_type_ process-focusable) symbol) ;; 18
(should-draw? (_type_) symbol) ;; 19
(add-crumb! (_type_ vector) none) ;; 20
)
)
@@ -42779,7 +42848,7 @@
:size-assert #xfc
:flag-assert #x22008000fc
(:methods
(task-manager-desert-bbush-ring-method-32 (_type_) none) ;; 32
(get-mgr-name (_type_) string) ;; 32
(task-manager-desert-bbush-ring-method-33 (_type_) none) ;; 33
)
)
@@ -44496,12 +44565,12 @@
;; templea-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *templea-water-texture-anim-array* texture-anim-array)
;; (define-extern *templea-warp-texture-anim-array* texture-anim-array)
;; (define-extern templea-warp-texture-anim-func function)
;; (define-extern *templeb-warp-texture-anim-array* texture-anim-array)
;; (define-extern templeb-warp-texture-anim-func function)
;; (define-extern *templec-water-texture-anim-array* texture-anim-array)
(define-extern *templea-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *templea-warp-texture-anim-array* (texture-anim-array texture-anim))
(define-extern templea-warp-texture-anim-func (function none))
(define-extern *templeb-warp-texture-anim-array* (texture-anim-array texture-anim))
(define-extern templeb-warp-texture-anim-func (function none))
(define-extern *templec-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; hover-training ;;
@@ -46284,16 +46353,16 @@
;; sewer-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *sewc-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewd-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewe-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewg-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewh-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewi-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewj-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewl-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewm-water-texture-anim-array* texture-anim-array)
;; (define-extern *sewn-water-texture-anim-array* texture-anim-array)
(define-extern *sewc-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewd-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewe-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewg-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewh-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewi-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewj-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewl-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewm-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *sewn-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; kg-hopper ;;
@@ -50287,7 +50356,7 @@
;; desresc-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *desresc-warp-texture-anim-array* texture-anim-array)
(define-extern *desresc-warp-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; desert-rescue ;;
@@ -50984,7 +51053,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-extern check-drop-level-ctyslumb-drop-userdata (function sparticle-system sparticle-cpuinfo vector none))
(define-extern *ctyslumb-water-texture-anim-array* texture-anim-array)
(define-extern *ctyslumb-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; mech-part ;;
@@ -51090,7 +51159,7 @@
;; nstb-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *nstb-quicksand-anim-array* texture-anim-array)
(define-extern *nstb-quicksand-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; nst-mood ;;
@@ -51733,7 +51802,7 @@
)
)
(define-extern *ctyslumc-water-texture-anim-array* texture-anim-array)
(define-extern *ctyslumc-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern ctyslumc-flag-init-by-other (function vector entity-actor object :behavior ctyslumc-flag))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -51908,8 +51977,8 @@
;; factoryc-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *factoryc-alpha-texture-anim-array* texture-anim-array)
;; (define-extern set-facc-conveyor-speed! function)
(define-extern *factoryc-alpha-texture-anim-array* (texture-anim-array texture-anim))
(define-extern set-facc-conveyor-speed! (function float float))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; conveyor ;;
@@ -52558,7 +52627,7 @@
(define-extern wang-texture-anim-init (function texture-anim none))
(define-extern real-wang-texture-anim-func (function texture-anim texture-anim none))
(define-extern wang-texture-anim-func (function none))
(define-extern wang-texture-anim-func (function texture-anim texture-anim none))
(define-extern *hfrag-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -54182,7 +54251,7 @@
;; glider-ring-part ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-extern *hanga-sprite-texture-anim-array* texture-anim-array)
(define-extern *hanga-sprite-texture-anim-array* (texture-anim-array texture-anim))
(define-extern cloud-shadow-find-ground (function vector matrix vector vector float))
(define-extern birth-func-fader (function sparticle-system sparticle-cpuinfo sparticle-launchinfo none))
(define-extern sparticle-fader (function sparticle-system sparticle-cpuinfo sparticle-launchinfo none))
@@ -54385,7 +54454,7 @@
(define-extern hanga-login (function level none))
(define-extern hanga-activate (function level none))
(define-extern hanga-deactivate (function level none))
(define-extern *hanga-water-texture-anim-array* texture-anim-array)
(define-extern *hanga-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; elec-gate ;;
@@ -57037,7 +57106,7 @@
;; desertd-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *desertd-water-texture-anim-array* texture-anim-array)
(define-extern *desertd-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ctyfarm-obs ;;
@@ -57861,7 +57930,7 @@
(deftype tire-trail-crumb (light-trail-breadcrumb)
((offset vector :inline :offset-assert 16)
(uu float :offset 28)
(uu float :offset 28 :score 1)
)
:method-count-assert 9
:size-assert #x20
@@ -57874,13 +57943,13 @@
:size-assert #x80
:flag-assert #x1800000080
(:methods
(tire-trail-method-22 (_type_) none) ;; 22
(tire-trail-method-23 (_type_) none) ;; 23
(add-crumb-with-offset-and-uu (_type_ vector vector float) none) ;; 22
(tire-trail-method-23 (_type_ vector vector float) none) ;; 23
)
)
(deftype tire-trail-tracker (light-trail-tracker)
()
((trail tire-trail :override))
:method-count-assert 21
:size-assert #xac
:flag-assert #x15003000ac
@@ -60281,7 +60350,7 @@
;; mhcityb-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *lmhcityb-tfrag-texture-anim-array* texture-anim-array)
(define-extern *lmhcityb-tfrag-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; rublcst-scenes ;;
@@ -61291,7 +61360,7 @@
(define-extern init-mood-tower (function mood-context float))
(define-extern update-tower-lights (function mood-context none))
(define-extern update-mood-tower (function mood-context float int none :behavior time-of-day-proc))
(define-extern *towerb-water-texture-anim-array* texture-anim-array)
(define-extern *towerb-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; tower-scenes ;;
@@ -63331,7 +63400,7 @@
;; wasstada-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *wasstada-alpha-texture-anim-array* texture-anim-array)
(define-extern *wasstada-alpha-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; wasstada-mood ;;
@@ -63355,7 +63424,7 @@
;; factorya-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *factoryb-water-texture-anim-array* texture-anim-array)
(define-extern *factoryb-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; factoryb-init ;;
@@ -63367,9 +63436,9 @@
;; mhcitya-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *lmhcitya-tfrag-texture-anim-array* texture-anim-array)
;; (define-extern *mhcitya-pris-texture-anim-array* texture-anim-array)
;; (define-extern set-mhcity-de-door-skin! function)
(define-extern *lmhcitya-tfrag-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *mhcitya-pris-texture-anim-array* (texture-anim-array texture-anim))
(define-extern set-mhcity-de-door-skin! (function float float))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ctyinda-part ;;
@@ -63677,10 +63746,10 @@
;; rubble-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *rubblea-water-texture-anim-array* texture-anim-array)
;; (define-extern *rubblea2-water-texture-anim-array* texture-anim-array)
;; (define-extern *rubbleb-water-texture-anim-array* texture-anim-array)
;; (define-extern *rubblec-water-texture-anim-array* texture-anim-array)
(define-extern *rubblea-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *rubblea2-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *rubbleb-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *rubblec-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; stadiuma-part ;;
@@ -65151,9 +65220,9 @@
;; forest-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *foresta-water-texture-anim-array* texture-anim-array)
;; (define-extern *forestb-water-texture-anim-array* texture-anim-array)
;; (define-extern *lforplnt-pris-texture-anim-array* texture-anim-array)
(define-extern *foresta-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *forestb-water-texture-anim-array* (texture-anim-array texture-anim))
(define-extern *lforplnt-pris-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; forest-ring-chase ;;
@@ -65410,8 +65479,8 @@
;; ltnfxhip-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *ltnfxhip-texture-anim-array* texture-anim-array)
;; (define-extern ltnfxhip-texture-anim-func function)
(define-extern *ltnfxhip-texture-anim-array* (texture-anim-array texture-anim))
(define-extern ltnfxhip-texture-anim-func (function none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ctygenb-part ;;
@@ -67812,7 +67881,7 @@
;; gungame-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *lgunnorm-water-texture-anim-array* texture-anim-array)
(define-extern *lgunnorm-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; gungame-obs ;;
@@ -68092,8 +68161,8 @@
;; ljkdxvin-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *ljkdxvin-texture-anim-array* texture-anim-array)
;; (define-extern ljkdxvin-texture-anim-func function)
(define-extern *ljkdxvin-texture-anim-array* (texture-anim-array texture-anim))
(define-extern ljkdxvin-texture-anim-func (function none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; target-tube ;;
@@ -71489,7 +71558,7 @@
;; waspal-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *waspal-water-texture-anim-array* texture-anim-array)
(define-extern *waspal-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; throne-scenes ;;
@@ -72665,7 +72734,7 @@
;; mined-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-extern *mined-tfrag-texture-anim-array* texture-anim-array)
(define-extern *mined-tfrag-texture-anim-array* (texture-anim-array texture-anim))
(define-extern set-mined-pillar-texture! (function float none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -73051,8 +73120,8 @@
;; volcanox-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *volcanox-warp-texture-anim-array* texture-anim-array)
;; (define-extern volcanox-warp-texture-anim-func function)
(define-extern *volcanox-warp-texture-anim-array* (texture-anim-array texture-anim))
(define-extern volcanox-warp-texture-anim-func (function none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; volcanox-mood ;;
@@ -73252,7 +73321,7 @@
;; templex-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *templex-water-texture-anim-array* texture-anim-array)
(define-extern *templex-water-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; templex-scenes ;;
@@ -73635,7 +73704,7 @@
;; volcano-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *volcanoa-alpha-texture-anim-array* texture-anim-array)
(define-extern *volcanoa-alpha-texture-anim-array* (texture-anim-array texture-anim))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; spiky-frog ;;
@@ -74348,8 +74417,8 @@
;; deshover-texture ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define-extern *deshover-texture-anim-array* texture-anim-array)
;; (define-extern deshover-texture-anim-func function)
(define-extern *deshover-texture-anim-array* (texture-anim-array texture-anim))
(define-extern deshover-texture-anim-func (function none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; terraformer-head ;;
+3
View File
@@ -127,6 +127,9 @@
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
"rip_streamed_audio": false,
////////////////////////////
// PATCHING OPTIONS
////////////////////////////
@@ -138,7 +138,7 @@
[7, "(function none)"],
[3, "(function symbol :behavior process)"]
],
"scene": [[4, "(function none :behavior scene-player)"]],
"scene": [[4, "(function symbol :behavior scene-player)"]],
"pov-camera": [
[
7,
+305 -5
View File
@@ -333,10 +333,6 @@
"TEXT/11COMMON.TXT"
],
// uncomment the next line to extract audio to wave files.
// "audio_dir_file_name": "jak3/VAG",
"audio_dir_file_name": "",
"streamed_audio_file_names": [
"VAGWAD.ENG",
"VAGWAD.FRE",
@@ -365,11 +361,315 @@
"jakc-finger-dark",
"jakc-hair-dark",
// darkjak-highres
"jakchires-arm",
"jakchires-arm-norm",
"jakchires-arm-dark",
"jakchires-eye",
"jakchires-eye-norm",
"jakchires-eye-dark",
"jakchires-eyebrow",
"jakchires-eyebrow-norm",
"jakchires-eyebrow-dark",
"jakchires-eyelid",
"jakchires-eyelid-norm",
"jakchires-eyelid-dark",
"jakchires-facelft",
"jakchires-facelft-norm",
"jakchires-facelft-dark",
"jakchires-facert",
"jakchires-facert-norm",
"jakchires-facert-dark",
"jakchires-hair",
"jakchires-hair-norm",
"jakchires-hair-dark",
// Skull Gem
"skull-gem-dest",
"skull-gem-alpha-00",
"skull-gem-alpha-01",
"skull-gem-alpha-02"
"skull-gem-alpha-02",
// default-water
"bomb-gradient",
"bomb-gradient-rim",
"bomb-gradient-flames",
"lightjak-wings",
"lighjak-wings-u-src",
"lightjak-wings-v-src",
"mushroom-dest",
"mushroom-src",
// default-warp
"shield-env-rim-dest",
"common-white",
"shield-env-uscroll",
"shield-env-rim-src",
// hanga-sprite
"glider-ring-dest2",
"glider-ring-dest",
"splash-foam",
"racegate",
// templea-water
"templea-waterfall-dest",
"templea-waterfall",
// templea-warp
"holograph-env-rim-dest",
"holograph-env-noise",
"holograph-env-scan",
"holograph-env-rim",
"environment-phong-rim",
// foresta-water
"fora-water-dest",
"fora-water",
"fora-waterfall-01-dest",
"fora-waterfall-01",
"fora-water-wave-01-dest",
"fora-water-wave-01",
// forestb-water
"forb-water-dest",
"forb-water",
"forb-waterfall-01-dest",
"forb-waterfall-01",
"forb-water-wave-01-dest",
"forb-water-wave-01",
// lforplnt-pris
"mh-gem-dest",
"mh-gem",
"mh-gem-alpha-01",
"mh-gem-alpha-02",
// lmhcitya-tfrag
"mhcitya-base-goo-01-dest",
"mhcitya-base-goo-01",
// lmhcityb-tfrag
"mhcityb-base-goo-01-dest",
"mhcityb-base-goo-01",
// mhcitya-pris
// "mhcity-de-door-skin-01-dest",
// "mhcity-de-door-skin-01",
// "mhcity-de-door-skin-02"
// templec-water
"tplc-water-dest",
"tplc-water",
// sewc-water
"sewer-water-01-c-dest",
"sewer-water-01-c",
"sewer-waterfall-01-c-dest",
"sewer-waterfall-01-c",
"sewer-waterfall-02-c-dest",
"sewer-waterfall-02-c",
"sewer-water-wave-01-c-dest",
"sewer-water-wave-01-c",
"sewer-water-highlight-01-c-dest",
"sewer-water-highlight-01-c",
// sewd-water
"sewer-water-01-d-dest",
"sewer-water-01-d",
"sewer-waterfall-02-d-dest",
"sewer-waterfall-02-d",
"sewer-water-highlight-01-d-dest",
"sewer-water-highlight-01-d",
"sewer-water-wave-01-d-dest",
"sewer-water-wave-01-d",
"sewer-water-wave-02-d-dest",
"sewer-water-wave-02-d",
"sewer-water-still-01-d-dest",
"sewer-water-still-01-d",
// sewe-water
"sewer-water-01-e-dest",
"sewer-water-01-e",
"sewer-waterfall-01-e-dest",
"sewer-waterfall-01-e",
"sewer-waterfall-02-e-dest",
"sewer-waterfall-02-e",
"sewer-water-highlight-01-e-dest",
"sewer-water-highlight-01-e",
// sewg-water
"sewer-water-01-g-dest",
"sewer-water-01-g",
"sewer-waterfall-02-g-dest",
"sewer-waterfall-02-g",
"sewer-water-wave-01-g-dest",
"sewer-water-wave-01-g",
// sewh-water
"sewer-water-01-h-dest",
"sewer-water-01-h",
"sewer-waterfall-02-h-dest",
"sewer-waterfall-02-h",
"sewer-water-wave-02-h-dest",
"sewer-water-wave-02-h",
"sewer-watefall-froth-01-h-dest",
"sewer-watefall-froth-01-h",
// sewi-water
"sewer-water-still-01-i-dest",
"sewer-water-still-01-i",
"sewer-waterfall-02-i-dest",
"sewer-waterfall-02-i",
"sewer-water-wave-01-i-dest",
"sewer-water-wave-01-i",
// sewj-water
"sewer-waterfall-02-j-dest",
"sewer-waterfall-02-j",
"sewer-watefall-froth-01-j-dest",
"sewer-watefall-froth-01-j",
// sewl-water
"sewer-waterfall-02-l-dest",
"sewer-waterfall-02-l",
"sewer-watefall-froth-01-l-dest",
"sewer-watefall-froth-01-l",
// sewm-water
"sewer-water-01-m-dest",
"sewer-water-01-m",
"sewer-waterfall-01-m-dest",
"sewer-waterfall-01-m",
"sewer-waterfall-02-m-dest",
"sewer-waterfall-02-m",
"sewer-water-highlight-01-m-dest",
"sewer-water-highlight-01-m",
"sewer-water-wave-01-m-dest",
"sewer-water-wave-01-m",
"sewer-water-still-01-m-dest",
"sewer-water-still-01-m",
"sewer-watefall-froth-01-m-dest",
"sewer-watefall-froth-01-m",
// sewn-water
"sewer-waterfall-01-n-dest",
"sewer-waterfall-01-n",
"sewer-waterfall-02-n-dest",
"sewer-waterfall-02-n",
// "sewer-water-highlight-01-n-dest",
// "sewer-water-highlight-01-n",
"sewer-water-wave-01-n-dest",
"sewer-water-wave-01-n",
"sewer-water-still-01-n-dest",
"sewer-water-still-01-n",
// hanga-water
// "des-thermal-01-dest",
// "des-thermal-01"
// desresc-warp
"sat-shield-dest",
"sat-shield-env-uvscroll",
"sat-shield",
// security
"security-env-dest",
"security-env-uscroll",
"security-dot-dest",
"security-dot-src",
// lgunnorm-water
"kg-target-c-forcefield-01-dest",
"kg-target-c-forcefield-01",
// templex-water
"temple-waterfall-dest",
"temple-waterfall",
// desertd-water
"des-waterfall-dest",
"des-waterfall",
// towerb-water
"tow-energy-bridge-dest",
"tow-energy-bridge",
// factoryb-water
"hemi-gradient-dest",
"hemi-gradient-rim",
"hemi-gradient-flames-dest",
"hemi-gradient-flames",
// factoryc-alpha
"facc-convey-dest",
"facc-convey",
"facc-convey-02-dest",
"facc-convey-02",
// waspal-water
"waspala-water-dest",
"waspala-water",
"waspala-waterfall-dest",
"waspala-waterfall",
// rubblea-water
"rub-water-dest",
"rub-water",
// rubblea2-water
"rub-water-desta2",
"rub-watera2",
// rubbleb-water
"rub-water-destb",
"rub-waterb",
// rubblec-water
"rub-water-destc",
"rub-waterc",
// nstb-quicksand
"nstb-quicksand-dest",
"nstb-quicksand-scroll",
// ctyslumb-water
"ctyslumb-water-dest",
"ctyslumb-water",
"ctyslumb-fountain-fall-dest",
"ctyslumb-fountain-fall",
// ctyslumc-water
"ctyslumc-water-dest",
"ctyslumc-water",
"ctyslumc-fountain-fall-dest",
"ctyslumc-fountain-fall",
// mined-tfrag
"mined-pillar-side-dest",
"mined-pillar-side-cold",
"mined-pillar-side-cooling",
"mined-pillar-side-hot",
"mined-pillar-molten",
"mined-pillar-top2side-dest",
"mined-pillar-top2side-cold",
"mined-pillar-top2side-cooling",
"mined-pillar-top2side-hot",
"mined-pillar-top-dest",
"mined-pillar-top-cold",
"mined-pillar-top-cooling",
"mined-pillar-top-hot",
"mined-pillar-molten-top",
// volcanoa-alpha
"vola-lava-01-dest",
"vola-lava-01",
"vola-lava-fall-dest",
"vola-lava-fall",
// wasstada-alpha
"wstd-lava-base-dest",
"wstd-lava-base"
],
"levels_to_extract": [
+22 -16
View File
@@ -1850,6 +1850,8 @@
["_stack_", 148, "float"],
["_stack_", 152, "float"],
["_stack_", 156, "float"],
[25, "a1", "light-trail-breadcrumb"],
[178, "s4", "light-trail-breadcrumb"],
[556, "a0", "vector"]
],
"compute-trail-scaled-t": [[17, "v1", "float"]],
@@ -2683,8 +2685,13 @@
[[21, 25], "a0", "prim-strip"]
],
"(event tracking light-trail-tracker)": [[55, "v1", "float"]],
"(method 21 light-trail)": [[50, "v1", "light-trail-breadcrumb"]],
"(method 14 light-trail)": [[47, "a0", "uint"]],
"(method 21 light-trail)": [[[18, 64], "gp", "light-trail-breadcrumb"]],
"(method 14 light-trail)": [
[47, "a0", "uint"],
[[10, 32], "a1", "light-trail-breadcrumb"],
[[34, 60], "s3", "light-trail-breadcrumb"],
[[34, 73], "s2", "light-trail-breadcrumb"]
],
"debug-menu-item-var-update-display-str": [
[48, "v1", "int"],
[63, "v1", "int"],
@@ -2735,16 +2742,12 @@
[27, "gp", "process-drawable"],
[30, "gp", "process-drawable"]
],
"(method 23 weapon-trail)": [
[62, "v1", "light-trail-breadcrumb"],
[65, "v1", "light-trail-breadcrumb"]
],
"(method 23 weapon-trail)": [[[0, 100], "gp", "weapon-trail-crumb"]],
"(method 22 weapon-trail)": [[32, "v0", "light-trail-breadcrumb"]],
"(method 22 tread-trail)": [[19, "v0", "light-trail-breadcrumb"]],
"(method 23 tread-trail)": [
[51, "v1", "light-trail-breadcrumb"],
[67, "v0", "light-trail-breadcrumb"]
],
"(method 23 tread-trail)": [[[0, 100], "s5", "tread-trail-crumb"]],
"(method 23 tire-trail)": [[[0, 74], "s5", "tire-trail-crumb"]],
"(method 22 tire-trail)": [[[18, 24], "v1", "tire-trail-crumb"]],
"(trans idle fma-sphere)": [[39, "a2", "process-drawable"]],
"part-water-splash-callback": [[3, "v1", "float"]],
"(method 15 water-control)": [[48, "v1", "float"]],
@@ -6428,11 +6431,11 @@
],
"cshape-reaction-scorp-shot": [[15, "v1", "v-scorp-shot"]],
"(method 78 wvehicle)": [
[262, "s1", "process-focusable"],
[271, "s1", "process-focusable"],
[287, "s1", "process-focusable"],
[309, "s1", "process-focusable"],
[322, "s1", "process-focusable"],
[262, "s1", "tire-trail-tracker"],
[271, "s1", "tire-trail-tracker"],
[287, "s1", "tire-trail-tracker"],
[309, "s1", "tire-trail-tracker"],
[322, "s1", "tire-trail-tracker"],
[358, "v1", "collide-shape-prim-group"]
],
"(method 97 wvehicle)": [
@@ -6551,7 +6554,10 @@
[15, "v1", "process-drawable"],
[22, "v1", "process-drawable"]
],
"(method 19 tire-trail)": [],
"(method 19 tire-trail)": [
[[5, 28], "s5", "tire-trail-crumb"],
[[5, 28], "s4", "tire-trail-crumb"]
],
"vehicle-spawn": [[93, "gp", "vehicle"]],
"vehicle-spawn-hack": [[41, "gp", "vehicle"]],
"(method 11 w-parking-spot)": [[42, "v0", "vector"]],
+41 -3
View File
@@ -515,8 +515,44 @@ TPageResultStats process_tpage(ObjectFileData& data,
// currently not needed.
break;
case int(PSM::PSMT8):
ASSERT(tex.clutpsm == int(CPSM::PSMCT32));
{
if (tex.clutpsm == (int)CPSM::PSMCT16) {
// will store output pixels, rgba (8888)
std::vector<u8> index_out;
// width is like the TEX0 register, in 64 texel units.
// not sure what the other widths are yet.
int read_width = 64 * tex.width[0];
// loop over pixels in output texture image
for (int y = 0; y < tex.h; y++) {
for (int x = 0; x < tex.w; x++) {
// read as the PSMT8 type. The dest field tells us a block offset.
auto addr8 = psmt8_addr(x, y, read_width) + tex.dest[0] * 256;
u8 value = *(u8*)(vram.data() + addr8);
index_out.push_back(value);
}
}
std::array<math::Vector4<u8>, 256> unscrambled_clut{};
for (int i = 0; i < 256; i++) {
u32 clut_chunk = i / 16;
u32 off_in_chunk = i % 16;
u8 clx = 0, cly = 0;
if (clut_chunk & 1) {
clx = 8;
}
cly = (clut_chunk >> 1) * 2;
if (off_in_chunk >= 8) {
off_in_chunk -= 8;
cly++;
}
clx += off_in_chunk;
u32 clut_addr = psmct16_addr(clx, cly, 64) + tex.clutdest * 256;
memcpy(&unscrambled_clut[i], vram.data() + clut_addr, 4);
}
texture_db.add_index_texture(texture_page.id, tex_id, index_out, unscrambled_clut,
tex.w, tex.h, tex.name, texture_page.name, level_names);
stats.successful_textures++;
} else if (tex.clutpsm == (int)PSM::PSMCT32) {
// will store output pixels, index (u8)
std::vector<u8> index_out;
@@ -555,10 +591,12 @@ TPageResultStats process_tpage(ObjectFileData& data,
texture_db.add_index_texture(texture_page.id, tex_id, index_out, unscrambled_clut,
tex.w, tex.h, tex.name, texture_page.name, level_names);
stats.successful_textures++;
} else {
ASSERT_NOT_REACHED();
}
break;
default:
lg::die("Animated texture {} format {}\n", tex.name, tex.psm);
lg::die("Animated texture {} format {} clut {}\n", tex.name, tex.psm, tex.clutpsm);
}
}
+284
View File
@@ -0,0 +1,284 @@
#include "decompilation_process.h"
#include <string>
#include <vector>
#include "config.h"
#include "common/log/log.h"
#include "common/util/Timer.h"
#include "common/util/os.h"
#include "Disasm/OpcodeInfo.h"
#include "ObjectFile/ObjectFileDB.h"
#include "data/streamed_audio.h"
#include "level_extractor/extract_level.h"
int run_decompilation_process(decompiler::Config config,
const fs::path& in_folder,
const fs::path& out_folder,
const bool minimal_for_extractor) {
using namespace decompiler;
Timer decomp_timer;
lg::info("[Mem] Top of main: {} MB\n", get_peak_rss() / (1024 * 1024));
init_opcode_info();
lg::info("[Mem] After init: {} MB\n", get_peak_rss() / (1024 * 1024));
std::vector<fs::path> dgos, objs, strs, tex_strs, art_strs;
if (minimal_for_extractor) {
// TODO - does this even matter, or can we just make the DGOs lazily loaded (does it already
// happen?)
for (const auto& dgo_name : config.dgo_names) {
std::string common_name = "GAME.CGO";
if (dgo_name.length() > 3 && dgo_name.substr(dgo_name.length() - 3) == "DGO") {
// ends in DGO, it's a level
dgos.push_back(in_folder / dgo_name);
} else if (dgo_name.length() >= common_name.length() &&
dgo_name.substr(dgo_name.length() - common_name.length()) == common_name) {
// it's COMMON.CGO, we need that too.
dgos.push_back(in_folder / dgo_name);
}
}
} else {
for (const auto& dgo_name : config.dgo_names) {
dgos.push_back(in_folder / dgo_name);
}
}
if (minimal_for_extractor) {
// TODO - does this even matter, or can we just make the DGOs lazily loaded (does it already
// happen?)
for (const auto& obj_name : config.object_file_names) {
if (obj_name.length() > 3 && obj_name.substr(obj_name.length() - 3) == "TXT") {
// ends in TXT
objs.push_back(in_folder / obj_name);
}
}
} else {
for (const auto& obj_name : config.object_file_names) {
objs.push_back(in_folder / obj_name);
}
}
if (!minimal_for_extractor) {
for (const auto& str_name : config.str_file_names) {
strs.push_back(in_folder / str_name);
}
}
for (const auto& str_name : config.str_texture_file_names) {
tex_strs.push_back(in_folder / str_name);
}
for (const auto& str_name : config.str_art_file_names) {
art_strs.push_back(in_folder / str_name);
}
lg::info("[Mem] After config read: {} MB", get_peak_rss() / (1024 * 1024));
// build file database
lg::info("Setting up object file DB...");
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, art_strs,
config);
// Explicitly fail if a file in the 'allowed_objects' list wasn't found in the DB
// as this is another silent error that can be confusing
if (!config.allowed_objects.empty()) {
for (const auto& expected_obj : config.allowed_objects) {
if (db.obj_files_by_name.count(expected_obj) == 0) {
// TODO - this is wrong for jak1, fix eventually as this is now done in 3 places
lg::error(
"Expected to find '{}' in the ObjectFileDB but did not. Check "
"./decompiler/config/{}/inputs.jsonc",
expected_obj, config.game_name);
return 1;
}
}
}
lg::info("[Mem] After DB setup: {} MB", get_peak_rss() / (1024 * 1024));
// write out DGO file info
file_util::create_dir_if_needed(out_folder);
file_util::write_text_file(out_folder / "dgo.txt", db.generate_dgo_listing());
// write out object file map (used for future decompilations, if desired)
file_util::write_text_file(out_folder / "obj.txt",
db.generate_obj_listing(config.merged_objects));
// dump raw objs
if (config.dump_objs) {
auto path = out_folder / "raw_obj";
file_util::create_dir_if_needed(path);
db.dump_raw_objects(path);
}
// process files (required for all analysis)
db.process_link_data(config);
lg::info("[Mem] After link data: {} MB", get_peak_rss() / (1024 * 1024));
db.find_code(config);
db.process_labels();
lg::info("[Mem] After code: {} MB", get_peak_rss() / (1024 * 1024));
// top level decompile (do this before printing asm so we get function names)
if (config.find_functions) {
db.ir2_top_level_pass(config);
}
// print disassembly
if (config.disassemble_code || config.disassemble_data) {
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
config.write_hex_near_instructions);
}
if (config.process_art_groups) {
db.extract_art_info();
// dump art info to json if requested
if (config.dump_art_group_info) {
auto ag_file_name = out_folder / "dump" / "art-group-info.min.json";
nlohmann::json ag_json = db.dts.art_group_info;
file_util::create_dir_if_needed_for_file(ag_file_name);
file_util::write_text_file(ag_file_name, ag_json.dump(-1));
lg::info("[DUMP] Dumped art group info to {}", ag_file_name.string());
}
if (config.dump_joint_geo_info) {
auto jg_file_name = out_folder / "dump" / "joint-node-info.min.json";
nlohmann::json jg_json = db.dts.jg_info;
file_util::create_dir_if_needed_for_file(jg_file_name);
file_util::write_text_file(jg_file_name, jg_json.dump(-1));
lg::info("[DUMP] Dumped joint node info to {}", jg_file_name.string());
}
} else if (!config.art_group_info_dump.empty() || !config.jg_info_dump.empty()) {
// process art groups (used in decompilation)
// - if the config has a path to the art info dump, just use that
// - otherwise (or if we want to dump it fresh) extract it
if (!config.art_group_info_dump.empty()) {
db.dts.art_group_info = config.art_group_info_dump;
}
if (!config.jg_info_dump.empty()) {
db.dts.jg_info = config.jg_info_dump;
}
} else {
lg::error("`process_art_groups` was false and no art-group-info dump was provided!");
return 1;
}
if (config.process_tpages && !config.texture_info_dump.empty()) {
db.dts.textures = config.texture_info_dump;
}
// main decompile.
if (config.decompile_code) {
db.analyze_functions_ir2(out_folder, config, {}, {}, {});
}
if (config.generate_all_types) {
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
db.ir2_analyze_all_types(out_folder / "new-all-types.gc", config.old_all_types_file,
config.hacks.types_with_bad_inspect_methods);
}
lg::info("[Mem] After decomp: {} MB", get_peak_rss() / (1024 * 1024));
// write out all symbols
file_util::write_text_file(out_folder / "all-syms.gc", db.dts.dump_symbol_types());
// write art groups
if (config.process_art_groups) {
db.dump_art_info(out_folder);
}
if (config.hexdump_code || config.hexdump_data) {
db.write_object_file_words(out_folder, config.hexdump_data, config.hexdump_code);
}
// data stuff
if (config.write_scripts) {
db.find_and_write_scripts(out_folder);
}
// ensure asset dir exists
file_util::create_dir_if_needed(out_folder / "assets");
if (config.process_game_text) {
auto result = db.process_game_text_files(config);
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
}
}
lg::info("[Mem] After text: {} MB", get_peak_rss() / (1024 * 1024));
if (config.process_subtitle_text || config.process_subtitle_images) {
auto result = db.process_all_spool_subtitles(
config, config.process_subtitle_images ? out_folder / "assets" / "subtitle-images" : "");
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_subs.txt", result);
}
}
lg::info("[Mem] After spool handling: {} MB", get_peak_rss() / (1024 * 1024));
TextureDB tex_db;
if (config.process_tpages || config.levels_extract) {
auto textures_out = out_folder / "textures";
auto dump_out = out_folder / "import";
file_util::create_dir_if_needed(textures_out);
auto result = db.process_tpages(tex_db, textures_out, config, dump_out);
if (!result.empty() && config.process_tpages) {
file_util::write_text_file(textures_out / "tpage-dir.txt", result);
file_util::write_text_file(textures_out / "tex-remap.txt",
tex_db.generate_texture_dest_adjustment_table());
}
if (config.dump_tex_info) {
auto texture_file_name = out_folder / "dump" / "tex-info.min.json";
nlohmann::json texture_json = db.dts.textures;
file_util::create_dir_if_needed_for_file(texture_file_name);
file_util::write_text_file(texture_file_name, texture_json.dump(-1));
lg::info("[DUMP] Dumped texture info to {}", texture_file_name.string());
}
}
lg::info("[Mem] After textures: {} MB", get_peak_rss() / (1024 * 1024));
// Merge textures before replacing them, in other words, replacements take priority
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
game_version_names[config.game_version] / "texture_merges";
if (fs::exists(texture_merge_path)) {
tex_db.merge_textures(texture_merge_path);
}
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[config.game_version] / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);
}
if (config.process_game_count) {
auto result = db.process_game_count_file();
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
}
}
if (config.levels_extract) {
auto level_out_path =
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
file_util::create_dir_if_needed(level_out_path);
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
}
lg::info("[Mem] After extraction: {} MB", get_peak_rss() / (1024 * 1024));
if (config.rip_streamed_audio) {
auto streaming_audio_out = out_folder / "audio";
file_util::create_dir_if_needed(streaming_audio_out);
process_streamed_audio(config, streaming_audio_out, in_folder,
config.streamed_audio_file_names);
}
lg::info("Decompiler has finished successfully in {:.2f} seconds.", decomp_timer.getSeconds());
return 0;
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include "config.h"
int run_decompilation_process(decompiler::Config config,
const fs::path& in_folder,
const fs::path& out_folder,
const bool minimal_for_extractor);
+26 -110
View File
@@ -5,10 +5,9 @@
#include "common/util/term_util.h"
#include "common/util/unicode_util.h"
#include "decompiler/ObjectFile/ObjectFileDB.h"
#include "decompiler/config.h"
#include "decompiler/decompilation_process.h"
#include "decompiler/extractor/extractor_util.h"
#include "decompiler/level_extractor/extract_level.h"
#include "goalc/compiler/Compiler.h"
#include "third-party/CLI11.hpp"
@@ -102,116 +101,24 @@ std::tuple<std::optional<ISOMetadata>, ExtractorErrorCode> validate(
};
}
// TODO - remove code duplication, most of this is copying what happens in decompiler's `main.cpp`
void decompile(const fs::path& iso_data_path,
const std::string& data_subfolder,
const std::string& config_override) {
using namespace decompiler;
ExtractorErrorCode decompile(const fs::path& in_folder,
const std::string& data_subfolder,
const std::string& config_override) {
// Determine which config to use from the database
const auto version_info = get_version_info_or_default(iso_data_path);
const auto version_info = get_version_info_or_default(in_folder);
Config config = read_config_file(file_util::get_jak_project_dir() / "decompiler" / "config" /
version_info.game_name /
fmt::format("{}_config.jsonc", version_info.game_name),
version_info.decomp_config_version, config_override);
decompiler::Config config = decompiler::read_config_file(
file_util::get_jak_project_dir() / "decompiler" / "config" / version_info.game_name /
fmt::format("{}_config.jsonc", version_info.game_name),
version_info.decomp_config_version, config_override);
std::vector<fs::path> dgos, objs, tex_strs, art_strs;
// grab all DGOS we need (level + common)
// TODO - Jak 2 - jak 1 specific code?
for (const auto& dgo_name : config.dgo_names) {
std::string common_name = "GAME.CGO";
if (dgo_name.length() > 3 && dgo_name.substr(dgo_name.length() - 3) == "DGO") {
// ends in DGO, it's a level
dgos.push_back(iso_data_path / dgo_name);
} else if (dgo_name.length() >= common_name.length() &&
dgo_name.substr(dgo_name.length() - common_name.length()) == common_name) {
// it's COMMON.CGO, we need that too.
dgos.push_back(iso_data_path / dgo_name);
}
}
// grab all the object files we need (just text)
for (const auto& obj_name : config.object_file_names) {
if (obj_name.length() > 3 && obj_name.substr(obj_name.length() - 3) == "TXT") {
// ends in TXT
objs.push_back(iso_data_path / obj_name);
}
}
for (const auto& str_name : config.str_texture_file_names) {
tex_strs.push_back(iso_data_path / str_name);
}
for (const auto& str_name : config.str_art_file_names) {
art_strs.push_back(iso_data_path / str_name);
}
// set up objects
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, tex_strs, art_strs,
config);
// save object files
auto out_folder = file_util::get_jak_project_dir() / "decompiler_out" / data_subfolder;
auto raw_obj_folder = out_folder / "raw_obj";
file_util::create_dir_if_needed(raw_obj_folder);
db.dump_raw_objects(raw_obj_folder);
// analyze object file link data
db.process_link_data(config);
db.find_code(config);
db.process_labels();
// ensure asset dir exists
file_util::create_dir_if_needed(out_folder / "assets");
// text files
{
auto result = db.process_game_text_files(config);
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
}
}
// textures
decompiler::TextureDB tex_db;
auto textures_out = out_folder / "textures";
auto dump_out = out_folder / "import";
file_util::create_dir_if_needed(textures_out);
file_util::write_text_file(textures_out / "tpage-dir.txt",
db.process_tpages(tex_db, textures_out, config, dump_out));
// texture merges
// TODO - put all this stuff in somewhere common
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
game_version_names[config.game_version] / "texture_merges";
if (fs::exists(texture_merge_path)) {
tex_db.merge_textures(texture_merge_path);
}
// texture replacements
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[config.game_version] / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);
}
// game count
{
auto result = db.process_game_count_file();
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
}
}
// levels
{
auto level_out_path =
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
file_util::create_dir_if_needed(level_out_path);
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
const auto result = run_decompilation_process(config, in_folder, out_folder, true);
if (result != 0) {
return ExtractorErrorCode::DECOMPILATION_GENERIC_ERROR;
}
return ExtractorErrorCode::SUCCESS;
}
const std::unordered_map<std::string, GameIsoFlags> game_iso_flag_names = {
@@ -315,7 +222,6 @@ int main(int argc, char** argv) {
}
// - SETUP
decompiler::init_opcode_info();
if (!project_path_override.empty()) {
if (!fs::exists(project_path_override)) {
lg::error("Error: project path override '{}' does not exist", project_path_override.string());
@@ -426,7 +332,11 @@ int main(int argc, char** argv) {
// Get hash and file count
const auto [hash, file_count] = calculate_extraction_hash(iso_data_path);
// Validate
auto [version_info, code] = validate(iso_data_path, hash, file_count);
auto [version_info, validate_code] = validate(iso_data_path, hash, file_count);
if (validate_code == ExtractorErrorCode::VALIDATION_BAD_EXTRACTION ||
(flag_fail_on_validation && validate_code != ExtractorErrorCode::SUCCESS)) {
return static_cast<int>(validate_code);
}
}
// write out a json file with some metadata for the game
@@ -455,7 +365,10 @@ int main(int argc, char** argv) {
if (flag_decompile) {
try {
decompile(iso_data_path, data_subfolder, decomp_config_override);
const auto status_code = decompile(iso_data_path, data_subfolder, decomp_config_override);
if (status_code != ExtractorErrorCode::SUCCESS) {
return static_cast<int>(status_code);
}
} catch (std::exception& e) {
lg::error("Error during decompile: {}", e.what());
return static_cast<int>(ExtractorErrorCode::DECOMPILATION_GENERIC_ERROR);
@@ -463,7 +376,10 @@ int main(int argc, char** argv) {
}
if (flag_compile) {
compile(iso_data_path, data_subfolder);
const auto status_code = compile(iso_data_path, data_subfolder);
if (status_code != ExtractorErrorCode::SUCCESS) {
return static_cast<int>(status_code);
}
}
if (flag_play) {
+7 -4
View File
@@ -322,7 +322,8 @@ void extract_common(const ObjectFileDB& db,
compressed.data(), compressed.size());
if (config.rip_levels) {
auto file_path = file_util::get_jak_project_dir() / "glb_out" / "common.glb";
auto file_path = file_util::get_jak_project_dir() / "glb_out" /
game_version_names[config.game_version] / "common.glb";
file_util::create_dir_if_needed_for_file(file_path);
save_level_foreground_as_gltf(tfrag_level, art_group_data, file_path);
}
@@ -360,15 +361,17 @@ void extract_from_level(const ObjectFileDB& db,
if (config.rip_levels) {
auto back_file_path = file_util::get_jak_project_dir() / "glb_out" /
fmt::format("{}_background.glb", level_data.level_name);
game_version_names[config.game_version] /
fmt::format("{}-background.glb", level_data.level_name);
file_util::create_dir_if_needed_for_file(back_file_path);
save_level_background_as_gltf(level_data, back_file_path);
auto fore_file_path = file_util::get_jak_project_dir() / "glb_out" /
fmt::format("{}_foreground.glb", level_data.level_name);
game_version_names[config.game_version] /
fmt::format("{}-foreground.glb", level_data.level_name);
file_util::create_dir_if_needed_for_file(fore_file_path);
save_level_foreground_as_gltf(level_data, art_group_data, fore_file_path);
}
file_util::write_text_file(entities_folder / fmt::format("{}_actors.json", level_data.level_name),
file_util::write_text_file(entities_folder / fmt::format("{}-actors.json", level_data.level_name),
extract_actors_to_json(bsp_header.actors));
}
@@ -1,5 +1,7 @@
#include "extract_merc.h"
#include "merc_replacement.h"
#include "common/log/log.h"
#include "common/util/BitUtils.h"
#include "common/util/FileUtil.h"
@@ -1597,6 +1599,60 @@ void create_modifiable_vertex_data(
}
}
void replace_model(tfrag3::Level& lvl, tfrag3::MercModel& model, const fs::path& mdl_path) {
if (model.max_bones < 100) {
auto lvl_name = lvl.level_name == "" ? "common" : lvl.level_name;
lg::info("Replacing {} for {}: {} effects, {} max bones, {} max draws\n", model.name, lvl_name,
model.effects.size(), model.max_bones, model.max_draws);
std::vector<tfrag3::MercVertex> old_verts;
for (auto& e : model.effects) {
for (auto& d : e.all_draws) {
for (size_t i = 0; i < d.index_count; i++) {
auto idx = lvl.merc_data.indices.at(i + d.first_index);
if (idx != UINT32_MAX) {
old_verts.push_back(lvl.merc_data.vertices[idx]);
}
}
}
}
auto swap_info = load_replacement_merc_model(model.name, lvl.merc_data.indices.size(),
lvl.merc_data.vertices.size(), lvl.textures.size(),
mdl_path.string(), old_verts, false);
model = swap_info.new_model;
size_t old_start = lvl.merc_data.vertices.size();
for (auto& ind : swap_info.new_indices) {
ASSERT(ind >= old_start);
}
lvl.merc_data.indices.insert(lvl.merc_data.indices.end(), swap_info.new_indices.begin(),
swap_info.new_indices.end());
lvl.merc_data.vertices.insert(lvl.merc_data.vertices.end(), swap_info.new_vertices.begin(),
swap_info.new_vertices.end());
lvl.textures.insert(lvl.textures.end(), swap_info.new_textures.begin(),
swap_info.new_textures.end());
}
}
void add_custom_model_to_level(tfrag3::Level& lvl,
const std::string& name,
const fs::path& mdl_path) {
auto lvl_name = lvl.level_name == "" ? "common" : lvl.level_name;
lg::info("Adding custom model {} to {}", name, lvl_name);
auto merc_data =
load_replacement_merc_model(name, lvl.merc_data.indices.size(), lvl.merc_data.vertices.size(),
lvl.textures.size(), mdl_path.string(), {}, true);
for (auto& idx : merc_data.new_indices) {
lvl.merc_data.indices.push_back(idx);
}
for (auto& vert : merc_data.new_vertices) {
lvl.merc_data.vertices.push_back(vert);
}
lvl.merc_data.models.push_back(merc_data.new_model);
lvl.textures.insert(lvl.textures.end(), merc_data.new_textures.begin(),
merc_data.new_textures.end());
}
/*!
* Top-level merc extraction
*/
@@ -1731,5 +1787,33 @@ void extract_merc(const ObjectFileData& ag_data,
}
}
}
// do model replacements if present
auto merc_replacement_folder = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[version] / "merc_replacements";
if (file_util::file_exists(merc_replacement_folder.string())) {
auto merc_replacements =
file_util::find_files_in_dir(merc_replacement_folder, std::regex(".*\\.glb"));
for (auto& path : merc_replacements) {
auto name = path.stem().string();
auto it = std::find_if(out.merc_data.models.begin(), out.merc_data.models.end(),
[&](const auto& m) { return m.name == name; });
if (it != out.merc_data.models.end()) {
auto& model = *it;
replace_model(out, model, path);
}
}
}
// add custom models if present
auto lvl_name = out.level_name == "" ? "common" : out.level_name;
auto models_folder = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[version] / "models" / lvl_name;
if (file_util::file_exists(models_folder.string())) {
auto custom_models = file_util::find_files_in_dir(models_folder, std::regex(".*\\.glb"));
for (auto& mdl : custom_models) {
add_custom_model_to_level(out, mdl.stem().string(), mdl);
}
}
}
} // namespace decompiler
@@ -0,0 +1,211 @@
#include "merc_replacement.h"
using namespace gltf_util;
namespace decompiler {
void extract(const std::string& name,
MercExtractData& out,
const tinygltf::Model& model,
const std::vector<NodeWithTransform>& all_nodes,
u32 index_offset,
u32 vertex_offset,
u32 tex_offset) {
ASSERT(out.new_vertices.empty());
std::map<int, tfrag3::MercDraw> draw_by_material;
int mesh_count = 0;
int prim_count = 0;
for (const auto& n : all_nodes) {
const auto& node = model.nodes[n.node_idx];
if (node.extras.Has("set_invisible") && node.extras.Get("set_invisible").Get<int>()) {
continue;
}
if (node.mesh >= 0) {
const auto& mesh = model.meshes[node.mesh];
mesh_count++;
for (const auto& prim : mesh.primitives) {
prim_count++;
// extract index buffer
std::vector<u32> prim_indices = gltf_util::gltf_index_buffer(
model, prim.indices, out.new_vertices.size() + vertex_offset);
ASSERT_MSG(prim.mode == TINYGLTF_MODE_TRIANGLES, "Unsupported triangle mode");
// extract vertices
auto verts =
gltf_util::gltf_vertices(model, prim.attributes, n.w_T_node, true, true, mesh.name);
out.new_vertices.insert(out.new_vertices.end(), verts.vtx.begin(), verts.vtx.end());
out.new_colors.insert(out.new_colors.end(), verts.vtx_colors.begin(),
verts.vtx_colors.end());
out.normals.insert(out.normals.end(), verts.normals.begin(), verts.normals.end());
ASSERT(out.new_colors.size() == out.new_vertices.size());
// TODO: just putting it all in one material
auto& draw = draw_by_material[prim.material];
draw.mode = gltf_util::make_default_draw_mode(); // todo rm
draw.tree_tex_id = 0; // todo rm
draw.num_triangles += prim_indices.size() / 3;
draw.no_strip = true;
draw.index_count = prim_indices.size();
draw.first_index = index_offset + out.new_indices.size();
out.new_indices.insert(out.new_indices.end(), prim_indices.begin(), prim_indices.end());
}
}
}
tfrag3::MercEffect e;
out.new_model.name = name;
out.new_model.max_bones = 120;
out.new_model.max_draws = 200;
for (const auto& [mat_idx, d_] : draw_by_material) {
e.all_draws.push_back(d_);
auto& draw = e.all_draws.back();
draw.mode = make_default_draw_mode();
if (mat_idx == -1) {
lg::warn("Draw had a material index of -1, using default texture.");
draw.tree_tex_id = 0;
continue;
}
const auto& mat = model.materials[mat_idx];
int tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index;
if (tex_idx == -1) {
lg::warn("Material {} has no texture, using default texture.", mat.name);
draw.tree_tex_id = 0;
continue;
}
const auto& tex = model.textures[tex_idx];
ASSERT(tex.sampler >= 0);
ASSERT(tex.source >= 0);
draw.mode = draw_mode_from_sampler(model.samplers.at(tex.sampler));
const auto& img = model.images[tex.source];
draw.tree_tex_id = tex_offset + texture_pool_add_texture(&out.tex_pool, img);
}
lg::info("total of {} unique materials", e.all_draws.size());
e.has_mod_draw = false;
out.new_model.effects.push_back(e);
out.new_model.effects.push_back(e);
out.new_model.effects.push_back(e);
out.new_model.effects.push_back(e);
lg::info("Merged {} meshes and {} prims into {} vertices", mesh_count, prim_count,
out.new_vertices.size());
}
const tfrag3::MercVertex& find_closest(const std::vector<tfrag3::MercVertex>& old,
float x,
float y,
float z) {
float best_dist = 1e10;
int best_idx = 0;
for (int i = 0; i < old.size(); i++) {
auto& v = old[i];
float dx = v.pos[0] - x;
float dy = v.pos[1] - y;
float dz = v.pos[2] - z;
float dist = (dx * dx) + (dy * dy) + (dz * dz);
if (dist < best_dist) {
best_dist = dist;
best_idx = i;
}
}
return old[best_idx];
}
void merc_convert_replacement(MercSwapData& out,
const MercExtractData& in,
const std::vector<tfrag3::MercVertex>& old_verts) {
out.new_model = in.new_model;
out.new_indices = in.new_indices;
out.new_textures = in.tex_pool.textures_by_idx;
// convert vertices
for (size_t i = 0; i < in.new_vertices.size(); i++) {
const auto& y = in.new_vertices[i];
const auto& copy_from = find_closest(old_verts, y.x, y.y, y.z);
auto& x = out.new_vertices.emplace_back();
x.pos[0] = y.x;
x.pos[1] = y.y;
x.pos[2] = y.z;
x.normal[0] = copy_from.normal[0];
x.normal[1] = copy_from.normal[1];
x.normal[2] = copy_from.normal[2];
x.weights[0] = copy_from.weights[0];
x.weights[1] = copy_from.weights[1];
x.weights[2] = copy_from.weights[2];
x.st[0] = y.s;
x.st[1] = y.t;
x.rgba[0] = in.new_colors[i][0];
x.rgba[1] = in.new_colors[i][1];
x.rgba[2] = in.new_colors[i][2];
x.rgba[3] = in.new_colors[i][3];
x.mats[0] = copy_from.mats[0];
x.mats[1] = copy_from.mats[1];
x.mats[2] = copy_from.mats[2];
}
}
void merc_convert_custom(MercSwapData& out, const MercExtractData& in) {
out.new_model = in.new_model;
out.new_indices = in.new_indices;
out.new_textures = in.tex_pool.textures_by_idx;
// convert vertices
for (size_t i = 0; i < in.new_vertices.size(); i++) {
const auto& y = in.new_vertices[i];
auto& x = out.new_vertices.emplace_back();
x.pos[0] = y.x;
x.pos[1] = y.y;
x.pos[2] = y.z;
x.normal[0] = in.normals.at(i).x();
x.normal[1] = in.normals.at(i).y();
x.normal[2] = in.normals.at(i).z();
x.weights[0] = 1.0f;
x.weights[1] = 0.0f;
x.weights[2] = 0.0f;
x.st[0] = y.s;
x.st[1] = y.t;
x.rgba[0] = in.new_colors[i][0];
x.rgba[1] = in.new_colors[i][1];
x.rgba[2] = in.new_colors[i][2];
x.rgba[3] = in.new_colors[i][3];
x.mats[0] = 3;
x.mats[1] = 0;
x.mats[2] = 0;
}
}
MercSwapData load_replacement_merc_model(const std::string& name,
u32 current_idx_count,
u32 current_vtx_count,
u32 current_tex_count,
const std::string& path,
const std::vector<tfrag3::MercVertex>& old_verts,
bool custom_mdl) {
MercSwapData result;
lg::info("Reading gltf mesh: {}", path);
tinygltf::TinyGLTF loader;
tinygltf::Model model;
std::string err, warn;
bool res = loader.LoadBinaryFromFile(&model, &err, &warn, path);
ASSERT_MSG(warn.empty(), warn.c_str());
ASSERT_MSG(err.empty(), err.c_str());
ASSERT_MSG(res, "Failed to load GLTF file!");
auto all_nodes = flatten_nodes_from_all_scenes(model);
MercExtractData extract_data;
extract(name, extract_data, model, all_nodes, current_idx_count, current_vtx_count,
current_tex_count);
if (custom_mdl) {
merc_convert_custom(result, extract_data);
} else {
merc_convert_replacement(result, extract_data, old_verts);
}
return result;
}
} // namespace decompiler
@@ -0,0 +1,32 @@
#pragma once
#include "common/log/log.h"
#include "common/util/gltf_util.h"
namespace decompiler {
struct MercExtractData {
gltf_util::TexturePool tex_pool;
std::vector<u32> new_indices;
std::vector<tfrag3::PreloadedVertex> new_vertices;
std::vector<math::Vector<u8, 4>> new_colors;
std::vector<math::Vector3f> normals;
tfrag3::MercModel new_model;
};
// Data produced by loading a replacement model
struct MercSwapData {
std::vector<u32> new_indices;
std::vector<tfrag3::MercVertex> new_vertices;
std::vector<tfrag3::Texture> new_textures;
tfrag3::MercModel new_model;
};
MercSwapData load_replacement_merc_model(const std::string& name,
u32 current_idx_count,
u32 current_vtx_count,
u32 current_tex_count,
const std::string& path,
const std::vector<tfrag3::MercVertex>& old_verts,
bool custom_mdl);
} // namespace decompiler
+5 -255
View File
@@ -1,33 +1,15 @@
#include <cstdio>
#include <string>
#include <vector>
#include "config.h"
#include "decompilation_process.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/Timer.h"
#include "common/util/diff.h"
#include "common/util/os.h"
#include "common/util/set_util.h"
#include "common/util/term_util.h"
#include "common/util/unicode_util.h"
#include "common/versions/versions.h"
#include "ObjectFile/ObjectFileDB.h"
#include "decompiler/data/TextureDB.h"
#include "decompiler/data/streamed_audio.h"
#include "decompiler/level_extractor/extract_level.h"
#include "third-party/CLI11.hpp"
#include "third-party/json.hpp"
template <typename... Args>
static void mem_log(const std::string& format, Args&&... args) {
#ifndef _WIN32
lg::info("[Mem] " + format, std::forward<Args>(args)...);
#endif
}
int main(int argc, char** argv) {
ArgumentGuard u8_guard(argc, argv);
@@ -81,11 +63,9 @@ int main(int argc, char** argv) {
return 1;
}
using namespace decompiler;
Config config;
decompiler::Config config;
try {
config = read_config_file(config_path, config_game_version, config_override);
config = decompiler::read_config_file(config_path, config_game_version, config_override);
} catch (const std::exception& e) {
lg::error("Failed to parse config: {}", e.what());
return 1;
@@ -115,7 +95,7 @@ int main(int argc, char** argv) {
// Warning message if expected ELF isn't found, user could be using bad assets / didn't extract
// the ISO properly
if (!config.expected_elf_name.empty() && !exists(in_folder / config.expected_elf_name)) {
if (!config.expected_elf_name.empty() && !fs::exists(in_folder / config.expected_elf_name)) {
lg::error(
"WARNING - '{}' does not contain the expected ELF file '{}'. Was the ISO extracted "
"properly or is there a version mismatch?",
@@ -123,235 +103,5 @@ int main(int argc, char** argv) {
}
// -- Begin the Decompilation!
Timer decomp_timer;
mem_log("Top of main: {} MB\n", get_peak_rss() / (1024 * 1024));
init_opcode_info();
mem_log("After init: {} MB\n", get_peak_rss() / (1024 * 1024));
std::vector<fs::path> dgos, objs, strs, tex_strs, art_strs;
for (const auto& dgo_name : config.dgo_names) {
dgos.push_back(in_folder / dgo_name);
}
for (const auto& obj_name : config.object_file_names) {
objs.push_back(in_folder / obj_name);
}
for (const auto& str_name : config.str_file_names) {
strs.push_back(in_folder / str_name);
}
for (const auto& str_name : config.str_texture_file_names) {
tex_strs.push_back(in_folder / str_name);
}
for (const auto& str_name : config.str_art_file_names) {
art_strs.push_back(in_folder / str_name);
}
mem_log("After config read: {} MB", get_peak_rss() / (1024 * 1024));
// build file database
lg::info("Setting up object file DB...");
ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, art_strs,
config);
// Explicitly fail if a file in the 'allowed_objects' list wasn't found in the DB
// as this is another silent error that can be confusing
if (!config.allowed_objects.empty()) {
for (const auto& expected_obj : config.allowed_objects) {
if (db.obj_files_by_name.count(expected_obj) == 0) {
// TODO - this is wrong for jak1, fix eventually as this is now done in 3 places
lg::error(
"Expected to find '{}' in the ObjectFileDB but did not. Check "
"./decompiler/config/{}/inputs.jsonc",
expected_obj, config.game_name);
return 1;
}
}
}
mem_log("After DB setup: {} MB", get_peak_rss() / (1024 * 1024));
// write out DGO file info
file_util::write_text_file(out_folder / "dgo.txt", db.generate_dgo_listing());
// write out object file map (used for future decompilations, if desired)
file_util::write_text_file(out_folder / "obj.txt",
db.generate_obj_listing(config.merged_objects));
// dump raw objs
if (config.dump_objs) {
auto path = out_folder / "raw_obj";
file_util::create_dir_if_needed(path);
db.dump_raw_objects(path);
}
// process files (required for all analysis)
db.process_link_data(config);
mem_log("After link data: {} MB", get_peak_rss() / (1024 * 1024));
db.find_code(config);
db.process_labels();
mem_log("After code: {} MB", get_peak_rss() / (1024 * 1024));
// top level decompile (do this before printing asm so we get function names)
if (config.find_functions) {
db.ir2_top_level_pass(config);
}
// print disassembly
if (config.disassemble_code || config.disassemble_data) {
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
config.write_hex_near_instructions);
}
if (config.process_art_groups) {
db.extract_art_info();
// dump art info to json if requested
if (config.dump_art_group_info) {
auto ag_file_name = out_folder / "dump" / "art-group-info.min.json";
nlohmann::json ag_json = db.dts.art_group_info;
file_util::create_dir_if_needed_for_file(ag_file_name);
file_util::write_text_file(ag_file_name, ag_json.dump(-1));
lg::info("[DUMP] Dumped art group info to {}", ag_file_name.string());
}
if (config.dump_joint_geo_info) {
auto jg_file_name = out_folder / "dump" / "joint-node-info.min.json";
nlohmann::json jg_json = db.dts.jg_info;
file_util::create_dir_if_needed_for_file(jg_file_name);
file_util::write_text_file(jg_file_name, jg_json.dump(-1));
lg::info("[DUMP] Dumped joint node info to {}", jg_file_name.string());
}
} else if (!config.art_group_info_dump.empty() || !config.jg_info_dump.empty()) {
// process art groups (used in decompilation)
// - if the config has a path to the art info dump, just use that
// - otherwise (or if we want to dump it fresh) extract it
if (!config.art_group_info_dump.empty()) {
db.dts.art_group_info = config.art_group_info_dump;
}
if (!config.jg_info_dump.empty()) {
db.dts.jg_info = config.jg_info_dump;
}
} else {
lg::error("`process_art_groups` was false and no art-group-info dump was provided!");
return 1;
}
if (config.process_tpages && !config.texture_info_dump.empty()) {
db.dts.textures = config.texture_info_dump;
}
// main decompile.
if (config.decompile_code) {
db.analyze_functions_ir2(out_folder, config, {}, {}, {});
}
if (config.generate_all_types) {
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
db.ir2_analyze_all_types(out_folder / "new-all-types.gc", config.old_all_types_file,
config.hacks.types_with_bad_inspect_methods);
}
mem_log("After decomp: {} MB", get_peak_rss() / (1024 * 1024));
// write out all symbols
file_util::write_text_file(out_folder / "all-syms.gc", db.dts.dump_symbol_types());
// write art groups
if (config.process_art_groups) {
db.dump_art_info(out_folder);
}
if (config.hexdump_code || config.hexdump_data) {
db.write_object_file_words(out_folder, config.hexdump_data, config.hexdump_code);
}
// data stuff
if (config.write_scripts) {
db.find_and_write_scripts(out_folder);
}
if (config.process_game_text) {
auto result = db.process_game_text_files(config);
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_text.txt", result);
}
}
mem_log("After text: {} MB", get_peak_rss() / (1024 * 1024));
if (config.process_subtitle_text || config.process_subtitle_images) {
auto result = db.process_all_spool_subtitles(
config, config.process_subtitle_images ? out_folder / "assets" / "subtitle-images" : "");
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_subs.txt", result);
}
}
mem_log("After spool handling: {} MB", get_peak_rss() / (1024 * 1024));
TextureDB tex_db;
if (config.process_tpages || config.levels_extract) {
auto textures_out = out_folder / "textures";
auto dump_out = out_folder / "import";
file_util::create_dir_if_needed(textures_out);
auto result = db.process_tpages(tex_db, textures_out, config, dump_out);
if (!result.empty() && config.process_tpages) {
file_util::write_text_file(textures_out / "tpage-dir.txt", result);
file_util::write_text_file(textures_out / "tex-remap.txt",
tex_db.generate_texture_dest_adjustment_table());
}
if (config.dump_tex_info) {
auto texture_file_name = out_folder / "dump" / "tex-info.min.json";
nlohmann::json texture_json = db.dts.textures;
file_util::create_dir_if_needed_for_file(texture_file_name);
file_util::write_text_file(texture_file_name, texture_json.dump(-1));
lg::info("[DUMP] Dumped texture info to {}", texture_file_name.string());
}
}
mem_log("After textures: {} MB", get_peak_rss() / (1024 * 1024));
// Merge textures before replacing them, in other words, replacements take priority
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
game_version_names[config.game_version] / "texture_merges";
if (fs::exists(texture_merge_path)) {
tex_db.merge_textures(texture_merge_path);
}
auto replacements_path = file_util::get_jak_project_dir() / "custom_assets" /
game_version_names[config.game_version] / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);
}
if (config.process_game_count) {
auto result = db.process_game_count_file();
if (!result.empty()) {
file_util::write_text_file(out_folder / "assets" / "game_count.txt", result);
}
}
if (config.levels_extract) {
auto level_out_path =
file_util::get_jak_project_dir() / "out" / game_version_names[config.game_version] / "fr3";
file_util::create_dir_if_needed(level_out_path);
extract_all_levels(db, tex_db, config.levels_to_extract, "GAME.CGO", config, level_out_path);
}
mem_log("After extraction: {} MB", get_peak_rss() / (1024 * 1024));
if (!config.audio_dir_file_name.empty()) {
auto streaming_audio_in = in_folder / "VAG";
auto streaming_audio_out = out_folder / "assets" / "streaming_audio";
file_util::create_dir_if_needed(streaming_audio_out);
process_streamed_audio(config, streaming_audio_out, in_folder,
config.streamed_audio_file_names);
}
lg::info("Decompiler has finished successfully in {:.2f} seconds.", decomp_timer.getSeconds());
return 0;
return run_decompilation_process(config, in_folder, out_folder, false);
}
-1
View File
@@ -2576,7 +2576,6 @@ void CallOp::propagate_types2(types2::Instruction& instr,
if (can_use_call_parent) {
out_types[Register(Reg::GPR, Reg::V0)]->type = TP_Type::make_from_ts(call_parent_result_type);
lg::print("used special {}\n", call_parent_result_type.print());
use_normal_last_arg = false;
}
}
+24
View File
@@ -201,6 +201,7 @@ set(RUNTIME_SOURCE
mips2c/jak3_functions/sky.cpp
mips2c/jak3_functions/texture.cpp
mips2c/jak3_functions/particle_curves.cpp
mips2c/jak3_functions/cloth.cpp
mips2c/jak3_functions/collide_cache.cpp
mips2c/jak3_functions/collide_hash.cpp
mips2c/jak3_functions/collide_edge_grab.cpp
@@ -254,6 +255,29 @@ set(RUNTIME_SOURCE
overlord/jak2/streamlfo.cpp
overlord/jak2/streamlist.cpp
overlord/jak2/vag.cpp
overlord/jak3/overlord.cpp
overlord/jak3/pagemanager.cpp
overlord/jak3/iso_cd.cpp
overlord/jak3/dma.cpp
overlord/jak3/iso.cpp
overlord/jak3/iso_queue.cpp
overlord/jak3/srpc.cpp
overlord/jak3/vag.cpp
overlord/jak3/ssound.cpp
overlord/jak3/iso_api.cpp
overlord/jak3/spustreams.cpp
overlord/jak3/list.cpp
overlord/jak3/vblank_handler.cpp
overlord/jak3/dvd_driver.cpp
overlord/jak3/basefile.cpp
overlord/jak3/basefilesystem.cpp
overlord/jak3/ramdisk.cpp
overlord/jak3/isocommon.cpp
overlord/jak3/init.cpp
overlord/jak3/stream.cpp
overlord/jak3/sbank.cpp
overlord/jak3/soundcommon.cpp
overlord/jak3/streamlist.cpp
runtime.cpp
sce/deci2.cpp
sce/iop.cpp
+7
View File
@@ -54,4 +54,11 @@
:lines "game/assets/jak2/subtitle/subtitle_lines_en-GB.json"
:meta "game/assets/jak2/subtitle/subtitle_meta_en-GB.json"
:lines-base "game/assets/jak2/subtitle/subtitle_lines_en-US.json"
:meta-base "game/assets/jak2/subtitle/subtitle_meta_en-US.json")
(file-json
:language-id 9
:text-version "jak2"
:lines "game/assets/jak2/subtitle/subtitle_lines_fi-FI.json"
:meta "game/assets/jak2/subtitle/subtitle_meta_fi-FI.json"
:lines-base "game/assets/jak2/subtitle/subtitle_lines_en-US.json"
:meta-base "game/assets/jak2/subtitle/subtitle_meta_en-US.json"))
+2 -1
View File
@@ -21,7 +21,8 @@
(file-json 7 jak2 "common" '("game/assets/jak2/text/game_custom_text_en-GB.json"))
;; custom languages
(file-json 8 jak2 "common" '("game/assets/jak2/text/game_custom_text_pt-PT.json"))
(file-json 9 jak2 "common" '("game/assets/jak2/text/game_custom_text_fi-FI.json"))
(file-json 9 jak2 "common" '("game/assets/jak2/text/game_custom_text_fi-FI.json"
"game/assets/jak2/text/game_base_text_fi-FI.json"))
(file-json 10 jak2 "common" '("game/assets/jak2/text/game_custom_text_sv-SE.json"))
(file-json 11 jak2 "common" '("game/assets/jak2/text/game_custom_text_da-DK.json"))
(file-json 12 jak2 "common" '("game/assets/jak2/text/game_custom_text_no-NO.json"))
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,6 +1,7 @@
{
"1a3": "138",
"1b5": "161",
"133a": "1113",
"1200": "1031",
"1201": "1032",
"1202": "1034",
@@ -0,0 +1,531 @@
{
"0100": "Lopeta",
"0101": "Tauko~",
"0102": "Tekstityksen kieli",
"0103": "Ääniformaatti",
"0104": "Mono",
"0105": "Stereo",
"0106": "Surround",
"0107": "Äänitehosteet",
"0108": "Musiikki",
"0109": "Puhe",
"010a": "Kieli",
"010b": "Värinätoiminto",
"010c": "Vinkit",
"010d": "Keskitä ruutu",
"010e": "Päällä",
"010f": "Pois",
"0110": "Käytä suuntanäppäimiä",
"0111": "<FLAG_USA> English",
"0112": "<FLAG_FRANCE> Fran,cais",
"0113": "<FLAG_GERMAN> Deutsch",
"0114": "<FLAG_SPAIN> Español",
"0115": "<FLAG_ITALIAN> Italiano",
"0116": "<FLAG_KOREA> ~Y~Z<K32e>~Z<K31a>~Z<K3c8>~Y~Z<K35e>~Z<K36b>~Z<K3de>~Y~Z<K30f>~Z<K31d>",
"0117": "<FLAG_JAPAN> にほんご",
"0118": "Kuvasuhde",
"0119": "Progressiivinen skannaus",
"011a": "Videotila",
"011b": "Peliasetukset",
"011c": "Grafiikan asetukset",
"011d": "Ääniasetukset",
"011e": "4x3",
"011f": "16x9",
"0120": "60Hz",
"0121": "50Hz",
"0122": "Jak II",
"0123": "Poistu demosta",
"0124": "Kyllä",
"0125": "Ei",
"0126": "Takaisin",
"0127": "OK",
"0128": "Seuraava",
"0129": "Edellinen",
"012a": "Jatka tallentamatta",
"012b": "Valitse tallennuspaikka",
"012c": "Valitse ladattava tallennus",
"012d": "Lataa peli",
"012e": "Tallenna peli",
"012f": "Tyhjä",
"0130": "Asetukset",
"0131": "Uusi peli",
"0132": "Paina START-näppäintä",
"0133": "Lopeta peli",
"0134": "Kartta",
"0135": "Valitse aloitus",
"0136": "Ennätykset",
"0137": "1. sija",
"0138": "2. sija",
"0139": "3. sija",
"013a": "4. sija",
"013b": "5. sija",
"013c": "6. sija",
"013d": "7. sija",
"013e": "8. sija",
"013f": "NYFE-leijuri",
"0140": "Luokka 1",
"0141": "Luokka 2",
"0142": "Luokka 3",
"0143": "Harjoitusrata",
"0144": "Haulikko",
"0145": "Läjäytin",
"0146": "Vulkanus-piippu",
"0147": "Rauhantekijä",
"0148": "Oninin haaste",
"0149": "Metallipää-mäiskintä",
"014a": "JET-lauta-haaste",
"014b": "Oninin teltta",
"014c": "Sikahevon saluuna",
"014d": "Stadion",
"014e": "Luokka 1 - käänteinen",
"014f": "Luokka 2 - käänteinen",
"0150": "Luokka 3 - käänteinen",
"0151": "Sataman kisa",
"0152": "Kaupungin kisa",
"0153": "Salaisuudet",
"0154": "Avattu",
"0155": "Poista Jakin pukinparta",
"0156": "Käänteinen maailma",
"0157": "Loputtomat ammukset",
"0158": "Haavoittumattomuus",
"0159": "Sankaritila",
"015a": "Välinäytösten 1. näytös",
"015b": "Välinäytösten 2. näytös",
"015c": "Välinäytösten 3. näytös",
"015d": "Leikekirja",
"015e": "Mega-leikekirja",
"015f": "Leikekirja 3",
"0160": "Tehtävän valinta",
"0161": "Loputon Raivo-Jak",
"0162": "Vulkanus-tykin harjoitusrata",
"0163": "Rauhantekijän harjoitusrata",
"0164": "Käänteiset kisat",
"0165": "Isopäinen Jak",
"0166": "Pienipäinen Jak",
"0167": "Saatavilla",
"0168": "Kerätty",
"0169": "Tehtävät",
"016a": "Valitse esialoitus",
"016b": "Valitse kioski-aloitus",
"016c": "Valitse kohtaus",
"016d": "Tekstitys",
"016e": "Aloita uudelleen",
"016f": "<ICON_MISSION_TODO>",
"0170": "<ICON_MISSION_COMPLETE>",
"0171": "Ei mitään",
"0172": "Peli",
"0173": "Aloita/lopeta",
"0174": "Osta",
"0175": "Voitto",
"0176": "Häviö",
"0177": "Kokonaisaika",
"0178": "Kierros ",
"0179": "Palauta painamalla <PAD_SQUARE>",
"017a": "Kiireinen",
"017b": "Jatka painamalla <PAD_X>",
"017c": "____~%Suoritetut tehtävät",
"017d": "Suorittamattomat tehtävät",
"017e": "Yritä uudelleen?",
"017f": "Salaisuus saatavilla päävalikosta",
"0180": "<PAD_X> = Kyllä, <PAD_TRIANGLE> = Ei",
"0181": "Paina <PAD_TRIANGLE> puhuaksesi.",
"0182": "Paina <PAD_TRIANGLE> käyttääksesi.",
"0183": "Paina <PAD_TRIANGLE> matkustaaksesi.",
"0184": "Valitse taso suuntanäppäimellä",
"0185": "Paina <PAD_TRIANGLE> poistuaksesi.",
"0186": "Paina <PAD_TRIANGLE> pelataksesi.",
"0187": "Halutako pelata uudelleen?",
"0188": "Tehtävä suoritettu",
"0189": "Tehtävä epäonnistui",
"018a": "Yritä uudelleen?",
"018b": "Ruutu ottaa nyt käyttöön 60Hz-tilan",
"018c": "Ruutu ottaa nyt käyttöön progressiivisen skannauksen",
"018d": "Jos kuva näkyy virheellisenä, televisiosi ei tue tätä tilaa",
"018e": "Jos niin käy, odota 10 sekuntia, niin ruutu palautuu takaisin",
"018f": "Ruutu on nyt 60Hz-tilassa",
"0190": "Ruutu on nyt Progresiivinen skannaus -tilassa",
"0191": "Haluatko pitää tämän tilan käytössä?",
"0192": "Levy poistettiin",
"0193": "Syötä Jak II -levy sisään, jotta voit jatkaa pelaamista",
"0194": "Virhe tietojen lukemisessa",
"0195": "Tarkista Jak II -levysi ja yritä uudelleen",
"0196": "Haluatko varmasti lopettaa?",
"0197": "Haluatko aloittaa pelin?",
"0198": "Ei tarpeeksi tilaa muistikortilla Memory__Card__(PS2) paikassa Memory__Card__Slot__~D",
"0199": "Ei Memory__Card__(PS2) liitettynä paikassa Memory__Card__slot__~D",
"019a": "Memory__Card__(PS2) paikassa Memory__Card__slot__~D on alustamaton",
"019b": "Jak II vaatii ~D Kt vapaata tilaa",
"019c": "Syötä Jak II -pelitietoja sisältävä Memory__Card__(PS2) paikkaan Memory__Card__slot__~D",
"019d": "Syötä Memory__Card__(PS2) jossa on tarpeeksi tilaa, muuten pelitietojasi ei voida tallentaa",
"019e": "Ilman alustamista pelitietoja ei voida tallentaa",
"019f": "Tallennetaan tietoja",
"01a0": "Ladataan tietoja",
"01a1": "Alustetaan",
"01a2": "Luodaan tallennustiedostoa",
"01a3": "Älä poista Memory__Card__(PS2) paikassa Memory__Card__slot__~D tai sammuta laitettasi",
"01a4": "Jak II -tallennus on jo olemassa valitsemassasi tiedostossa",
"01a5": "Haluatko korvata tämän?",
"01a6": "Alusta?",
"01a7": "Jatka?",
"01a8": "Takaisin?",
"01a9": "Virhe ladattaessa",
"01aa": "virhe tallentaessa",
"01ab": "Virhe alustaessa",
"01ac": "Virhe luodessa tallennustiedostoa",
"01ad": "Tarkista Memory__Card__(PS2) paikassa Memory__Card__slot__~D",
"01ae": "Tarkista Memory__Card__(PS2) paikassa Memory__Card__slot__~D ja yritä uudelleen",
"01af": "Memory__Card__(PS2) paikasta Memory__Card__slot__~D poistettiin",
"01b0": "Automaattinen tallennus on poistettu käytöstä",
"01b1": "Tallenna pelisi manuaalisesti, niin automaattinen tallennus palautetaan käyttöön",
"01b2": "Jak II -tallennustietoja ei löytynyt kortilta Memory__Card__(PS2) paikassa Memory__Card__slot__~D",
"01b3": "Haluatko luoda uuden Jak II -tallennuksen?",
"01b4": "Kun oheinen kuvake ilmestyy, edistykesi tallennetaan",
"01b5": "Kun tämä kuvake on ruudulla, älä irrota Memory__Card__(PS2) tai sammuta laitettasi",
"01b6": "Pakene <COLOR_WHITE>linnoituksesta",
"01b7": "Suojele Koria ja lasta",
"01b8": "Nouda lippu <COLOR_WHITE>aavekaupungista",
"01b9": "Etsi <COLOR_WHITE>pumppaamon<COLOR_PROGRESS> venttiili",
"01ba": "Räjäytä ammukset <COLOR_WHITE>linnoituksessa",
"01bb": "Kuljeta toimitus <COLOR_WHITE>Sikahevon saluunaan",
"01bc": "Läpäise haulikon <COLOR_WHITE>harjoitusrata",
"01bd": "Suojele Sigiä <COLOR_WHITE>pumppaamolla",
"01be": "Tuhoa tykit <COLOR_WHITE>viemärissä",
"01bf": "Etsi <COLOR_WHITE>läjäytin<COLOR_PROGRESS>-modi",
"01c0": "Pelasta Vin <COLOR_WHITE>avolouhoksella",
"01c1": "Voita aika <COLOR_WHITE>kisatalliin",
"01c2": "Läpäise läjäyttimen <COLOR_WHITE>harjoitusrata",
"01c3": "Tuhoa munat <COLOR_WHITE>poralautalla",
"01c4": "Etsi <COLOR_WHITE>pumppaamon<COLOR_PROGRESS> partio",
"01c5": "Nouda rahat Krewille",
"01c6": "Voita JET-lauta-haaste <COLOR_WHITE>stadionilla",
"01c7": "Etsi Linssi <COLOR_WHITE>vuoristotemppelissä",
"01c8": "Etsi Siru <COLOR_WHITE>vuoristotemppelissä",
"01c9": "Etsi Ratas <COLOR_WHITE>vuoristotemppelissä",
"01ca": "Käynnistä 5 virtakytkintä",
"01cb": "Nouse hissillä <COLOR_WHITE>palatsiin",
"01cc": "Päihitä paroni <COLOR_WHITE>palatsissa",
"01cd": "Kuljeta Vastarinnan jäsenet",
"01ce": "Suojele paikkaa <COLOR_WHITE>aavekaupungissa",
"01cf": "Nappaa tarkkailijat <COLOR_WHITE>Havenin metsässä",
"01d0": "Saata lapsi <COLOR_WHITE>voimalaan",
"01d1": "Pelasta vaanijoita Brutterille",
"01d2": "Tuhoa lasti <COLOR_WHITE>satamalla",
"01d3": "Pysäytä tankkeri",
"01d4": "Tuhoa välineistö <COLOR_WHITE>kaivannolla",
"01d5": "Räjäytä ecokaivot <COLOR_WHITE>avolouhoksella",
"01d6": "Tyhjennä <COLOR_WHITE>viemäri<COLOR_PROGRESS> löytääksesi patsaan",
"01d7": "Tuhoa alus <COLOR_WHITE>poralautalla",
"01d8": "Pelasta vaanijat <COLOR_WHITE>kaivannolla",
"01d9": "Tapa Metallipäät <COLOR_WHITE>Havenin metsässä",
"01da": "Voita luokan 3 kisa <COLOR_WHITE>stadionilla",
"01db": "Nouda sinetin pala <COLOR_WHITE>kaivannolla",
"01dc": "Nouda sinetin pala <COLOR_WHITE>vesislummeilla",
"01dd": "Tuhoa 5 Villikissa-leijuria",
"01de": "Voita Oninin haaste",
"01df": "Käytä esineitä <COLOR_WHITE>Ei-kenenkään-kanjonissa",
"01e0": "Kohtaa testit <COLOR_WHITE>Marin haudassa",
"01e1": "Avaa holvin ovi <COLOR_WHITE>Marin haudassa",
"01e2": "Läpäise ensimmäinen <COLOR_WHITE>miehuuden testi",
"01e3": "Läpäise toinen <COLOR_WHITE>miehuuden testi",
"01e4": "Päihitä paroni <COLOR_WHITE>Marin haudassa",
"01e5": "Pelasta ystävät <COLOR_WHITE>linnoituksesta",
"01e6": "Saata miehet <COLOR_WHITE>viemärien<COLOR_PROGRESS> läpi",
"01e7": "Etsi <COLOR_WHITE>Rauhantekijä",
"01e8": "Voita luokan 2 kisa <COLOR_WHITE>stadionilla",
"01e9": "Suojele piilopaikkaa pommiboteilta",
"01ea": "Tutki <COLOR_WHITE>rakennustyömaa",
"01eb": "Kiipeä <COLOR_WHITE>rakennustyömaata",
"01ec": "Voita Erol kisahaasteessa",
"01ed": "Tuhoa munat <COLOR_WHITE>avolouhoksella",
"01ee": "Nouda Elämän siemen <COLOR_WHITE>aavekaupungissa",
"01ef": "Vie Elämän siemen <COLOR_WHITE>Havenin metsään",
"01f0": "Suojele Samosia <COLOR_WHITE>Havenin metsässä",
"01f1": "Tuhoa <COLOR_WHITE>poralautan<COLOR_PROGRESS> torni",
"01f2": "Voita luokan 1 kisa <COLOR_WHITE>stadionilla",
"01f3": "Tutki <COLOR_WHITE>palatsia",
"01f4": "Hanki Marin sydän <COLOR_WHITE>asetehtaalla",
"01f5": "Päihitä Krew <COLOR_WHITE>asetehtaalla",
"01f6": "Voita peli <COLOR_WHITE>Sikahevon saluunassa",
"01f7": "Etsi Sig <COLOR_WHITE>satamanpohjalla",
"01f8": "Saata Sig <COLOR_WHITE>satamanpohjan<COLOR_PROGRESS> läpi",
"01f9": "Puolusta <COLOR_WHITE>stadionia",
"01fa": "Puolusta vaanijapalloa",
"01fb": "Tuhoa tunnelit <COLOR_WHITE>satamanpohjalla",
"01fc": "Taistele tiesi <COLOR_WHITE>pesän muurille",
"01fd": "Löydä Paroni <COLOR_WHITE>rakennustyömaalla",
"01fe": "Tuhoa <COLOR_WHITE>pesän muuri",
"01ff": "Tuhoa Metalli-Kor <COLOR_WHITE>pesällä",
"0200": "Puhu <COLOR_WHITE>Korille",
"0201": "Puhu <COLOR_WHITE>Tornille",
"0202": "Puhu <COLOR_WHITE>Krewille",
"0203": "Puhu <COLOR_WHITE>Oninille",
"0204": "Puhu <COLOR_WHITE>Vinille",
"0205": "Puhu <COLOR_WHITE>Varjolle",
"0206": "Puhu <COLOR_WHITE>Sigille",
"0207": "Puhu <COLOR_WHITE>Mekaanikolle",
"0208": "Puhu <COLOR_WHITE>Keiralle",
"0209": "Puhu <COLOR_WHITE>Brutterille",
"020a": "Tarkista <COLOR_WHITE>basaari",
"020b": "Tarkista <COLOR_WHITE>vesislummit",
"020c": "Mene <COLOR_WHITE>Ei-kenenkään-kanjonille",
"020d": "Mene <COLOR_WHITE>Marin hautaan",
"020e": "Voita <COLOR_WHITE>Metallipää-mäiskintä",
"020f": "Puolusta <COLOR_WHITE>sataman muuria",
"0210": "Tarkista <COLOR_WHITE>rakennustyömaa",
"0211": "Hyökkää <COLOR_WHITE>Metallipäiden pesään",
"0212": "Käy <COLOR_WHITE>Oraakkelin<COLOR_PROGRESS> luona",
"0213": "Haven City",
"0214": "Linnoitus",
"0215": "Laskeutumisalusta",
"0216": "Palatsin katto",
"0217": "Palatsi",
"0218": "Asetehdas",
"0219": "Aavekaupunki",
"021a": "Pumppaamo",
"021b": "Viemäri",
"021c": "Avolouhos",
"021d": "Vuoristotemppeli",
"021e": "Havenin metsä",
"021f": "Poralautta",
"0220": "Marin hauta",
"0221": "Kaivanto",
"0222": "Satamanpohja",
"0223": "Pesä",
"0224": "Hyppää painamalla <PAD_X>",
"0225": "Kieri painamalla <PAD_L1> liikkeessä",
"0226": "Paina <PAD_X> ja sitten <PAD_X> uudelleen ilmassa",
"0227": "Hyökkää painamalla <PAD_SQUARE> tai <PAD_CIRCLE>",
"0228": "Kieri ja paina sitten <PAD_X> syöksyhyppyyn",
"0229": "Hyppää ja paina <PAD_SQUARE> ilmassa",
"022a": "Paina <PAD_L1> ja sitten <PAD_X> korkeaan hyppyyn",
"022b": "Ammu painamalla <PAD_R1>",
"022c": "<PAD_DPAD_UP> laittaa aseen pois",
"022d": "<PAD_DPAD_UP> tai <PAD_R1> tuo aseen esiin",
"022e": "Pelaa haulikon harjoitusrata painamalla <PAD_X>",
"022f": "<PAD_X> = Haulikon harjoitus~%<PAD_SQUARE> = Vulkanus-tykin harjoitus",
"0230": "Vaihda asetta painamalla <PAD_DPAD_DOWN>",
"0231": "Pelaa läjäyttimen harjoitusrata painamalla <PAD_X>",
"0232": "<PAD_X> = Läjäyttimen harjoitus~%<PAD_SQUARE> = Rauhantekijän harjoitus",
"0233": "Potkaise kohdetta ja paina <PAD_R1> tehdäksesi pikatulisarjan",
"0234": "Ammu laatikoita",
"0235": "Tavoite",
"0236": "Kulta",
"0237": "Hopea",
"0238": "Pronssi",
"0239": "Käytä lautaa painamalla <PAD_R2>",
"023a": "Hyppy: Paina <PAD_X>",
"023b": "Kyykkyhyppy: Paina <PAD_L1> ja sitten <PAD_X>",
"023c": "Voimahyppy: Paina <PAD_X> hieman laskeuduttuasi hypystä",
"023d": "Kaideliuku: Paina <PAD_SQUARE> ja <PAD_ANALOG_ANY>",
"023e": "Pyörähdys: Paina <PAD_X> ja sitten <PAD_R1> ja <PAD_ANALOG_LEFT_RIGHT>",
"023f": "Voltti: Paina <PAD_X> ja sitten <PAD_R1> ja <PAD_ANALOG_UP_DOWN>",
"0240": "Temppu: Paina <PAD_X> ja sitten <PAD_L1> ja <PAD_ANALOG_ANY>",
"0241": "Saat paljon pisteitä, jos liu'ut ja teet tempun liukuaksesi uudestaan",
"0242": "Aloita haaste aktivoimalla tuomari",
"0243": "Yritä uudelleen!",
"0244": "Palaa talliin",
"0245": "Tehtävä suoritettu: Palaa Krewin luo",
"0246": "Vaihda leijuvyöhykettä painamalla <PAD_R2>",
"0247": "Sukella painamalla <PAD_CIRCLE> pohjassa uidessasi",
"0248": "<PAD_CIRCLE> = Turbo~%<PAD_R1> tai <PAD_L1> = Hyppy",
"0249": "Iske Titaaniasulla painamalla <PAD_SQUARE>",
"024a": "Tartu Titaaniasulla lohkareisiin painamalla <PAD_R1>",
"024b": "Heitä nostetut esineet painamalla <PAD_SQUARE>",
"024c": "Paina <PAD_X> rampin yläpäässä",
"024d": "Liu'u kaidetta JET-laudalla painamalla <PAD_SQUARE> tai <PAD_CIRCLE>",
"024e": "Käytä <PAD_DPAD_ANY> ja <PAD_X> <PAD_CIRCLE> <PAD_SQUARE> <PAD_TRIANGLE>",
"024f": "Pumppaamo",
"0250": "Avolouhos",
"0251": "Katso traileri",
"0252": "<PAD_R2> mennäksesi laudan päälle tai pois",
"0253": "Käytä pimeää voimaa painamalla <PAD_L2>",
"0254": "Sony Computer Entertainment America~%presents",
"0255": "Sony Computer Entertainment Europe~%presents",
"0256": "Sony Computer Entertainment Korea~%presents",
"0257": "Sony Computer Entertainment Inc.~%presents",
"0258": "A game by",
"0259": "Jak II",
"025a": "Kaksi vuotta myöhemmin...",
"025b": "Viikko myöhemmin...",
"025c": "Asepäivitys hankittu",
"025d": "Haulikko hankittu",
"025e": "Läjäytin-modi mankittu",
"025f": "Vulkanus-piippu hankittu",
"0260": "Rauhantekijä hankittu",
"0261": "Haulikon tulinopeus päivitetty",
"0262": "Aseiden ammuskapasiteetti päivitetty",
"0263": "Aseiden vahinkoa päivitetty",
"0264": "Tehtävä suoritettu",
"0265": "Punainen turvapassi hankittu",
"0266": "Vihreä turvapassi hankittu",
"0267": "Keltainen turvapassi hankittu",
"0268": "Palatsin turvapassi hankittu",
"0269": "Musta turvapassi hankittu",
"026a": "Linssi hankittu",
"026b": "Ratas hankittu",
"026c": "Siru hankittu",
"026d": "Tuo 25 metallipäiden kallohelmeä",
"026e": "Tuo 200 metallipäiden kallohelmeä",
"026f": "Tuo 25 metallipäiden kallohelmeä",
"0270": "Tuo 200 metallipäiden kallohelmeä",
"0271": "Tuo 200 metallipäiden kallohelmeä",
"0272": "Tuo 100 metallipäiden kallohelmeä",
"0273": "Raivopommi: Paina <PAD_X> ja sitten <PAD_SQUARE>",
"0274": "Raivopurkaus: Paina <PAD_SQUARE> ja sitten <PAD_X>",
"0275": "Raivo-Jak on nyt haavoittumaton!",
"0276": "Raivojätti: Paina <PAD_L2> raivotilassa",
"0277": "Ohi",
"0278": "Valitse tapahtuma",
"0279": "Skeittipuisto",
"027a": "Luokan 3 kisa",
"027b": "Luokan 2 kisa",
"027c": "Luokan 1 kisa",
"027d": "Käänteinen luokan 3 kisa",
"027e": "Käänteinen luokan 2 kisa",
"027f": "Käänteinen luokan 1 kisa",
"0280": "Daxter saa suupalan",
"0281": "Tavataan Torn",
"0282": "Noutamassa lippua",
"0283": "Suojele pyhää paikkaa",
"0284": "Meidän maailmamme!",
"0285": "Vanhoja muistoja",
"0286": "Vin tarvitsee apua",
"0287": "Tavataan Vin",
"0288": "Hyviä ja huonoja uutisia",
"0289": "Suuri murskaus",
"028a": "Meillä on yhä ongelmia",
"028b": "Kaivot posahtavat!",
"028c": "Tavataan Kor ja lapsi",
"028d": "Vastarinta",
"028e": "Villikissa-tehtävä",
"028f": "Tornin toimitus",
"0290": "Tavataan Krew ja Sig",
"0291": "Yllätyshyökkäys!",
"0292": "Ashelin on huolissaan",
"0293": "Vin, kamu. Tarvitsemme palveluksen.",
"0294": "Kuka on verhojen takana?",
"0295": "Tiedonjyvä",
"0296": "Iloinen jälleennäkeminen",
"0297": "Kissatappelu",
"0298": "Jak poistuu paikalta",
"0299": "Daxterin suuri voitto",
"029a": "Keira paljastaa suunnitelmansa",
"029b": "Suuri kilpailu",
"029c": "Voittajan piiri",
"029d": "Tavataan Oraakkeli",
"029e": "Jak saa pimeän voiman",
"029f": "Jak saa toisen pimeän voiman",
"02a0": "Jak saa kolmannen pimeän voiman",
"02a1": "Jak saa neljännen pimeän voiman",
"02a2": "Valitus, naiset, ja laulu",
"02a3": "Rahankerääjät",
"02a4": "Mikä tämän lapsen tarina on?",
"02a5": "Krewilla on uusi keikka",
"02a6": "Tavataan Brutter",
"02a7": "Krewin kilpailusopimus",
"02a8": "Mitä te kaksi oikein teitte?",
"02a9": "Oninin haaste",
"02aa": "Marin sinetti on valmis",
"02ab": "Pelasta lisää vaanijoita",
"02ac": "Suojele piilopaikkaa",
"02ad": "Krew uhkailee",
"02ae": "Pelaaja astelee esiin",
"02af": "Saadaan aikakartta",
"02b0": "Brutter pelastaa päivän",
"02b1": "Leijutaan pois",
"02b2": "Saadaan keltainen ase",
"02b3": "Saadaan JET-lauta",
"02b4": "Jak laittaa JET-laudan pois",
"02b5": "Ihka oma Rauhantekijämme!",
"02b6": "Ulosmeno",
"02b7": "Jak matkaa pesään",
"02b8": "Paluu",
"02b9": "Ashelin kuljettaa Jakin",
"02ba": "Pala sinettiä",
"02bb": "Erol inhoaa häviötä",
"02bc": "Torn ja ammusvarasto",
"02bd": "Metallipäitä kaupungissa?",
"02be": "Nyt räjähtää!",
"02bf": "Torn myöntää petoksensa",
"02c0": "Aikakaksoset",
"02c1": "Krewin viemärikeikka",
"02c2": "Mikä on tuo löyhkä?",
"02c3": "Taiteenkeräilijä",
"02c4": "Että kaipaankin housuja!",
"02c5": "Sig paljastaa sielunsa",
"02c6": "Patsaanposauttelua",
"02c7": "Se on ansa!",
"02c8": "Daxter saa suupalan",
"02c9": "Daxter matkustaa putkea",
"02ca": "Työtarjous",
"02cb": "Torn tarjoaa tehtävän",
"02cc": "Tavataan Ashelin",
"02cd": "Daxter tekee siirtonsa",
"02ce": "Tästä tulee hauskaa!",
"02cf": "Boom, beibi!",
"02d0": "Peukut alas",
"02d1": "Heihei",
"02d2": "Temppu",
"02d3": "Hyvää yötä",
"02d4": "Toimit hienosti, tulokas",
"02d5": "Vin tahtoo munakokkelia",
"02d6": "Kor on huolissaan",
"02d7": "Poika on kadoksissa",
"02d8": "Ohjaustorni räjähtää",
"02d9": "Tavataan Onin ja Pecker",
"02da": "Vekotin romahtaa",
"02db": "Hyvät fiilikset",
"02dc": "Daxter kärventyy",
"02dd": "Salatapaaminen",
"02de": "Paroni kohtaa Jakin",
"02df": "Minä tuhoan sinut!",
"02e0": "Takaisin mistä aloitimme",
"02e1": "Salaisuus pommin rakentamiseen",
"02e2": "Krewin kaunotar",
"02e3": "Oi voi...",
"02e4": "Lentoon",
"02e5": "Laskeutumisalusta",
"02e6": "Jak löytää Marin haudan!",
"02e7": "tomb-open-door-res",
"02e8": "tomb-open-door-2-res",
"02e9": "Haudan ovet",
"02ea": "Ensimmäinen säde",
"02eb": "Toinen säde",
"02ec": "Ovet avautuvat",
"02ed": "Edeltäjäkivi!",
"02ee": "Paroni varastaa show'n",
"02ef": "Daxter ojentaa auttavan kätensä",
"02f0": "Daxterin karvainen takaa-ajo",
"02f1": "Tavataan Varjo",
"02f2": "Daxterin pöhkötarina",
"02f3": "Pecker haastaa riitaa",
"02f4": "Samos ja siemen",
"02f5": "Näky",
"02f6": "Kor ja lapsi",
"02f7": "Pelasta lisää vaanijoita",
"02f8": "Marin haudan legenda",
"02f9": "Se on kirous, eikö vain?",
"02fa": "Pora romahtaa",
"02fb": "Valotorni nousee",
"02fc": "Sinetti avaa portin",
"02fd": "Sig on ongelmissa",
"02fe": "Juokse!",
"02ff": "Sigin vahva käsi",
"0300": "Sieltä se taas tulee!",
"0301": "Sigin viimeinen hetki",
"0302": "Kivi... ase... pesä!",
"0303": "Jak matkaa pesään",
"0304": "Poistutaan pesästä",
"0305": "Kor hyppää esiin",
"0306": "Etkö tunnista häntä?",
"0307": "Outo uusi maailma",
"0308": "Juhlinta",
"0309": "<ICON_MISSION_COMPLETE>",
"030a": "<ICON_MISSION_TODO>",
"030b": "<FLAG_UK> English",
"030c": "Ota tekstitys käyttöön painamalla <PAD_SQUARE>",
"030d": "Tekstitys käytössä",
"030e": "Tekstitys ei käytössä",
"030f": "JET-lauta",
"0310": "Jatka"
}
@@ -232,5 +232,6 @@
"1336": "Fast Progress Menu",
"1337": "PS2 LOD Distance",
"1338": "Off",
"1339": "Display"
"1339": "Display",
"133a": "Suomi"
}
@@ -5,7 +5,7 @@
"1101": "Pelataan bonustehtävää",
"1102": "Haulikon harjoitusrata",
"1103": "Läjäyttimen harjoitusrata",
"1104": "Vulkanusraivon harjoitusrata",
"1104": "Vulkanus-tykin harjoitusrata",
"1105": "Rauhantekijän harjoitusrata",
"1106": "Oninin haaste",
"1107": "Metallipää-mäiskintä",
@@ -18,8 +18,8 @@
"1206": "4x3 (PS2)",
"1207": "16x9 (PS2)",
"1208": "Valitse leveys- ja korkeussuhde",
"1209": "Paina <PAD_X> vahvistaaksesi ja poistuaksesi.",
"120a": "Paina <PAD_CIRCLE> vahvistaaksesi ja poistuaksesi.",
"1209": "Vahvista ja poistu painamalla <PAD_X>.",
"120a": "Vahvista ja poistu painamalla <PAD_CIRCLE>.",
"120b": "Kuvasuhde ei saa olla pienempi kuin 4x3!",
"120c": "Musiikkisoitin",
"120d": "Pystytahdistus",
@@ -34,7 +34,7 @@
"1216": "Muuntoase",
"1217": "JET-lauta",
"1218": "Titaaniasu",
"1219": "Pimeä Jak",
"1219": "Raivo-Jak",
"121a": "Ajoneuvo",
"121b": "Vaara",
"121c": "Ei mikään",
@@ -85,10 +85,10 @@
"124a": "Ohjaimen LED-asetukset",
"124b": "Näytä pelaajan tila",
"124c": "Näytä terveyden määrä",
"124d": "Lopeta auto-tallennus",
"124e": "Auto-tallennus pois päältä",
"124d": "Lopeta autom. tallennus",
"124e": "Autom. tallennus pois",
"124f": "Haluatko varmasti lopettaa automaattisen tallentamisen?",
"1250": "Turbo JET-lauta Haven Cityssä",
"1250": "Turbo-JET-lauta Haven Cityssä",
"1251": "Vihollisten terveyspalkit",
"1252": "Ajoneuvojen terveyspalkit",
"1253": "Ajoneuvojen haavoittumattomuus",
@@ -96,13 +96,13 @@
"1255": "Kerää kerättävät automaattisesti",
"1256": "Musiikkisoitin",
"1257": "Tekstuuriton tila",
"1258": "Nopeat välianimaatiot",
"1259": "Hitaat välianimaatiot",
"1258": "Nopeat välinäytökset",
"1259": "Hitaat välinäytökset",
"125a": "Nopea pelattavuus",
"125b": "Hidas pelattavuus",
"125c": "Pikamatkustus Haven Cityssä",
"125d": "Edeltäjähelmien seuranta",
"125e": "Todellinen vuorokauden aika",
"125e": "Todellinen vuorokaudenaika",
"125f": "Tyyni Haven City",
"1260": "Näytä JET-laudan temput",
"1261": "Huono sää",
@@ -112,14 +112,14 @@
"1265": "Käännä kaikki 3 venttiiliä ja löydä Marin patsas tehtävässä \"~S\" alle ~D sekunnissa",
"1266": "Vähennä Haven Cityn asukaslukua ~D kappaleella",
"1267": "Vähennä Haven Cityn ajoneuvojen määrää ~D kappaleella",
"1268": "Metsästä jokaista Metallipäälajia",
"1268": "Metsästä jokaista metallipää-lajia",
"1269": "Käytä JET-lautaa rikkoaksesi säiliöt auki",
"126a": "Siirrä repeämäkuljetin jättäen Samos ja nuori Samos vaurioitta",
"1280": "Kuvakulma-asetukset",
"1281": "Vasen/oikea (ensimmäinen persoona)",
"1282": "Ylös/alas (ensimmäinen persoona)",
"1283": "Vasen/oikea (kolmas persoona)",
"1284": "Ylös/alas (kolmas persoona)",
"1281": "Vasen/oikea (1. persoona)",
"1282": "Ylös/alas (1. persoona)",
"1283": "Vasen/oikea (3. persoona)",
"1284": "Ylös/alas (3. persoona)",
"1285": "Palauta oletukset",
"1286": "Normaali",
"1287": "Käänteinen",
@@ -137,15 +137,15 @@
"1293": "Ohjainasetukset",
"1294": "Valitse ohjain",
"1295": "Analogisauvan katvealue",
"1296": "Älä huomioi, kun ikkuna ei aktiivinen",
"1296": "Älä huomioi työpöydällä",
"1297": "Ohjaimen LED terveydelle",
"1298": "Ohjaimen LED muihin tiloihin",
"1299": "Salli näppäimistö",
"129a": "Salli hiiri",
"129b": "Hiiriasetukset",
"129c": "Kameran ohjaus hiirellä",
"129d": "Vaakasuuntainen herkkyys",
"129e": "Pystysuuntainen herkkyys",
"129d": "Herkkyys (vaakasuunta)",
"129e": "Herkkyys (pystysuunta)",
"129f": "Pelaajan ohjaus hiirellä",
"12a0": "Objektien varjot",
"12a1": "Normaali",
@@ -156,25 +156,25 @@
"12a6": "Muut tilastot",
"12a7": "Tappoja yhteensä",
"12a8": "Jakin tappamia",
"12a9": "Pimeän Jakin tappamia",
"12a9": "Raivo-Jakin tappamia",
"12aa": "Daxterin tappamia",
"12ab": "Muiden tappamia",
"12ac": "Läjäytin",
"12ad": "Haulikko",
"12ae": "Vulkanusraivo",
"12ae": "Vulkanus-tykki",
"12af": "Rauhantekijä",
"12b0": "JET-lauta",
"12b1": "JET-lautatemppu",
"12b1": "JET-lauta-temppu",
"12b2": "Titaaniasun isku",
"12b3": "Titaaniasun runko",
"12b4": "Tykki",
"12b5": "Isku",
"12b6": "Lyyhistyi",
"12b6": "Maaisku",
"12b7": "Kohokoukku",
"12b8": "Pyörähdys",
"12b9": "Kierintä",
"12bf": "Pimeä pommi",
"12c0": "Pimeä purkaus",
"12bf": "Raivopommi",
"12c0": "Raivopurkaus",
"12c3": "Karmiinivartija",
"12c4": "Sig",
"12c5": "Ashelin",
@@ -208,24 +208,24 @@
"1315": "Tämä asetus on erittäin kokeellinen. Kun peliä ei pelata 60 Hz:n kuvataajuudella, visuaalisia sekä pelattavuuden ongelmia voi ilmaantua sen seurauksena.",
"1316": "Paikallinen tulos",
"1320": "Ei mitään",
"1321": "Spin",
"1322": "Buusti",
"1321": "Pyörähdys",
"1322": "Nopeuslisä",
"1323": "Voltti",
"1324": "Kaideliuku",
"1325": "Kaidehyppy",
"1326": "Nosegrab",
"1327": "Method",
"1328": "Board Spin",
"1329": "Board Flip",
"1328": "Lautapyörähdys",
"1329": "Lautavoltti",
"132a": "Noseflip",
"132b": "Kickflip",
"132c": "Hyppy",
"132d": "Kyykkyhyppy",
"132e": "Pikahyppy",
"132f": "Pimeä Jak",
"1330": "Pimeä pommi",
"1331": "Pimeä purkaus",
"1332": "Pimeä jätti",
"132f": "Raivo-Jak",
"1330": "Raivopommi",
"1331": "Raivopurkaus",
"1332": "Raivojätti",
"1333": "PS2-asetukset",
"1334": "Objektien vähennys",
"1335": "Pakota ympäristökartoitus",
+9 -4
View File
@@ -484,7 +484,7 @@
03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -873,6 +873,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:MacOSX
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
@@ -1080,7 +1081,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b10,start:b7,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -1090,6 +1091,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -1388,6 +1390,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b00000b050000,Microsoft Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b000001050000,Microsoft Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,platform:Linux,
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1465,7 +1468,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1687,6 +1690,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050082795e040000e002000003090000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1694,7 +1698,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b000009050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b000015050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000001050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000005050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-16
View File
@@ -31,19 +31,3 @@ struct RPC_Dgo_Cmd {
// a buffer.
uint8_t pad[32];
};
namespace jak3 {
struct RPC_Dgo_Cmd {
uint16_t rsvd;
uint16_t result;
uint32_t buffer1;
uint32_t buffer2;
uint32_t buffer_heap_top;
char name[16];
uint16_t cgo_id;
uint8_t pad[30];
};
static_assert(sizeof(RPC_Dgo_Cmd) == 0x40);
} // namespace jak3
static_assert(sizeof(RPC_Dgo_Cmd) == sizeof(jak3::RPC_Dgo_Cmd));
@@ -3,6 +3,10 @@
#include "fmt/core.h"
#include "third-party/imgui/imgui.h"
std::string BucketRenderer::name() const {
return m_name;
}
std::string BucketRenderer::name_and_id() const {
return fmt::format("[{:2d}] {}", (int)m_my_id, m_name);
}
@@ -26,8 +26,8 @@ class EyeRenderer;
struct SharedRenderState {
explicit SharedRenderState(std::shared_ptr<TexturePool> _texture_pool,
std::shared_ptr<Loader> _loader,
GameVersion version)
: shaders(version), texture_pool(_texture_pool), loader(_loader) {}
GameVersion _version)
: shaders(_version), texture_pool(_texture_pool), loader(_loader), version(_version) {}
ShaderLibrary shaders;
std::shared_ptr<TexturePool> texture_pool;
std::shared_ptr<Loader> loader;
@@ -98,6 +98,7 @@ class BucketRenderer {
virtual void render(DmaFollower& dma,
SharedRenderState* render_state,
ScopedProfilerNode& prof) = 0;
std::string name() const;
std::string name_and_id() const;
virtual ~BucketRenderer() = default;
bool& enabled() { return m_enabled; }
@@ -158,4 +159,4 @@ class PrintRenderer : public BucketRenderer {
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
bool empty() const override { return true; }
void draw_debug_window() override {}
};
};
@@ -579,6 +579,7 @@ u32 get_direct_qwc_or_nop(const VifCode& code) {
return code.immediate;
}
default:
printf("expected direct, got %s\n", code.print().c_str());
ASSERT(false);
}
}
+27 -7
View File
@@ -186,7 +186,7 @@ EyeRenderer::SpriteInfo decode_sprite(const DmaTransfer& dma) {
memcpy(&result.a, dma.data + 16 + 12, 1); // a
// uv0
memcpy(&result.uv0[0], &dma.data[32], 8);
memcpy(&result.uv0, &dma.data[32], 8);
// xyz0
memcpy(&result.xyz0[0], &dma.data[48], 12);
@@ -236,8 +236,11 @@ std::vector<EyeRenderer::SingleEyeDraws> EyeRenderer::get_draws(DmaFollower& dma
bool using_64 = false;
{
auto draw0 = read_eye_draw(dma);
ASSERT(draw0.sprite.uv0[0] == 0);
ASSERT(draw0.sprite.uv0[1] == 0);
// ASSERT(draw0.sprite.uv0[0] == 0);
// ASSERT(draw0.sprite.uv0[1] == 0);
// printf("hashed name is 0x%x 0x%x\n", draw0.sprite.uv0[0], draw0.sprite.uv0[1]);
l_draw.fnv_name_hash = draw0.sprite.uv0;
r_draw.fnv_name_hash = draw0.sprite.uv0;
ASSERT(draw0.sprite.uv1[0] == 0);
ASSERT(draw0.sprite.uv1[1] == 0);
if (draw0.scissor.y1 - draw0.scissor.y0 == 63) {
@@ -509,7 +512,9 @@ void EyeRenderer::run_gpu(const std::vector<SingleEyeDraws>& draws,
buffer_idx = 0;
for (size_t draw_idx = 0; draw_idx < draws.size(); draw_idx++) {
const auto& draw = draws[draw_idx];
const auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
auto& out_tex = m_gpu_eye_textures[draw.tex_slot()];
out_tex.fnv_name_hash = draw.fnv_name_hash;
out_tex.lr = draw.lr;
// first, the clear
float clear[4] = {0, 0, 0, 0};
@@ -574,15 +579,30 @@ std::optional<u64> EyeRenderer::lookup_eye_texture(u8 eye_id) {
}
}
std::optional<u64> EyeRenderer::lookup_eye_texture_hash(u64 hash, bool lr) {
for (auto& slot : m_gpu_eye_textures) {
if (slot.fnv_name_hash == hash && slot.lr == lr) {
auto* gpu_tex = slot.gpu_tex;
if (gpu_tex) {
return gpu_tex->gpu_textures.at(0).gl;
} else {
fmt::print("lookup eye failed for {} (1)\n", hash);
return {};
}
}
}
fmt::print("lookup eye failed for {} (2)\n", hash);
return {};
}
//////////////////////
// DMA Decode
//////////////////////
std::string EyeRenderer::SpriteInfo::print() const {
std::string result;
result +=
fmt::format("a: {:x} uv: ({}, {}), ({}, {}) xyz: ({}, {}, {}), ({}, {}, {})", a, uv0[0],
uv0[1], uv1[0], uv1[1], xyz0[0], xyz0[1], xyz0[2], xyz1[0], xyz1[1], xyz1[2]);
result += fmt::format("a: {:x} uv: ({}), ({}, {}) xyz: ({}, {}, {}), ({}, {}, {})", a, uv0,
uv1[0], uv1[1], xyz0[0], xyz0[1], xyz0[2], xyz1[0], xyz1[1], xyz1[2]);
return result;
}
+5 -1
View File
@@ -22,10 +22,11 @@ class EyeRenderer : public BucketRenderer {
void handle_eye_dma2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
std::optional<u64> lookup_eye_texture(u8 eye_id);
std::optional<u64> lookup_eye_texture_hash(u64 hash, bool lr);
struct SpriteInfo {
u8 a;
u32 uv0[2];
u64 uv0; // stores hashed name of merc-ctrl that reads this eye.
u32 uv1[2];
u32 xyz0[3];
u32 xyz1[3];
@@ -53,6 +54,8 @@ class EyeRenderer : public BucketRenderer {
GpuTexture* gpu_tex = nullptr;
u32 tbp;
FramebufferTexturePair fb;
u64 fnv_name_hash = 0;
bool lr = false;
// note: eye texture increased to 128x128 (originally 32x32) here.
GpuEyeTex() : fb(128, 128, GL_UNSIGNED_INT_8_8_8_8_REV) {}
@@ -65,6 +68,7 @@ class EyeRenderer : public BucketRenderer {
GLuint m_gl_vertex_buffer;
struct SingleEyeDraws {
u64 fnv_name_hash = 0;
int lr;
int pair;
bool using_64 = false;
@@ -28,6 +28,7 @@
#include "game/graphics/pipelines/opengl.h"
#include "third-party/imgui/imgui.h"
#include "third-party/imgui/imgui_stdlib.h"
// for the vif callback
#include "game/kernel/common/kmachine.h"
@@ -36,6 +37,7 @@
#ifdef _WIN32
#include <Windows.h>
#endif
#include "common/util/string_util.h"
namespace {
std::string g_current_renderer;
@@ -84,7 +86,11 @@ OpenGLRenderer::OpenGLRenderer(std::shared_ptr<TexturePool> texture_pool,
&gl_error_ignores_api_other[0], GL_FALSE);
#endif
lg::debug("OpenGL context information: {}", (const char*)glGetString(GL_VERSION));
lg::info("OpenGL context version: {}", (const char*)glGetString(GL_VERSION));
lg::info("OpenGL context renderer: {}", (const char*)glGetString(GL_RENDERER));
lg::info("OpenGL context vendor: {}", (const char*)glGetString(GL_VENDOR));
lg::info("OpenGL context shading language version: {}",
(const char*)glGetString(GL_SHADING_LANGUAGE_VERSION));
const tfrag3::Level* common_level = nullptr;
{
@@ -263,6 +269,11 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC_L0_PRIS, BucketId::GMERC_L1_PRIS, i), m_generic2,
Generic2::Mode::NORMAL);
init_bucket_renderer<Generic2BucketRenderer>(
fmt::format("gmerc2-l{}-pris", i), BucketCategory::GENERIC,
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_PRIS, BucketId::GMERC2_L1_PRIS, i), m_generic2,
Generic2::Mode::PRIM);
init_bucket_renderer<Merc2BucketRenderer>(
fmt::format("merc-l{}-pris2", i), BucketCategory::MERC,
GET_BUCKET_ID_FOR_LIST(BucketId::MERC_L0_PRIS2, BucketId::MERC_L1_PRIS2, i), m_merc2);
@@ -270,6 +281,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
fmt::format("gmerc-l{}-pris2", i), BucketCategory::GENERIC,
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC_L0_PRIS2, BucketId::GMERC_L1_PRIS2, i), m_generic2,
Generic2::Mode::NORMAL);
init_bucket_renderer<Generic2BucketRenderer>(
fmt::format("gmerc2-l{}-pris2", i), BucketCategory::GENERIC,
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_PRIS2, BucketId::GMERC2_L1_PRIS2, i),
m_generic2, Generic2::Mode::PRIM);
}
// 401
@@ -281,6 +296,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
BucketId::GMERC_LCOM_PRIS, m_generic2,
Generic2::Mode::NORMAL);
init_bucket_renderer<Generic2BucketRenderer>("gmerc2-lcom-pris", BucketCategory::GENERIC,
BucketId::GMERC2_LCOM_PRIS, m_generic2,
Generic2::Mode::PRIM);
// 461
init_bucket_renderer<TextureUploadHandler>("tex-lcom-sky-post", BucketCategory::TEX,
BucketId::TEX_LCOM_SKY_POST, m_texture_animator);
@@ -306,6 +325,10 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
fmt::format("tfrag-l{}-water", i), BucketCategory::TFRAG,
GET_BUCKET_ID_FOR_LIST(BucketId::TFRAG_L0_WATER, BucketId::TFRAG_L1_WATER, i),
std::vector{tfrag3::TFragmentTreeKind::WATER}, false, i, anim_slot_array());
init_bucket_renderer<Generic2BucketRenderer>(
fmt::format("gmerc2-l{}-water", i), BucketCategory::GENERIC,
GET_BUCKET_ID_FOR_LIST(BucketId::GMERC2_L0_WATER, BucketId::GMERC2_L1_WATER, i),
m_generic2, Generic2::Mode::PRIM);
}
// 563
@@ -313,11 +336,20 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
BucketId::TEX_LCOM_WATER, m_texture_animator);
init_bucket_renderer<Merc2BucketRenderer>("merc-lcom-water", BucketCategory::MERC,
BucketId::MERC_LCOM_WATER, m_merc2);
init_bucket_renderer<Generic2BucketRenderer>("generic2-lcom-water", BucketCategory::GENERIC,
BucketId::GMERC2_LCOM_WATER, m_generic2,
Generic2::Mode::PRIM);
// 568
init_bucket_renderer<TextureUploadHandler>("tex-sprite", BucketCategory::TEX,
BucketId::TEX_SPRITE, m_texture_animator);
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-1", BucketCategory::GENERIC,
BucketId::GENERIC_SPRITE_1, m_generic2,
Generic2::Mode::PRIM);
init_bucket_renderer<Sprite3>("particles", BucketCategory::SPRITE, BucketId::PARTICLES);
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-2", BucketCategory::GENERIC,
BucketId::GENERIC_SPRITE_2, m_generic2,
Generic2::Mode::PRIM);
init_bucket_renderer<Generic2BucketRenderer>("generic-sprite-3", BucketCategory::OTHER,
BucketId::GENERIC_SPRITE_3, m_generic2,
Generic2::Mode::LIGHTNING);
@@ -1078,8 +1110,13 @@ void OpenGLRenderer::draw_renderer_selection_window() {
ImGui::TreePop();
}
ImGui::InputText("Renderer Filter", &m_renderer_filter);
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
auto renderer = m_bucket_renderers[i].get();
if (!m_renderer_filter.empty() && !str_util::contains(renderer->name(), m_renderer_filter)) {
continue;
}
if (renderer && !renderer->empty()) {
ImGui::PushID(i);
if (ImGui::TreeNode(renderer->name_and_id().c_str())) {
@@ -123,6 +123,7 @@ class OpenGLRenderer {
float m_last_pmode_alp = 1.;
bool m_enable_fast_blackout_loads = true;
std::string m_renderer_filter = "";
struct FboState {
struct {
+612 -126
View File
@@ -60,23 +60,48 @@
* A simple list of preallocated textures by size. If a texture needs to be resized, it's faster
* to swap to a different OpenGL texture from this pool than glTexImage2D with a different size.
*/
OpenGLTexturePool::OpenGLTexturePool() {
OpenGLTexturePool::OpenGLTexturePool(GameVersion version) {
struct Alloc {
u64 w, h, n;
};
// list of sizes to preallocate: {width, height, count}.
for (const auto& a : std::vector<Alloc>{{4, 4, 2},
{4, 64, 2},
{16, 16, 5},
{32, 16, 1},
{32, 32, 10},
{32, 64, 1},
{64, 32, 6},
{64, 64, 30},
{64, 128, 4},
{128, 128, 10},
{256, 1, 2},
{256, 256, 7}}) {
PerGameVersion<std::vector<Alloc>> tex_allocs{{{4, 4, 2},
{4, 64, 2},
{16, 16, 5},
{32, 16, 1},
{32, 32, 10},
{32, 64, 1},
{64, 32, 6},
{64, 64, 30},
{64, 128, 4},
{128, 128, 10},
{256, 1, 2},
{256, 256, 7}},
{{4, 4, 2},
{4, 64, 2},
{16, 16, 5},
{32, 16, 1},
{32, 32, 10},
{32, 64, 1},
{64, 32, 6},
{64, 64, 30},
{64, 128, 4},
{128, 128, 10},
{256, 1, 2},
{256, 256, 7}},
{{4, 4, 3},
{4, 64, 6},
{16, 16, 5},
{32, 16, 1},
{32, 32, 20},
{32, 64, 1},
{64, 32, 15},
{64, 64, 85},
{64, 128, 4},
{128, 128, 185},
{256, 1, 2},
{256, 256, 7}}};
for (const auto& a : tex_allocs[version]) {
auto& l = textures[(a.w << 32) | a.h];
l.resize(a.n);
glGenTextures(a.n, l.data());
@@ -370,6 +395,7 @@ TextureAnimator::TextureAnimator(ShaderLibrary& shaders,
const tfrag3::Level* common_level,
GameVersion version)
: m_common_level(common_level),
m_opengl_texture_pool(version),
m_psm32_to_psm8_8_8(8, 8, 8, 64),
m_psm32_to_psm8_16_16(16, 16, 16, 64),
m_psm32_to_psm8_32_32(32, 32, 16, 64),
@@ -420,6 +446,7 @@ TextureAnimator::TextureAnimator(ShaderLibrary& shaders,
m_shader_id = shader.id();
m_uniforms.rgba = glGetUniformLocation(shader.id(), "rgba");
m_uniforms.enable_tex = glGetUniformLocation(shader.id(), "enable_tex");
m_uniforms.set_alpha = glGetUniformLocation(shader.id(), "set_alpha");
m_uniforms.positions = glGetUniformLocation(shader.id(), "positions");
m_uniforms.uvs = glGetUniformLocation(shader.id(), "uvs");
m_uniforms.channel_scramble = glGetUniformLocation(shader.id(), "channel_scramble");
@@ -642,7 +669,7 @@ GLuint TextureAnimator::get_by_slot(int idx) {
}
// IDs sent from GOAL telling us what texture operation to perform.
enum PcTextureAnimCodes {
enum class PcTextureAnimCodesJak2 : u16 {
FINISH_ARRAY = 13,
ERASE_DEST_TEXTURE = 14,
UPLOAD_CLUT_16_16 = 15,
@@ -673,6 +700,361 @@ enum PcTextureAnimCodes {
CLOUDS_HIRES = 43,
};
struct FixedAnimInfoJak2 {
PcTextureAnimCodesJak2 code = (PcTextureAnimCodesJak2)0;
std::string name;
int anim_array_idx = -1;
};
FixedAnimInfoJak2 anim_code_to_info(PcTextureAnimCodesJak2 code, const TextureAnimator& animator) {
ASSERT(code > (PcTextureAnimCodesJak2)0);
FixedAnimInfoJak2 anim;
anim.code = code;
switch (code) {
case PcTextureAnimCodesJak2::SKULL_GEM: {
anim.name = "skull-gem";
anim.anim_array_idx = animator.m_skull_gem_fixed_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::BOMB: {
anim.name = "bomb";
anim.anim_array_idx = animator.m_bomb_fixed_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::CAS_CONVEYOR: {
anim.name = "cas-conveyor";
anim.anim_array_idx = animator.m_cas_conveyor_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::SECURITY: {
anim.name = "security";
anim.anim_array_idx = animator.m_security_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::WATERFALL: {
anim.name = "waterfall";
anim.anim_array_idx = animator.m_waterfall_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::WATERFALL_B: {
anim.name = "waterfall-b";
anim.anim_array_idx = animator.m_waterfall_b_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::LAVA: {
anim.name = "lava";
anim.anim_array_idx = animator.m_lava_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::LAVA_B: {
anim.name = "lava-b";
anim.anim_array_idx = animator.m_lava_b_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::STADIUMB: {
anim.name = "stadiumb";
anim.anim_array_idx = animator.m_stadiumb_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::FORTRESS_PRIS: {
anim.name = "fort-pris";
anim.anim_array_idx = animator.m_fortress_pris_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::FORTRESS_WARP: {
anim.name = "fort-warp";
anim.anim_array_idx = animator.m_fortress_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::METKOR: {
anim.name = "metkor";
anim.anim_array_idx = animator.m_metkor_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::SHIELD: {
anim.name = "shield";
anim.anim_array_idx = animator.m_shield_anim_array_idx;
} break;
case PcTextureAnimCodesJak2::KREW_HOLO: {
anim.name = "krew-holo";
anim.anim_array_idx = animator.m_krew_holo_anim_array_idx;
} break;
default:
anim.name = "unknown";
lg::error("Unknown texture anim code {}", (int)code);
}
return anim;
}
enum class PcTextureAnimCodesJak3 : u16 {
FINISH_ARRAY = 13,
ERASE_DEST_TEXTURE = 14,
UPLOAD_CLUT_16_16 = 15,
GENERIC_UPLOAD = 16,
SET_SHADER = 17,
DRAW = 18,
DARKJAK = 22,
DARKJAK_HIGHRES = 23,
SKULL_GEM = 27,
DEFAULT_WATER = 28,
DEFAULT_WARP = 29,
TEMPLEA_WATER = 30,
TEMPLEA_WARP = 31,
TEMPLEB_WARP = 32,
TEMPLEC_WATER = 33,
SEWC_WATER = 34,
SEWD_WATER = 35,
SEWE_WATER = 36,
SEWG_WATER = 37,
SEWH_WATER = 38,
SEWI_WATER = 39,
SEWJ_WATER = 40,
SEWL_WATER = 41,
SEWM_WATER = 42,
SEWN_WATER = 43,
DESRESC_WARP = 44,
CTYSLUMB_WATER = 45,
NSTB_QUICKSAND = 46,
CTYSLUMC_WATER = 47,
FACTORYC_ALPHA = 48,
HFRAG = 49,
HANGA_SPRITE = 50,
HANGA_WATER = 51,
DESERTD_WATER = 52,
LMHCITYB_TFRAG = 53,
TOWERB_WATER = 54,
COMB_FIELD = 55,
WASSTADA_ALPHA = 56,
FACTORYB_WATER = 57,
LMHCITYA_TFRAG = 58,
MHCITYA_PRIS = 59,
RUBBLEA_WATER = 60,
RUBBLEA2_WATER = 61,
RUBBLEB_WATER = 62,
RUBBLEC_WATER = 63,
FORESTA_WATER = 64,
FORESTB_WATER = 65,
LFORPLNT_PRIS = 66,
LTNFXHIP = 67,
LGUNNORM_WATER = 68,
LJKDXVIN = 69,
SECURITY = 70,
WASPAL_WATER = 71,
MINED_TFRAG = 72,
VOLCANOX_WARP = 73,
TEMPLEX_WATER = 74,
VOLCANOA_WATER = 75,
DESHOVER = 76,
CLOUDS_AND_FOG = 77,
CLOUDS_HIRES = 78,
};
struct FixedAnimInfoJak3 {
PcTextureAnimCodesJak3 code = (PcTextureAnimCodesJak3)0;
std::string name;
int anim_array_idx = -1;
};
FixedAnimInfoJak3 anim_code_to_info(PcTextureAnimCodesJak3 code, const TextureAnimator& animator) {
ASSERT(code > (PcTextureAnimCodesJak3)0);
FixedAnimInfoJak3 anim;
anim.code = code;
switch (code) {
case PcTextureAnimCodesJak3::SKULL_GEM: {
anim.name = "skull-gem";
anim.anim_array_idx = animator.m_skull_gem_fixed_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::DEFAULT_WATER: {
anim.name = "default-water";
anim.anim_array_idx = animator.m_default_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::DEFAULT_WARP: {
anim.name = "default-warp";
anim.anim_array_idx = animator.m_default_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TEMPLEA_WATER: {
anim.name = "templea-water";
anim.anim_array_idx = animator.m_templea_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TEMPLEA_WARP: {
anim.name = "templea-warp";
anim.anim_array_idx = animator.m_templea_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TEMPLEB_WARP: {
anim.name = "templeb-warp";
anim.anim_array_idx = animator.m_templeb_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TEMPLEC_WATER: {
anim.name = "templec-water";
anim.anim_array_idx = animator.m_templec_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWC_WATER: {
anim.name = "sewc-water";
anim.anim_array_idx = animator.m_sewc_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWD_WATER: {
anim.name = "sewd-water";
anim.anim_array_idx = animator.m_sewd_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWE_WATER: {
anim.name = "sewe-water";
anim.anim_array_idx = animator.m_sewe_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWG_WATER: {
anim.name = "sewg-water";
anim.anim_array_idx = animator.m_sewg_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWH_WATER: {
anim.name = "sewh-water";
anim.anim_array_idx = animator.m_sewh_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWI_WATER: {
anim.name = "sewi-water";
anim.anim_array_idx = animator.m_sewi_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWJ_WATER: {
anim.name = "sewj-water";
anim.anim_array_idx = animator.m_sewj_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWL_WATER: {
anim.name = "sewl-water";
anim.anim_array_idx = animator.m_sewl_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWM_WATER: {
anim.name = "sewm-water";
anim.anim_array_idx = animator.m_sewm_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SEWN_WATER: {
anim.name = "sewn-water";
anim.anim_array_idx = animator.m_sewn_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::DESRESC_WARP: {
anim.name = "desresc-warp";
anim.anim_array_idx = animator.m_desresc_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::CTYSLUMB_WATER: {
anim.name = "ctyslumb-water";
anim.anim_array_idx = animator.m_ctyslumb_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::NSTB_QUICKSAND: {
anim.name = "nstb-quicksand";
anim.anim_array_idx = animator.m_nstb_quicksand_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::CTYSLUMC_WATER: {
anim.name = "ctyslumc-water";
anim.anim_array_idx = animator.m_ctyslumc_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::FACTORYC_ALPHA: {
anim.name = "factoryc-alpha";
anim.anim_array_idx = animator.m_factoryc_alpha_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::HFRAG: {
anim.name = "hfrag";
anim.anim_array_idx = animator.m_hfrag_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::HANGA_SPRITE: {
anim.name = "hanga-sprite";
anim.anim_array_idx = animator.m_hanga_sprite_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::HANGA_WATER: {
anim.name = "hanga-water";
anim.anim_array_idx = animator.m_hanga_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::DESERTD_WATER: {
anim.name = "desertd-water";
anim.anim_array_idx = animator.m_desertd_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LMHCITYB_TFRAG: {
anim.name = "lmhcityb-tfrag";
anim.anim_array_idx = animator.m_lmhcityb_tfrag_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TOWERB_WATER: {
anim.name = "towerb-water";
anim.anim_array_idx = animator.m_towerb_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::COMB_FIELD: {
anim.name = "comb-field";
anim.anim_array_idx = animator.m_comb_field_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::WASSTADA_ALPHA: {
anim.name = "wasstada-alpha";
anim.anim_array_idx = animator.m_wasstada_alpha_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::FACTORYB_WATER: {
anim.name = "factoryb-water";
anim.anim_array_idx = animator.m_factoryb_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LMHCITYA_TFRAG: {
anim.name = "lmhcitya-tfrag";
anim.anim_array_idx = animator.m_lmhcitya_tfrag_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::MHCITYA_PRIS: {
anim.name = "mhcitya-pris";
anim.anim_array_idx = animator.m_mhcitya_pris_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::RUBBLEA_WATER: {
anim.name = "rubblea-water";
anim.anim_array_idx = animator.m_rubblea_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::RUBBLEA2_WATER: {
anim.name = "rubblea2-water";
anim.anim_array_idx = animator.m_rubblea2_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::RUBBLEB_WATER: {
anim.name = "rubbleb-water";
anim.anim_array_idx = animator.m_rubbleb_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::RUBBLEC_WATER: {
anim.name = "rubblec-water";
anim.anim_array_idx = animator.m_rubblec_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::FORESTA_WATER: {
anim.name = "foresta-water";
anim.anim_array_idx = animator.m_foresta_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::FORESTB_WATER: {
anim.name = "forestb-water";
anim.anim_array_idx = animator.m_forestb_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LFORPLNT_PRIS: {
anim.name = "lforplnt-pris";
anim.anim_array_idx = animator.m_lforplnt_pris_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LTNFXHIP: {
anim.name = "ltnfxhip";
anim.anim_array_idx = animator.m_ltnfxhip_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LGUNNORM_WATER: {
anim.name = "lgunnorm-water";
anim.anim_array_idx = animator.m_lgunnorm_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::LJKDXVIN: {
anim.name = "ljkdxvin";
anim.anim_array_idx = animator.m_ljkdxvin_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::SECURITY: {
anim.name = "security";
anim.anim_array_idx = animator.m_security_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::WASPAL_WATER: {
anim.name = "waspal-water";
anim.anim_array_idx = animator.m_waspal_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::MINED_TFRAG: {
anim.name = "mined-tfrag";
anim.anim_array_idx = animator.m_mined_tfrag_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::VOLCANOX_WARP: {
anim.name = "volcanox-warp";
anim.anim_array_idx = animator.m_volcanox_warp_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::TEMPLEX_WATER: {
anim.name = "templex-water";
anim.anim_array_idx = animator.m_templex_water_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::VOLCANOA_WATER: {
anim.name = "volcanoa-water";
anim.anim_array_idx = animator.m_volcanoa_anim_array_idx;
} break;
case PcTextureAnimCodesJak3::DESHOVER: {
anim.name = "deshover";
anim.anim_array_idx = animator.m_deshover_anim_array_idx;
} break;
default:
anim.name = "unknown";
lg::error("Unknown texture anim code {}", (int)code);
}
return anim;
}
// metadata for an upload from GOAL memory
struct TextureAnimPcUpload {
u32 data; // goal pointer
@@ -726,117 +1108,191 @@ void TextureAnimator::handle_texture_anim_data(DmaFollower& dma,
auto tf = dma.read_and_advance();
auto vif0 = tf.vifcode0();
if (vif0.kind == VifCode::Kind::PC_PORT) {
switch (vif0.immediate) {
case UPLOAD_CLUT_16_16: {
auto p = scoped_prof("clut-16-16");
handle_upload_clut_16_16(tf, ee_mem);
} break;
case ERASE_DEST_TEXTURE: {
auto p = scoped_prof("erase");
handle_erase_dest(dma);
} break;
case GENERIC_UPLOAD: {
auto p = scoped_prof("generic-upload");
handle_generic_upload(tf, ee_mem);
} break;
case SET_SHADER: {
auto p = scoped_prof("set-shader");
handle_set_shader(dma);
} break;
case DRAW: {
auto p = scoped_prof("draw");
handle_draw(dma, *texture_pool);
} break;
case FINISH_ARRAY:
done = true;
switch (this->m_version) {
case GameVersion::Jak2:
switch (static_cast<PcTextureAnimCodesJak2>(vif0.immediate)) {
case PcTextureAnimCodesJak2::UPLOAD_CLUT_16_16: {
auto p = scoped_prof("clut-16-16");
handle_upload_clut_16_16(tf, ee_mem);
} break;
case PcTextureAnimCodesJak2::ERASE_DEST_TEXTURE: {
auto p = scoped_prof("erase");
handle_erase_dest(dma);
} break;
case PcTextureAnimCodesJak2::GENERIC_UPLOAD: {
auto p = scoped_prof("generic-upload");
handle_generic_upload(tf, ee_mem);
} break;
case PcTextureAnimCodesJak2::SET_SHADER: {
auto p = scoped_prof("set-shader");
handle_set_shader(dma);
} break;
case PcTextureAnimCodesJak2::DRAW: {
auto p = scoped_prof("draw");
handle_draw(dma, *texture_pool);
} break;
case PcTextureAnimCodesJak2::FINISH_ARRAY:
done = true;
break;
case PcTextureAnimCodesJak2::DARKJAK: {
auto p = scoped_prof("darkjak");
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak2::PRISON_JAK: {
auto p = scoped_prof("prisonjak");
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak2::ORACLE_JAK: {
auto p = scoped_prof("oraclejak");
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak2::NEST_JAK: {
auto p = scoped_prof("nestjak");
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak2::KOR_TRANSFORM: {
auto p = scoped_prof("kor");
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak2::SKULL_GEM:
case PcTextureAnimCodesJak2::BOMB:
case PcTextureAnimCodesJak2::CAS_CONVEYOR:
case PcTextureAnimCodesJak2::SECURITY:
case PcTextureAnimCodesJak2::WATERFALL:
case PcTextureAnimCodesJak2::WATERFALL_B:
case PcTextureAnimCodesJak2::LAVA:
case PcTextureAnimCodesJak2::LAVA_B:
case PcTextureAnimCodesJak2::STADIUMB:
case PcTextureAnimCodesJak2::FORTRESS_PRIS:
case PcTextureAnimCodesJak2::FORTRESS_WARP:
case PcTextureAnimCodesJak2::METKOR:
case PcTextureAnimCodesJak2::SHIELD:
case PcTextureAnimCodesJak2::KREW_HOLO: {
auto anim =
anim_code_to_info(static_cast<PcTextureAnimCodesJak2>(vif0.immediate), *this);
auto p = scoped_prof(anim.name.c_str());
run_fixed_animation_array(anim.anim_array_idx, tf, texture_pool);
break;
}
case PcTextureAnimCodesJak2::CLOUDS_AND_FOG:
case PcTextureAnimCodesJak2::CLOUDS_HIRES: {
auto p = scoped_prof("clouds-and-fog");
handle_clouds_and_fog(tf, texture_pool,
vif0.immediate == (u16)PcTextureAnimCodesJak2::CLOUDS_HIRES);
} break;
case PcTextureAnimCodesJak2::SLIME: {
auto p = scoped_prof("slime");
handle_slime(tf, texture_pool);
break;
}
default:
lg::print("bad imm: {}\n", vif0.immediate);
ASSERT_NOT_REACHED();
}
break;
case GameVersion::Jak3:
switch (static_cast<PcTextureAnimCodesJak3>(vif0.immediate)) {
case PcTextureAnimCodesJak3::UPLOAD_CLUT_16_16: {
auto p = scoped_prof("clut-16-16");
handle_upload_clut_16_16(tf, ee_mem);
} break;
case PcTextureAnimCodesJak3::ERASE_DEST_TEXTURE: {
auto p = scoped_prof("erase");
handle_erase_dest(dma);
} break;
case PcTextureAnimCodesJak3::GENERIC_UPLOAD: {
auto p = scoped_prof("generic-upload");
handle_generic_upload(tf, ee_mem);
} break;
case PcTextureAnimCodesJak3::SET_SHADER: {
auto p = scoped_prof("set-shader");
handle_set_shader(dma);
} break;
case PcTextureAnimCodesJak3::DRAW: {
auto p = scoped_prof("draw");
handle_draw(dma, *texture_pool);
} break;
case PcTextureAnimCodesJak3::FINISH_ARRAY:
done = true;
break;
case PcTextureAnimCodesJak3::DARKJAK: {
auto p = scoped_prof("darkjak");
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak3::DARKJAK_HIGHRES: {
auto p = scoped_prof("darkjak-highres");
run_clut_blender_group(tf, m_darkjak_highres_clut_blender_idx, frame_idx);
} break;
case PcTextureAnimCodesJak3::SKULL_GEM:
case PcTextureAnimCodesJak3::DEFAULT_WATER:
case PcTextureAnimCodesJak3::DEFAULT_WARP:
case PcTextureAnimCodesJak3::TEMPLEA_WATER:
case PcTextureAnimCodesJak3::TEMPLEA_WARP:
case PcTextureAnimCodesJak3::TEMPLEB_WARP:
case PcTextureAnimCodesJak3::TEMPLEC_WATER:
case PcTextureAnimCodesJak3::SEWC_WATER:
case PcTextureAnimCodesJak3::SEWD_WATER:
case PcTextureAnimCodesJak3::SEWE_WATER:
case PcTextureAnimCodesJak3::SEWG_WATER:
case PcTextureAnimCodesJak3::SEWH_WATER:
case PcTextureAnimCodesJak3::SEWI_WATER:
case PcTextureAnimCodesJak3::SEWJ_WATER:
case PcTextureAnimCodesJak3::SEWL_WATER:
case PcTextureAnimCodesJak3::SEWM_WATER:
case PcTextureAnimCodesJak3::SEWN_WATER:
case PcTextureAnimCodesJak3::DESRESC_WARP:
case PcTextureAnimCodesJak3::CTYSLUMB_WATER:
case PcTextureAnimCodesJak3::NSTB_QUICKSAND:
case PcTextureAnimCodesJak3::CTYSLUMC_WATER:
case PcTextureAnimCodesJak3::FACTORYC_ALPHA:
case PcTextureAnimCodesJak3::HFRAG:
case PcTextureAnimCodesJak3::HANGA_SPRITE:
case PcTextureAnimCodesJak3::HANGA_WATER:
case PcTextureAnimCodesJak3::DESERTD_WATER:
case PcTextureAnimCodesJak3::LMHCITYB_TFRAG:
case PcTextureAnimCodesJak3::TOWERB_WATER:
case PcTextureAnimCodesJak3::COMB_FIELD:
case PcTextureAnimCodesJak3::WASSTADA_ALPHA:
case PcTextureAnimCodesJak3::FACTORYB_WATER:
case PcTextureAnimCodesJak3::LMHCITYA_TFRAG:
case PcTextureAnimCodesJak3::MHCITYA_PRIS:
case PcTextureAnimCodesJak3::RUBBLEA_WATER:
case PcTextureAnimCodesJak3::RUBBLEA2_WATER:
case PcTextureAnimCodesJak3::RUBBLEB_WATER:
case PcTextureAnimCodesJak3::RUBBLEC_WATER:
case PcTextureAnimCodesJak3::FORESTA_WATER:
case PcTextureAnimCodesJak3::FORESTB_WATER:
case PcTextureAnimCodesJak3::LFORPLNT_PRIS:
case PcTextureAnimCodesJak3::LTNFXHIP:
case PcTextureAnimCodesJak3::LGUNNORM_WATER:
case PcTextureAnimCodesJak3::LJKDXVIN:
case PcTextureAnimCodesJak3::SECURITY:
case PcTextureAnimCodesJak3::WASPAL_WATER:
case PcTextureAnimCodesJak3::MINED_TFRAG:
case PcTextureAnimCodesJak3::VOLCANOX_WARP:
case PcTextureAnimCodesJak3::TEMPLEX_WATER:
case PcTextureAnimCodesJak3::VOLCANOA_WATER:
case PcTextureAnimCodesJak3::DESHOVER: {
auto anim =
anim_code_to_info(static_cast<PcTextureAnimCodesJak3>(vif0.immediate), *this);
auto p = scoped_prof(anim.name.c_str());
run_fixed_animation_array(anim.anim_array_idx, tf, texture_pool);
break;
}
case PcTextureAnimCodesJak3::CLOUDS_AND_FOG:
case PcTextureAnimCodesJak3::CLOUDS_HIRES: {
auto p = scoped_prof("clouds-and-fog");
handle_clouds_and_fog(tf, texture_pool,
vif0.immediate == (u16)PcTextureAnimCodesJak3::CLOUDS_HIRES);
break;
}
default:
lg::print("bad imm: {}\n", vif0.immediate);
ASSERT_NOT_REACHED();
}
break;
case DARKJAK: {
auto p = scoped_prof("darkjak");
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
} break;
case PRISON_JAK: {
auto p = scoped_prof("prisonjak");
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx, frame_idx);
} break;
case ORACLE_JAK: {
auto p = scoped_prof("oraclejak");
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx, frame_idx);
} break;
case NEST_JAK: {
auto p = scoped_prof("nestjak");
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx, frame_idx);
} break;
case KOR_TRANSFORM: {
auto p = scoped_prof("kor");
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx, frame_idx);
} break;
case SKULL_GEM: {
auto p = scoped_prof("skull-gem");
run_fixed_animation_array(m_skull_gem_fixed_anim_array_idx, tf, texture_pool);
} break;
case BOMB: {
auto p = scoped_prof("bomb");
run_fixed_animation_array(m_bomb_fixed_anim_array_idx, tf, texture_pool);
} break;
case CAS_CONVEYOR: {
auto p = scoped_prof("cas-conveyor");
run_fixed_animation_array(m_cas_conveyor_anim_array_idx, tf, texture_pool);
} break;
case SECURITY: {
auto p = scoped_prof("security");
run_fixed_animation_array(m_security_anim_array_idx, tf, texture_pool);
} break;
case WATERFALL: {
auto p = scoped_prof("waterfall");
run_fixed_animation_array(m_waterfall_anim_array_idx, tf, texture_pool);
} break;
case WATERFALL_B: {
auto p = scoped_prof("waterfall-b");
run_fixed_animation_array(m_waterfall_b_anim_array_idx, tf, texture_pool);
} break;
case LAVA: {
auto p = scoped_prof("lava");
run_fixed_animation_array(m_lava_anim_array_idx, tf, texture_pool);
} break;
case LAVA_B: {
auto p = scoped_prof("lava-b");
run_fixed_animation_array(m_lava_b_anim_array_idx, tf, texture_pool);
} break;
case STADIUMB: {
auto p = scoped_prof("stadiumb");
run_fixed_animation_array(m_stadiumb_anim_array_idx, tf, texture_pool);
} break;
case FORTRESS_PRIS: {
auto p = scoped_prof("fort-pris");
run_fixed_animation_array(m_fortress_pris_anim_array_idx, tf, texture_pool);
} break;
case FORTRESS_WARP: {
auto p = scoped_prof("fort-warp");
run_fixed_animation_array(m_fortress_warp_anim_array_idx, tf, texture_pool);
} break;
case METKOR: {
auto p = scoped_prof("metkor");
run_fixed_animation_array(m_metkor_anim_array_idx, tf, texture_pool);
} break;
case SHIELD: {
auto p = scoped_prof("shield");
run_fixed_animation_array(m_shield_anim_array_idx, tf, texture_pool);
} break;
case KREW_HOLO: {
auto p = scoped_prof("krew-holo");
run_fixed_animation_array(m_krew_holo_anim_array_idx, tf, texture_pool);
} break;
case CLOUDS_AND_FOG:
case CLOUDS_HIRES: {
auto p = scoped_prof("clouds-and-fog");
handle_clouds_and_fog(tf, texture_pool, vif0.immediate == CLOUDS_HIRES);
} break;
case SLIME: {
auto p = scoped_prof("slime");
handle_slime(tf, texture_pool);
} break;
default:
lg::print("bad imm: {}\n", vif0.immediate);
lg::print("unsupported game version {}\n", (int)this->m_version);
ASSERT_NOT_REACHED();
}
} else {
@@ -1818,6 +2274,21 @@ void TextureAnimator::set_up_opengl_for_fixed(const FixedLayerDef& def,
blend_c == GsAlpha::BlendMode::SOURCE && blend_d == GsAlpha::BlendMode::DEST) {
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
} else if (blend_a == GsAlpha::BlendMode::SOURCE &&
blend_b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
blend_c == GsAlpha::BlendMode::ZERO_OR_FIXED &&
blend_d == GsAlpha::BlendMode::ZERO_OR_FIXED && def.blend_fix == 128) {
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
} else if (blend_a == GsAlpha::BlendMode::SOURCE &&
blend_b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
blend_c == GsAlpha::BlendMode::ZERO_OR_FIXED &&
blend_d == GsAlpha::BlendMode::DEST) {
// 0, 2, 2, 1
// (Cs - 0) * FIX / 128 + Cd
// So source is fix / 128, and dest is 1
float color = (float)def.blend_fix / 128.f;
glBlendColor(color, color, color, color);
glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE, GL_ONE, GL_ZERO);
} else {
lg::print("unhandled blend: {} {} {} {}\n", (int)blend_a, (int)blend_b, (int)blend_c,
(int)blend_d);
@@ -1958,14 +2429,23 @@ void TextureAnimator::set_draw_data_from_interpolated(DrawData* result,
const LayerVals& vals,
int w,
int h) {
ASSERT(vals.rot == 0);
result->color = (vals.color * 128.f).cast<u32>();
math::Vector2f pos_scale(vals.scale.x() * w, vals.scale.y() * h);
math::Vector2f pos_offset(2048.f + (vals.offset.x() * w), 2048.f + (vals.offset.y() * h));
math::Vector2f st_scale = vals.st_scale;
math::Vector2f st_offset = vals.st_offset;
const math::Vector2f corners[4] = {math::Vector2f{-0.5, -0.5}, math::Vector2f{0.5, -0.5},
math::Vector2f{-0.5, 0.5}, math::Vector2f{0.5, 0.5}};
math::Vector2f corners[4] = {math::Vector2f{-0.5, -0.5}, math::Vector2f{0.5, -0.5},
math::Vector2f{-0.5, 0.5}, math::Vector2f{0.5, 0.5}};
if (vals.rot) {
const float rotation_radians = 2.f * M_PI * vals.rot / 65536.f;
const float sine = std::sin(rotation_radians);
const float cosine = std::cos(rotation_radians);
math::Vector2f vx(sine, cosine);
math::Vector2f vy(cosine, -sine);
for (auto& corner : corners) {
corner = vx * corner.x() + vy * corner.y();
}
}
math::Vector2f sts[4];
math::Vector2<u32> poss[4];
@@ -2056,8 +2536,14 @@ void TextureAnimator::run_fixed_animation(FixedAnim& anim, float time) {
if (true) { // todo
glColorMask(true, true, true, false);
glUniform1f(m_uniforms.alpha_multiply, 2.f);
glUniform1i(m_uniforms.set_alpha, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glColorMask(false, false, false, true);
if (anim.def.set_alpha) {
glUniform1i(m_uniforms.set_alpha, 1);
glUniform4f(m_uniforms.rgba, draw_data.color.x(), draw_data.color.x(),
draw_data.color.x(), 128.f);
}
glUniform1f(m_uniforms.alpha_multiply, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} else {
@@ -59,7 +59,7 @@ struct ShaderContext {
};
struct OpenGLTexturePool {
OpenGLTexturePool();
OpenGLTexturePool(GameVersion version);
~OpenGLTexturePool();
GLuint allocate(u64 w, u64 h);
void free(GLuint texture, u64 w, u64 h);
@@ -148,6 +148,18 @@ struct FixedLayerDef {
GsAlpha::BlendMode blend_modes[4]; // abcd
u8 blend_fix = 0;
void set_blend(GsAlpha::BlendMode a,
GsAlpha::BlendMode b,
GsAlpha::BlendMode c,
GsAlpha::BlendMode d,
u8 fix) {
blend_modes[0] = a;
blend_modes[1] = b;
blend_modes[2] = c;
blend_modes[3] = d;
blend_fix = fix;
}
void set_blend_b2_d1() {
blend_modes[0] = GsAlpha::BlendMode::SOURCE;
blend_modes[1] = GsAlpha::BlendMode::ZERO_OR_FIXED;
@@ -181,6 +193,15 @@ struct FixedAnimDef {
// alpha blend off, so alpha doesn't matter i think.
std::vector<FixedLayerDef> layers;
bool move_to_pool = false;
bool set_alpha = false;
void set_times(std::vector<std::pair<float, float>> times) {
ASSERT(layers.size() >= times.size());
for (size_t i = 0; i < layers.size(); i++) {
auto& layer = layers.at(i);
layer.start_time = times.at(i).first;
layer.end_time = times.at(i).second;
}
}
};
struct DynamicLayerData {
@@ -343,6 +364,7 @@ class TextureAnimator {
GLuint tcc;
GLuint alpha_multiply;
GLuint minimum, maximum;
GLuint set_alpha;
} m_uniforms;
struct {
@@ -396,6 +418,8 @@ class TextureAnimator {
m_psm32_to_psm8_64_64;
ClutReader m_clut_table;
public:
// jak 2
int m_skull_gem_fixed_anim_array_idx = -1;
int m_bomb_fixed_anim_array_idx = -1;
int m_cas_conveyor_anim_array_idx = -1;
@@ -411,9 +435,59 @@ class TextureAnimator {
int m_shield_anim_array_idx = -1;
int m_krew_holo_anim_array_idx = -1;
// jak 3
int m_default_water_anim_array_idx = -1;
int m_default_warp_anim_array_idx = -1;
int m_templea_water_anim_array_idx = -1;
int m_templea_warp_anim_array_idx = -1;
int m_templeb_warp_anim_array_idx = -1;
int m_templec_water_anim_array_idx = -1;
int m_sewc_water_anim_array_idx = -1;
int m_sewd_water_anim_array_idx = -1;
int m_sewe_water_anim_array_idx = -1;
int m_sewg_water_anim_array_idx = -1;
int m_sewh_water_anim_array_idx = -1;
int m_sewi_water_anim_array_idx = -1;
int m_sewj_water_anim_array_idx = -1;
int m_sewl_water_anim_array_idx = -1;
int m_sewm_water_anim_array_idx = -1;
int m_sewn_water_anim_array_idx = -1;
int m_desresc_warp_anim_array_idx = -1;
int m_ctyslumb_water_anim_array_idx = -1;
int m_nstb_quicksand_anim_array_idx = -1;
int m_ctyslumc_water_anim_array_idx = -1;
int m_factoryc_alpha_anim_array_idx = -1;
int m_hfrag_anim_array_idx = -1;
int m_hanga_sprite_anim_array_idx = -1;
int m_hanga_water_anim_array_idx = -1;
int m_desertd_water_anim_array_idx = -1;
int m_lmhcityb_tfrag_anim_array_idx = -1;
int m_towerb_water_anim_array_idx = -1;
int m_comb_field_anim_array_idx = -1;
int m_wasstada_alpha_anim_array_idx = -1;
int m_factoryb_water_anim_array_idx = -1;
int m_lmhcitya_tfrag_anim_array_idx = -1;
int m_mhcitya_pris_anim_array_idx = -1;
int m_rubblea_water_anim_array_idx = -1;
int m_rubblea2_water_anim_array_idx = -1;
int m_rubbleb_water_anim_array_idx = -1;
int m_rubblec_water_anim_array_idx = -1;
int m_foresta_water_anim_array_idx = -1;
int m_forestb_water_anim_array_idx = -1;
int m_lforplnt_pris_anim_array_idx = -1;
int m_ltnfxhip_anim_array_idx = -1;
int m_lgunnorm_water_anim_array_idx = -1;
int m_ljkdxvin_anim_array_idx = -1;
int m_waspal_water_anim_array_idx = -1;
int m_mined_tfrag_anim_array_idx = -1;
int m_volcanox_warp_anim_array_idx = -1;
int m_templex_water_anim_array_idx = -1;
int m_volcanoa_anim_array_idx = -1;
int m_deshover_anim_array_idx = -1;
int m_darkjak_highres_clut_blender_idx = -1;
std::vector<FixedAnimArray> m_fixed_anim_arrays;
public:
// note: for now these can't be easily changed because each layer has its own hand-tuned
// parameters from the original game. If you want to change it, you'll need to make up parameters
// for those new layers.
File diff suppressed because it is too large. Load diff
@@ -119,3 +119,7 @@ void TextureUploadHandler::draw_debug_window() {
m_direct->draw_debug_window();
}
}
bool TextureUploadHandler::empty() const {
return m_upload_count == 0;
}
@@ -18,6 +18,7 @@ class TextureUploadHandler : public BucketRenderer {
bool add_direct = false);
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void draw_debug_window() override;
bool empty() const override;
private:
struct TextureUpload {
@@ -129,8 +129,8 @@ Hfrag::HfragLevel* Hfrag::get_hfrag_level(const std::string& name,
// first, see if this level is loaded. If not, there's nothing we can do.
auto lev_data = render_state->loader->get_tfrag3_level(name);
if (!lev_data) {
printf("[hfrag] can't display %s because it's not loaded.\n", name.c_str());
render_state->loader->debug_print_loaded_levels();
// printf("[hfrag] can't display %s because it's not loaded.\n", name.c_str());
// render_state->loader->debug_print_loaded_levels();
return nullptr;
}
+20 -5
View File
@@ -1,9 +1,7 @@
#include "debug_gui.h"
#include <algorithm>
#include "common/global_profiler/GlobalProfiler.h"
#include "common/util/string_util.h"
#include "game/graphics/display.h"
#include "game/graphics/gfx.h"
@@ -164,10 +162,27 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
}
if (ImGui::BeginMenu("Event Profiler")) {
if (ImGui::Checkbox("Record", &record_events)) {
if (ImGui::Checkbox("Record Events", &record_events)) {
prof().set_enable(record_events);
}
ImGui::MenuItem("Dump to file", nullptr, &dump_events);
ImGui::SameLine();
ImGui::Text(fmt::format("({}/{})", prof().get_next_idx(), prof().get_max_events()).c_str());
ImGui::InputInt("Event Buffer Size", &max_event_buffer_size);
if (ImGui::Button("Resize")) {
prof().update_event_buffer_size(max_event_buffer_size);
}
if (ImGui::Button("Reset Events")) {
prof().clear();
}
ImGui::Separator();
ImGui::Checkbox("Enable Compression", &prof().m_enable_compression);
if (ImGui::Button("Dump to File")) {
record_events = false;
prof().dump_to_json();
}
// if (ImGui::Button("Open dump folder")) {
// // TODO - https://github.com/mlabbe/nativefiledialog
// }
ImGui::EndMenu();
}
+1 -1
View File
@@ -64,7 +64,7 @@ class OpenGlDebugGui {
bool small_profiler = false;
bool record_events = false;
bool dump_events = false;
int max_event_buffer_size = 65536;
bool want_reboot_in_debug = false;
bool screenshot_hotkey_enabled = true;
@@ -70,11 +70,16 @@ void Generic2::render_in_mode(DmaFollower& dma,
case Mode::LIGHTNING:
process_dma_lightning(dma, render_state->next_bucket);
break;
case Mode::PRIM:
process_dma_prim(dma, render_state->next_bucket);
break;
default:
ASSERT_NOT_REACHED();
}
}
m_empty = m_next_free_vert == 0;
{
// the next pass is to look at all of that data, and figure out the best order to draw it
// using OpenGL
@@ -84,6 +89,7 @@ void Generic2::render_in_mode(DmaFollower& dma,
setup_draws(true, true);
break;
case Mode::LIGHTNING:
case Mode::PRIM:
setup_draws(false, true);
break;
case Mode::WARP:
@@ -11,7 +11,7 @@ class Generic2 {
u32 num_buckets = 800);
~Generic2();
enum class Mode { NORMAL, LIGHTNING, WARP };
enum class Mode { NORMAL, LIGHTNING, WARP, PRIM };
void render_in_mode(DmaFollower& dma,
SharedRenderState* render_state,
@@ -19,6 +19,7 @@ class Generic2 {
Mode mode);
void draw_debug_window();
bool empty() { return m_empty; }
struct Vertex {
math::Vector<float, 3> xyz;
@@ -42,6 +43,7 @@ class Generic2 {
void process_dma_jak1(DmaFollower& dma, u32 next_bucket);
void process_dma_lightning(DmaFollower& dma, u32 next_bucket);
void process_dma_jak2(DmaFollower& dma, u32 next_bucket);
void process_dma_prim(DmaFollower& dma, u32 next_bucket);
void setup_draws(bool enable_at, bool default_fog);
void do_draws(SharedRenderState* render_state, ScopedProfilerNode& prof);
void do_draws_for_alpha(SharedRenderState* render_state,
@@ -84,6 +86,8 @@ class Generic2 {
float hud_mat_23, hud_mat_32, hud_mat_33;
bool uses_hud = false;
bool uses_full_matrix = false;
math::Vector4f full_matrix[4];
} m_drawing_config;
struct GsState {
@@ -198,8 +202,10 @@ class Generic2 {
GLuint vertex_buffer;
GLuint index_buffer;
GLuint alpha_reject, color_mult, fog_color, scale, mat_23, mat_32, mat_33, fog_consts,
hvdf_offset;
hvdf_offset, use_full_matrix, full_matrix;
GLuint gfx_hack_no_tex;
GLuint warp_sample_mode;
} m_ogl;
bool m_empty = false;
};
@@ -22,4 +22,9 @@ void Generic2BucketRenderer::render(DmaFollower& dma,
return;
}
m_generic->render_in_mode(dma, render_state, prof, m_mode);
m_empty = m_generic->empty();
}
bool Generic2BucketRenderer::empty() const {
return m_empty;
}
@@ -11,8 +11,10 @@ class Generic2BucketRenderer : public BucketRenderer {
Generic2::Mode mode);
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void draw_debug_window() override;
bool empty() const override;
private:
std::shared_ptr<Generic2> m_generic;
Generic2::Mode m_mode;
bool m_empty = false;
};
@@ -190,6 +190,16 @@ void Generic2::determine_draw_modes(bool enable_at, bool default_fog) {
current_mode.set_alpha_fail(reg.afail());
current_mode.set_zt(reg.zte());
current_mode.set_depth_test(reg.ztest());
// detect a strange way of disabling z writes by light-trail.
// we don't actually handle alpha_fail later on in Direct - it doesn't map well to modern
// graphics and would require a draw call per primitive.
if (current_mode.get_alpha_fail() == GsTest::AlphaFail::FB_ONLY &&
current_mode.get_aref() == 0x80 &&
current_mode.get_alpha_test() == DrawMode::AlphaTest::GEQUAL) {
current_mode.set_alpha_test(DrawMode::AlphaTest::ALWAYS);
current_mode.disable_depth_write();
}
}
m_adgifs[i].mode = current_mode;
@@ -271,6 +281,10 @@ void Generic2::process_matrices() {
bool found_proj_matrix = false;
std::array<math::Vector4f, 4> projection_matrix, hud_matrix;
for (u32 i = 0; i < m_next_free_frag; i++) {
if (m_drawing_config.uses_full_matrix) {
memcpy(&m_drawing_config.full_matrix, m_fragments[i].header, 64);
break;
}
float mat_33;
memcpy(&mat_33, m_fragments[i].header + 15 * sizeof(float), sizeof(float));
if (mat_33 == 0) {
@@ -550,6 +550,83 @@ void unpack_vertex(Generic2::Vertex* out, const u8* in, int count) {
}
}
void Generic2::process_dma_prim(DmaFollower& dma, u32 next_bucket) {
reset_buffers();
auto first_data = dma.read_and_advance();
// handle the stuff at the beginning.
// if the engine didn't run the generic renderer setup function, this bucket will end here.
if (is_nop_zero(first_data) && next_bucket == dma.current_tag_offset()) {
return;
}
// MARK NOP (for profiling)
auto v0k = first_data.vifcode0().kind;
ASSERT((v0k == VifCode::Kind::MARK || v0k == VifCode::Kind::NOP) &&
first_data.vifcode1().kind == VifCode::Kind::NOP);
// NOP DIRECT (set up GS, from generic setup)
auto direct_setup = dma.read_and_advance();
ASSERT(direct_setup.size_bytes == 32 && direct_setup.vifcode0().kind == VifCode::Kind::NOP &&
direct_setup.vifcode1().kind == VifCode::Kind::DIRECT);
m_drawing_config.zmsk = false;
m_drawing_config.uses_full_matrix = true;
// STYCYCL to set up generic VU1 constants
auto constants = dma.read_and_advance();
ASSERT(constants.size_bytes == 128);
ASSERT(constants.vifcode0().kind == VifCode::Kind::STCYCL);
ASSERT(constants.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
memcpy(&m_drawing_config.pfog0, constants.data + 0, 4);
memcpy(&m_drawing_config.fog_min, constants.data + 4, 4);
memcpy(&m_drawing_config.fog_max, constants.data + 8, 4);
memcpy(m_drawing_config.hvdf_offset.data(), constants.data + 32, 16);
// 32: MSCALF 0x0 STMOD 0b0 init generic VU1
auto mscalf = dma.read_and_advance();
ASSERT(mscalf.vifcode0().kind == VifCode::Kind::MSCALF &&
mscalf.vifcode1().kind == VifCode::Kind::STMOD);
// 0: NOP NOP
// auto another_nop = dma.read_and_advance();
// ASSERT(is_nop_zero(another_nop));
while (dma.current_tag_offset() != next_bucket) {
auto up1 = dma.read_and_advance();
while (up1.vifcode0().kind == VifCode::Kind::NOP && up1.vifcode1().kind == VifCode::Kind::NOP) {
up1 = dma.read_and_advance();
}
if (up1.vifcode0().kind == VifCode::Kind::FLUSHA) {
while (dma.current_tag_offset() != next_bucket) {
auto it = dma.read_and_advance();
}
break;
}
auto up2 = dma.read_and_advance();
auto call = dma.read_and_advance();
// up1 is a 12 qw upload for control:
// up2 is vertex upload.
auto* frag = &next_frag();
ASSERT(up1.size_bytes == Generic2::FRAG_HEADER_SIZE + 5 * 16); // header + adgif
memcpy(frag->header, up1.data, Generic2::FRAG_HEADER_SIZE);
frag->adgif_idx = m_next_free_adgif;
frag->adgif_count = 1;
frag->mscal_addr = 6;
frag->uses_hud = false;
auto* adgif = &next_adgif();
memcpy(&adgif->data, up1.data + Generic2::FRAG_HEADER_SIZE, sizeof(AdGifData));
// (new 'static 'gif-tag-regs-32 :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2
// (gif-reg-id xyzf2))
int num_vtx = up2.size_bytes / (16 * 3);
frag->vtx_count = num_vtx;
frag->vtx_idx = m_next_free_vert;
alloc_vtx(num_vtx);
unpack_vertex(&m_verts[frag->vtx_idx], up2.data, num_vtx);
}
}
void Generic2::process_dma_lightning(DmaFollower& dma, u32 next_bucket) {
reset_buffers();
auto first_data = dma.read_and_advance();
@@ -74,6 +74,8 @@ void Generic2::opengl_setup(ShaderLibrary& shaders) {
m_ogl.hvdf_offset = glGetUniformLocation(id, "hvdf_offset");
m_ogl.gfx_hack_no_tex = glGetUniformLocation(id, "gfx_hack_no_tex");
m_ogl.warp_sample_mode = glGetUniformLocation(id, "warp_sample_mode");
m_ogl.use_full_matrix = glGetUniformLocation(id, "use_full_matrix");
m_ogl.full_matrix = glGetUniformLocation(id, "full_matrix");
}
void Generic2::opengl_cleanup() {
@@ -307,6 +309,12 @@ void Generic2::do_draws(SharedRenderState* render_state, ScopedProfilerNode& pro
glPrimitiveRestartIndex(UINT32_MAX);
opengl_bind_and_setup_proj(render_state);
if (m_drawing_config.uses_full_matrix) {
glUniform1i(m_ogl.use_full_matrix, 1);
glUniformMatrix4fv(m_ogl.full_matrix, 1, GL_FALSE, m_drawing_config.full_matrix[0].data());
} else {
glUniform1i(m_ogl.use_full_matrix, 0);
}
constexpr DrawMode::AlphaBlend alpha_order[ALPHA_MODE_COUNT] = {
DrawMode::AlphaBlend::SRC_0_FIX_DST, DrawMode::AlphaBlend::SRC_SRC_SRC_SRC,
DrawMode::AlphaBlend::SRC_DST_SRC_DST, DrawMode::AlphaBlend::SRC_0_SRC_DST,
@@ -7,6 +7,7 @@
#endif
#include "common/global_profiler/GlobalProfiler.h"
#include "common/util/fnv.h"
#include "game/graphics/opengl_renderer/EyeRenderer.h"
#include "game/graphics/opengl_renderer/background/background_common.h"
@@ -54,6 +55,8 @@ std::mutex g_merc_data_mutex;
Merc2::Merc2(ShaderLibrary& shaders, const std::vector<GLuint>* anim_slot_array)
: m_anim_slot_array(anim_slot_array) {
ASSERT(fnv64("the quick brown fox jumps over the lazy dog") == 0x7404cea13ff89bb0);
// Set up main vertex array. This will point to the data stored in the .FR3 level file, and will
// be uploaded to the GPU by the Loader.
glGenVertexArrays(1, &m_vao);
@@ -535,11 +538,14 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
auto* flags = (const PcMercFlags*)input_data;
int num_effects = flags->effect_count; // mostly just a sanity check
ASSERT(num_effects < kMaxEffect);
// hack for custom models to disable blerc/mod draws
bool is_custom_model = model->effects.at(0).all_draws.at(0).no_strip;
u64 current_ignore_alpha_bits = flags->ignore_alpha_mask; // shader settings
u64 current_effect_enable_bits = flags->enable_mask; // mask for game to disable an effect
bool model_uses_mod = flags->bitflags & 1; // if we should update vertices from game.
bool model_uses_mod =
flags->bitflags & 1 && !is_custom_model; // if we should update vertices from game.
bool model_disables_fog = flags->bitflags & 2;
bool model_uses_pc_blerc = flags->bitflags & 4;
bool model_uses_pc_blerc = flags->bitflags & 4 && !is_custom_model;
bool model_disables_envmap = flags->bitflags & 8;
input_data += 32;
@@ -609,6 +615,8 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
u32 lights = alloc_lights(current_lights);
stats->num_lights++;
u64 hash = fnv64(model->name);
// loop over effects, creating draws for each
for (size_t ei = 0; ei < model->effects.size(); ei++) {
// game has disabled it?
@@ -633,7 +641,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
// do fixed draws:
for (auto& fdraw : effect.mod.fix_draw) {
alloc_normal_draw(fdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
model_disables_fog);
model_disables_fog, hash);
if (should_envmap) {
try_alloc_envmap_draw(fdraw, effect.envmap_mode, effect.envmap_texture, lev_bucket,
fade_buffer + 4 * ei, first_bone, lights, uses_water);
@@ -643,7 +651,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
// do mod draws
for (auto& mdraw : effect.mod.mod_draw) {
auto n = alloc_normal_draw(mdraw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
model_disables_fog);
model_disables_fog, hash);
// modify the draw, set the mod flag and point it to the opengl buffer
n->flags |= MOD_VTX;
n->mod_vtx_buffer = mod_opengl_buffers[ei];
@@ -665,7 +673,7 @@ void Merc2::handle_pc_model(const DmaTransfer& setup,
fade_buffer + 4 * ei, first_bone, lights, uses_water);
}
alloc_normal_draw(draw, ignore_alpha, lev_bucket, first_bone, lights, uses_water,
model_disables_fog);
model_disables_fog, hash);
}
}
}
@@ -761,7 +769,9 @@ void Merc2::render(DmaFollower& dma,
SharedRenderState* render_state,
ScopedProfilerNode& prof,
MercDebugStats* stats) {
bool hack = stats->collect_debug_model_list;
*stats = {};
stats->collect_debug_model_list = hack;
if (stats->collect_debug_model_list) {
stats->model_list.clear();
}
@@ -1053,6 +1063,7 @@ Merc2::Draw* Merc2::try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw,
draw->first_index = mdraw.first_index;
draw->index_count = mdraw.index_count;
draw->mode = envmap_mode;
draw->hash = 0;
if (jak1_water_mode) {
draw->mode.enable_ab();
draw->mode.disable_depth_write();
@@ -1073,12 +1084,14 @@ Merc2::Draw* Merc2::alloc_normal_draw(const tfrag3::MercDraw& mdraw,
u32 first_bone,
u32 lights,
bool jak1_water_mode,
bool disable_fog) {
bool disable_fog,
u64 hash) {
Draw* draw = &lev_bucket->draws[lev_bucket->next_free_draw++];
draw->flags = 0;
draw->first_index = mdraw.first_index;
draw->index_count = mdraw.index_count;
draw->mode = mdraw.mode;
draw->hash = hash;
if (jak1_water_mode) {
draw->mode.set_ab(true);
draw->mode.disable_depth_write();
@@ -1205,7 +1218,7 @@ void Merc2::do_draws(const Draw* draw_array,
bool set_fade,
SharedRenderState* render_state) {
glBindVertexArray(m_vao);
int last_tex = -1;
s32 last_tex = INT32_MIN;
int last_light = -1;
bool normal_vtx_buffer_bound = true;
@@ -1244,10 +1257,19 @@ void Merc2::do_draws(const Draw* draw_array,
if (draw.texture < (int)lev->textures.size() && draw.texture >= 0) {
glBindTexture(GL_TEXTURE_2D, lev->textures.at(draw.texture));
} else if ((draw.texture & 0xffffff00) == 0xefffff00) {
auto maybe_eye = render_state->eye_renderer->lookup_eye_texture(draw.texture & 0xff);
if (maybe_eye) {
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
if (render_state->version >= GameVersion::Jak3) {
auto maybe_eye =
render_state->eye_renderer->lookup_eye_texture_hash(draw.hash, (draw.texture & 1));
if (maybe_eye) {
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
}
} else {
auto maybe_eye = render_state->eye_renderer->lookup_eye_texture(draw.texture & 0xff);
if (maybe_eye) {
glBindTexture(GL_TEXTURE_2D, *maybe_eye);
}
}
use_mipmaps_for_filtering = false;
} else if (draw.texture < 0) {
int slot = -(draw.texture + 1);
@@ -192,6 +192,7 @@ class Merc2 {
u8 fade[4];
// no strip hack for custom models
u8 no_strip;
u64 hash;
};
struct LevelDrawBucket {
@@ -213,7 +214,8 @@ class Merc2 {
u32 first_bone,
u32 lights,
bool jak1_water_mode,
bool disable_fog);
bool disable_fog,
u64 hash);
Draw* try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw,
const DrawMode& envmap_mode,
@@ -17,8 +17,14 @@ void Merc2BucketRenderer::render(DmaFollower& dma,
}
m_renderer->render(dma, render_state, prof, &m_debug_stats);
m_empty = m_debug_stats.num_predicted_draws == 0;
}
void Merc2BucketRenderer::draw_debug_window() {
m_renderer->draw_debug_window(&m_debug_stats);
}
bool Merc2BucketRenderer::empty() const {
return m_empty;
}
@@ -8,8 +8,10 @@ class Merc2BucketRenderer : public BucketRenderer {
Merc2BucketRenderer(const std::string& name, int my_id, std::shared_ptr<Merc2> merc);
void draw_debug_window() override;
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
bool empty() const override;
private:
bool m_empty = false;
std::shared_ptr<Merc2> m_renderer;
MercDebugStats m_debug_stats;
};
@@ -10,6 +10,8 @@ uniform vec3 fog_constants;
uniform vec4 scale;
uniform float mat_23;
uniform float mat_33;
uniform bool use_full_matrix;
uniform mat4 full_matrix;
uniform vec4 hvdf_offset;
uniform uint warp_sample_mode;
@@ -38,11 +40,17 @@ void main() {
// maddax.xyzw ACC, vf08, vf16 matrix multiply X
// vu.acc.madda(Mask::xyzw, gen.mat0, gen.vtx_load0.x());
transformed.xyz = position_in * scale.xyz;
transformed.z += mat_32;
transformed.w = mat_23 * position_in.z + mat_33;
transformed *= -1; // todo?
if (use_full_matrix) {
transformed = -full_matrix[3];
transformed -= full_matrix[0] * position_in.x ;
transformed -= full_matrix[1] * position_in.y;
transformed -= full_matrix[2] * position_in.z ;
} else {
transformed.xyz = position_in * scale.xyz;
transformed.z += mat_32;
transformed.w = mat_23 * position_in.z + mat_33;
transformed *= -1;
}
// div Q, vf01.x, vf12.w perspective divide
@@ -4,6 +4,7 @@ out vec4 color;
uniform vec4 rgba;
uniform int enable_tex;
uniform int set_alpha;
uniform int tcc;
uniform ivec4 channel_scramble;
uniform float alpha_multiply;
@@ -57,5 +58,9 @@ void main() {
} else {
color = (rgba / 128.);
}
color.a *= alpha_multiply;
if (set_alpha == 1) {
color.a = 0.5;
} else {
color.a *= alpha_multiply;
}
}
-18
View File
@@ -448,23 +448,6 @@ void render_game_frame(int game_width,
}
}
void update_global_profiler() {
if (g_gfx_data->debug_gui.dump_events) {
prof().set_enable(false);
g_gfx_data->debug_gui.dump_events = false;
// TODO - the file rotation code had an infinite loop here if it couldn't find anything
// matching the format
//
// Does the existing log rotation code have that problem?
auto file_path = file_util::get_jak_project_dir() / "profile_data" /
fmt::format("prof-{}.json", str_util::current_local_timestamp_no_colons());
file_util::create_dir_if_needed_for_file(file_path);
prof().dump_to_json(file_path.string());
}
}
void GLDisplay::process_sdl_events() {
SDL_Event evt;
while (SDL_PollEvent(&evt) != 0) {
@@ -603,7 +586,6 @@ void GLDisplay::render() {
// Start timing for the next frame.
g_gfx_data->debug_gui.start_frame();
prof().instant_event("ROOT");
update_global_profiler();
// toggle even odd and wake up engine waiting on vsync.
// TODO: we could play with moving this earlier, right after the final bucket renderer.
-1
View File
@@ -125,7 +125,6 @@ struct link_control {
}
};
void klink_init_globals();
Ptr<u8> c_symlink2(Ptr<u8> objData, Ptr<u8> linkObj, Ptr<u8> relocTable);
extern link_control saved_link_control;
+33 -17
View File
@@ -448,6 +448,19 @@ u64 pc_get_mips2c(u32 name) {
return Mips2C::gLinkedFunctionTable.get(n);
}
u64 pc_get_display_id() {
if (Display::GetMainDisplay()) {
return Display::GetMainDisplay()->get_display_manager()->get_active_display_id();
}
return 0;
}
void pc_set_display_id(u64 display_id) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_display_id(display_id);
}
}
u64 pc_get_display_name(u32 id, u32 str_dest_ptr) {
std::string name = "";
if (Display::GetMainDisplay()) {
@@ -469,17 +482,16 @@ u64 pc_get_display_name(u32 id, u32 str_dest_ptr) {
}
u32 pc_get_display_mode() {
auto display_mode = WindowDisplayMode::Windowed;
auto display_mode = game_settings::DisplaySettings::DisplayMode::Windowed;
if (Display::GetMainDisplay()) {
display_mode = Display::GetMainDisplay()->get_display_manager()->get_window_display_mode();
display_mode = Display::GetMainDisplay()->get_display_manager()->get_display_mode();
}
switch (display_mode) {
case WindowDisplayMode::Borderless:
case game_settings::DisplaySettings::DisplayMode::Borderless:
return g_pc_port_funcs.intern_from_c("borderless").offset;
case WindowDisplayMode::Fullscreen:
case game_settings::DisplaySettings::DisplayMode::Fullscreen:
return g_pc_port_funcs.intern_from_c("fullscreen").offset;
default:
case WindowDisplayMode::Windowed:
return g_pc_port_funcs.intern_from_c("windowed").offset;
}
}
@@ -490,13 +502,13 @@ void pc_set_display_mode(u32 symptr) {
}
if (symptr == g_pc_port_funcs.intern_from_c("windowed").offset || symptr == s7.offset) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
WindowDisplayMode::Windowed);
game_settings::DisplaySettings::DisplayMode::Windowed);
} else if (symptr == g_pc_port_funcs.intern_from_c("borderless").offset) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
WindowDisplayMode::Borderless);
game_settings::DisplaySettings::DisplayMode::Borderless);
} else if (symptr == g_pc_port_funcs.intern_from_c("fullscreen").offset) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_display_mode(
WindowDisplayMode::Fullscreen);
game_settings::DisplaySettings::DisplayMode::Fullscreen);
}
}
@@ -568,12 +580,6 @@ void pc_get_window_scale(u32 x_ptr, u32 y_ptr) {
}
}
void pc_get_fullscreen_display(u64 display_id) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_fullscreen_display_id(display_id);
}
}
void pc_set_window_size(u64 width, u64 height) {
if (Display::GetMainDisplay()) {
Display::GetMainDisplay()->get_display_manager()->enqueue_set_window_size(width, height);
@@ -601,6 +607,14 @@ void pc_get_resolution(u32 id, u32 w_ptr, u32 h_ptr) {
}
}
u64 pc_is_supported_resolution(u64 width, u64 height) {
if (Display::GetMainDisplay()) {
return bool_to_symbol(
Display::GetMainDisplay()->get_display_manager()->is_supported_resolution(width, height));
}
return bool_to_symbol(false);
}
u64 pc_get_controller_name(u32 id, u32 str_dest_ptr) {
std::string name = "";
if (Display::GetMainDisplay()) {
@@ -912,9 +926,11 @@ void init_common_pc_port_functions(
// -- DISPLAY RELATED --
// Returns the name of the display with the given id or #f if not found / empty
make_func_symbol_func("pc-get-display-id", (void*)pc_get_display_id);
make_func_symbol_func("pc-set-display-id!", (void*)pc_set_display_id);
make_func_symbol_func("pc-get-display-name", (void*)pc_get_display_name);
make_func_symbol_func("pc-get-display-mode", (void*)pc_get_display_mode);
make_func_symbol_func("pc-set-display-mode", (void*)pc_set_display_mode);
make_func_symbol_func("pc-set-display-mode!", (void*)pc_set_display_mode);
make_func_symbol_func("pc-get-display-count", (void*)pc_get_display_count);
// Returns resolution of the monitor's current display mode
make_func_symbol_func("pc-get-active-display-size", (void*)pc_get_active_display_size);
@@ -925,10 +941,10 @@ void init_common_pc_port_functions(
make_func_symbol_func("pc-get-window-size", (void*)pc_get_window_size);
// Returns scale of window. This is for DPI stuff.
make_func_symbol_func("pc-get-window-scale", (void*)pc_get_window_scale);
make_func_symbol_func("pc-set-fullscreen-display", (void*)pc_get_fullscreen_display);
make_func_symbol_func("pc-set-window-size", (void*)pc_set_window_size);
make_func_symbol_func("pc-set-window-size!", (void*)pc_set_window_size);
make_func_symbol_func("pc-get-num-resolutions", (void*)pc_get_num_resolutions);
make_func_symbol_func("pc-get-resolution", (void*)pc_get_resolution);
make_func_symbol_func("pc-is-supported-resolution?", (void*)pc_is_supported_resolution);
// -- INPUT RELATED --
// Returns the name of the display with the given id or #f if not found / empty
-1
View File
@@ -16,7 +16,6 @@ void load_and_link_dgo_from_c_fast(const char* name,
Ptr<kheapinfo> heap,
u32 linkFlag,
s32 bufferSize);
void load_and_link_dgo(u64 name_gstr, u64 heap_info, u64 flag, u64 buffer_size);
void kdgo_init_globals();
extern RPC_Dgo_Cmd sMsg[2];
extern RPC_Dgo_Cmd* sLastMsg;
+5 -4
View File
@@ -8,6 +8,7 @@
#include "game/kernel/common/kdgo.h"
#include "game/kernel/common/kmalloc.h"
#include "game/kernel/jak3/klink.h"
#include "game/overlord/jak3/rpc_interface.h"
namespace jak3 {
@@ -39,7 +40,7 @@ void BeginLoadingDGO(const char* name, Ptr<u8> buffer1, Ptr<u8> buffer2, Ptr<u8>
RpcSync(DGO_RPC_CHANNEL); // make sure old RPC is finished
// put a dummy value here just to make sure the IOP overwrites it.
sMsg[msgID].result = DGO_RPC_RESULT_INIT; // !! this is 666
sMsg[msgID].status = DGO_RPC_RESULT_INIT; // !! this is 666
// inform IOP of buffers
sMsg[msgID].buffer1 = buffer1.offset;
@@ -78,13 +79,13 @@ Ptr<u8> GetNextDGO(u32* lastObjectFlag) {
Ptr<u8> buffer(0);
if (sLastMsg) {
// if we got a good result, get pointer to object
if ((sLastMsg->result == DGO_RPC_RESULT_MORE) || (sLastMsg->result == DGO_RPC_RESULT_DONE)) {
if ((sLastMsg->status == DGO_RPC_RESULT_MORE) || (sLastMsg->status == DGO_RPC_RESULT_DONE)) {
buffer.offset =
sLastMsg->buffer1; // buffer 1 always contains location of most recently loaded object.
}
// not the last one, so don't set the flag.
if (sLastMsg->result == DGO_RPC_RESULT_MORE) {
if (sLastMsg->status == DGO_RPC_RESULT_MORE) {
*lastObjectFlag = 0;
}
@@ -111,7 +112,7 @@ void ContinueLoadingDGO(Ptr<u8> b1, Ptr<u8> b2, Ptr<u8> heapPtr) {
u32 msgID = sMsgNum;
jak3::RPC_Dgo_Cmd* sendBuff = sMsg + sMsgNum;
sMsgNum = sMsgNum ^ 1;
sendBuff->result = DGO_RPC_RESULT_INIT;
sendBuff->status = DGO_RPC_RESULT_INIT;
sMsg[msgID].buffer1 = b1.offset;
sMsg[msgID].buffer2 = b2.offset;
sMsg[msgID].buffer_heap_top = heapPtr.offset;
+220
View File
@@ -0,0 +1,220 @@
//--------------------------MIPS2C---------------------
// clang-format off
#include "game/mips2c/mips2c_private.h"
#include "game/kernel/jak3/kscheme.h"
using ::jak3::intern_from_c;
namespace Mips2C::jak3 {
namespace method_21_cloth_system {
u64 execute(void* ctxt) {
auto* c = (ExecutionContext*)ctxt;
bool bc = false;
u32 call_addr = 0;
c->daddiu(sp, sp, -80); // daddiu sp, sp, -80
c->daddiu(a3, sp, 16); // daddiu a3, sp, 16
c->daddiu(t0, sp, 32); // daddiu t0, sp, 32
c->lwu(v1, 68, a0); // lwu v1, 68(a0)
c->lw(v1, 0, v1); // lw v1, 0(v1)
c->lw(a1, 96, a0); // lw a1, 96(a0)
c->daddiu(a1, a1, -1); // daddiu a1, a1, -1
c->lw(a2, 100, a0); // lw a2, 100(a0)
c->daddiu(a2, a2, -1); // daddiu a2, a2, -1
c->addiu(t1, r0, 0); // addiu t1, r0, 0
c->addiu(t1, r0, 0); // addiu t1, r0, 0
c->mov64(t1, a3); // or t1, a3, r0
c->lui(t2, 16000); // lui t2, 16000
c->mtc1(f0, t2); // mtc1 f0, t2
c->swc1(f0, 0, t1); // swc1 f0, 0(t1)
c->lui(t2, 16000); // lui t2, 16000
c->mtc1(f0, t2); // mtc1 f0, t2
c->swc1(f0, 4, t1); // swc1 f0, 4(t1)
c->lui(t2, 16000); // lui t2, 16000
c->mtc1(f0, t2); // mtc1 f0, t2
c->swc1(f0, 8, t1); // swc1 f0, 8(t1)
c->lui(t2, 16000); // lui t2, 16000
c->mtc1(f0, t2); // mtc1 f0, t2
c->swc1(f0, 12, t1); // swc1 f0, 12(t1)
c->mov64(t1, t0); // or t1, t0, r0
c->mtc1(f0, r0); // mtc1 f0, r0
c->swc1(f0, 0, t1); // swc1 f0, 0(t1)
c->mtc1(f0, r0); // mtc1 f0, r0
c->swc1(f0, 4, t1); // swc1 f0, 4(t1)
c->mtc1(f0, r0); // mtc1 f0, r0
c->swc1(f0, 8, t1); // swc1 f0, 8(t1)
c->lwc1(f0, 144, a0); // lwc1 f0, 144(a0)
c->swc1(f0, 12, t1); // swc1 f0, 12(t1)
c->vmax_bc(DEST::xyzw, BC::w, vf1, vf0, vf0); // vmaxw.xyzw vf1, vf0, vf0
c->lqc2(vf10, 0, a3); // lqc2 vf10, 0(a3)
c->lqc2(vf15, 0, t0); // lqc2 vf15, 0(t0)
c->sd(r0, 48, sp); // sd r0, 48(sp)
c->addiu(a3, r0, 0); // addiu a3, r0, 0
//beq r0, r0, L187 // beq r0, r0, L187
// nop // sll r0, r0, 0
goto block_10; // branch always
block_1:
c->addiu(t0, r0, 0); // addiu t0, r0, 0
//beq r0, r0, L186 // beq r0, r0, L186
// nop // sll r0, r0, 0
goto block_8; // branch always
block_2:
c->addiu(t1, r0, 48); // addiu t1, r0, 48
c->ld(t2, 48, sp); // ld t2, 48(sp)
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
c->daddu(t1, t1, t2); // daddu t1, t1, t2
c->sw(t1, 56, sp); // sw t1, 56(sp)
c->addiu(t1, r0, 48); // addiu t1, r0, 48
c->ld(t2, 48, sp); // ld t2, 48(sp)
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
c->daddu(t1, t1, t2); // daddu t1, t1, t2
c->sw(t1, 60, sp); // sw t1, 60(sp)
c->addiu(t1, r0, 48); // addiu t1, r0, 48
c->ld(t2, 48, sp); // ld t2, 48(sp)
c->lw(t3, 96, a0); // lw t3, 96(a0)
c->daddu(t2, t2, t3); // daddu t2, t2, t3
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
c->daddu(t1, t1, t2); // daddu t1, t1, t2
c->sw(t1, 64, sp); // sw t1, 64(sp)
c->addiu(t1, r0, 48); // addiu t1, r0, 48
c->lw(t2, 96, a0); // lw t2, 96(a0)
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
c->ld(t3, 48, sp); // ld t3, 48(sp)
c->daddu(t2, t2, t3); // daddu t2, t2, t3
c->mult3(t1, t1, t2); // mult3 t1, t1, t2
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
c->lwu(t2, 0, a0); // lwu t2, 0(a0)
c->daddu(t1, t1, t2); // daddu t1, t1, t2
c->sw(t1, 68, sp); // sw t1, 68(sp)
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
c->lqc2(vf2, 0, t1); // lqc2 vf2, 0(t1)
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
c->lqc2(vf5, 0, t1); // lqc2 vf5, 0(t1)
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
c->lqc2(vf3, 0, t1); // lqc2 vf3, 0(t1)
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
c->lqc2(vf4, 0, t1); // lqc2 vf4, 0(t1)
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
c->lqc2(vf20, 32, t1); // lqc2 vf20, 32(t1)
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
c->lqc2(vf23, 32, t1); // lqc2 vf23, 32(t1)
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
c->lqc2(vf21, 32, t1); // lqc2 vf21, 32(t1)
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
c->lqc2(vf22, 32, t1); // lqc2 vf22, 32(t1)
c->vmula_bc(DEST::xyzw, BC::x, vf2, vf20); // vmulax.xyzw acc, vf2, vf20
c->vmadda_bc(DEST::xyzw, BC::x, vf3, vf21); // vmaddax.xyzw acc, vf3, vf21
c->vmadda_bc(DEST::xyzw, BC::x, vf5, vf23); // vmaddax.xyzw acc, vf5, vf23
c->vmadd_bc(DEST::xyzw, BC::x, vf8, vf4, vf22); // vmaddx.xyzw vf8, vf4, vf22
c->vmul_bc(DEST::xyzw, BC::x, vf8, vf8, vf10); // vmulx.xyzw vf8, vf8, vf10
c->lwu(t1, 68, a0); // lwu t1, 68(a0)
c->daddiu(t1, t1, 12); // daddiu t1, t1, 12
c->addiu(t2, r0, 0); // addiu t2, r0, 0
//beq r0, r0, L185 // beq r0, r0, L185
// nop // sll r0, r0, 0
goto block_6; // branch always
block_3:
c->lqc2(vf11, 0, t1); // lqc2 vf11, 0(t1)
c->vsub(DEST::xyzw, vf13, vf8, vf11); // vsub.xyzw vf13, vf8, vf11
c->vmul(DEST::xyzw, vf9, vf13, vf13); // vmul.xyzw vf9, vf13, vf13
c->vmula_bc(DEST::xyzw, BC::x, vf1, vf9); // vmulax.xyzw acc, vf1, vf9
c->vmadda_bc(DEST::xyzw, BC::y, vf1, vf9); // vmadday.xyzw acc, vf1, vf9
c->vmadd_bc(DEST::xyzw, BC::z, vf14, vf1, vf9); // vmaddz.xyzw vf14, vf1, vf9
c->vadd_bc(DEST::w, BC::w, vf11, vf11, vf15); // vaddw.w vf11, vf11, vf15
c->vmul(DEST::xyzw, vf12, vf11, vf11); // vmul.xyzw vf12, vf11, vf11
c->vsub_bc(DEST::xyzw, BC::w, vf9, vf14, vf12); // vsubw.xyzw vf9, vf14, vf12
c->mov128_gpr_vf(t3, vf9); // qmfc2.i t3, vf9
bc = ((s64)c->sgpr64(t3)) >= 0; // bgez t3, L184
// nop // sll r0, r0, 0
if (bc) {goto block_5;} // branch non-likely
c->vrsqrt(vf11, BC::w, vf14, BC::x); // vrsqrt Q, vf11.w, vf14.x
c->vmax_bc(DEST::xyz, BC::x, vf20, vf0, vf20); // vmaxx.xyz vf20, vf0, vf20
c->vmax_bc(DEST::xyz, BC::x, vf21, vf0, vf21); // vmaxx.xyz vf21, vf0, vf21
c->vmax_bc(DEST::xyz, BC::x, vf22, vf0, vf22); // vmaxx.xyz vf22, vf0, vf22
c->vmax_bc(DEST::xyz, BC::x, vf23, vf0, vf23); // vmaxx.xyz vf23, vf0, vf23
c->vwaitq(); // vwaitq
// Unknown instr: vmulaq.xyzw acc, vf13, Q
c->vmula_q(DEST::xyzw, vf13);
c->vmsuba(DEST::xyzw, vf1, vf13); // vmsuba.xyzw acc, vf1, vf13
c->vmadd(DEST::xyzw, vf2, vf1, vf2); // vmadd.xyzw vf2, vf1, vf2
c->vmadd(DEST::xyzw, vf3, vf1, vf3); // vmadd.xyzw vf3, vf1, vf3
c->vmadd(DEST::xyzw, vf5, vf1, vf5); // vmadd.xyzw vf5, vf1, vf5
c->vmadd(DEST::xyzw, vf4, vf1, vf4); // vmadd.xyzw vf4, vf1, vf4
c->vmadd(DEST::xyzw, vf8, vf1, vf8); // vmadd.xyzw vf8, vf1, vf8
block_5:
c->daddiu(t1, t1, 16); // daddiu t1, t1, 16
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
block_6:
c->slt(t3, t2, v1); // slt t3, t2, v1
bc = c->sgpr64(t3) != 0; // bne t3, r0, L183
// nop // sll r0, r0, 0
if (bc) {goto block_3;} // branch non-likely
c->mov64(t1, s7); // or t1, s7, r0
c->mov64(t1, s7); // or t1, s7, r0
c->lwu(t1, 56, sp); // lwu t1, 56(sp)
c->sqc2(vf2, 0, t1); // sqc2 vf2, 0(t1)
c->lwu(t1, 68, sp); // lwu t1, 68(sp)
c->sqc2(vf5, 0, t1); // sqc2 vf5, 0(t1)
c->lwu(t1, 60, sp); // lwu t1, 60(sp)
c->sqc2(vf3, 0, t1); // sqc2 vf3, 0(t1)
c->lwu(t1, 64, sp); // lwu t1, 64(sp)
c->sqc2(vf4, 0, t1); // sqc2 vf4, 0(t1)
c->mov128_gpr_vf(t1, vf4); // qmfc2.i t1, vf4
c->ld(t1, 48, sp); // ld t1, 48(sp)
c->daddiu(t1, t1, 1); // daddiu t1, t1, 1
c->sd(t1, 48, sp); // sd t1, 48(sp)
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
block_8:
c->slt(t1, t0, a1); // slt t1, t0, a1
bc = c->sgpr64(t1) != 0; // bne t1, r0, L182
// nop // sll r0, r0, 0
if (bc) {goto block_2;} // branch non-likely
c->mov64(t0, s7); // or t0, s7, r0
c->mov64(t0, s7); // or t0, s7, r0
c->ld(t0, 48, sp); // ld t0, 48(sp)
c->daddiu(t0, t0, 1); // daddiu t0, t0, 1
c->sd(t0, 48, sp); // sd t0, 48(sp)
c->daddiu(a3, a3, 1); // daddiu a3, a3, 1
block_10:
c->slt(t0, a3, a2); // slt t0, a3, a2
bc = c->sgpr64(t0) != 0; // bne t0, r0, L181
// nop // sll r0, r0, 0
if (bc) {goto block_1;} // branch non-likely
c->mov64(v1, s7); // or v1, s7, r0
c->mov64(v0, s7); // or v0, s7, r0
//jr ra // jr ra
c->daddiu(sp, sp, 80); // daddiu sp, sp, 80
goto end_of_function; // return
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
// nop // sll r0, r0, 0
end_of_function:
return c->gprs[v0].du64[0];
}
void link() {
gLinkedFunctionTable.reg("(method 21 cloth-system)", execute, 256);
}
} // namespace method_21_cloth_system
} // namespace Mips2C
+10
View File
@@ -905,6 +905,16 @@ struct ExecutionContext {
}
}
void vmula_q(DEST mask, int src0) {
auto s0 = vf_src(src0);
for (int i = 0; i < 4; i++) {
if ((u64)mask & (1 << i)) {
acc.f[i] = s0.f[i] * Q;
}
}
}
void vadda_bc(DEST mask, BC bc, int src0, int src1) {
auto s0 = vf_src(src0);
auto s1 = vf_src(src1);
+3 -1
View File
@@ -393,6 +393,7 @@ namespace shadow_add_double_edges { extern void link(); }
namespace shadow_add_single_tris { extern void link(); }
namespace shadow_add_double_tris { extern void link(); }
namespace shadow_execute { extern void link(); }
namespace method_21_cloth_system { extern void link(); }
}
// clang-format on
@@ -654,7 +655,8 @@ PerGameVersion<std::unordered_map<std::string, std::vector<void (*)()>>> gMips2C
jak3::shadow_find_single_edges::link, jak3::shadow_find_double_edges::link,
jak3::shadow_add_verts::link, jak3::shadow_add_facing_single_tris::link,
jak3::shadow_add_single_edges::link, jak3::shadow_add_double_edges::link,
jak3::shadow_add_single_tris::link, jak3::shadow_add_double_tris::link}}}};
jak3::shadow_add_single_tris::link, jak3::shadow_add_double_tris::link}},
{"cloth", {jak3::method_21_cloth_system::link}}}};
void LinkedFunctionTable::reg(const std::string& name, u64 (*exec)(void*), u32 stack_size) {
const auto& it = m_executes.insert({name, {exec, Ptr<u8>()}});
+3
View File
@@ -460,6 +460,9 @@ void* RPC_Loader(unsigned int /*fno*/, void* data, int size) {
snd_SetPlayBackMode(0);
}
} break;
case Jak2SoundCommand::mirror_mode: {
gMirrorMode = cmd->mirror.value;
} break;
default:
ASSERT_MSG(false, fmt::format("Unhandled RPC Loader command {}", int(cmd->j2command)));
}
+1
View File
@@ -58,6 +58,7 @@ enum class Jak2SoundCommand : u16 {
iop_mem = 48,
cancel_dgo = 49,
set_stereo_mode = 50,
mirror_mode = 201,
};
struct SoundRpcCommand {
+1 -1
View File
@@ -30,7 +30,7 @@ void StopVAG(VagCmd* cmd, int /*param_2*/);
enum VolumeCategory {
DIALOGUE = 2, // VAG streams. Copied "dialogue" name from jak 1.
};
int MasterVolume[17];
int MasterVolume[32];
void vag_init_globals() {
memset(VagCmds, 0, sizeof(VagCmds));
+1 -1
View File
@@ -113,7 +113,7 @@ extern int TrapSRAM[N_VAG_CMDS];
extern int StreamVoice[N_VAG_CMDS];
extern int ActiveVagStreams;
extern int MasterVolume[17];
extern int MasterVolume[32];
void vag_init_globals();
+333
View File
@@ -0,0 +1,333 @@
#include "basefile.h"
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "game/overlord/jak3/overlord.h"
#include "game/overlord/jak3/pagemanager.h"
#include "game/overlord/jak3/vag.h"
namespace jak3 {
void jak3_overlord_init_globals_basefile() {}
/*!
* Construct a CBaseFile in an unused state.
*/
CBaseFile::CBaseFile() {
m_Buffer.m_pCurrentData = nullptr;
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_nMinNumPages = 1;
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
m_Buffer.m_nDataLength = 0;
m_Buffer.m_pPageList = nullptr;
m_Buffer.m_pIsoCmd = nullptr;
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
m_ProcessDataSemaphore = -1;
m_FileDef = nullptr;
m_FileKind = Kind::UNKNOWN;
m_Status = EIsoStatus::NONE_0;
m_ReadRate = 0;
m_LengthPages = 0;
m_PageOffset = 0;
m_nNumPages = kDefaultBufferPageCount;
}
/*!
* Construct a CBaseFile for a given file, but keep it in the "idle" state, with no buffer
* allocated.
*/
CBaseFile::CBaseFile(const jak3::ISOFileDef* file, int semaphore) {
m_Buffer.m_pCurrentData = nullptr;
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
m_Buffer.m_nDataLength = 0;
m_Buffer.m_nMinNumPages = 1;
m_Buffer.m_pPageList = nullptr;
m_Buffer.m_pIsoCmd = nullptr;
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
m_nNumPages = kDefaultBufferPageCount;
m_FileDef = file;
m_ProcessDataSemaphore = semaphore;
m_FileKind = Kind::UNKNOWN;
m_Status = EIsoStatus::IDLE_1;
m_ReadRate = 0;
m_LengthPages = 0;
m_PageOffset = 0;
}
/*!
* Update our buffer to handle crossing page boundaries, return pointer to next data.
*/
uint8_t* CBaseFile::CheckPageBoundary() {
// Can't check page boundary if the buffer is not allocated.
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
// Can't check page boundary if there is no manager
ASSERT(m_Buffer.m_pPageList);
CPageList* page_list = m_Buffer.m_pPageList;
CPage* page = page_list->m_pCurrentActivePage;
// can only return data if there's an active page
if (!page || page_list->m_nNumActivePages <= 0) {
return nullptr;
}
// buffer doesn't know the current page, just reset it to the start of the active page.
if (m_Buffer.m_pCurrentPageStart == nullptr) {
m_Buffer.m_pCurrentData = page->m_pPageMemStart;
m_Buffer.m_pCurrentPageStart = page->m_pPageMemStart;
} else {
uint8_t* end_ptr = page->m_pPageMemEnd;
// check if our data pointer crossed the page boundary
if (end_ptr <= m_Buffer.m_pCurrentData) {
// it did!
uint8_t* past_boundary_ptr = m_Buffer.m_pCurrentData;
// get the next active page
CPage* next_page = page_list->StepActivePage();
if (!next_page) {
// no more active pages, no data to process
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_pCurrentData = nullptr;
ovrld_log(LogCategory::PAGING, "File {} ran out of pages in CheckPageBoundary",
m_FileDef->name.data);
} else {
// this is a little weird, but if we went past the end of the previous page, we actually
// start at an offset into the next page - perhaps the user could know that pages are
// consecutive in memory?
uint8_t* new_page_mem = next_page->m_pPageMemStart;
m_Buffer.m_pCurrentData = new_page_mem + (end_ptr + 1 - past_boundary_ptr);
m_Buffer.m_pCurrentPageStart = new_page_mem;
ovrld_log(LogCategory::PAGING, "File {} advanced to next page (wrapped {} bytes)",
m_FileDef->name.data, (end_ptr + 1 - past_boundary_ptr));
}
}
}
return m_Buffer.m_pCurrentData;
}
/*!
* Allocate pages and set up the CBuffer for the given ISO Msg and type.
*/
int CBaseFile::InitBuffer(CBuffer::BufferType type, jak3::ISO_Hdr* msg) {
ASSERT(msg);
m_Buffer.m_pCurrentData = nullptr;
m_Buffer.m_pPageList = nullptr;
m_Buffer.m_pIsoCmd = msg;
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_nDataLength = 0;
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
m_Buffer.m_nMinNumPages = 1;
m_Buffer.m_nMaxNumPages = kDefaultBufferPageCount;
m_nNumPages = 4;
// adjust size based on the request buffer type
switch (type) {
case CBuffer::BufferType::REQUEST_NORMAL: { // 3
m_Buffer.m_pCurrentData = nullptr;
m_Buffer.m_nMinNumPages = 1;
m_Buffer.m_nMaxNumPages = 4;
m_nNumPages = 4;
m_Buffer.m_nDataLength = 0;
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_eBufferType = CBuffer::BufferType::NORMAL; // 1
// and the iso msg request.
switch (msg->msg_type) {
case ISO_Hdr::MsgType::LOAD_EE:
case ISO_Hdr::MsgType::LOAD_IOP:
case ISO_Hdr::MsgType::LOAD_EE_CHUNK:
m_Buffer.m_nMinNumPages = 1;
m_nNumPages = 4;
m_Buffer.m_nMaxNumPages = 4;
break;
case ISO_Hdr::MsgType::LOAD_SOUNDBANK:
m_Buffer.m_nMinNumPages = 1;
m_Buffer.m_nMaxNumPages = 2;
break;
default:
break;
}
} break;
case CBuffer::BufferType::REQUEST_VAG: {
m_Buffer.m_pCurrentData = nullptr;
m_Buffer.m_eBufferType = CBuffer::BufferType::VAG;
m_Buffer.m_nMinNumPages = 1;
m_nNumPages = 0x10;
m_Buffer.m_nDataLength = 0;
m_Buffer.m_pCurrentPageStart = nullptr;
m_Buffer.m_nMaxNumPages = 0x10;
} break;
default:
ASSERT_NOT_REACHED(); // bad buffer type
}
ovrld_log(LogCategory::PAGING, "File {} initializing buffer ({} pages {} min {} max)",
m_FileDef->name.data, m_nNumPages, m_Buffer.m_nMinNumPages, m_Buffer.m_nMaxNumPages);
// Actual allocation of page data
CPageList* page_list = AllocPages();
if (page_list) {
// set up the current pointers of the buffer.
m_Buffer.m_pCurrentPageStart = page_list->m_pFirstPage->m_pPageMemStart;
m_Buffer.m_pCurrentData = m_Buffer.m_pCurrentPageStart;
return 1;
} else {
ovrld_log(LogCategory::WARN, "File {} failed to allocate a page list.", m_FileDef->name.data);
// if it failed, terminate the buffer
TerminateBuffer();
return 0;
}
}
/*!
* Free page memory, clear event flags for cpages.
*/
void CBaseFile::TerminateBuffer() {
ovrld_log(LogCategory::PAGING, "File {} terminating buffer.", m_FileDef->name.data);
auto buffer_type = m_Buffer.m_eBufferType;
if (buffer_type != CBuffer::BufferType::EBT_FREE) {
// clean up our pages
auto* page_list = m_Buffer.m_pPageList;
if (page_list) {
// stop try to load
page_list->CancelActivePages();
}
switch (buffer_type) {
case CBuffer::BufferType::EBT_FREE:
case CBuffer::BufferType::NORMAL:
case CBuffer::BufferType::VAG:
case CBuffer::BufferType::REQUEST_NORMAL:
case CBuffer::BufferType::REQUEST_VAG:
// return memory
FreePages();
// reset our buffer
m_Buffer.m_nDataLength = 0;
m_Buffer.m_pCurrentPageStart = 0;
m_Buffer.m_eBufferType = CBuffer::BufferType::EBT_FREE;
// reset our command
if (buffer_type != CBuffer::BufferType::EBT_FREE) {
ASSERT(m_Buffer.m_pIsoCmd);
m_Buffer.m_pIsoCmd = nullptr;
}
break;
default:
ASSERT_NOT_REACHED(); // Invalid buffer type
}
} else {
ASSERT_NOT_REACHED(); // Buffer already terminated, shouldn't happen again.
}
}
/*!
* Allocate CPage and CPageList as needed to reach the target number of pages.
*/
CPageList* CBaseFile::AllocPages() {
// should have picked a buffer type
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
if (m_Buffer.m_eBufferType == CBuffer::BufferType::EBT_FREE) {
return nullptr;
}
// We might have a PageList or not
auto* old_plist = m_Buffer.m_pPageList;
int old_unstepped_pages = 0;
bool have_plist = old_plist != nullptr;
CPageList* ret_plist = nullptr;
// if we do have a pagelist, we'll reuse it and any unstepped pages.
if (have_plist) {
old_unstepped_pages = old_plist->m_nNumUnsteppedPages;
ret_plist = old_plist;
}
int page_alloc_count = 0;
// to increase unstepped pages to the target m_nNumPages, we need to allocate this many more.
page_alloc_count = m_nNumPages - old_unstepped_pages;
// lg::warn("page counts in AllocPages: {} {}", m_nNumPages, old_unstepped_pages);
if (old_plist) {
// lg::warn(" {} {}", old_plist->m_nNumPages, old_plist->m_nNumActivePages);
}
if (old_unstepped_pages < (int)m_nNumPages) {
// alloc count will be positive.
// reduce allocation count to at most the number of free pages
if (get_page_manager()->m_CCache.m_nNumFreePages < page_alloc_count) {
page_alloc_count = get_page_manager()->m_CCache.m_nNumFreePages;
}
} else {
// alloc count would be negative, don't allocate
page_alloc_count = 0;
}
switch (m_Buffer.m_eBufferType) {
case CBuffer::BufferType::NORMAL:
case CBuffer::BufferType::REQUEST_NORMAL: {
// don't do anything special
} break;
case CBuffer::BufferType::VAG:
case CBuffer::BufferType::REQUEST_VAG: {
// for VAG commands, we don't bother buffering more than the DMA transfer size
int dma_xfer_size = ((ISO_VAGCommand*)m_Buffer.m_pIsoCmd)->xfer_size;
if (dma_xfer_size) {
ASSERT(dma_xfer_size > 0);
int limit = (dma_xfer_size + 0x7fff) >> 0xf;
if (page_alloc_count > limit) {
ovrld_log(LogCategory::WARN, "File {} wants {} pages, but VAG DMA sizes limit us to ",
m_FileDef->name.data, page_alloc_count, limit);
lg::info("page count dma limit {} -> {}\n", page_alloc_count, limit);
page_alloc_count = limit;
}
}
} break;
default:
ASSERT_NOT_REACHED(); // bad buffer type.
}
if (page_alloc_count == 0) {
return ret_plist;
}
ovrld_log(LogCategory::PAGING, "File {} wants {} more pages in AllocPages.", m_FileDef->name.data,
page_alloc_count);
if (have_plist) {
ret_plist = get_page_manager()->GrowPageList(m_Buffer.m_pPageList, page_alloc_count);
} else {
ret_plist = get_page_manager()->AllocPageList(page_alloc_count, 0);
}
if (ret_plist) {
m_Buffer.m_pPageList = ret_plist;
if (!have_plist) {
m_Buffer.m_pCurrentData = ret_plist->m_pFirstPage->m_pPageMemStart;
}
} else {
ASSERT_NOT_REACHED(); // might be ok.
}
return ret_plist;
}
/*!
* Free all pages and the page list.
*/
void CBaseFile::FreePages() {
ASSERT(m_Buffer.m_eBufferType != CBuffer::BufferType::EBT_FREE);
if (m_Buffer.m_pPageList) {
get_page_manager()->FreePageList(m_Buffer.m_pPageList);
}
m_Buffer.m_pPageList = nullptr;
}
} // namespace jak3
+76
View File
@@ -0,0 +1,76 @@
#pragma once
#include "common/common_types.h"
#include "game/overlord/jak3/isocommon.h"
#include "game/overlord/jak3/pagemanager.h"
namespace jak3 {
void jak3_overlord_init_globals_basefile();
struct CPageList;
struct ISOFileDef;
struct ISO_Hdr;
constexpr int kDefaultBufferPageCount = 4;
/*!
* Base class for a file that the ISO system is processing.
* This represents an "open" file, and contains references to the buffer holding this file's data
*/
struct CBaseFile {
CBaseFile();
CBaseFile(const ISOFileDef* file, int semaphore);
virtual ~CBaseFile() = default;
uint8_t* CheckPageBoundary();
int InitBuffer(CBuffer::BufferType type, ISO_Hdr* msg);
CPageList* AllocPages();
void TerminateBuffer();
void FreePages();
// buffer that stores some contents of this file
CBuffer m_Buffer;
// the number of pages that were allocated for reading this file.
u32 m_nNumPages;
// Metadata about the file
const ISOFileDef* m_FileDef;
// The compression format used on the file
enum class Kind {
UNKNOWN = 0,
NORMAL = 1,
LZO_COMPRESSED = 2,
} m_FileKind = Kind::UNKNOWN;
EIsoStatus m_Status = EIsoStatus::NONE_0;
// The expected read rate for streaming, used to prioritize CD reads. Can be 0 if unknown/not
// applicable.
int m_ReadRate = 0;
// Number of sectors that we should read in total, decided based on the file size and request from
// user when they opened this file.
int m_LengthPages = 0; // really, in pages...
// The current offset. (todo: is this for data we read, processed?)
int m_PageOffset = 0;
// Semaphore that we should wait on before handing new data to the process callback.
// Set to -1 if there is no semaphore.
// (this is a bit of hack, only used for VAG streaming).
int m_ProcessDataSemaphore = 0;
// virtual methods
virtual EIsoStatus BeginRead() = 0;
virtual EIsoStatus SyncRead() = 0;
virtual void Close() = 0;
virtual int RecoverPages(int num_pages) = 0;
virtual int GetSector() = 0;
// ??
// ??
// ??
};
} // namespace jak3
+26
View File
@@ -0,0 +1,26 @@
#include "basefilesystem.h"
#include "common/util/Assert.h"
#include "game/sce/iop.h"
using namespace iop;
namespace jak3 {
void jak3_overlord_init_globals_basefilesystem() {}
CBaseFileSystem::CBaseFileSystem() {
for (auto& sema : m_Sema) {
sema = -1;
SemaParam param;
param.max_count = 1;
param.attr = 0;
param.init_count = 1;
param.option = 0;
sema = CreateSema(&param);
if (sema < 0) {
ASSERT_NOT_REACHED();
}
}
}
} // namespace jak3
Loaded 100 of 621 files, more files were not shown because too many files have changed in this diff. Show more