Skip to content

Commit

Permalink
Add support for HD textures, which have the same checksum but differe…
Browse files Browse the repository at this point in the history
…nt format or size.

See #2569 for details.
  • Loading branch information
gonetz committed Feb 14, 2022
1 parent 555fbac commit 10a1291
Show file tree
Hide file tree
Showing 15 changed files with 317 additions and 170 deletions.
225 changes: 159 additions & 66 deletions src/GLideNHQ/TxCache.cpp

Large diffs are not rendered by default.

27 changes: 3 additions & 24 deletions src/GLideNHQ/TxCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,6 @@
#include "TxInternal.h"
#include "TxUtil.h"

struct Checksum
{
union
{
uint64 _checksum; /* checksum hi:palette low:texture */
struct
{
uint32 _low;
uint32 _hi;
};
};

Checksum(uint64 checksum) : _checksum(checksum) {}
operator bool() {
return _checksum != 0;
}
operator uint64() {
return _checksum;
}
};

class TxCacheImpl;

class TxCache
Expand All @@ -66,8 +45,8 @@ class TxCache

bool save();
bool load(bool force);
bool del(Checksum checksum); /* checksum hi:palette low:texture */
bool isCached(Checksum checksum); /* checksum hi:palette low:texture */
bool del(Checksum checksum);
bool isCached(Checksum checksum, N64FormatSize n64FmtSz) const;
void clear();
uint64 size() const; // number of elements
uint64 totalSize() const; // size of elements in bytes
Expand All @@ -82,7 +61,7 @@ class TxCache
virtual ~TxCache();
TxCache(uint32 options, uint64 cacheLimit, const wchar_t *cachePath, const wchar_t *ident, dispInfoFuncExt callback);
bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0);
bool get(Checksum checksum, GHQTexInfo *info);
bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info);
bool empty() const;
};

Expand Down
32 changes: 17 additions & 15 deletions src/GLideNHQ/TxFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ TxFilter::TxFilter(int maxwidth,
}

boolean
TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, uint64 g64crc, GHQTexInfo *info)
TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat, uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info)
{
uint8 *texture = src;
uint8 *tmptex = _tex1;
Expand All @@ -186,7 +186,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat,

/* check if we have it in cache */
if ((g64crc & 0xffffffff00000000) == 0 && /* we reach here only when there is no hires texture for this crc */
_txTexCache->get(g64crc, info)) {
_txTexCache->get(g64crc, n64FmtSz, info)) {
DBG_INFO(80, wst("cache hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format);
return 1; /* yep, we've got it */
}
Expand Down Expand Up @@ -451,6 +451,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat,
info->width = srcwidth;
info->height = srcheight;
info->is_hires_tex = 0;
info->n64_format_size = n64FmtSz;
setTextureFormat(destformat, info);

/* cache the texture. */
Expand All @@ -463,7 +464,7 @@ TxFilter::filter(uint8 *src, int srcwidth, int srcheight, ColorFormat srcformat,
}

boolean
TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
TxFilter::hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info)
{
/* NOTE: Rice CRC32 sometimes return the same value for different textures.
* As a workaround, Glide64 CRC32 is used for the key for NON-hires
Expand All @@ -476,13 +477,13 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i
*/

DBG_INFO(80, wst("hirestex: r_crc64:%08X %08X, g64crc:%08X %08X\n"),
(uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff),
r_crc64._palette, r_crc64._texture,
(uint32)(g64crc >> 32), (uint32)(g64crc & 0xffffffff));

#if HIRES_TEXTURE
/* check if we have it in hires memory cache. */
if ((_options & HIRESTEXTURES_MASK) && r_crc64) {
if (_txHiResLoader->get(r_crc64, info)) {
if (_txHiResLoader->get(r_crc64, n64FmtSz, info)) {
DBG_INFO(80, wst("hires hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format);

/* TODO: Enable emulation for special N64 combiner modes. There are few ways
Expand All @@ -509,11 +510,11 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i

return 1; /* yep, got it */
}
if (_txHiResLoader->get((r_crc64 >> 32), info) ||
_txHiResLoader->get((r_crc64 & 0xffffffff), info)) {
if (_txHiResLoader->get(r_crc64._palette, n64FmtSz, info) ||
_txHiResLoader->get(r_crc64._texture, n64FmtSz, info)) {
DBG_INFO(80, wst("hires hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format);

/* for true CI textures, we use the passed in palette to convert to
/* for true CI textures, we use the passed in palette to convert to
* ARGB1555 and add it to memory cache.
*
* NOTE: we do this AFTER all other texture cache searches because
Expand Down Expand Up @@ -543,6 +544,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i
info->width = width;
info->height = height;
info->is_hires_tex = 1;
info->n64_format_size = n64FmtSz;
setTextureFormat(format, info);

/* XXX: add to hires texture cache!!! */
Expand All @@ -558,7 +560,7 @@ TxFilter::hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *i

/* check if we have it in memory cache */
if (_cacheSize && g64crc) {
if (_txTexCache->get(g64crc, info)) {
if (_txTexCache->get(g64crc, n64FmtSz, info)) {
DBG_INFO(80, wst("cache hit: %d x %d gfmt:%x\n"), info->width, info->height, info->format);
return 1; /* yep, we've got it */
}
Expand All @@ -579,7 +581,7 @@ TxFilter::checksum64(uint8 *src, int width, int height, int size, int rowStride,
}

boolean
TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, uint16 n64fmt, uint64 r_crc64)
TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64)
{
assert(gfmt != graphics::colorFormat::RGBA);
if (!_initialized)
Expand All @@ -588,9 +590,9 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorForm
if (!(_options & DUMP_TEX))
return 0;

DBG_INFO(80, wst("gfmt = %02x n64fmt = %02x\n"), u32(gfmt), n64fmt);
DBG_INFO(80, wst("gfmt = %02x n64fmt = %02x\n"), u32(gfmt), n64FmtSz._format);
DBG_INFO(80, wst("hirestex: r_crc64:%08X %08X\n"),
(uint32)(r_crc64 >> 32), (uint32)(r_crc64 & 0xffffffff));
r_crc64._palette, r_crc64._texture);

if (gfmt != graphics::internalcolorFormat::RGBA8) {
if (!_txQuantize->quantize(src, _tex1, rowStridePixel, height, gfmt, graphics::internalcolorFormat::RGBA8))
Expand All @@ -611,13 +613,13 @@ TxFilter::dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorForm
if (!osal_path_existsW(tmpbuf.c_str()) && osal_mkdirp(tmpbuf.c_str()) != 0)
return 0;

if ((n64fmt >> 8) == 0x2) {
if (n64FmtSz._format == 0x2) {
wchar_t wbuf[256];
tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X#%08X_ciByRGBA.png"), _ident.c_str(), (uint32)(r_crc64 & 0xffffffff), (n64fmt >> 8), (n64fmt & 0xf), (uint32)(r_crc64 >> 32));
tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X#%08X_ciByRGBA.png"), _ident.c_str(), r_crc64._texture, n64FmtSz._format, n64FmtSz._size, r_crc64._palette);
tmpbuf.append(wbuf);
} else {
wchar_t wbuf[256];
tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X_all.png"), _ident.c_str(), (uint32)(r_crc64 & 0xffffffff), (n64fmt >> 8), (n64fmt & 0xf));
tx_swprintf(wbuf, 256, wst("/%ls#%08X#%01X#%01X_all.png"), _ident.c_str(), r_crc64._texture, n64FmtSz._format, n64FmtSz._size);
tmpbuf.append(wbuf);
}

Expand Down
6 changes: 4 additions & 2 deletions src/GLideNHQ/TxFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ class TxFilter
int srcheight,
ColorFormat srcformat,
uint64 g64crc, /* glide64 crc, 64bit for future use */
N64FormatSize n64FmtSz,
GHQTexInfo *info);
boolean hirestex(uint64 g64crc, /* glide64 crc, 64bit for future use */
uint64 r_crc64, /* checksum hi:palette low:texture */
Checksum r_crc64,
uint16 *palette,
N64FormatSize n64FmtSz,
GHQTexInfo *info);
uint64 checksum64(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);
boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, uint16 n64fmt, uint64 r_crc64);
boolean dmptx(uint8 *src, int width, int height, int rowStridePixel, ColorFormat gfmt, N64FormatSize n64FmtSz, Checksum r_crc64);
boolean reloadhirestex();
void dumpcache();
};
Expand Down
12 changes: 6 additions & 6 deletions src/GLideNHQ/TxFilterExport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,20 @@ txfilter_shutdown(void)

TAPI boolean TAPIENTRY
txfilter_filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat,
uint64 g64crc, GHQTexInfo *info)
uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info)
{
if (txFilter)
return txFilter->filter(src, srcwidth, srcheight, ColorFormat(u32(srcformat)),
g64crc, info);
g64crc, n64FmtSz, info);

return 0;
}

TAPI boolean TAPIENTRY
txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info)
txfilter_hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info)
{
if (txFilter)
return txFilter->hirestex(g64crc, r_crc64, palette, info);
return txFilter->hirestex(g64crc, r_crc64, palette, n64FmtSz, info);

return 0;
}
Expand All @@ -85,10 +85,10 @@ txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, ui
}

TAPI boolean TAPIENTRY
txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64)
txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64)
{
if (txFilter)
return txFilter->dmptx(src, width, height, rowStridePixel, ColorFormat(u32(gfmt)), n64fmt, r_crc64);
return txFilter->dmptx(src, width, height, rowStridePixel, ColorFormat(u32(gfmt)), n64FmtSz, r_crc64);

return 0;
}
Expand Down
89 changes: 72 additions & 17 deletions src/GLideNHQ/TxFilterExport.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#define CHDIR(a) chdir(a)
#endif

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#ifdef __MSC__
typedef __int64 int64;
typedef unsigned __int64 uint64;
Expand Down Expand Up @@ -100,21 +103,77 @@ typedef unsigned char boolean;
#define GZ_HIRESTEXCACHE 0x00800000
#define DUMP_TEXCACHE 0x01000000
#define DUMP_HIRESTEXCACHE 0x02000000
#define TILE_HIRESTEX 0x04000000
#define UNDEFINED_0 0x08000000
#define UNDEFINED_0 0x04000000
#define UNDEFINED_1 0x08000000
#define FORCE16BPP_HIRESTEX 0x10000000
#define FORCE16BPP_TEX 0x20000000
#define LET_TEXARTISTS_FLY 0x40000000 /* a little freedom for texture artists */
#define DUMP_TEX 0x80000000

struct GHQTexInfo {
unsigned char *data = nullptr;
int width = 0;
int height = 0;
unsigned int format = 0;
unsigned short texture_format = 0;
unsigned short pixel_type = 0;
unsigned char is_hires_tex = 0;
struct Checksum
{
union
{
uint64 _checksum; /* checksum hi:palette low:texture */
struct
{
uint32 _texture;
uint32 _palette;
};
};

Checksum(uint64 checksum) : _checksum(checksum) {}
Checksum(uint32 texture, uint32 palette) : _texture(texture), _palette(palette) {}

operator bool() const {
return _checksum != 0;
}

operator uint64() const {
return _checksum;
}
};

struct N64FormatSize
{
union
{
uint16 _formatsize;
struct
{
uint8 _format;
uint8 _size;
};
};

N64FormatSize(uint16 n64format, uint16 n64size) :
_format(static_cast<uint8>(n64format)),
_size(static_cast<uint8>(n64size))
{}

uint16 formatsize() const
{
return _formatsize;
}

bool operator==(const N64FormatSize& _other) const
{
return _other._formatsize == _formatsize;
}
};

struct GHQTexInfo
{
GHQTexInfo() {}
~GHQTexInfo() {}
unsigned char *data{ nullptr };
unsigned int width{ 0u };
unsigned int height{ 0u };
unsigned int format{ 0u };
unsigned short texture_format{ 0u };
unsigned short pixel_type{ 0u };
unsigned char is_hires_tex{ 0u };
N64FormatSize n64_format_size{ 0u, 0u };
};

/* Callback to display hires texture info.
Expand Down Expand Up @@ -155,10 +214,6 @@ typedef void (*dispInfoFuncExt)(const wchar_t *format, ...);
#endif
#endif // OS_WINDOWS

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

#ifdef __cplusplus
extern "C"{
#endif
Expand All @@ -173,16 +228,16 @@ txfilter_shutdown(void);

TAPI boolean TAPIENTRY
txfilter_filter(uint8 *src, int srcwidth, int srcheight, uint16 srcformat,
uint64 g64crc, GHQTexInfo *info);
uint64 g64crc, N64FormatSize n64FmtSz, GHQTexInfo *info);

TAPI boolean TAPIENTRY
txfilter_hirestex(uint64 g64crc, uint64 r_crc64, uint16 *palette, GHQTexInfo *info);
txfilter_hirestex(uint64 g64crc, Checksum r_crc64, uint16 *palette, N64FormatSize n64FmtSz, GHQTexInfo *info);

TAPI uint64 TAPIENTRY
txfilter_checksum(uint8 *src, int width, int height, int size, int rowStride, uint8 *palette);

TAPI boolean TAPIENTRY
txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, uint16 n64fmt, uint64 r_crc64);
txfilter_dmptx(uint8 *src, int width, int height, int rowStridePixel, uint16 gfmt, N64FormatSize n64FmtSz, Checksum r_crc64);

TAPI boolean TAPIENTRY
txfilter_reloadhirestex();
Expand Down
8 changes: 4 additions & 4 deletions src/GLideNHQ/TxHiResCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ int TxHiResCache::_getConfig() const
{
return getOptions() &
(HIRESTEXTURES_MASK |
TILE_HIRESTEX |
FORCE16BPP_HIRESTEX |
GZ_HIRESTEXCACHE |
FILE_HIRESTEXCACHE |
Expand Down Expand Up @@ -251,7 +250,7 @@ TxHiResCache::LoadResult TxHiResCache::_loadHiResTextures(const wchar_t * dir_pa
chksum64 <<= 32;
chksum64 |= (uint64)chksum;
}
if (isCached(chksum64)) {
if (isCached(chksum64, N64FormatSize(fmt, siz))) {
#if !DEBUG
INFO(80, wst("-----\n"));
INFO(80, wst("file: %s\n"), fname);
Expand Down Expand Up @@ -281,6 +280,7 @@ TxHiResCache::LoadResult TxHiResCache::_loadHiResTextures(const wchar_t * dir_pa
tmpInfo.width = width;
tmpInfo.height = height;
tmpInfo.is_hires_tex = 1;
tmpInfo.n64_format_size = N64FormatSize(fmt, siz);
setTextureFormat(format, &tmpInfo);

/* remove redundant in cache */
Expand Down Expand Up @@ -325,7 +325,7 @@ bool TxHiResCache::add(Checksum checksum, GHQTexInfo *info, int dataSize)
return TxCache::add(checksum, info, dataSize);
}

bool TxHiResCache::get(Checksum checksum, GHQTexInfo *info)
bool TxHiResCache::get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info)
{
return TxCache::get(checksum, info);
return TxCache::get(checksum, n64FmtSz, info);
}
2 changes: 1 addition & 1 deletion src/GLideNHQ/TxHiResCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class TxHiResCache : public TxCache, public TxHiResLoader
dispInfoFuncExt callback);
bool empty() const override;
bool add(Checksum checksum, GHQTexInfo *info, int dataSize = 0) override;
bool get(Checksum checksum, GHQTexInfo *info) override;
bool get(Checksum checksum, N64FormatSize n64FmtSz, GHQTexInfo *info) override;
bool reload() override;
void dump() override;
};
Expand Down
Loading

0 comments on commit 10a1291

Please sign in to comment.