Rework: Add nolerp filtering by *

This commit is contained in:
Denis Pauk 2023-08-13 15:20:26 +03:00
parent b31e174966
commit dc678793ea
8 changed files with 198 additions and 137 deletions

View File

@ -357,6 +357,7 @@ REFVK_OBJS_ := \
src/files/wal.o \
src/files/pvs.o \
src/common/shared.o \
src/common/utils.o \
src/common/md4.o
ifeq ($(YQ2_OSTYPE), Windows)

View File

@ -38,14 +38,50 @@
#error YQ2OSTYPE should be defined by the build system
#endif
#ifndef YQ2ARCH
#error YQ2ARCH should be defined by the build system
#endif
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
#ifdef _WIN32
#define CFGDIR "YamagiQ2"
#else
#ifndef __HAIKU__
#define CFGDIR ".yq2"
#else
#define CFGDIR "yq2"
#endif
#endif
#ifndef YQ2ARCH
#ifdef _MSC_VER
// Setting YQ2ARCH for VisualC++ from CMake doesn't work when using VS integrated CMake
// so set it in code instead
#ifdef YQ2ARCH
#undef YQ2ARCH
#endif
#ifdef _M_X64
// this matches AMD64 and ARM64EC (but not regular ARM64), but they're supposed to be binary-compatible somehow, so whatever
#define YQ2ARCH "x86_64"
#elif defined(_M_ARM64)
#define YQ2ARCH "arm64"
#elif defined(_M_ARM)
#define YQ2ARCH "arm"
#elif defined(_M_IX86)
#define YQ2ARCH "x86"
#else
// if you're not targeting one of the aforementioned architectures,
// check https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
// to find out how to detect yours and add it here - and please send a patch :)
#error "Unknown CPU architecture!"
// (for a quick and dirty solution, comment out the previous line, but keep in mind
// that savegames may not be compatible with other builds of Yamagi Quake II)
#define YQ2ARCH "UNKNOWN"
#endif // _M_X64 etc
#else // other compilers than MSVC
#error YQ2ARCH should be defined by the build system
#endif // _MSC_VER
#endif // YQ2ARCH
/* ================================================================== */
typedef struct sizebuf_s
@ -708,17 +744,18 @@ void Com_Printf(char *fmt, ...) PRINTF_ATTR(1, 2);
void Com_DPrintf(char *fmt, ...) PRINTF_ATTR(1, 2);
void Com_VPrintf(int print_level, const char *fmt, va_list argptr); /* print_level is PRINT_ALL or PRINT_DEVELOPER */
void Com_MDPrintf(char *fmt, ...) PRINTF_ATTR(1, 2);
YQ2_ATTR_NORETURN void Com_Error(int code, char *fmt, ...) PRINTF_ATTR(2, 3);
YQ2_ATTR_NORETURN_FUNCPTR void Com_Error(int code, char *fmt, ...) PRINTF_ATTR(2, 3);
YQ2_ATTR_NORETURN void Com_Quit(void);
/* Ugly work around for unsupported
* format specifiers unter mingw. */
#define YQ2_COM_PRId64 PRId64
#define YQ2_COM_PRIu64 PRIu64
#ifdef WIN32
#define YQ2_COM_PRId64 "%I64d"
#define YQ2_COM_PRIdS "%Id"
#else
#define YQ2_COM_PRId64 "%ld"
#define YQ2_COM_PRIdS "%zd"
#endif

View File

@ -74,7 +74,7 @@ typedef enum
} modtype_t;
#define MAX_LBM_HEIGHT 480
#define DEFAULT_NOLERP_LIST "pics/conchars.* pics/ch1.* pics/ch2. pics/ch3.*"
extern void R_Printf(int level, const char* msg, ...) PRINTF_ATTR(2, 3);
/* Shared images load */

View File

@ -61,16 +61,17 @@ typedef unsigned char byte;
// must be used as prefix (YQ2_ATTR_NORETURN void bla();)!
#define YQ2_ATTR_NORETURN _Noreturn
#define YQ2_STATIC_ASSERT(C, M) _Static_assert((C), M)
# if defined(__GNUC__)
#if defined(__GNUC__)
#define YQ2_ATTR_MALLOC __attribute__ ((__malloc__))
#define YQ2_ATTR_INLINE __attribute__((always_inline)) inline
# elif defined(_MSC_VER)
#define YQ2_ATTR_MALLOC __declspec(restrict)
# else
#elif defined(_MSC_VER)
#define YQ2_ATTR_MALLOC __declspec(restrict)
#define YQ2_ATTR_INLINE __forceinline
#else
// no equivalent per see
#define YQ2_ATTR_MALLOC
#define YQ2_ATTR_INLINE inline
# endif
#endif
#elif defined(__GNUC__) // GCC and clang should support this attribute
#define YQ2_ALIGNAS_SIZE(SIZE) __attribute__(( __aligned__(SIZE) ))
#define YQ2_ALIGNAS_TYPE(TYPE) __attribute__(( __aligned__(__alignof__(TYPE)) ))
@ -96,7 +97,7 @@ typedef unsigned char byte;
// must be used as prefix (YQ2_ATTR_NORETURN void bla();)!
#define YQ2_ATTR_NORETURN __declspec(noreturn)
#define YQ2_ATTR_MALLOC __declspec(restrict)
#define YQ2_ATTR_MALLOC __declspec(restrict)
#define YQ2_ATTR_INLINE __forceinline
#define YQ2_STATIC_ASSERT(C, M) assert((C) && M)
#else
@ -104,7 +105,7 @@ typedef unsigned char byte;
#define YQ2_ALIGNAS_SIZE(SIZE)
#define YQ2_ALIGNAS_TYPE(TYPE)
#define YQ2_ATTR_NORETURN
#define YQ2_ATTR_MALLOC
#define YQ2_ATTR_MALLOC
#define YQ2_ATTR_INLINE inline
#define YQ2_STATIC_ASSERT(C, M) assert((C) && M)
#endif
@ -372,6 +373,9 @@ float frandk(void);
float crandk(void);
void randk_seed(void);
/* Addition code utilities */
qboolean Utils_FilenameFiltered(const char *name, const char *filter, char sepator);
/*
* ==============================================================
*

View File

@ -1410,121 +1410,3 @@ Info_SetValueForKey(char *s, char *key, char *value)
*s = 0;
}
/*
* TODO: Sync with yquake
*/
/*
* name: file name
* filter: file name line rule with '*'
* return false for empty filter
*/
static qboolean
File_Filtered_Line(const char *name, const char *filter)
{
const char *current_filter = filter;
// skip empty filter
if (!*current_filter)
{
return false;
}
while (*current_filter)
{
char part_filter[MAX_QPATH];
const char *name_part;
const char *str_end;
str_end = strchr(current_filter, '*');
if (!str_end)
{
if (!strstr(name, current_filter))
{
// no such part in string
return false;
}
// have such part
break;
}
// copy filter line
if ((str_end - current_filter) >= MAX_QPATH)
{
return false;
}
memcpy(part_filter, current_filter, str_end - current_filter);
part_filter[str_end - current_filter] = 0;
// place part in name
name_part = strstr(name, part_filter);
if (!name_part)
{
// no such part in string
return false;
}
// have such part
name = name_part + strlen(part_filter);
// move to next filter
current_filter = str_end + 1;
}
return true;
}
/*
* name: file name
* filter: file names separated by sepator, and '!' for skip file
*/
qboolean
File_Filtered(const char *name, const char *filter, char sepator)
{
const char *current_filter = filter;
while (*current_filter)
{
char line_filter[MAX_QPATH];
const char *str_end;
str_end = strchr(current_filter, sepator);
// its end of filter
if (!str_end)
{
// check rules inside line
if (File_Filtered_Line(name, current_filter))
{
return true;
}
return false;
}
// copy filter line
if ((str_end - current_filter) >= MAX_QPATH)
{
return false;
}
memcpy(line_filter, current_filter, str_end - current_filter);
line_filter[str_end - current_filter] = 0;
// check rules inside line
if (*line_filter == '!')
{
// has invert rule
if (File_Filtered_Line(name, line_filter + 1))
{
return false;
}
}
else
{
if (File_Filtered_Line(name, line_filter))
{
return true;
}
}
// move to next filter
current_filter = str_end + 1;
}
return false;
}
/*
* End of unsynced code
*/

137
src/common/utils.c Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Additional functions shared between client and renders
*
* =======================================================================
*/
#include "header/shared.h"
/*
* name: file name
* filter: file name line rule with '*'
* return false for empty filter
*/
static qboolean
Utils_FilenameFiltered_Line(const char *name, const char *filter)
{
const char *current_filter = filter;
// skip empty filter
if (!*current_filter)
{
return false;
}
while (*current_filter)
{
char part_filter[MAX_QPATH];
const char *name_part;
const char *str_end;
str_end = strchr(current_filter, '*');
if (!str_end)
{
if (!strstr(name, current_filter))
{
// no such part in string
return false;
}
// have such part
break;
}
// copy filter line
if ((str_end - current_filter) >= MAX_QPATH)
{
return false;
}
memcpy(part_filter, current_filter, str_end - current_filter);
part_filter[str_end - current_filter] = 0;
// place part in name
name_part = strstr(name, part_filter);
if (!name_part)
{
// no such part in string
return false;
}
// have such part
name = name_part + strlen(part_filter);
// move to next filter
current_filter = str_end + 1;
}
return true;
}
/*
* name: file name
* filter: file names separated by sepator, and '!' for skip file
*/
qboolean
Utils_FilenameFiltered(const char *name, const char *filter, char sepator)
{
const char *current_filter = filter;
while (*current_filter)
{
char line_filter[MAX_QPATH];
const char *str_end;
str_end = strchr(current_filter, sepator);
// its end of filter
if (!str_end)
{
// check rules inside line
if (Utils_FilenameFiltered_Line(name, current_filter))
{
return true;
}
return false;
}
// copy filter line
if ((str_end - current_filter) >= MAX_QPATH)
{
return false;
}
memcpy(line_filter, current_filter, str_end - current_filter);
line_filter[str_end - current_filter] = 0;
// check rules inside line
if (*line_filter == '!')
{
// has invert rule
if (Utils_FilenameFiltered_Line(name, line_filter + 1))
{
return false;
}
}
else
{
if (Utils_FilenameFiltered_Line(name, line_filter))
{
return true;
}
}
// move to next filter
current_filter = str_end + 1;
}
return false;
}

View File

@ -693,9 +693,9 @@ void Vk_TextureMode( char *string )
if (unfiltered2D && image->type == it_pic)
{
// exception to that exception: stuff on the r_lerp_list
nolerp = (lerplist == NULL) || File_Filtered(image->name, lerplist, ' ');
nolerp = (lerplist == NULL) || Utils_FilenameFiltered(image->name, lerplist, ' ');
}
else if (nolerplist != NULL && File_Filtered(image->name, nolerplist, ' '))
else if (nolerplist != NULL && Utils_FilenameFiltered(image->name, nolerplist, ' '))
{
nolerp = true;
}
@ -1106,11 +1106,11 @@ Vk_LoadPic(const char *name, byte *pic, int width, int realwidth,
{
// if r_2D_unfiltered is true(ish), nolerp should usually be true,
// *unless* the texture is on the r_lerp_list
nolerp = (lerplist == NULL) || File_Filtered(name, lerplist, ' ');
nolerp = (lerplist == NULL) || Utils_FilenameFiltered(name, lerplist, ' ');
}
else if (nolerplist != NULL)
{
nolerp = File_Filtered(name, nolerplist, ' ');
nolerp = Utils_FilenameFiltered(name, nolerplist, ' ');
}
{

View File

@ -1169,7 +1169,7 @@ R_Register( void )
r_scale8bittextures = ri.Cvar_Get("r_scale8bittextures", "0", CVAR_ARCHIVE);
vk_underwater = ri.Cvar_Get("vk_underwater", "1", CVAR_ARCHIVE);
/* don't bilerp characters and crosshairs */
r_nolerp_list = ri.Cvar_Get("r_nolerp_list", "pics/conchars.pcx pics/ch1.pcx pics/ch2.pcx pics/ch3.pcx", CVAR_ARCHIVE);
r_nolerp_list = ri.Cvar_Get("r_nolerp_list", DEFAULT_NOLERP_LIST, CVAR_ARCHIVE);
/* textures that should always be filtered, even if r_2D_unfiltered or an unfiltered gl mode is used */
r_lerp_list = ri.Cvar_Get("r_lerp_list", "", CVAR_ARCHIVE);
/* don't bilerp any 2D elements */