Compare commits

..
Author SHA1 Message Date
Tyler Wilding a36eeeea1d ci: only run on PRs 2024-08-02 23:36:30 -04:00
Tyler Wilding ce581e18bb git: get rid of nested .gitignores in ./out 2024-08-02 23:28:37 -04:00
Tyler Wilding a20ccb37e1 ci: add a workflow to compare compilation output with master 2024-08-02 23:26:50 -04:00
Aloqas 2e9b099d58 [jak1] update finnish translations (#3619)
A long overdue Finnish translation update with better subtitle timings
and wording.
2024-08-01 17:21:40 -04:00
Tyler Wilding 276169f525 New Crowdin updates (#3621) 2024-07-31 16:32:22 -04: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
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
622 changed files with 55129 additions and 13484 deletions

No files matched your search

@@ -0,0 +1,90 @@
name: Compiler Output Check
on:
pull_request:
branches:
- master
jobs:
build:
name: Clang
runs-on: ubuntu-20.04
timeout-minutes: 60
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Package Dependencies
run: |
sudo apt update
sudo apt install build-essential cmake \
clang gcc g++ lcov make nasm libxrandr-dev \
libxinerama-dev libxcursor-dev libpulse-dev \
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup sccache
uses: hendrikmuhs/[email protected]
with:
variant: sccache
key: linux-ubuntu-20.04--Release-linux-clang-asan-${{ github.sha }}
restore-keys: linux-ubuntu-20.04--Release-linux-clang-asan
max-size: 1000M
- name: CMake Generation (PR)
env:
CC: clang
CXX: clang++
run: |
cmake -B build --preset=Release-linux-clang-asan \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build goalc (PR)
run: cmake --build build --parallel $((`nproc`)) --target goalc
- name: Compile and preserve (PR)
run: |
./build/goalc/goalc --game jak1 --cmd "(make-group \"all-code\")"
./build/goalc/goalc --game jak2 --cmd "(make-group \"all-code\")"
./build/goalc/goalc --game jak3 --cmd "(make-group \"all-code\")"
mv ./out/jak1/obj ./out/jak1/obj.pr
mv ./out/jak2/obj ./out/jak2/obj.pr
mv ./out/jak3/obj ./out/jak3/obj.pr
- name: Checkout Master
uses: actions/checkout@v4
with:
ref: master
- name: CMake Generation (master)
env:
CC: clang
CXX: clang++
run: |
cmake -B build --preset=Release-linux-clang-asan \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build goalc (master)
run: cmake --build build --parallel $((`nproc`)) --target goalc
- name: Compile and preserve (master)
run: |
./build/goalc/goalc --game jak1 --cmd "(make-group \"all-code\")"
./build/goalc/goalc --game jak2 --cmd "(make-group \"all-code\")"
./build/goalc/goalc --game jak3 --cmd "(make-group \"all-code\")"
mv ./out/jak1/obj ./out/jak1/obj.master
mv ./out/jak2/obj ./out/jak2/obj.master
mv ./out/jak3/obj ./out/jak3/obj.master
- name: Compare Results and Produce Report
run: |
python ./scripts/gsrc/compare-compilation-outputs.py --base "./out/jak1/obj.master,./out/jak2/obj.master,./out/jak3/obj.master" --compare "./out/jak1/obj.pr,./out/jak2/obj.pr,./out/jak3/obj.pr" --markdown
SCRIPT_EXIT_CODE=$?
cat ./comp-diff-report.md >> $GITHUB_STEP_SUMMARY
if [ "$SCRIPT_EXIT_CODE" -ne 0 ]; then
exit 1
fi
+6 -1
View File
@@ -32,6 +32,7 @@ linux-default/
*.bin
*.log
*.p2s
out/
savestate-out/
savestate_out/
failures/
@@ -58,11 +59,15 @@ 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
ci-artifacts/
out/build/
__pycache__/
# sqlite stuff
-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>();
}
}
@@ -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"],
+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
+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);
+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());
}
+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
+13
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
+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 ;;
@@ -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 -1
View File
@@ -361,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);
}
}
+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
-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
File diff suppressed because it is too large. Load diff
@@ -46,7 +46,7 @@
"VISMÄNNEN HAR BLIVIT KIDNAPPADE,",
"GOL OCH MAIA HAR SAMLAT IHOP TILLRÄCKLIGT MED ECO",
"FÖR ATT KUNNA GENOMFÖRA SIN HEMSKA PLAN,",
"OCH FÖR ATT KUNNA STOPPA DEM, SÅ MÅSTE NI",
"OCH FÖR ATT KUNNA STOPPA DOM, SÅ MÅSTE NI",
"SLÅ ER FRAM HELA VÄGEN GENOM DERAS CITADELL!",
"EH... JA. SÅ KAN MAN, EH... NOG SAMMANFATTA DET HELA.",
"NI MÅSTE RÄDDA MIN FAR INNAN DET ÄR FÖR SENT!",
@@ -323,7 +323,7 @@
],
"explorer-resolution": [
"JAG SER ATT NI TVÅ ÄR TILLBAKA FÖR ATT GENOMFÖRA BYTET. BRA, BRA, MYCKET BRA!",
"ÄH, DU HAR MED DIG ÖH, DOM PRECURSOR-KULOR VI KOM ÖVERENS OM?",
"ÄH, NI HAR MED ER ÖH, DOM PRECURSOR-KULOR VI KOM ÖVERENS OM?",
"JAG HOPPAS ATT DU FÅR ANVÄNDNING AV DEN HÄR SURT FÖRVÄRVADE KRAFTCELLEN.",
"TACK SÅ MYCKET, GODDAG, ADJÖ!"
],
@@ -2242,7 +2242,7 @@
],
"sksp0079": [
"AH! JAG KOMMER ATT DÖ! JAG KOMMER, FARFAR!",
"DU MÅSTE FÅ DEN HÄR SAKEN ÖVER TILL ANDRA SIDAN INNAN DEN BLIR ÖVERHETTAD!"
"NI MÅSTE FÅ DEN HÄR SAKEN ÖVER TILL ANDRA SIDAN INNAN DEN BLIR ÖVERHETTAD!"
],
"sksp0080": [
"ANVÄND KURVAN FÖR ATT KUNNA STYRA BÄTTRE!"
File diff suppressed because it is too large. Load diff
+38 -38
View File
@@ -6,16 +6,16 @@
"0107": "HALUATKO PELATA UUDELLEEN?",
"0108": "LOPETA",
"0109": "TAUKO",
"010a": "EFEKTIEN VOIMAKKUUS",
"010b": "MUSIIKIN VOIMAKKUUS",
"010c": "PUHEEN VOIMAKKUUS",
"010a": "ÄÄNITEHOSTEET",
"010b": "MUSIIKKI",
"010c": "PUHE",
"010d": "KIELI",
"010e": "VÄRÄHTELYT",
"010e": "VÄRINÄTOIMINTO",
"010f": "VINKIT",
"0110": "KESKITÄ RUUTU",
"0111": "PÄÄLLÄ",
"0112": "POIS",
"0113": "KÄYTÄ D-PAD:IA",
"0113": "KÄYTÄ SUUNTANÄPPÄIMIÄ",
"0114": "ENGLISH",
"0115": "FRANÇAIS",
"0116": "DEUTSCH",
@@ -24,36 +24,36 @@
"0119": "にほんご",
"011a": "PAINA <PAD_CIRCLE> VAIHTAAKSESI 90 HELMEÄ VOIMAKENNOON.",
"011b": "PAINA <PAD_CIRCLE> VAIHTAAKSESI 120 HELMEÄ VOIMAKENNOON.",
"011c": "PAINA <PAD_CIRCLE> MENNÄKSESI.",
"011d": "PAINA <PAD_TRIANGLE> PERUAKSESI.",
"011c": "MATKUSTA PAINAMALLA <PAD_CIRCLE>.",
"011d": "PERU PAINAMALLA <PAD_TRIANGLE>.",
"011e": "GEYSIRSAARI",
"011f": "VIHREÄN TIETÄJÄN MÖKKI",
"0120": "SINISEN TIETÄJÄN MÖKKI",
"0121": "PUNAISEN TIETÄJÄN MÖKKI",
"0122": "GOLIN AND MAIAN LINNOITUS",
"0123": "PAINA <PAD_CIRCLE> PUHUAKSESI SAMOSILLE",
"0124": "PAINA <PAD_CIRCLE> PUHUAKSESI KEIRALLE",
"0123": "PAINA <PAD_CIRCLE> PUHUAKSESI SAMOSILLE.",
"0124": "PAINA <PAD_CIRCLE> PUHUAKSESI KEIRALLE.",
"0125": "KUVASUHDE",
"0126": "VIDEON TILA",
"0126": "VIDEOTILA",
"0127": "PELIASETUKSET",
"0128": "GRAFIIKKA-ASETUKSET",
"0129": "ÄÄNIASETUKSET",
"012a": "4X3",
"012b": "16X9",
"012c": "60HZ",
"012d": "50HZ",
"012c": "60 HZ",
"012d": "50 HZ",
"012e": "JAK AND DAXTER",
"012f": "LÖYDÄ KÄTKETTY VOIMAKENNO",
"0130": "LIIAN VÄHÄN TILAA MUISTIKORTILLA MEMORY_CARD_(PS2, INSERTED IN MEMORY_CARD_SLOT_~D",
"0131": "EI MEMORY_CARD_(PS2, LIITETTYNÄ IN MEMORY_CARD_SLOT_~D",
"0132": "MEMORY_CARD_(PS2, PAIKASSA MEMORY_CARD_SLOT_~D ON ALUSTAMATON",
"0133": "JAK AND DAXTER VAATII ~DKB VAPAATA TILAA",
"0134": "KIINNITÄ MEMORY_CARD_(PS2, JOSSA ON TARPEEKSI TILAA, MUUTEN PELITIETOJA EI VOIDA TALLENTAA",
"0130": "EI TARPEEKSI TILAA MUISTIKORTILLA MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D",
"0131": "EI MEMORY_CARD_(PS2) LIITETTYNÄ PAIKASSA MEMORY_CARD_SLOT_~D",
"0132": "MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D ON ALUSTAMATON",
"0133": "JAK AND DAXTER VAATII ~D KT VAPAATA TILAA",
"0134": "SYÖTÄ MEMORY_CARD_(PS2), JOSSA ON TARPEEKSI TILAA, MUUTEN PELITIETOJASI EI VOIDA TALLENTAA",
"0135": "ILMAN ALUSTAMISTA PELITIETOJA EI VOIDA TALLENTAA",
"0136": "TALLENNETAAN TIETOJA",
"0137": "LADATAAN TIETOJA",
"0138": "ÄLÄ POISTA MEMORY_CARD_(PS2, IN MEMORY_CARD_SLOT_~D TAI SAMMUTA LAITETTASI",
"0139": "HALUATKO PÄÄLLEKIRJOITTAA TÄMÄN?",
"0138": "ÄLÄ POISTA MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D TAI SAMMUTA LAITETTASI",
"0139": "HALUATKO KORVATA SEN?",
"013a": "ALUSTA?",
"013c": "KYLLÄ",
"013d": "EI",
@@ -62,7 +62,7 @@
"0140": "VALITSE TALLENNUSPAIKKA",
"0141": "VALITSE LADATTAVA TALLENNUS",
"0142": "JAK AND DAXTER -TALLENNUS ON JO OLEMASSA VALITSEMASSASI TIEDOSTOSSA",
"0143": "SYÖTÄ MEMORY_CARD_(PS2, JOKA SISÄLTÄÄ JAK AND DAXTER -TALLENNUSTIETOJA PAIKKAAN MEMORY_CARD_SLOT_~D",
"0143": "SYÖTÄ JAK AND DAXTER -PELITIETOJA SISÄLTÄVÄ MEMORY_CARD_(PS2) PAIKKAAN MEMORY_CARD_SLOT_~D",
"0144": "JATKA?",
"014b": "LATAA PELI",
"014c": "TALLENNA PELI",
@@ -72,29 +72,29 @@
"0150": "ASETUKSET",
"0151": "VIRHE LADATTAESSA",
"0152": "VIRHE TALLENTAESSA",
"0153": "VIRHE ALUSTAMISESSA",
"0153": "VIRHE ALUSTAESSA",
"0154": "VIRHE LUODESSA TALLENNUSTIEDOSTOA",
"0156": "MEMORY_CARD_(PS2, PAIKASTA MEMORY_CARD_SLOT_~D POISTETTIIN",
"0157": "AUTOMAATTITALLENNUS ON POISTETTU KÄYTÖSTÄ",
"0158": "KÄYTÄ TALLENNA PELI -ASETUSTA TALLENTAAKSESI PELIN MANUAALISESTI JA UUDELLEENKÄYNNISTÄÄKSESI AUTOMAATTITALLENNUKSEN",
"0159": "JAK AND DAXTER -TALLENNUSTIETOJA EI LÖYTYNYT MEMORY_CARD_(PS2, PAIKASSA MEMORY_CARD_SLOT_~D",
"0156": "MEMORY_CARD_(PS2) PAIKASTA MEMORY_CARD_SLOT_~D POISTETTIIN",
"0157": "AUTOMAATTINEN TALLENNUS ON POISTETTU KÄYTÖSTÄ",
"0158": "TALLENNA PELISI MANUAALISESTI, NIIN AUTOMAATTINEN TALLENNUS PALAUTETAAN KÄYTTÖÖN",
"0159": "JAK AND DAXTER -TALLENNUSTIETOJA EI LÖYTYNYT KORITLTA MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D",
"015a": "HALUATKO LUODA UUDEN JAK AND DAXTER -TALLENNUKSEN?",
"015b": "TARKISTA MEMORY_CARD_(PS2, PAIKASSA MEMORY_CARD_SLOT_~D",
"015b": "TARKISTA MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D",
"015c": "UUSI PELI",
"015d": "TAKAISIN?",
"015e": "OK",
"015f": "POISTU DEMOSTA",
"0160": "KUN OHEINEN KUVAKE ILMESTYY, EDISTYKSESI TALLENNETAAN",
"0161": "KUN TÄMÄ KUVAKE ON RUUDULLA, ÄLÄ POISTA THE MEMORY_CARD_(PS2, TAI SAMMUTA LAITETTASI",
"0161": "KUN TÄMÄ KUVAKE ON RUUDULLA, ÄLÄ IRROTA MEMORY_CARD_(PS2) TAI SAMMUTA LAITETTASI",
"0162": "TEHTÄVÄ SUORITETTU",
"0163": "TARKISTA MEMORY_CARD_(PS2, IN MEMORY_CARD_SLOT_~D JA YRITÄ UUDELLEEN",
"0163": "TARKISTA MEMORY_CARD_(PS2) PAIKASSA MEMORY_CARD_SLOT_~D JA YRITÄ UUDELLEEN",
"0164": "RUUTU OTTAA NYT KÄYTTÖÖN 60HZ-TILAN",
"0165": "JOS KUVA NÄKYY VIRHEELLISENÄ, TELEVISIOSI EI TUE TÄTÄ TILAA",
"0166": "JOS NÄIN KÄY, ODOTA 10 SEKUNTIA NIIN RUUTU PALAUTETAAN TAKAISIN",
"0166": "JOS NIIN KÄY, ODOTA 10 SEKUNTIA, NIIN RUUTU PALAUTUU TAKAISIN",
"0167": "RUUTU ON NYT 60HZ-TILASSA",
"0168": "HALUATKO PITÄÄ TÄMÄN TILAN KÄYTÖSSÄ?",
"0169": "KÄYTÄ D-PAD:IA VALITAKSESI TASON",
"016a": "LEVY ON POISTETTU",
"0169": "VALITSE TASO SUUNTANÄPPÄIMILLÄ",
"016a": "LEVY POISTETTIIN",
"016b": "SYÖTÄ JAK AND DAXTER -LEVY SISÄÄN, JOTTA VOIT JATKAA PELAAMISTA",
"016c": "VIRHE TIETOJEN LUKEMISESSA",
"016d": "TARKISTA JAK AND DAXTER -LEVYSI JA YRITÄ UUDELLEEN",
@@ -104,7 +104,7 @@
"0171": "YHTEENSÄ KERÄTTY:",
"0200": "TUO 90 HELMEÄ PORMESTARILLE",
"0201": "TUO 90 HELMEÄ ENOLLESI",
"0202": "PAIMENNA NAUKIT TAKAISIN AITAUKSEENSA",
"0202": "PAIMENNA NAUKIT TAKAISIN AITAUKSEEN",
"0203": "PALAA VILJELIJÄN LUO",
"0204": "TUO 120 HELMEÄ ORAAKKELILLE",
"0205": "AVAA ECO-KERÄIMIEN TUKOKSET",
@@ -117,9 +117,9 @@
"020c": "YHDISTÄ ECO-SÄTEET",
"020d": "KIIPEÄ TEMPPELIN HUIPULLE",
"020e": "ETSI SINISEN ECON KATKAISIN",
"020f": "PÄIHITÄ PIMEÄN ECON KASVI",
"020f": "PÄIHITÄ PIMEÄ ECO-KASVI",
"0210": "NAPPAA 200 KILOA KALAA",
"0211": "OTA KIINNI VEISTÄJÄN MUUSA",
"0211": "NAPPAA KIINNI VEISTÄJÄN MUUSA",
"0212": "VIE MUUSA TAKAISIN VEISTÄJÄLLE",
"0213": "KIIPEÄ VAANIJAPAATTIIN",
"0214": "PYSÄYTÄ KANUUNA",
@@ -135,7 +135,7 @@
"021e": "VIHREÄN TIETÄJÄN MÖKKI",
"021f": "KEIRAN TALLI",
"0220": "SANDOVERIN KYLÄ",
"0221": "VARTIJARANTA",
"0221": "VAHTIRANTA",
"0222": "KIELLETTY VIIDAKKO",
"0223": "USVASAARI",
"0224": "TULIKANJONI",
@@ -145,14 +145,14 @@
"0228": "FLUT FLUT",
"0229": "HELMIORAAKKELI",
"022a": "TRANS-ALUSTA",
"022b": "VIHREÄN ECON KERÄIMET",
"022b": "VIHREÄT ECO-KERÄIMET",
"022c": "EDELTÄJÄHELMI",
"022d": "VOIMAKENNO",
"022e": "NAPPAA PUDONNUT VOIMAKENNO",
"022f": "KORJAA ECO-SÄDE",
"0230": "PALAA PORMESTARIN LUO",
"0262": "TUTKI RANNIKKOA",
"0263": "KIIPEÄ VARTIJAN PÄÄLLE",
"0263": "KIIPEÄ VAHDIN PÄÄLLE",
"0264": "SEURAA ROTKOA MERENRANNALLE",
"0265": "AVAA LUKITTU TEMPPELIN OVI",
"0266": "YLLÄ VOIMAKENNOLLE ZOOMERILLA",
@@ -223,7 +223,7 @@
"040e": "KIIPEÄ VALTAVAA ROBOTTIA",
"040f": "TUTKI PIMEÄÄ LUOLAA",
"0410": "AMMU JAUHAVAT VAANIJAT KIIKARIESI AVULLA",
"0411": "TUHOA PIMEÄN ECON KRISTALLIT",
"0411": "TUHOA PIMEÄT ECO-KRISTALLIT",
"0412": "PÄIHITÄ LUOLAN LEPAKOT",
"0413": "VAPAUTA 7 PARTIOKÄRPÄSTÄ",
"0414": "PUNAISEN TIETÄJÄN LABRA",
@@ -204,7 +204,7 @@
"1601": "CONTROLLER AUSWÄHLEN",
"1602": "STICK DEADZONE",
"1603": "IGNORIERE WENN UNFOKUSIERT",
"1604": "CONTROLLER LED FÜR LEBEN",
"1604": "CONTROLLER LED FÜR HP",
"1605": "CONTROLLER LED FÜR ECO",
"1606": "KAMERA VERFOLGEN",
"1607": "HORIZONTALE SENSITIVITÄT",
@@ -2,15 +2,15 @@
"1000": "KUVAKULMA-ASETUKSET",
"1001": "NORMAALI",
"1002": "KÄÄNTEINEN",
"1003": "ENSIMMÄISEN PERSOONAN VAAKAKAMERA",
"1004": "ENSIMMÄISEN PERSOONAN PYSTYKAMERA",
"1005": "KOLMANNEN PERSOONAN VAAKAKAMERA",
"1006": "KOLMANNEN PERSOONAN PYSTYKAMERA",
"1003": "VAAKAOHJAUS (1. PERSOONA)",
"1004": "PYSTYOHJAUS (1. PERSOONA)",
"1005": "VAAKAOHJAUS (3. PERSOONA)",
"1006": "PYSTYOHJAUS (3. PERSOONA)",
"1007": "PALAUTA OLETUKSET",
"1010": "HELPPOKÄYTTÖISYYS",
"1011": "EDELTÄJÄHELMIEN HEHKU",
"1020": "PS2-ASETUKSET",
"1021": "PS2 LATAUSNOPEUS",
"1021": "PS2-LATAUSNOPEUS",
"1022": "PARTIKKELEIDEN VÄHENNYS",
"1023": "MUSIIKIN ULOS HÄIVYTYS",
"1024": "MUSIIKIN SISÄÄN HÄIVYTYS",
@@ -24,11 +24,11 @@
"1034": "KOKORUUTU",
"1035": "RESOLUUTIO",
"1036": "~D X ~D",
"1037": "PS2 KUVASUHDE",
"1038": "KUN PS2 KUVASUHDE ON KÄYTÖSSÄ, VAIN KUVASUHTEET 4X3 JA 16X9 OVAT VALITTAVISSA. JATKA?",
"1037": "PS2-KUVASUHDE",
"1038": "KUN PS2-KUVASUHDE ON KÄYTÖSSÄ, VAIN KUVASUHTEET 4X3 JA 16X9 OVAT VALITTAVISSA. JATKA?",
"1039": "KUVASUHDE (PS2)",
"1040": "TEKSTITYKSET KÄYTÖSSÄ",
"1041": "TEKSTITYKSET EI KÄYTÖSSÄ",
"1040": "TEKSTITYS KÄYTÖSSÄ",
"1041": "TEKSTITYS EI KÄYTÖSSÄ",
"1042": "TEKSTIN KIELI",
"1043": "NÄYTTÖ",
"1044": "NÄYTTÖ ~D",
@@ -50,8 +50,8 @@
"1075": "ALHAINEN",
"1076": "MINIMI",
"1077": "PS2",
"1078": "TEKSTITYKSET",
"1079": "VINKKITEKSTITYKSET",
"1078": "TEKSTITYS",
"1079": "VINKKIEN TEKSTITYS",
"1080": "HUIJAUKSET",
"1081": "SALAISUUDET",
"1082": "VALITSE KAPPALE",
@@ -68,8 +68,8 @@
"1093": "LOPUTON KELTAINEN ECO",
"1094": "VAIHTOEHTOINEN DAXTER",
"1095": "HAAVOITTUMATTOMUUS",
"1096": "KAIKKI MUSIIKKIKAPPALEET",
"1097": "TODELLINEN VUOROKAUDEN AIKA",
"1096": "KAIKKI MUSIIKKITYYLIT",
"1097": "TODELLINEN VUOROKAUDENAIKA",
"1098": "LÄPÄISE PELI 100%",
"1099": "LÄPÄISE PELI",
"1100": "KELTAINEN TIETÄJÄ",
@@ -96,17 +96,17 @@
"1500": "SPEEDRUN-TILA",
"138": "ÄLÄ LISÄÄ TAI POISTA MITÄÄN OHEISLAITTEITA, SAMMUTA LAITETTASI TAI SAMMUTA PELIÄ",
"161": "KUN TÄMÄ KUVAKE ON RUUDULLA, ÄLÄ LISÄÄ TAI POISTA MITÄÄN OHEISLAITTEITA, SAMMUTA LAITETTASI TAI SAMMUTA PELIÄ",
"100c": "AUTO-TALLENNUS POIS PÄÄLTÄ",
"100d": "HALUATKO VARMASTI LOPETTAA AUTO-TALLENTAMISEN?",
"100e": "LOPETA AUTO-TALLENNUS",
"100c": "AUTOM. TALLENNUS POIS",
"100d": "HALUATKO VARMASTI LOPETTAA AUTOMAATTISEN TALLENNUKSEN?",
"100e": "LOPETA AUTOM. TALLENNUS",
"100f": "SEKALAISET",
"103a": "SOVITA RUUTUUN",
"103b": "PYSTYTAHDISTUS",
"103c": "4X3 (PS2)",
"103d": "16X9 (PS2)",
"103e": "~DX~D",
"103f": "OTA TEKSTITYKSET KÄYTTÖÖN PAINAMALLA <PAD_SQUARE>",
"107a": "TEKSTITYSTEN KIELI",
"103f": "OTA TEKSTITYS KÄYTTÖÖN PAINAMALLA <PAD_SQUARE>",
"107a": "TEKSTITYKSEN KIELI",
"107b": "NÄYTÄ PUHUJA TEKSTITYKSISSÄ",
"107c": "AINA",
"107d": "EI KOSKAAN",
@@ -120,7 +120,7 @@
"109f": "KÄÄNTEINEN MAAILMA",
"10a0": "SUURIPÄINEN JAK",
"10c0": "MUSIIKKISOITIN",
"10c1": "VÄLIANIMAATIO-SOITIN",
"10c1": "VÄLINÄYTÖSSSOITIN",
"10c2": "TOISTA LOPPUTEKSTIT",
"10c3": "LEIKEKIRJA",
"10d0": "OLETUS",
@@ -160,7 +160,7 @@
"10f2": "SOLAN LOPPUOSA",
"10f3": "HÄMÄHÄKKILUOLAAN",
"10f4": "LUMIVUORILLE",
"10f5": "KAIVOSMIEHET",
"10f5": "MAINARIT",
"10f6": "ROBOTTILUOLAN TELINEET",
"10f7": "EDELTÄJÄROBOTIN HUIPPU",
"10f8": "PÄÄLUOLA",
@@ -171,10 +171,10 @@
"10fd": "LUMIPALLOT",
"10fe": "TUNNELIN KESKIOSA",
"10ff": "TUNNELIN LOPPU",
"1501": "OHITA VÄLIANIMAATIOT",
"1501": "VÄLINÄYTÖSTEN OHITUKSET",
"1502": "VALITSE TARKISTUSPISTE",
"1503": "SPEEDRUN-ASETUKSET",
"1504": "VAROITUS: NÄMÄ ASETUKSET AUTOMAATTITALLENTAVAT ENSIMMÄISEEN TALLENNUSPAIKKAAN!",
"1504": "VAROITUS: NÄMÄ ASETUKSET TALLENTAVAT AUTOMAATTISESTI ENSIMMÄISEEN TALLENNUSPAIKKAAN!",
"1505": "ALOITA SPEEDRUN UUDELLEEN",
"1506": "UUSI TÄYDEN PELIN SPEEDRUN",
"150e": "UUSI YKSITTÄISEN TASON SPEEDRUN",
@@ -199,16 +199,16 @@
"1521": "HUBI 1 100%",
"1522": "HUBI 2 100%",
"1523": "HUBI 3 100%",
"1524": "KAIKKI VÄLIANIMAATIOT",
"1524": "KAIKKI VÄLINÄYTÖKSET",
"1600": "OHJAUSSYÖTTEEN ASETUKSET",
"1601": "VALITSE OHJAIN",
"1602": "ANALOGISAUVAN KATVEALUE",
"1603": "ÄLÄ HUOMIOI, JOS IKKUNA EI AKTIIVINEN",
"1603": "ÄLÄ HUOMIOI TYÖPÖYDÄLLÄ",
"1604": "OHJAIMEN LED TERVEYDELLE",
"1605": "OHJAIMEN LED ECO-VOIMILLE",
"1606": "KAMERAN OHJAUS HIIRELLÄ",
"1607": "VAAKASUUNTAINEN HERKKYYS",
"1608": "PYSTYSUUNTAINEN HERKKYYS",
"1607": "HERKKYYS (VAAKASUUNTA)",
"1608": "HERKKYYS (PYSTYSUUNTA)",
"1609": "PELAAJAN OHJAUS HIIRELLÄ",
"160a": "PELIOHJAIMEN KYTKENNÄT",
"160b": "NÄPPÄIMISTÖN KYTKENNÄT",
@@ -220,8 +220,8 @@
"1611": "MUUTA KYTKENTÖJÄ",
"1612": "OHJAIN ~D",
"1613": "PIILOTA OSOITIN AUTOMAATTISESTI",
"1614": "MÄÄRITTÄMÄTÖN",
"1614": "TYHJÄ",
"1615": "TUNTEMATON",
"1616": "MUITA ASETUKSIA RUUDUN KOOLLE EI SAATAVISSA",
"1616": "MUITA KUVASUHTEITA EI OLE SAATAVILLA",
"1617": "OHJAIMEN LED LÄMPÖMITTARILLE"
}
@@ -16,59 +16,59 @@
"1024": "ミュージック ゲイン",
"1025": "アクター カリング",
"1026": "バックグラウンド カリング",
"1027": "かんきょう マッピングを きょうせいする",
"1027": "??マッピングを???に?行",
"1030": "DISCORDリッチプレゼンス",
"1031": "スクリーンモード",
"1032": "ウィンドウ",
"1033": "ボーダレス",
"1034": "フルスクリーン",
"1035": "かいぞうど",
"1035": "?像?",
"1036": "~D X ~D",
"1037": "PS2 アスペクト ひ",
"1038": "PS2アスペクトひが ゆうこうになると、4X3と16X9しか せんたくできません ぞっこうしますか?",
"1039": "アスペクト ひ (PS2)",
"1040": "じまくあり",
"1041": "じまくなし",
"1042": "テキストのことば",
"1043": "ディスプレー",
"1044": "ディスプレー ~D",
"1037": "PS2 アスペクト?",
"1038": "PS2アスペクト?が??になると、4?3と16?9しかのアスペクト?が??できません.?行しますか?",
"1039": "アスペクト? (PS2)",
"1040": "??あり",
"1041": "??なし",
"1042": "テキスト??",
"1043": "ディスプレイ",
"1044": "ディスプレイ ~D",
"1050": "MSAA",
"1051": "~DX",
"1052": "2X",
"1053": "4X",
"1054": "8X",
"1055": "16X",
"1060": "フレームレート (じっけんてき)",
"1060": "フレームレート (???)",
"1061": "60",
"1062": "100",
"1063": "150",
"1070": "LEVEL OF DETAIL (はいけい)",
"1071": "LEVEL OF DETAIL (ぜんけい)",
"1072": "さいこう",
"1073": "たかい",
"1074": "ふつう",
"1075": "ひくい",
"1076": "さいてい",
"1072": "??",
"1073": "?",
"1074": "中",
"1075": "?",
"1076": "??",
"1077": "PS2",
"1078": "じまく",
"1079": "ヒントじまく",
"1078": "??",
"1079": "ヒント??",
"1080": "チート",
"1081": "シークレット",
"1082": "きょくをせんたくする",
"1083": "スタイルをせんたくする",
"1082": "?を??する",
"1083": "スタイルを??する",
"1084": "チューンドプリカーソルロボット",
"1085": "スタッフロール",
"1086": "?????",
"1087": "ハイブリッドラーカー クロウ",
"1088": "サカナとりゲームのテーマ",
"1089": "チャレンジーのテーマ",
"1090": "むげんの青のエコ",
"1091": "むげんの赤のエコ",
"1092": "むげんの緑のエコ",
"1093": "むげんの黄のエコ",
"1094": "へんかのダクスター",
"1095": "むてき",
"1096": "すべてBGMのへんか",
"1090": "??の青のエコ",
"1091": "??の赤のエコ",
"1092": "??の緑のエコ",
"1093": "??の黄のエコ",
"1094": "?わりのダクスター",
"1095": "??",
"1096": "???トラック",
"1097": "リアルタイムオブデイ",
"1098": "100%クリア",
"1099": "ゲームクリア",
@@ -76,8 +76,8 @@
"1101": "赤の賢者",
"1102": "青の賢者",
"1103": "城のハブ",
"1104": "プリカーソルロボットの中かん",
"1105": "プリカーソルロボットのけつまつ",
"1104": "プリカーソルロボットの中?",
"1105": "プリカーソルロボットの?わり",
"1106": "スタイル 1",
"1107": "スタイル 2",
"1110": "ENGLISH (UK)",
@@ -94,37 +94,37 @@
"111b": "POLSKI",
"111c": "LIETUVIŲ KALBA",
"1500": "スピードラン モード",
"138": "しゅうへんききをぬいたり, さしたり, でんげんを きったりは しないでください",
"161": "このアイコンが あらわれているあいだ、しゅうへんききをぬいたり, さしたり, でんげんを きったりは しないでください",
"138": "????をぬいたり, さしたり, ??を?ったりは しないでください",
"161": "このアイコンが あらわれている?、????をぬいたり, さしたり, ??を?ったりは しないでください",
"100c": "オートセーブ オフ",
"100d": "オートセーブをきっても よろしいでしょうか?",
"100e": "DISABLE AUTO-SAVE",
"100f": "そのほか",
"103a": "FIT TO SCREEN",
"103b": "すいちょくどうき",
"100d": "オートセーブを?っても よろしいでしょうか?",
"100e": "オートセーブを??にする",
"100f": "その?",
"103a": "スクリーンに合わせる",
"103b": "????",
"103c": "4X3 (PS2)",
"103d": "16X9 (PS2)",
"103e": "~DX~D",
"103f": "<PAD_SQUARE> で じまくのきりかえ",
"107a": "じまくのことば",
"107b": "じまくではなしてをひょうじする",
"107c": "イツモ",
"103f": "<PAD_SQUARE> で ??の?り?え",
"107a": "??の??",
"107b": "??にスピーカーを??",
"107c": "いつも",
"107d": "いつもしなく",
"107e": "OFF-SCREEN",
"107f": "ヒントロッグ",
"107e": "オフ スクリーン",
"107f": "ヒントログ",
"109a": "ビッグヘッド ジャック",
"109b": "スモールヘッド ジャック",
"109c": "ビッグハンドジャック",
"109d": "あたまがおおきいキャラクター",
"109d": "ビッグヘッドキャラクター",
"109e": "テクスチャなしモード",
"109f": "かがみ世界",
"10a0": "でかいヘッド ジャック",
"10c0": "BGM プレイヤー",
"10c1": "SCENE PLAYER",
"109f": "??世界",
"10a0": "ビッグヘッド ジャック",
"10c0": "ミュージックプレイヤー",
"10c1": "プレイヤーを??",
"10c2": "スタッフロール",
"10c3": "スクラップブック",
"10d0": "デフォルト",
"10d1": "みしよう",
"10d1": "???",
"10d2": "セイジィ",
"10d3": "セイジィの家",
"10d4": "小鳥のオバチャマ",
@@ -1,6 +1,9 @@
{
"cutscenes": {},
"other": {
"DSbop001": [
"Tu as l'air vraiment en colère, Jak."
],
"agnt001": [
"Hé, conduisez prudemment !"
],
@@ -2016,22 +2019,22 @@
"Les scanners indiquent des oeufs de Metal Heads toujours actifs."
],
"daxm001": [
"Shoot the platform, Jak."
"Vise la plateforme, Jak."
],
"daxm002": [
"We need something to get through that gate!"
"Il nous faut quelque chose pour passer ce portail !"
],
"daxm003": [
"Shoot the Metal Head when he moves his shield!"
"Tire sur le Metal Head dès qu'il bouge son bouclier !"
],
"daxm004": [
"Hit him in his stomach!"
"Vise l'estomac !"
],
"daxm005": [
"Whoa! That path dropped like uh... a rock!"
"Waouh, ce sentier plonge... à pic !"
],
"daxm006": [
"Smack the box, baby!"
"Trop de la balle, mon chou !"
],
"daxm007": [
"That's what I call a rocky road!"
@@ -2040,10 +2043,10 @@
"We gotta get to the top!"
],
"daxm009": [
"We made it!!"
"On l'a fait !!"
],
"daxm010": [
"Rock 'n roll!"
"Le délire !"
],
"ds001": [
"On doit trouver le Baron, Jak."
@@ -6553,18 +6556,6 @@
"kwbf042": [
"Arghh ! Espèce de... !"
],
"mtn-plat-buried-rocks-a": [
"*Tremblement de terre*"
],
"mtn-step-plat-rocks-a": [
"*Une plateforme apparait dans le mur*"
],
"mtn-step-plat-rocks-b": [
"*Des plateformes apparaissent dans le mur*"
],
"mtn-step-plat-rocks-c": [
"*Des plateformes apparaissent dans le mur et le rocher*"
],
"ora006": [
"Rapportez-moi encore 200 Gemmes Crâniennes de Metal Heads",
"et je vous montrerai une autre énergie noire."
@@ -7559,12 +7550,6 @@
"c'est sûrement quelque chose de précieux.",
"Vous devriez jeter un oeil."
],
"tombplta": [
"*Les pilliers prennent de la hauteur*"
],
"tombpltb": [
"*Un escalier apparait et s'assemble*"
],
"tor001": [
"L'opération est un véritable succès. Tous les membres des Souterrains sont sains et saufs.",
"Rentrez à la cachette, j'ai une nouvelle mission à vous confier en attendant que ça se calme."
@@ -7806,12 +7791,6 @@
"Ils entrent de force !!",
"Ils sont trop nombreux !! Jak !!! AHHHH !!!"
],
"wtrdrain": [
"*L'eau se vide du SAS*"
],
"wtrfill": [
"*Le SAS se remplit d'eau*"
],
"ys001": [
"Excellent les gars ! Revenez à la cachette,",
"j'ai une autre mission pour vous."
@@ -7850,7 +7829,7 @@
"mog": "Mog",
"onin": "Onin",
"oracle": "Oracle",
"pecker": "Pecker",
"pecker": "Mog",
"precursor": "Precurseur",
"samos": "Samos",
"sig": "Sig",
File diff suppressed because it is too large. Load diff
@@ -5,14 +5,14 @@
"You sure seem angry, Jak."
],
"DSbop002": [
"Do you remember how to jump?"
"ジャンプできる?"
],
"DSbop003": [
"Jump onto that crate to get over the barricade."
],
"DSbop004": [
"Ooh, that's a high ledge!",
"Try jumping once, then jump again while in the air",
"デカイ段差!ジャンプして空中でもう一度ジャンプだよ!!",
"to reach that one."
],
"DSbop005": [
@@ -1705,7 +1705,7 @@
"This sector is closed."
],
"cityv039": [
"Alert: Prison escape in progress."
"警告:脱獄者が発生"
],
"cityv040": [
"Alert: City under attack."
@@ -2128,7 +2128,7 @@
"Break those tubes in the center."
],
"ds020": [
"Please tell me you remember how to roll..."
"なあ転がり方、覚えてる?"
],
"ds023": [
"Let's rock!"
File diff suppressed because it is too large. Load diff
@@ -65,50 +65,6 @@
}
]
},
"mtn-plat-buried-rocks-a": {
"lines": [
{
"frame_end": 168,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"mtn-step-plat-rocks-a": {
"lines": [
{
"frame_end": 88,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"mtn-step-plat-rocks-b": {
"lines": [
{
"frame_end": 92,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"mtn-step-plat-rocks-c": {
"lines": [
{
"frame_end": 80,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"sam001": {
"lines": [
{
@@ -170,50 +126,6 @@
}
]
},
"tombplta": {
"lines": [
{
"frame_end": 129,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"tombpltb": {
"lines": [
{
"frame_end": 350,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"wtrdrain": {
"lines": [
{
"frame_end": 163,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"wtrfill": {
"lines": [
{
"frame_end": 165,
"frame_start": 0,
"merge": false,
"offscreen": true,
"speaker": "none"
}
]
},
"ys002": {
"lines": [
{
@@ -1,16 +1,16 @@
{
"1a3": "Bitte entferne oder verbinde kein Zubehör und schalte nicht das System oder Spiel aus",
"1a3": "Bitte entferne oder verbinde kein Zubehör und schalte weder das System noch das Spiel aus",
"1b5": "Während dieses Symbol angezeigt wird, entferne oder verbinde kein Zubehör und schalte nicht das System oder das Spiel aus",
"1100": "Nicht in einer Mission",
"1100": "Keine Mission",
"1101": "Spielt eine Bonusmission",
"1102": "Blaster-Trainingskurs",
"1102": "Scatter Waffen-Training",
"1103": "Blaster-Trainingskurs",
"1104": "Vulcan-Fury-Trainingskurs",
"1105": "Friedensstifter-Trainingskurs",
"1106": "Onins Spiel",
"1107": "Metal Head Matsch",
"1200": "Anzeigemodus",
"1201": "Fenster",
"1201": "Fenstermodus",
"1202": "Vollbild",
"1203": "Randlos",
"1204": "Automatisch",
@@ -28,7 +28,7 @@
"1210": "Breite",
"1211": "Höhe",
"1212": "??????????",
"1213": "Jetzt spielt...",
"1213": "Wird gerade gespielt...",
"1214": "Kein Titel",
"1215": "Standard",
"1216": "Morph-Waffe",
@@ -1,12 +1,12 @@
{
"1a3": "Sauvegarde en cours. Veuillez à ne retirer ou n'insérer aucun périphérique, ni éteindre votre système ou arrêter le jeu.",
"1b5": "Lorsque cette icône est à l'écran, ne retirez ou n'insérez aucun périphérique, ni éteindre votre système ou arrêter le jeu.",
"1100": "Pas dans une mission",
"1a3": "Sauvegarde en cours. Veillez à ne retirer ou n'insérer aucun périphérique, ni éteindre votre système ou arrêter le jeu.",
"1b5": "Lorsque cette icône apparait, ne retirez ou n'insérez aucun périphérique, ni éteindre votre système ou arrêter le jeu.",
"1100": "Pas en mission",
"1101": "Jouer une mission bonus",
"1102": "Pulvérisator (Entrainement)",
"1103": "Blaster (Entrainement)",
"1104": "Vulcanobarillet (Entrainement)",
"1105": "Pacificateur (Entrainement)",
"1102": "Pulvérisator (Entraînement)",
"1103": "Blaster (Entraînement)",
"1104": "Vulcanobarillet (Entraînement)",
"1105": "Pacificateur (Entraînement)",
"1106": "Le jeu d'Onin",
"1107": "Chasse-taupe",
"1200": "Mode d'affichage",
@@ -113,7 +113,7 @@
"1266": "Réduire la population d'Abriville de ~D",
"1267": "Réduire le nombre de véhicules d'Abriville de ~D",
"1268": "Chassez toutes les espèces de Metal Head",
"1269": "Use the JET-Board to break open containers",
"1269": "Utilisez le JET-Board pour casser les caisses",
"126a": "Transport the Rift Rider while leaving Samos and Young Samos unscathed",
"1280": "Options de caméra",
"1281": "Horizontal (1ère Personne)",
@@ -155,24 +155,24 @@
"12a5": "Bestiaire",
"12a6": "Autres statistiques",
"12a7": "Total Tué",
"12a8": "Killed by Jak",
"12a9": "Killed by Dark Jak",
"12aa": "Killed by Daxter",
"12ab": "Killed by Others",
"12a8": "Tué par Jak",
"12a9": "Tué par Dark Jak",
"12aa": "Tué par Daxter",
"12ab": "Tué par d'autres",
"12ac": "Blaster",
"12ad": "Scatter Gun",
"12ae": "Vulcan Fury",
"12af": "Peacemaker",
"12ad": "Pulvérisator",
"12ae": "Vulcanobarillet",
"12af": "Pacificateur",
"12b0": "JET-Board",
"12b1": "JET-Board Trick",
"12b2": "Titan Suit Punch",
"12b3": "Titan Suit Body",
"12b1": "Figure de JET-Board",
"12b2": "Coup de poing de la Combinaison Titan",
"12b3": "Combinaison Titan",
"12b4": "Gunpod",
"12b5": "Punch",
"12b5": "Coup de poing",
"12b6": "Flop",
"12b7": "Uppercut",
"12b8": "Spin",
"12b9": "Roll",
"12b9": "Rouler",
"12bf": "Dark Bomb",
"12c0": "Dark Blast",
"12c3": "Grenagarde",
@@ -230,7 +230,7 @@
"1334": "Actor Culling",
"1335": "Force Environment Mapping",
"1336": "Menu de pause rapide",
"1337": "PS2 LOD Distance",
"1338": "Off",
"1337": "Distance du niveau de détail PS2",
"1338": "Non",
"1339": "Écran"
}
+156 -156
View File
@@ -1,46 +1,46 @@
{
"1a3": "しゅうへんききをぬいたり, さしたり, でんげんを きったりは しないでください",
"1b5": "このアイコンが あらわれているあいだ、しゅうへんききをぬいたり, さしたり, でんげんを きったりは しないでください",
"1100": "Not in a mission",
"1101": "Playing a bonus mission",
"1102": "Scatter Gun Training Course",
"1103": "Blaster Training Course",
"1104": "Vulcan Fury Training Course",
"1105": "Peace Maker Training Course",
"1106": "Onin Game",
"1107": "Metal Head Mash",
"1200": "スクリーンモード",
"1a3": "??機器をぬいたり, さしたり, 電源を切ったりは しないでください",
"1b5": "このアイコンが あらわれている間、??機器をぬいたり, さしたり, 電源を切ったりは しないでください",
"1100": "ミッションがありません",
"1101": "ボーナスミッションをプレイする",
"1102": "レッドバースト・ガン トレーニングコース",
"1103": "イエローブラスター・ガン トレーニングコース",
"1104": "ブルーバルカン・ガン トレーニングコース",
"1105": "ピースメーカー トレーニングコース",
"1106": "オニンゲーム",
"1107": "メタルたたき",
"1200": "ディスプレイモード",
"1201": "ウィンドウ",
"1202": "フルスクリーン",
"1203": "ボーダレス",
"1204": "Automatic",
"1205": "Custom",
"1204": "自動",
"1205": "カスタム",
"1206": "4x3 (PS2)",
"1207": "16x9 (PS2)",
"1208": "Choose width and height ratio",
"1209": "Press <PAD_X> to confirm and exit.",
"120a": "Press <PAD_CIRCLE> to confirm and exit.",
"120b": "Ratio must not be lower than 4x3!",
"120c": "BGMプレイヤー",
"120d": "すいちょくどうき",
"1208": "?と高さの??を選?",
"1209": "<PAD_X> を押して??して終了します",
"120a": "<PAD_CIRCLE> を押して??して終了します",
"120b": "??は4x3より低くてはなりません!",
"120c": "ミュージックプレイヤー",
"120d": "????",
"120e": "テキストの言語",
"120f": "OpenGOAL Secrets",
"1210": "Width",
"1211": "Height",
"120f": "OpenGOALシークレット",
"1210": "??",
"1211": "高さ",
"1212": "??????????",
"1213": "Now playing...",
"1214": "No Track",
"1214": "トラックなし",
"1215": "デフォルト",
"1216": "モーフィング・ガン",
"1217": "ジェットボード",
"1218": "タイタンスーツ",
"1219": "ダークジャック",
"121a": "乗り物",
"121b": "Danger",
"121b": "??",
"121c": "None",
"121d": "Low",
"121e": "Medium",
"121f": "High",
"121d": "低",
"121e": "中",
"121f": "高",
"1220": "Haven Exploration",
"1221": "Guard Pursuit",
"1222": "Ram Head Battle (Alt)",
@@ -65,172 +65,172 @@
"1235": "Weapons Factory",
"1236": "Arena Race",
"1237": "Dead Town",
"1238": "Window Size",
"1239": "Select Window Size",
"123a": "かいぞうど",
"123b": "Select Game Resolution",
"123c": "Level Of Detail (はいけい)",
"123d": "Level Of Detail (ぜんけい)",
"123f": "じまくではなしてをひょうじする",
"1238": "ウィンドウサイズ",
"1239": "ウィンドウサイズを選?",
"123a": "解像?",
"123b": "ゲーム解像?を選?",
"123c": "???(バックグラウンド)",
"123d": "???(フォアグラウンド)",
"123f": "字幕にスピーカーを表示",
"1240": "いつもしなく",
"1241": "Off-Screen",
"1242": "イツモ",
"1243": "ゲームのこくど",
"1241": "オフスクリーン",
"1242": "?時",
"1243": "ゲーム地?",
"1244": "アメリカ(SCEA)",
"1245": "ヨーロッパ(SCEE)",
"1246": "にほん(SCEI)",
"1247": "かんこく(SCEK)",
"1248": "MSAA",
"1249": "~DX",
"124a": "Controller LED Options",
"124b": "Show Player State",
"124c": "Show Amount of Health",
"124a": "コントローラーLEDオプション",
"124b": "プレイヤーステータスを表示",
"124c": "?力を表示",
"124d": "オートセーブを無?にする",
"124e": "オートセーブ オフ",
"124f": "オートセーブをきっても よろしいでしょうか?",
"1250": "Turbo JET-Board in Haven City",
"1251": "Enemy Health Bars",
"1252": "Vehicle Health Bars",
"1253": "Vehicle Invulnerability",
"1254": "Statistics",
"1255": "Automatically Grab Collectables",
"1256": "Music Player",
"1257": "No Textures Mode",
"1258": "Fast Movies",
"1259": "Slow Movies",
"125a": "Fast Gameplay",
"125b": "Slow Gameplay",
"125c": "Instant Travel in Haven City",
"125d": "Precursor Orb Tracker",
"1250": "ヘイブンシティのターボジェットボード",
"1251": "敵の?力バー",
"1252": "??の?力バー",
"1253": "??の無敵",
"1254": "????",
"1255": "コレクションを自動?に??する",
"1256": "ミュージックプレイヤー",
"1257": "テクスチャなしモード",
"1258": "?いムービー",
"1259": "?いムービー",
"125a": "高?ゲームプレイ",
"125b": "低?ゲームプレイ",
"125c": "ヘイブンシティの???行",
"125d": "プリカーソルオーブトラッカー",
"125e": "リアルタイムオブデイ",
"125f": "Pacified Haven City",
"1260": "JET-Board Trick Display",
"1261": "Bad Weather",
"1262": "Nice Weather",
"1263": "Vehicle Hijack Voice Lines",
"1264": "Locked",
"1265": "Hit all 3 valves and find Mar's Statue in \"~S\" in under ~D seconds",
"1266": "Reduce Haven City's population count by ~D",
"1267": "Reduce Haven City's vehicle count by ~D",
"1268": "Hunt every species of Metal Head",
"1269": "Use the JET-Board to break open containers",
"126a": "Transport the Rift Rider while leaving Samos and Young Samos unscathed",
"125f": "??なヘブンシティ",
"1260": "ジェットボードトリックディスプレイ",
"1261": "?い天?",
"1262": "?い天?",
"1263": "??ハイジャック??ライン",
"1264": "ロック中",
"1265": "3つのバルブをすべてヒットさせ、~D秒以内に?~S?のマールの像を見つける",
"1266": "ヘブンシティの??を~D人?らす",
"1267": "ヘブンシティの??を~D台?らす",
"1268": "??な種?のメタルヘッドを?る",
"1269": "ジェットボードを使って開いているコンテナを破壊する",
"126a": "セイジィと?いセイジィを無?のままリフト・ライダーまで輸送する",
"1280": "カメラ オプション",
"1281": "Left/Right (1st Person)",
"1282": "Up/Down (1st Person)",
"1283": "Left/Right (3rd Person)",
"1284": "Up/Down (3rd Person)",
"1285": "Reset to Default",
"1281": "左/右 (1人?)",
"1282": "上/下(1人?)",
"1283": "左/右 (3人?)",
"1284": "上/下(3人?)",
"1285": "デフォルトに戻す",
"1286": "ノーマル",
"1287": "リバース",
"1288": "パーティクル カリング",
"1289": "Discordリッチプレゼンス",
"128a": "Default",
"128b": "Low",
"128c": "High",
"128d": "Credits",
"128a": "デフォルト",
"128b": "低",
"128c": "高",
"128d": "クレジット",
"128e": "フレームレート",
"128f": "そのほか",
"128f": "その?",
"1290": "スピードラン モード",
"1291": "Input Options",
"1292": "リセット デフォルト",
"1293": "コントローラオプション",
"1294": "コントローラをせんたくする",
"1295": "Analog Deadzone",
"1296": "Ignore If Window Unfocused",
"1297": "コントローラのLedでたい力をひょうじする",
"1298": "Use LED for Other States",
"1299": "Enable Keyboard",
"129a": "Enable Mouse",
"1291": "入力??",
"1292": "????に戻す",
"1293": "コントローラーオプション",
"1294": "コントローラーを選?する",
"1295": "アナログデッドゾーン",
"1296": "ウィンドウのフォーカスが外れているときは無?する",
"1297": "コントローラーのLEDで?力を表示する",
"1298": "LEDを?の??で使用",
"1299": "キーボードを??にする",
"129a": "マウスを??にする",
"129b": "マウスオプション",
"129c": "Track Camera",
"129d": "Horizontal Sensitivity",
"129e": "Vertical Sensitivity",
"129f": "Player Movement",
"12a0": "Object Shadows",
"12a1": "Normal",
"12a2": "Extended",
"12a3": "No valid resolutions found.",
"12a4": "Automatic",
"12a5": "Bestiary",
"12a6": "Other Statistics",
"12a7": "Total Killed",
"12a8": "Killed by Jak",
"12a9": "Killed by Dark Jak",
"12aa": "Killed by Daxter",
"12ab": "Killed by Others",
"12ac": "Blaster",
"12ad": "Scatter Gun",
"12ae": "Vulcan Fury",
"12af": "Peacemaker",
"12b0": "JET-Board",
"12b1": "JET-Board Trick",
"12b2": "Titan Suit Punch",
"12b3": "Titan Suit Body",
"12b4": "Gunpod",
"12b5": "Punch",
"12b6": "Flop",
"12b7": "Uppercut",
"12b8": "Spin",
"12b9": "Roll",
"12bf": "Dark Bomb",
"12c0": "Dark Blast",
"12c3": "Krimzon Guard",
"12c4": "Sig",
"12c5": "Ashelin",
"12c6": "Jinx",
"12c7": "Grim",
"12c8": "Mog",
"12c9": "Metal Heads",
"12ca": "Other Friends",
"12cb": "Other Enemies",
"1300": "Auto Hide Cursor",
"1301": "Reassign Binds",
"129c": "?跡カメラ",
"129d": "水?感?",
"129e": "??感?",
"129f": "プレイヤーの?動",
"12a0": "オブジェクトの?",
"12a1": "ノーマル",
"12a2": "??",
"12a3": "??な解像?が見つかりませんでした",
"12a4": "自動",
"12a5": "ベスティアリー",
"12a6": "その?の????",
"12a7": "?キル数",
"12a8": "ジャックに倒された",
"12a9": "ダークジャックに倒された",
"12aa": "ダクスターに倒された",
"12ab": "?者に倒された",
"12ac": "イエローブラスター",
"12ad": "レッドバースト",
"12ae": "ブルーバルカン",
"12af": "ピースメーカー",
"12b0": "ジェットボード",
"12b1": "ジェットボードトリック",
"12b2": "タイタンスーツのパンチ",
"12b3": "タイタンスーツのボディ",
"12b4": "砲撃台",
"12b5": "パンチ",
"12b6": "フロップ",
"12b7": "アッパーカット",
"12b8": "スピン",
"12b9": "ロール",
"12bf": "ダークボム",
"12c0": "ダークブラスト",
"12c3": "クリムゾンガード",
"12c4": "ジーグ",
"12c5": "アシュリン",
"12c6": "ジンクス",
"12c7": "グリム",
"12c8": "モグ",
"12c9": "メタルヘッド",
"12ca": "?の友?",
"12cb": "?の敵",
"1300": "自動でカーソルを?す",
"1301": "バインドの??り?て",
"1302": "コントローラのバインド",
"1303": "キーボードのバインド",
"1304": "マウスのバインド",
"1305": "No Options",
"1306": "Waiting",
"1307": "みけってい",
"1308": "?られていない",
"1309": "High-Resolution Sky",
"130a": "Fast Airlocks and Doors",
"130b": "Fast Elevators",
"130c": "Speedrun",
"1305": "オプションなし",
"1306": "?機中",
"1307": "???",
"1308": "??",
"1309": "高解像?の空",
"130a": "高?エアロックとドア",
"130b": "高?エレベーター",
"130c": "スピードラン",
"130d": "Any%",
"130e": "Any% - Hoverless",
"130f": "All Missions",
"1310": "100%",
"1311": "Any% - All Orbs",
"1312": "Any% - Hero Mode",
"1313": "Local Time",
"1314": "Warning!",
"1315": "This setting is highly experimental. When not played at 60 frames per second, visual and gameplay issues may arise as a result.",
"1316": "Local Score",
"1313": "ローカルタイム",
"1314": "警告!",
"1315": "この??は??に???なものです.?秒60フレームで??されていない場合、???な??やゲームプレイの??が発?する?能性があります.",
"1316": "ローカルスコア",
"1320": "なし",
"1321": "スピン",
"1322": "ブースト",
"1323": "フリップ",
"1324": "レールグラインド",
"1325": "レールジャンプ",
"1326": "Nosegrab",
"1327": "Method",
"1326": "ノーズグラブ",
"1327": "メソッド",
"1328": "ボードスピン",
"1329": "ボードフリップ",
"132a": "Noseflip",
"132a": "ノーズフリップ",
"132b": "キックフリップ",
"132c": "ジャンプ",
"132d": "Duck Jump",
"132e": "Quick Jump",
"132d": "ダックジャンプ",
"132e": "クイックジャンプ",
"132f": "ダークジャック",
"1330": "Dark Bomb",
"1331": "Dark Blast",
"1332": "Dark Giant",
"1333": "PS2 Options",
"1334": "Actor Culling",
"1335": "Force Environment Mapping",
"1336": "Fast Progress Menu",
"1337": "PS2 LOD Distance",
"1338": "Off",
"1339": "Display"
"1330": "ダークボム",
"1331": "ダークブラスト",
"1332": "ダークジャイアント",
"1333": "PS2オプション",
"1334": "アクターカリング",
"1335": "?制?に??マッピング",
"1336": "高?進行??メニュー",
"1337": "PS2 LOD ??",
"1338": "オフ",
"1339": "ディスプレイ"
}
+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
+33
View File
@@ -0,0 +1,33 @@
#pragma once
namespace jak3 {
void jak3_overlord_init_globals_basefilesystem();
struct ISOFileDef;
struct ISOName;
struct CBaseFile;
struct VagDirEntry;
constexpr int kMaxOpenFiles = 16;
/*!
* Base class for "FileSystem", which supports finding and opening files.
* The only implementation we have is CISOCDFileSystem
*/
struct CBaseFileSystem {
CBaseFileSystem();
virtual ~CBaseFileSystem() = default;
// semaphores for processing open files
int m_Sema[kMaxOpenFiles];
virtual int Init() = 0;
// polldrive
virtual ISOFileDef* Find(const char* name) = 0;
virtual ISOFileDef* FindIN(const ISOName* name) = 0;
virtual int GetLength(const ISOFileDef* file) = 0;
virtual CBaseFile* Open(const ISOFileDef* file_def, int sector_offset, int file_kind) = 0;
virtual CBaseFile* OpenWAD(const ISOFileDef* file_def, int page_offset) = 0;
virtual VagDirEntry* FindVAGFile(const char* name) = 0;
};
} // namespace jak3
+526
View File
@@ -0,0 +1,526 @@
#include "dma.h"
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "game/overlord/jak3/basefile.h"
#include "game/overlord/jak3/overlord.h"
#include "game/overlord/jak3/vag.h"
#include "game/sce/iop.h"
#include "game/sound/sdshim.h"
#include "game/sound/sndshim.h"
#define VOICE_BIT(voice) (1 << ((voice) >> 1))
namespace jak3 {
using namespace iop;
namespace {
// most recent call to voice_trans_wrapper's arguments
u32 g_voiceTransMode = 0;
u32 g_voiceTransSize = 0;
s16 g_voiceTransChannel = 0;
const void* g_voiceTransAddr = nullptr;
u32 g_voiceTransSpuAddr = 0;
// if we've started a transfer recently
bool g_voiceTransRunning = false;
// when that transfer was started
u32 g_voiceTransTime = 0;
// despite the name, this is really an indicator that the SPU streaming system is waiting
// for a SPU interrupt on completion.
bool g_bSpuDmaBusy = false;
int g_nSpuDmaChannel = 0;
ISO_VAGCommand* g_pDmaVagCmd = nullptr;
ISO_VAGCommand* g_pDmaStereoVagCmd = nullptr;
int g_nSpuDmaChunks = 0;
std::array<DmaQueueEntry, 16> g_aSpuDmaQueue;
int g_nSpuDmaQueueHead = 0;
int g_nSpuDmaQueueTail = 0;
int g_nSpuDmaQueueCount = 0;
struct DmaInterruptHandlerHack {
s32 chan = 0;
sceSdTransIntrHandler cb = nullptr;
void* data;
int countdown = 0;
} g_DmaInterruptHack;
} // namespace
void jak3_overlord_init_globals_dma() {
g_voiceTransMode = 0;
g_voiceTransSize = 0;
g_voiceTransChannel = 0;
g_voiceTransAddr = nullptr;
g_voiceTransSpuAddr = 0;
g_voiceTransRunning = false;
g_voiceTransTime = 0;
g_bSpuDmaBusy = false;
g_nSpuDmaChannel = 0;
g_pDmaVagCmd = nullptr;
g_pDmaStereoVagCmd = nullptr;
g_nSpuDmaChunks = 0;
g_aSpuDmaQueue = {};
g_nSpuDmaQueueHead = 0;
g_nSpuDmaQueueCount = 0;
g_nSpuDmaQueueTail = 0;
g_DmaInterruptHack = {};
}
// The DMA callback hack below is used to defer dma completion "interrupts" until the next run
// of the ISO Thread. This avoids re-entry type problems where the original design would set off
// a dma transfer in the completion handler of the previous transfer, and expect a few instructions
// to run after.
void uninstall_dma_intr() {
g_DmaInterruptHack = {};
}
void set_dma_intr_handler_hack(s32 chan, sceSdTransIntrHandler cb, void* data) {
ASSERT(!g_DmaInterruptHack.cb);
g_DmaInterruptHack.chan = chan;
g_DmaInterruptHack.cb = cb;
g_DmaInterruptHack.data = data;
g_DmaInterruptHack.countdown = 10;
}
int SPUDmaIntr(int channel, void* userdata);
void dma_intr_hack() {
if (g_DmaInterruptHack.countdown) {
g_DmaInterruptHack.countdown--;
if (g_DmaInterruptHack.countdown == 0) {
int chan = g_DmaInterruptHack.chan;
void* data = g_DmaInterruptHack.data;
g_DmaInterruptHack = {};
SPUDmaIntr(chan, data);
}
}
}
/*!
* This function is used to set up a DMA transfer to SPU DMA.
*
* This wrapper was added very close to the end of Jak 3's development.
*
* I believe it basically checks for dma transfers that are somehow "dropped", and retries them.
* Since I don't think our IOP framework will ever do this, we have an assert if the dropped logic
* ever goes off.
*/
int voice_trans_wrapper(s16 chan, u32 mode, const void* iop_addr, u32 spu_addr, u32 size) {
// remember the transfer settings. If there's a transfer in progress, so we can't start here,
// we'll use these to start the transfer later.
g_voiceTransMode = mode;
g_voiceTransSize = size;
g_voiceTransChannel = chan;
g_voiceTransAddr = iop_addr;
g_voiceTransSpuAddr = spu_addr;
if (g_voiceTransRunning) {
// I claim this should never happen, and this is their workaround for a bug.
ASSERT_NOT_REACHED();
return -0xd2; // busy
} else {
g_voiceTransRunning = true;
g_voiceTransTime = GetSystemTimeLow();
return sceSdVoiceTrans(chan, mode, iop_addr, spu_addr, size);
}
}
u32 read_rate_calc(u32 pitch) {
u64 pitch1 = (pitch >> 3);
u64 mult_result = pitch1 * 0x2492'4925ull;
return mult_result >> 32;
}
/*!
* The worst function of all time - the SPU DMA completion interrupt.
*/
int SPUDmaIntr(int channel, void* userdata) {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr enter! {} 0x{:x}", channel, (u64)userdata);
if (!g_bSpuDmaBusy) {
// we got an interrupt, but weren't expecting it, or no longer have the need for the data.
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - not busy");
return 0;
}
if (channel != g_nSpuDmaChannel) {
// interrupt was for the wrong channel, somehow.
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - not our channel ??");
return 0;
}
// since we're in the completion handler, we know that there is no voice trans (SPU DMA) running.
g_voiceTransRunning = false;
// This next block will handle updating the playback command that triggered this dma:
if (g_pDmaVagCmd) {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDma for cmd {}", g_pDmaVagCmd->name);
if (!g_pDmaStereoVagCmd) {
// non-stereo audio
// set a flag to indicate even/odd number of chunks have been dma'd
if ((g_nSpuDmaChunks & 1) == 0) {
g_pDmaVagCmd->flags.dma_complete_even_chunk_count = 1;
} else {
g_pDmaVagCmd->flags.dma_complete_odd_chunk_count = 1;
}
} else {
// stereo audio. This requires two uploads, one for left/right audio. If we've finished the
// first, start the second one here:
if (g_pDmaStereoVagCmd->xfer_size) {
// parameters for second upload
int chan = g_pDmaVagCmd->dma_chan;
const u8* iop_addr = g_pDmaStereoVagCmd->dma_iop_mem_ptr;
int size = g_pDmaStereoVagCmd->xfer_size;
// SPU addr - toggle the buffer based on stereo side:
// TODO: better explanation of why this picks the correct buffer.
int spu_addr;
if ((g_nSpuDmaChunks & 1) == 0) {
spu_addr = g_pDmaStereoVagCmd->stream_sram;
} else {
spu_addr = g_pDmaStereoVagCmd->stream_sram + 0x2000;
}
// these lines reordered to possibly support immediate dma completion callback??
// clear flag so we know not to transfer the next part
g_pDmaStereoVagCmd->xfer_size = 0;
g_pDmaStereoVagCmd->dma_iop_mem_ptr = nullptr;
// start next transfer
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr starting stereo sibling transfer");
set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, userdata);
voice_trans_wrapper(chan, 0, iop_addr, spu_addr, size);
return 0;
}
// second stereo upload completed - update double-buffering flags
if ((g_nSpuDmaChunks & 1) == 0) {
g_pDmaVagCmd->flags.dma_complete_even_chunk_count = 1;
g_pDmaStereoVagCmd->flags.dma_complete_even_chunk_count = 1;
} else {
g_pDmaVagCmd->flags.dma_complete_odd_chunk_count = 1;
g_pDmaStereoVagCmd->flags.dma_complete_odd_chunk_count = 1;
}
}
// if this is the first chunk, we'll start the actual audio here:
// lg::warn("----------> interrupt with chunks {}\n", g_nSpuDmaChunks);
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks count {}", g_nSpuDmaChunks);
if (g_nSpuDmaChunks == 0) {
// compute pitch/playback rate
int pitch = CalculateVAGPitch(g_pDmaVagCmd->pitch1, g_pDmaVagCmd->pitch_cmd);
ASSERT(pitch == (pitch & 0xffff));
// inform the ISO system how fast we're reading
if (g_pDmaVagCmd->m_pBaseFile) {
// unlike actual playback, this is done with the pitch1 value from the file itself - so if
// we speed up/slow down stuff in debug, it won't change streaming modes
const int pitch_from_file =
CalculateVAGPitch(g_pDmaVagCmd->pitch1_file, g_pDmaVagCmd->pitch_cmd);
int rate = g_pDmaStereoVagCmd ? pitch_from_file * 0x2ee : pitch_from_file * 0x177;
g_pDmaVagCmd->m_pBaseFile->m_ReadRate = read_rate_calc(rate);
}
// start!
u32 voice_mask = 0;
if (!g_pDmaStereoVagCmd) {
// forget any previous spu address
g_pDmaVagCmd->current_spu_address = 0;
static_assert(SD_VA_SSA == 0x2040);
static_assert(SD_S_KOFF == 0x1600);
static_assert(SD_S_KON == 0x1500);
static_assert(SD_VP_ADSR1 == 0x300);
static_assert(SD_VP_ADSR2 == 0x400);
static_assert(SD_VP_PITCH == 0x200);
// before touching SPU2 hardware, wait for voice safety:
BlockUntilVoiceSafe(g_pDmaVagCmd->voice, 0x900);
// set address and ADSR settings
sceSdSetAddr(g_pDmaVagCmd->voice | SD_VA_SSA, g_pDmaVagCmd->stream_sram + 0x30);
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR1, 0xff);
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
if (g_pDmaVagCmd->flags.paused) {
pitch = 0;
}
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, pitch);
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice);
} else {
// forget any previous spu address
g_pDmaVagCmd->current_spu_address = 0;
g_pDmaStereoVagCmd->current_spu_address = 0;
// wait for voices to be safe to adjust
BlockUntilVoiceSafe(g_pDmaVagCmd->voice, 0x900);
BlockUntilVoiceSafe(g_pDmaStereoVagCmd->voice, 0x900);
// set voice params
sceSdSetAddr(g_pDmaVagCmd->voice | SD_VA_SSA, g_pDmaVagCmd->stream_sram + 0x30);
sceSdSetAddr(g_pDmaStereoVagCmd->voice | SD_VA_SSA, g_pDmaStereoVagCmd->stream_sram + 0x30);
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR1, 0xff);
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_ADSR1, 0xff);
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_ADSR2, 0x1fc0);
if (g_pDmaVagCmd->flags.paused) {
pitch = 0;
}
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, pitch);
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_PITCH, pitch);
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice) | VOICE_BIT(g_pDmaStereoVagCmd->voice);
}
// do key-on or key-off
if (g_pDmaVagCmd->flags.paused) {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 0, key off");
BlockUntilAllVoicesSafe();
sceSdSetSwitch(SD_S_KOFF | (g_pDmaVagCmd->voice & 1), voice_mask);
} else {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 0, key on");
BlockUntilAllVoicesSafe();
sceSdSetSwitch(SD_S_KON | (g_pDmaVagCmd->voice & 1), voice_mask);
}
// remember the time of the key-on/off. This is used to avoid sending voice commands
// quickly, which somehow confuses the sound hardware.
auto sys_time = GetSystemTimeLow();
MarkVoiceKeyedOnOff(g_pDmaVagCmd->voice, sys_time);
if (g_pDmaStereoVagCmd) {
MarkVoiceKeyedOnOff(g_pDmaStereoVagCmd->voice, sys_time);
}
} else if (g_nSpuDmaChunks == 1) {
g_pDmaVagCmd->flags.saw_chunks1 = 1;
if (g_pDmaStereoVagCmd) {
g_pDmaStereoVagCmd->flags.saw_chunks1 = 1;
}
if (g_pDmaVagCmd->flags.paused) {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 1, pausing");
u32 voice_mask = 0;
if (!g_pDmaStereoVagCmd) {
// pause by setting pitches to 0
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, 0);
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaVagCmd->voice), 0x900);
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice);
} else {
sceSdSetParam(g_pDmaStereoVagCmd->voice | SD_VP_PITCH, 0);
sceSdSetParam(g_pDmaVagCmd->voice | SD_VP_PITCH, 0);
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaVagCmd->voice), 0x900);
BlockUntilVoiceSafe(VOICE_BIT(g_pDmaStereoVagCmd->voice), 0x900);
voice_mask = VOICE_BIT(g_pDmaVagCmd->voice) | VOICE_BIT(g_pDmaStereoVagCmd->voice);
}
// switch off
BlockUntilAllVoicesSafe();
sceSdSetSwitch(SD_S_KOFF | (g_pDmaVagCmd->voice & 1), voice_mask);
auto sys_time = GetSystemTimeLow();
MarkVoiceKeyedOnOff(g_pDmaVagCmd->voice, sys_time);
if (g_pDmaStereoVagCmd) {
MarkVoiceKeyedOnOff(g_pDmaStereoVagCmd->voice, sys_time);
}
} else {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr chunks 1, unpausing by call to UnPauseVAG");
g_pDmaVagCmd->flags.paused = 1;
UnPauseVAG(g_pDmaVagCmd);
}
}
// now that we've processed the command from this interrupt, mark it as safe to modify
g_pDmaVagCmd->safe_to_modify_dma = 1;
if (g_pDmaStereoVagCmd) {
g_pDmaStereoVagCmd->safe_to_modify_dma = 1;
}
// and forget it!
g_pDmaVagCmd = nullptr;
g_pDmaStereoVagCmd = nullptr;
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr dma handling of VAG cmd is complete");
}
// release ref on this page. (interestingly, not a dma ref...)
if (userdata) {
CPage* page = (CPage*)userdata;
int ret = page->ReleaseRef();
ASSERT(ret >= 0);
}
// now - see if we have another queued dma transfer
ASSERT(g_nSpuDmaQueueCount >= 0);
if (g_nSpuDmaQueueCount == 0) {
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr dma queue is empty, disabling interrupt");
// we're done!
// set_dma_intr_handler_hack(channel, nullptr, nullptr);
uninstall_dma_intr();
// if (-1 < channel) {
// snd_FreeSPUDMA(channel);
// }
g_bSpuDmaBusy = false;
} else {
ovrld_log(LogCategory::SPU_DMA_STR,
"SPUDmaIntr dma queue is not empty, preparing to run {} ({} pending)",
g_nSpuDmaQueueHead, g_nSpuDmaQueueCount);
// nope, more dma to run
auto* next_xfer = &g_aSpuDmaQueue[g_nSpuDmaQueueHead];
// set up the next interrupt handler
set_dma_intr_handler_hack(channel, SPUDmaIntr, next_xfer->user_data);
// args for the dma transfer
int next_chan = channel;
int next_mode = 0;
const void* next_iop = next_xfer->iop_mem;
u32 next_spu = next_xfer->spu_addr;
u32 next_length = next_xfer->length;
// load up the commands to handle
g_pDmaVagCmd = next_xfer->command;
g_pDmaStereoVagCmd = nullptr;
if (g_pDmaVagCmd) {
g_pDmaStereoVagCmd = g_pDmaVagCmd->stereo_sibling;
}
g_nSpuDmaChunks = next_xfer->num_isobuffered_chunks;
// advance the queue!
g_nSpuDmaQueueCount = g_nSpuDmaQueueCount + -1;
g_nSpuDmaQueueHead = g_nSpuDmaQueueHead + 1;
if (0xf < g_nSpuDmaQueueHead) {
g_nSpuDmaQueueHead = 0;
}
// start the next one!
// set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, userdata);
voice_trans_wrapper(next_chan, next_mode, next_iop, next_spu, next_length);
}
ovrld_log(LogCategory::SPU_DMA_STR, "SPUDmaIntr exit - end of function");
return 0;
}
/*!
* Start DMA to EE.
*/
void DMA_SendToEE(void* ee_dest,
const void* iop_src,
u32 length,
void callback(void*),
void* callback_arg) {
ASSERT(iop_src);
ASSERT(ee_dest);
ASSERT(((uintptr_t)iop_src & 3) == 0);
ASSERT(((uintptr_t)ee_dest & 0xf) == 0);
ASSERT(length < 0xffff0);
sceSifDmaData cmd; // DMA settings
// setup command
cmd.mode = 0;
cmd.data = iop_src;
cmd.addr = ee_dest;
cmd.size = length;
// instant DMA
// ovrld_log(LogCategory::EE_DMA, "DMA_SendToEE: 0x{:x}, size {}", (u64)ee_dest, length);
sceSifSetDma(&cmd, 1);
// for now, we'll do the callback here, but I bet it will cause problems
if (callback) {
callback(callback_arg);
}
}
/*!
* Start DMA transfer to SPU. Despite the name, this does not actually "sync" - the transfer will
* be ongoing. If there is an ongoing transfer when this is called, the transfer will be queued.
*/
int DMA_SendToSPUAndSync(const u8* iop_mem,
int length,
int spu_addr,
ISO_VAGCommand* cmd,
void* user_data) {
// CpuSuspendIntr(local_28);
int ret = 1;
bool defer = false;
ovrld_log(LogCategory::SPU_DMA_STR,
"DMA to SPU requested for {}, {} bytes to 0x{:x}, currently busy? {}",
cmd ? cmd->name : "NO-CMD", length, spu_addr, g_bSpuDmaBusy);
if (g_bSpuDmaBusy == 0) {
// not busy, we can actually start dma now.
g_nSpuDmaChannel = snd_GetFreeSPUDMA();
if (g_nSpuDmaChannel == -1) {
return 0;
}
// set globals for DMA processing
if (cmd) {
g_nSpuDmaChunks = cmd->num_isobuffered_chunks;
g_pDmaStereoVagCmd = cmd->stereo_sibling;
g_pDmaVagCmd = cmd;
}
} else {
// busy, need to queue the dma
ASSERT(g_nSpuDmaQueueCount <= (int)g_aSpuDmaQueue.size());
// set values:
g_aSpuDmaQueue[g_nSpuDmaQueueTail].length = length;
g_aSpuDmaQueue[g_nSpuDmaQueueTail].spu_addr = spu_addr;
g_aSpuDmaQueue[g_nSpuDmaQueueTail].user_data = user_data;
g_aSpuDmaQueue[g_nSpuDmaQueueTail].num_isobuffered_chunks =
cmd ? cmd->num_isobuffered_chunks : 0;
g_aSpuDmaQueue[g_nSpuDmaQueueTail].command = cmd;
g_aSpuDmaQueue[g_nSpuDmaQueueTail].iop_mem = iop_mem;
g_nSpuDmaQueueCount = g_nSpuDmaQueueCount + 1;
g_nSpuDmaQueueTail = g_nSpuDmaQueueTail + 1;
if (0xf < g_nSpuDmaQueueTail) {
g_nSpuDmaQueueTail = 0;
}
defer = true;
}
// set up the stereo command
if (cmd) {
cmd->safe_to_modify_dma = 0;
auto* stereo = cmd->stereo_sibling;
if (stereo) {
stereo->num_isobuffered_chunks = cmd->num_isobuffered_chunks;
stereo->dma_iop_mem_ptr = iop_mem + length;
cmd->dma_chan = g_nSpuDmaChannel;
stereo->xfer_size = length;
}
}
// kick off dma, if we decided not to queue.
if (!defer) {
g_bSpuDmaBusy = true;
set_dma_intr_handler_hack(g_nSpuDmaChannel, SPUDmaIntr, user_data);
voice_trans_wrapper(g_nSpuDmaChannel, 0, iop_mem, spu_addr, length);
}
return ret;
}
/*!
* Run a dma transfer that was delayed or dropped.
*/
void RunDeferredVoiceTrans() {
// only if there's a currently happening transfer.
if (g_voiceTransRunning) {
if (GetSystemTimeLow() - g_voiceTransTime > 0x384000) {
ovrld_log(LogCategory::WARN, "DeferredVoiceTrans has detected hung dma... expect problems.");
// original game also check sceSdVoiceTransStatus here, we'll possibly need to mess with this
// if we delay dma completion interrupts...
g_voiceTransRunning = false;
voice_trans_wrapper(g_voiceTransChannel, g_voiceTransMode, g_voiceTransAddr,
g_voiceTransSpuAddr, g_voiceTransSize);
}
}
}
} // namespace jak3
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include "common/common_types.h"
namespace jak3 {
void jak3_overlord_init_globals_dma();
struct ISO_VAGCommand;
int voice_trans_wrapper(s16 chan, u32 mode, const void* iop_addr, u32 spu_addr, u32 size);
void DMA_SendToEE(void* ee_dest,
const void* iop_src,
u32 length,
void callback(void*),
void* callback_arg);
int DMA_SendToSPUAndSync(const u8* iop_mem,
int length,
int spu_addr,
ISO_VAGCommand* cmd,
void* user_data);
void RunDeferredVoiceTrans();
struct ISO_VAGCommand;
struct DmaQueueEntry {
ISO_VAGCommand* command = nullptr;
const void* iop_mem = nullptr;
u32 spu_addr = 0;
u32 length = 0;
void* user_data = nullptr;
u32 num_isobuffered_chunks = 0;
};
void dma_intr_hack();
} // namespace jak3
+583
View File
@@ -0,0 +1,583 @@
#include "dvd_driver.h"
#include <cstring>
#include <memory>
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "common/util/FileUtil.h"
#include "game/overlord/jak3/isocommon.h"
#include "game/overlord/jak3/overlord.h"
#include "game/sce/iop.h"
namespace jak3 {
using namespace iop;
std::unique_ptr<CDvdDriver> g_DvdDriver;
s32 g_nDvdDriverThread = -1;
void jak3_overlord_init_globals_dvd_driver() {
g_DvdDriver = std::make_unique<CDvdDriver>();
g_nDvdDriverThread = -1;
}
CDvdDriver* get_driver() {
return g_DvdDriver.get();
}
CMsg::CMsg(jak3::CMsg::MsgKind msg) : m_msg(msg) {
m_ret = 1;
m_thread = GetThreadId();
}
int CMsg::send() {
// note: changed from passing data
// and removed corresponding -4 to skip back past the vtable in DVD thread
// (what were they thinking?)
s32 ret = SendMbx(get_driver()->msgbox, this);
if (ret == 0) {
get_driver()->KickDvdThread();
SleepThread();
return m_ret;
}
return ret;
}
// CMsgLock::CMsgLock() : CMsg(CMsg::MsgKind::LOCK) {}
//
// void CMsgLock::handler() {
// get_driver()->Lock();
// m_ret = 0;
// }
// CMsgReadRaw::CMsgReadRaw(jak3::BlockParams* params) : CMsg(CMsg::MsgKind::READ_RAW) {
// m_block_params = *params;
// }
//
// void CMsgReadRaw::handler() {
// m_ret = get_driver()->ReadDirect(&m_block_params);
// }
CMsgCancelRead::CMsgCancelRead(jak3::CDescriptor* desc) : CMsg(CMsg::MsgKind::CANCEL_READ) {
m_desc = desc;
}
void CMsgCancelRead::handler() {
get_driver()->CancelRead(m_desc);
m_ret = 0;
}
u32 DvdThread();
CDvdDriver::CDvdDriver() {
fifo_entry_sema = -1;
current_thread_priority = 0x13;
disk_type = 5;
tray_flag = 1;
// m_nLockCount = 0;
event_flag = -1;
fifo_access_sema = -1;
tray_flag2 = 1;
initialized = 0;
m_nNumFifoEntries = 0;
ring_head = 0;
ring_tail = 0;
read_in_progress = 0;
callback = nullptr;
// locked = false;
trayflag3 = 0;
m_nDvdThreadAccessSemaCount = 0;
memset(ring, 0, sizeof(Block) * 16);
}
void CDvdDriver::Initialize() {
if (!initialized) {
*this = {};
ThreadParam thread_param;
thread_param.attr = 0x2000000;
// mbox_param.option = gDvdDriverThreadOptions; // ???
thread_param.entry = DvdThread;
thread_param.stackSize = 0x800;
thread_param.initPriority = 0x13;
thread_param.option = 0;
strcpy(thread_param.name, "dvd");
// mbox_param.attr = (int)PTR_DvdThread_00015c98; // ???
g_nDvdDriverThread = CreateThread(&thread_param);
ASSERT(g_nDvdDriverThread >= 0);
SemaParam sema_param;
sema_param.attr = 0;
sema_param.init_count = 1;
sema_param.max_count = 1;
sema_param.option = 0;
fifo_access_sema = CreateSema(&sema_param);
ASSERT(fifo_access_sema >= 0);
sema_param.max_count = 0x10;
sema_param.attr = 0;
sema_param.init_count = 0x10;
sema_param.option = 0;
fifo_entry_sema = CreateSema(&sema_param);
ASSERT(fifo_entry_sema >= 0);
MbxParam mbox_param;
mbox_param.attr = 0;
mbox_param.option = 0;
msgbox = CreateMbx(&mbox_param);
ASSERT(msgbox >= 0);
EventFlagParam param;
param.attr = 0;
param.option = 0;
param.init_pattern = 0;
event_flag = CreateEventFlag(&param);
ASSERT(event_flag >= 0);
StartThread(g_nDvdDriverThread, 0); // this...
}
initialized = 1;
}
void CDvdDriver::SetDriverCallback(std::function<void(int)> f) {
callback = f;
}
// GetDriveCallback
// Poll - would kick the thread...
// void CDvdDriver::Lock() {
// ASSERT_NOT_REACHED();
// if (GetThreadId() == g_nDvdDriverThread) {
// m_nLockCount++;
// locked = true;
// // needs break HACK
// needs_break = false;
// } else {
// CMsgLock lock;
// lock.send();
// }
// }
// Read
int CDvdDriver::ReadMultiple(CDescriptor* descriptor,
int* pages_read_out,
BlockParams* params,
int num_blocks,
bool block_if_queue_full) {
*pages_read_out = 0;
s32 ret = 1;
// check block parameters are reasonable
if (ValidateBlockParams(params, num_blocks) != 0) {
bool from_dvd_thread = GetThreadId() == g_nDvdDriverThread;
if (from_dvd_thread) {
// there is a setting to control if this function should block if there are too many
// queued reads. If the is called from the DVD thread, then this would deadlock.
// the original game ignored the block argument, but I'm asserting
block_if_queue_full = 0;
ASSERT_NOT_REACHED();
}
ovrld_log(LogCategory::DRIVER, "[driver] ReadMultiple (from our thread? {}) num_blocks {}",
from_dvd_thread, num_blocks);
ret = 0;
if (0 < num_blocks) {
// loop, until we've done all the requested reads.
do {
s32 acquired_slots = 0;
if (0 < num_blocks) {
// loop to try to get up to num_blocks slots in the fifo
// but, if we get less, we'll take that too
do {
if (PollSema(this->fifo_entry_sema) == -0x1a3)
break;
acquired_slots = acquired_slots + 1;
} while (acquired_slots < num_blocks);
}
ovrld_log(LogCategory::DRIVER, "[driver] ReadMultiple acquired {} slots in ring",
acquired_slots);
// if we are blocking, and we acquired no slots, then we'll wait here until we get one slot.
if ((block_if_queue_full != 0) && (acquired_slots < 1)) {
ovrld_log(LogCategory::DRIVER, "[driver] ring is full, blocking!");
acquired_slots = 1; // the one we'll get from the WaitSema below
do {
} while (WaitSema(fifo_entry_sema) != 0);
}
// lock, now that we've gotten the slots
AcquireFIFOSema(from_dvd_thread);
num_blocks = num_blocks - acquired_slots;
// if we didn't get any slots, bail.
if (acquired_slots < 1) {
ovrld_log(LogCategory::DRIVER, "[driver] ring is full, bailing!");
ReleaseFIFOSema(from_dvd_thread);
if (0 < *pages_read_out) {
KickDvdThread();
}
return 2;
}
// loop, updating the ring for each slot we aquired
do {
auto* slot = ring + ring_tail;
ovrld_log(LogCategory::DRIVER, "[driver] inserting in ring slot {}", ring_tail);
ring_tail++;
if (0xf < ring_tail) {
ring_tail = 0;
}
m_nNumFifoEntries++;
auto* tail = descriptor->m_pTail;
slot->descriptor = descriptor;
slot->params = params[*pages_read_out];
*pages_read_out = (*pages_read_out) + 1;
if (!tail) {
descriptor->m_pHead = slot;
} else {
tail->next = slot;
}
acquired_slots = acquired_slots + -1;
descriptor->m_pTail = slot;
slot->next = nullptr;
} while (acquired_slots != 0);
ReleaseFIFOSema(from_dvd_thread);
KickDvdThread();
ret = 0;
} while (0 < num_blocks);
}
} else {
ASSERT_NOT_REACHED();
}
return ret;
}
void CDvdDriver::CancelRead(jak3::CDescriptor* desc) {
if (GetThreadId() == g_nDvdDriverThread) {
AcquireFIFOSema(true);
if ((read_in_progress != 0) && (ring[ring_head].descriptor == desc)) {
// while (iVar1 = sceCdBreak(), iVar1 == 0) {
// DelayThread(8000);
// sceCdSync(0);
// }
// sceCdSync(0);
read_in_progress = 0;
}
Block* iter = desc->m_pHead;
Block* tail = desc->m_pTail;
while (iter) {
if (iter->descriptor) {
CompletionHandler(iter, 6);
}
iter->descriptor = nullptr;
iter->next = nullptr;
if (iter == tail)
break;
iter = desc->m_pHead;
}
if (desc->m_pTail == tail) {
desc->m_pTail = nullptr;
}
ReleaseFIFOSema(true);
} else {
CMsgCancelRead msg(desc);
msg.send();
}
}
s32 CDvdDriver::ValidateBlockParams(jak3::BlockParams* params, int num_params) {
if (!params) {
lg::die("Invalid BlockParams: nullptr");
return 0;
}
if (num_params < 1) {
lg::die("Invalid BlockParams: size == 0");
return 0;
}
for (int i = 0; i < num_params; i++) {
auto& p = params[i];
if (p.destination == nullptr) {
lg::die("Invalid BlockParams: {} had nullptr dest", i);
return 0;
}
int kMaxSector = 1000000;
if (p.sector_num > kMaxSector) {
// this is just a sanity check - if we ever have larger files this is okay to increase.
lg::die("Invalid BlockParams: {} had sector num {}", i, p.sector_num);
return 0;
}
if (p.num_sectors > 0x1d0) {
lg::die("Invalid BlockParams: {} had sector count {}", i, p.num_sectors);
return 0;
}
if (!p.file_def) {
lg::die("Invalid BlockParams: {} had no file", i);
return 0;
}
}
return 1;
}
void CDvdDriver::KickDvdThread() {
while (SetEventFlag(event_flag, 1)) {
;
}
}
int CDvdDriver::AcquireFIFOSema(bool from_dvd_thread) {
int iVar1;
int iVar2;
if ((from_dvd_thread != 0) &&
(iVar2 = m_nDvdThreadAccessSemaCount, m_nDvdThreadAccessSemaCount = iVar2 + 1, 0 < iVar2)) {
return 0;
}
iVar1 = WaitSema(this->fifo_access_sema);
iVar2 = 0;
if ((iVar1 != 0) && (iVar2 = iVar1, from_dvd_thread != 0)) {
m_nDvdThreadAccessSemaCount = m_nDvdThreadAccessSemaCount + -1;
iVar2 = iVar1;
}
return iVar2;
}
int CDvdDriver::ReleaseFIFOSema(bool from_dvd_thread) {
int iVar1;
int iVar2;
if (from_dvd_thread != 0) {
iVar2 = m_nDvdThreadAccessSemaCount + -1;
if (m_nDvdThreadAccessSemaCount < 1) {
return -0x1a4;
}
m_nDvdThreadAccessSemaCount = iVar2;
if (0 < iVar2) {
return 0;
}
}
iVar1 = SignalSema(fifo_access_sema);
iVar2 = 0;
if ((iVar1 != 0) && (iVar2 = iVar1, from_dvd_thread != 0)) {
m_nDvdThreadAccessSemaCount = m_nDvdThreadAccessSemaCount + 1;
iVar2 = iVar1;
}
return iVar2;
}
/*!
* PC port added function to actually do a read of a block.
*/
void CDvdDriver::read_from_file(const jak3::Block* block) {
const auto* fd = block->params.file_def;
ASSERT(fd);
FileCacheEntry* selected_entry = nullptr;
// get a cache entry
for (auto& entry : m_file_cache) {
// if we already opened this file, use that
if (entry.def == fd) {
selected_entry = &entry;
break;
}
// otherwise pick the least recently used
if (!selected_entry) {
selected_entry = &entry;
} else {
if (selected_entry->last_use_count > entry.last_use_count) {
selected_entry = &entry;
}
}
}
// open a new file if needed
if (selected_entry->def != fd) {
lg::debug("CDvdDriver swapping files {} - > {}",
selected_entry->def ? selected_entry->def->name.data : "NONE", fd->name.data);
if (selected_entry->def) {
fclose(selected_entry->fp);
}
selected_entry->def = fd;
selected_entry->fp = file_util::open_file(fd->full_path, "rb");
if (!selected_entry->fp) {
lg::die("Failed to open {} {}", fd->full_path, strerror(errno));
}
selected_entry->offset_in_file = 0;
}
// increment use counter
selected_entry->last_use_count = m_file_cache_counter++;
const u64 desired_offset = block->params.sector_num * 0x800;
// see if we're reading entirely past the end of the file
if (desired_offset >= fd->length) {
return;
}
if (selected_entry->offset_in_file != desired_offset) {
lg::debug("CDvdDriver jumping in file {}: {} -> {}", fd->name.data,
selected_entry->offset_in_file, desired_offset);
if (fseek(selected_entry->fp, desired_offset, SEEK_SET)) {
ASSERT_NOT_REACHED_MSG("Failed to fseek");
}
selected_entry->offset_in_file = desired_offset;
}
// read
s64 read_length = block->params.num_sectors * 0x800;
s64 extra_length = read_length + desired_offset - fd->length;
if (extra_length > 0) {
read_length -= extra_length;
}
auto ret = fread(block->params.destination, read_length, 1, selected_entry->fp);
if (ret != 1) {
lg::die("Failed to read {} {}, size {} of {} (ret {})", fd->full_path, strerror(errno),
read_length, fd->length, ret);
}
selected_entry->offset_in_file += read_length;
}
u32 DvdThread() {
auto* driver = get_driver();
while (true) {
// Poll for messages
CMsg* msg = nullptr;
while (true) {
int poll_status = PollMbx((MsgPacket**)&msg, driver->msgbox);
if (poll_status || !msg) {
break;
}
// run message code
msg->handler();
// wake the waiting thread.
WakeupThread(msg->m_thread);
}
bool completed = false;
// if a read is in progress, wait for it to finish.
if (driver->read_in_progress) {
// TODO: if we switch to async reads, this is where we'd want to sync.
// sceCdSync(0);
completed = true;
// error checking
}
driver->AcquireFIFOSema(true);
// error handling
// handle ring book-keeping.
// note that these are somewhat double-buffered - we'll sync on read i-1, start read i, then
// run the completion handler for read i - 1.
// the completion is what actually removes stuff from the ring.
s32 fifo_slots_freed = completed ? 1 : 0;
s32 ring_entry = driver->ring_head + (completed ? 1 : 0);
if (ring_entry > 15) {
ring_entry = 0;
}
Block* block = driver->ring + ring_entry;
s32 fifo_entries = driver->m_nNumFifoEntries - fifo_slots_freed;
if (fifo_entries) {
// start a new read.
driver->read_in_progress = 1;
ovrld_log(LogCategory::DRIVER, "[driver thread] Reading for slot {}", block - driver->ring);
driver->read_from_file(block);
} else {
driver->read_in_progress = 0;
}
// run completion handler for the previous read - not the one we just started!
Block sblock;
if (completed) {
auto* last_block = &driver->ring[driver->ring_head];
ovrld_log(LogCategory::DRIVER, "[driver thread] Completion handler for {}",
driver->ring_head);
sblock = *last_block;
if (sblock.descriptor && sblock.descriptor->m_pHead) {
ASSERT(sblock.descriptor->m_pHead == last_block);
}
if (((sblock.descriptor)->m_pHead == last_block) &&
((sblock.descriptor)->m_pHead = &sblock, (sblock.descriptor)->m_pTail == last_block)) {
(sblock.descriptor)->m_pTail = &sblock;
}
}
driver->ring_head = ring_entry;
driver->m_nNumFifoEntries = fifo_entries;
while (0 < fifo_slots_freed) {
fifo_slots_freed = fifo_slots_freed + -1;
SignalSema(driver->fifo_entry_sema);
}
if (completed != 0) {
driver->CompletionHandler(&sblock, 0);
}
driver->ReleaseFIFOSema(true);
// this logic here was modified - we go to waiting if we have no more reads.
if (driver->m_nNumFifoEntries == 0) {
ovrld_log(LogCategory::DRIVER, "[driver thread] No work, waiting.");
WaitEventFlag(driver->event_flag, 1, 0x11);
ovrld_log(LogCategory::DRIVER, "[driver thread] Woken up!");
}
// s32 status;
// if ((((driver->locked != false)) ||
// ((driver->needs_break == 0 && (driver->m_nNumFifoEntries == 0)))) &&
// ((status = WaitEventFlag(driver->event_flag, 1, 0x11),
// status != 0 && (status != -0x1a2)))) {
// if (status == -0x1a9) {
// do {
// SleepThread();
// } while (true);
// }
// DelayThread(8000);
// }
}
}
void CDvdDriver::CompletionHandler(jak3::Block* block, int code) {
// there is some janky thread priority changes here,
// but they do not seem to be needed with the changes to the ISO thread.
// PushPri(this,local_20,0x35);
auto* desc = block->descriptor;
if (desc && desc->m_pHead) {
desc->m_status = code;
int thread = desc->m_ThreadID;
if (desc->m_Callback) {
(desc->m_Callback)(desc->m_File, block, code);
}
if (0 < thread) {
WakeupThread(thread);
}
Block* next;
if ((desc->m_pHead == block) && (next = block->next, desc->m_pHead = next, next == nullptr)) {
desc->m_pTail = nullptr;
}
}
block->next = nullptr;
block->descriptor = nullptr;
// PopPri(this, local_20[0]);
}
CDvdDriver::~CDvdDriver() {
for (auto& entry : m_file_cache) {
if (entry.fp) {
fclose(entry.fp);
}
}
}
} // namespace jak3
+144
View File
@@ -0,0 +1,144 @@
#pragma once
#include <functional>
#include "common/common_types.h"
#include "game/overlord/jak3/isocommon.h"
namespace jak3 {
void jak3_overlord_init_globals_dvd_driver();
/*!
* The DVD Driver is what actually called the Sony CD library functions.
* It also had many special cases for handling errors, open trays, retries, etc that are not
* recreated in this port.
*
* The original DVD driver thread didn't run the actual reads - the Sony CD library had its own
* threads for async reads. However, they would call sceCdSync() to wait until a read finished.
* It's not clear if sceCdSync would allow other threads to run while waiting on the read to finish.
* but if it did, this is a bit of a difference in the blocking behavior.
*
* This is something that could be revisited, as freads will now essentially block the entire
* overlord, including refilling sound RAM.
*/
struct CDescriptor;
struct BlockParams;
struct CPage;
struct ISOFileDef;
// The CMSG system is used to pass messages from external threads to the driver. It's mostly used
// internally by the driver, when functions are called on it from outside threads. In these cases
// the Cmsg will get send to the driver thread and handler will run on it here.
struct CMsg {
enum class MsgKind {
// LOCK = 0,
READ_RAW = 1,
CANCEL_READ = 2,
};
CMsg(MsgKind msg);
virtual int send();
virtual void handler() = 0;
u8 data[8];
MsgKind m_msg;
int m_thread;
int m_ret;
};
// struct CMsgLock : public CMsg {
// CMsgLock();
// void handler() override;
// };
// struct CMsgReadRaw : public CMsg {
// explicit CMsgReadRaw(BlockParams* params);
// void handler() override;
// BlockParams m_block_params;
// };
struct CMsgCancelRead : public CMsg {
explicit CMsgCancelRead(CDescriptor* desc);
void handler() override;
CDescriptor* m_desc;
};
struct CISOCDFile;
/*!
* Reference to an ongoing or requested read at the driver level, possibly made up of multiple
* blocks. In this case, the head/tail pointers point to Blocks stored inside the CDvdDriver's
* internal FIFO.
*/
struct CDescriptor {
CDescriptor() = default;
int m_unk0 = 0;
void (*m_Callback)(CISOCDFile*, Block*, s32) = nullptr;
int m_ThreadID = 0;
int m_status = 0;
CISOCDFile* m_File = nullptr;
Block* m_pHead = nullptr;
Block* m_pTail = nullptr;
};
class CDvdDriver {
public:
CDvdDriver();
~CDvdDriver();
void Initialize();
void CancelRead(CDescriptor* descriptor);
int ReadMultiple(CDescriptor* descriptor,
int* pages_read_out,
BlockParams* params,
int num_pages,
bool block_if_queue_full);
void SetDriverCallback(std::function<void(int)> f);
// int ReadDirect(BlockParams* params);
void KickDvdThread();
// void Lock();
int GetDiskType() const { return disk_type; }
s32 ValidateBlockParams(BlockParams* params, int num_params);
int ReleaseFIFOSema(bool from_dvd_thread);
int AcquireFIFOSema(bool from_dvd_thread);
void read_from_file(const Block* block);
void CompletionHandler(Block* block, int code);
u8 initialized = 0;
s32 event_flag = -1;
s32 fifo_access_sema = -1;
s32 fifo_entry_sema = -1;
s32 msgbox = -1;
s32 m_nNumFifoEntries = 0;
s32 ring_head = 0;
s32 ring_tail = 0;
Block ring[16];
u8 read_in_progress; // more likely: read in progress
std::function<void(int)> callback;
s32 current_thread_priority = 0;
// s32 m_nLockCount = 0;
// bool locked = false;
//
s32 disk_type;
u8 tray_flag2;
u8 trayflag3;
u8 tray_flag;
s32 m_nDvdThreadAccessSemaCount = 0;
private:
struct FileCacheEntry {
const ISOFileDef* def = nullptr;
FILE* fp = nullptr;
u32 last_use_count = 0;
u64 offset_in_file = 0;
};
u32 m_file_cache_counter = 0;
static constexpr int kNumFileCacheEntries = 6;
FileCacheEntry m_file_cache[kNumFileCacheEntries];
};
// replacement for g_DvdDriver
CDvdDriver* get_driver();
} // namespace jak3
+50
View File
@@ -0,0 +1,50 @@
#include "game/overlord/jak3/basefile.h"
#include "game/overlord/jak3/basefilesystem.h"
#include "game/overlord/jak3/dma.h"
#include "game/overlord/jak3/dvd_driver.h"
#include "game/overlord/jak3/iso.h"
#include "game/overlord/jak3/iso_api.h"
#include "game/overlord/jak3/iso_cd.h"
#include "game/overlord/jak3/iso_queue.h"
#include "game/overlord/jak3/isocommon.h"
#include "game/overlord/jak3/list.h"
#include "game/overlord/jak3/overlord.h"
#include "game/overlord/jak3/pagemanager.h"
#include "game/overlord/jak3/ramdisk.h"
#include "game/overlord/jak3/sbank.h"
#include "game/overlord/jak3/soundcommon.h"
#include "game/overlord/jak3/spustreams.h"
#include "game/overlord/jak3/srpc.h"
#include "game/overlord/jak3/ssound.h"
#include "game/overlord/jak3/stream.h"
#include "game/overlord/jak3/streamlist.h"
#include "game/overlord/jak3/vag.h"
#include "game/overlord/jak3/vblank_handler.h"
namespace jak3 {
void jak3_overlord_init_globals_all() {
jak3_overlord_init_globals_overlord();
jak3_overlord_init_globals_pagemanager();
jak3_overlord_init_globals_iso_cd();
jak3_overlord_init_globals_dma();
jak3_overlord_init_globals_iso();
jak3_overlord_init_globals_iso_queue();
jak3_overlord_init_globals_srpc();
jak3_overlord_init_globals_vag();
jak3_overlord_init_globals_ssound();
jak3_overlord_init_globals_iso_api();
jak3_overlord_init_globals_spustreams();
jak3_overlord_init_globals_list();
jak3_overlord_init_globals_vblank_handler();
jak3_overlord_init_globals_dvd_driver();
jak3_overlord_init_globals_basefile();
jak3_overlord_init_globals_basefilesystem();
jak3_overlord_init_globals_ramdisk();
jak3_overlord_init_globals_isocommon();
jak3_overlord_init_globals_stream();
jak3_overlord_init_globals_sbank();
jak3_overlord_init_globals_soundcommon();
jak3_overlord_init_globals_streamlist();
}
} // namespace jak3
+5
View File
@@ -0,0 +1,5 @@
#pragma once
namespace jak3 {
void jak3_overlord_init_globals_all();
}
Loaded 100 of 622 files, more files were not shown because too many files have changed in this diff. Show more