[jak 2] ETIE (#2326)

Definitely needs a clean up pass, but I think the functionality is very
close.

There's a few "hacks" still:
- I am using the emerc logic for environment mapping, which doesn't care
about the length of the normals. I can't figure out how the normal
scaling worked in etie. I want to do a little bit more experimentation
with this before merging.
- There is some part about adgifs for TIE and ETIE that I don't
understand. The clearly correct behavior of TIE/ETIE is that the alpha
settings from the adgif shader are overwritten by the settings from the
renderer. But I can't figure out how this happens in all cases.
- Fade out is completely disabled. I think this is fine because the
performance difference isn't bad. But if you are comparing screenshots
with PCSX2, it will make things look a tiny bit different.
This commit is contained in:
water111
2023-03-17 20:35:26 -04:00
committed by GitHub
parent 6670124296
commit 2fa4a23ea1
41 changed files with 9101 additions and 858 deletions
+6
View File
@@ -225,6 +225,8 @@ VuDisassembler::VuDisassembler(VuKind kind) : m_kind(kind) {
add_op(VuInstrK::SQRT, "sqrt").fsf_zero().ftf_0().vis_zero().dst_q().src_vft();
add_op(VuInstrK::SQD, "sqd").dst_mask().src_vfs().src_vit();
add_op(VuInstrK::ERLENG, "erleng").dst_mask().vft_zero().src_vfs().dst_p();
add_op(VuInstrK::ESUM, "esum").dst_mask().vft_zero().src_vfs().dst_p();
add_op(VuInstrK::ESADD, "esadd").dst_mask().vft_zero().src_vfs().dst_p();
add_op(VuInstrK::ELENG, "eleng").dst_mask().vft_zero().src_vfs().dst_p();
add_op(VuInstrK::MFP, "mfp").dst_mask().dst_vft().src_p();
}
@@ -294,10 +296,14 @@ VuInstrK VuDisassembler::lower_kind(u32 in) {
return VuInstrK::XTOP;
case 0b11011'1111'00:
return VuInstrK::XGKICK;
case 0b11100'1111'00:
return VuInstrK::ESADD;
case 0b11100'1111'10:
return VuInstrK::ELENG;
case 0b11100'1111'11:
return VuInstrK::ERLENG;
case 0b11101'1111'10:
return VuInstrK::ESUM;
case 0b11110'1111'11:
return VuInstrK::WAITP;
}
+2 -2
View File
@@ -126,13 +126,13 @@ enum class VuInstrK {
JALR,
MFP,
WAITP,
// ESADD,
ESADD,
// ERSADD,
ELENG,
ERLENG,
// EATANxy,
// EATANxz,
// ESUM,
ESUM,
// ERCPR,
// ESQRT,
// ERSQRT,
+14 -16
View File
@@ -24991,13 +24991,14 @@
;; etie-vu1 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#|
(deftype etie-consts (structure)
((gifbufs qword :inline :offset-assert 0)
(adgif qword :inline :offset-assert 16)
(alpha qword :inline :offset-assert 32)
(strgif qword :inline :offset-assert 48)
(envgif qword :inline :offset-assert 64)
;(adgif qword :inline :offset-assert 16)
(adgif gs-gif-tag :inline :offset-assert 16)
;;(alpha qword :inline :offset-assert 32)
(alpah gs-adcmd :inline)
(strgif gs-gif-tag :inline :offset-assert 48)
(envgif gs-gif-tag :inline :offset-assert 64)
(envmap adgif-shader :inline :offset-assert 80)
(pers0 vector :inline :offset-assert 160)
(pers1 vector :inline :offset-assert 176)
@@ -25006,27 +25007,24 @@
:size-assert #xc0
:flag-assert #x9000000c0
)
|#
#|
(deftype etie-matrix (structure)
((rmtx matrix :inline :offset-assert 0)
(nmtx matrix3 :inline :offset-assert 64)
(morph float :offset-assert 76)
(fog float :offset-assert 92)
(fade uint32 :offset-assert 108)
(morph float :offset 76)
(fog float :offset 92)
(fade uint32 :offset 108)
(tint qword :inline :offset-assert 112)
)
:method-count-assert 9
:size-assert #x80
:flag-assert #x900000080
)
|#
;; (define-extern etie-vu1-block object)
;; (define-extern etie-magic function)
;; (define-extern etie-init-consts function)
(define-extern etie-init-engine (function dma-buffer none))
(define-extern etie-vu1-block vu-function)
(define-extern etie-magic (function int int))
(define-extern etie-init-consts (function etie-consts gs-alpha none))
(define-extern etie-init-engine (function dma-buffer gs-alpha gs-test none))
(define-extern etie-end-buffer (function dma-buffer none))
;; (define-extern etie-float-reg-bp function)
;; (define-extern etie-float-reg function)
@@ -25201,7 +25199,7 @@
(define-extern draw-drawable-tree-instance-tie (function drawable-tree-instance-tie level none))
(define-extern tie-init-scissor-buf (function bucket-id gs-alpha gs-test gs-test none))
(define-extern tie-init-buf (function bucket-id gs-alpha gs-test gs-test none))
(define-extern tie-init-envmap-buf (function bucket-id gs-alpha int int none))
(define-extern tie-init-envmap-buf (function bucket-id gs-alpha gs-test none))
(define-extern tie-init-envmap-scissor-buf (function bucket-id gs-alpha int int none))
(define-extern *tie-init-table* (inline-array tie-init-data))
(define-extern tie-vu1-init-buffers (function none))
@@ -11005,5 +11005,17 @@
"(method 98 gun-buoy)": [
[46, "v1", "collide-shape-moving"],
[76, "v1", "collide-shape-moving"]
],
"etie-init-engine": [
[[3, 10], "a0", "dma-packet"],
[[12, 19], "a0", "gs-gif-tag"],
[24, "a0", "(pointer gs-reg64)"],
[[34, 48], "a0", "dma-packet"],
[[58, 66], "a0", "dma-packet"],
[[68, 75], "a0", "dma-packet"],
[[79, 86], "a0", "(pointer uint32)"],
[[87, 94], "a0", "(pointer vif-tag)"]
]
}
+4 -1
View File
@@ -16,7 +16,8 @@ void TextureDB::add_texture(u32 tpage,
u16 h,
const std::string& tex_name,
const std::string& tpage_name,
const std::vector<std::string>& level_names) {
const std::vector<std::string>& level_names,
u32 num_mips) {
auto existing_tpage_name = tpage_names.find(tpage);
if (existing_tpage_name == tpage_names.end()) {
tpage_names[tpage] = tpage_name;
@@ -32,6 +33,7 @@ void TextureDB::add_texture(u32 tpage,
ASSERT(existing_tex->second.h == h);
ASSERT(existing_tex->second.rgba_bytes == data);
ASSERT(existing_tex->second.page == tpage);
ASSERT(existing_tex->second.num_mips == num_mips);
} else {
auto& new_tex = textures[combo_id];
new_tex.rgba_bytes = data;
@@ -39,6 +41,7 @@ void TextureDB::add_texture(u32 tpage,
new_tex.w = w;
new_tex.h = h;
new_tex.page = tpage;
new_tex.num_mips = num_mips;
}
for (const auto& level_name : level_names) {
texture_ids_per_level[level_name].insert(combo_id);
+3 -1
View File
@@ -15,6 +15,7 @@ struct TextureDB {
std::string name;
u32 page;
std::vector<u32> rgba_bytes;
u32 num_mips = -1;
};
std::unordered_map<u32, TextureData> textures;
@@ -28,7 +29,8 @@ struct TextureDB {
u16 h,
const std::string& tex_name,
const std::string& tpage_name,
const std::vector<std::string>& level_names);
const std::vector<std::string>& level_names,
u32 num_mips);
void replace_textures(const fs::path& path);
};
+6 -6
View File
@@ -537,7 +537,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
} else if (tex.psm == int(PSM::PSMT8) && tex.clutpsm == int(CPSM::PSMCT16)) {
// will store output pixels, rgba (8888)
@@ -580,7 +580,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
} else if (tex.psm == int(PSM::PSMCT16) && tex.clutpsm == 0) {
// not a clut.
@@ -605,7 +605,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
} else if (tex.psm == int(PSM::PSMT4) && tex.clutpsm == int(CPSM::PSMCT16)) {
// will store output pixels, rgba (8888)
@@ -646,7 +646,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
} else if (tex.psm == int(PSM::PSMT4) && tex.clutpsm == int(CPSM::PSMCT32)) {
// will store output pixels, rgba (8888)
@@ -687,7 +687,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
} else if (tex.psm == int(PSM::PSMCT32) && tex.clutpsm == 0) {
// not a clut.
@@ -712,7 +712,7 @@ TPageResultStats process_tpage(ObjectFileData& data,
file_util::write_rgba_png(texture_dump_dir / fmt::format("{}.png", tex.name), out.data(),
tex.w, tex.h);
texture_db.add_texture(texture_page.id, tex_id, out, tex.w, tex.h, tex.name,
texture_page.name, level_names);
texture_page.name, level_names, tex.num_mips);
stats.successful_textures++;
}
+36
View File
@@ -445,6 +445,15 @@ std::string TFragment::print(const PrintSettings& settings, int indent) const {
return result;
}
void memcpy_plain_data(u8* dst, const Ref& ref, size_t size_bytes) {
const auto& words = ref.data->words_by_seg.at(ref.seg);
for (size_t i = 0; i < size_bytes; i++) {
size_t byte_offset = ref.byte_offset + i;
u8 byte = words.at(byte_offset / 4).get_byte(byte_offset % 4);
memcpy(dst + i, &byte, sizeof(u8));
}
}
void TieFragment::read_from_file(TypedRef ref,
const decompiler::DecompilerTypeSystem& dts,
DrawStats* stats,
@@ -492,6 +501,15 @@ void TieFragment::read_from_file(TypedRef ref,
}
stats->total_tie_prototype_tris += num_tris;
if (version > GameVersion::Jak1) {
u16 normals_qwc = read_plain_data_field<u16>(ref, "normal-count", dts);
if (normals_qwc) {
normals.resize(16 * normals_qwc);
auto normals_data_ref = deref_label(get_field_ref(ref, "normal-ref", dts));
memcpy_plain_data((u8*)normals.data(), normals_data_ref, normals_qwc * 16);
}
}
}
std::string TieFragment::print(const PrintSettings& /*settings*/, int indent) const {
@@ -1037,6 +1055,24 @@ void PrototypeBucketTie::read_from_file(TypedRef ref,
for (int i = 0; i < int(8 * time_of_day.height); i++) {
time_of_day.colors.push_back(deref_u32(palette, 3 + i));
}
if (version > GameVersion::Jak1) {
auto fr = get_field_ref(ref, "envmap-shader", dts);
const auto& word = fr.data->words_by_seg.at(fr.seg).at(fr.byte_offset / 4);
if (word.kind() == decompiler::LinkedWord::PTR) {
has_envmap_shader = true;
Ref envmap_shader_ref(deref_label(fr));
for (int i = 0; i < 5 * 16; i++) {
int byte = envmap_shader_ref.byte_offset + i;
u8 val =
ref.ref.data->words_by_seg.at(envmap_shader_ref.seg).at(byte / 4).get_byte(byte % 4);
envmap_shader[i] = val;
}
}
u32 tint = read_plain_data_field<u32>(ref, "tint-color", dts);
memcpy(tint_color.data(), &tint, 4);
}
}
std::string PrototypeBucketTie::print(const PrintSettings& settings, int indent) const {
+6 -1
View File
@@ -6,6 +6,7 @@
#include <vector>
#include "common/common_types.h"
#include "common/math/Vector.h"
#include "common/versions.h"
#include "decompiler/level_extractor/common_formats.h"
@@ -406,6 +407,8 @@ struct TieFragment : public Drawable {
std::string debug_label_name;
std::vector<s8> normals;
// todo, lots more
};
@@ -479,7 +482,9 @@ struct PrototypeBucketTie {
TimeOfDayPalette time_of_day;
// todo envmap shader
bool has_envmap_shader = false;
u8 envmap_shader[5 * 16]; // jak 2 only
math::Vector<u8, 4> tint_color;
// todo collide-frag
DrawableInlineArrayCollideFragment collide_frag;
// todo tie-colors
+2 -3
View File
@@ -2070,9 +2070,8 @@ void make_tfrag3_data(std::map<u32, std::vector<GroupedDraw>>& draws,
vtx.z = vert.pre_cam_trans_pos.z();
vtx.s = vert.stq.x();
vtx.t = vert.stq.y();
vtx.q_unused = vert.stq.z();
// if this is true, we can remove a divide in the shader
ASSERT(vtx.q_unused == 1.f);
// because this is true, we can remove a divide in the shader
ASSERT(vert.stq.z() == 1.f);
vtx.color_index = vert.rgba / 4;
// ASSERT((vert.rgba >> 2) < 1024); spider cave has 2048?
ASSERT((vert.rgba & 3) == 0);
File diff suppressed because it is too large Load Diff