Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[graphics] Ocean Mid (in progress) #1232

Merged
merged 6 commits into from
Mar 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/util/colors.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace colors {
// some reasonable colors that are different from each other
constexpr int COLOR_COUNT = 131;
u32 common_colors[COLOR_COUNT] = {
constexpr u32 common_colors[COLOR_COUNT] = {
0xF0F8FE, 0xFAEBD7, 0x00FFFF, 0x70DB93, 0xF0FFFF, 0xF5F5DC, 0x000000, 0x0000FF, 0x9F5F9F,
0xB5A642, 0xD9D919, 0x8C7853, 0xA52A2A, 0x5F9EA0, 0xD2691E, 0xB87333, 0xFF7F50, 0xDC143C,
0x00FFFF, 0x00008B, 0x5C4033, 0x008B8B, 0xB8860B, 0xA9A9A9, 0x006400, 0xBDB76B, 0x8B008B,
Expand Down
42 changes: 29 additions & 13 deletions decompiler/VuDisasm/VuDisassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,18 +830,25 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
vi_src(instr.src.at(1).to_string(m_label_names), mips2c_format));
case VuInstrK::IOR:
if (instr.src.at(1).is_int_reg(0)) {
ASSERT(!instr.dst->is_int_reg(0));
ASSERT(!instr.src.at(0).is_int_reg(0));
if (mips2c_format) {
return fmt::format("vis[{}] = vis[{}];", instr.dst->to_string(m_label_names),
instr.src.at(0).to_string(m_label_names));
fmt::print("instr: {}\n", to_string(instr));
if (instr.src.at(0).is_int_reg(0) && instr.src.at(1).is_int_reg(0)) {
return fmt::format("vu.{} = 0;", instr.dst->to_string(m_label_names));
} else {
return fmt::format("vu.{} = vu.{};", instr.dst->to_string(m_label_names),
instr.src.at(0).to_string(m_label_names));
ASSERT(!instr.dst->is_int_reg(0));
ASSERT(!instr.src.at(0).is_int_reg(0));
if (mips2c_format) {
return fmt::format("vis[{}] = vis[{}];", instr.dst->to_string(m_label_names),
instr.src.at(0).to_string(m_label_names));
} else {
return fmt::format("vu.{} = vu.{};", instr.dst->to_string(m_label_names),
instr.src.at(0).to_string(m_label_names));
}
}

} else {
goto unknown;
return fmt::format("vu.{} = vu.{} | vu.{};", instr.dst->to_string(m_label_names),
instr.src.at(0).to_string(m_label_names),
instr.src.at(1).to_string(m_label_names));
}

case VuInstrK::MFP:
Expand All @@ -865,8 +872,7 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
bc_to_part(*instr.second_src_field));

case VuInstrK::ERLENG:
return fmt::format("vu.P = erleng(Mask::{}, vu.{}); /* TODO erleng */",
mask_to_string(*instr.mask), instr.src.at(0).to_string(m_label_names));
return fmt::format("vu.P = erleng(vu.{});", instr.src.at(0).to_string(m_label_names));
case VuInstrK::RSQRT:
return fmt::format(
"c->Q = c->vf_src({}).vf.{}() / std::sqrt(c->vf_src({}).vf.{}());",
Expand All @@ -891,8 +897,11 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
vf_src(instr.src.at(0).to_string(m_label_names), mips2c_format),
vf_src(instr.src.at(1).to_string(m_label_names), mips2c_format));
case VuInstrK::FCAND:
return fmt::format("ASSERT(false); vu.vi01 = cf & 0x{:x};\n", instr.src.at(0).value());

return fmt::format("fcand(vu.vi01, 0x{:x}, cf);\n", instr.src.at(0).value());
case VuInstrK::FCOR:
return fmt::format("fcor(vu.vi01, 0x{:x}, cf);\n", instr.src.at(0).value());
case VuInstrK::FCSET:
return fmt::format("cf = 0x{:x};\n", instr.src.at(0).value());
case VuInstrK::ADDbc:
case VuInstrK::SUBbc:
case VuInstrK::MULbc:
Expand Down Expand Up @@ -971,6 +980,9 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.{});", mask_to_string(*instr.mask),
instr.src.at(0).to_string(m_label_names),
instr.src.at(1).to_string(m_label_names));
case VuInstrK::MULAq:
return fmt::format("vu.acc.mula(Mask::{}, vu.{}, vu.Q);", mask_to_string(*instr.mask),
instr.src.at(0).to_string(m_label_names));
case VuInstrK::MULAbc:
return fmt::format(mips2c_format
? "c->acc.vf.mula(Mask::{}, c->vf_src({}).vf, c->vf_src({}).vf.{}());"
Expand All @@ -985,13 +997,17 @@ std::string VuDisassembler::to_cpp(const VuInstruction& instr, bool mips2c_forma
return fmt::format("vu.{} = xtop();", instr.src.at(0).to_string(m_label_names));
default:
unk++;
fmt::print("unknown 0 is {}\n", to_string(instr));

return "ASSERT(false);"; //"???";
}

unknown:

unk++;
return "???";
fmt::print("unknown 1 is {}\n", to_string(instr));

return "ASSERT(false);";
}

std::string VuDisassembler::to_string(const VuInstruction& instr) const {
Expand Down
2 changes: 2 additions & 0 deletions game/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ set(RUNTIME_SOURCE
graphics/opengl_renderer/foreground/Generic2_DMA.cpp
graphics/opengl_renderer/foreground/Generic2_Build.cpp
graphics/opengl_renderer/foreground/Generic2_OpenGL.cpp
graphics/opengl_renderer/ocean/OceanMid.cpp
graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
graphics/opengl_renderer/ocean/OceanMidAndFar.cpp
graphics/opengl_renderer/ocean/OceanTexture.cpp
graphics/opengl_renderer/ocean/OceanTexture_PC.cpp
Expand Down
2 changes: 2 additions & 0 deletions game/graphics/opengl_renderer/DirectRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class DirectRenderer : public BucketRenderer {
m_blend_state.d = GsAlpha::BlendMode::SOURCE;
}

void set_mipmap(bool en) { m_debug_state.disable_mipmap = !en; }

private:
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
Expand Down
1 change: 1 addition & 0 deletions game/graphics/opengl_renderer/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,5 @@ ShaderLibrary::ShaderLibrary() {
at(ShaderId::EYE) = {"eye"};
at(ShaderId::GENERIC) = {"generic"};
at(ShaderId::OCEAN_TEXTURE) = {"ocean_texture"};
at(ShaderId::OCEAN_TEXTURE_MIPMAP) = {"ocean_texture_mipmap"};
}
1 change: 1 addition & 0 deletions game/graphics/opengl_renderer/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum class ShaderId {
EYE = 11,
GENERIC = 12,
OCEAN_TEXTURE = 13,
OCEAN_TEXTURE_MIPMAP = 14,
MAX_SHADERS
};

Expand Down
145 changes: 145 additions & 0 deletions game/graphics/opengl_renderer/ocean/OceanMid.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#include "OceanMid.h"

static bool is_end_tag(const DmaTag& tag, const VifCode& v0, const VifCode& v1) {
return tag.qwc == 2 && tag.kind == DmaTag::Kind::CNT && v0.kind == VifCode::Kind::NOP &&
v1.kind == VifCode::Kind::DIRECT;
}

OceanMid::OceanMid() {
for (auto& x : m_vu_data) {
x.fill(999.);
}
vu.vf25 = Vf(1, 1, 1, 1);
}

void OceanMid::run(DmaFollower& dma,
SharedRenderState* render_state,
ScopedProfilerNode& prof,
DirectRenderer& direct) {
// 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);
// TODO
} else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 &&
v1.kind == VifCode::Kind::MSCALF) {
switch (v1.immediate) {
case 46:
run_call46_vu2c(render_state, prof, direct);
break;
case 73:
run_call73_vu2c(render_state, prof, direct);
break;
case 107:
run_call107_vu2c(render_state, prof, direct);
break;
case 275:
run_call275_vu2c(render_state, prof, direct);
break;
default:
fmt::print("unknown call1: {}\n", v1.immediate);
}
// TODO
} 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:
fmt::print("unknown call2: {}\n", v0.immediate);
ASSERT(false);
}

// TODO
}

else {
fmt::print("{} {}\n", data.vifcode0().print(), data.vifcode1().print());
ASSERT(false);
}
}
}

void OceanMid::run_call0() {
run_call0_vu2c();
}
Loading