From 2a848e32e4a8a66c0cf3bf34c54c498f19cd6135 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 2 Sep 2025 21:19:01 +0200 Subject: [PATCH 01/13] port map icon packet for serverinfo screen based on https://codeberg.org/srb2classic/srb2classic/pulls/134 with adjustments many thanks for the help @indev450 ! <3 --- src/d_clisrv.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++-- src/d_clisrv.h | 4 +- src/d_net.c | 1 + src/r_defs.h | 3 + src/r_patch.c | 144 ++++++++++++++++++++++++++ src/r_patch.h | 126 +++++++++++------------ 6 files changed, 476 insertions(+), 69 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f8bf137f9..96e0f2f41 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -16,6 +16,8 @@ #include //for unlink #endif +#include + #include "i_time.h" #include "i_net.h" #include "i_system.h" @@ -87,6 +89,16 @@ boolean serverrunning = false; INT32 serverplayer = 0; char motd[254], server_context[8]; // Message of the Day, Unique Context (even without Mumble support) +#define MAP_ICON_REQUEST_FREQUENCY 8 + +static UINT8 map_icon_index; // amount of fragments we have retrieved +static UINT8 map_icon_needed; // amount of fragments we need to get the full data set +static INT32 map_icon_read; // amount of bytes we have read +static UINT32 map_icon_missing; // bitmask of fragments we haven't received yet +static tic_t map_icon_last_request; // last time we sent an icon request, to avoid flood +static UINT8 *map_icon_data; +static patch_t *map_icon; + plrinfo playerinfo[MAXPLAYERS]; SINT8 joinnode = 0; // used for CL_VIEWSERVER @@ -1337,9 +1349,40 @@ static inline void CL_DrawConnectionStatus(void) V_DrawThinString(12 + 80, 18, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.servername)); - const char *map = va("%sP", serverlist[joinnode].info.mapname); - patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : W_CachePatchName("BLANKLVL", PU_CACHE); - V_DrawSmallScaledPatch(10, 18, 0, current_map); + if (map_icon == NULL) + { + const char *map = va("%sP", serverlist[joinnode].info.mapname); + patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : NULL; + + if (current_map != NULL) + V_DrawSmallScaledPatch(10, 18, 0, current_map); + else if (map_icon_data != NULL) + { + if (I_GetTime() - map_icon_last_request > MAP_ICON_REQUEST_FREQUENCY) + { + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + netbuffer->packettype = PT_NEEDMAPICON; + + // failed to retrieve map icon, request it again + HSendPacket(servernode, false, 0, 0); + map_icon_last_request = I_GetTime(); + } + + V_DrawFill(10, 18, MAP_ICON_WIDTH / 2, MAP_ICON_HEIGHT / 2, 31); + char dots[4] = "..."; + if ((I_GetTime() & 0xf) < 4) + dots[0] = '\0'; + else if ((I_GetTime() & 0xf) < 8) + dots[1] = '\0'; + else if ((I_GetTime() & 0xf) < 12) + dots[2] = '\0'; + V_DrawString(10 + MAP_ICON_WIDTH / 4 - V_StringWidth("...", 0) / 2, 18 + MAP_ICON_HEIGHT / 4 - 3, 0, dots); + } + else + V_DrawSmallScaledPatch(10, 18, 0, W_CachePatchName("BLANKLVL", PU_CACHE)); + } + else + V_DrawSmallScaledPatch(10, 18, 0, map_icon); V_DrawThinString(12 + 80, 38, V_ALLOWLOWERCASE, va("%s", serverlist[joinnode].info.maptitle)); V_DrawThinString(12 + 80, 48, V_ALLOWLOWERCASE, va("%s", Gametype_Names[serverlist[joinnode].info.gametype])); @@ -1722,6 +1765,83 @@ static void SV_SendPlayerInfo(INT32 node) HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS); } +static void SV_SendMapIcon(INT32 node) +{ + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + + const char *map = va("%sP", G_BuildMapName(gamemap)); + if (!W_LumpExists(map)) + { + // send an empty icon to tell the client there is no map icon + netbuffer->packettype = PT_MAPICON; + UINT8 *icondata = netbuffer->u.mapicondata; + WRITEUINT8(icondata, 0x80); + HSendPacket(node, false, 0, 1); + return; + } + + patch_t *current_map = W_CachePatchName(map, PU_CACHE); + if (current_map->width != MAP_ICON_WIDTH || current_map->height != MAP_ICON_HEIGHT) + { + // we only support 160x100 for now + netbuffer->packettype = PT_MAPICON; + UINT8 *icondata = netbuffer->u.mapicondata; + WRITEUINT8(icondata, 0x80); + HSendPacket(node, false, 0, 1); + return; + } + + UINT8 *data = Z_Malloc(2 * current_map->width * current_map->height, PU_STATIC, NULL); + UINT8 *pixeldata = data + current_map->width * current_map->height; + + R_PatchToPixels(current_map, pixeldata); + + z_stream stream; + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + if (deflateInit(&stream, Z_DEFAULT_COMPRESSION) != Z_OK) + { + CONS_Alert(CONS_WARNING, "Cannot compress map icon, not enough memory\n"); + Z_Free(data); + return; + } + + stream.next_in = pixeldata; + stream.avail_in = current_map->width * current_map->height; + stream.next_out = data; + stream.avail_out = current_map->width * current_map->height; + if (deflate(&stream, Z_FINISH) != Z_STREAM_END) + { + CONS_Alert(CONS_WARNING, "Cannot compress map icon, error occured during compression\n"); + deflateEnd(&stream); + Z_Free(data); + return; + } + size_t count = stream.total_out; + deflateEnd(&stream); + + size_t index = 0; + + for (size_t i = 0; i < count; i += MAXPACKETLENGTH-BASEPACKETSIZE-1) + { + size_t size = min(MAXPACKETLENGTH-BASEPACKETSIZE-1, count-i); + + UINT8 *icondata = netbuffer->u.mapicondata; + netbuffer->packettype = PT_MAPICON; + + if (count-i <= MAXPACKETLENGTH-BASEPACKETSIZE-1) + WRITEUINT8(icondata, 0x80 | index); + else + WRITEUINT8(icondata, index); + index++; + + WRITEMEM(icondata, &data[i], size); + HSendPacket(node, false, 0, size + 1); + } + Z_Free(data); +} + /** Sends a PT_SERVERCFG packet * * \param node The destination @@ -2704,9 +2824,26 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic if (cl_mode == CL_VIEWSERVER) { if (key == KEY_ENTER || key == KEY_JOY1) + { cl_mode = CL_CHECKFILES; + if (map_icon != NULL) + Patch_Free(map_icon); + map_icon = NULL; + if (map_icon_data != NULL) + Z_Free(map_icon_data); + map_icon_data = NULL; + } else if (key == KEY_ESCAPE || key == KEY_JOY1+1) + { cl_mode = CL_ABORTED; + if (map_icon != NULL) + Patch_Free(map_icon); + map_icon = NULL; + if (map_icon_data != NULL) + Z_Free(map_icon_data); + map_icon_data = NULL; + map_icon_request_count = 0; + } } // Only ESC and non-keyboard keys abort connection @@ -4707,7 +4844,7 @@ static void HandleConnect(SINT8 node) connectedplayers++; #ifdef SATURNJOIN - const boolean issaturn = (((doomcom->datalength-BASEPACKETSIZE) == sizeof(clientconfig_pak)) && netbuffer->u.clientcfg.issaturn == ISSATURN); // Check the packet lenght to skip potential garbo data! + const boolean issaturn = (((doomcom->datalength) == sizeof(clientconfig_pak)) && netbuffer->u.clientcfg.issaturn == ISSATURN); // Check the packet lenght to skip potential garbo data! #endif if (bannednode && bannednode[node].banid != SIZE_MAX) @@ -4916,6 +5053,17 @@ static void HandleServerInfo(SINT8 node) if (client && cl_mode > CL_SEARCHING && node == servernode) memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME); + + if (map_icon_data != NULL) + Z_Free(map_icon_data); + if (map_icon != NULL) + Patch_Free(map_icon); + map_icon_data = Z_Malloc(MAP_ICON_WIDTH * MAP_ICON_HEIGHT, PU_CACHE, NULL); + map_icon_index = 0; + map_icon_needed = 0xff; + map_icon_read = 0; + map_icon_missing = 0xffffffff; + map_icon_last_request = I_GetTime(); } static void HandlePlayerInfo(void) @@ -4927,6 +5075,100 @@ static void HandlePlayerInfo(void) playerinfo[i] = netbuffer->u.playerinfo[i]; } +static void PT_MapIcon(void) +{ + if (map_icon_data == NULL) + return; + + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + + UINT8 *icondata = netbuffer->u.mapicondata; + + map_icon_last_request = I_GetTime(); + + UINT8 index = READUINT8(icondata); + if (index & 0x80) + map_icon_needed = (index & 0x7f) + 1; + index &= 0x7f; + + // check if we already got this fragment + if (map_icon_missing & ((UINT32)1 << index)) + { + map_icon_missing &= ~((UINT32)1 << index); + INT32 offset = index * (MAXPACKETLENGTH-BASEPACKETSIZE-1); + if (offset + doomcom->datalength-1 > MAP_ICON_WIDTH * MAP_ICON_HEIGHT) + { + CONS_Alert(CONS_WARNING, "Excess amount of data for map icon (expected %d, got %d)\n", MAP_ICON_WIDTH * MAP_ICON_HEIGHT, offset + doomcom->datalength-1); + Z_Free(map_icon_data); + map_icon_data = NULL; + return; + } + + READMEM(icondata, &map_icon_data[offset], doomcom->datalength-1); + map_icon_read += doomcom->datalength-1; + map_icon_index++; + } + + if (map_icon_index >= map_icon_needed) + { + if (map_icon_read == 0) + { + // map has no icon + Z_Free(map_icon_data); + map_icon_data = NULL; + return; + } + + UINT8 *data = Z_Malloc(MAP_ICON_WIDTH * MAP_ICON_HEIGHT, PU_STATIC, NULL); + z_stream stream; + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + stream.next_in = map_icon_data; + stream.avail_in = map_icon_read; + if (inflateInit(&stream) != Z_OK) + { + CONS_Alert(CONS_WARNING, "Cannot decompress map icon, not enough memory\n"); + Z_Free(data); + Z_Free(map_icon_data); + map_icon_data = NULL; + return; + } + stream.next_out = data; + stream.avail_out = MAP_ICON_WIDTH * MAP_ICON_HEIGHT; + if (inflate(&stream, Z_FINISH) != Z_STREAM_END) + { + CONS_Alert(CONS_WARNING, "Failed to decompress map icon, map icon is invalid or corrupted\n"); + deflateEnd(&stream); + Z_Free(data); + Z_Free(map_icon_data); + map_icon_data = NULL; + return; + } + inflateEnd(&stream); + Z_Free(map_icon_data); + map_icon_data = NULL; + + if (stream.total_out > MAP_ICON_WIDTH * MAP_ICON_HEIGHT) + { + CONS_Alert(CONS_WARNING, "Excess amount of data for map icon (expected %d, got %ld)\n", MAP_ICON_WIDTH * MAP_ICON_HEIGHT, stream.total_out); + Z_Free(data); + return; + } + else if (stream.total_out < MAP_ICON_WIDTH * MAP_ICON_HEIGHT) + { + CONS_Alert(CONS_WARNING, "Insufficient amount of data for map icon (expected %d, got %ld)\n", MAP_ICON_WIDTH * MAP_ICON_HEIGHT, stream.total_out); + Z_Free(data); + return; + } + + //map_icon = Patch_CreateFromData(MAP_ICON_WIDTH, MAP_ICON_HEIGHT, data); + map_icon = (patch_t *)R_PixelsToPatch(data, MAP_ICON_WIDTH, MAP_ICON_HEIGHT, 0, 0, NULL); + + Z_Free(data); + } +} + static void PT_TellFilesNeeded(SINT8 node) { if (server && serverrunning) @@ -4975,11 +5217,18 @@ static void PT_AskInfo(SINT8 node) doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); SV_SendPlayerInfo(node); // Send extra info + //SV_SendMapIcon(node); // idk i dont think we need this here } Net_CloseConnection(node); } +static void PT_NeedMapIcon(SINT8 node) +{ + SV_SendMapIcon(node); + Net_CloseConnection(node); +} + // Negative response of client join request static void PT_ServerRefuse(SINT8 node) { @@ -5240,6 +5489,12 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_PLAYERINFO: HandlePlayerInfo(); break; + case PT_MAPICON: + PT_MapIcon(); + break; + case PT_NEEDMAPICON: + PT_NeedMapIcon(node); + break; case PT_SERVERTICS: // Do not remove my own server (we have just get a out of order packet) if (node == servernode) @@ -5528,10 +5783,10 @@ static void PT_TextCmd(INT32 netconsole, SINT8 node) // ignore if the textcmd size var is actually larger than it should be // BASEPACKETSIZE + 1 (for size) + textcmd[0] should == datalength - if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-BASEPACKETSIZE-1) + if (netbuffer->u.textcmd[0] > (size_t)doomcom->datalength-1) { DEBFILE(va("GetPacket: Bad Textcmd packet size! (expected %d, actual %s, node %u, player %d)\n", - netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-BASEPACKETSIZE-1), + netbuffer->u.textcmd[0], sizeu1((size_t)doomcom->datalength-1), node, netconsole)); Net_UnAcknowledgePacket(node); return; diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 4b967e670..7582fdc2c 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -120,6 +120,8 @@ typedef enum PT_ISSATURN, // Saturn specific identifier packet #endif + PT_MAPICON, // Send map image icon (gamespy). + PT_NEEDMAPICON, // Request missed map icon (gamespy). NUMPACKETTYPE } packettype_t; @@ -513,6 +515,7 @@ typedef struct INT32 filesneedednum; // 4 bytes filesneededconfig_pak filesneededcfg; // ??? bytes UINT32 pingtable[MAXPLAYERS+1]; // 68 bytes + UINT8 mapicondata[0]; } u; // This is needed to pack diff packet types data together } ATTRPACK doomdata_t; @@ -564,7 +567,6 @@ typedef enum KR_TIMEOUT, //Connection Timeout KR_BAN, //Banned by server KR_LEAVE, //Quit the game - } kickreason_t; /* the max number of name changes in some time period */ diff --git a/src/d_net.c b/src/d_net.c index 3a75a29a4..af1d1a777 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1201,6 +1201,7 @@ boolean HGetPacket(void) GotAcks(); continue; } + doomcom->datalength -= BASEPACKETSIZE; break; } #endif // ifndef NONET diff --git a/src/r_defs.h b/src/r_defs.h index e1fc574bc..37a06c03d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -25,6 +25,9 @@ #include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT +#define MAP_ICON_WIDTH 160 +#define MAP_ICON_HEIGHT 100 + // // ClipWallSegment // Clips the given range of columns diff --git a/src/r_patch.c b/src/r_patch.c index f48996ea4..587d79153 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -451,6 +451,114 @@ void *Patch_CreateGL(patch_t *patch) } #endif // HWRENDER +// +// R_MaskedFlatToPatch +// +// Convert raw pixels to a patch. +// +void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize) +{ + INT16 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + size_t size = 0; + + if (!raw) + return NULL; + + // Write image size and offset + WRITEINT16(imgptr, width); + WRITEINT16(imgptr, height); + WRITEINT16(imgptr, leftoffset); + WRITEINT16(imgptr, topoffset); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += width*4; + + // Write columns + for (x = 0; x < width; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + // Write column pointer + WRITEINT32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < height; y++) + { + UINT8 pixel = raw[((y * width) + x)]; + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITEUINT8(imgptr, writeY); + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + WRITEUINT8(imgptr, pixel); + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITEUINT8(imgptr, 0); + + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + memcpy(img, imgbuf, size); + + if (destsize != NULL) + *destsize = size; + + patch_t *converted = Patch_Create((softwarepatch_t *)img, size, NULL); +#ifdef HWRENDER + Patch_CreateGL(converted); +#endif + Z_Free(img); + + return converted; +} // // R_MaskedFlatToPatch @@ -615,3 +723,39 @@ UINT16 R_GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) return 0xFF00; } + +void R_PatchToPixels(patch_t *patch, UINT8 *dst) +{ + for (INT32 x = 0; x < patch->width; ++x) + { + INT32 y = 0; + INT32 prevdelta = -1; + + column_t *column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[x])); + + while (column->topdelta != 0xff) + { + INT32 topdelta = column->topdelta; + + if (topdelta <= prevdelta) + topdelta += prevdelta; + + prevdelta = topdelta; + + for (; y-topdelta < column->length; ++y) + { + UINT8 pixel = 0; + + if (y >= topdelta) + { + UINT8 *source = (UINT8*)(column) + 3; + pixel = source[y-topdelta]; + } + + dst[(y*patch->width) + x] = pixel; + } + + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } +} diff --git a/src/r_patch.h b/src/r_patch.h index 2978ff10c..2dc9c2f4e 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -1,62 +1,64 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 2018-2019 by Jaime "Lactozilla" Passos. -// Copyright (C) 2019 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file r_patch.h -/// \brief Patch generation. - -#ifndef __R_PATCH__ -#define __R_PATCH__ - -#include "r_defs.h" - -// Structs -typedef enum -{ - ROTAXIS_X, // Roll (the default) - ROTAXIS_Y, // Pitch - ROTAXIS_Z // Yaw -} rotaxis_t; - -typedef struct -{ - INT32 x, y; - rotaxis_t rotaxis; -} spriteframepivot_t; - -typedef struct -{ - spriteframepivot_t pivot[64]; - boolean available; -} spriteinfo_t; - -// Patch functions -patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); -void Patch_Free(patch_t *patch); - -#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) -void Patch_FreeTags(INT32 lowtag, INT32 hightag); - -#ifdef HWRENDER -void *Patch_AllocateHardwarePatch(patch_t *patch); -void *Patch_CreateGL(patch_t *patch); -#endif - -// Conversions between patches / flats / textures... -boolean R_CheckIfPatch(lumpnum_t lump); - -// SpriteInfo -extern spriteinfo_t spriteinfo[NUMSPRITES]; -void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); -void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); - -void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize); -UINT16 R_GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip); - -#endif // __R_PATCH__ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2018-2019 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_patch.h +/// \brief Patch generation. + +#ifndef __R_PATCH__ +#define __R_PATCH__ + +#include "r_defs.h" + +// Structs +typedef enum +{ + ROTAXIS_X, // Roll (the default) + ROTAXIS_Y, // Pitch + ROTAXIS_Z // Yaw +} rotaxis_t; + +typedef struct +{ + INT32 x, y; + rotaxis_t rotaxis; +} spriteframepivot_t; + +typedef struct +{ + spriteframepivot_t pivot[64]; + boolean available; +} spriteinfo_t; + +// Patch functions +patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest); +void Patch_Free(patch_t *patch); + +#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum) +void Patch_FreeTags(INT32 lowtag, INT32 hightag); + +#ifdef HWRENDER +void *Patch_AllocateHardwarePatch(patch_t *patch); +void *Patch_CreateGL(patch_t *patch); +#endif + +// Conversions between patches / flats / textures... +boolean R_CheckIfPatch(lumpnum_t lump); + +// SpriteInfo +extern spriteinfo_t spriteinfo[NUMSPRITES]; +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); +void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); + +void *R_MaskedFlatToPatch(UINT16 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize); +void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, INT16 topoffset, size_t *destsize); +UINT16 R_GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip); +void R_PatchToPixels(patch_t *patch, UINT8 *dst); // Important: dst must have enough space for patch->width*patch->height pixels! + +#endif // __R_PATCH__ -- 2.54.0 From 275d28c9c6afee47fd1cf0819b12c6a9905d0974 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 2 Sep 2025 21:22:00 +0200 Subject: [PATCH 02/13] implement map icon request counter/limit tries 5 times then gives up this is just since vanilla clients do not send anything back to us so this would endlessly retry which is pointless can be adjusted if needed --- src/d_clisrv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 96e0f2f41..30f5f4d66 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -96,6 +96,7 @@ static UINT8 map_icon_needed; // amount of fragments we need to get the full dat static INT32 map_icon_read; // amount of bytes we have read static UINT32 map_icon_missing; // bitmask of fragments we haven't received yet static tic_t map_icon_last_request; // last time we sent an icon request, to avoid flood +static int map_icon_request_count; // current count of icon requests sent static UINT8 *map_icon_data; static patch_t *map_icon; @@ -1223,6 +1224,10 @@ static inline void CL_DrawConnectionStatus(void) if (!menuactive) // menu already draws its own fade V_DrawFadeScreen(0xFF00, 16); // force default + // reset the counter for mapicon + if (cl_mode != CL_VIEWSERVER) + map_icon_request_count = 0; + if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES && cl_mode != CL_CHECKFILES && cl_mode != CL_VIEWSERVER #ifdef HAVE_CURL && cl_mode != CL_DOWNLOADHTTPFILES @@ -1356,7 +1361,7 @@ static inline void CL_DrawConnectionStatus(void) if (current_map != NULL) V_DrawSmallScaledPatch(10, 18, 0, current_map); - else if (map_icon_data != NULL) + else if (map_icon_data != NULL && map_icon_request_count <= 5) { if (I_GetTime() - map_icon_last_request > MAP_ICON_REQUEST_FREQUENCY) { @@ -1366,6 +1371,7 @@ static inline void CL_DrawConnectionStatus(void) // failed to retrieve map icon, request it again HSendPacket(servernode, false, 0, 0); map_icon_last_request = I_GetTime(); + map_icon_request_count++; } V_DrawFill(10, 18, MAP_ICON_WIDTH / 2, MAP_ICON_HEIGHT / 2, 31); @@ -5085,6 +5091,7 @@ static void PT_MapIcon(void) UINT8 *icondata = netbuffer->u.mapicondata; map_icon_last_request = I_GetTime(); + map_icon_request_count = 0; UINT8 index = READUINT8(icondata); if (index & 0x80) -- 2.54.0 From e160427108324a215cfc130560dd04ece8ce3c38 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 2 Sep 2025 21:37:58 +0200 Subject: [PATCH 03/13] add smol comment --- src/d_clisrv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 30f5f4d66..c8d3b2b85 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1359,6 +1359,7 @@ static inline void CL_DrawConnectionStatus(void) const char *map = va("%sP", serverlist[joinnode].info.mapname); patch_t *current_map = W_LumpExists(map) ? W_CachePatchName(map, PU_CACHE) : NULL; + // check first if we may have the map icon loaded already if (current_map != NULL) V_DrawSmallScaledPatch(10, 18, 0, current_map); else if (map_icon_data != NULL && map_icon_request_count <= 5) -- 2.54.0 From f67f8e7dbf4b817fb29fb85d36917ba5150b11e7 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 2 Sep 2025 22:17:46 +0200 Subject: [PATCH 04/13] cache patch width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit just to avoid some cache misses in a somewhat tight lööp --- src/r_patch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/r_patch.c b/src/r_patch.c index 587d79153..3f7fdc983 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -726,7 +726,9 @@ UINT16 R_GetPatchPixel(patch_t *patch, INT32 x, INT32 y, boolean flip) void R_PatchToPixels(patch_t *patch, UINT8 *dst) { - for (INT32 x = 0; x < patch->width; ++x) + const INT16 width = patch->width; + + for (INT32 x = 0; x < width; ++x) { INT32 y = 0; INT32 prevdelta = -1; @@ -752,7 +754,7 @@ void R_PatchToPixels(patch_t *patch, UINT8 *dst) pixel = source[y-topdelta]; } - dst[(y*patch->width) + x] = pixel; + dst[(y*width) + x] = pixel; } column = (column_t *)((UINT8 *)column + column->length + 4); -- 2.54.0 From 92d6c2b7b0143945033b10bb99596c89a1cea5fc Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 3 Sep 2025 10:15:20 +0200 Subject: [PATCH 05/13] make patch/pixel conversion account for padding data/no data just set everything to transparent pixel 247 (0xf7) so we neither write nor read garbage data and just can cut it out as transparent during pixel to patch conversion --- src/r_patch.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/r_patch.c b/src/r_patch.c index 3f7fdc983..d8e0b94f3 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -491,6 +491,16 @@ void *R_PixelsToPatch(UINT8 *raw, INT16 width, INT16 height, INT16 leftoffset, I for (y = 0; y < height; y++) { UINT8 pixel = raw[((y * width) + x)]; + UINT8 opaque = (pixel != 0xf7); // If not 247 (0xf7), we have a pixel + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITEUINT8(imgptr, 0); + startofspan = NULL; + continue; + } // Start new column if we need to if (!startofspan || spanSize == 255) @@ -728,6 +738,9 @@ void R_PatchToPixels(patch_t *patch, UINT8 *dst) { const INT16 width = patch->width; + // init out destination to cyan so we can easily check for it when we convert it back to a patch + memset(dst, 0xf7, (width * patch->height)); // should this be here or should this be taken care of before passing it? + for (INT32 x = 0; x < width; ++x) { INT32 y = 0; -- 2.54.0 From cd7ce5698ca89162ea937962530b94e552cad047 Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 5 Sep 2025 17:34:09 +0300 Subject: [PATCH 06/13] Update vote background if hud.setVoteBackground was called on vote screen --- src/lua_hudlib.c | 4 ++++ src/y_inter.c | 2 +- src/y_inter.h | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 98120cebf..c33b2fca1 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1278,6 +1278,10 @@ static int lib_hudsetvotebackground(lua_State *L) strncpy(VoteScreen.luaPrefix, prefix, 4); strupr(VoteScreen.luaPrefix); + // Update background if we're already on vote screen + if (gamestate == GS_VOTING) + Y_VoteScreenCheck(); + return 0; } diff --git a/src/y_inter.c b/src/y_inter.c index 0c096127a..bbd9f11fe 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -820,7 +820,7 @@ static void Y_FollowIntermission(void) // // Y_VoteScreenCheck // -static void Y_VoteScreenCheck(void) +void Y_VoteScreenCheck(void) { strcpy(VoteScreen.Prefix, "INTS"); diff --git a/src/y_inter.h b/src/y_inter.h index be8592357..31dc96694 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -21,6 +21,7 @@ void Y_VoteTicker(void); void Y_StartVote(void); void Y_EndVote(void); void Y_SetupVoteFinish(SINT8 pick, SINT8 level); +void Y_VoteScreenCheck(void); typedef struct { -- 2.54.0 From 437f900c257578930644994a5881849ae0747e6a Mon Sep 17 00:00:00 2001 From: Indev Date: Fri, 5 Sep 2025 18:21:01 +0300 Subject: [PATCH 07/13] Clear dangling pointers in VoteScreen struct after mapload --- src/p_setup.c | 2 ++ src/y_inter.c | 16 ++++++++++++++++ src/y_inter.h | 1 + 3 files changed, 19 insertions(+) diff --git a/src/p_setup.c b/src/p_setup.c index f36ab9b44..3d5bf3f7f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2942,6 +2942,8 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) //Patch_FreeTag(PU_PATCH_ROTATED); // we keep those ty! Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + Y_VoteClear(); + #if defined (WALLSPLATS) || defined (FLOORSPLATS) // clear the splats from previous level R_ClearLevelSplats(); diff --git a/src/y_inter.c b/src/y_inter.c index bbd9f11fe..892187d85 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1574,6 +1574,22 @@ void Y_EndVote(void) voteendtic = -1; } +// +// Y_VoteClear +// Resets patches to prevent dangling pointers +// +void Y_VoteClear(void) +{ + VoteScreen.bgpatch = NULL; + VoteScreen.widebgpatch = NULL; + + for (size_t i = 0; i < sizeof(VoteScreen.cursor)/sizeof(VoteScreen.cursor[0]); ++i) + VoteScreen.cursor[i] = NULL; + + VoteScreen.randomlvl = NULL; + VoteScreen.rubyicon = NULL; +} + // // Y_SetupVoteFinish // diff --git a/src/y_inter.h b/src/y_inter.h index 31dc96694..401461db7 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -22,6 +22,7 @@ void Y_StartVote(void); void Y_EndVote(void); void Y_SetupVoteFinish(SINT8 pick, SINT8 level); void Y_VoteScreenCheck(void); +void Y_VoteClear(void); typedef struct { -- 2.54.0 From 01b24e54179207c65f9a79e6bf5d9b5a7ad40983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 8 Sep 2025 18:01:26 +0200 Subject: [PATCH 08/13] Fix use-after-free when listing servers --- src/d_clisrv.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index b20feac37..92fd72981 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2949,6 +2949,17 @@ static void CL_ConnectToServer(void) serverlist[i].info.version, serverlist[i].info.subversion); } SL_ClearServerList(servernode); + + if (map_icon_data != NULL) + Z_Free(map_icon_data); + if (map_icon != NULL) + Patch_Free(map_icon); + map_icon_data = Z_Malloc(MAP_ICON_WIDTH * MAP_ICON_HEIGHT, PU_CACHE, NULL); + map_icon_index = 0; + map_icon_needed = 0xff; + map_icon_read = 0; + map_icon_missing = 0xffffffff; + map_icon_last_request = I_GetTime(); #endif do @@ -5004,17 +5015,6 @@ static void HandleTimeout(SINT8 node) M_StartMessage(M_GetText("Server Timeout\n\nPress Esc\n"), NULL, MM_NOTHING); } -// Helper function for packets that should only be sent by the server -// If it is NOT from the server, bail out and close the connection! -static boolean ServerOnly(SINT8 node) -{ - if (node == servernode) - return false; - - Net_CloseConnection(node); - return true; -} - #ifndef NONET /** Called when a PT_SERVERINFO packet is received * @@ -5043,17 +5043,6 @@ static void HandleServerInfo(SINT8 node) if (client && cl_mode > CL_SEARCHING && node == servernode) memcpy(connectedservername, netbuffer->u.serverinfo.servername, MAXSERVERNAME); - - if (map_icon_data != NULL) - Z_Free(map_icon_data); - if (map_icon != NULL) - Patch_Free(map_icon); - map_icon_data = Z_Malloc(MAP_ICON_WIDTH * MAP_ICON_HEIGHT, PU_CACHE, NULL); - map_icon_index = 0; - map_icon_needed = 0xff; - map_icon_read = 0; - map_icon_missing = 0xffffffff; - map_icon_last_request = I_GetTime(); } static void HandlePlayerInfo(void) @@ -5065,11 +5054,25 @@ static void HandlePlayerInfo(void) playerinfo[i] = netbuffer->u.playerinfo[i]; } +// Helper function for packets that should only be sent by the server +// If it is NOT from the server, bail out and close the connection! +static boolean ServerOnly(SINT8 node) +{ + if (node == servernode) + return false; + + Net_CloseConnection(node); + return true; +} + static void PT_MapIcon(void) { if (map_icon_data == NULL) return; + if (ServerOnly(doomcom->remotenode)) + return; + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); UINT8 *icondata = netbuffer->u.mapicondata; -- 2.54.0 From 77a00b08a5d628c9c373dcf4a7e79046f7000c2a Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 8 Sep 2025 19:29:01 +0200 Subject: [PATCH 09/13] optimize gl vhseffect slightly we dont need to remake our screen texture 3 times also avoid combining float with interger maths esp in the loop --- src/hardware/r_opengl/r_opengl.c | 55 +++++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 4dcd1253b..32aa784d1 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3348,7 +3348,6 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd) void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 downdistort, UINT8 barsize) { - int tex = HWD_SCREENTEXTURE_VHS; float xfix, yfix; float fix[8]; GLubyte color[4] = {255, 255, 255, 255}; @@ -3368,14 +3367,19 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 xfix = 1/((float)(screen_texsizew)/((float)((screen_width)))); yfix = 1/((float)(screen_texsizeh)/((float)((screen_height)))); - // Slight fuzziness - GL_MakeScreenTexture(tex); - GL_SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); - pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + const GLfloat scrwf = (float)screen_width; + const GLfloat scrwh = (float)screen_height; - for (i = 0; i < 1; i += 2.f/vid.height) + // Slight fuzziness + GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS); + GL_SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); + pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]); + + const float stride = 2.f/scrwh; + + for (i = 0; i < 1; i += stride) { - fix[2] = (float)(rand() % 128) / -22000 * xfix; + fix[2] = (float)(rand() % 128) / -22000.f * xfix; fix[0] = fix[2]; fix[6] = fix[0] + xfix; fix[4] = fix[2] + xfix; @@ -3393,8 +3397,8 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 } // Upward bar - GL_MakeScreenTexture(tex); - pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + //GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS); + //pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]); color[0] = color[1] = color[2] = 190; color[3] = 250; @@ -3402,14 +3406,14 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 fix[0] = 0.0f; fix[6] = xfix; - fix[2] = (float)updistort / screen_width * xfix; + fix[2] = (float)updistort / scrwf * xfix; fix[4] = fix[2] + fix[6]; - screenVerts[1] = screenVerts[10] = 2.0f*upbary/screen_height - 1.0f; - screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/screen_height; + screenVerts[1] = screenVerts[10] = 2.0f*upbary/scrwh - 1.0f; + screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrwh; - fix[1] = fix[7] = (float)upbary/screen_height * yfix; - fix[3] = fix[5] = fix[1] + (float)barsize/2/screen_height * yfix; + fix[1] = fix[7] = (float)upbary/scrwh * yfix; + fix[3] = fix[5] = fix[1] + (float)barsize/2/scrwh * yfix; pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -3422,19 +3426,19 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); // Downward bar - GL_MakeScreenTexture(tex); - pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); + //GL_MakeScreenTexture(HWD_SCREENTEXTURE_VHS); + //pglBindTexture(GL_TEXTURE_2D, screenTextures[HWD_SCREENTEXTURE_VHS]); fix[0] = 0.0f; fix[6] = xfix; - fix[2] = (float)downdistort / screen_width * -xfix; + fix[2] = (float)downdistort / scrwf * -xfix; fix[4] = fix[2] + fix[6]; - screenVerts[1] = screenVerts[10] = 2.0f*downbary/screen_height - 1.0f; - screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/screen_height; + screenVerts[1] = screenVerts[10] = 2.0f*downbary/scrwh - 1.0f; + screenVerts[4] = screenVerts[7] = screenVerts[1] + (float)barsize/scrwh; - fix[1] = fix[7] = (float)downbary/screen_height * yfix; - fix[3] = fix[5] = fix[1] + (float)barsize/2/screen_height * yfix; + fix[1] = fix[7] = (float)downbary/scrwh * yfix; + fix[3] = fix[5] = fix[1] + (float)barsize/2/scrwh * yfix; pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -3450,11 +3454,13 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 // Create a texture from the screen. void GL_MakeScreenTexture(int tex) { - boolean firstTime = (screenTextures[tex] == 0); + boolean firstTime; if (!gl_enable_screen_textures) return; + firstTime = (screenTextures[tex] == 0); + // Create screen texture if (firstTime) pglGenTextures(1, &screenTextures[tex]); @@ -3539,7 +3545,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh pglBindTexture(GL_TEXTURE_2D, screenTextures[tex]); if (useshader) - pglUseProgram(gl_shaders[SHADER_PALETTE_POSTPROCESS].program); // palette postprocess shader + pglUseProgram(gl_shaders[SHADER_PALETTE_POSTPROCESS].program); // Final postprocess step of palette rendering, after everything else has been drawn. pglColor4ubv(white); @@ -3557,6 +3563,7 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh void GL_SetPaletteLookup(UINT8 *lut) { GLenum internalFormat; + if (gl_version[0] == '1' || gl_version[0] == '2') { // if the OpenGL version is below 3.0, then the GL_R8 format may not be available. @@ -3584,6 +3591,7 @@ void GL_SetPaletteLookup(UINT8 *lut) UINT32 GL_CreateLightTable(RGBA_t *hw_lighttable) { LTListItem *item = malloc(sizeof(LTListItem)); + if (!LightTablesTail) { LightTablesHead = LightTablesTail = item; @@ -3593,6 +3601,7 @@ UINT32 GL_CreateLightTable(RGBA_t *hw_lighttable) LightTablesTail->next = item; LightTablesTail = item; } + item->next = NULL; pglGenTextures(1, &item->id); pglBindTexture(GL_TEXTURE_2D, item->id); -- 2.54.0 From ff5bb34204ab5e5ed0d3209212462a153f9d8752 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 8 Sep 2025 19:33:46 +0200 Subject: [PATCH 10/13] parentheses hell --- src/hardware/r_opengl/r_opengl.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 32aa784d1..3a903a9af 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -3142,8 +3142,8 @@ void GL_PostImgRedraw(float points[SCREENVERTS][SCREENVERTS][2]) return; // X/Y stretch fix for all resolutions(!) - xfix = (float)(screen_texsizew)/((float)((screen_width)/(float)(SCREENVERTS-1))); - yfix = (float)(screen_texsizeh)/((float)((screen_height)/(float)(SCREENVERTS-1))); + xfix = (float)screen_texsizew/((float)(screen_width/(float)(SCREENVERTS-1))); + yfix = (float)screen_texsizeh/((float)(screen_height/(float)(SCREENVERTS-1))); pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); @@ -3230,12 +3230,9 @@ void GL_DrawScreenTexture(int tex, FSurfaceInfo *surf, FBITFIELD polyflags) if (gl_enable_screen_textures != 2) return; - xfix = 1/((float)(screen_texsizew)/((float)((screen_width)))); - yfix = 1/((float)(screen_texsizeh)/((float)((screen_height)))); + xfix = 1/((float)screen_texsizew/(float)screen_width); + yfix = 1/((float)screen_texsizeh/(float)screen_height); - // const float screenVerts[12] - - // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3289,12 +3286,9 @@ void GL_DoScreenWipe(int wipeStart, int wipeEnd) if (!gl_enable_screen_textures) return; - xfix = 1/((float)(screen_texsizew)/((float)((screen_width)))); - yfix = 1/((float)(screen_texsizeh)/((float)((screen_height)))); + xfix = 1/((float)screen_texsizew/(float)screen_width); + yfix = 1/((float)screen_texsizeh/(float)screen_height); - // const float screenVerts[12] - - // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3364,8 +3358,8 @@ void GL_RenderVhsEffect(fixed_t upbary, fixed_t downbary, UINT8 updistort, UINT8 if (gl_enable_screen_textures != 2) return; - xfix = 1/((float)(screen_texsizew)/((float)((screen_width)))); - yfix = 1/((float)(screen_texsizeh)/((float)((screen_height)))); + xfix = 1/((float)screen_texsizew/(float)screen_width); + yfix = 1/((float)screen_texsizeh/(float)screen_height); const GLfloat scrwf = (float)screen_width; const GLfloat scrwh = (float)screen_height; @@ -3494,8 +3488,8 @@ void GL_DrawScreenFinalTexture(int tex, INT32 width, INT32 height, boolean usesh if (gl_enable_screen_textures != 2) return; - xfix = 1/((float)(screen_texsizew)/((float)((screen_width)))); - yfix = 1/((float)(screen_texsizeh)/((float)((screen_height)))); + xfix = 1/((float)screen_texsizew/(float)screen_width); + yfix = 1/((float)screen_texsizeh/(float)screen_height); origaspect = (float)screen_width / screen_height; newaspect = (float)width / height; -- 2.54.0 From 29db810c54ebdfe8cfd04614a04e180ffb9d9498 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 9 Sep 2025 18:16:52 +0200 Subject: [PATCH 11/13] delet remaining "highcolor" stuff --- src/android/i_video.c | 4 ---- src/dedicated/i_video.c | 4 +--- src/i_video.h | 5 ----- src/r_data.c | 44 ----------------------------------------- src/r_data.h | 3 --- src/screen.c | 4 ++-- src/screen.h | 2 +- src/sdl/i_video.c | 2 -- 8 files changed, 4 insertions(+), 64 deletions(-) diff --git a/src/android/i_video.c b/src/android/i_video.c index 4db66afe0..bbe1cf3a3 100644 --- a/src/android/i_video.c +++ b/src/android/i_video.c @@ -10,12 +10,8 @@ rendermode_t rendermode = render_soft; -boolean highcolor = false; - boolean allow_fullscreen = false; - - consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; void I_StartupGraphics(void){} diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c index 8f8781e9e..e2a712995 100644 --- a/src/dedicated/i_video.c +++ b/src/dedicated/i_video.c @@ -29,8 +29,6 @@ rendermode_t rendermode = render_none; -boolean highcolor = false; - // synchronize page flipping with screen refresh consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -153,7 +151,7 @@ boolean I_UseNativeKeyboard(void) return false; } -void I_SetBorderlessWindow(void) +void I_SetBorderlessWindow(void) { } diff --git a/src/i_video.h b/src/i_video.h index 88d295ed9..d9bb9e1ce 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -40,11 +40,6 @@ typedef enum */ extern rendermode_t rendermode; - -/** \brief use highcolor modes if true -*/ -extern boolean highcolor; - /** \brief setup video mode */ void I_StartupGraphics(void); diff --git a/src/r_data.c b/src/r_data.c index 688b03972..0b4b153e4 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -121,10 +121,6 @@ UINT8 invertmap[256]; // for debugging/info purposes size_t flatmemory, spritememory, texturememory; // gotta play by 2.2 rules to get this to work -// highcolor stuff -INT16 color8to16[256]; // remap color index to highcolor rgb value -INT16 *hicolormaps; // test a 32k colormap remaps high -> high - // Blends two pixels together, using the equation // that matches the specified alpha style. UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) @@ -1661,40 +1657,6 @@ const char *R_ColormapNameForNum(INT32 num) } -// -// build a table for quick conversion from 8bpp to 15bpp -// - -// -// added "static inline" keywords, linking with the debug version -// of allegro, it have a makecol15 function of it's own, now -// with "static inline" keywords,it sloves this problem ;) -// -FUNCMATH static inline int makecol15(int r, int g, int b) -{ - return (((r >> 3) << 10) | ((g >> 3) << 5) | ((b >> 3))); -} - -static void R_Init8to16(void) -{ - UINT8 *palette; - int i; - - palette = W_CacheLumpName("PLAYPAL",PU_CACHE); - - for (i = 0; i < 256; i++) - { - // PLAYPAL uses 8 bit values - color8to16[i] = (INT16)makecol15(palette[0], palette[1], palette[2]); - palette += 3; - } - - // test a big colormap - hicolormaps = Z_Malloc(16384*sizeof(*hicolormaps), PU_STATIC, NULL); - for (i = 0; i < 16384; i++) - hicolormaps[i] = (INT16)(i<<1); -} - // // R_InitData // @@ -1703,12 +1665,6 @@ static void R_Init8to16(void) // void R_InitData(void) { - if (highcolor) - { - CONS_Printf("InitHighColor...\n"); - R_Init8to16(); - } - CONS_Printf("R_LoadTextures()...\n"); R_LoadTextures(); diff --git a/src/r_data.h b/src/r_data.h index 58afc34d0..2a74d591c 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -69,9 +69,6 @@ extern fixed_t *textureheight; // needed for texture pegging UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); -extern INT16 color8to16[256]; // remap color index to highcolor -extern INT16 *hicolormaps; // remap high colors to high colors.. - extern CV_PossibleValue_t Color_cons_t[]; // Load TEXTURE1/TEXTURE2/PNAMES definitions, create lookup tables diff --git a/src/screen.c b/src/screen.c index a8a3ca78b..4d239e186 100644 --- a/src/screen.c +++ b/src/screen.c @@ -8,7 +8,7 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file screen.c -/// \brief Handles multiple resolutions, 8bpp/16bpp(highcolor) modes +/// \brief Handles multiple resolutions #include "doomdef.h" #include "doomstat.h" @@ -37,7 +37,7 @@ // global video state // ------------------ viddef_t vid; -INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1) +INT32 setmodeneeded; // video mode change needed if > 0 (the mode number to set + 1) static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; diff --git a/src/screen.h b/src/screen.h index 38483b28d..42bc6c144 100644 --- a/src/screen.h +++ b/src/screen.h @@ -8,7 +8,7 @@ // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file screen.h -/// \brief Handles multiple resolutions, 8bpp/16bpp(highcolor) modes +/// \brief Handles multiple resolutions #ifndef __SCREEN_H__ #define __SCREEN_H__ diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 8e19b33ac..389e086e2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -113,8 +113,6 @@ unsigned msaa = 0; boolean a2c = false; #endif -boolean highcolor = false; - static void KeyboardLayout_OnChange(void) { HU_Shiftform(); -- 2.54.0 From c98861be6eead0a719ba2b1a7a0ee181047632a3 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 10 Sep 2025 13:07:15 +0200 Subject: [PATCH 12/13] fix tracker module playback going nuts when changing audio buffer size forgor CV_CALL :chaosleep: --- src/s_sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index aead25f0c..1bac40a46 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -62,7 +62,7 @@ consvar_t cv_samplerate = {"samplerate", "44100", 0, CV_Unsigned, NULL, 22050, N #endif static CV_PossibleValue_t audbuffersize_cons_t[] = {{128, "128"}, {256, "256"}, {512, "512"}, {1024, "1024"}, {2048, "2048"}, {4096, "4096"}, {0, NULL}}; -consvar_t cv_audbuffersize = {"audiobuffersize", "2048", CV_SAVE, audbuffersize_cons_t, BufferSize_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_audbuffersize = {"audiobuffersize", "2048", CV_SAVE|CV_CALL, audbuffersize_cons_t, BufferSize_OnChange, 0, NULL, NULL, 0, 0, NULL}; // stereo reverse consvar_t stereoreverse = {"stereoreverse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -- 2.54.0 From 677e381a2ca4f2681de6e3c11e242de50ab155e8 Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 15 Sep 2025 16:16:31 +0200 Subject: [PATCH 13/13] dont send server icon if current map is supposed to be hidden in line with kart not sending maptitle to ms in the same case --- src/d_clisrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 92fd72981..e581a8dfb 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1760,7 +1760,7 @@ static void SV_SendMapIcon(INT32 node) doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); const char *map = va("%sP", G_BuildMapName(gamemap)); - if (!W_LumpExists(map)) + if (!W_LumpExists(map) || (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU)) { // send an empty icon to tell the client there is no map icon netbuffer->packettype = PT_MAPICON; -- 2.54.0