mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
nvn_tex.c multiplied a level's width by its samples and its blocks by their bytes in 32 bits, and nvn_tex_linear_stride did the same: a descriptor with a width past 2^30 (garbled, or not set up yet) wrapped to a small size, and the texture got a small allocation for a large image. Block counts, row bytes and GOB counts are now 64-bit (mip, blk, pick_tile and adj_tile take 64-bit sizes), and the linear stride saturates at 2^32 - 1 instead of wrapping. Real textures lay out as before. Checked: --probe-nvn-tex gains two cases (an RGBA8 texture 2^30 + 64 texels wide, and its linear stride). Before, the first failed: 2,048 bytes against 2^35 + 2,048. After, all 135 cases pass, the 40 layout goldens of the original SDK among them; --probe-nvn shows the same four failures as the baseline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 lines
1.5 KiB
C
25 lines
1.5 KiB
C
// NVN texture storage layout (Tegra X1 block-linear), see nvn_tex.c.
|
|
// Contains altered code Copyright (C) 2018-2020 fincs (zlib, license text in nvn_tex.c; see THIRD_PARTY_NOTICES.md).
|
|
// nvn_texdesc and nvn_texlayout are defined in nvn_obj.h.
|
|
#pragma once
|
|
#include <stdint.h>
|
|
#include "nvn_obj.h"
|
|
|
|
void nvn_tex_layout(const nvn_texdesc *d, nvn_texlayout *o);
|
|
uint64_t nvn_tex_level_offset(const nvn_texdesc *d, unsigned level);
|
|
int nvn_fmt_bpb(int format, int *bw, int *bh); // Bytes per block (0 = unknown format), block width and height
|
|
// Block height / block depth actually used by level `level` (log2 of the GOB count): the per-level block height shrinks with that level's row count (block rows), and deswizzling uses it level by level
|
|
void nvn_tex_level_tiles(const nvn_texdesc *d, unsigned level, unsigned *tileH, unsigned *tileD);
|
|
|
|
/* LINEAR_RENDER_TARGET (0x40) uses pitch storage even without LINEAR (0x10).
|
|
NX2NAVI's CPU-loaded water height/mask textures use that flag alone. */
|
|
static inline int nvn_tex_is_linear(const nvn_texdesc *d) { return (d->flags & 0x50) != 0; }
|
|
// computed in 64 bits; a stride past 32 bits (a garbled descriptor) saturates instead of wrapping to a small one
|
|
static inline uint32_t nvn_tex_linear_stride(const nvn_texdesc *d) {
|
|
if (d->stride) return d->stride;
|
|
int bw, bh; int bpb = nvn_fmt_bpb(d->format, &bw, &bh);
|
|
uint64_t align = (d->flags & 0x40) ? 128 : 32;
|
|
uint64_t s = ((((uint64_t)d->width + bw - 1) / bw) * bpb + align - 1) & ~(align - 1);
|
|
return s > UINT32_MAX ? UINT32_MAX : (uint32_t)s;
|
|
}
|