Skip to content
This repository was archived by the owner on Dec 11, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions inc/common/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ typedef struct file_info_s {
#define FS_Mallocz(size) Z_TagMallocz(size, TAG_FILESYSTEM)
#define FS_CopyString(string) Z_TagCopyString(string, TAG_FILESYSTEM)
#define FS_LoadFile(path, buf) FS_LoadFileEx(path, buf, 0, TAG_FILESYSTEM)
#define FS_LoadFileFlags(path, buf, flags) \
FS_LoadFileEx(path, buf, (flags), TAG_FILESYSTEM)
#define FS_FreeFile(buf) Z_Free(buf)

// just regular malloc for now
Expand Down
7 changes: 6 additions & 1 deletion inc/refresh/refresh.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,12 @@ typedef enum {
IF_REPEAT = (1 << 6),
IF_NEAREST = (1 << 7),
IF_OPAQUE = (1 << 8),
IF_SRGB = (1 << 9)
IF_SRGB = (1 << 9),

// Image source indicator/requirement flags
IF_SRC_BASE = (0x1 << 16),
IF_SRC_GAME = (0x2 << 16),
IF_SRC_MASK = (0x3 << 16),
} imageflags_t;

typedef enum {
Expand Down
34 changes: 30 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -489,15 +489,15 @@ TARGET_INCLUDE_DIRECTORIES(server PRIVATE "${ZLIB_INCLUDE_DIRS}")
# Use dynamic zlib for steam runtime
if (CONFIG_LINUX_STEAM_RUNTIME_SUPPORT)
TARGET_LINK_LIBRARIES(client SDL2main SDL2-static z)
TARGET_LINK_LIBRARIES(server SDL2main SDL2-static z)
TARGET_LINK_LIBRARIES(server z)
else()
TARGET_LINK_LIBRARIES(client SDL2main SDL2-static zlibstatic)
TARGET_LINK_LIBRARIES(server SDL2main SDL2-static zlibstatic)
TARGET_LINK_LIBRARIES(server zlibstatic)
endif()

SET_TARGET_PROPERTIES(client
PROPERTIES
OUTPUT_NAME "q2rtx"
OUTPUT_NAME "q2rtx${BINARY_POSTFIX}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}"
Expand All @@ -508,7 +508,7 @@ SET_TARGET_PROPERTIES(client

SET_TARGET_PROPERTIES(server
PROPERTIES
OUTPUT_NAME "q2rtxded"
OUTPUT_NAME "q2rtxded${BINARY_POSTFIX}"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}"
Expand Down Expand Up @@ -543,6 +543,32 @@ IF(IS_64_BIT)
)
ENDIF()

include(ProcessorCount)

if(WIN32 AND IS_64_BIT)
set(X86_BUILD_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/build_x86")
file(MAKE_DIRECTORY "${X86_BUILD_DIRECTORY}")
set(OUTPUT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/config_x86_out.txt")
set(ERROR_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/config_x86_err.txt")
execute_process(COMMAND "${CMAKE_COMMAND}" "${CMAKE_SOURCE_DIR}" "-G" "${CMAKE_GENERATOR}" "-A" "Win32" "-DBINARY_POSTFIX=_x86"
WORKING_DIRECTORY "${X86_BUILD_DIRECTORY}"
OUTPUT_FILE "${OUTPUT_FILE_NAME}"
ERROR_FILE "${ERROR_FILE_NAME}"
RESULT_VARIABLE CONFIG_RESULT)
if(NOT CONFIG_RESULT EQUAL 0)
message(WARNING "Configuring X86 dedicated server failed with exit code ${CONFIG_RESULT}")
message(STATUS " Please see ${OUTPUT_FILE_NAME} and ${ERROR_FILE_NAME} for output")
else()
ProcessorCount(N)
if(N GREATER 0)
set(PARALLEL_ARGS "-j" "${N}")
endif()
add_custom_target(server_x86 ALL
COMMAND "${CMAKE_COMMAND}" "--build" "${X86_BUILD_DIRECTORY}" "--target" "server" "--config" "$<CONFIG>" ${PARALLEL_ARGS}
COMMENT "Build X86 dedicated server")
endif()
endif()

IF(CONFIG_LINUX_PACKAGING_SUPPORT)
# Put the real game binary in /usr/share so we can have a wrapper in /usr/bin
INSTALL(TARGETS client DESTINATION share/quake2rtx/bin COMPONENT shareware)
Expand Down
2 changes: 1 addition & 1 deletion src/client/ui/playermodels.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static qboolean IconOfSkinExists(char *skin, char **pcxfiles, int npcxfiles)
Q_strlcat(scratch, "_i.pcx", sizeof(scratch));

for (i = 0; i < npcxfiles; i++) {
if (strcmp(pcxfiles[i], scratch) == 0)
if (stricmp(pcxfiles[i], scratch) == 0)
return qtrue;
}

Expand Down
6 changes: 1 addition & 5 deletions src/common/bsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1188,11 +1188,7 @@ qerror_t BSP_Load(const char *name, bsp_t **bsp_p)

if (!BSP_LoadPatchedPVS(bsp))
{
if (dedicated->integer)
Com_WPrintf("WARNING: Pathced PVS file for %s unavailable. Some entities may disappear.\n"
"Load the map with the RTX renderer once to generate the patched PVS file.\n", bsp->name);
else
BSP_BuildPvsMatrix(bsp);
BSP_BuildPvsMatrix(bsp);
}
else
{
Expand Down
16 changes: 9 additions & 7 deletions src/common/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -3690,13 +3690,15 @@ static void fs_game_changed(cvar_t *self)
// otherwise, restart the filesystem
CL_RestartFilesystem(qfalse);

// FIXME: if baseq2/autoexec.cfg exists DO NOT exec default.cfg and config.cfg.
// this assumes user prefers to do configuration via autoexec.cfg and doesn't
// want settings and binds messed up whenever gamedir changes after startup.
if (!FS_FileExistsEx(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE)) {
Com_AddConfigFile(COM_DEFAULT_CFG, FS_PATH_GAME);
Com_AddConfigFile(COM_Q2RTX_CFG, 0);
Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);
Com_AddConfigFile(COM_DEFAULT_CFG, FS_PATH_GAME);
Com_AddConfigFile(COM_Q2RTX_CFG, 0);
Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME);

// If baseq2/autoexec.cfg exists exec it again after default.cfg and config.cfg.
// Assumes user prefers to do configuration via autoexec.cfg and hopefully
// settings and binds will be restored to their preference whenever gamedir changes after startup.
if(Q_stricmp(s, BASEGAME) && FS_FileExistsEx(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE)) {
Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE);
}

// exec autoexec.cfg (must be a real file within the game directory)
Expand Down
199 changes: 119 additions & 80 deletions src/refresh/images.c
Original file line number Diff line number Diff line change
Expand Up @@ -785,14 +785,20 @@ static image_t *lookup_image(const char *name,
return NULL;
}

static int _try_image_format(imageformat_t fmt, image_t *image, byte **pic)
#define TRY_IMAGE_SRC_GAME 1
#define TRY_IMAGE_SRC_BASE 0

static int _try_image_format(imageformat_t fmt, image_t *image, int try_src, byte **pic)
{
byte *data;
ssize_t len;
qerror_t ret;

// load the file
len = FS_LoadFile(image->name, (void **)&data);
int fs_flags = 0;
if (try_src > 0)
fs_flags = try_src == TRY_IMAGE_SRC_GAME ? FS_PATH_GAME : FS_PATH_BASE;
len = FS_LoadFileFlags(image->name, (void **)&data, fs_flags);
if (!data) {
return len;
}
Expand All @@ -812,16 +818,16 @@ static int _try_image_format(imageformat_t fmt, image_t *image, byte **pic)
return ret < 0 ? ret : fmt;
}

static int try_image_format(imageformat_t fmt, image_t *image, byte **pic)
static int try_image_format(imageformat_t fmt, image_t *image, int try_src, byte **pic)
{
// replace the extension
memcpy(image->name + image->baselen + 1, img_loaders[fmt].ext, 4);
return _try_image_format(fmt, image, pic);
return _try_image_format(fmt, image, try_src, pic);
}


// tries to load the image with a different extension
static int try_other_formats(imageformat_t orig, image_t *image, byte **pic)
static int try_other_formats(imageformat_t orig, image_t *image, int try_src, byte **pic)
{
imageformat_t fmt;
qerror_t ret;
Expand All @@ -834,7 +840,7 @@ static int try_other_formats(imageformat_t orig, image_t *image, byte **pic)
continue; // don't retry twice
}

ret = try_image_format(fmt, image, pic);
ret = try_image_format(fmt, image, try_src, pic);
if (ret != Q_ERR_NOENT) {
return ret; // found something
}
Expand All @@ -846,7 +852,7 @@ static int try_other_formats(imageformat_t orig, image_t *image, byte **pic)
return Q_ERR_NOENT; // don't retry twice
}

return try_image_format(fmt, image, pic);
return try_image_format(fmt, image, try_src, pic);
}

static void get_image_dimensions(imageformat_t fmt, image_t *image)
Expand Down Expand Up @@ -957,11 +963,23 @@ load_img(const char *name, image_t *image)
// load the pic from disk
pic = NULL;

// first try with original extension
ret = _try_image_format(fmt, image, &pic);
if (ret == Q_ERR_NOENT) {
// retry with remaining extensions
ret = try_other_formats(fmt, image, &pic);
// Always prefer images from the game dir, even if format might be 'inferior'
for (int try_location = Q_stricmp(fs_game->string, BASEGAME) ? TRY_IMAGE_SRC_GAME : TRY_IMAGE_SRC_BASE;
try_location >= TRY_IMAGE_SRC_BASE;
try_location--)
{
int location_flag = try_location == TRY_IMAGE_SRC_GAME ? IF_SRC_GAME : IF_SRC_MASK;
if(((image->flags & IF_SRC_MASK) != 0) && ((image->flags & IF_SRC_MASK) != location_flag))
continue;

// first try with original extension
ret = _try_image_format(fmt, image, try_location, &pic);
if (ret == Q_ERR_NOENT) {
// retry with remaining extensions
ret = try_other_formats(fmt, image, try_location, &pic);
}
if (ret >= 0)
break;
}

// if we are replacing 8-bit texture with a higher resolution 32-bit
Expand Down Expand Up @@ -1029,80 +1047,101 @@ static qerror_t find_or_load_image(const char *name, size_t len,
if (!vid_rtx->integer && (type != IT_PIC))
override_textures = 0;

for (int use_override = override_textures; use_override >= 0; use_override--)
{
// fill in some basic info
if (use_override)
{
const char* last_slash = strrchr(name, '/');
if (!last_slash)
last_slash = name;
else
last_slash += 1;

strcpy(image->name, "overrides/");
strcat(image->name, last_slash);
image->baselen = strlen(image->name) - 4;
}
else
{
memcpy(image->name, name, len + 1);
image->baselen = len - 4;
}
image->type = type;
image->flags = flags;
image->registration_sequence = registration_sequence;

// find out original extension
for (fmt = 0; fmt < IM_MAX; fmt++) {
if (!Q_stricmp(image->name + image->baselen + 1, img_loaders[fmt].ext)) {
break;
}
}
// Always prefer images from the game dir, even if format might be 'inferior'
for (int try_location = Q_stricmp(fs_game->string, BASEGAME) ? TRY_IMAGE_SRC_GAME : TRY_IMAGE_SRC_BASE;
try_location >= TRY_IMAGE_SRC_BASE;
try_location--)
{
int location_flag = try_location == TRY_IMAGE_SRC_GAME ? IF_SRC_GAME : IF_SRC_MASK;
if(((flags & IF_SRC_MASK) != 0) && ((flags & IF_SRC_MASK) != location_flag))
continue;

// load the pic from disk
pic = NULL;
for (int use_override = override_textures; use_override >= 0; use_override--)
{
// fill in some basic info
if (use_override)
{
const char *last_slash = strrchr(name, '/');
if (!last_slash)
last_slash = name;
else
last_slash += 1;

if (fmt == IM_MAX) {
// unknown extension, but give it a chance to load anyway
ret = try_other_formats(IM_MAX, image, &pic);
if (ret == Q_ERR_NOENT) {
// not found, change error to invalid path
ret = Q_ERR_INVALID_PATH;
}
}
else if (override_textures) {
// forcibly replace the extension
ret = try_other_formats(IM_MAX, image, &pic);
}
else {
// first try with original extension
ret = _try_image_format(fmt, image, &pic);
if (ret == Q_ERR_NOENT) {
// retry with remaining extensions
ret = try_other_formats(fmt, image, &pic);
}
}
strcpy(image->name, "overrides/");
strcat(image->name, last_slash);
image->baselen = strlen(image->name) - 4;
}
else
{
memcpy(image->name, name, len + 1);
image->baselen = len - 4;
}
image->type = type;
image->flags = flags | location_flag;
image->registration_sequence = registration_sequence;

// find out original extension
for (fmt = 0; fmt < IM_MAX; fmt++)
{
if (!Q_stricmp(image->name + image->baselen + 1, img_loaders[fmt].ext))
{
break;
}
}

// record last modified time (skips reload when invoking IMG_ReloadAll)
image->last_modified = 0;
FS_LastModified(image->name, &image->last_modified);
// load the pic from disk
pic = NULL;

if (fmt == IM_MAX)
{
// unknown extension, but give it a chance to load anyway
ret = try_other_formats(IM_MAX, image, try_location, &pic);
if (ret == Q_ERR_NOENT)
{
// not found, change error to invalid path
ret = Q_ERR_INVALID_PATH;
}
}
else if (override_textures)
{
// forcibly replace the extension
ret = try_other_formats(IM_MAX, image, try_location, &pic);
}
else
{
// first try with original extension
ret = _try_image_format(fmt, image, try_location, &pic);
if (ret == Q_ERR_NOENT)
{
// retry with remaining extensions
ret = try_other_formats(fmt, image, try_location, &pic);
}
}

if (use_override)
{
memcpy(image->name, name, len + 1);
image->baselen = len - 4;
}
// record last modified time (skips reload when invoking IMG_ReloadAll)
image->last_modified = 0;
FS_LastModified(image->name, &image->last_modified);

// if we are replacing 8-bit texture with a higher resolution 32-bit
// texture, we need to recover original image dimensions
if (fmt <= IM_WAL && ret > IM_WAL) {
get_image_dimensions(fmt, image);
}
if (use_override)
{
memcpy(image->name, name, len + 1);
image->baselen = len - 4;
}

if(ret >= 0)
break;
}
// if we are replacing 8-bit texture with a higher resolution 32-bit
// texture, we need to recover original image dimensions
if (fmt <= IM_WAL && ret > IM_WAL)
{
get_image_dimensions(fmt, image);
}

if (ret >= 0)
break;
}

if (ret >= 0)
break;
}

if (ret < 0) {
memset(image, 0, sizeof(*image));
Expand Down
Loading