From e8911758f0d07d70b4be2cbfc3ee052e4e263ad9 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Mon, 2 May 2022 21:26:17 -0400 Subject: [PATCH] [graphics] small improvements (#1351) * faster texture upload lookup * fix debug menu * cleanup * one more --- .github/workflows/linux-workflow.yaml | 4 +- game/CMakeLists.txt | 1 + .../graphics/opengl_renderer/BucketRenderer.h | 2 - game/graphics/opengl_renderer/EyeRenderer.cpp | 10 +- game/graphics/opengl_renderer/Loader.cpp | 9 +- .../opengl_renderer/OpenGLRenderer.cpp | 8 +- game/graphics/opengl_renderer/SkyBlendCPU.cpp | 3 +- game/graphics/opengl_renderer/SkyBlendGPU.cpp | 3 +- .../opengl_renderer/TextureUploadHandler.cpp | 1 + game/graphics/opengl_renderer/debug_gui.cpp | 6 +- .../opengl_renderer/ocean/OceanTexture.cpp | 5 +- game/graphics/texture/TexturePool.cpp | 149 ++++++++++-------- game/graphics/texture/TexturePool.h | 98 ++++++++++-- game/graphics/texture/jak1_tpage_dir.cpp | 102 ++++++++++++ game/graphics/texture/jak1_tpage_dir.h | 7 + game/kernel/kmemcard.cpp | 10 +- 16 files changed, 316 insertions(+), 102 deletions(-) create mode 100644 game/graphics/texture/jak1_tpage_dir.cpp create mode 100644 game/graphics/texture/jak1_tpage_dir.h diff --git a/.github/workflows/linux-workflow.yaml b/.github/workflows/linux-workflow.yaml index 19819d8b6c..34a3c701da 100644 --- a/.github/workflows/linux-workflow.yaml +++ b/.github/workflows/linux-workflow.yaml @@ -114,7 +114,9 @@ jobs: run: | mkdir -p ./ci-artifacts/out ./.github/scripts/releases/extract_build_linux.sh ./ci-artifacts/out ./ - tar -czf ./ci-artifacts/linux.tar.gz -C ./ci-artifacts . + pushd ci-artifacts + tar czf linux.tar.gz ./out + popd - name: Upload Assets and Potential Publish Release if: github.repository == 'open-goal/jak-project' && startsWith(github.ref, 'refs/tags/') && matrix.compiler == 'clang' diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 20a8d812ab..9f00567b30 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -120,6 +120,7 @@ set(RUNTIME_SOURCE graphics/opengl_renderer/Sprite3.cpp graphics/opengl_renderer/SpriteRenderer.cpp graphics/opengl_renderer/TextureUploadHandler.cpp + graphics/texture/jak1_tpage_dir.cpp graphics/texture/TextureConverter.cpp graphics/texture/TexturePool.cpp graphics/pipelines/opengl.cpp diff --git a/game/graphics/opengl_renderer/BucketRenderer.h b/game/graphics/opengl_renderer/BucketRenderer.h index 4d4feed35b..6a45d673ee 100644 --- a/game/graphics/opengl_renderer/BucketRenderer.h +++ b/game/graphics/opengl_renderer/BucketRenderer.h @@ -37,12 +37,10 @@ struct SharedRenderState { bool use_sky_cpu = true; bool use_occlusion_culling = true; bool enable_merc_xgkick = true; - bool enable_generic_xgkick = true; bool use_direct2 = true; math::Vector fog_color; float fog_intensity = 1.f; bool no_multidraw = true; - bool render_collision_mesh = true; void reset(); bool has_pc_data = false; diff --git a/game/graphics/opengl_renderer/EyeRenderer.cpp b/game/graphics/opengl_renderer/EyeRenderer.cpp index 4144d5107f..3ec866dadb 100644 --- a/game/graphics/opengl_renderer/EyeRenderer.cpp +++ b/game/graphics/opengl_renderer/EyeRenderer.cpp @@ -24,8 +24,9 @@ void EyeRenderer::init_textures(TexturePool& texture_pool) { in.gpu_texture = gl_tex; in.w = 32; in.h = 32; - in.page_name = "PC-EYES"; - in.name = fmt::format("{}-eye-cpu-{}", lr ? "left" : "right", pair_idx); + in.debug_page_name = "PC-EYES"; + in.debug_name = fmt::format("{}-eye-cpu-{}", lr ? "left" : "right", pair_idx); + in.id = texture_pool.allocate_pc_port_texture(); auto* gpu_tex = texture_pool.give_texture_and_load_to_vram(in, tbp); m_cpu_eye_textures[tidx] = {gl_tex, gpu_tex, tbp}; } @@ -37,8 +38,9 @@ void EyeRenderer::init_textures(TexturePool& texture_pool) { in.gpu_texture = m_gpu_eye_textures[tidx].fb.texture(); in.w = 32; in.h = 32; - in.page_name = "PC-EYES"; - in.name = fmt::format("{}-eye-gpu-{}", lr ? "left" : "right", pair_idx); + in.debug_page_name = "PC-EYES"; + in.debug_name = fmt::format("{}-eye-gpu-{}", lr ? "left" : "right", pair_idx); + in.id = texture_pool.allocate_pc_port_texture(); m_gpu_eye_textures[tidx].gpu_tex = texture_pool.give_texture_and_load_to_vram(in, tbp); m_gpu_eye_textures[tidx].tbp = tbp; } diff --git a/game/graphics/opengl_renderer/Loader.cpp b/game/graphics/opengl_renderer/Loader.cpp index 70dd3a0ccc..4bdbaffaa5 100644 --- a/game/graphics/opengl_renderer/Loader.cpp +++ b/game/graphics/opengl_renderer/Loader.cpp @@ -192,13 +192,13 @@ u64 Loader::add_texture(TexturePool& pool, const tfrag3::Texture& tex, bool is_c glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, aniso); if (tex.load_to_pool) { TextureInput in; - in.page_name = tex.debug_tpage_name; - in.name = tex.debug_name; + in.debug_page_name = tex.debug_tpage_name; + in.debug_name = tex.debug_name; in.w = tex.w; in.h = tex.h; in.gpu_texture = gl_tex; in.common = is_common; - in.combo_id = tex.combo_id; + in.id = PcTextureId::from_combo_id(tex.combo_id); in.src_data = (const u8*)tex.data.data(); pool.give_texture(in); } @@ -632,7 +632,8 @@ void Loader::update(TexturePool& texture_pool) { for (size_t i = 0; i < lev.second.data.level->textures.size(); i++) { auto& tex = lev.second.data.level->textures[i]; if (tex.load_to_pool) { - texture_pool.unload_texture(tex.debug_name, lev.second.data.textures.at(i)); + texture_pool.unload_texture(PcTextureId::from_combo_id(tex.combo_id), + lev.second.data.textures.at(i)); } } lk.unlock(); diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index de43f9203d..060f530fdf 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -110,7 +110,7 @@ void OpenGLRenderer::init_bucket_renderers() { BucketId::MERC_TFRAG_TEX_LEVEL0); // 11 : GMERC_TFRAG_TEX_LEVEL0 init_bucket_renderer("l0-tfrag-generic", BucketCategory::GENERIC, - BucketId::GENERIC_TFRAG_TEX_LEVEL0); + BucketId::GENERIC_TFRAG_TEX_LEVEL0, 1500000, 10000, 10000, 800); //----------------------- // LEVEL 1 tfrag texture @@ -130,7 +130,7 @@ void OpenGLRenderer::init_bucket_renderers() { BucketId::MERC_TFRAG_TEX_LEVEL1); // 18 : GMERC_TFRAG_TEX_LEVEL1 init_bucket_renderer("l1-tfrag-generic", BucketCategory::GENERIC, - BucketId::GENERIC_TFRAG_TEX_LEVEL1); + BucketId::GENERIC_TFRAG_TEX_LEVEL1, 1500000, 10000, 10000, 800); //----------------------- // LEVEL 0 shrub texture @@ -366,12 +366,10 @@ void OpenGLRenderer::draw_renderer_selection_window() { ImGui::Begin("Renderer Debug"); ImGui::Checkbox("Use old single-draw", &m_render_state.no_multidraw); - ImGui::Checkbox("Render collision mesh", &m_render_state.render_collision_mesh); ImGui::SliderFloat("Fog Adjust", &m_render_state.fog_intensity, 0, 10); ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu); ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling); ImGui::Checkbox("Merc XGKICK", &m_render_state.enable_merc_xgkick); - ImGui::Checkbox("Generic XGKICK", &m_render_state.enable_generic_xgkick); ImGui::Checkbox("Blackout Loads", &m_enable_fast_blackout_loads); ImGui::Checkbox("Direct 2", &m_render_state.use_direct2); @@ -458,7 +456,7 @@ void OpenGLRenderer::dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof) m_category_times[(int)m_bucket_categories[bucket_id]] += bucket_prof.get_elapsed_time(); // hack to draw the collision mesh in the middle the drawing - if (bucket_id == (int)BucketId::ALPHA_TEX_LEVEL0 - 1 && m_render_state.render_collision_mesh && + if (bucket_id == (int)BucketId::ALPHA_TEX_LEVEL0 - 1 && Gfx::g_global_settings.collision_enable) { auto p = prof.make_scoped_child("collision-draw"); m_collide_renderer.render(&m_render_state, p); diff --git a/game/graphics/opengl_renderer/SkyBlendCPU.cpp b/game/graphics/opengl_renderer/SkyBlendCPU.cpp index 181966635c..c5dac8ddcf 100644 --- a/game/graphics/opengl_renderer/SkyBlendCPU.cpp +++ b/game/graphics/opengl_renderer/SkyBlendCPU.cpp @@ -194,7 +194,8 @@ void SkyBlendCPU::init_textures(TexturePool& tex_pool) { in.gpu_texture = m_textures[i].gl; in.w = m_sizes[i]; in.h = m_sizes[i]; - in.name = fmt::format("PC-SKY-CPU-{}", i); + in.debug_name = fmt::format("PC-SKY-CPU-{}", i); + in.id = tex_pool.allocate_pc_port_texture(); u32 tbp = SKY_TEXTURE_VRAM_ADDRS[i]; m_textures[i].tex = tex_pool.give_texture_and_load_to_vram(in, tbp); m_textures[i].tbp = tbp; diff --git a/game/graphics/opengl_renderer/SkyBlendGPU.cpp b/game/graphics/opengl_renderer/SkyBlendGPU.cpp index 44ca9d70b9..655822429f 100644 --- a/game/graphics/opengl_renderer/SkyBlendGPU.cpp +++ b/game/graphics/opengl_renderer/SkyBlendGPU.cpp @@ -65,7 +65,8 @@ void SkyBlendGPU::init_textures(TexturePool& tex_pool) { in.gpu_texture = m_textures[i]; in.w = m_sizes[i]; in.h = in.w; - in.name = fmt::format("PC-SKY-GPU-{}", i); + in.debug_name = fmt::format("PC-SKY-GPU-{}", i); + in.id = tex_pool.allocate_pc_port_texture(); u32 tbp = SKY_TEXTURE_VRAM_ADDRS[i]; m_tex_info[i] = {tex_pool.give_texture_and_load_to_vram(in, tbp), tbp}; } diff --git a/game/graphics/opengl_renderer/TextureUploadHandler.cpp b/game/graphics/opengl_renderer/TextureUploadHandler.cpp index f8e1f8ffa8..ed9f51cb67 100644 --- a/game/graphics/opengl_renderer/TextureUploadHandler.cpp +++ b/game/graphics/opengl_renderer/TextureUploadHandler.cpp @@ -23,6 +23,7 @@ void TextureUploadHandler::render(DmaFollower& dma, // note: these uploads may have texture that we need for eye rendering. flush_uploads(uploads, render_state); render_state->eye_renderer->handle_eye_dma2(dma, render_state, prof); + uploads.clear(); } auto data = dma.read_and_advance(); diff --git a/game/graphics/opengl_renderer/debug_gui.cpp b/game/graphics/opengl_renderer/debug_gui.cpp index da5091d3c1..bf9129e52e 100644 --- a/game/graphics/opengl_renderer/debug_gui.cpp +++ b/game/graphics/opengl_renderer/debug_gui.cpp @@ -123,8 +123,10 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) { ImGui::EndMenu(); } - if (ImGui::BeginMenu("Reboot in Debug Mode")) { - want_reboot_in_debug = true; + if (ImGui::BeginMenu("Debug Mode")) { + if (ImGui::MenuItem("Reboot now!")) { + want_reboot_in_debug = true; + } ImGui::EndMenu(); } } diff --git a/game/graphics/opengl_renderer/ocean/OceanTexture.cpp b/game/graphics/opengl_renderer/ocean/OceanTexture.cpp index 13300ae36f..849e2799d4 100644 --- a/game/graphics/opengl_renderer/ocean/OceanTexture.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanTexture.cpp @@ -56,8 +56,9 @@ void OceanTexture::init_textures(TexturePool& pool) { in.gpu_texture = m_result_texture.texture(); in.w = TEX0_SIZE; in.h = TEX0_SIZE; - in.page_name = "PC-OCEAN"; - in.name = fmt::format("pc-ocean-mip-{}", m_generate_mipmaps); + 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); } diff --git a/game/graphics/texture/TexturePool.cpp b/game/graphics/texture/TexturePool.cpp index bdb9684826..8e632d6b46 100644 --- a/game/graphics/texture/TexturePool.cpp +++ b/game/graphics/texture/TexturePool.cpp @@ -9,6 +9,7 @@ #include "common/log/log.h" #include "game/graphics/pipelines/opengl.h" #include "common/util/Assert.h" +#include "game/graphics/texture/jak1_tpage_dir.h" namespace { const char empty_string[] = ""; @@ -49,41 +50,33 @@ u64 upload_to_gpu(const u8* data, u16 w, u16 h) { } GpuTexture* TexturePool::give_texture(const TextureInput& in) { - const auto& it = m_loaded_textures.find(in.name); - if (it == m_loaded_textures.end()) { + // const auto& it = m_loaded_textures.find(in.name); + const auto existing = m_loaded_textures.lookup_or_insert(in.id); + if (!existing.second) { // nothing references this texture yet. - GpuTexture gtex; - gtex.page_name = in.page_name; - gtex.name = in.name; - gtex.w = in.w; - gtex.h = in.h; - gtex.is_common = in.common; - gtex.gpu_textures = {{in.gpu_texture, in.src_data}}; - gtex.combo_id = in.combo_id; - gtex.is_placeholder = false; - - return &m_loaded_textures.insert({in.name, gtex}).first->second; + existing.first->tex_id = in.id; + existing.first->w = in.w; + existing.first->h = in.h; + existing.first->is_common = in.common; + existing.first->gpu_textures = {{in.gpu_texture, in.src_data}}; + existing.first->is_placeholder = false; + *m_id_to_name.lookup_or_insert(in.id).first = + fmt::format("{}/{}", in.debug_page_name, in.debug_name); + return existing.first; } else { - if (!it->second.is_placeholder) { - fmt::print( - "[tex2] loader providing {}, but we already have an entry for it {} common? {} mine " - "{}x{} 0x{:x} new {}x{} 0x{:x}.\n", - in.name, it->second.name, it->second.is_common, in.w, in.h, in.combo_id, it->second.w, - it->second.h, it->second.combo_id); - ASSERT(!it->second.gpu_textures.empty()); + if (!existing.first->is_placeholder) { + // two sources for texture. this is fine. + ASSERT(!existing.first->gpu_textures.empty()); } else { - ASSERT(it->second.gpu_textures.empty()); + ASSERT(existing.first->gpu_textures.empty()); } - it->second.is_placeholder = false; - it->second.page_name = in.page_name; - it->second.name = in.name; - it->second.w = in.w; - it->second.h = in.h; - it->second.gpu_textures.push_back({in.gpu_texture, in.src_data}); - it->second.is_common = in.common; - it->second.combo_id = in.combo_id; - refresh_links(it->second); - return &it->second; + existing.first->is_placeholder = false; + existing.first->w = in.w; + existing.first->h = in.h; + existing.first->gpu_textures.push_back({in.gpu_texture, in.src_data}); + existing.first->is_common = in.common; + refresh_links(*existing.first); + return existing.first; } } @@ -133,25 +126,27 @@ void TexturePool::refresh_links(GpuTexture& texture) { } } -void TexturePool::unload_texture(const std::string& name, u64 id) { - auto& tex = m_loaded_textures.at(name); - if (tex.is_common) { +void TexturePool::unload_texture(PcTextureId tex_id, u64 gpu_id) { + auto* tex = m_loaded_textures.lookup_existing(tex_id); + ASSERT(tex); + if (tex->is_common) { ASSERT(false); return; } - if (tex.is_placeholder) { - fmt::print("trying to unload something that was already placholdered: {} {}\n", name, - tex.gpu_textures.size()); + if (tex->is_placeholder) { + fmt::print("trying to unload something that was already placholdered: {} {}\n", + get_debug_texture_name(tex_id), tex->gpu_textures.size()); } - ASSERT(!tex.is_placeholder); - auto it = std::find_if(tex.gpu_textures.begin(), tex.gpu_textures.end(), - [&](const auto& a) { return a.gl == id; }); - ASSERT(it != tex.gpu_textures.end()); - tex.gpu_textures.erase(it); - if (tex.gpu_textures.empty()) { - tex.is_placeholder = true; + ASSERT(!tex->is_placeholder); + auto it = std::find_if(tex->gpu_textures.begin(), tex->gpu_textures.end(), + [&](const auto& a) { return a.gl == gpu_id; }); + ASSERT(it != tex->gpu_textures.end()); + + tex->gpu_textures.erase(it); + if (tex->gpu_textures.empty()) { + tex->is_placeholder = true; } - refresh_links(tex); + refresh_links(*tex); } void GpuTexture::remove_slot(u32 slot) { @@ -208,19 +203,26 @@ void TexturePool::handle_upload_now(const u8* tpage, int mode, const u8* memory_ // each texture may have multiple mip levels. for (int mip_idx = 0; mip_idx < tex.num_mips; mip_idx++) { if (has_segment[tex.segment_of_mip(mip_idx)]) { - auto name = std::string(goal_string(texture_page.name_ptr, memory_base)) + - goal_string(tex.name_ptr, memory_base); + PcTextureId current_id(texture_page.id, tex_idx); + if (!m_id_to_name.lookup_existing(current_id)) { + auto name = std::string(goal_string(texture_page.name_ptr, memory_base)) + + goal_string(tex.name_ptr, memory_base); + *m_id_to_name.lookup_or_insert(current_id).first = name; + m_name_to_id[name] = current_id; + } + auto& slot = m_textures[tex.dest[mip_idx]]; + if (slot.source) { - if (slot.source->name == name) { + if (slot.source->tex_id == current_id) { // we already have it, no need to do anything } else { slot.source->remove_slot(tex.dest[mip_idx]); - slot.source = get_gpu_texture_for_slot(name, tex.dest[mip_idx]); + slot.source = get_gpu_texture_for_slot(current_id, tex.dest[mip_idx]); ASSERT(slot.gpu_texture != (u64)-1); } } else { - slot.source = get_gpu_texture_for_slot(name, tex.dest[mip_idx]); + slot.source = get_gpu_texture_for_slot(current_id, tex.dest[mip_idx]); ASSERT(slot.gpu_texture != (u64)-1); } } @@ -246,18 +248,19 @@ void TexturePool::relocate(u32 destination, u32 source, u32 format) { } } -GpuTexture* TexturePool::get_gpu_texture_for_slot(const std::string& name, u32 slot) { - auto it = m_loaded_textures.find(name); - if (it == m_loaded_textures.end()) { - GpuTexture placeholder; - placeholder.name = name; +GpuTexture* TexturePool::get_gpu_texture_for_slot(PcTextureId id, u32 slot) { + auto it = m_loaded_textures.lookup_or_insert(id); + if (!it.second) { + GpuTexture& placeholder = *it.first; + placeholder.tex_id = id; placeholder.is_placeholder = true; placeholder.slots.push_back(slot); - auto r = m_loaded_textures.insert({name, placeholder}); + + // auto r = m_loaded_textures.insert({name, placeholder}); m_textures[slot].gpu_texture = m_placeholder_texture_id; - return &r.first->second; + return it.first; } else { - auto result = &it->second; + auto result = it.first; result->add_slot(slot); m_textures[slot].gpu_texture = result->is_placeholder ? m_placeholder_texture_id : result->gpu_textures.at(0).gl; @@ -276,7 +279,8 @@ std::optional TexturePool::lookup_mt4hh(u32 location) { return {}; } -TexturePool::TexturePool() { +TexturePool::TexturePool() + : m_loaded_textures(get_jak1_tpage_dir()), m_id_to_name(get_jak1_tpage_dir()) { m_placeholder_data.resize(16 * 16); u32 c0 = 0xa0303030; u32 c1 = 0xa0e0e0e0; @@ -301,14 +305,17 @@ void TexturePool::draw_debug_window() { auto& record = m_textures[i]; total_textures++; if (record.source) { - if (std::regex_search(record.source->name, regex)) { + if (std::regex_search(get_debug_texture_name(record.source->tex_id), regex)) { ImGui::PushID(id++); - draw_debug_for_tex(record.source->name, record.source, i); + draw_debug_for_tex(get_debug_texture_name(record.source->tex_id), record.source, i); ImGui::PopID(); total_displayed_textures++; } - total_vram_bytes += - record.source->w * record.source->h * 4; // todo, if we support other formats + if (!record.source->gpu_textures.empty()) { + total_vram_bytes += + record.source->w * record.source->h * 4; // todo, if we support other formats + } + total_uploaded_textures++; } } @@ -328,7 +335,7 @@ void TexturePool::draw_debug_for_tex(const std::string& name, GpuTexture* tex, u ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8, 0.8, 0.3, 1.0)); } if (ImGui::TreeNode(fmt::format("{} {}", name, slot).c_str())) { - ImGui::Text("P: %s sz: %d x %d", tex->page_name.c_str(), tex->w, tex->h); + ImGui::Text("P: %s sz: %d x %d", get_debug_texture_name(tex->tex_id).c_str(), tex->w, tex->h); if (!tex->is_placeholder) { ImGui::Image((void*)tex->gpu_textures.at(0).gl, ImVec2(tex->w, tex->h)); } else { @@ -339,4 +346,18 @@ void TexturePool::draw_debug_for_tex(const std::string& name, GpuTexture* tex, u ImGui::Separator(); } ImGui::PopStyleColor(); +} + +PcTextureId TexturePool::allocate_pc_port_texture() { + ASSERT(m_next_pc_texture_to_allocate < EXTRA_PC_PORT_TEXTURE_COUNT); + return PcTextureId(get_jak1_tpage_dir().size() - 1, m_next_pc_texture_to_allocate++); +} + +std::string TexturePool::get_debug_texture_name(PcTextureId id) { + auto it = m_id_to_name.lookup_existing(id); + if (it) { + return *it; + } else { + return "???"; + } } \ No newline at end of file diff --git a/game/graphics/texture/TexturePool.h b/game/graphics/texture/TexturePool.h index c5b5899c3d..8d386cbc37 100644 --- a/game/graphics/texture/TexturePool.h +++ b/game/graphics/texture/TexturePool.h @@ -9,6 +9,7 @@ #include "common/common_types.h" #include "game/graphics/texture/TextureConverter.h" #include "common/util/Serializer.h" +#include "common/util/SmallVector.h" // verify all texture lookups. // will make texture lookups slower and likely caused dropped frames when loading @@ -67,6 +68,71 @@ constexpr int SKY_TEXTURE_VRAM_ADDRS[2] = {8064, 8096}; * The game will inform us when it uploads to VRAM */ +struct PcTextureId { + u16 page = -1; + u16 tex = -1; + + PcTextureId(u16 p, u16 t) : page(p), tex(t) {} + PcTextureId() = default; + + static PcTextureId from_combo_id(u32 val) { return PcTextureId(val >> 16, val & 0xffff); } + + bool operator==(const PcTextureId& other) const { return page == other.page && tex == other.tex; } +}; + +template +class TextureMap { + public: + TextureMap(const std::vector& tpage_dir) { + u32 off = 0; + for (auto& x : tpage_dir) { + m_dir.push_back(off); + off += x; + } + m_data.resize(off); + } + + T* lookup_existing(PcTextureId id) { + auto& elt = m_data[m_dir[id.page] + id.tex]; + if (elt.present) { + return &elt.val; + } else { + return nullptr; + } + } + + T& at(PcTextureId id) { + auto& elt = m_data[m_dir[id.page] + id.tex]; + if (elt.present) { + return elt.val; + } + ASSERT(false); + } + + std::pair lookup_or_insert(PcTextureId id) { + auto& elt = m_data[m_dir[id.page] + id.tex]; + if (elt.present) { + return std::make_pair(&elt.val, true); + } else { + elt.present = true; + return std::make_pair(&elt.val, false); + } + } + + void erase(PcTextureId id) { + auto& elt = m_data[m_dir[id.page] + id.tex]; + elt.present = false; + } + + private: + std::vector m_dir; + struct Element { + T val; + bool present = false; + }; + std::vector m_data; +}; + /*! * The lowest level reference to texture data. */ @@ -80,8 +146,9 @@ struct TextureData { * It's possible for there to be 0 instances of the texture loaded yet. */ struct GpuTexture { - std::string page_name; - std::string name; + GpuTexture(PcTextureId id) : tex_id(id) {} + GpuTexture() = default; + PcTextureId tex_id; // all the currently loaded copies of this texture std::vector gpu_textures; @@ -92,9 +159,6 @@ struct GpuTexture { // the vram address that contain this texture, stored in mt4hh format std::vector mt4hh_slots; - // our "combo id", containing the tpage and texture ID - u32 combo_id = -1; - // texture dimensions u16 w, h; @@ -137,11 +201,13 @@ struct TextureVRAMReference { * A texture provided by the loader. */ struct TextureInput { - std::string page_name; - std::string name; + std::string debug_page_name; + std::string debug_name; + + PcTextureId id; + u64 gpu_texture = -1; bool common = false; - u32 combo_id = -1; const u8* src_data; u16 w, h; }; @@ -236,7 +302,7 @@ class TexturePool { void handle_upload_now(const u8* tpage, int mode, const u8* memory_base, u32 s7_ptr); GpuTexture* give_texture(const TextureInput& in); GpuTexture* give_texture_and_load_to_vram(const TextureInput& in, u32 vram_slot); - void unload_texture(const std::string& name, u64 id); + void unload_texture(PcTextureId tex_id, u64 gpu_id); /*! * Look up an OpenGL texture by vram address. Return std::nullopt if the game hasn't loaded @@ -284,10 +350,13 @@ class TexturePool { void move_existing_to_vram(GpuTexture* tex, u32 slot_addr); std::mutex& mutex() { return m_mutex; } + PcTextureId allocate_pc_port_texture(); + + std::string get_debug_texture_name(PcTextureId id); private: void refresh_links(GpuTexture& texture); - GpuTexture* get_gpu_texture_for_slot(const std::string& name, u32 slot); + GpuTexture* get_gpu_texture_for_slot(PcTextureId id, u32 slot); char m_regex_input[256] = ""; std::array m_textures; @@ -300,7 +369,14 @@ class TexturePool { std::vector m_placeholder_data; u64 m_placeholder_texture_id = 0; - std::unordered_map m_loaded_textures; + TextureMap m_loaded_textures; + + // we maintain a mapping of all textures/ids we've seen so far. + // this is only used for debug. + TextureMap m_id_to_name; + std::unordered_map m_name_to_id; + + u32 m_next_pc_texture_to_allocate = 0; std::mutex m_mutex; }; \ No newline at end of file diff --git a/game/graphics/texture/jak1_tpage_dir.cpp b/game/graphics/texture/jak1_tpage_dir.cpp new file mode 100644 index 0000000000..b785a7ba88 --- /dev/null +++ b/game/graphics/texture/jak1_tpage_dir.cpp @@ -0,0 +1,102 @@ +#include +#include "common/common_types.h" +#include "jak1_tpage_dir.h" +namespace { + +std::vector tpage_dir = { + 0x0, 0x2, 0x37, 0x1, 0x1, 0x10, 0x2, 0x4, 0x3, 0x2, 0x1, 0x5, 0x7, 0x8, 0x1, 0x1, 0x1, 0xb, 0xe, + 0x8, 0x1, 0x6, 0x4, 0x6, 0x3, 0x3, 0x6, 0x6, 0x4, 0x4, 0x4, 0xd, 0x1, 0x4, 0x9, 0xc, 0x1, 0x1, + 0x6, 0x3, 0x2, 0x14, 0x1, 0x1, 0x2, 0x2, 0x34, 0x34, 0x4, 0x15, 0x1, 0x1, 0x1, 0x8, 0x6, 0xb, + 0xb, 0x7, 0x17, 0x1, 0x7, 0x20, 0xd, 0xa, 0x1, 0x1, 0xb, 0x11, 0x2, 0x9, 0xb, 0xa, 0xe, 0x1, + 0x6, 0x6, 0x1, 0x2, 0x2, 0x33, 0x33, 0xd, 0x2, 0x9, 0x4, 0x68, 0x1, 0x9, 0x1, 0x2, 0x1, 0x5, + 0x9, 0x7, 0x14, 0xa, 0x1, 0x1, 0x1, 0x2, 0x10, 0x4, 0x2, 0x17, 0x2, 0x1, 0x13, 0x6, 0x1, 0x1, + 0x1, 0x2, 0x1, 0x16, 0x1, 0x5, 0x1, 0xe, 0x3, 0x2, 0x1, 0x9, 0x15, 0x3, 0x1, 0x2, 0x40, 0x6, + 0xb, 0x9, 0x2, 0x8, 0xf, 0x2, 0x2, 0x7, 0x11, 0x5, 0x7, 0x13, 0x9, 0x1, 0x1, 0x1, 0x8, 0x1, 0x1, + 0x1, 0x1, 0x1, 0x2, 0x2, 0x9, 0x2, 0xb, 0x5, 0x1, 0xa, 0x15, 0x2e, 0x4, 0x22, 0xb, 0x2e, 0x1e, + 0x6, 0x4, 0x6, 0x3, 0x3, 0x6, 0x6, 0x2, 0x19, 0x5, 0x5, 0x8, 0x37, 0x15, 0x2, 0x1, 0x1, 0x4, + 0x4, 0x8, 0x9, 0x9, 0x9, 0x9, 0x8, 0x6, 0x1e, 0x7, 0x1, 0x5, 0x9, 0x72, 0xc, 0x5, 0x16, 0x5, + 0x4, 0x1, 0x6, 0x3, 0x3, 0x3, 0x3, 0x1, 0x1, 0x1c, 0xa3, 0x47, 0x1b, 0xc9, 0xa, 0x1, 0x16, 0x1, + 0x4, 0x4, 0x4, 0x4, 0x4, 0xd, 0x4, 0xc, 0x2d, 0x4, 0x1, 0x1, 0xf, 0x2, 0x2, 0x10, 0x3, 0x3, 0x1, + 0x1, 0x1, 0x1, 0x1, 0x4, 0x4, 0x9, 0x9, 0x5, 0x6, 0xa, 0x4, 0x1, 0x5, 0x4, 0x9, 0x2, 0x1, 0x4, + 0x2, 0x2, 0x3, 0x12, 0xa, 0x8, 0x4, 0x5, 0x1, 0x1, 0x6, 0x6, 0x7, 0xf, 0x1d, 0x4, 0x4, 0x93, + 0x1, 0x2, 0x15, 0x1, 0xc, 0x1, 0xb, 0x1, 0x5, 0x1e, 0x1, 0x3c, 0x10, 0x5, 0x4, 0x5, 0x3, 0xb, + 0x4, 0x8, 0x4, 0x4, 0x9, 0x6, 0x3, 0x1d, 0x2e, 0x1, 0x3, 0x15, 0xb, 0x1, 0x1, 0x1, 0x2, 0x1, + 0x1, 0x1, 0x1, 0x9, 0x8, 0x1a, 0x5, 0xe, 0x1, 0x1e, 0xc, 0x57, 0x71, 0x1, 0x4, 0x8, 0x5, 0x15, + 0x7, 0xa, 0x1f, 0xc, 0x6, 0x12, 0x1, 0x2, 0x9, 0x4c, 0xa, 0xc9, 0x1, 0x8, 0x8, 0x1b, 0x8, 0x1d, + 0x15, 0x1, 0x19, 0x97, 0x6c, 0xd, 0x3, 0x4, 0x4, 0x2, 0x2, 0x3d, 0xa, 0x36, 0x4, 0x8, 0x21, + 0x15, 0x1, 0x1, 0x2, 0x6, 0x2, 0xb, 0x6, 0xb, 0xc, 0x5, 0x4, 0x15, 0x14, 0x1, 0x21, 0x5, 0x6, + 0xb, 0x1, 0x1b, 0x57, 0x1e, 0x2, 0xc, 0x16, 0x9, 0x5, 0x9, 0x1, 0x1, 0x2f, 0x1a, 0x9, 0x80, + 0x19, 0x97, 0xd, 0x26, 0x8, 0xb, 0x8, 0x1, 0x6, 0x4, 0x1, 0x2, 0x1c, 0x9, 0x13, 0xe, 0x8, 0x1, + 0x1, 0x8, 0x4, 0x6, 0x1, 0xd, 0x6, 0x1c, 0x8, 0x1, 0x1d, 0x1, 0x3, 0x4, 0x2, 0x2, 0x1, 0x1, + 0x12, 0x3d, 0x13, 0x5, 0x1, 0x25, 0x1, 0x1, 0xb, 0xa, 0x1, 0xe, 0x1, 0xb, 0xa, 0xb, 0x1, 0x38, + 0x5, 0x8, 0x1, 0x2, 0x51, 0xc, 0x2, 0x1, 0x5, 0x2, 0x7a, 0x5, 0x5, 0x1, 0x1, 0x2, 0x1, 0x1, 0x7, + 0xe, 0xd, 0x2, 0x4, 0x1, 0x1, 0xc, 0x5, 0x3, 0x1, 0x2, 0x24, 0x15, 0x24, 0x8, 0x11, 0x1, 0x1, + 0x1, 0x5, 0x1, 0x1, 0x8, 0x2, 0x2, 0x1, 0x1, 0xb, 0xa, 0xa, 0x5, 0x1, 0x1d, 0x4, 0x6, 0x2, 0x4, + 0x9, 0x15, 0x4, 0x4, 0x1, 0x6, 0x2, 0x5c, 0x70, 0x9, 0x1, 0xc, 0x74, 0x5, 0x2, 0x7, 0x2, 0x4, + 0x2, 0x5, 0x19, 0x1, 0x71, 0x4, 0x8, 0x6, 0x2, 0x2, 0x2, 0x11, 0x11, 0x2, 0x6, 0x5, 0xa, 0x2, + 0x1, 0x2, 0x4, 0xf, 0x3b, 0x2, 0x5, 0x5, 0x4, 0x5, 0x4, 0xf, 0xd, 0x2, 0x2, 0x2, 0x7, 0x3f, 0xc, + 0x9, 0x3a, 0xa, 0x15, 0x14, 0x4, 0x4, 0x1, 0xa, 0x9, 0x8, 0x1, 0x7, 0x5b, 0x9, 0x13, 0x1c, 0x18, + 0x5, 0x5, 0x6, 0x18, 0x4, 0x8, 0x14, 0x3a, 0x13, 0x1, 0x43, 0x4, 0x3, 0x17, 0x1, 0x16, 0x15, + 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x8a, 0x1, 0x4, 0x1, 0x1, 0x8, 0x1, 0x1, 0x1, 0x1, 0x9, 0x6, 0x6, + 0x1, 0x13, 0xa, 0x10, 0x5, 0x3, 0x6, 0x6, 0x3, 0x3, 0x4, 0xf, 0x13, 0xb, 0x3, 0x1, 0x1, 0x3, + 0x3, 0x3, 0x14, 0x13, 0x6, 0x15, 0xa, 0x1, 0x5, 0x4, 0x1, 0x2, 0x5, 0x2, 0xd, 0x9, 0xf, 0x5d, + 0x9, 0x47, 0xd, 0x6, 0x5, 0x5d, 0xa, 0x47, 0x15, 0x42, 0x9, 0x6, 0x3, 0x5, 0x2, 0xe, 0xd, 0x11, + 0x4, 0x5, 0x2, 0x1, 0x15, 0x1, 0x1, 0x4, 0x2, 0x13, 0xf, 0x11, 0x11, 0x2, 0xa, 0x9, 0x5, 0x5, + 0x7, 0x5, 0x4, 0x3, 0x4, 0x13, 0x5, 0xb, 0x1, 0x12, 0x12, 0x4, 0x13, 0x1, 0x1, 0x1, 0x1, 0xc, + 0x11, 0x9, 0x5b, 0xa, 0x13, 0xd, 0xa, 0x8, 0x1, 0x1, 0x2, 0x9, 0x6, 0x1, 0x1, 0x1, 0x2, 0x1, + 0x1, 0xa, 0x9, 0x2, 0xf, 0x1, 0x8, 0x3, 0x9, 0x3, 0x1, 0x9, 0x6, 0x6, 0x5, 0x2, 0x5, 0x2, 0x5, + 0x3, 0x1, 0x57, 0x3, 0x1, 0x1, 0x7, 0x3, 0x1, 0x9, 0x7, 0x3, 0x3, 0x3, 0xb1, 0x2, 0x1, 0x12, + 0x2b, 0x3, 0x1, 0x3, 0x2, 0x4, 0x1, 0x2, 0x5, 0x6, 0xd, 0x1, 0x1, 0x1, 0x2, 0x2, 0x6, 0x5, 0x2, + 0x2, 0x2, 0x10, 0x1, 0x1, 0x24, 0x1, 0x1, 0x1, 0x1, 0x6, 0x4, 0x7, 0x21, 0x2, 0x9, 0xa, 0xa, + 0x16, 0xb, 0x34, 0x5, 0x3, 0x10, 0x1, 0x1, 0x2e, 0x13, 0x2, 0x13, 0x1, 0x1, 0x1, 0x25, 0x13, + 0x4, 0x47, 0x8, 0x7, 0x4, 0x35, 0x1, 0xb, 0x19, 0x2, 0x2, 0x8, 0x8, 0x7, 0x10, 0xd, 0x6, 0x6, + 0xa, 0x3, 0x6a, 0x13, 0x18, 0x12, 0x3, 0x57, 0x1d, 0x1, 0xb, 0x5, 0x4, 0x7, 0x1, 0x1, 0x2, 0x2, + 0x2, 0x7, 0x15, 0x2f, 0x1, 0x2, 0xb, 0x4, 0x4, 0x3, 0x5, 0xb, 0xa, 0x9, 0x1, 0x4, 0x5, 0x3, 0x3, + 0x3, 0xb, 0x1b, 0x32, 0x9, 0x4, 0x4, 0x1, 0x1, 0x15, 0x1d, 0x13, 0x12, 0x6, 0xe, 0x4, 0x2, 0x7, + 0x2, 0xc, 0x6, 0x2, 0x5, 0x3, 0x3, 0x9, 0x7, 0xe, 0x9, 0x2, 0x1, 0x3, 0x5, 0x3, 0x3, 0x4, 0x4, + 0x3, 0x6, 0x5, 0x5, 0x19, 0x6, 0x3, 0x1, 0x11, 0x12, 0x84, 0x1c, 0x19, 0xa3, 0x2e, 0xe, 0x13, + 0x47, 0x1, 0x1, 0xc, 0x2, 0x1, 0x5, 0x4, 0x5, 0x4, 0x8, 0x7, 0x7, 0x5, 0x5, 0x3, 0xa, 0x5, 0x3, + 0x5, 0x4, 0x1, 0x6, 0x4, 0x4, 0x1, 0xe, 0x7, 0x2, 0x15, 0x2, 0x2, 0x14, 0x1, 0xc, 0xa, 0x5d, + 0x4, 0x3, 0x2, 0xa, 0x5d, 0x19, 0x1, 0x2, 0x1, 0x1, 0xa, 0x14, 0x1, 0x12, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x17, 0x1, 0x1, 0x13, 0x2, 0x2, 0x1, 0x3, 0x1a, 0x5, 0x15, 0x1, 0x5, 0x1, 0x1a, 0x2, + 0x1, 0xc, 0x6, 0x1, 0x1, 0x1, 0x1, 0x7, 0x7, 0x7, 0xc, 0xd, 0xd, 0x10, 0x1b, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x5, 0x2, 0x4d, 0x2b, 0x8, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0xe, 0xb, 0xa, 0x1, + 0xb, 0x1, 0xb, 0xa, 0x1, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x1, 0x1, 0x15, 0x11, 0x1, 0x8, + 0x1, 0x5, 0x1, 0x1, 0x5, 0x4, 0x4, 0x5, 0xb, 0x6, 0x7, 0x2, 0x1, 0x1, 0x2, 0x1, 0x19, 0x19, 0x2, + 0x2, 0x2, 0x6, 0x8, 0x3, 0x3, 0x4, 0x8, 0x8, 0x3, 0x1, 0x1a, 0xe, 0x3, 0x1, 0xf, 0x1, 0x9, 0x4, + 0xc, 0x5, 0x5, 0x6, 0x1, 0x3b, 0x16, 0x8, 0x7, 0x2, 0x5, 0x32, 0xd, 0x2, 0x55, 0xe, 0x3, 0x14, + 0x3, 0x9, 0x9, 0x3, 0x2, 0x12, 0x12, 0x8, 0x14, 0x13, 0x12, 0x12, 0x9, 0xa, 0x39, 0xf, 0x7, 0x6, + 0x2, 0x1, 0x5, 0x9, 0x9, 0x9, 0x1, 0x9, 0xe, 0x18, 0x1, 0x3, 0x9, 0x3, 0x9, 0x1, 0x4, 0x2, 0x4, + 0x4, 0x2, 0x9, 0x9, 0x9, 0x3, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x3, 0x16, 0x5, 0x2, + 0x2, 0x3, 0x1, 0x9, 0x3, 0x3f, 0x28, 0x9, 0x26, 0x9, 0xa, 0x65, 0x39, 0xc, 0x15, 0x9, 0x1, 0x2, + 0x7, 0xb, 0xc, 0xb, 0xb, 0x2e, 0x4, 0x1e, 0x15, 0x1, 0x2, 0x1, 0x1, 0x2, 0x3, 0x2, 0x2, 0xb, + 0x9, 0x1, 0x4, 0x4, 0x65, 0x16, 0x8f, 0x1, 0x10, 0xf, 0xf, 0x7, 0x9, 0x41, 0x9, 0xb, 0xb, 0xe, + 0x12, 0x20, 0x2, 0x2, 0x2, 0x2, 0x2, 0x9, 0x15, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, + 0x1, 0x1, 0x1, 0xa, 0xd, 0xd, 0x9, 0x1, 0x1, 0xd, 0x68, 0x17, 0x94, 0x1, 0xf, 0x1, 0x1, 0x1, + 0xd, 0x79, 0x17, 0x94, 0xd, 0xf, 0x10, 0x16, 0xf, 0x13, 0xd, 0xc, 0x10, 0xb, 0x8, 0x4, 0x2, 0x2, + 0x1, 0xb, 0x4, 0x9, 0x61, 0x1, 0x2, 0x7, 0xb, 0xb, 0xf, 0xa, 0x1d, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, + 0x2, 0x2, 0x10, 0x4, 0x5, 0x1, 0x9, 0x9, 0x1, 0x9, 0x3, 0x3f, 0x13, 0x9, 0x41, 0xa, 0x20, 0x9, + 0x3f, 0xc, 0x3a, 0x9, 0xa, 0x63, 0x39, 0x1, 0xb, 0xb, 0x1, 0xa, 0x6, 0x1, 0x4, 0x4, 0x4, 0x18, + 0xa, 0x39, 0x10, 0x19, 0x7, 0x8, 0x9, 0x53, 0x6, 0x2b, 0x1, 0x2, 0x1, 0x2, 0x5, 0x3, 0x1, 0x1, + 0x2, 0xd, 0x9, 0x2, 0x1, 0x17, 0x3, 0x1, 0xc, 0xf, 0x10, 0x16, 0x1, 0xd, 0x9, 0x4, 0x7, 0xd, + 0xb, 0xd, 0xc, 0xc, 0x1a, 0x2, 0xc, 0x15, 0x2, 0x2, 0xd, 0x1, 0x1, 0xa, 0x8, 0x8, 0xa, 0xa, 0xa, + 0x8, 0x7, 0xd, 0x9, 0x2, 0x3, 0xf, 0xb, 0xf, 0xf, 0x1, 0xd, 0xa, 0x14, 0x11, 0x16, 0x12, 0x1, + 0x7, 0x1, 0x2, 0x2, 0x1, 0x9, 0x9, 0x2, 0x2, 0x3, 0x9, 0x61, 0x5, 0xb1, 0x12, 0x2a, 0x4a, 0x6, + 0x2, 0x6, 0x13, 0x13, 0x1, 0x2f, 0xb, 0x12, 0x9, 0x3e, 0x4, 0x28, 0x2, 0x1, 0x4, 0x5, 0x3, 0x3, + 0x4, 0x1, 0xf, 0x19, 0x10, 0x1, 0x1, 0x1, 0x1, 0x1, 0x9, 0x17, 0x27, 0x3, 0x9, 0x7, 0x3, 0x27, + 0x2, 0x1, 0x5, 0x6, 0xe, 0x8, 0x8, 0x1, 0x8, 0x9, 0x3, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1a, 0x1, + 0x10, 0x3, 0x9, 0x1, 0x9, 0x9, 0x9, 0x9, 0x3, 0x3, 0x3, 0x19, 0x9, 0x3a, 0x3, 0x1, 0x5, 0x11, + 0xa, 0xa, 0x1, 0x11, 0x1, 0x1, 0x1, 0x4, 0x4, 0x4, 0x6, 0x9, 0x9, 0x2, 0x3, 0xa, 0xf, 0x8, 0x6, + 0x7, 0xb, 0x9, 0xa, 0x5, 0xa, 0x5, 0x9, 0x6, 0x9, 0x4, 0x1, 0x3, 0x3, 0x4, 0x4, 0x3, 0x3, 0xa, + 0x11, 0x9, 0xe, 0x11, 0xe, 0x8, 0x7, 0x8, 0x7, 0x8, 0x4, 0x5, 0x6, 0x5, 0xa, 0x5, 0xe, 0xd, 0x5, + 0xe, 0xd, 0x5, 0x5, 0x5, 0x6, 0x5, 0x6, 0xf, 0x8, 0x8, 0x7, 0x6, 0x8, 0x3, 0x1, 0x5, 0x1, 0x1, + 0x4, 0x4, 0x1, 0x1, 0x9, 0x2, 0xd, 0x7, 0xc, 0xc, 0xa, 0x6, 0x4, 0x1, 0x1, 0x3, 0x2, 0x9, 0x4, + 0x2, 0x2, 0x4, 0x4, 0x1, 0x4, 0x2, 0x21, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x2, + 0x3, + // Pc port texture page: + EXTRA_PC_PORT_TEXTURE_COUNT}; +} + +const std::vector get_jak1_tpage_dir() { + return tpage_dir; +} \ No newline at end of file diff --git a/game/graphics/texture/jak1_tpage_dir.h b/game/graphics/texture/jak1_tpage_dir.h new file mode 100644 index 0000000000..be28bd12d5 --- /dev/null +++ b/game/graphics/texture/jak1_tpage_dir.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include "common/common_types.h" + +const std::vector get_jak1_tpage_dir(); +constexpr u32 EXTRA_PC_PORT_TEXTURE_COUNT = 50; \ No newline at end of file diff --git a/game/kernel/kmemcard.cpp b/game/kernel/kmemcard.cpp index 0863b07f56..be5fcb08f2 100644 --- a/game/kernel/kmemcard.cpp +++ b/game/kernel/kmemcard.cpp @@ -344,12 +344,12 @@ void pc_game_load_open_file(FILE* fd) { mc_print("closing save file.."); if (fclose(fd) == 0) { // cb_closedload // - p2++; // added : check if aux bank exists - auto new_bankname = file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4 + p2]; - bool aux_exists = std::filesystem::exists(new_bankname); - if (p2 < 2 && aux_exists) { + if (p2 < 1 && std::filesystem::exists(file_util::get_user_memcard_dir() / + filename[op.param2 * 2 + 4 + p2 + 1])) { + p2++; mc_print("reading next save bank {}", filename[op.param2 * 2 + 4 + p2]); + auto new_bankname = file_util::get_user_memcard_dir() / filename[op.param2 * 2 + 4 + p2]; auto new_fd = fopen(new_bankname.string().c_str(), "rb"); pc_game_load_open_file(new_fd); } else { @@ -365,7 +365,7 @@ void pc_game_load_open_file(FILE* fd) { (McHeader*)(op.data_ptr.c() + BANK_TOTAL_SIZE + sizeof(McHeader) + BANK_SIZE); static_assert(BANK_TOTAL_SIZE * 2 == 0x21000, "save layout"); ok[0] = true; - ok[1] = aux_exists; + ok[1] = p2 == 1; for (int idx = 0; idx < 2; idx++) { u32 expected_save_count = headers[idx]->save_count;