Merge pull request 'Use xxhash for file hashing instead of md5' (#48) from xxhash into blankart-dev

Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/48
This commit is contained in:
NepDisk 2025-04-26 21:54:15 +00:00
commit e5386110d3
25 changed files with 7594 additions and 330 deletions

View file

@ -55,6 +55,35 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
2-Clause BSD License
applies to:
- xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
--------------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
0-Clause BSD License 0-Clause BSD License

View file

@ -91,6 +91,8 @@ target_link_libraries(SRB2SDL2 PRIVATE tcbrindle::span)
target_link_libraries(SRB2SDL2 PRIVATE fmt::fmt-header-only) target_link_libraries(SRB2SDL2 PRIVATE fmt::fmt-header-only)
target_link_libraries(SRB2SDL2 PRIVATE Tracy::TracyClient) target_link_libraries(SRB2SDL2 PRIVATE Tracy::TracyClient)
target_link_libraries(SRB2SDL2 PRIVATE xxHash::xxhash)
target_compile_definitions(SRB2SDL2 PRIVATE -DUSE_STUN) target_compile_definitions(SRB2SDL2 PRIVATE -DUSE_STUN)
if(SRB2_CONFIG_ENABLE_DISCORDRPC) if(SRB2_CONFIG_ENABLE_DISCORDRPC)
target_link_libraries(SRB2SDL2 PRIVATE DiscordRPC::DiscordRPC) target_link_libraries(SRB2SDL2 PRIVATE DiscordRPC::DiscordRPC)

View file

@ -36,6 +36,7 @@ extern "C" {
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; const UINT64 tv = ( UINT64)(b); memcpy(p, &tv, sizeof( UINT64)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
@ -46,6 +47,7 @@ extern "C" {
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; *p_tmp = ( UINT64)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; *p_tmp = (fixed_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEFIXED(p,b) do { fixed_t *p_tmp = (fixed_t *)p; *p_tmp = (fixed_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
#define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; *p_tmp = (angle_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) #define WRITEANGLE(p,b) do { angle_t *p_tmp = (angle_t *)p; *p_tmp = (angle_t)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0)
@ -59,6 +61,7 @@ extern "C" {
#define READUINT16(p) ({ const UINT16 *p_tmp = (const UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READUINT16(p) ({ const UINT16 *p_tmp = (const UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READINT32(p) ({ const INT32 *p_tmp = (const INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READINT32(p) ({ const INT32 *p_tmp = (const INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READUINT32(p) ({ const UINT32 *p_tmp = (const UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READUINT32(p) ({ const UINT32 *p_tmp = (const UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READUINT64(p) ({ const UINT64 *p_tmp = (const UINT64 *)p; UINT64 b; memcpy(&b, p, sizeof( UINT64)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READCHAR(p) ({ const char *p_tmp = (const char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READCHAR(p) ({ const char *p_tmp = (const char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READFIXED(p) ({ const fixed_t *p_tmp = (const fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READFIXED(p) ({ const fixed_t *p_tmp = (const fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
#define READANGLE(p) ({ const angle_t *p_tmp = (const angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; }) #define READANGLE(p) ({ const angle_t *p_tmp = (const angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(const void**)(&(p)) = (const void *)p_tmp; b; })
@ -69,6 +72,7 @@ extern "C" {
#define READUINT16(p) ((const UINT16*)(*(const void**)(&(p)) = (const void*)&((const UINT16*)(p))[1]))[-1] #define READUINT16(p) ((const UINT16*)(*(const void**)(&(p)) = (const void*)&((const UINT16*)(p))[1]))[-1]
#define READINT32(p) ((const INT32*)(*(const void**)(&(p)) = (const void*)&((const INT32*)(p))[1]))[-1] #define READINT32(p) ((const INT32*)(*(const void**)(&(p)) = (const void*)&((const INT32*)(p))[1]))[-1]
#define READUINT32(p) ((const UINT32*)(*(const void**)(&(p)) = (const void*)&((const UINT32*)(p))[1]))[-1] #define READUINT32(p) ((const UINT32*)(*(const void**)(&(p)) = (const void*)&((const UINT32*)(p))[1]))[-1]
#define READUINT64(p) ((const UINT64*)(*(const void**)(&(p)) = (const void*)&((const UINT64*)(p))[1]))[-1]
#define READCHAR(p) ((const char*)(*(const void**)(&(p)) = (const void*)&((const char*)(p))[1]))[-1] #define READCHAR(p) ((const char*)(*(const void**)(&(p)) = (const void*)&((const char*)(p))[1]))[-1]
#define READFIXED(p) ((const fixed_t*)(*(const void**)(&(p)) = (const void*)&((const fixed_t*)(p))[1]))[-1] #define READFIXED(p) ((const fixed_t*)(*(const void**)(&(p)) = (const void*)&((const fixed_t*)(p))[1]))[-1]
#define READANGLE(p) ((const angle_t*)(*(const void**)(&(p)) = (const void*)&((const angle_t*)(p))[1]))[-1] #define READANGLE(p) ((const angle_t*)(*(const void**)(&(p)) = (const void*)&((const angle_t*)(p))[1]))[-1]
@ -96,12 +100,26 @@ FUNCINLINE static ATTRINLINE void writelong(void *ptr, INT32 val)
cp[3] = val; cp[3] = val;
} }
FUNCINLINE static ATTRINLINE void writelonglong(void *ptr, INT64 val)
{
SINT8 *cp = ptr;
cp[0] = val; val >>= 8;
cp[1] = val; val >>= 8;
cp[2] = val; val >>= 8;
cp[3] = val; val >>= 8;
cp[4] = val; val >>= 8;
cp[5] = val; val >>= 8;
cp[6] = val; val >>= 8;
cp[7] = val;
}
#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; *p_tmp = ( UINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0) #define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; *p_tmp = ( SINT8)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; writeshort (p, ( INT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; writeshort (p, ( INT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; writeshort (p, ( UINT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; writeshort (p, ( UINT16)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; writelong (p, ( INT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; writelong (p, ( INT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; writelong (p, ( UINT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; writelong (p, ( UINT32)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEUINT64(p,b) do { UINT64 *p_tmp = ( UINT64 *)p; writelonglong(p,(UINT64)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b) ; p_tmp++; p = (void *)p_tmp;} while (0) #define WRITECHAR(p,b) do { char *p_tmp = ( char *)p; *p_tmp = ( char)(b) ; p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEFIXED(p,b) do {fixed_t *p_tmp = (fixed_t *)p; writelong (p, (fixed_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEFIXED(p,b) do {fixed_t *p_tmp = (fixed_t *)p; writelong (p, (fixed_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
#define WRITEANGLE(p,b) do {angle_t *p_tmp = (angle_t *)p; writelong (p, (angle_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0) #define WRITEANGLE(p,b) do {angle_t *p_tmp = (angle_t *)p; writelong (p, (angle_t)(b)); p_tmp++; p = (void *)p_tmp;} while (0)
@ -134,12 +152,19 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0]; return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0];
} }
FUNCINLINE static ATTRINLINE UINT64 readulonglong(void *ptr)
{
UINT8 *ucp = ptr;
return (ucp[7] << 56) | (ucp[6] << 48) | (ucp[5] << 40) | (ucp[4] << 32) | (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0];
}
#define READUINT8(p) ((const UINT8*)(p = (const void*)&((const UINT8*)p)[1]))[-1] #define READUINT8(p) ((const UINT8*)(p = (const void*)&((const UINT8*)p)[1]))[-1]
#define READSINT8(p) ((const SINT8*)(p = (const void*)&((const SINT8*)p)[1]))[-1] #define READSINT8(p) ((const SINT8*)(p = (const void*)&((const SINT8*)p)[1]))[-1]
#define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1]) #define READINT16(p) readshort(&((const INT16*)(p = (const void*)&((const INT16*)p)[1]))[-1])
#define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1]) #define READUINT16(p) readushort(&((const UINT16*)(p = (const void*)&((const UINT16*)p)[1]))[-1])
#define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1]) #define READINT32(p) readlong(&((const INT32*)(p = (const void*)&((const INT32*)p)[1]))[-1])
#define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1])) #define READUINT32(p) readulong(&((const UINT32*)(p = (const void*)&((const UINT32*)p)[1]))
#define READUINT64(p) readulonglong(&((const UINT64*)(p = (const void*)&((const UINT64*)p)[1]))
#define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1] #define READCHAR(p) ((const char*)(p = (const void*)&((const char*)p)[1]))[-1]
#define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1]) #define READFIXED(p) readlong(&((const fixed_t*)(p = (const void*)&((const fixed_t*)p)[1]))[-1])
#define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1]) #define READANGLE(p) readulong(&((const angle_t*)(p = (const void*)&((const angle_t*)p)[1]))[-1])

View file

@ -846,7 +846,7 @@ static void COM_Exec_f(void)
// Now try by searching the file path // Now try by searching the file path
// filename is modified with the full found path // filename is modified with the full found path
strcpy(filename, COM_Argv(1)); strcpy(filename, COM_Argv(1));
if (findfile(filename, NULL, true) != FS_NOTFOUND) if (findfile(filename, 0, true) != FS_NOTFOUND)
FIL_ReadFile(filename, &buf); FIL_ReadFile(filename, &buf);
if (!buf) if (!buf)

View file

@ -951,7 +951,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string, CopyCaretColors(netbuffer->u.serverinfo.servername, cv_servername.string,
MAXSERVERNAME); MAXSERVERNAME);
M_Memcpy(netbuffer->u.serverinfo.mapmd5, mapmd5, 16); netbuffer->u.serverinfo.maphash = maphash;
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) && !(mapheaderinfo[prevmap]->zonttl[0])) if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) && !(mapheaderinfo[prevmap]->zonttl[0]))
netbuffer->u.serverinfo.iszone = 1; netbuffer->u.serverinfo.iszone = 1;
@ -1637,7 +1637,7 @@ static boolean CL_FinishedFileList(void)
totalfilesrequestedsize = 0; totalfilesrequestedsize = 0;
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{ {
totalfilesrequestednum++; totalfilesrequestednum++;
totalfilesrequestedsize += fileneeded[i].totalsize; totalfilesrequestedsize += fileneeded[i].totalsize;
@ -1802,7 +1802,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
if (http_source[0]) if (http_source[0])
{ {
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{ {
curl_transfers++; curl_transfers++;
} }
@ -1814,7 +1814,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
case CL_DOWNLOADHTTPFILES: case CL_DOWNLOADHTTPFILES:
waitmore = false; waitmore = false;
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH)
{ {
if (!curl_running) if (!curl_running)
CURLPrepareFile(http_source, i); CURLPrepareFile(http_source, i);

View file

@ -284,7 +284,7 @@ struct serverinfo_pak
tic_t leveltime; tic_t leveltime;
char servername[MAXSERVERNAME]; char servername[MAXSERVERNAME];
char maptitle[33]; char maptitle[33];
unsigned char mapmd5[16]; UINT64 maphash;
UINT8 actnum; UINT8 actnum;
UINT8 iszone; UINT8 iszone;
char httpsource[MAX_MIRROR_LENGTH]; // HTTP URL to download from, always defined for compatibility char httpsource[MAX_MIRROR_LENGTH]; // HTTP URL to download from, always defined for compatibility

View file

@ -81,14 +81,14 @@
#include <tracy/tracy/Tracy.hpp> #include <tracy/tracy/Tracy.hpp>
// Put hashes here to get them out of header hell. // Put hashes here to get them out of header hell.
#define ASSET_HASH_MAIN_PK3 "6e6de1491bdd5410adedbe6e446a8990" #define ASSET_HASH_MAIN_PK3 0x52f03a1c98030bb0
#define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7" #define ASSET_HASH_SRB2_SRB 0xf3ec1ea4d0eca4a9
#define ASSET_HASH_GFX_KART "06f86ee16136eb8a7043b15001797034" #define ASSET_HASH_GFX_KART 0xc91b0d43f5ba131f
#define ASSET_HASH_TEXTURES_KART "abb53d56aba47c3a8cb0f764da1c8b80" #define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
#define ASSET_HASH_CHARS_KART "e2c428347dde52858a3dacd29fc5b964" #define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
#define ASSET_HASH_MAPS_KART "d051e55141ba736582228c456953cd98" #define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
#ifdef USE_PATCH_FILE #ifdef USE_PATCH_FILE
#define ASSET_HASH_PATCH_PK3 "00000000000000000000000000000000" #define ASSET_HASH_PATCH_PK3 0x0000000000000000
#endif #endif
#ifdef CMAKECONFIG #ifdef CMAKECONFIG
@ -1193,7 +1193,7 @@ static void IdentifyVersion(void)
snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir); snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir);
configfile[sizeof configfile - 1] = '\0'; configfile[sizeof configfile - 1] = '\0';
// if you change the ordering of this or add/remove a file, be sure to update the md5 // if you change the ordering of this or add/remove a file, be sure to update the hash
// checking in D_SRB2Main // checking in D_SRB2Main
D_AddFile(startupiwads, va(pandf,srb2waddir,GRAPHICSNAME)); D_AddFile(startupiwads, va(pandf,srb2waddir,GRAPHICSNAME));
@ -1483,16 +1483,16 @@ void D_SRB2Main(void)
D_CleanFile(startupiwads); D_CleanFile(startupiwads);
#ifndef DEVELOP #ifndef DEVELOP
// Check MD5s of autoloaded files // Check hashes of autoloaded files
// Note: Do not add any files that ignore MD5! // Note: Do not add any files that ignore hashing!
W_VerifyFileMD5(MAINWAD_SRB2, ASSET_HASH_SRB2_SRB); W_VerifyFileHash(MAINWAD_SRB2, ASSET_HASH_SRB2_SRB);
W_VerifyFileMD5(MAINWAD_GFX, ASSET_HASH_GFX_KART); W_VerifyFileHash(MAINWAD_GFX, ASSET_HASH_GFX_KART);
W_VerifyFileMD5(MAINWAD_TEXTURES, ASSET_HASH_TEXTURES_KART); W_VerifyFileHash(MAINWAD_TEXTURES, ASSET_HASH_TEXTURES_KART);
W_VerifyFileMD5(MAINWAD_CHARS, ASSET_HASH_CHARS_KART); W_VerifyFileHash(MAINWAD_CHARS, ASSET_HASH_CHARS_KART);
W_VerifyFileMD5(MAINWAD_MAPS, ASSET_HASH_MAPS_KART); W_VerifyFileHash(MAINWAD_MAPS, ASSET_HASH_MAPS_KART);
W_VerifyFileMD5(MAINWAD_MAIN, ASSET_HASH_MAIN_PK3); W_VerifyFileHash(MAINWAD_MAIN, ASSET_HASH_MAIN_PK3);
#ifdef USE_PATCH_FILE #ifdef USE_PATCH_FILE
W_VerifyFileMD5(MAINWAD_PATCH, ASSET_HASH_PATCH_PK3); W_VerifyFileHash(MAINWAD_PATCH, ASSET_HASH_PATCH_PK3);
#endif #endif
#endif //ifndef DEVELOP #endif //ifndef DEVELOP

View file

@ -50,7 +50,6 @@
#include "lua_hook.h" #include "lua_hook.h"
#include "m_cond.h" #include "m_cond.h"
#include "m_anigif.h" #include "m_anigif.h"
#include "md5.h"
// SRB2kart // SRB2kart
#include "k_kart.h" #include "k_kart.h"
@ -201,7 +200,7 @@ static void Command_Displayplayer_f(void);
static void Command_ExitLevel_f(void); static void Command_ExitLevel_f(void);
static void Command_Showmap_f(void); static void Command_Showmap_f(void);
static void Command_Mapmd5_f(void); static void Command_Maphash_f(void);
static void Command_Teamchange_f(void); static void Command_Teamchange_f(void);
static void Command_Teamchange2_f(void); static void Command_Teamchange2_f(void);
@ -788,7 +787,7 @@ void D_RegisterServerCommands(void)
COM_AddCommand("retry", Command_Retry_f); COM_AddCommand("retry", Command_Retry_f);
COM_AddCommand("exitlevel", Command_ExitLevel_f); COM_AddCommand("exitlevel", Command_ExitLevel_f);
COM_AddCommand("showmap", Command_Showmap_f); COM_AddCommand("showmap", Command_Showmap_f);
COM_AddCommand("mapmd5", Command_Mapmd5_f); COM_AddCommand("maphash", Command_Maphash_f);
COM_AddCommand("addfile", Command_Addfile); COM_AddCommand("addfile", Command_Addfile);
COM_AddCommand("listwad", Command_ListWADS_f); COM_AddCommand("listwad", Command_ListWADS_f);
@ -4487,10 +4486,10 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
READSTRINGN(*cp, filename, 255); READSTRINGN(*cp, filename, 255);
// Maybe add md5 support? // Maybe add hashing support?
if (strstr(filename, ".soc") != NULL) if (strstr(filename, ".soc") != NULL)
{ {
ncs = findfile(filename,NULL,true); ncs = findfile(filename, 0, true);
if (ncs != FS_FOUND) if (ncs != FS_FOUND)
{ {
@ -4627,29 +4626,19 @@ static void Command_Addfile(void)
WRITESTRINGN(buf_p,p,240); WRITESTRINGN(buf_p,p,240);
// calculate and check md5 // calculate and check the hash
{ {
UINT8 md5sum[16]; UINT64 filehash;
#ifdef NOMD5 #ifdef NOFILEHASH
memset(md5sum,0,16); filehash = 0;
#else #else
FILE *fhandle;
boolean valid = true; boolean valid = true;
if (!W_MakeFileHash(fn, true, &filehash))
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) continue; // file not found
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
md5_stream(fhandle, md5sum);
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else // file not found
continue;
for (i = 0; i < numwadfiles; i++) for (i = 0; i < numwadfiles; i++)
{ {
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) if (wadfiles[i]->hash == filehash)
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn);
valid = false; valid = false;
@ -4662,7 +4651,7 @@ static void Command_Addfile(void)
continue; continue;
} }
#endif #endif
WRITEMEM(buf_p, md5sum, 16); WRITEUINT64(buf_p, filehash);
} }
WRITEUINT8(buf_p, compat); WRITEUINT8(buf_p, compat);
@ -4680,13 +4669,13 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
filestatus_t ncs = FS_NOTCHECKED; filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16]; UINT64 filehash;
boolean kick = false; boolean kick = false;
boolean toomany = false; boolean toomany = false;
INT32 i,j; INT32 i,j;
READSTRINGN(*cp, filename, 240); READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16); filehash = READUINT64(cp);
wadcompat_t compat = READUINT8(*cp); wadcompat_t compat = READUINT8(*cp);
// Only the server processes this message. // Only the server processes this message.
@ -4709,7 +4698,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
toomany = true; toomany = true;
else else
ncs = findfile(filename,md5sum,true); ncs = findfile(filename, filehash, true);
if (ncs != FS_FOUND || toomany) if (ncs != FS_FOUND || toomany)
{ {
@ -4719,7 +4708,7 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename); sprintf(message, M_GetText("Too many files loaded to add %s\n"), filename);
else if (ncs == FS_NOTFOUND) else if (ncs == FS_NOTFOUND)
sprintf(message, M_GetText("The server doesn't have %s\n"), filename); sprintf(message, M_GetText("The server doesn't have %s\n"), filename);
else if (ncs == FS_MD5SUMBAD) else if (ncs == FS_BADHASH)
sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename); sprintf(message, M_GetText("Checksum mismatch on %s\n"), filename);
else else
sprintf(message, M_GetText("Unknown error finding wad file (%s)\n"), filename); sprintf(message, M_GetText("Unknown error finding wad file (%s)\n"), filename);
@ -4740,10 +4729,10 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
{ {
char filename[241]; char filename[241];
filestatus_t ncs = FS_NOTCHECKED; filestatus_t ncs = FS_NOTCHECKED;
UINT8 md5sum[16]; UINT64 filehash;
READSTRINGN(*cp, filename, 240); READSTRINGN(*cp, filename, 240);
READMEM(*cp, md5sum, 16); filehash = READUINT64(*cp);
wadcompat_t compat = READUINT8(*cp); wadcompat_t compat = READUINT8(*cp);
if (playernum != serverplayer) if (playernum != serverplayer)
@ -4754,7 +4743,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
return; return;
} }
ncs = findfile(filename,md5sum,true); ncs = findfile(filename, filehash, true);
if (ncs != FS_FOUND || !P_AddWadFile(filename, compat)) if (ncs != FS_FOUND || !P_AddWadFile(filename, compat))
{ {
@ -4769,7 +4758,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), filename); CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), filename);
M_StartMessage(va("The server added a file \n(%s)\nthat you do not have.\n\nPress ESC\n",filename), NULL, MM_NOTHING); M_StartMessage(va("The server added a file \n(%s)\nthat you do not have.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
} }
else if (ncs == FS_MD5SUMBAD) else if (ncs == FS_BADHASH)
{ {
CONS_Printf(M_GetText("Checksum mismatch while loading %s.\nMake sure you have the copy of\nthis file that the server has.\n"), filename); CONS_Printf(M_GetText("Checksum mismatch while loading %s.\nMake sure you have the copy of\nthis file that the server has.\n"), filename);
M_StartMessage(va("Checksum mismatch while loading \n%s.\nThe server seems to have a\ndifferent version of this file.\n\nPress ESC\n",filename), NULL, MM_NOTHING); M_StartMessage(va("Checksum mismatch while loading \n%s.\nThe server seems to have a\ndifferent version of this file.\n\nPress ESC\n",filename), NULL, MM_NOTHING);
@ -5434,16 +5423,10 @@ static void Command_Showmap_f(void)
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
} }
static void Command_Mapmd5_f(void) static void Command_Maphash_f(void)
{ {
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
{ CONS_Printf("%s: " HASHFMT "\n", G_BuildMapName(gamemap), maphash);
INT32 i;
char md5tmp[33];
for (i = 0; i < 16; ++i)
sprintf(&md5tmp[i*2], "%02x", mapmd5[i]);
CONS_Printf("%s: %s\n", G_BuildMapName(gamemap), md5tmp);
}
else else
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
} }

View file

@ -51,7 +51,6 @@
#include "p_setup.h" #include "p_setup.h"
#include "m_misc.h" #include "m_misc.h"
#include "m_menu.h" #include "m_menu.h"
#include "md5.h"
#include "filesrch.h" #include "filesrch.h"
#include <errno.h> #include <errno.h>
@ -104,7 +103,7 @@ static tic_t lasttimeackpacketsent = 0;
typedef struct typedef struct
{ {
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT64 hash;
boolean *receivedfragments; boolean *receivedfragments;
UINT32 fragmentsize; UINT32 fragmentsize;
UINT32 currentsize; UINT32 currentsize;
@ -207,7 +206,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
count++; count++;
WRITEUINT32(p, wadfiles[i]->filesize); WRITEUINT32(p, wadfiles[i]->filesize);
WRITESTRINGN(p, wadfilename, MAX_WADPATH); WRITESTRINGN(p, wadfilename, MAX_WADPATH);
WRITEMEM(p, wadfiles[i]->md5sum, 16); WRITEUINT64(p, wadfiles[i]->hash);
WRITEUINT8(p, wadfiles[i]->compatmode); WRITEUINT8(p, wadfiles[i]->compatmode);
} }
if (netbuffer->packettype == PT_MOREFILESNEEDED) if (netbuffer->packettype == PT_MOREFILESNEEDED)
@ -241,7 +240,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
fileneeded[i].file = NULL; // The file isn't open yet fileneeded[i].file = NULL; // The file isn't open yet
READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum fileneeded[i].hash = READUINT64(p); // The last 8 bytes are the file checksum
fileneeded[i].compatmode = READUINT8(p); fileneeded[i].compatmode = READUINT8(p);
} }
} }
@ -255,7 +254,7 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
fileneeded[0].justdownloaded = false; fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX; fileneeded[0].totalsize = UINT32_MAX;
fileneeded[0].file = NULL; fileneeded[0].file = NULL;
memset(fileneeded[0].md5sum, 0, 16); fileneeded[0].hash = 0;
strcpy(fileneeded[0].filename, tmpsave); strcpy(fileneeded[0].filename, tmpsave);
} }
@ -295,19 +294,12 @@ boolean CL_CheckDownloadable(void)
{ {
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10); CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
if (fileneeded[i].status == FS_MD5SUMBAD) if (fileneeded[i].status == FS_BADHASH)
CONS_Printf(M_GetText(" wrong version, md5: ")); CONS_Printf(M_GetText(" wrong version, hash: "));
else else
CONS_Printf(M_GetText(" not found, md5: ")); CONS_Printf(M_GetText(" not found, hash: "));
{ CONS_Printf(HASHFMT "\n", fileneeded[i].hash);
INT32 j;
char md5tmp[33];
for (j = 0; j < 16; j++)
sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
CONS_Printf("%s", md5tmp);
}
CONS_Printf("\n");
} }
switch (dlstatus) switch (dlstatus)
@ -335,7 +327,7 @@ static boolean CL_CanResumeDownload(fileneeded_t *file)
{ {
return pauseddownload return pauseddownload
&& !strcmp(pauseddownload->filename, file->filename) // Same name && !strcmp(pauseddownload->filename, file->filename) // Same name
&& !memcmp(pauseddownload->md5sum, file->md5sum, 16) // Same checksum && pauseddownload->hash == file->hash // Same checksum
&& pauseddownload->fragmentsize == file->fragmentsize; // Same fragment size && pauseddownload->fragmentsize == file->fragmentsize; // Same fragment size
} }
@ -388,7 +380,7 @@ boolean CL_SendFileRequest(void)
return false; return false;
} }
#endif #endif
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK))
{ {
// Error check for the first time around. // Error check for the first time around.
totalfreespaceneeded += fileneeded[i].totalsize; totalfreespaceneeded += fileneeded[i].totalsize;
@ -419,7 +411,7 @@ tryagain:
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
{ {
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)) if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK))
{ {
// Pre-prepare. // Pre-prepare.
size_t checklen; size_t checklen;
@ -457,7 +449,7 @@ tryagain:
CONS_Printf("Direct download - missing files are as follows:\n"); CONS_Printf("Direct download - missing files are as follows:\n");
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
{ {
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK || fileneeded[i].status == FS_REQUESTED)) // FS_REQUESTED added if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK || fileneeded[i].status == FS_REQUESTED)) // FS_REQUESTED added
CONS_Printf(" %s\n", fileneeded[i].filename); CONS_Printf(" %s\n", fileneeded[i].filename);
} }
return false; return false;
@ -571,8 +563,8 @@ INT32 CL_CheckFiles(void)
if (i >= fileneedednum || j >= numwadfiles) if (i >= fileneedednum || j >= numwadfiles)
return 2; return 2;
// For the sake of speed, only bother with a md5 check // For the sake of speed, only bother with a hash check
if (memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16)) if (wadfiles[j]->hash != fileneeded[i].hash)
return 2; return 2;
// compatmode has to match too! // compatmode has to match too!
@ -590,7 +582,7 @@ INT32 CL_CheckFiles(void)
for (i = 0; i < fileneedednum; i++) for (i = 0; i < fileneedednum; i++)
{ {
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK) if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_BADHASH || fileneeded[i].status == FS_FALLBACK)
downloadrequired = true; downloadrequired = true;
if (fileneeded[i].status != FS_OPEN) if (fileneeded[i].status != FS_OPEN)
@ -611,7 +603,7 @@ INT32 CL_CheckFiles(void)
{ {
nameonly(strcpy(wadfilename, wadfiles[j]->filename)); nameonly(strcpy(wadfilename, wadfiles[j]->filename));
if (!stricmp(wadfilename, fileneeded[i].filename) && if (!stricmp(wadfilename, fileneeded[i].filename) &&
!memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16)) wadfiles[j]->hash == fileneeded[i].hash)
{ {
CONS_Debug(DBG_NETPLAY, "already loaded\n"); CONS_Debug(DBG_NETPLAY, "already loaded\n");
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
@ -621,7 +613,7 @@ INT32 CL_CheckFiles(void)
packetsize += nameonlylength(fileneeded[i].filename) + 22; packetsize += nameonlylength(fileneeded[i].filename) + 22;
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true); fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].hash, true);
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status); CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
return 4; return 4;
} }
@ -655,7 +647,7 @@ boolean CL_LoadServerFiles(void)
fileneeded[i].status = FS_OPEN; fileneeded[i].status = FS_OPEN;
return false; return false;
} }
else if (fileneeded[i].status == FS_MD5SUMBAD) else if (fileneeded[i].status == FS_BADHASH)
I_Error("Wrong version of file %s", fileneeded[i].filename); I_Error("Wrong version of file %s", fileneeded[i].filename);
else else
{ {
@ -866,7 +858,7 @@ void CL_PrepareDownloadLuaFile(void)
fileneeded[0].justdownloaded = false; fileneeded[0].justdownloaded = false;
fileneeded[0].totalsize = UINT32_MAX; fileneeded[0].totalsize = UINT32_MAX;
fileneeded[0].file = NULL; fileneeded[0].file = NULL;
memset(fileneeded[0].md5sum, 0, 16); fileneeded[0].hash = 0;
strcpy(fileneeded[0].filename, luafiletransfers->realfilename); strcpy(fileneeded[0].filename, luafiletransfers->realfilename);
// Make sure all directories in the file path exist // Make sure all directories in the file path exist
@ -1551,8 +1543,8 @@ void PT_FileFragment(void)
case FS_OPEN: case FS_OPEN:
s = "FS_OPEN"; s = "FS_OPEN";
break; break;
case FS_MD5SUMBAD: case FS_BADHASH:
s = "FS_MD5SUMBAD"; s = "FS_BADHASH";
break; break;
default: default:
s = "unknown"; s = "unknown";
@ -1609,7 +1601,7 @@ void CloseNetFile(void)
I_Error("CloseNetFile: No more memory\n"); I_Error("CloseNetFile: No more memory\n");
strcpy(pauseddownload->filename, fileneeded[i].filename); strcpy(pauseddownload->filename, fileneeded[i].filename);
memcpy(pauseddownload->md5sum, fileneeded[i].md5sum, 16); pauseddownload->hash = fileneeded[i].hash;
pauseddownload->currentsize = fileneeded[i].currentsize; pauseddownload->currentsize = fileneeded[i].currentsize;
pauseddownload->receivedfragments = fileneeded[i].receivedfragments; pauseddownload->receivedfragments = fileneeded[i].receivedfragments;
pauseddownload->fragmentsize = fileneeded[i].fragmentsize; pauseddownload->fragmentsize = fileneeded[i].fragmentsize;
@ -1694,66 +1686,57 @@ size_t nameonlylength(const char *s)
#define O_BINARY 0 #define O_BINARY 0
#endif #endif
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum) filestatus_t checkfilehash(const char *filename, UINT64 wantedhash)
{ {
#if defined (NOMD5) #ifdef NOFILEHASH
(void)wantedmd5sum; (void)wantedhash;
(void)filename; (void)filename;
return FS_FOUND;
#else #else
FILE *fhandle; if (!wantedhash)
UINT8 md5sum[16];
if (!wantedmd5sum)
return FS_FOUND; return FS_FOUND;
fhandle = fopen(filename, "rb"); UINT64 filehash;
if (fhandle) if (W_MakeFileHash(filename, false, &filehash) && wantedhash == filehash)
{ return FS_FOUND;
md5_stream(fhandle,md5sum); else
fclose(fhandle); return FS_BADHASH;
if (!memcmp(wantedmd5sum, md5sum, 16))
return FS_FOUND;
return FS_MD5SUMBAD;
}
I_Error("Couldn't open %s for md5 check", filename);
#endif #endif
return FS_FOUND; // will never happen, but makes the compiler shut up
} }
// Rewritten by Monster Iestyn to be less stupid // Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned // Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore) // (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath) filestatus_t findfile(char *filename, UINT64 wantedhash, boolean completepath)
{ {
filestatus_t homecheck; // store result of last file search filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third) boolean badhash = false; // store whether hash was bad from either of the first two searches (if nothing was found in the third)
// first, check SRB2's "home" directory // first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); homecheck = filesearch(filename, srb2home, wantedhash, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :) if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND; return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
badmd5 = true; badhash = true;
// if not found at all, just move on without doing anything // if not found at all, just move on without doing anything
// next, check SRB2's "path" directory // next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); homecheck = filesearch(filename, srb2path, wantedhash, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :) if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND; return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 else if (homecheck == FS_BADHASH) // file has a bad hash; move on and look for a file with the right hash
badmd5 = true; badhash = true;
// if not found at all, just move on without doing anything // if not found at all, just move on without doing anything
// finally check "." directory // finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10); homecheck = filesearch(filename, ".", wantedhash, completepath, 10);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got return homecheck; // otherwise return the result we got
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found return (badhash ? FS_BADHASH : FS_NOTFOUND); // hash is bad or file not found
} }
#ifdef HAVE_CURL #ifdef HAVE_CURL
@ -1911,7 +1894,7 @@ void CURLGetFile(void)
{ {
fclose(curl_curfile->file); fclose(curl_curfile->file);
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD) if (checkfilehash(curl_curfile->filename, curl_curfile->hash) == FS_BADHASH)
{ {
CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename); CONS_Alert(CONS_ERROR, M_GetText("HTTP Download of %s finished but is corrupt or has been modified\n"), filename);
curl_curfile->status = FS_FALLBACK; curl_curfile->status = FS_FALLBACK;

View file

@ -37,7 +37,7 @@ typedef enum
FS_REQUESTED, FS_REQUESTED,
FS_DOWNLOADING, FS_DOWNLOADING,
FS_OPEN, // Is opened and used in w_wad FS_OPEN, // Is opened and used in w_wad
FS_MD5SUMBAD, FS_BADHASH,
FS_FALLBACK, // HTTP failed FS_FALLBACK, // HTTP failed
} filestatus_t; } filestatus_t;
@ -45,7 +45,7 @@ struct fileneeded_t
{ {
UINT8 willsend; // Is the server willing to send it? UINT8 willsend; // Is the server willing to send it?
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT64 hash;
filestatus_t status; // The value returned by recsearch filestatus_t status; // The value returned by recsearch
boolean justdownloaded; // To prevent late fragments from causing an I_Error boolean justdownloaded; // To prevent late fragments from causing an I_Error
boolean compatmode; boolean compatmode;
@ -155,9 +155,9 @@ void Command_Downloads_f(void);
boolean fileexist(char *filename, time_t ptime); boolean fileexist(char *filename, time_t ptime);
// Search a file in the wadpath, return FS_FOUND when found // Search a file in the wadpath, return FS_FOUND when found
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, filestatus_t findfile(char *filename, UINT64 wantedhash,
boolean completepath); boolean completepath);
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum); filestatus_t checkfilehash(const char *filename, UINT64 wantedhash);
void nameonly(char *s); void nameonly(char *s);
size_t nameonlylength(const char *s); size_t nameonlylength(const char *s);

View file

@ -121,7 +121,7 @@ extern char logfilename[1024];
/* A mod name to further distinguish versions. */ /* A mod name to further distinguish versions. */
#define SRB2APPLICATION "SRB2Kart" #define SRB2APPLICATION "SRB2Kart"
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable hash checking and stuff, all in one go. :3
#ifdef DEVELOP #ifdef DEVELOP
#define VERSIONSTRING "Development EXE" #define VERSIONSTRING "Development EXE"
#define VERSIONSTRING_RC "Development EXE" "\0" #define VERSIONSTRING_RC "Development EXE" "\0"
@ -431,6 +431,13 @@ UINT32 quickncasehash (const char *p, size_t n)
return x; return x;
} }
// Standard Hashing Functions (tm)
// see W_MakeFileHash for hashing files
#include "xxhash.h"
#define HASH64(p, n) ((UINT64)XXH3_64bits(p, n))
#define HASH32(p, n) ((UINT32)(XXH3_64bits(p, n) & UINT32_MAX))
#define HASHFMT "%jx"
#ifndef __cplusplus #ifndef __cplusplus
#ifndef min // Double-Check with WATTCP-32's cdefs.h #ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y)) #define min(x, y) (((x) < (y)) ? (x) : (y))

View file

@ -5,11 +5,11 @@
/// filesearch: /// filesearch:
/// ///
/// ATTENTION : make sure there is enouth space in filename to put a full path (255 or 512) /// ATTENTION : make sure there is enouth space in filename to put a full path (255 or 512)
/// if needmd5check == 0 there is no md5 check /// if wantedhash == 0 there is no hash check
/// if completepath then filename will be change with the full path and name /// if completepath then filename will be change with the full path and name
/// maxsearchdepth == 0 only search given directory, no subdirs /// maxsearchdepth == 0 only search given directory, no subdirs
/// return FS_NOTFOUND /// return FS_NOTFOUND
/// FS_MD5SUMBAD; /// FS_BADHASH;
/// FS_FOUND /// FS_FOUND
#include <stdio.h> #include <stdio.h>
@ -337,12 +337,12 @@ char *refreshdirname = NULL;
#if defined (_XBOX) && defined (_MSC_VER) #if defined (_XBOX) && defined (_MSC_VER)
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash,
boolean completepath, int maxsearchdepth) boolean completepath, int maxsearchdepth)
{ {
//NONE? //NONE?
startpath = filename = NULL; startpath = filename = NULL;
wantedmd5sum = NULL; wantedhash = 0;
maxsearchdepth = 0; maxsearchdepth = 0;
completepath = false; completepath = false;
return FS_NOTFOUND; return FS_NOTFOUND;
@ -369,7 +369,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
#else #else
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth) filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash, boolean completepath, int maxsearchdepth)
{ {
filestatus_t retval = FS_NOTFOUND; filestatus_t retval = FS_NOTFOUND;
DIR **dirhandle; DIR **dirhandle;
@ -446,7 +446,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
} }
else if (!strcasecmp(searchname, dent->d_name)) else if (!strcasecmp(searchname, dent->d_name))
{ {
switch (checkfilemd5(searchpath, wantedmd5sum)) switch (checkfilehash(searchpath, wantedhash))
{ {
case FS_FOUND: case FS_FOUND:
if (completepath) if (completepath)
@ -456,8 +456,8 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
retval = FS_FOUND; retval = FS_FOUND;
found = 1; found = 1;
break; break;
case FS_MD5SUMBAD: case FS_BADHASH:
retval = FS_MD5SUMBAD; retval = FS_BADHASH;
break; break;
default: // prevent some compiler warnings default: // prevent some compiler warnings
break; break;
@ -788,7 +788,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut)
if (strcmp(dent->d_name, filenamebuf[i])) if (strcmp(dent->d_name, filenamebuf[i]))
continue; continue;
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum)) if (cv_addons_md5.value && !checkfilehash(menupath, wadfiles[i]->hash))
continue; continue;
ext |= EXT_LOADED; ext |= EXT_LOADED;

View file

@ -20,7 +20,7 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
\param filename the file to look for \param filename the file to look for
\param startpath where to start look from \param startpath where to start look from
\param wantedmd5sum want to check with MD5 \param wantedhash want to check with a hash
\param completepath want to return the complete path of the file? \param completepath want to return the complete path of the file?
\param maxsearchdepth the max depth to search for the file \param maxsearchdepth the max depth to search for the file
@ -29,7 +29,7 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
*/ */
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, filestatus_t filesearch(char *filename, const char *startpath, UINT64 wantedhash,
boolean completepath, int maxsearchdepth); boolean completepath, int maxsearchdepth);
#define menudepth 20 #define menudepth 20

View file

@ -38,7 +38,6 @@
#include "y_inter.h" #include "y_inter.h"
#include "v_video.h" #include "v_video.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "md5.h" // demo checksums
#include "p_saveg.h" // savebuffer_t #include "p_saveg.h" // savebuffer_t
#include "g_party.h" #include "g_party.h"
@ -110,7 +109,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING // DEMO RECORDING
// //
#define DEMOVERSION 0x0007 #define DEMOVERSION 0x0008
#define DEMOHEADER "\xF0" "KartReplay" "\x0F" #define DEMOHEADER "\xF0" "KartReplay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too! #define DF_GHOST 0x01 // This demo contains ghost data too!
@ -2133,12 +2132,12 @@ void G_BeginRecording(void)
snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername); snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Record Attack" : connectedservername);
// demo checksum // demo checksum
demobuf.p += 16; demobuf.p += sizeof(UINT64);
// game data // game data
M_Memcpy(demobuf.p, "PLAY", 4); demobuf.p += 4; M_Memcpy(demobuf.p, "PLAY", 4); demobuf.p += 4;
WRITESTRINGN(demobuf.p, mapheaderinfo[gamemap-1]->lumpname, MAXMAPLUMPNAME); WRITESTRINGN(demobuf.p, mapheaderinfo[gamemap-1]->lumpname, MAXMAPLUMPNAME);
M_Memcpy(demobuf.p, mapmd5, 16); demobuf.p += 16; WRITEUINT64(demobuf.p, maphash);
WRITEUINT8(demobuf.p, demoflags); WRITEUINT8(demobuf.p, demoflags);
WRITEUINT8(demobuf.p, gametype & 0xFF); WRITEUINT8(demobuf.p, gametype & 0xFF);
@ -2154,8 +2153,8 @@ void G_BeginRecording(void)
{ {
nameonly(( filename = va("%s", wadfiles[i]->filename) )); nameonly(( filename = va("%s", wadfiles[i]->filename) ));
WRITESTRINGL(demobuf.p, filename, MAX_WADPATH); WRITESTRINGL(demobuf.p, filename, MAX_WADPATH);
WRITEMEM(demobuf.p, wadfiles[i]->md5sum, 16); WRITEUINT64(demobuf.p, wadfiles[i]->hash);
WRITEUINT8(demobuf.p, wadfiles[i]->compatmode); WRITEUINT8(demobuf.p, !!wadfiles[i]->compatmode);
totalfiles++; totalfiles++;
} }
@ -2327,7 +2326,7 @@ void G_BeginMetal(void)
WRITEUINT16(demobuf.p,DEMOVERSION); WRITEUINT16(demobuf.p,DEMOVERSION);
// demo checksum // demo checksum
demobuf.p += 16; demobuf.p += sizeof(UINT64);
M_Memcpy(demobuf.p, "METL", 4); demobuf.p += 4; M_Memcpy(demobuf.p, "METL", 4); demobuf.p += 4;
@ -2399,7 +2398,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
{ {
UINT8 totalfiles; UINT8 totalfiles;
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT64 filehash;
filestatus_t ncs; filestatus_t ncs;
boolean toomany = false; boolean toomany = false;
boolean alreadyloaded; boolean alreadyloaded;
@ -2416,7 +2415,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
strlcpy(filename, (char *)(*pp), sizeof filename); strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp)); SKIPSTRING((*pp));
} }
READMEM((*pp), md5sum, 16); filehash = READUINT64((*pp));
compatmode = READUINT8((*pp)); compatmode = READUINT8((*pp));
if (!toomany) if (!toomany)
@ -2425,7 +2424,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
for (j = 0; j < numwadfiles; ++j) for (j = 0; j < numwadfiles; ++j)
{ {
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) if (filehash == wadfiles[j]->hash)
{ {
alreadyloaded = true; alreadyloaded = true;
break; break;
@ -2438,7 +2437,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
toomany = true; toomany = true;
else else
ncs = findfile(filename, md5sum, false); ncs = findfile(filename, filehash, false);
if (toomany) if (toomany)
{ {
@ -2450,7 +2449,7 @@ static void G_LoadDemoExtraFiles(UINT8 **pp)
{ {
if (ncs == FS_NOTFOUND) if (ncs == FS_NOTFOUND)
CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename); CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename);
else if (ncs == FS_MD5SUMBAD) else if (ncs == FS_BADHASH)
CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename); CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename);
else else
CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename); CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename);
@ -2478,7 +2477,7 @@ static void G_SkipDemoExtraFiles(UINT8 **pp)
for (i = 0; i < totalfiles; ++i) for (i = 0; i < totalfiles; ++i)
{ {
SKIPSTRING((*pp));// file name SKIPSTRING((*pp));// file name
(*pp) += 16;// md5 (*pp) += sizeof(UINT64); // hash
(*pp) += 1; // compatmode (*pp) += 1; // compatmode
} }
} }
@ -2489,7 +2488,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
{ {
UINT8 totalfiles, filesloaded, nmusfilecount; UINT8 totalfiles, filesloaded, nmusfilecount;
char filename[MAX_WADPATH]; char filename[MAX_WADPATH];
UINT8 md5sum[16]; UINT64 filehash;
boolean toomany = false; boolean toomany = false;
boolean alreadyloaded; boolean alreadyloaded;
UINT8 i, j; UINT8 i, j;
@ -2506,7 +2505,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
strlcpy(filename, (char *)(*pp), sizeof filename); strlcpy(filename, (char *)(*pp), sizeof filename);
SKIPSTRING((*pp)); SKIPSTRING((*pp));
} }
READMEM((*pp), md5sum, 16); filehash = READUINT64((*pp));
(void)READUINT8((*pp)); // compatmode (void)READUINT8((*pp)); // compatmode
if (!toomany) if (!toomany)
@ -2521,7 +2520,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
else else
continue; continue;
if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) if (filehash == wadfiles[j]->hash)
{ {
alreadyloaded = true; alreadyloaded = true;
@ -2540,7 +2539,7 @@ static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick)
if (numwadfiles >= MAX_WADFILES) if (numwadfiles >= MAX_WADFILES)
error = DFILE_ERROR_CANNOTLOAD; error = DFILE_ERROR_CANNOTLOAD;
else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) else if (!quick && findfile(filename, filehash, false) != FS_FOUND)
error = DFILE_ERROR_CANNOTLOAD; error = DFILE_ERROR_CANNOTLOAD;
else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER)
error |= DFILE_ERROR_NOTLOADED; error |= DFILE_ERROR_NOTLOADED;
@ -2593,11 +2592,11 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
s = READUINT16(p); s = READUINT16(p);
I_Assert(s == DEMOVERSION); I_Assert(s == DEMOVERSION);
p += 64; // full demo title p += 64; // full demo title
p += 16; // demo checksum p += sizeof(UINT64); // demo checksum
I_Assert(!memcmp(p, "PLAY", 4)); I_Assert(!memcmp(p, "PLAY", 4));
p += 4; // PLAY p += 4; // PLAY
SKIPSTRING(p); // gamemap SKIPSTRING(p); // gamemap
p += 16; // map md5 p += sizeof(UINT64); // map hash
flags = READUINT8(p); // demoflags flags = READUINT8(p); // demoflags
p++; // gametype p++; // gametype
p++; // numlaps p++; // numlaps
@ -2647,7 +2646,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
return UINT8_MAX; return UINT8_MAX;
} }
p += 64; // full demo title p += 64; // full demo title
p += 16; // demo checksum p += sizeof(UINT64); // demo checksum
if (memcmp(p, "PLAY", 4)) if (memcmp(p, "PLAY", 4))
{ {
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
@ -2655,7 +2654,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
return UINT8_MAX; return UINT8_MAX;
} p += 4; // "PLAY" } p += 4; // "PLAY"
SKIPSTRING(p); // gamemap SKIPSTRING(p); // gamemap
p += 16; // mapmd5 p += sizeof(UINT64); // maphash
flags = READUINT8(p); flags = READUINT8(p);
p++; // gametype p++; // gametype
p++; // numlaps p++; // numlaps
@ -2750,7 +2749,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
if (version != VERSION || subversion != SUBVERSION) if (version != VERSION || subversion != SUBVERSION)
pdemo->type = MD_OUTDATED; pdemo->type = MD_OUTDATED;
info_p += 16; // demo checksum info_p += sizeof(UINT64); // demo checksum
if (memcmp(info_p, "PLAY", 4)) if (memcmp(info_p, "PLAY", 4))
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath);
@ -2762,7 +2761,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
info_p += 4; // "PLAY" info_p += 4; // "PLAY"
READSTRINGN(info_p, mapname, sizeof(mapname)); READSTRINGN(info_p, mapname, sizeof(mapname));
pdemo->map = G_MapNumber(mapname); pdemo->map = G_MapNumber(mapname);
info_p += 16; // mapmd5 info_p += sizeof(UINT64); // maphash
pdemoflags = READUINT8(info_p); pdemoflags = READUINT8(info_p);
@ -3033,7 +3032,7 @@ void G_DoPlayDemo(char *defdemoname)
M_Memcpy(demo.titlename, demobuf.p, 64); M_Memcpy(demo.titlename, demobuf.p, 64);
demobuf.p += 64; demobuf.p += 64;
demobuf.p += 16; // demo checksum demobuf.p += sizeof(UINT64); // demo checksum
if (memcmp(demobuf.p, "PLAY", 4)) if (memcmp(demobuf.p, "PLAY", 4))
{ {
@ -3050,7 +3049,7 @@ void G_DoPlayDemo(char *defdemoname)
demobuf.p += 4; // "PLAY" demobuf.p += 4; // "PLAY"
READSTRINGN(demobuf.p, mapname, sizeof(mapname)); // gamemap READSTRINGN(demobuf.p, mapname, sizeof(mapname)); // gamemap
gamemap = G_MapNumber(mapname)+1; gamemap = G_MapNumber(mapname)+1;
demobuf.p += 16; // mapmd5 demobuf.p += sizeof(UINT64); // maphash
demoflags = READUINT8(demobuf.p); demoflags = READUINT8(demobuf.p);
gametype = READUINT8(demobuf.p); gametype = READUINT8(demobuf.p);
@ -3388,7 +3387,8 @@ void G_AddGhost(char *defdemoname)
{ {
INT32 i; INT32 i;
lumpnum_t l; lumpnum_t l;
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
UINT64 demohash;
demoghost *gh; demoghost *gh;
UINT8 flags; UINT8 flags;
UINT8 *buffer,*p; UINT8 *buffer,*p;
@ -3457,12 +3457,12 @@ void G_AddGhost(char *defdemoname)
} }
p += 64; // title p += 64; // title
M_Memcpy(md5, p, 16); p += 16; // demo checksum demohash = READUINT64(p); // demo checksum
for (gh = ghosts; gh; gh = gh->next) for (gh = ghosts; gh; gh = gh->next)
if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum? if (demohash == gh->checksum) // another ghost in the game already has this checksum?
{ // Don't add another one, then! { // Don't add another one, then!
CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname); CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (hash was matched)\n", pdemoname);
Z_Free(pdemoname); Z_Free(pdemoname);
Z_Free(buffer); Z_Free(buffer);
return; return;
@ -3478,7 +3478,7 @@ void G_AddGhost(char *defdemoname)
SKIPSTRING(p); // gamemap SKIPSTRING(p); // gamemap
p += 16; // mapmd5 (possibly check for consistency?) p += sizeof(UINT64); // maphash (possibly check for consistency?)
flags = READUINT8(p); flags = READUINT8(p);
if (!(flags & DF_GHOST)) if (!(flags & DF_GHOST))
@ -3605,7 +3605,7 @@ void G_AddGhost(char *defdemoname)
gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL);
gh->next = ghosts; gh->next = ghosts;
gh->buffer = buffer; gh->buffer = buffer;
M_Memcpy(gh->checksum, md5, 16); gh->checksum = demohash;
gh->p = p; gh->p = p;
ghosts = gh; ghosts = gh;
@ -3707,7 +3707,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
} }
p += 64; // full demo title p += 64; // full demo title
p += 16; // demo checksum p += sizeof(UINT64); // demo checksum
if (memcmp(p, "PLAY", 4)) if (memcmp(p, "PLAY", 4))
{ {
@ -3716,7 +3716,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
p += 4; // "PLAY" p += 4; // "PLAY"
SKIPSTRING(p); // gamemap SKIPSTRING(p); // gamemap
p += 16; // mapmd5 (possibly check for consistency?) p += sizeof(UINT64); // maphash (possibly check for consistency?)
flags = READUINT8(p); flags = READUINT8(p);
if (!(flags & DF_GHOST)) if (!(flags & DF_GHOST))
@ -3843,7 +3843,7 @@ void G_DoPlayMetal(void)
Z_Free(metalbuffer); Z_Free(metalbuffer);
return; return;
} }
metal_p += 16; // demo checksum metal_p += sizeof(UINT64); // demo checksum
if (memcmp(metal_p, "METL", 4)) if (memcmp(metal_p, "METL", 4))
{ {
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n")); CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n"));
@ -3876,17 +3876,11 @@ void G_DoneLevelLoad(void)
=================== ===================
*/ */
// Writes the demo's checksum, or just random garbage if you can't do that for some reason. // Writes the demo's checksum.
static void WriteDemoChecksum(void) static void WriteDemoChecksum(void)
{ {
UINT8 *p = demobuf.buffer+16; // checksum position UINT8 *p = demobuf.buffer+16; // checksum position
#ifdef NOMD5 WRITEUINT64(p, HASH64(p+16, demobuf.p - (p+16)));
UINT8 i;
for (i = 0; i < 16; i++, p++)
*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
md5_buffer((char *)p+16, demobuf.p - (p+16), p); // make a checksum of everything after the checksum in the file.
#endif
} }
// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist // Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
@ -4113,13 +4107,9 @@ void G_SaveDemo(void)
WRITEUINT32(demoinfo_p, length); WRITEUINT32(demoinfo_p, length);
// Doesn't seem like I can use WriteDemoChecksum here, correct me if I'm wrong -Sal // Doesn't seem like I can use WriteDemoChecksum here, correct me if I'm wrong -Sal
#ifdef NOMD5
for (UINT8 i = 0; i < 16; i++, p++)
*p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
// Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable.
md5_buffer((char *)p+16, (demobuf.buffer + length) - (p+16), p); WRITEUINT64(p, HASH64(p+16, (demobuf.buffer + length) - (p+16)));
#endif
if (FIL_WriteFile(demoname, demobuf.buffer, demobuf.p - demobuf.buffer)) // finally output the file. if (FIL_WriteFile(demoname, demobuf.buffer, demobuf.p - demobuf.buffer)) // finally output the file.
demo.savemode = DSM_SAVED; demo.savemode = DSM_SAVED;

View file

@ -160,7 +160,7 @@ void G_LoadMetal(UINT8 **buffer);
// Your naming conventions are stupid and useless. // Your naming conventions are stupid and useless.
// There is no conflict here. // There is no conflict here.
struct demoghost { struct demoghost {
UINT8 checksum[16]; UINT64 checksum;
UINT8 *buffer, *p, color; UINT8 *buffer, *p, color;
UINT8 fadein; UINT8 fadein;
UINT16 version; UINT16 version;

View file

@ -68,8 +68,6 @@
#include "f_finale.h" // wipes #include "f_finale.h" // wipes
#include "md5.h" // map MD5
#include "deh_tables.h" #include "deh_tables.h"
// for MapLoad hook // for MapLoad hook
@ -116,10 +114,10 @@
#endif #endif
// //
// Map MD5, calculated on level load. // Map hash, calculated on level load.
// Sent to clients in PT_SERVERINFO. // Sent to clients in PT_SERVERINFO.
// //
unsigned char mapmd5[16]; UINT64 maphash;
// //
// MAP related Lookup tables. // MAP related Lookup tables.
@ -7634,49 +7632,15 @@ static void P_ConvertBinaryMap(void)
P_WriteTextmap(); P_WriteTextmap();
} }
/** Compute MD5 message digest for bytes read from memory source static void P_MakeMapHash(virtres_t *virt, UINT64 *dest)
*
* The resulting message digest number will be written into the 16 bytes
* beginning at RESBLOCK.
*
* \param filename path of file
* \param resblock resulting MD5 checksum
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found
*/
static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
{ {
#ifdef NOMD5
(void)buffer;
(void)len;
memset(resblock, 0x00, 16);
return 1;
#else
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5\n");
if (md5_buffer(buffer, len, resblock) == NULL)
return 1;
CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE);
return 0;
#endif
}
static void P_MakeMapMD5(virtres_t *virt, void *dest)
{
unsigned char resmd5[16];
if (udmf) if (udmf)
{ {
virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5); *dest = HASH64((char*)textmap->data, textmap->size);
} }
else else
{ {
unsigned char linemd5[16];
unsigned char sectormd5[16];
unsigned char thingmd5[16];
unsigned char sidedefmd5[16];
UINT8 i;
// Create a hash for the current map // Create a hash for the current map
// get the actual lumps! // get the actual lumps!
virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); virtlump_t* virtlines = vres_Find(virt, "LINEDEFS");
@ -7684,16 +7648,12 @@ static void P_MakeMapMD5(virtres_t *virt, void *dest)
virtlump_t* virtmthings = vres_Find(virt, "THINGS"); virtlump_t* virtmthings = vres_Find(virt, "THINGS");
virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS");
P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); *dest = 0;
P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); *dest += HASH64((char*)virtlines->data, virtlines->size);
P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); *dest += HASH64((char*)virtsectors->data, virtsectors->size);
P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); *dest += HASH64((char*)virtmthings->data, virtmthings->size);
*dest += HASH64((char*)virtsides->data, virtsides->size);
for (i = 0; i < 16; i++)
resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF;
} }
M_Memcpy(dest, &resmd5, 16);
} }
static boolean P_SetMapNamespace(void) static boolean P_SetMapNamespace(void)
@ -7801,7 +7761,7 @@ static boolean P_LoadMapFromFile(void)
if (sectors[i].tags.count) if (sectors[i].tags.count)
spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t)); spawnsectors[i].tags.tags = memcpy(Z_Malloc(sectors[i].tags.count*sizeof(mtag_t), PU_LEVEL, NULL), sectors[i].tags.tags, sectors[i].tags.count*sizeof(mtag_t));
P_MakeMapMD5(curmapvirt, &mapmd5); P_MakeMapHash(curmapvirt, &maphash);
TracyCZoneEnd(__zone); TracyCZoneEnd(__zone);
return true; return true;
} }

View file

@ -24,8 +24,8 @@
extern "C" { extern "C" {
#endif #endif
// map md5, sent to players via PT_SERVERINFO // map hash, sent to players via PT_SERVERINFO
extern unsigned char mapmd5[16]; extern UINT64 maphash;
// Player spawn spots for deathmatch. // Player spawn spots for deathmatch.
#define MAX_DM_STARTS 64 #define MAX_DM_STARTS 64

View file

@ -2382,7 +2382,7 @@ static const char *searchWad(const char *searchDir)
filestatus_t fstemp; filestatus_t fstemp;
strcpy(tempsw, WADKEYWORD); strcpy(tempsw, WADKEYWORD);
fstemp = filesearch(tempsw,searchDir,NULL,true,20); fstemp = filesearch(tempsw,searchDir,0,true,20);
if (fstemp == FS_FOUND) if (fstemp == FS_FOUND)
{ {
pathonly(tempsw); pathonly(tempsw);

View file

@ -62,7 +62,6 @@
#include "r_picformats.h" #include "r_picformats.h"
#include "i_time.h" #include "i_time.h"
#include "i_system.h" #include "i_system.h"
#include "md5.h"
#include "lua_script.h" #include "lua_script.h"
#include "g_game.h" // G_MapNumber #include "g_game.h" // G_MapNumber
@ -211,7 +210,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
// If findfile finds the file, the full path will be returned // If findfile finds the file, the full path will be returned
// in filenamebuf == *filename. // in filenamebuf == *filename.
if (findfile(filenamebuf, NULL, true)) if (findfile(filenamebuf, 0, true))
{ {
if ((handle = fopen_utf8(*filename, "rb")) == NULL) if ((handle = fopen_utf8(*filename, "rb")) == NULL)
{ {
@ -378,39 +377,52 @@ static inline boolean CheckCompatWad(UINT16 wadnum)
return false; return false;
} }
/** Compute MD5 message digest for bytes read from STREAM of this filname. // adapted from the example in xxhash.h
* static UINT64 hashfile(FILE *f)
* The resulting message digest number will be written into the 16 bytes {
* beginning at RESBLOCK. static XXH3_state_t *state;
char buffer[4096];
size_t count;
if (!state)
state = XXH3_createState();
XXH3_64bits_reset(state);
while ((count = fread(buffer, 1, sizeof(buffer), f)) != 0)
XXH3_64bits_update(state, buffer, count);
return XXH3_64bits_digest(state);
}
/** Computes and returns the hash for a file.
* *
* \param filename path of file * \param filename path of file
* \param resblock resulting MD5 checksum * \param openwad true if W_OpenWadFile should be used instead of fopen
* \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found * \param ret pointer to UINT64 to store hash
* \return true on success, false on error
*/ */
static inline INT32 W_MakeFileMD5(const char *filename, void *resblock) boolean W_MakeFileHash(const char *filename, boolean openwad, UINT64 *ret)
{ {
#ifdef NOMD5 #ifdef NOFILEHASH
(void)filename; (void)filename;
memset(resblock, 0x00, 16); (void)openwad;
*ret = 0;
return true;
#else #else
FILE *fhandle; FILE *fhandle = openwad ? W_OpenWadFile(&filename, true) : fopen(filename, "rb");
if ((fhandle = fopen(filename, "rb")) != NULL) if (fhandle == NULL)
{ {
tic_t t = I_GetTime(); CONS_Alert(CONS_WARNING, "Could not open %s for hashing\n", filename);
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",filename); return false;
if (md5_stream(fhandle, resblock) == 1)
{
fclose(fhandle);
return 1;
}
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f seconds\n",
filename, (float)(I_GetTime() - t)/NEWTICRATE);
fclose(fhandle);
return 0;
} }
CONS_Debug(DBG_SETUP, "Hashing file %s\n", filename);
*ret = hashfile(fhandle);
fclose(fhandle);
return true;
#endif #endif
return 1;
} }
// Invalidates the cache of lump numbers. Call this whenever a wad is added. // Invalidates the cache of lump numbers. Call this whenever a wad is added.
@ -863,10 +875,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
wadfile_t *wadfile; wadfile_t *wadfile;
restype_t type; restype_t type;
UINT16 numlumps = 0; UINT16 numlumps = 0;
#ifndef NOMD5 UINT64 filehash = 0;
size_t i;
#endif
UINT8 md5sum[16];
int important; int important;
if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
@ -907,17 +916,18 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
important = !important; important = !important;
#ifndef NOMD5 #ifndef NOFILEHASH
// //
// w-waiiiit! // w-waiiiit!
// Let's not add a wad file if the MD5 matches // Let's not add a wad file if the hash matches
// an MD5 of an already added WAD file! // the hash of an already added WAD file!
// //
W_MakeFileMD5(filename, md5sum); if (!W_MakeFileHash(filename, false, &filehash))
filehash = 0;
for (i = 0; i < numwadfiles; i++) for (size_t i = 0; i < numwadfiles; i++)
{ {
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) if (wadfiles[i]->hash == filehash)
{ {
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (handle) if (handle)
@ -972,7 +982,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadco
wadfile->type = type; wadfile->type = type;
// already generated, just copy it over // already generated, just copy it over
M_Memcpy(&wadfile->md5sum, &md5sum, 16); wadfile->hash = filehash;
// //
// set up caching // set up caching
@ -2143,74 +2153,32 @@ void *W_CachePatchLongName(const char *name, INT32 tag)
return W_CachePatchNum(num, tag); return W_CachePatchNum(num, tag);
} }
#ifndef NOMD5 /** Verifies a file's hash is as it should be.
* For releases, used as cheat prevention -- if the hash doesn't match, a
/** * fatal error is thrown. In debug mode, a hash mismatch only triggers a
* Prints an MD5 string into a human-readable textual format.
*
* \param md5 The md5 in binary form -- MD5_LEN (16) bytes.
* \param buf Where to print the textual form. Needs 2*MD5_LEN+1 (33) bytes.
* \author Graue <graue@oceanbase.org>
*/
#define MD5_FORMAT \
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
static void PrintMD5String(const UINT8 *md5, char *buf)
{
snprintf(buf, 2*MD5_LEN+1, MD5_FORMAT,
md5[0], md5[1], md5[2], md5[3],
md5[4], md5[5], md5[6], md5[7],
md5[8], md5[9], md5[10], md5[11],
md5[12], md5[13], md5[14], md5[15]);
}
#endif
/** Verifies a file's MD5 is as it should be.
* For releases, used as cheat prevention -- if the MD5 doesn't match, a
* fatal error is thrown. In debug mode, an MD5 mismatch only triggers a
* warning. * warning.
* *
* \param wadfilenum Number of the loaded wad file to check. * \param wadfilenum Number of the loaded wad file to check.
* \param matchmd5 The MD5 sum this wad should have, expressed as a * \param matchhash The hash value this wad should have.
* textual string.
* \author Graue <graue@oceanbase.org> * \author Graue <graue@oceanbase.org>
*/ */
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) void W_VerifyFileHash(UINT16 wadfilenum, UINT64 matchhash)
{ {
#ifdef NOMD5 #ifdef NOFILEHASH
(void)wadfilenum; (void)wadfilenum;
(void)matchmd5; (void)matchhash;
#else #else
UINT8 realmd5[MD5_LEN];
INT32 ix;
I_Assert(strlen(matchmd5) == 2*MD5_LEN);
I_Assert(wadfilenum < numwadfiles); I_Assert(wadfilenum < numwadfiles);
// Convert an md5 string like "7d355827fa8f981482246d6c95f9bd48"
// into a real md5.
for (ix = 0; ix < 2*MD5_LEN; ix++)
{
INT32 n, c = matchmd5[ix];
if (isdigit(c))
n = c - '0';
else
{
I_Assert(isxdigit(c));
if (isupper(c)) n = c - 'A' + 10;
else n = c - 'a' + 10;
}
if (ix & 1) realmd5[ix>>1] = (UINT8)(realmd5[ix>>1]+n);
else realmd5[ix>>1] = (UINT8)(n<<4);
}
if (memcmp(realmd5, wadfiles[wadfilenum]->md5sum, 16)) if (matchhash != wadfiles[wadfilenum]->hash)
{ {
char actualmd5text[2*MD5_LEN+1];
PrintMD5String(wadfiles[wadfilenum]->md5sum, actualmd5text);
#ifdef _DEBUG #ifdef _DEBUG
CONS_Printf CONS_Printf
#else #else
I_Error I_Error
#endif #endif
(M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); (M_GetText("File is old, is corrupt or has been modified: %s (found hash: " HASHFMT ", wanted: " HASHFMT ")\n"),
wadfiles[wadfilenum]->filename, wadfiles[wadfilenum]->hash, matchhash);
} }
#endif #endif
} }

View file

@ -126,7 +126,7 @@ struct wadfile_t
UINT16 numlumps; // this wad's number of resources UINT16 numlumps; // this wad's number of resources
FILE *handle; FILE *handle;
UINT32 filesize; // for network UINT32 filesize; // for network
UINT8 md5sum[16]; UINT64 hash;
boolean important; // also network - !W_VerifyNMUSlumps boolean important; // also network - !W_VerifyNMUSlumps
boolean compatmode; boolean compatmode;
@ -154,6 +154,8 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadcompat_t compat); UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup, wadcompat_t compat);
boolean W_MakeFileHash(const char *filename, boolean openwad, UINT64 *ret);
// W_InitMultipleFiles returns 1 if all is okay, 0 otherwise, // W_InitMultipleFiles returns 1 if all is okay, 0 otherwise,
// so that it stops with a message if a file was not found, but not if all is okay. // so that it stops with a message if a file was not found, but not if all is okay.
// W_InitMultipleFiles exits if a file was not found, but not if all is okay. // W_InitMultipleFiles exits if a file was not found, but not if all is okay.
@ -224,7 +226,7 @@ void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag);
void W_UnlockCachedPatch(void *patch); void W_UnlockCachedPatch(void *patch);
void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); void W_VerifyFileHash(UINT16 wadfilenum, UINT64 matchhash);
int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error); int W_VerifyNMUSlumps(const char *filename, boolean exit_on_error);

View file

@ -535,3 +535,4 @@ endif()
add_subdirectory(tracy) add_subdirectory(tracy)
add_subdirectory(tcbrindle_span) add_subdirectory(tcbrindle_span)
add_subdirectory(fmt) add_subdirectory(fmt)
add_subdirectory(xxhash)

8
thirdparty/xxhash/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,8 @@
# Update from https://github.com/Cyan4973/xxHash/releases/
# xxHash version 0.8.3
# License: BSD 2-clause
add_library(xxhash STATIC "${CMAKE_CURRENT_SOURCE_DIR}/include/xxhash.c")
target_compile_options(xxhash PRIVATE -O3) # do some optimization will ya
target_include_directories(xxhash PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
add_library(xxHash::xxhash ALIAS xxhash)

26
thirdparty/xxhash/LICENSE vendored Normal file
View file

@ -0,0 +1,26 @@
xxHash Library
Copyright (c) 2012-2021 Yann Collet
All rights reserved.
BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

42
thirdparty/xxhash/include/xxhash.c vendored Normal file
View file

@ -0,0 +1,42 @@
/*
* xxHash - Extremely Fast Hash algorithm
* Copyright (C) 2012-2023 Yann Collet
*
* BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You can contact the author at:
* - xxHash homepage: https://www.xxhash.com
* - xxHash source repository: https://github.com/Cyan4973/xxHash
*/
/*
* xxhash.c instantiates functions defined in xxhash.h
*/
#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
#define XXH_IMPLEMENTATION /* access definitions */
#include "xxhash.h"

7238
thirdparty/xxhash/include/xxhash.h vendored Normal file

File diff suppressed because it is too large Load diff