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:
commit
e5386110d3
25 changed files with 7594 additions and 330 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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])
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
src/d_netfil.c
103
src/d_netfil.c
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
86
src/g_demo.c
86
src/g_demo.c
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
144
src/w_wad.c
144
src/w_wad.c
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
1
thirdparty/CMakeLists.txt
vendored
1
thirdparty/CMakeLists.txt
vendored
|
|
@ -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
8
thirdparty/xxhash/CMakeLists.txt
vendored
Normal 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
26
thirdparty/xxhash/LICENSE
vendored
Normal 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
42
thirdparty/xxhash/include/xxhash.c
vendored
Normal 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
7238
thirdparty/xxhash/include/xxhash.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue