mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-02 02:30:22 -04:00
add HD particles
This commit is contained in:
@@ -30,6 +30,10 @@
|
||||
#include "dusk/math.h"
|
||||
#endif
|
||||
|
||||
#if DUSK_TPHD
|
||||
#include "dusk/tphd/HdAssetLayer.hpp"
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
//#pragma nosyminline on
|
||||
#endif
|
||||
@@ -1205,6 +1209,10 @@ void dPa_control_c::createCommon(void const* param_0) {
|
||||
mHeap = mDoExt_createSolidHeapFromSystem(0, 0);
|
||||
JKRHEAP_NAME(mHeap, "dPa_control_c::mHeap");
|
||||
JUT_ASSERT(2518, mHeap != NULL);
|
||||
#if DUSK_TPHD
|
||||
dusk::tphd::register_hd_particle_textures("common-r", (void*)param_0,
|
||||
m_resHeap->getSize((void*)param_0));
|
||||
#endif
|
||||
mCommonResMng = JKR_NEW_ARGS (mHeap, 0) JPAResourceManager(param_0, mHeap);
|
||||
JUT_ASSERT(2521, mCommonResMng != NULL);
|
||||
mCommonResMng->swapTexture(mDoGph_gInf_c::getFrameBufferTimg(), "dummy");
|
||||
@@ -1231,6 +1239,13 @@ void dPa_control_c::createRoomScene() {
|
||||
mSceneHeap = mDoExt_createSolidHeapFromGame(0, 0);
|
||||
JKRHEAP_NAME(mSceneHeap, "dPa_control_c::mSceneHeap");
|
||||
JUT_ASSERT(2573, mSceneHeap != NULL);
|
||||
#if DUSK_TPHD
|
||||
{
|
||||
char stem[16];
|
||||
std::snprintf(stem, sizeof(stem), "Pscene%03u", static_cast<unsigned>(field_0x18));
|
||||
dusk::tphd::register_hd_particle_textures(stem, m_sceneRes, m_resHeap->getSize(m_sceneRes));
|
||||
}
|
||||
#endif
|
||||
mSceneResMng = JKR_NEW_ARGS (mSceneHeap, 0) JPAResourceManager(m_sceneRes, mSceneHeap);
|
||||
JUT_ASSERT(2576, mSceneResMng != NULL);
|
||||
mSceneResMng->swapTexture(mDoGph_gInf_c::getFrameBufferTimg(), "dummy");
|
||||
|
||||
@@ -476,6 +476,14 @@ void registerHdSurface(const Gx2FormatMapping& m, const GtxSurface& s,
|
||||
}
|
||||
}
|
||||
|
||||
void applyTimgAttributes(ResTIMG* timg, const GtxSurface& s, s32 imageOffset) {
|
||||
timg->imageOffset = imageOffset;
|
||||
const u8 hdMips = static_cast<u8>(std::clamp<u32>(s.mipCount, 1u, 11u));
|
||||
timg->mipmapCount = hdMips;
|
||||
timg->maxLOD = static_cast<s8>((hdMips - 1) * 8);
|
||||
timg->maxAnisotropy = GX_ANISO_4;
|
||||
}
|
||||
|
||||
bool register_hd_bti_replacement_for_buffer(const TphdPack& pack, std::string_view resourceName,
|
||||
void* buffer, size_t resourceSize, bool replaceExistingPointer) {
|
||||
if (buffer == nullptr || resourceSize < 0x20 || !endsWithSuffixCI(resourceName, ".bti")) {
|
||||
@@ -503,10 +511,7 @@ bool register_hd_bti_replacement_for_buffer(const TphdPack& pack, std::string_vi
|
||||
}
|
||||
|
||||
auto* timg = reinterpret_cast<ResTIMG*>(buffer);
|
||||
timg->imageOffset = 0x20;
|
||||
const u8 hdMips = static_cast<u8>(std::clamp<u32>(s.mipCount, 1u, 11u));
|
||||
timg->mipmapCount = hdMips;
|
||||
timg->maxLOD = static_cast<s8>((hdMips - 1) * 8);
|
||||
applyTimgAttributes(timg, s, 0x20);
|
||||
registerHdSurface(*m, s, static_cast<u8*>(buffer) + 0x20, gtx->name, 0, replaceExistingPointer);
|
||||
return true;
|
||||
}
|
||||
@@ -572,11 +577,7 @@ size_t register_hd_bmd_textures_for_buffer(const TphdPack& pack, std::string_vie
|
||||
}
|
||||
|
||||
const u32 newImgOff = 0x20 + i * 0x20;
|
||||
timg->imageOffset = static_cast<s32>(newImgOff);
|
||||
const u8 hdMips = static_cast<u8>(std::clamp<u32>(s.mipCount, 1u, 11u));
|
||||
timg->mipmapCount = hdMips;
|
||||
timg->maxLOD = static_cast<s8>((hdMips - 1) * 8);
|
||||
timg->maxAnisotropy = GX_ANISO_4;
|
||||
applyTimgAttributes(timg, s, static_cast<s32>(newImgOff));
|
||||
registerHdSurface(*m, s, bmdBytes.data() + btiAbs + newImgOff, gtx->name, i,
|
||||
replaceExistingPointer);
|
||||
++reg;
|
||||
@@ -894,6 +895,50 @@ void rebuild_hd_overlay_locked() {
|
||||
|
||||
}
|
||||
|
||||
void register_hd_particle_textures(std::string_view jpcStem, void* jpcBuffer, size_t jpcSize) {
|
||||
if (g_contentPath.empty() || jpcBuffer == nullptr || jpcSize < 0x10) return;
|
||||
auto* jpc = static_cast<u8*>(jpcBuffer);
|
||||
if (std::memcmp(jpc, "JPAC2-10", 8) != 0) return;
|
||||
|
||||
const std::filesystem::path sidecar =
|
||||
g_contentPath / "tex" / "Particle" / (std::string(jpcStem) + ".jpc.gtx.gz");
|
||||
auto gz = read_file(sidecar);
|
||||
if (!gz) return;
|
||||
auto gfx2 = decompressGzip(*gz);
|
||||
if (!gfx2) return;
|
||||
auto surfaces = parseGtx(*gfx2);
|
||||
if (surfaces.empty()) return;
|
||||
|
||||
// JPAC2-10 header: texture count @ +0x0A (BE u16), texture table @ +0x0C (BE u32).
|
||||
const u32 texCnt = *reinterpret_cast<const BE(u16)*>(jpc + 0x0A);
|
||||
const u32 texTableOff = *reinterpret_cast<const BE(u32)*>(jpc + 0x0C);
|
||||
if (texCnt != surfaces.size()) {
|
||||
HdLog.warn("HD particle {}: jpc texCnt {} != sidecar surfaces {} -> skip",
|
||||
jpcStem, texCnt, surfaces.size());
|
||||
return;
|
||||
}
|
||||
|
||||
size_t reg = 0;
|
||||
u32 off = texTableOff;
|
||||
for (u32 i = 0; i < texCnt && off + 0x40 <= jpcSize; ++i) {
|
||||
const u32 entrySize = *reinterpret_cast<const BE(u32)*>(jpc + off + 4);
|
||||
const char* texName = reinterpret_cast<const char*>(jpc + off + 0x0C);
|
||||
const auto& s = surfaces[i];
|
||||
const Gx2FormatMapping* m = s.baseData.empty() ? nullptr : findFormatMapping(s.format);
|
||||
if (m != nullptr && std::strncmp(texName, "dummy", 5) != 0) {
|
||||
auto* timg = reinterpret_cast<ResTIMG*>(jpc + off + 0x20);
|
||||
const s32 stored = timg->imageOffset;
|
||||
const s32 imgOff = stored ? stored : 0x20;
|
||||
applyTimgAttributes(timg, s, imgOff);
|
||||
const void* pixelPtr = reinterpret_cast<const u8*>(timg) + imgOff;
|
||||
registerHdSurface(*m, s, pixelPtr, jpcStem, i, true);
|
||||
++reg;
|
||||
}
|
||||
off += entrySize ? entrySize : 0x40;
|
||||
}
|
||||
HdLog.info("registerHdParticle[{}]: {}/{} textures registered", jpcStem, reg, texCnt);
|
||||
}
|
||||
|
||||
void set_hd_content_path(std::filesystem::path contentPath) {
|
||||
g_contentPath = std::move(contentPath);
|
||||
std::lock_guard lk{g_cacheMutex};
|
||||
|
||||
@@ -30,6 +30,9 @@ void register_mounted_hd_archive(s32 entryNum, void* arcBytes, size_t arcSize);
|
||||
void register_copied_hd_resource(s32 entryNum, std::string_view resourceName, void* buffer,
|
||||
size_t resourceSize);
|
||||
|
||||
// Register HD particle textures which live in a loose `tex/Particle/<jpcStem>.jpc.gtx.gz` sidecar
|
||||
void register_hd_particle_textures(std::string_view jpcStem, void* jpcBuffer, size_t jpcSize);
|
||||
|
||||
// Returns bytes remaining in a registered HD archive range that contains ptr.
|
||||
// Used for debug heap accounting because some HD buffers are not JKR-owned.
|
||||
std::optional<size_t> find_registered_hd_archive_remaining(const void* ptr);
|
||||
|
||||
Reference in New Issue
Block a user