mirror of
https://github.com/open-goal/jak-project
synced 2026-07-31 08:16:02 -04:00
jak2: ocean renderer (#2142)
Initial implementation of the `ocean-mid`, `ocean-far` and `ocean-near` renderers for Jak 2. There's still a few things to sort out, mainly: - [x] ~Backwards compatibility with Jak 1. The only thing that currently stands in the way of that is figuring out a clean way to "un-hardcode" the texture base pointer in C++ without creating a completely separate `OceanTexture` class for Jak 2. One thing I thought of would be modifying `BucketRenderer`'s virtual `init_textures` method to also pass the `GameVersion`, but I'm not sure if there's a better way.~ - [x] ~The sudden transition from `ocean-near` to `ocean-mid`. Not sure why it's happening or how to fix it.~ - [x] The ocean has two new methods in Jak 2, `ocean::89` and `ocean::79`, one of which seems to be related to time of day sky colors. ~Even without them implemented, the end result looks quite close, so we may be able to skip them?~ `ocean::89` generates `ocean-mid` envmap textures, so it will likely be required, but will not be handled right now. Reverted the VU prologue removals because it made the tests fail.
This commit is contained in:
@@ -2724,7 +2724,7 @@
|
||||
(bucket-3 3) ;; blit displays
|
||||
(tex-lcom-sky-pre 4) ;; tex
|
||||
(sky-draw 5) ;; sky
|
||||
(bucket-6 6) ;; ocean
|
||||
(ocean-mid-far 6) ;; ocean
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; All levels with tfrag tpage
|
||||
@@ -3080,7 +3080,7 @@
|
||||
|
||||
(tex-lcom-sky-post 309)
|
||||
|
||||
(bucket-310 310) ;; ocean
|
||||
(ocean-near 310) ;; ocean
|
||||
(bucket-311 311) ;; depth-cue
|
||||
|
||||
(tex-all-sprite 312)
|
||||
|
||||
@@ -99,9 +99,9 @@ void RenderMux::draw_debug_window() {
|
||||
m_renderers[m_render_idx]->draw_debug_window();
|
||||
}
|
||||
|
||||
void RenderMux::init_textures(TexturePool& tp) {
|
||||
void RenderMux::init_textures(TexturePool& tp, GameVersion version) {
|
||||
for (auto& rend : m_renderers) {
|
||||
rend->init_textures(tp);
|
||||
rend->init_textures(tp, version);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class BucketRenderer {
|
||||
virtual bool empty() const { return false; }
|
||||
virtual void draw_debug_window() = 0;
|
||||
virtual void init_shaders(ShaderLibrary&) {}
|
||||
virtual void init_textures(TexturePool&) {}
|
||||
virtual void init_textures(TexturePool&, GameVersion) {}
|
||||
|
||||
protected:
|
||||
std::string m_name;
|
||||
@@ -111,7 +111,7 @@ class RenderMux : public BucketRenderer {
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
void init_shaders(ShaderLibrary&) override;
|
||||
void init_textures(TexturePool&) override;
|
||||
void init_textures(TexturePool&, GameVersion) override;
|
||||
void set_idx(u32 i) { m_render_idx = i; };
|
||||
|
||||
private:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/////////////////////////
|
||||
EyeRenderer::EyeRenderer(const std::string& name, int id) : BucketRenderer(name, id) {}
|
||||
|
||||
void EyeRenderer::init_textures(TexturePool& texture_pool) {
|
||||
void EyeRenderer::init_textures(TexturePool& texture_pool, GameVersion) {
|
||||
// set up eyes
|
||||
for (int pair_idx = 0; pair_idx < NUM_EYE_PAIRS; pair_idx++) {
|
||||
for (int lr = 0; lr < 2; lr++) {
|
||||
|
||||
@@ -16,7 +16,7 @@ class EyeRenderer : public BucketRenderer {
|
||||
~EyeRenderer();
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void draw_debug_window() override;
|
||||
void init_textures(TexturePool& texture_pool) override;
|
||||
void init_textures(TexturePool& texture_pool, GameVersion) override;
|
||||
|
||||
void handle_eye_dma2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
|
||||
@@ -93,8 +93,8 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-lcom-sky-pre", BucketCategory::TEX,
|
||||
BucketId::TEX_LCOM_SKY_PRE);
|
||||
init_bucket_renderer<DirectRenderer>("sky-draw", BucketCategory::OTHER, BucketId::SKY_DRAW, 1024);
|
||||
init_bucket_renderer<SkipRenderer>("ocean-mid-far", BucketCategory::OCEAN,
|
||||
BucketId::OCEAN_MID_FAR);
|
||||
init_bucket_renderer<OceanMidAndFar>("ocean-mid-far", BucketCategory::OCEAN,
|
||||
BucketId::OCEAN_MID_FAR);
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-l0-tfrag", BucketCategory::TEX,
|
||||
BucketId::TEX_L0_TFRAG);
|
||||
init_bucket_renderer<TFragment>("tfrag-l0-tfrag", BucketCategory::TFRAG, BucketId::TFRAG_L0_TFRAG,
|
||||
@@ -279,7 +279,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-lcom-sky-post", BucketCategory::TEX,
|
||||
BucketId::TEX_LCOM_SKY_POST);
|
||||
// 310
|
||||
init_bucket_renderer<SkipRenderer>("bucket-310", BucketCategory::OCEAN, BucketId::OCEAN_NEAR);
|
||||
init_bucket_renderer<OceanNear>("ocean-near", BucketCategory::OCEAN, BucketId::OCEAN_NEAR);
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-all-sprite", BucketCategory::TEX,
|
||||
BucketId::TEX_ALL_SPRITE);
|
||||
init_bucket_renderer<Sprite3>("particles", BucketCategory::SPRITE, BucketId::PARTICLES);
|
||||
@@ -309,7 +309,7 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
|
||||
}
|
||||
|
||||
m_bucket_renderers[i]->init_shaders(m_render_state.shaders);
|
||||
m_bucket_renderers[i]->init_textures(*m_render_state.texture_pool);
|
||||
m_bucket_renderers[i]->init_textures(*m_render_state.texture_pool, GameVersion::Jak2);
|
||||
}
|
||||
m_render_state.loader->load_common(*m_render_state.texture_pool, "GAME");
|
||||
}
|
||||
@@ -534,7 +534,7 @@ void OpenGLRenderer::init_bucket_renderers_jak1() {
|
||||
}
|
||||
|
||||
m_bucket_renderers[i]->init_shaders(m_render_state.shaders);
|
||||
m_bucket_renderers[i]->init_textures(*m_render_state.texture_pool);
|
||||
m_bucket_renderers[i]->init_textures(*m_render_state.texture_pool, GameVersion::Jak1);
|
||||
}
|
||||
sky_cpu_blender->init_textures(*m_render_state.texture_pool);
|
||||
sky_gpu_blender->init_textures(*m_render_state.texture_pool);
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include "common/log/log.h"
|
||||
|
||||
constexpr int OCEAN_TEX_TBP_JAK1 = 8160; // todo
|
||||
constexpr int OCEAN_TEX_TBP_JAK2 = 672;
|
||||
|
||||
CommonOceanRenderer::CommonOceanRenderer() {
|
||||
m_vertices.resize(4096 * 10); // todo decrease
|
||||
for (auto& buf : m_indices) {
|
||||
@@ -244,8 +247,14 @@ void CommonOceanRenderer::handle_near_adgif(const u8* data, u32 offset, u32 coun
|
||||
most_recent_tbp = reg.tbp0();
|
||||
} break;
|
||||
case GsRegisterAddress::ALPHA_1: {
|
||||
// ignore, we've hardcoded alphas.
|
||||
GsAlpha reg(value);
|
||||
if (reg.a_mode() == GsAlpha::BlendMode::SOURCE &&
|
||||
reg.b_mode() == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
reg.c_mode() == GsAlpha::BlendMode::DEST && reg.d_mode() == GsAlpha::BlendMode::DEST) {
|
||||
m_current_bucket = VertexBucket::ENV_MAP;
|
||||
}
|
||||
} break;
|
||||
|
||||
case GsRegisterAddress::FRAME_1: {
|
||||
u32 mask = value >> 32;
|
||||
if (mask) {
|
||||
@@ -290,7 +299,9 @@ void CommonOceanRenderer::flush_near(SharedRenderState* render_state, ScopedProf
|
||||
case 0: {
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
auto tex = render_state->texture_pool->lookup(8160);
|
||||
auto tbp =
|
||||
render_state->version == GameVersion::Jak1 ? OCEAN_TEX_TBP_JAK1 : OCEAN_TEX_TBP_JAK2;
|
||||
auto tex = render_state->texture_pool->lookup(tbp);
|
||||
if (!tex) {
|
||||
tex = render_state->texture_pool->get_placeholder_texture();
|
||||
}
|
||||
@@ -419,7 +430,7 @@ void CommonOceanRenderer::handle_mid_adgif(const u8* data, u32 offset) {
|
||||
}
|
||||
}
|
||||
|
||||
if (most_recent_tbp != 8160) {
|
||||
if (most_recent_tbp != OCEAN_TEX_TBP_JAK2) {
|
||||
m_envmap_tex = most_recent_tbp;
|
||||
}
|
||||
|
||||
@@ -482,7 +493,9 @@ void CommonOceanRenderer::flush_mid(SharedRenderState* render_state, ScopedProfi
|
||||
for (int bucket = 0; bucket < 2; bucket++) {
|
||||
switch (bucket) {
|
||||
case 0: {
|
||||
auto tex = render_state->texture_pool->lookup(8160);
|
||||
auto tbp =
|
||||
render_state->version == GameVersion::Jak1 ? OCEAN_TEX_TBP_JAK1 : OCEAN_TEX_TBP_JAK2;
|
||||
auto tex = render_state->texture_pool->lookup(tbp);
|
||||
if (!tex) {
|
||||
tex = render_state->texture_pool->get_placeholder_texture();
|
||||
}
|
||||
|
||||
@@ -133,6 +133,127 @@ void OceanMid::run(DmaFollower& dma, SharedRenderState* render_state, ScopedProf
|
||||
m_common_ocean_renderer.flush_mid(render_state, prof);
|
||||
}
|
||||
|
||||
void OceanMid::run_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
m_common_ocean_renderer.init_for_mid();
|
||||
// first is setting base and offset
|
||||
{
|
||||
auto base_offset_tag = dma.read_and_advance();
|
||||
ASSERT(base_offset_tag.size_bytes == 0);
|
||||
auto base = base_offset_tag.vifcode0();
|
||||
ASSERT(base.kind == VifCode::Kind::BASE);
|
||||
ASSERT(base.immediate == VU1_INPUT_BUFFER_BASE);
|
||||
auto offset = base_offset_tag.vifcode1();
|
||||
ASSERT(offset.kind == VifCode::Kind::OFFSET);
|
||||
ASSERT(offset.immediate == VU1_INPUT_BUFFER_OFFSET);
|
||||
}
|
||||
|
||||
// next is constants
|
||||
{
|
||||
auto constants = dma.read_and_advance();
|
||||
ASSERT(constants.size_bytes == sizeof(Constants));
|
||||
ASSERT(constants.vifcode0().kind == VifCode::Kind::STCYCL); // for whatever reason they do this
|
||||
auto unpack = constants.vifcode1();
|
||||
ASSERT(VifCodeUnpack(unpack).addr_qw == Vu1Data::CONSTANTS);
|
||||
memcpy(&m_constants, constants.data, sizeof(Constants));
|
||||
memcpy(m_vu_data + Vu1Data::CONSTANTS, &m_constants, sizeof(Constants));
|
||||
}
|
||||
|
||||
// next is call 0
|
||||
{
|
||||
auto call0 = dma.read_and_advance();
|
||||
ASSERT(call0.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
auto c = call0.vifcode1();
|
||||
ASSERT(c.kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(c.immediate == 0);
|
||||
run_call0();
|
||||
}
|
||||
|
||||
while (!is_end_tag(dma.current_tag(), dma.current_tag_vif0(), dma.current_tag_vif1())) {
|
||||
auto data = dma.read_and_advance();
|
||||
auto v0 = data.vifcode0();
|
||||
auto v1 = data.vifcode1();
|
||||
if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_32) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
// ASSERT(up.use_tops_flag);
|
||||
u16 addr = up.addr_qw + (up.use_tops_flag ? get_upload_buffer() : 0);
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
memcpy(m_vu_data + addr, data.data, 16 * v1.num);
|
||||
ASSERT(16 * v1.num == data.size_bytes);
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_8) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
ASSERT(up.use_tops_flag);
|
||||
ASSERT(up.is_unsigned);
|
||||
u16 addr = up.addr_qw + get_upload_buffer();
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
|
||||
u32 temp[4];
|
||||
for (u32 i = 0; i < v1.num; i++) {
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
temp[j] = data.data[4 * i + j];
|
||||
}
|
||||
memcpy(m_vu_data + addr + i, temp, 16);
|
||||
}
|
||||
ASSERT(4 * v1.num == data.size_bytes);
|
||||
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x204 &&
|
||||
v1.kind == VifCode::Kind::UNPACK_V4_8) {
|
||||
auto up = VifCodeUnpack(v1);
|
||||
ASSERT(up.use_tops_flag);
|
||||
ASSERT(up.is_unsigned);
|
||||
u16 addr = up.addr_qw + get_upload_buffer();
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
|
||||
u32 temp[4];
|
||||
for (u32 i = 0; i < v1.num; i++) {
|
||||
for (u32 j = 0; j < 4; j++) {
|
||||
temp[j] = data.data[4 * i + j];
|
||||
}
|
||||
// cl = 4
|
||||
// wl = 2
|
||||
u32 addr_off = 4 * (i / 2) + i % 2;
|
||||
memcpy(m_vu_data + addr + addr_off, temp, 16);
|
||||
}
|
||||
ASSERT(8 * v1.num == data.size_bytes);
|
||||
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
|
||||
v1.kind == VifCode::Kind::MSCALF) {
|
||||
switch (v1.immediate) {
|
||||
case 46:
|
||||
run_call46_vu2c();
|
||||
break;
|
||||
case 73:
|
||||
run_call73_vu2c_jak2();
|
||||
break;
|
||||
case 107:
|
||||
run_call107_vu2c_jak2();
|
||||
break;
|
||||
case 275:
|
||||
run_call275_vu2c_jak2();
|
||||
break;
|
||||
default:
|
||||
lg::warn("unknown call1: {}", v1.immediate);
|
||||
}
|
||||
} else if (v0.kind == VifCode::Kind::MSCALF && v1.kind == VifCode::Kind::FLUSHA) {
|
||||
switch (v0.immediate) {
|
||||
case 41:
|
||||
run_call41_vu2c();
|
||||
break;
|
||||
case 43:
|
||||
run_call43_vu2c();
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown call2: {}", v0.immediate));
|
||||
}
|
||||
} else {
|
||||
ASSERT_MSG(false, fmt::format("{} {}", data.vifcode0().print(), data.vifcode1().print()));
|
||||
}
|
||||
}
|
||||
m_common_ocean_renderer.flush_mid(render_state, prof);
|
||||
}
|
||||
|
||||
void OceanMid::run_call0() {
|
||||
run_call0_vu2c();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ class OceanMid {
|
||||
public:
|
||||
OceanMid();
|
||||
void run(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void run_jak2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
private:
|
||||
void run_call0();
|
||||
@@ -17,13 +18,18 @@ class OceanMid {
|
||||
void run_call43_vu2c();
|
||||
void run_call46_vu2c();
|
||||
void run_call73_vu2c();
|
||||
void run_call73_vu2c_jak2();
|
||||
void run_call107_vu2c();
|
||||
void run_call107_vu2c_jak2();
|
||||
void run_call275_vu2c();
|
||||
void run_call275_vu2c_jak2();
|
||||
void xgkick(u16 addr);
|
||||
|
||||
void run_L26_vu2c();
|
||||
void run_L32_vu2c();
|
||||
void run_L32_vu2c_jak2();
|
||||
void run_L38_vu2c();
|
||||
void run_L38_vu2c_jak2();
|
||||
void run_L43_vu2c();
|
||||
void run_L45_vu2c();
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ void OceanMidAndFar::draw_debug_window() {
|
||||
m_direct.draw_debug_window();
|
||||
}
|
||||
|
||||
void OceanMidAndFar::init_textures(TexturePool& pool) {
|
||||
m_texture_renderer.init_textures(pool);
|
||||
void OceanMidAndFar::init_textures(TexturePool& pool, GameVersion version) {
|
||||
m_texture_renderer.init_textures(pool, version);
|
||||
}
|
||||
|
||||
void OceanMidAndFar::render(DmaFollower& dma,
|
||||
@@ -25,6 +25,19 @@ void OceanMidAndFar::render(DmaFollower& dma,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (render_state->version) {
|
||||
case GameVersion::Jak1:
|
||||
render_jak1(dma, render_state, prof);
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
render_jak2(dma, render_state, prof);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OceanMidAndFar::render_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// jump to bucket
|
||||
auto data0 = dma.read_and_advance();
|
||||
ASSERT(data0.vif1() == 0);
|
||||
@@ -44,7 +57,7 @@ void OceanMidAndFar::render(DmaFollower& dma,
|
||||
|
||||
{
|
||||
auto p = prof.make_scoped_child("texture");
|
||||
m_texture_renderer.handle_ocean_texture(dma, render_state, p);
|
||||
m_texture_renderer.handle_ocean_texture_jak1(dma, render_state, p);
|
||||
}
|
||||
|
||||
handle_ocean_far(dma, render_state, prof);
|
||||
@@ -65,6 +78,73 @@ void OceanMidAndFar::render(DmaFollower& dma,
|
||||
m_direct.set_mipmap(false);
|
||||
}
|
||||
|
||||
void advance_and_print_dma(DmaFollower& dma) {
|
||||
auto data = dma.read_and_advance();
|
||||
printf(
|
||||
"dma transfer:\n%ssize: %d\nvif0: %s, data: %d\nvif1: %s, data: %d, imm: "
|
||||
"%d\n\n",
|
||||
dma.current_tag().print().c_str(), data.size_bytes, data.vifcode0().print().c_str(),
|
||||
data.vif0(), data.vifcode1().print().c_str(), data.vifcode1().num, data.vifcode1().immediate);
|
||||
}
|
||||
|
||||
void OceanMidAndFar::render_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// jump to bucket
|
||||
auto data0 = dma.read_and_advance();
|
||||
ASSERT(data0.vif1() == 0 || data0.vifcode1().kind == VifCode::Kind::NOP);
|
||||
ASSERT(data0.vif0() == 0 || data0.vifcode0().kind == VifCode::Kind::MARK);
|
||||
ASSERT(data0.size_bytes == 0);
|
||||
|
||||
// see if bucket is empty or not
|
||||
if (dma.current_tag_offset() == render_state->next_bucket) {
|
||||
// fmt::print("ocean-mid-far: early exit!\n");
|
||||
return;
|
||||
}
|
||||
m_direct.reset_state();
|
||||
|
||||
// TODO handle ocean::89 and ocean::79
|
||||
// handle_ocean_89_jak2(dma, render_state, prof);
|
||||
|
||||
{
|
||||
auto p = prof.make_scoped_child("texture");
|
||||
m_texture_renderer.handle_ocean_texture_jak2(dma, render_state, p);
|
||||
}
|
||||
|
||||
// handle_ocean_79_jak2(dma, render_state, prof);
|
||||
handle_ocean_far(dma, render_state, prof);
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
|
||||
m_direct.set_mipmap(true);
|
||||
handle_ocean_mid(dma, render_state, prof);
|
||||
|
||||
auto final_next = dma.read_and_advance();
|
||||
ASSERT(final_next.vifcode0().kind == VifCode::Kind::NOP &&
|
||||
final_next.vifcode1().kind == VifCode::Kind::NOP && final_next.size_bytes == 0);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
ASSERT(dma.current_tag_offset() == render_state->next_bucket);
|
||||
|
||||
// auto transfers = 0;
|
||||
// // print the entire chain
|
||||
// printf("START OCEAN MID FAR DMA!!!!!!!\n");
|
||||
// while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
// auto data = dma.read_and_advance();
|
||||
// printf(
|
||||
// "dma transfer %d:\n%ssize: %d\nvif0: %s, data: %d\nvif1: %s, data: %d, imm: "
|
||||
// "%d\n\n",
|
||||
// transfers, dma.current_tag().print().c_str(), data.size_bytes,
|
||||
// data.vifcode0().print().c_str(), data.vif0(), data.vifcode1().print().c_str(),
|
||||
// data.vifcode1().num, data.vifcode1().immediate);
|
||||
// transfers++;
|
||||
// }
|
||||
// printf("transfers: %d\n\n", transfers);
|
||||
|
||||
m_direct.flush_pending(render_state, prof);
|
||||
m_direct.set_mipmap(false);
|
||||
}
|
||||
|
||||
void OceanMidAndFar::handle_ocean_far(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
@@ -98,7 +178,13 @@ void OceanMidAndFar::handle_ocean_mid(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
if (dma.current_tag_vifcode0().kind == VifCode::Kind::BASE) {
|
||||
m_mid_renderer.run(dma, render_state, prof);
|
||||
switch (render_state->version) {
|
||||
case GameVersion::Jak1:
|
||||
m_mid_renderer.run(dma, render_state, prof);
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
m_mid_renderer.run_jak2(dma, render_state, prof);
|
||||
}
|
||||
} else {
|
||||
// not drawing
|
||||
return;
|
||||
@@ -107,4 +193,12 @@ void OceanMidAndFar::handle_ocean_mid(DmaFollower& dma,
|
||||
while (!is_end_tag(dma.current_tag(), dma.current_tag_vifcode0(), dma.current_tag_vifcode1())) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_ocean_89_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {}
|
||||
|
||||
void handle_ocean_79_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {}
|
||||
@@ -17,8 +17,10 @@ class OceanMidAndFar : public BucketRenderer {
|
||||
public:
|
||||
OceanMidAndFar(const std::string& name, int my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void render_jak1(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void render_jak2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void draw_debug_window() override;
|
||||
void init_textures(TexturePool& pool) override;
|
||||
void init_textures(TexturePool& pool, GameVersion version) override;
|
||||
|
||||
private:
|
||||
void handle_ocean_far(DmaFollower& dma,
|
||||
@@ -27,6 +29,12 @@ class OceanMidAndFar : public BucketRenderer {
|
||||
void handle_ocean_mid(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_ocean_89_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_ocean_79_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
|
||||
DirectRenderer m_direct;
|
||||
OceanTexture m_texture_renderer;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,8 +13,8 @@ OceanNear::OceanNear(const std::string& name, int my_id)
|
||||
|
||||
void OceanNear::draw_debug_window() {}
|
||||
|
||||
void OceanNear::init_textures(TexturePool& pool) {
|
||||
m_texture_renderer.init_textures(pool);
|
||||
void OceanNear::init_textures(TexturePool& pool, GameVersion version) {
|
||||
m_texture_renderer.init_textures(pool, version);
|
||||
}
|
||||
|
||||
static bool is_end_tag(const DmaTag& tag, const VifCode& v0, const VifCode& v1) {
|
||||
@@ -33,6 +33,19 @@ void OceanNear::render(DmaFollower& dma,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (render_state->version) {
|
||||
case GameVersion::Jak1:
|
||||
render_jak1(dma, render_state, prof);
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
render_jak2(dma, render_state, prof);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OceanNear::render_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// jump to bucket
|
||||
auto data0 = dma.read_and_advance();
|
||||
ASSERT(data0.vif1() == 0);
|
||||
@@ -52,7 +65,7 @@ void OceanNear::render(DmaFollower& dma,
|
||||
{
|
||||
auto p = prof.make_scoped_child("texture");
|
||||
// TODO: this looks the same as the previous ocean renderer to me... why do it again?
|
||||
m_texture_renderer.handle_ocean_texture(dma, render_state, p);
|
||||
m_texture_renderer.handle_ocean_texture_jak1(dma, render_state, p);
|
||||
}
|
||||
|
||||
if (dma.current_tag().qwc != 2) {
|
||||
@@ -117,6 +130,88 @@ void OceanNear::render(DmaFollower& dma,
|
||||
m_common_ocean_renderer.flush_near(render_state, prof);
|
||||
}
|
||||
|
||||
void OceanNear::render_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// jump to bucket
|
||||
auto data0 = dma.read_and_advance();
|
||||
ASSERT(data0.vif1() == 0 || data0.vifcode1().kind == VifCode::Kind::NOP);
|
||||
ASSERT(data0.vif0() == 0 || data0.vifcode0().kind == VifCode::Kind::MARK);
|
||||
ASSERT(data0.size_bytes == 0);
|
||||
|
||||
// see if bucket is empty or not
|
||||
if (dma.current_tag_offset() == render_state->next_bucket) {
|
||||
// fmt::print("ocean-near: early exit!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto p = prof.make_scoped_child("texture");
|
||||
m_texture_renderer.handle_ocean_texture_jak2(dma, render_state, p);
|
||||
}
|
||||
|
||||
if (dma.current_tag().qwc != 2) {
|
||||
lg::error("abort OceanNear::render!");
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// direct setup
|
||||
{
|
||||
m_common_ocean_renderer.init_for_near();
|
||||
auto setup = dma.read_and_advance();
|
||||
ASSERT(setup.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(setup.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
ASSERT(setup.size_bytes == 32);
|
||||
}
|
||||
|
||||
// offset and base
|
||||
{
|
||||
auto ob = dma.read_and_advance();
|
||||
ASSERT(ob.size_bytes == 0);
|
||||
auto base = ob.vifcode0();
|
||||
auto off = ob.vifcode1();
|
||||
ASSERT(base.kind == VifCode::Kind::BASE);
|
||||
ASSERT(off.kind == VifCode::Kind::OFFSET);
|
||||
ASSERT(base.immediate == VU1_INPUT_BUFFER_BASE);
|
||||
ASSERT(off.immediate == VU1_INPUT_BUFFER_OFFSET);
|
||||
}
|
||||
|
||||
while (!is_end_tag(dma.current_tag(), dma.current_tag_vif0(), dma.current_tag_vif1())) {
|
||||
auto data = dma.read_and_advance();
|
||||
auto v0 = data.vifcode0();
|
||||
auto v1 = data.vifcode1();
|
||||
|
||||
if (v0.kind == VifCode::Kind::STCYCL && v1.kind == VifCode::Kind::UNPACK_V4_32) {
|
||||
ASSERT(v0.immediate == 0x404);
|
||||
auto up = VifCodeUnpack(v1);
|
||||
u16 addr = up.addr_qw + (up.use_tops_flag ? get_upload_buffer() : 0);
|
||||
ASSERT(addr + v1.num <= 1024);
|
||||
memcpy(m_vu_data + addr, data.data, 16 * v1.num);
|
||||
} else if (v0.kind == VifCode::Kind::MSCALF && v1.kind == VifCode::Kind::STMOD) {
|
||||
ASSERT(v1.immediate == 0);
|
||||
switch (v0.immediate) {
|
||||
case 0:
|
||||
run_call0_vu2c_jak2();
|
||||
break;
|
||||
case 39:
|
||||
run_call39_vu2c_jak2();
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("unknown ocean near call: {}", v0.immediate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
dma.read_and_advance();
|
||||
}
|
||||
|
||||
m_common_ocean_renderer.flush_near(render_state, prof);
|
||||
}
|
||||
|
||||
void OceanNear::xgkick(u16 addr) {
|
||||
m_common_ocean_renderer.kick_from_near((const u8*)&m_vu_data[addr]);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,23 @@ class OceanNear : public BucketRenderer {
|
||||
public:
|
||||
OceanNear(const std::string& name, int my_id);
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void render_jak1(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void render_jak2(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void draw_debug_window() override;
|
||||
void init_textures(TexturePool& pool) override;
|
||||
void init_textures(TexturePool& pool, GameVersion version) override;
|
||||
|
||||
private:
|
||||
void run_call0_vu2c();
|
||||
void run_call0_vu2c_jak2();
|
||||
void run_call39_vu2c();
|
||||
void run_call39_vu2c_jak2();
|
||||
void run_L15_vu2c();
|
||||
void run_L15_vu2c_jak2();
|
||||
void run_L21_vu2c();
|
||||
void run_L21_vu2c_jak2();
|
||||
void run_L23_vu2c();
|
||||
void run_L25_vu2c();
|
||||
void run_L25_vu2c_jak2();
|
||||
void run_L30_vu2c();
|
||||
void run_L32_vu2c();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,9 @@
|
||||
|
||||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
constexpr int OCEAN_TEX_TBP = 8160; // todo
|
||||
constexpr int OCEAN_TEX_TBP_JAK1 = 8160; // todo
|
||||
constexpr int OCEAN_TEX_TBP_JAK2 = 672;
|
||||
|
||||
OceanTexture::OceanTexture(bool generate_mipmaps)
|
||||
: m_generate_mipmaps(generate_mipmaps),
|
||||
m_result_texture(TEX0_SIZE,
|
||||
@@ -53,7 +55,7 @@ OceanTexture::~OceanTexture() {
|
||||
destroy_pc();
|
||||
}
|
||||
|
||||
void OceanTexture::init_textures(TexturePool& pool) {
|
||||
void OceanTexture::init_textures(TexturePool& pool, GameVersion version) {
|
||||
TextureInput in;
|
||||
in.gpu_texture = m_result_texture.texture();
|
||||
in.w = TEX0_SIZE;
|
||||
@@ -61,7 +63,14 @@ void OceanTexture::init_textures(TexturePool& pool) {
|
||||
in.debug_page_name = "PC-OCEAN";
|
||||
in.debug_name = fmt::format("pc-ocean-mip-{}", m_generate_mipmaps);
|
||||
in.id = pool.allocate_pc_port_texture();
|
||||
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP);
|
||||
switch (version) {
|
||||
case GameVersion::Jak1:
|
||||
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP_JAK1);
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
m_tex0_gpu = pool.give_texture_and_load_to_vram(in, OCEAN_TEX_TBP_JAK2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::draw_debug_window() {
|
||||
@@ -70,9 +79,9 @@ void OceanTexture::draw_debug_window() {
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
void OceanTexture::handle_ocean_texture_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// if we're doing mipmaps, render to temp.
|
||||
// otherwise, render directly to target.
|
||||
FramebufferTexturePairContext ctxt(m_generate_mipmaps ? m_temp_texture : m_result_texture);
|
||||
@@ -224,7 +233,169 @@ void OceanTexture::handle_ocean_texture(DmaFollower& dma,
|
||||
}
|
||||
|
||||
// give to gpu!
|
||||
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP);
|
||||
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP_JAK1);
|
||||
}
|
||||
|
||||
void OceanTexture::handle_ocean_texture_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
// if we're doing mipmaps, render to temp.
|
||||
// otherwise, render directly to target.
|
||||
FramebufferTexturePairContext ctxt(m_generate_mipmaps ? m_temp_texture : m_result_texture);
|
||||
// render to the first texture
|
||||
{
|
||||
// (set-display-gs-state arg0 21 128 128 0 0)
|
||||
auto data = dma.read_and_advance();
|
||||
(void)data;
|
||||
}
|
||||
|
||||
// set up GS for envmap texture drawing
|
||||
{
|
||||
// (ocean-texture-add-envmap arg0)
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == sizeof(AdGifData) + 16); // 16 for the giftag.
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
memcpy(&m_envmap_adgif, data.data + 16, sizeof(AdGifData));
|
||||
// HACK
|
||||
setup_renderer();
|
||||
}
|
||||
|
||||
// set up VIF
|
||||
{
|
||||
// (new 'static 'vif-tag)
|
||||
// (new 'static 'vif-tag :imm #x4 :cmd (vif-cmd offset))
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == 64);
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::NOP);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::DIRECT);
|
||||
ASSERT(data.vifcode0().immediate == 0);
|
||||
ASSERT(data.vifcode1().immediate == 0x4);
|
||||
}
|
||||
|
||||
// (dma-buffer-add-vu-function arg0 ocean-texture-vu1-block 1)
|
||||
dma.read_and_advance();
|
||||
|
||||
{
|
||||
// (ocean-texture-add-constants obj arg0)
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == sizeof(OceanTextureConstants));
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(data.vifcode0().immediate == 0x404);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
||||
ASSERT(data.vifcode1().immediate == TexVu1Data::CONSTANTS);
|
||||
memcpy(&m_texture_constants, data.data, sizeof(OceanTextureConstants));
|
||||
}
|
||||
|
||||
// vertices are uploaded double buffered
|
||||
m_texture_vertices_loading = m_texture_vertices_a;
|
||||
m_texture_vertices_drawing = m_texture_vertices_b;
|
||||
|
||||
// add first group of vertices
|
||||
{
|
||||
// (ocean-texture-add-verts arg0 sv-16)
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == sizeof(m_texture_vertices_a));
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(data.vifcode0().immediate == 0x404);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
ASSERT(data.vifcode1().num == data.size_bytes / 16);
|
||||
VifCodeUnpack up(data.vifcode1());
|
||||
ASSERT(up.addr_qw == 0);
|
||||
ASSERT(up.use_tops_flag == true);
|
||||
memcpy(m_texture_vertices_loading, data.data, sizeof(m_texture_vertices_a));
|
||||
}
|
||||
|
||||
// first call
|
||||
{
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == 0);
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(data.vifcode0().immediate == TexVu1Prog::START);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
run_L1_PC_jak2();
|
||||
}
|
||||
|
||||
// loop over vertex groups
|
||||
for (int i = 0; i < NUM_FRAG_LOOPS; i++) {
|
||||
auto verts = dma.read_and_advance();
|
||||
ASSERT(verts.size_bytes == sizeof(m_texture_vertices_a));
|
||||
ASSERT(verts.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(verts.vifcode0().immediate == 0x404);
|
||||
ASSERT(verts.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
ASSERT(verts.vifcode1().num == verts.size_bytes / 16);
|
||||
VifCodeUnpack up(verts.vifcode1());
|
||||
ASSERT(up.addr_qw == 0);
|
||||
ASSERT(up.use_tops_flag == true);
|
||||
memcpy(m_texture_vertices_loading, verts.data, sizeof(m_texture_vertices_a));
|
||||
|
||||
auto call = dma.read_and_advance();
|
||||
ASSERT(call.size_bytes == 0);
|
||||
ASSERT(call.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(call.vifcode0().immediate == TexVu1Prog::REST);
|
||||
ASSERT(call.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
run_L2_PC_jak2();
|
||||
}
|
||||
|
||||
// last upload does something weird...
|
||||
{
|
||||
// (ocean-texture-add-verts-last arg0 (the-as (inline-array vector) sv-48) sv-64)
|
||||
auto data0 = dma.read_and_advance();
|
||||
ASSERT(data0.size_bytes == 128 * 16);
|
||||
ASSERT(data0.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(data0.vifcode0().immediate == 0x404);
|
||||
ASSERT(data0.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
ASSERT(data0.vifcode1().num == data0.size_bytes / 16);
|
||||
VifCodeUnpack up0(data0.vifcode1());
|
||||
ASSERT(up0.addr_qw == 0);
|
||||
ASSERT(up0.use_tops_flag == true);
|
||||
memcpy(m_texture_vertices_loading, data0.data, 128 * 16);
|
||||
|
||||
auto data1 = dma.read_and_advance();
|
||||
ASSERT(data1.size_bytes == 64 * 16);
|
||||
ASSERT(data1.vifcode0().kind == VifCode::Kind::STCYCL);
|
||||
ASSERT(data1.vifcode0().immediate == 0x404);
|
||||
ASSERT(data1.vifcode1().kind == VifCode::Kind::UNPACK_V4_32);
|
||||
ASSERT(data1.vifcode1().num == data1.size_bytes / 16);
|
||||
VifCodeUnpack up1(data1.vifcode1());
|
||||
ASSERT(up1.addr_qw == 128);
|
||||
ASSERT(up1.use_tops_flag == true);
|
||||
memcpy(m_texture_vertices_loading + 128, data1.data, 64 * 16);
|
||||
}
|
||||
|
||||
// last rest call
|
||||
{
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == 0);
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(data.vifcode0().immediate == TexVu1Prog::REST);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
run_L2_PC_jak2();
|
||||
}
|
||||
|
||||
// last call
|
||||
{
|
||||
auto data = dma.read_and_advance();
|
||||
ASSERT(data.size_bytes == 0);
|
||||
ASSERT(data.vifcode0().kind == VifCode::Kind::MSCALF);
|
||||
ASSERT(data.vifcode0().immediate == TexVu1Prog::DONE);
|
||||
ASSERT(data.vifcode1().kind == VifCode::Kind::STMOD); // not sure why...
|
||||
// this program does nothing.
|
||||
}
|
||||
|
||||
flush(render_state, prof);
|
||||
if (m_generate_mipmaps) {
|
||||
// if we did mipmaps, the above code rendered to temp, and now we need to generate mipmaps
|
||||
// in the real output
|
||||
make_texture_with_mipmaps(render_state, prof);
|
||||
}
|
||||
|
||||
// (reset-display-gs-state *display* arg0)
|
||||
// dma.read_and_advance();
|
||||
|
||||
// give to gpu!
|
||||
render_state->texture_pool->move_existing_to_vram(m_tex0_gpu, OCEAN_TEX_TBP_JAK2);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
class OceanTexture {
|
||||
public:
|
||||
OceanTexture(bool generate_mipmaps);
|
||||
void handle_ocean_texture(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void init_textures(TexturePool& pool);
|
||||
void handle_ocean_texture_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_ocean_texture_jak2(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void init_textures(TexturePool& pool, GameVersion version);
|
||||
void draw_debug_window();
|
||||
~OceanTexture();
|
||||
|
||||
@@ -22,6 +25,10 @@ class OceanTexture {
|
||||
void run_L5_PC();
|
||||
void xgkick_PC(Vf* src);
|
||||
|
||||
void run_L1_PC_jak2();
|
||||
void run_L2_PC_jak2();
|
||||
void run_L3_PC_jak2();
|
||||
|
||||
void setup_renderer();
|
||||
void flush(SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
|
||||
@@ -394,6 +394,240 @@ void OceanTexture::xgkick_PC(Vf* src) {
|
||||
}
|
||||
}
|
||||
|
||||
void OceanTexture::run_L1_PC_jak2() {
|
||||
// L1:
|
||||
// lq.xyzw vf14_startx, 988(vi00) | maxw.xyzw vf01_ones, vf00, vf00
|
||||
vu.startx = Vf(m_texture_constants.start);
|
||||
// lq.xyzw vf02_offset, 989(vi00)
|
||||
// lq.xyzw vf03_tbuf, 986(vi00)
|
||||
// lq.xyzw vf04_dbuf, 987(vi00)
|
||||
// lq.xyzw vf05_giftag, 985(vi00)
|
||||
// lq.xyzw vf06_cam_nrm, 991(vi00)
|
||||
// lq.xyzw vf07_constants, 990(vi00)
|
||||
// iaddiu vi11_0x80, vi00, 0x80
|
||||
// mtir vi08_tptr, vf03_tbuf.x
|
||||
vu.tptr = get_tbuf();
|
||||
// mtir vi09_tbase, vf03_tbuf.x
|
||||
vu.tbase = get_tbuf();
|
||||
// mr32.xyzw vf03_tbuf, vf03_tbuf
|
||||
swap_tbuf();
|
||||
// xtop vi05_in_ptr
|
||||
vu.in_ptr = swap_vu_upload_buffers();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5_PC();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5_PC();
|
||||
|
||||
// nop :e
|
||||
// nop
|
||||
}
|
||||
|
||||
void OceanTexture::run_L2_PC_jak2() {
|
||||
// L2:
|
||||
// xtop vi05_in_ptr
|
||||
vu.in_ptr = swap_vu_upload_buffers();
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5_PC();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5_PC();
|
||||
|
||||
// mtir vi06_dbuf_write, vf04_dbuf.x
|
||||
vu.dbuf_write = get_dbuf();
|
||||
// bal vi12_ra, L3
|
||||
// mr32.xyzw vf04_dbuf, vf04_dbuf
|
||||
swap_dbuf();
|
||||
run_L3_PC_jak2();
|
||||
|
||||
// mtir vi03_dbuf_read_a, vf04_dbuf.x
|
||||
vu.dbuf_read_a = get_dbuf();
|
||||
// bal vi12_ra, L5
|
||||
// mtir vi04_dbuf_read_b, vf04_dbuf.y
|
||||
vu.dbuf_read_b = get_dbuf_other();
|
||||
run_L5_PC();
|
||||
|
||||
// nop :e
|
||||
// nop
|
||||
}
|
||||
|
||||
void OceanTexture::run_L3_PC_jak2() {
|
||||
Vf base_pos; // vf15
|
||||
u16 loop_idx;
|
||||
|
||||
Vf vtx0; // vf16
|
||||
Vf vtx1; // vf17
|
||||
Vf vtx2; // vf18
|
||||
Vf vtx3; // vf19
|
||||
|
||||
Vf res0; // vf20
|
||||
Vf res1; // vf21
|
||||
Vf res2; // vf22
|
||||
Vf res3; // vf23
|
||||
|
||||
Vf nrm0; // vf24
|
||||
Vf nrm1; // vf25
|
||||
Vf nrm2; // vf26
|
||||
|
||||
Vf reflect; // vf27
|
||||
|
||||
Vf cout0; // vf28
|
||||
Vf cout1; // vf29
|
||||
Vf cout2; // vf30
|
||||
Vf cout3; // vf31
|
||||
|
||||
Accumulator acc;
|
||||
const Vf ones(1, 1, 1, 1);
|
||||
const Vf vf00(0, 0, 0, 1);
|
||||
const u16 vi11 = 0x80;
|
||||
bool bc;
|
||||
|
||||
// clang-format off
|
||||
// L3:
|
||||
// ior vi07, vi06, vi00 | nop 56
|
||||
vu.dbuf_write_base = vu.dbuf_write;
|
||||
// move.xyzw vf15, vf14 | nop 57
|
||||
base_pos.move(Mask::xyzw, vu.startx);
|
||||
// iaddi vi01, vi00, 0x8 | nop 58
|
||||
loop_idx = 8;
|
||||
// lq.xyzw vf24, 1(vi05) | mulw.xyzw vf20, vf15, vf00 59 (?? what are they doing here)
|
||||
res0.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm0, vu.in_ptr + 1);
|
||||
// lq.xyzw vf26, 3(vi05) | mulw.xyzw vf21, vf15, vf00 60
|
||||
res1.mul(Mask::xyzw, base_pos, 1.f); lq_buffer(Mask::xyzw, nrm2, vu.in_ptr + 5);
|
||||
// nop | mulw.xyzw vf22, vf15, vf00 61
|
||||
lq_buffer(Mask::xyzw, nrm2, vu.in_ptr + 5);
|
||||
// nop | mulw.xyzw vf23, vf15, vf00 62
|
||||
res3.mul(Mask::xyzw, base_pos, 1.f);
|
||||
// nop | addx.x vf21, vf21, vf02 63
|
||||
res1.add(Mask::x, res1, m_texture_constants.offsets.x());
|
||||
// nop | addy.x vf22, vf22, vf02 64
|
||||
res2.add(Mask::x, res2, m_texture_constants.offsets.y());
|
||||
L4:
|
||||
// nop | addz.x vf23, vf23, vf02 65
|
||||
res3.add(Mask::x, res3, m_texture_constants.offsets.z());
|
||||
// nop | addw.x vf15, vf15, vf02 66
|
||||
base_pos.add(Mask::x, base_pos, m_texture_constants.offsets.w());
|
||||
// sq.xyzw vf20, 2(vi06) | mulx.x vf28, vf01, vf24 67
|
||||
cout0.mul(Mask::x, ones, nrm0.x()); sq_buffer(Mask::xyzw, res0, vu.dbuf_write + 2);
|
||||
// sq.xyzw vf21, 5(vi06) | muly.x vf29, vf01, vf24 68
|
||||
cout1.mul(Mask::x, ones, nrm0.y()); sq_buffer(Mask::xyzw, res1, vu.dbuf_write + 5);
|
||||
// sq.xyzw vf22, 8(vi06) | mulz.x vf30, vf01, vf24 69
|
||||
cout2.mul(Mask::x, ones, nrm0.z()); sq_buffer(Mask::xyzw, res2, vu.dbuf_write + 8);
|
||||
// sq.xyzw vf23, 11(vi06) | mulw.x vf31, vf01, vf24 70
|
||||
cout3.mul(Mask::x, ones, nrm0.w()); sq_buffer(Mask::xyzw, res3, vu.dbuf_write + 11);
|
||||
// lq.xyzw vf16, 0(vi05) | mulx.y vf28, vf01, vf26 71
|
||||
cout0.mul(Mask::y, ones, nrm2.x()); lq_buffer(Mask::xyzw, vtx0, vu.in_ptr);
|
||||
// lq.xyzw vf17, 2(vi05) | muly.y vf29, vf01, vf26 72
|
||||
cout1.mul(Mask::y, ones, nrm2.y()); lq_buffer(Mask::xyzw, vtx1, vu.in_ptr + 2);
|
||||
// lq.xyzw vf18, 4(vi05) | mulz.y vf30, vf01, vf26 73
|
||||
cout2.mul(Mask::y, ones, nrm2.z()); lq_buffer(Mask::xyzw, vtx2, vu.in_ptr + 4);
|
||||
// lq.xyzw vf19, 6(vi05) | mulw.y vf31, vf01, vf26 74
|
||||
cout3.mul(Mask::y, ones, nrm2.w()); lq_buffer(Mask::xyzw, vtx3, vu.in_ptr + 6);
|
||||
// iaddi vi05, vi05, 0x8 | ftoi0.xyzw vf16, vf16 75
|
||||
vtx0.ftoi0(Mask::xyzw, vtx0); vu.in_ptr = vu.in_ptr + 8;
|
||||
// nop | ftoi0.xyzw vf17, vf17 76
|
||||
vtx1.ftoi0(Mask::xyzw, vtx1);
|
||||
// nop | ftoi0.xyzw vf18, vf18 77
|
||||
vtx2.ftoi0(Mask::xyzw, vtx2);
|
||||
// iaddi vi01, vi01, -0x1 | ftoi0.xyzw vf19, vf19 78
|
||||
vtx3.ftoi0(Mask::xyzw, vtx3); loop_idx = loop_idx + -1;
|
||||
// sq.xyzw vf16, 1(vi06) | add.xyzw vf28, vf28, vf07 79
|
||||
cout0.add(Mask::xyzw, cout0, m_texture_constants.cam_nrm); sq_buffer(Mask::xyzw, vtx0, vu.dbuf_write + 1);
|
||||
// sq.xyzw vf17, 4(vi06) | add.xyzw vf29, vf29, vf07 80
|
||||
cout1.add(Mask::xyzw, cout1, m_texture_constants.cam_nrm); sq_buffer(Mask::xyzw, vtx1, vu.dbuf_write + 4);
|
||||
// sq.xyzw vf18, 7(vi06) | add.xyzw vf30, vf30, vf07 81
|
||||
cout2.add(Mask::xyzw, cout2, m_texture_constants.cam_nrm); sq_buffer(Mask::xyzw, vtx2, vu.dbuf_write + 7);
|
||||
// sq.xyzw vf19, 10(vi06) | add.xyzw vf31, vf31, vf07 82
|
||||
cout3.add(Mask::xyzw, cout3, m_texture_constants.cam_nrm); sq_buffer(Mask::xyzw, vtx3, vu.dbuf_write + 10);
|
||||
// lq.xyzw vf24, 1(vi05) | sub.zw vf28, vf01, vf00 83
|
||||
cout0.sub(Mask::zw, ones, vf00); lq_buffer(Mask::xyzw, nrm0, vu.in_ptr + 1);
|
||||
// lq.xyzw vf26, 5(vi05) | sub.zw vf29, vf01, vf00 84
|
||||
cout1.sub(Mask::zw, ones, vf00); lq_buffer(Mask::xyzw, nrm2, vu.in_ptr + 5);
|
||||
// nop | sub.zw vf30, vf01, vf00 85
|
||||
cout2.sub(Mask::zw, ones, vf00);
|
||||
// nop | sub.zw vf31, vf01, vf00 86
|
||||
cout3.sub(Mask::zw, ones, vf00);
|
||||
// sq.xyzw vf28, 0(vi06) | mulw.xyzw vf20, vf15, vf00 87
|
||||
res0.mul(Mask::xyzw, base_pos, 1.f); sq_buffer(Mask::xyzw, cout0, vu.dbuf_write);
|
||||
// sq.xyzw vf29, 3(vi06) | mulw.xyzw vf21, vf15, vf00 88
|
||||
res1.mul(Mask::xyzw, base_pos, 1.f); sq_buffer(Mask::xyzw, cout1, vu.dbuf_write + 3);
|
||||
// sq.xyzw vf30, 6(vi06) | mulw.xyzw vf22, vf15, vf00 89
|
||||
res2.mul(Mask::xyzw, base_pos, 1.f); sq_buffer(Mask::xyzw, cout2, vu.dbuf_write + 6);
|
||||
// sq.xyzw vf31, 9(vi06) | mulw.xyzw vf23, vf15, vf00 90
|
||||
res3.mul(Mask::xyzw, base_pos, 1.f); sq_buffer(Mask::xyzw, cout3, vu.dbuf_write + 9);
|
||||
// BRANCH!
|
||||
// ibgtz vi01, L4 | addx.x vf21, vf21, vf02 91
|
||||
res1.add(Mask::x, res1, m_texture_constants.offsets.x()); bc = ((s16)loop_idx) > 0;
|
||||
// iaddi vi06, vi06, 0xc | addy.x vf22, vf22, vf02 92
|
||||
res2.add(Mask::x, res2, m_texture_constants.offsets.y()); vu.dbuf_write = vu.dbuf_write + 12;
|
||||
if (bc) { goto L4; }
|
||||
|
||||
// lq.xyzw vf28, 0(vi07) | addx.y vf14, vf14, vf02 93
|
||||
vu.startx.add(Mask::y, vu.startx, m_texture_constants.offsets.x()); lq_buffer(Mask::xyzw, cout0, vu.dbuf_write_base);
|
||||
// lq.xyzw vf16, 1(vi07) | nop 94
|
||||
lq_buffer(Mask::xyzw, vtx0, vu.dbuf_write_base + 1);
|
||||
// sq.xyzw vf20, 2(vi06) | nop 95
|
||||
sq_buffer(Mask::xyzw, res0, vu.dbuf_write + 2);
|
||||
// sq.xyzw vf28, 0(vi06) | nop 96
|
||||
sq_buffer(Mask::xyzw, cout0, vu.dbuf_write);
|
||||
// jr vi12 | nop 97
|
||||
// sq.xyzw vf16, 1(vi06) | nop 98
|
||||
sq_buffer(Mask::xyzw, vtx0, vu.dbuf_write + 1);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void OceanTexture::setup_renderer() {
|
||||
m_pc.vtx_idx = 0;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ out vec4 fragment_color;
|
||||
out vec3 tex_coord;
|
||||
out float fog;
|
||||
|
||||
const float SCISSOR_ADJUST = 512.0/448.0;
|
||||
const float SCISSOR_ADJUST = HEIGHT_SCALE * 512.0/448.0;
|
||||
|
||||
uniform int bucket;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(define ocean-mid-block (new 'static 'vu-function :length #x490 :qlength #x248))
|
||||
(define ocean-mid-block (new 'static 'vu-function #|:length #x490 :qlength #x248|#))
|
||||
|
||||
(defmethod ocean-mid-setup-constants ocean ((obj ocean) (arg0 ocean-mid-constants))
|
||||
(let ((v1-0 *math-camera*))
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(define ocean-near-block (new 'static 'vu-function :length #x3dd :qlength #x1ef))
|
||||
(define ocean-near-block (new 'static 'vu-function #|:length #x3dd :qlength #x1ef|#))
|
||||
|
||||
(defmethod ocean-near-add-call ocean ((obj ocean) (arg0 dma-buffer) (arg1 int))
|
||||
(let* ((v1-0 arg0)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(define ocean-texture-vu1-block (new 'static 'vu-function :length #x7c :qlength 62))
|
||||
(define ocean-texture-vu1-block (new 'static 'vu-function #|:length #x7c :qlength 62|#))
|
||||
|
||||
(defmethod ocean-texture-setup-constants ocean ((obj ocean) (arg0 ocean-texture-constants))
|
||||
(set! (-> arg0 giftag tag)
|
||||
@@ -203,8 +203,8 @@
|
||||
)
|
||||
(ocean-texture-add-call-rest obj arg0)
|
||||
(ocean-texture-add-call-done obj arg0)
|
||||
(ocean-method-81 obj arg0)
|
||||
(reset-display-gs-state *display* arg0)
|
||||
;; (ocean-method-81 obj arg0)
|
||||
;; (reset-display-gs-state *display* arg0)
|
||||
0
|
||||
(none)
|
||||
)
|
||||
|
||||
@@ -1207,11 +1207,14 @@
|
||||
(let* ((s4-0 (-> *display* frames (-> *display* on-screen) global-buf))
|
||||
(s5-2 (-> s4-0 base))
|
||||
)
|
||||
(if (-> *time-of-day-context* sky)
|
||||
(ocean-method-89 obj s4-0)
|
||||
)
|
||||
;; TODO handle ocean::79 and ocean::89
|
||||
;; diasble tod ocean stuff
|
||||
;; (if (-> *time-of-day-context* sky)
|
||||
;; (ocean-method-89 obj s4-0)
|
||||
;; )
|
||||
(draw-ocean-texture obj s4-0 (the-as int (-> obj verts)))
|
||||
(ocean-method-79 obj s4-0)
|
||||
;; disable whatever this is
|
||||
;; (ocean-method-79 obj s4-0)
|
||||
(init-buffer! obj s4-0)
|
||||
(if (-> obj far-on)
|
||||
(draw-ocean-far obj s4-0)
|
||||
@@ -1230,7 +1233,7 @@
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) bucket-group)
|
||||
(bucket-id bucket-6)
|
||||
(bucket-id ocean-mid-far)
|
||||
s5-2
|
||||
(the-as (pointer dma-tag) a3-3)
|
||||
)
|
||||
@@ -1256,7 +1259,7 @@
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) bucket-group)
|
||||
(bucket-id bucket-310)
|
||||
(bucket-id ocean-near)
|
||||
s5-3
|
||||
(the-as (pointer dma-tag) a3-5)
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
(bucket-3 3) ;; blit displays
|
||||
(tex-lcom-sky-pre 4) ;; tex
|
||||
(sky-draw 5) ;; sky
|
||||
(bucket-6 6) ;; ocean
|
||||
(ocean-mid-far 6) ;; ocean
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; All levels with tfrag tpage
|
||||
@@ -389,7 +389,7 @@
|
||||
|
||||
(tex-lcom-sky-post 309)
|
||||
|
||||
(bucket-310 310) ;; ocean
|
||||
(ocean-near 310) ;; ocean
|
||||
(bucket-311 311) ;; depth-cue
|
||||
|
||||
(tex-all-sprite 312)
|
||||
|
||||
+6
-2
@@ -1485,7 +1485,7 @@
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) bucket-group)
|
||||
(bucket-id bucket-6)
|
||||
(bucket-id ocean-mid-far)
|
||||
s5-2
|
||||
(the-as (pointer dma-tag) a3-3)
|
||||
)
|
||||
@@ -1511,7 +1511,7 @@
|
||||
)
|
||||
(dma-bucket-insert-tag
|
||||
(-> *display* frames (-> *display* on-screen) bucket-group)
|
||||
(bucket-id bucket-310)
|
||||
(bucket-id ocean-near)
|
||||
s5-3
|
||||
(the-as (pointer dma-tag) a3-5)
|
||||
)
|
||||
@@ -1613,3 +1613,7 @@
|
||||
|
||||
;; definition (debug) for function test-to-from-spr
|
||||
;; ERROR: function was not converted to expressions. Cannot decompile.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user