[jak 2] fix texture lookup problem (#2373)

This should fix a bunch of texture-related issues by generating a table
of overlapping textures and just... adjusting them slightly so they
don't overlap. It's not the most elegant solution in the world, but I
think it's no worse than the existing hard-coded tpage dir stuff.
This commit is contained in:
water111 2023-03-21 19:41:14 -04:00 committed by GitHub
parent f276251a3a
commit df646282ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1628 additions and 9 deletions

View File

@ -17,7 +17,8 @@ void TextureDB::add_texture(u32 tpage,
const std::string& tex_name,
const std::string& tpage_name,
const std::vector<std::string>& level_names,
u32 num_mips) {
u32 num_mips,
u32 dest) {
auto existing_tpage_name = tpage_names.find(tpage);
if (existing_tpage_name == tpage_names.end()) {
tpage_names[tpage] = tpage_name;
@ -34,6 +35,7 @@ void TextureDB::add_texture(u32 tpage,
ASSERT(existing_tex->second.rgba_bytes == data);
ASSERT(existing_tex->second.page == tpage);
ASSERT(existing_tex->second.num_mips == num_mips);
ASSERT(existing_tex->second.dest == dest);
} else {
auto& new_tex = textures[combo_id];
new_tex.rgba_bytes = data;
@ -42,6 +44,7 @@ void TextureDB::add_texture(u32 tpage,
new_tex.h = h;
new_tex.page = tpage;
new_tex.num_mips = num_mips;
new_tex.dest = dest;
}
for (const auto& level_name : level_names) {
texture_ids_per_level[level_name].insert(combo_id);
@ -68,4 +71,51 @@ void TextureDB::replace_textures(const fs::path& path) {
}
}
}
/*!
* Generate a table of offsets
*/
std::string TextureDB::generate_texture_dest_adjustment_table() const {
// group textures by page
std::map<u32, std::vector<u32>> textures_by_page;
for (const auto& [texture_id, texture] : textures) {
textures_by_page[texture.page].push_back(texture_id);
}
std::string result = "{\n";
// loop over pages (this overlap trick only applies within a page)
for (const auto& [tpage, texture_ids_in_page] : textures_by_page) {
// organize by tbp offset
std::map<u32, std::vector<u32>> textures_by_tbp_offset;
for (auto tid : texture_ids_in_page) {
textures_by_tbp_offset[textures.at(tid).dest].push_back(tid);
}
// find tbp's with overlaps:
bool needs_remap = false;
for (const auto& [tbp, tex_ids] : textures_by_tbp_offset) {
if (tex_ids.size() > 1) {
needs_remap = true;
break;
}
}
if (needs_remap) {
result += fmt::format("{{{},{{\n", tpage);
for (const auto& [tbp, tex_ids] : textures_by_tbp_offset) {
if (tex_ids.size() > 1) {
int offset = 0;
for (auto id : tex_ids) {
result += fmt::format("{{{}, {}}},", id & 0xffff, offset++);
offset++;
}
}
}
result.pop_back();
result += "}},\n";
}
}
result += "}\n";
return result;
}
} // namespace decompiler

View File

@ -1,5 +1,6 @@
#pragma once
#include <map>
#include <set>
#include <string>
#include <unordered_map>
@ -14,11 +15,12 @@ struct TextureDB {
u16 w, h;
std::string name;
u32 page;
u32 dest = -1;
std::vector<u32> rgba_bytes;
u32 num_mips = -1;
};
std::unordered_map<u32, TextureData> textures;
std::map<u32, TextureData> textures;
std::unordered_map<u32, std::string> tpage_names;
std::unordered_map<std::string, std::set<u32>> texture_ids_per_level;
@ -30,8 +32,11 @@ struct TextureDB {
const std::string& tex_name,
const std::string& tpage_name,
const std::vector<std::string>& level_names,
u32 num_mips);
u32 num_mips,
u32 dest);
void replace_textures(const fs::path& path);
std::string generate_texture_dest_adjustment_table() const;
};
} // namespace decompiler

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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
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, tex.num_mips);
texture_page.name, level_names, tex.num_mips, tex.dest[0]);
stats.successful_textures++;
}

View File

@ -251,6 +251,8 @@ int main(int argc, char** argv) {
auto result = db.process_tpages(tex_db, textures_out);
if (!result.empty() && config.process_tpages) {
file_util::write_text_file(textures_out / "tpage-dir.txt", result);
file_util::write_text_file(textures_out / "tex-remap.txt",
tex_db.generate_texture_dest_adjustment_table());
}
}

View File

@ -120,6 +120,7 @@ set(RUNTIME_SOURCE
overlord/ssound.cpp
overlord/stream.cpp
graphics/gfx.cpp
graphics/jak2_texture_remap.cpp
graphics/display.cpp
graphics/sceGraphicsInterface.cpp
graphics/opengl_renderer/background/background_common.cpp

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
#pragma once
int lookup_jak2_texture_dest_offset(int tpage, int texture_idx);

View File

@ -9,6 +9,7 @@
#include "common/util/FileUtil.h"
#include "game/discord.h"
#include "game/graphics/jak2_texture_remap.h"
#include "game/kernel/common/Symbol4.h"
#include "game/kernel/common/fileio.h"
#include "game/kernel/common/kboot.h"
@ -625,6 +626,7 @@ void InitMachine_PCPort() {
make_function_symbol_from_c("__pc-texture-relocate", (void*)pc_texture_relocate);
make_function_symbol_from_c("__pc-get-mips2c", (void*)pc_get_mips2c);
make_function_symbol_from_c("__pc-set-levels", (void*)pc_set_levels);
make_function_symbol_from_c("__pc-get-tex-remap", (void*)lookup_jak2_texture_dest_offset);
// pad stuff
make_function_symbol_from_c("pc-pad-get-mapped-button", (void*)Gfx::get_mapped_button);

View File

@ -2346,6 +2346,20 @@ additionally, some texture pages have a chunk system that allows more specific c
;; set up dests (no idea why the tpage doesn't come with this set properly)
(set! (-> obj segment 1 dest) (-> obj segment 0 size))
(set! (-> obj segment 2 dest) (+ (-> obj segment 0 size) (-> obj segment 1 size)))
;; PC port: added texture remap
(dotimes (texture-idx (-> obj length))
(let ((tex (-> obj data texture-idx)))
(when (and tex (nonzero? tex))
(let ((offset (__pc-get-tex-remap (the int (-> obj id)) texture-idx)))
(when (nonzero? offset)
)
(+! (-> tex dest 0) offset)
)
)
)
)
(let* ((tpage-id (-> obj id))
(dir-entry (-> *texture-page-dir* entries tpage-id))
)

View File

@ -150,6 +150,7 @@
(define-extern __pc-texture-relocate (function object object object none))
(define-extern __pc-get-mips2c (function string function))
(define-extern __pc-set-levels (function (pointer string) none))
(define-extern __pc-get-tex-remap (function int int int))
(define-extern pc-pad-input-mode-set (function symbol none))
(define-extern pc-pad-input-pad-set (function int none))
(define-extern pc-pad-input-mode-get (function int))