From dc678793eaf607b85d9c0046415caa96786f0759 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Sun, 13 Aug 2023 15:20:26 +0300 Subject: [PATCH] Rework: Add nolerp filtering by * --- Makefile | 1 + src/common/header/common.h | 49 ++++++++++-- src/common/header/ref_shared.h | 2 +- src/common/header/shared.h | 18 +++-- src/common/shared.c | 118 ---------------------------- src/common/utils.c | 137 +++++++++++++++++++++++++++++++++ src/vk/vk_image.c | 8 +- src/vk/vk_rmain.c | 2 +- 8 files changed, 198 insertions(+), 137 deletions(-) create mode 100644 src/common/utils.c diff --git a/Makefile b/Makefile index 95969a1..1cc3313 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/src/common/header/common.h b/src/common/header/common.h index a602e0c..2d58ade 100644 --- a/src/common/header/common.h +++ b/src/common/header/common.h @@ -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 diff --git a/src/common/header/ref_shared.h b/src/common/header/ref_shared.h index 7c9f4c1..cb6985f 100644 --- a/src/common/header/ref_shared.h +++ b/src/common/header/ref_shared.h @@ -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 */ diff --git a/src/common/header/shared.h b/src/common/header/shared.h index 72e7bfb..da8f307 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -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); + /* * ============================================================== * diff --git a/src/common/shared.c b/src/common/shared.c index 14d370c..7b87018 100644 --- a/src/common/shared.c +++ b/src/common/shared.c @@ -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 - */ diff --git a/src/common/utils.c b/src/common/utils.c new file mode 100644 index 0000000..19f387f --- /dev/null +++ b/src/common/utils.c @@ -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; +} diff --git a/src/vk/vk_image.c b/src/vk/vk_image.c index 4eab4ae..1aac391 100644 --- a/src/vk/vk_image.c +++ b/src/vk/vk_image.c @@ -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, ' '); } { diff --git a/src/vk/vk_rmain.c b/src/vk/vk_rmain.c index 5dfa2ed..e9b3df0 100644 --- a/src/vk/vk_rmain.c +++ b/src/vk/vk_rmain.c @@ -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 */