diff --git a/.gitignore b/.gitignore index 7f8d56035..5d859a219 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.plg *.suo *.vcproj.*.*.user +*.kate-swp Win32_LIB_ASM_Debug Win32_LIB_ASM_Release *.bsc diff --git a/src/Makefile b/src/Makefile index 752579fdb..3422a0cf7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -171,7 +171,7 @@ sources:= makedir:=../make # -DCOMPVERSION: flag to use comptime.h -opts:=-DCOMPVERSION -g +opts:=-DCOMPVERSION -g -fwrapv libs:= # This is a list of variables names, of which if defined, diff --git a/src/Makefile.d/versions.mk b/src/Makefile.d/versions.mk index d34070bb9..83600d735 100644 --- a/src/Makefile.d/versions.mk +++ b/src/Makefile.d/versions.mk @@ -150,7 +150,7 @@ endif ifdef NONX86 ifdef X86_64 # yeah that SEEMS contradictory - opts+=-march=nocona + opts+=-march=x86-64-v2 endif else ifndef GCC29 diff --git a/src/Sourcefile b/src/Sourcefile index a2e9ee736..fc2c1bedc 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -46,11 +46,11 @@ tables.c v_video.c w_wad.c y_inter.c -z_zone.c +z_zone.cpp r_bsp.c r_data.c r_draw.c -r_fps.c +r_fps.cpp r_main.cpp r_patch.c r_patchrotation.c @@ -67,7 +67,7 @@ p_floor.c p_inter.c p_lights.c p_map.c -p_maputl.c +p_maputl.cpp p_mobj.c p_polyobj.c p_saveg.c diff --git a/src/android/i_system.c b/src/android/i_system.c index 7f034c752..b20625587 100644 --- a/src/android/i_system.c +++ b/src/android/i_system.c @@ -89,7 +89,7 @@ precise_t I_GetPreciseTime(void) return 0; } -UINT64 I_GetPrecisePrecision(void) +UINT64 I_GetPrecisePrecision(void) { return 1000000; } @@ -98,16 +98,6 @@ void I_GetEvent(void){} void I_OsPolling(void){} -ticcmd_t *I_BaseTiccmd(void) -{ - return NULL; -} - -ticcmd_t *I_BaseTiccmd2(void) -{ - return NULL; -} - void I_Quit(void) { LOGD("SRB2Kart quitting!"); diff --git a/src/blua/luaconf.h b/src/blua/luaconf.h index 2e5424ae4..2596838bb 100644 --- a/src/blua/luaconf.h +++ b/src/blua/luaconf.h @@ -18,6 +18,14 @@ #define INT32 int32_t #endif +#ifndef __cplusplus +#ifndef min // Double-Check with WATTCP-32's cdefs.h +#define min(x, y) (((x) < (y)) ? (x) : (y)) +#endif +#ifndef max // Double-Check with WATTCP-32's cdefs.h +#define max(x, y) (((x) > (y)) ? (x) : (y)) +#endif +#endif /* ** ================================================================== @@ -534,8 +542,11 @@ #endif #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) #define LUAI_MAXNUMBER2STR 12 /* 10 digits, sign, and \0 */ -#define lua_str2number(s,p) strtol((s), (p), 10) - +#define lua_str2number(s,p) ({ \ + long nmr = strtol((s), (p), 10); \ + nmr = max(INT32_MIN, min((nmr), INT32_MAX)); \ + nmr; \ + }) /* @@ The luai_num* macros define the primitive operations over numbers. diff --git a/src/byteptr.h b/src/byteptr.h index 205884acc..058e81b25 100644 --- a/src/byteptr.h +++ b/src/byteptr.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2024 by Sonic Team Junior. +// Copyright (C) 1999-2025 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,72 +14,47 @@ #ifndef __BYTEPTR_H__ #define __BYTEPTR_H__ -#if defined (__alpha__) || defined (__arm__) || defined (__mips__) || defined (__ia64__) || defined (__clang__) -#define DEALIGNED -#endif - #include "endian.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef SRB2_BIG_ENDIAN // // Little-endian machines // -#ifdef DEALIGNED -#define WRITEUINT8(p,b) do { UINT8 *p_tmp = (void *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITESINT8(p,b) do { SINT8 *p_tmp = (void *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT16(p,b) do { INT16 *p_tmp = (void *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble -#define WRITEUINT16(p,b) do { UINT16 *p_tmp = (void *)p; const UINT16 tv = ( UINT16)(b); memcpy(p, &tv, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT32(p,b) do { INT32 *p_tmp = (void *)p; const INT32 tv = ( INT32)(b); memcpy(p, &tv, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEUINT32(p,b) do { UINT32 *p_tmp = (void *)p; const UINT32 tv = ( UINT32)(b); memcpy(p, &tv, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITECHAR(p,b) do { char *p_tmp = (void *)p; const char tv = ( char)(b); memcpy(p, &tv, sizeof( char)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEFIXED(p,b) do { fixed_t *p_tmp = (void *)p; const fixed_t tv = (fixed_t)(b); memcpy(p, &tv, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEANGLE(p,b) do { angle_t *p_tmp = (void *)p; const angle_t tv = (angle_t)(b); memcpy(p, &tv, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; } while (0) -#else -#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 WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT16_2(p,b) do { INT16 *p_tmp = ( INT16 *)p; *p_tmp = ( INT16)(b); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) // dumb hack for mumble -#define WRITEUINT16(p,b) do { UINT16 *p_tmp = ( UINT16 *)p; *p_tmp = ( UINT16)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEINT32(p,b) do { INT32 *p_tmp = ( INT32 *)p; *p_tmp = ( INT32)(b); p_tmp++; p = (void *)p_tmp; } while (0) -#define WRITEUINT32(p,b) do { UINT32 *p_tmp = ( UINT32 *)p; *p_tmp = ( UINT32)(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; *p_tmp = (fixed_t)(b); p_tmp++; 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++; p = (void *)p_tmp; } while (0) -#endif +#define WRITEUINT8(p,b) do { UINT8 *p_tmp = ( UINT8 *)p; const UINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) +#define WRITESINT8(p,b) do { SINT8 *p_tmp = ( SINT8 *)p; const SINT8 tv = ( UINT8)(b); memcpy(p, &tv, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; } while (0) +#define WRITEINT16(p,b) do { INT16 *p_tmp = ( INT16 *)p; const INT16 tv = ( INT16)(b); memcpy(p, &tv, sizeof( INT16)); 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 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 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 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) -#ifdef __GNUC__ -#ifdef DEALIGNED -#define READUINT8(p) ({ UINT8 *p_tmp = (void *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; p = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = (void *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; p = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = (void *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = (void *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; p = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = (void *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = (void *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; p = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = (void *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; p = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (void *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; p = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (void *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; p = (void *)p_tmp; b; }) +// what is this? +#if defined (__GNUC__) +#define READUINT8(p) ({ UINT8 *p_tmp = (UINT8 *)p; UINT8 b; memcpy(&b, p, sizeof( UINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READSINT8(p) ({ SINT8 *p_tmp = (SINT8 *)p; SINT8 b; memcpy(&b, p, sizeof( SINT8)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READINT16(p) ({ INT16 *p_tmp = (INT16 *)p; INT16 b; memcpy(&b, p, sizeof( INT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READUINT16(p) ({ UINT16 *p_tmp = (UINT16 *)p; UINT16 b; memcpy(&b, p, sizeof( UINT16)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READINT32(p) ({ INT32 *p_tmp = (INT32 *)p; INT32 b; memcpy(&b, p, sizeof( INT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READUINT32(p) ({ UINT32 *p_tmp = (UINT32 *)p; UINT32 b; memcpy(&b, p, sizeof( UINT32)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READCHAR(p) ({ char *p_tmp = (char *)p; char b; memcpy(&b, p, sizeof( char)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b; memcpy(&b, p, sizeof(fixed_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) +#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b; memcpy(&b, p, sizeof(angle_t)); p_tmp++; *(void**)(&(p)) = (void *)p_tmp; b; }) #else -#define READUINT8(p) ({ UINT8 *p_tmp = ( UINT8 *)p; UINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = ( SINT8 *)p; SINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = ( INT16 *)p; INT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = ( UINT16 *)p; UINT16 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = ( INT32 *)p; INT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = ( UINT32 *)p; UINT32 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = ( char *)p; char b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#endif -#else -#define READUINT8(p) *(( UINT8 *)p)++ -#define READSINT8(p) *(( SINT8 *)p)++ -#define READINT16(p) *(( INT16 *)p)++ -#define READUINT16(p) *(( UINT16 *)p)++ -#define READINT32(p) *(( INT32 *)p)++ -#define READUINT32(p) *(( UINT32 *)p)++ -#define READCHAR(p) *(( char *)p)++ -#define READFIXED(p) *((fixed_t *)p)++ -#define READANGLE(p) *((angle_t *)p)++ +#define READUINT8(p) ((UINT8*)(*(void**)(&(p)) = (void*)&((UINT8*)(p))[1]))[-1] +#define READSINT8(p) ((SINT8*)(*(void**)(&(p)) = (void*)&((SINT8*)(p))[1]))[-1] +#define READINT16(p) ((INT16*)(*(void**)(&(p)) = (void*)&((INT16*)(p))[1]))[-1] +#define READUINT16(p) ((UINT16*)(*(void**)(&(p)) = (void*)&((UINT16*)(p))[1]))[-1] +#define READINT32(p) ((INT32*)(*(void**)(&(p)) = (void*)&((INT32*)(p))[1]))[-1] +#define READUINT32(p) ((UINT32*)(*(void**)(&(p)) = (void*)&((UINT32*)(p))[1]))[-1] +#define READCHAR(p) ((char*)(*(void**)(&(p)) = (void*)&((char*)(p))[1]))[-1] +#define READFIXED(p) ((fixed_t*)(*(void**)(&(p)) = (void*)&((fixed_t*)(p))[1]))[-1] +#define READANGLE(p) ((angle_t*)(*(void**)(&(p)) = (void*)&((angle_t*)(p))[1]))[-1] #endif #else //SRB2_BIG_ENDIAN @@ -142,19 +117,17 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) return (ucp[3] << 24) | (ucp[2] << 16) | (ucp[1] << 8) | ucp[0]; } -#define READUINT8(p) ({ UINT8 *p_tmp = ( UINT8 *)p; UINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READSINT8(p) ({ SINT8 *p_tmp = ( SINT8 *)p; SINT8 b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READINT16(p) ({ INT16 *p_tmp = ( INT16 *)p; INT16 b = readshort(p); p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT16(p) ({ UINT16 *p_tmp = ( UINT16 *)p; UINT16 b = readushort(p); p_tmp++; p = (void *)p_tmp; b; }) -#define READINT32(p) ({ INT32 *p_tmp = ( INT32 *)p; INT32 b = readlong(p); p_tmp++; p = (void *)p_tmp; b; }) -#define READUINT32(p) ({ UINT32 *p_tmp = ( UINT32 *)p; UINT32 b = readulong(p); p_tmp++; p = (void *)p_tmp; b; }) -#define READCHAR(p) ({ char *p_tmp = ( char *)p; char b = *p_tmp; p_tmp++; p = (void *)p_tmp; b; }) -#define READFIXED(p) ({ fixed_t *p_tmp = (fixed_t *)p; fixed_t b = readlong(p); p_tmp++; p = (void *)p_tmp; b; }) -#define READANGLE(p) ({ angle_t *p_tmp = (angle_t *)p; angle_t b = readulong(p); p_tmp++; p = (void *)p_tmp; b; }) +#define READUINT8(p) ((UINT8*)(p = (void*)&((UINT8*)p)[1]))[-1] +#define READSINT8(p) ((SINT8*)(p = (void*)&((SINT8*)p)[1]))[-1] +#define READINT16(p) readshort(&((INT16*)(p = (void*)&((INT16*)p)[1]))[-1]) +#define READUINT16(p) readushort(&((UINT16*)(p = (void*)&((UINT16*)p)[1]))[-1]) +#define READINT32(p) readlong(&((INT32*)(p = (void*)&((INT32*)p)[1]))[-1]) +#define READUINT32(p) readulong(&((UINT32*)(p = (void*)&((UINT32*)p)[1])) +#define READCHAR(p) ((char*)(p = (void*)&((char*)p)[1]))[-1] +#define READFIXED(p) readlong(&((fixed_t*)(p = (void*)&((fixed_t*)p)[1]))[-1]) +#define READANGLE(p) readulong(&((angle_t*)(p = (void*)&((angle_t*)p)[1]))[-1]) #endif //SRB2_BIG_ENDIAN -#undef DEALIGNED - #define WRITESTRINGN(p, s, n) do { \ size_t tmp_i; \ \ @@ -231,4 +204,8 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr) p += n; \ } while (0) +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __BYTEPTR_H__ diff --git a/src/core/memory.cpp b/src/core/memory.cpp index e75cf91f7..9e591e78c 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -10,10 +10,14 @@ #include "memory.h" -#include #include +#include +#include "../cxxutil.hpp" #include "../z_zone.h" +#include "../lua_script.h" + +using namespace srb2; namespace { @@ -58,6 +62,90 @@ void LinearMemory::reset() noexcept } // namespace +PoolAllocator::~PoolAllocator() +{ + release(); +} + +constexpr static size_t nearest_multiple(size_t v, size_t divisor) +{ + return (v + (divisor - 1)) & ~(divisor - 1); +} + +PoolAllocator::ChunkFooter* PoolAllocator::allocate_chunk() +{ + uint8_t* chunk = (uint8_t*)Z_Malloc(nearest_multiple(blocks_ * block_size_, alignof(ChunkFooter)) + sizeof(ChunkFooter), tag_, nullptr); + ChunkFooter* footer = (ChunkFooter*)(chunk + (blocks_ * block_size_)); + footer->next = nullptr; + footer->start = (void*)chunk; + for (size_t i = 0; i < blocks_; i++) + { + FreeBlock* cur = (FreeBlock*)(chunk + (i * block_size_)); + FreeBlock* next = (FreeBlock*)(chunk + ((i + 1) * block_size_)); + cur->next = next; + } + ((FreeBlock*)(chunk + ((blocks_ - 1) * block_size_)))->next = nullptr; + return footer; +} + +void* PoolAllocator::allocate() +{ + if (first_chunk_ == nullptr) + { + SRB2_ASSERT(head_ == nullptr); + + // No chunks allocated yet + first_chunk_ = allocate_chunk(); + head_ = (FreeBlock*)first_chunk_->start; + } + + if (head_->next == nullptr) + { + // Current chunk will be full; allocate another at the end of the list + ChunkFooter* last_chunk = first_chunk_; + while (last_chunk->next != nullptr) + { + last_chunk = last_chunk->next; + } + ChunkFooter* new_chunk = allocate_chunk(); + last_chunk->next = new_chunk; + head_->next = (FreeBlock*)new_chunk->start; + } + + FreeBlock* ret = head_; + head_ = head_->next; + return ret; +} + +void PoolAllocator::deallocate(void* p) +{ + // Required in case this block is reused + LUA_InvalidateUserdata(p); + + FreeBlock* block = reinterpret_cast(p); + block->next = head_; + head_ = block; +} + +void PoolAllocator::release() +{ + ChunkFooter* next = nullptr; + for (ChunkFooter* i = first_chunk_; i != nullptr; i = next) + { + uint8_t *chunk = (uint8_t*)i->start; + for (size_t j = 0; j < blocks_; j++) + { + // Invalidate all blocks that possibly weren't passed to deallocate + LUA_InvalidateUserdata(chunk + (j * block_size_)); + } + next = i->next; + Z_Free(i->start); + } + + first_chunk_ = nullptr; + head_ = nullptr; +} + static LinearMemory g_frame_memory {4 * 1024 * 1024}; void* Z_Frame_Alloc(size_t size) diff --git a/src/core/memory.h b/src/core/memory.h index ba49e3d51..d568d34e9 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -14,6 +14,58 @@ #include #ifdef __cplusplus + +#include + +namespace srb2 +{ + +/// Pool allocator; manages bulk allocations of same-size block. If the pool is full, +/// allocations will fail by returning nullptr. +class PoolAllocator final +{ + struct FreeBlock + { + FreeBlock* next; + }; + struct ChunkFooter + { + ChunkFooter* next; + void* start; + }; + ChunkFooter* first_chunk_; + FreeBlock* head_; + size_t block_size_; + size_t blocks_; + int32_t tag_; + + ChunkFooter* allocate_chunk(); + +public: + constexpr PoolAllocator(size_t block_size, size_t blocks, int32_t tag) + : first_chunk_(nullptr) + , head_(nullptr) + , block_size_(block_size) + , blocks_(blocks) + , tag_(tag) + {} + PoolAllocator(const PoolAllocator&) = delete; + PoolAllocator(PoolAllocator&&) noexcept = default; + ~PoolAllocator(); + + PoolAllocator& operator=(const PoolAllocator&) = delete; + PoolAllocator& operator=(PoolAllocator&&) noexcept = default; + + void* allocate(); + void deallocate(void* p); + constexpr size_t block_size() const noexcept { return block_size_; }; + + void release(); +}; + +} // namespace srb2 + + extern "C" { #endif // __cpluspplus diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 44207ab5d..f72ae4cb9 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -211,17 +211,10 @@ tic_t firstconnectattempttime = 0; // Must be a power of two #define TEXTCMD_HASH_SIZE 4 -typedef struct textcmdplayer_s -{ - INT32 playernum; - UINT8 cmd[MAXTEXTCMD]; - struct textcmdplayer_s *next; -} textcmdplayer_t; - typedef struct textcmdtic_s { tic_t tic; - textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; + UINT8 *playercmds[MAXPLAYERS]; struct textcmdtic_s *next; } textcmdtic_t; @@ -407,22 +400,13 @@ static void D_FreeTextcmd(tic_t tic) if (textcmdtic) { - INT32 i; - // Remove this tic from the list. *tctprev = textcmdtic->next; // Free all players. - for (i = 0; i < TEXTCMD_HASH_SIZE; i++) + for (INT32 i = 0; i < MAXPLAYERS; i++) { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i]; - - while (textcmdplayer) - { - textcmdplayer_t *tcpnext = textcmdplayer->next; - Z_Free(textcmdplayer); - textcmdplayer = tcpnext; - } + Z_Free(textcmdtic->playercmds[i]); } // Free this tic's own memory. @@ -439,10 +423,8 @@ static UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) // Do we have an entry for the tic? If so, look for player. if (textcmdtic) { - textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; - - if (textcmdplayer) return textcmdplayer->cmd; + UINT8 *cmd = textcmdtic->playercmds[playernum]; + if (cmd) return cmd; } return NULL; @@ -453,7 +435,6 @@ static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) { textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer_t *textcmdplayer, **tcpprev; // Look for the tic. while (textcmdtic && textcmdtic->tic != tic) @@ -469,24 +450,11 @@ static UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) textcmdtic->tic = tic; } - tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; - textcmdplayer = *tcpprev; - - // Look for the player. - while (textcmdplayer && textcmdplayer->playernum != playernum) - { - tcpprev = &textcmdplayer->next; - textcmdplayer = textcmdplayer->next; - } - // If we don't have an entry for the player, make it. - if (!textcmdplayer) - { - textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL); - textcmdplayer->playernum = playernum; - } + if (!textcmdtic->playercmds[playernum]) + textcmdtic->playercmds[playernum] = Z_Calloc(MAXTEXTCMD, PU_STATIC, NULL); - return textcmdplayer->cmd; + return textcmdtic->playercmds[playernum]; } static void ExtraDataTicker(void) @@ -4243,8 +4211,8 @@ consvar_t cv_resynchcooldown = {"gamestatecooldown", "5", CV_SAVE, resynchcooldo consvar_t cv_blamecfail = {"blamecfail", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL }; // max file size to send to a player (in kilobytes) -static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {51200, "MAX"}, {0, NULL}}; -consvar_t cv_maxsend = {"maxsend", "MAX", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t maxsend_cons_t[] = {{-1, "MIN"}, {999999999, "MAX"}, {0, NULL}}; +consvar_t cv_maxsend = {"maxsend", "204800", CV_SAVE, maxsend_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_noticedownload = {"noticedownload", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; // Speed of file downloading (in packets per tic) @@ -4560,6 +4528,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) displayplayers[i] = newplayernum; DEBFILE("spawning me\n"); } + D_SendPlayerConfig(); addedtogame = true; } @@ -5868,29 +5837,28 @@ static void PT_Resynched(SINT8 node) static void PT_ServerTics(SINT8 node) { tic_t realend, realstart; - UINT8 *pak, *txtpak = NULL, numtxtpak; // Only accept PT_SERVERTICS from the server. if (!FromServer(node, "PT_SERVERTICS")) return; doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + servertics_pak *packet = &netbuffer->u.serverpak; - realstart = ExpandTics(netbuffer->u.serverpak.starttic, maketic); - realend = realstart + netbuffer->u.serverpak.numtics; - - if (!txtpak) - txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots - * netbuffer->u.serverpak.numtics]; + realstart = ExpandTics(packet->starttic, maketic); + realend = realstart + packet->numtics; if (realend > gametic + CLIENTBACKUPTICS) realend = gametic + CLIENTBACKUPTICS; cl_packetmissed = realstart > neededtic; + UINT8 *pak = (UINT8 *)&packet->cmds; + UINT8 *txtpak = (UINT8 *)&packet->cmds[packet->numslots * packet->numtics]; + if (realstart <= neededtic && realend > neededtic) { tic_t i, j; - pak = (UINT8 *)&netbuffer->u.serverpak.cmds; + pak = (UINT8 *)&packet->cmds; for (i = realstart; i < realend; i++) { @@ -5899,10 +5867,10 @@ static void PT_ServerTics(SINT8 node) // copy the tics pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak, - netbuffer->u.serverpak.numslots*sizeof (ticcmd_t)); + packet->numslots*sizeof (ticcmd_t)); // copy the textcmds - numtxtpak = *txtpak++; + UINT8 numtxtpak = *txtpak++; for (j = 0; j < numtxtpak; j++) { @@ -5926,11 +5894,6 @@ static void PT_ServerTics(SINT8 node) else { DEBFILE(va("frame not in bound: %u (bounds are from %u to %u)\n", neededtic, realstart, realend)); - /*if (realend < neededtic - 2 * TICRATE || neededtic + 2 * TICRATE < realstart) - * I_Error("Received an out of order PT_SERVERTICS packet!\n" - * "Got tics %d-%d, needed tic %d\n\n" - * "Please report this crash on the Master Board,\n" - * "IRC or Discord so it can be fixed.\n", (INT32)realstart, (INT32)realend, (INT32)neededtic);*/ } } @@ -7050,6 +7013,69 @@ void NetKeepAlive(void) // If a tree falls in the forest but nobody is around to hear it, does it make a tic? #define DEDICATEDIDLETIME (10*TICRATE) +#ifdef DEDICATEDIDLETIME +static void DedicatedIdleUpdate(INT32 *realtics) +{ + INT32 i; + static tic_t dedicatedidle = 0; + + if (!server || !dedicated || gamestate != GS_LEVEL) + return; + + boolean empty = true; + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + empty = false; + break; + } + + if (empty) + { + if (leveltime == 2) + { + // On next tick... + dedicatedidle = DEDICATEDIDLETIME - 1; + } + else if (dedicatedidle >= DEDICATEDIDLETIME) + { + if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic + 1, 0)) + { + CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); + dedicatedidle = 0; + } + else + { + (*realtics) = 0; + } + } + else + { + dedicatedidle += (*realtics); + + if (dedicatedidle >= DEDICATEDIDLETIME) + { + const char *idlereason = "at round start"; + if (leveltime > 3) + idlereason = va("for %d seconds", dedicatedidle / TICRATE); + + CONS_Printf("DEDICATED: No players %s, idling...\n", idlereason); + (*realtics) = 0; + dedicatedidle = DEDICATEDIDLETIME; + } + } + } + else + { + if (dedicatedidle >= DEDICATEDIDLETIME) + { + CONS_Printf("DEDICATED: Awakening from idle (Player detected...)\n"); + } + dedicatedidle = 0; + } +} +#endif + void NetUpdate(void) { static tic_t resptime = 0; @@ -7063,54 +7089,6 @@ void NetUpdate(void) if (realtics <= 0) // nothing new to update return; -#ifdef DEDICATEDIDLETIME - if (server && dedicated && gamestate == GS_LEVEL) - { - static tic_t dedicatedidle = 0; - - for (i = 1; i < MAXNETNODES; ++i) - if (nodeingame[i]) - { - if (dedicatedidle == DEDICATEDIDLETIME) - { - CONS_Printf("DEDICATED: Awakening from idle (Node %d detected...)\n", i); - dedicatedidle = 0; - } - break; - } - - if (i == MAXNETNODES) - { - if (leveltime == 2) - { - // On next tick... - dedicatedidle = DEDICATEDIDLETIME-1; - } - else if (dedicatedidle == DEDICATEDIDLETIME) - { - if (D_GetExistingTextcmd(gametic, 0) || D_GetExistingTextcmd(gametic+1, 0)) - { - CONS_Printf("DEDICATED: Awakening from idle (Netxcmd detected...)\n"); - dedicatedidle = 0; - } - else - { - realtics = 0; - } - } - else if (++dedicatedidle == DEDICATEDIDLETIME) - { - const char *idlereason = "at round start"; - if (leveltime > 3) - idlereason = va("for %d seconds", dedicatedidle/TICRATE); - - CONS_Printf("DEDICATED: No nodes %s, idling...\n", idlereason); - realtics = 0; - } - } - } -#endif - if (realtics > 5) { if (server) @@ -7119,6 +7097,10 @@ void NetUpdate(void) realtics = 5; } +#ifdef DEDICATEDIDLETIME + DedicatedIdleUpdate(&realtics); +#endif + gametime = nowtime; UpdatePingTable(); diff --git a/src/d_main.c b/src/d_main.c index f191a546c..972d65844 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -220,11 +220,12 @@ static void D_GamePadMenuScrollTicker(void) } #undef SCROLLDELAY +static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0}; + static void D_DeviceLEDTick(void) { UINT8 i; static UINT16 color[MAXSPLITSCREENPLAYERS] = {0}; - static UINT16 curcolor[MAXSPLITSCREENPLAYERS] = {0}; if (numcontrollers == 0) { @@ -246,6 +247,11 @@ static void D_DeviceLEDTick(void) } } +void D_ResetDeviceLED(void) +{ + memset(curcolor, 0, sizeof(curcolor)); +} + // // D_ProcessEvents // Send all the events of the given timestamp down the responder chain @@ -326,7 +332,7 @@ static void D_Renderview(void) if (automapactive) return; - R_ApplyLevelInterpolators(rendertimefrac); + R_ApplyLevelInterpolators(R_GetTimeFrac(RTF_LEVEL)); if (rendermode == render_soft) { @@ -448,7 +454,7 @@ static boolean D_Display(void) if (rendermode == render_soft && !splitscreen) { - R_InterpolateViewRollAngle(rendertimefrac_unpaused); + R_InterpolateViewRollAngle(R_GetTimeFrac(RTF_CAMERA)); R_CheckViewMorph(); } @@ -808,7 +814,7 @@ void D_SRB2Loop(void) debugload--; #endif - interp = (R_UsingFrameInterpolation() && !dedicated); + interp = !dedicated && R_UsingFrameInterpolation(); doDisplay = false; renderisnewtic = (realtics > 0 || singletics); @@ -871,29 +877,12 @@ void D_SRB2Loop(void) const boolean lagging = ((deltatics >= 1.0) || hu_stopped); - if (!(paused || P_AutoPause()) && !lagging) - { - rendertimefrac = g_time.timefrac; - } - else - { - rendertimefrac = FRACUNIT; - } - - if (!lagging) - { - rendertimefrac_unpaused = g_time.timefrac; - } - else - { - rendertimefrac_unpaused = FRACUNIT; - } + R_SetTimeFrac(lagging ? FRACUNIT : g_time.timefrac); } else { renderdeltatics = realtics * FRACUNIT; - rendertimefrac = FRACUNIT; - rendertimefrac_unpaused = FRACUNIT; + R_SetTimeFrac(FRACUNIT); } if (interp || doDisplay) @@ -983,39 +972,17 @@ void D_SRB2Loop(void) // ========================================================================= // -// D_StartTitle +// D_ClearState // -void D_StartTitle(void) +void D_ClearState(void) { INT32 i; - if (netgame) - { - if (gametype == GT_RACE) // SRB2kart - { - G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat - - if (server) - { - char mapname[6]; - - strlcpy(mapname, G_BuildMapName(spstage_start), sizeof (mapname)); - strlwr(mapname); - mapname[5] = '\0'; - - COM_BufAddText(va("map %s\n", mapname)); - } - } - - return; - } - - M_ClearMenus(true); - // okay, stop now // (otherwise the game still thinks we're playing!) SV_StopServer(); SV_ResetServer(); + serverlistultimatecount = 0; for (i = 0; i < MAXPLAYERS; i++) CL_ClearPlayer(i); @@ -1031,8 +998,11 @@ void D_StartTitle(void) // reset modeattacking modeattacking = ATTACKING_NONE; - // empty maptol so mario/etc sounds don't play in sound test when they shouldn't + // empty some other semi-important state maptol = 0; + nextmapoverride = 0; + skipstats = 0; + gamemap = 1; gameaction = ga_nothing; memset(displayplayers, 0, sizeof(displayplayers)); @@ -1041,9 +1011,38 @@ void D_StartTitle(void) gametype = GT_RACE; // SRB2kart paused = false; + // clear cmd building stuff + memset(gamekeydown, 0, sizeof(gamekeydown)); + memset(joyxmove, 0, sizeof(joyxmove)); + memset(joyymove, 0, sizeof(joyymove)); + mousex = mousey = 0; + + // Reset the palette + if (rendermode != render_none) + V_SetPaletteLump("PLAYPAL"); + + G_ResetAllDeviceRumbles(); + + S_StopSounds(); S_ResetKeepAndSpecialMus(); // just in case + P_FreeLevelState(); + + G_SetGamestate(GS_NULL); + wipegamestate = GS_NULL; +} + +// +// D_StartTitle +// +void D_StartTitle(void) +{ + demo.title = false; + D_ClearState(); + netgame = false; // title menu shouldnt be a netgame lmao + M_ClearMenus(true); F_StartTitleScreen(); + D_ResetDeviceLED(); } // @@ -1073,25 +1072,23 @@ static INT32 D_DetectFileType(const char* filename) { if (pathisdirectory(filename) == 1) return 1; - else - { - if (!stricmp(&filename[strlen(filename) - 4], ".wad")) - return 2; - else if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) - return 3; - else if (!stricmp(&filename[strlen(filename) - 5], ".kart")) - return 4; - else if (!stricmp(&filename[strlen(filename) - 4], ".lua")) - return 5; - else if (!stricmp(&filename[strlen(filename) - 4], ".soc")) - return 6; + const size_t len = strlen(filename); - else if (!stricmp(&filename[strlen(filename) - 4], ".cfg")) - return 7; - else if (!stricmp(&filename[strlen(filename) - 4], ".txt")) - return 8; - } + if (!stricmp(&filename[len - 4], ".wad")) + return 2; + else if (!stricmp(&filename[len - 4], ".pk3")) + return 3; + else if (!stricmp(&filename[len - 5], ".kart")) + return 4; + else if (!stricmp(&filename[len - 4], ".lua")) + return 5; + else if (!stricmp(&filename[len - 4], ".soc")) + return 6; + else if (!stricmp(&filename[len - 4], ".cfg")) + return 7; + else if (!stricmp(&filename[len - 4], ".txt")) + return 8; return 0; } @@ -1257,11 +1254,148 @@ static boolean AddIWAD(void) return false; } -// extra graphic patches for saturn specific thingies +// Optional saturn extra files boolean found_extra_kart = false; boolean found_extra2_kart = false; boolean found_extra3_kart = false; +static void IdentifyVersion(void) +{ + const char *srb2waddir = NULL; + +#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) + // change to the directory where 'srb2.srb' is found + srb2waddir = I_LocateWad(); +#endif + + char tempsrb2path[256] = "."; + getcwd(tempsrb2path, 256); + + // get the current directory (possible problem on NT with "." as current dir) + if (!srb2waddir) + { + if (tempsrb2path[0]) + srb2waddir = tempsrb2path; + else + { + srb2waddir = "."; + } + } + +#if (1) // reduce the amount of findfile by only using full cwd in this func + if (strcmp(tempsrb2path, srb2waddir)) +#endif + { + strlcpy(srb2path, srb2waddir, sizeof (srb2path)); + } + + // Load the IWAD + if (!AddIWAD()) + { + I_Error("SRB2.SRB not found! Expected in %s\n", srb2waddir); + } + + // will be overwritten in case of -cdrom or unix/win home + snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir); + configfile[sizeof configfile - 1] = '\0'; + + // if you change the ordering of this or add/remove a file, be sure to update the md5 + // checking in D_SRB2Main + +#ifdef USE_PATCH_DTA + // Add our crappy patches to fix our bugs + D_AddFile(va(pandf,srb2waddir,"patch.dta")); +#endif + + D_AddFile(va(pandf, srb2waddir, "gfx.kart"), startupwadfiles); + D_AddFile(va(pandf, srb2waddir, "textures.kart"), startupwadfiles); + D_AddFile(va(pandf, srb2waddir, "chars.kart"), startupwadfiles); + D_AddFile(va(pandf, srb2waddir, "maps.kart"), startupwadfiles); +#ifdef USE_PATCH_KART + D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles); +#endif + + const char *path = NULL; + + path = va(pandf, srb2waddir, "extra.kart"); + + // completely optional + if (FIL_ReadFileOK(path)) + { + D_AddFile(path, startupwadfiles); + found_extra_kart = true; + } + + path = va(pandf, srb2waddir, "extra2.kart"); + + // completely optional 2: Back with a vengence + if (FIL_ReadFileOK(path)) + { + D_AddFile(path, startupwadfiles); + found_extra2_kart = true; + } + + path = va(pandf, srb2waddir, "extra3.kart"); + + if (FIL_ReadFileOK(path)) + { + D_AddFile(path, startupwadfiles); + found_extra3_kart = true; + } + +#if !defined (HAVE_SDL) || defined (HAVE_MIXER) +#define MUSICTEST(str) \ + musicpath = va(pandf,srb2waddir,str);\ + handle = W_OpenWadFile(&musicpath, false); \ + if (handle) \ + {\ + int ms = W_VerifyNMUSlumps(musicpath, handle, false); \ + fclose(handle); \ + if (ms == 0) \ + I_Error("File " str " has been modified with non-music/sound lumps"); \ + if (ms == 1) \ + D_AddFile(musicpath, startupwadfiles); \ + } + { + const char *musicpath; + FILE *handle; + + MUSICTEST("sounds.kart") + MUSICTEST("music.kart") + } +#undef MUSICTEST +#endif +} + +// +// Center the title string, then add the date and time of compilation. +// +static inline void D_MakeTitleString(char *s) +{ + char temp[82]; + char *t; + const char *u; + INT32 i; + const size_t len = (80-strlen(s))/2; + + for (i = 0, t = temp; i < 82; i++) + *t++=' '; + + for (t = temp + len, u = s; *u != '\0' ;) + *t++ = *u++; + + u = compdate; + for (t = temp + 1, i = 11; i-- ;) + *t++ = *u++; + u = comptime; + for (t = temp + 71, i = 8; i-- ;) + *t++ = *u++; + + temp[80] = '\0'; + strcpy(s, temp); +} + +// extra graphic patches for saturn specific thingies boolean xtra_speedo = false; // extra speedometer check boolean xtra_speedo_clr = false; // extra speedometer colour check boolean xtra_speedo3 = false; // 80x 11 extra speedometer check @@ -1286,118 +1420,6 @@ boolean minidoticon = false; // Dot graphic for minimap player angle displ boolean minilighticon = false; // mkwii-style minimap headlight // -static void IdentifyVersion(void) -{ - const char *srb2waddir = NULL; - -#if defined (__unix__) || defined (UNIXCOMMON) || defined (HAVE_SDL) - // change to the directory where 'srb2.srb' is found - srb2waddir = I_LocateWad(); -#endif - - // get the current directory (possible problem on NT with "." as current dir) - if (srb2waddir) - { - strlcpy(srb2path, srb2waddir, sizeof(srb2path)); - } - else - { - if (getcwd(srb2path, sizeof(srb2path))) - srb2waddir = srb2path; - else - { - srb2waddir = srb2path; - } - } - - // Load the IWAD - if (!AddIWAD()) - { - I_Error("SRB2.SRB not found! Expected in %s\n", srb2waddir); - } - - // will be overwritten in case of -cdrom or unix/win home - snprintf(configfile, sizeof configfile, "%s" PATHSEP CONFIGFILENAME, srb2waddir); - configfile[sizeof configfile - 1] = '\0'; - - // if you change the ordering of this or add/remove a file, be sure to update the md5 - // checking in D_SRB2Main - -#ifdef USE_PATCH_DTA - // Add our crappy patches to fix our bugs - D_AddFile(va(pandf,srb2waddir,"patch.dta")); -#endif - - D_AddFile(va(pandf,srb2waddir,"gfx.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"textures.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"chars.kart"), startupwadfiles); - D_AddFile(va(pandf,srb2waddir,"maps.kart"), startupwadfiles); -#ifdef USE_PATCH_KART - D_AddFile(va(pandf,srb2waddir,"patch.kart"), startupwadfiles); -#endif - // completely optional - if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra.kart"))) - { - D_AddFile(va(pandf,srb2waddir,"extra.kart"), startupwadfiles); - found_extra_kart = true; - } - - // completely optional 2: Back with a vengence - if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra2.kart"))) - { - D_AddFile(va(pandf,srb2waddir,"extra2.kart"), startupwadfiles); - found_extra2_kart = true; - } - - if (FIL_ReadFileOK(va(pandf,srb2waddir,"extra3.kart"))) - { - D_AddFile(va(pandf,srb2waddir,"extra3.kart"), startupwadfiles); - found_extra3_kart = true; - } - -#if !defined (HAVE_SDL) || defined (HAVE_MIXER) -#define MUSICTEST(str) \ - {\ - const char *musicpath = va(pandf,srb2waddir,str);\ - int ms = W_VerifyNMUSlumps(musicpath); \ - if (ms == 1) \ - D_AddFile(musicpath, startupwadfiles); \ - else if (ms == 0) \ - I_Error("File "str" has been modified with non-music/sound lumps"); \ - } - MUSICTEST("sounds.kart") - MUSICTEST("music.kart") -#undef MUSICTEST -#endif -} - -// -// Center the title string, then add the date and time of compilation. -// -static inline void D_MakeTitleString(char *s) -{ - char temp[82]; - char *t; - const char *u; - INT32 i; - - for (i = 0, t = temp; i < 82; i++) - *t++=' '; - - for (t = temp + (80-strlen(s))/2, u = s; *u != '\0' ;) - *t++ = *u++; - - u = compdate; - for (t = temp + 1, i = 11; i-- ;) - *t++ = *u++; - u = comptime; - for (t = temp + 71, i = 8; i-- ;) - *t++ = *u++; - - temp[80] = '\0'; - strcpy(s, temp); -} - static void D_CheckSaturnExtraFiles(void) { // Possible value that changes depending on whether required files for speedometer are found or not @@ -1499,12 +1521,14 @@ static void D_CheckSaturnExtraFiles(void) PUSHCONS(inputdisplay_cons_temp, last_inputdisplay_i, 3, "StickGFX"); } + // minimap dot if (W_LumpExists("MMAPDOT")) { minidoticon = true; PUSHCONS(minimapdot_cons_temp, last_minimapdot_i, 1, "Dot"); } + // minimap headlight if (W_LumpExists("MMAPHDLT")) { minilighticon = true; @@ -1785,9 +1809,6 @@ void D_SRB2Main(void) I_InitializeTime(); setlocale(LC_TIME, ""); - // Make backups of some SOCcable tables. - P_BackupTables(); - // Setup default unlockable conditions M_SetupDefaultConditionSets(); @@ -1920,8 +1941,12 @@ void D_SRB2Main(void) // setup loading screen SCR_Startup(); + // Do this in background; lots of number crunching + R_InitTranslucencyTables(); + // we need the font of the console CONS_Printf("HU_Init(): Setting up heads up display.\n"); + HU_Init(); COM_Init(); @@ -1983,13 +2008,7 @@ void D_SRB2Main(void) R_Init(); // setting up sound - if (dedicated) - { - sound_disabled = true; - music_disabled = true; - } - - if (M_CheckParm("-noaudio")) // combines -nosound and -nomusic + if (dedicated || M_CheckParm("-noaudio")) // combines -nosound and -nomusic { sound_disabled = true; music_disabled = true; @@ -2127,12 +2146,6 @@ void D_SRB2Main(void) } #endif - /*if (M_CheckParm("-ultimatemode")) - { - autostart = true; - ultimatemode = true; - }*/ - if (autostart || netgame) { gameaction = ga_nothing; @@ -2277,6 +2290,9 @@ const char *D_Home(void) } #endif// !__CYGWIN__ #endif// _WIN32 - if (usehome) return userhome; - else return NULL; + + if (usehome) + return userhome; + else + return NULL; } diff --git a/src/d_main.h b/src/d_main.h index 69bbe3026..fe904e15a 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -87,9 +87,12 @@ void D_ProcessEvents(void); const char *D_Home(void); +void D_ResetDeviceLED(void); + // // BASE LEVEL // +void D_ClearState(void); void D_StartTitle(void); #ifdef __cplusplus diff --git a/src/d_net.c b/src/d_net.c index af1d1a777..b2500e3e5 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -219,14 +219,14 @@ static boolean GetFreeAcknum(UINT8 *freeack) node_t *node = &nodes[doomcom->remotenode]; INT32 i, numfreeslot = 0; - doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); - if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0) { DEBFILE(va("too fast %d %d\n",node->remotefirstack,node->nextacknum)); return false; } + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + for (i = 0; i < MAXACKPACKETS; i++) { if (!ackpak[i].acknum) @@ -262,7 +262,10 @@ static boolean GetFreeAcknum(UINT8 *freeack) CONS_Debug(DBG_NETPLAY, "No more free ackpacket\n"); #endif if (netbuffer->packettype < PT_CANFAIL) - I_Error("Connection lost\n"); + { + CONS_Alert(CONS_WARNING, "Connection from %s is not acknowledging packets, killing connection\n", I_GetNodeAddress(doomcom->remotenode)); + Net_CloseConnection(doomcom->remotenode | FORCECLOSE); + } return false; } @@ -461,6 +464,7 @@ void Net_ConnectionTimeout(INT32 node) // Don't timeout several times if (nodes[node].flags & NF_TIMEOUT) return; + nodes[node].flags |= NF_TIMEOUT; // Send a very special packet to self (hack the reboundstore queue) @@ -487,11 +491,11 @@ void Net_AckTicker(void) for (i = 0; i < MAXACKPACKETS; i++) { - const INT32 nodei = ackpak[i].destinationnode; - node_t *node = &nodes[nodei]; - if (ackpak[i].acknum && ackpak[i].senttime + NODETIMEOUT < I_GetTime()) { + const INT32 nodei = ackpak[i].destinationnode; + node_t *node = &nodes[nodei]; + if (ackpak[i].resentnum > 10 && (node->flags & NF_CLOSE)) { DEBFILE(va("ack %d sent 10 times so connection is supposed lost: node %d\n", @@ -540,13 +544,14 @@ void Net_UnAcknowledgePacket(INT32 node) #ifdef NONET (void)node; #else - doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND; DEBFILE(va("UnAcknowledge node %d\n", node)); if (!node) return; + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + if (nodes[node].acktosend[hm1] == netbuffer->ack) { nodes[node].acktosend[hm1] = 0; @@ -683,7 +688,6 @@ void Net_CloseConnection(INT32 node) (void)node; #else INT32 i; - boolean forceclose = (node & FORCECLOSE) != 0; if (node == -1) { @@ -691,6 +695,8 @@ void Net_CloseConnection(INT32 node) return; // nope, just ignore it } + boolean forceclose = (node & FORCECLOSE) != 0; + node &= ~FORCECLOSE; if (!node) @@ -710,6 +716,12 @@ void Net_CloseConnection(INT32 node) Net_SendAcks(node); Net_SendAcks(node); } + else + { + // if the connection hasn't acknowledged anything, it's possible for it to permanently occupy the node. + // to prevent this, drop the connection. + forceclose = true; + } // check if we are waiting for an ack from this node for (i = 0; i < MAXACKPACKETS; i++) @@ -1259,13 +1271,12 @@ SINT8 I_NetMakeNode(const char *hostname) void D_SetDoomcom(void) { - if (doomcom) return; + if (doomcom) + return; + doomcom = Z_Calloc(sizeof (doomcom_t), PU_STATIC, NULL); doomcom->id = DOOMCOM_ID; doomcom->numslots = doomcom->numnodes = 1; - doomcom->gametype = 0; - doomcom->consoleplayer = 0; - doomcom->extratics = 0; } // diff --git a/src/d_netcmd.c b/src/d_netcmd.c index adeca66f9..6b0ed9799 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4404,7 +4404,9 @@ static void Command_Addfile(void) char buf[256]; char *buf_p = buf; INT32 i; - int musiconly; // W_VerifyNMUSlumps isn't boolean + int musiconly = -1; // W_VerifyNMUSlumps isn't boolean + + FILE *fhandle = NULL; if (COM_Argc() != 2) { @@ -4419,9 +4421,18 @@ static void Command_Addfile(void) if (!isprint(fn[i]) || fn[i] == ';') return; - musiconly = W_VerifyNMUSlumps(fn); + if (fhandle) + { + fclose(fhandle); + fhandle = NULL; + } - if (!musiconly) + if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) + { + musiconly = W_VerifyNMUSlumps(fn, fhandle, false); + } + + if (musiconly == -1) { // ... But only so long as they contain nothing more then music and sprites. if (netgame && !(server || IsPlayerAdmin(consoleplayer))) @@ -4445,36 +4456,31 @@ static void Command_Addfile(void) break; ++p; - WRITESTRINGN(buf_p,p,240); - // calculate and check md5 { UINT8 md5sum[16]; #ifdef NOMD5 memset(md5sum,0,16); #else - FILE *fhandle; - if ((fhandle = W_OpenWadFile(&fn, true)) != NULL) { 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 - return; for (i = 0; i < numwadfiles; i++) { - if (!memcmp(wadfiles[i]->md5sum, md5sum, 16)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); - return; - } + if (memcmp(wadfiles[i]->md5sum, md5sum, 16)) + continue; + + CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), fn); + goto addfile_finally; } #endif + // Finally okay to write this important data + WRITESTRINGN(buf_p,p,240); WRITEMEM(buf_p, md5sum, 16); } @@ -4482,6 +4488,10 @@ static void Command_Addfile(void) SendNetXCmd(XD_REQADDFILE, buf, buf_p - buf); else SendNetXCmd(XD_ADDFILE, buf, buf_p - buf); + +addfile_finally: + if (fhandle) + fclose(fhandle); } /** Adds something at runtime. @@ -5605,7 +5615,9 @@ void Command_ExitGame_f(void) closefilemenu(true); if (!modeattacking) + { D_StartTitle(); + } } void Command_Retry_f(void) diff --git a/src/d_netfil.c b/src/d_netfil.c index 356fb6854..6ed52d7d6 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -163,7 +163,8 @@ UINT8 *PutFileNeeded(UINT16 firstfile) nameonly(strcpy(wadfilename, wadfiles[i]->filename)); // Look below at the WRITE macros to understand what these numbers mean. - if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED) + const size_t len = strlen(wadfilename) + 1; + if (p + 1 + 4 + min(len, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED) { // Too many files to send all at once if (netbuffer->packettype == PT_MOREFILESNEEDED) @@ -178,7 +179,7 @@ UINT8 *PutFileNeeded(UINT16 firstfile) // Store in the upper four bits if (!cv_downloading.value) filestatus += (2 << 4); // Won't send - else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)) + else if (cv_maxsend.value == -1 || wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024) filestatus += (1 << 4); // Will send if requested // else // filestatus += (0 << 4); -- Won't send, too big @@ -212,6 +213,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi fileneedednum = firstfile + fileneedednum_parm; p = (UINT8 *)fileneededstr; + for (i = firstfile; i < fileneedednum; i++) { fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet @@ -648,7 +650,8 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) { filetx_t **q; // A pointer to the "next" field of the last file in the list filetx_t *p; // The new file request - INT32 i; + UINT16 wadnum; + char wadfilename[MAX_WADPATH]; if (cv_noticedownload.value) @@ -674,20 +677,21 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) nameonly(p->id.filename); // Look for the requested file through all loaded files - for (i = 0; wadfiles[i]; i++) + for (wadnum = 0; wadfiles[wadnum]; wadnum++) { - strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH); + strlcpy(wadfilename, wadfiles[wadnum]->filename, MAX_WADPATH); nameonly(wadfilename); + if (!stricmp(wadfilename, p->id.filename)) { // Copy file name with full path - strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH); + strlcpy(p->id.filename, wadfiles[wadnum]->filename, MAX_WADPATH); break; } } // Handle non-loaded file requests - if (!wadfiles[i]) + if (!wadfiles[wadnum]) { DEBFILE(va("%s not found in wadfiles\n", filename)); // This formerly checked if (!findfile(p->id.filename, NULL, true)) @@ -702,7 +706,7 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) } // Handle huge file requests (i.e. bigger than cv_maxsend.value KB) - if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024) + if (cv_maxsend.value != -1 && wadfiles[wadnum]->filesize > (UINT32)cv_maxsend.value * 1024) { // Too big // Don't inform client (client sucks, man) @@ -773,6 +777,7 @@ static void SV_EndFileSend(INT32 node) case SF_FILE: // It's a file, close it and free its filename if (cv_noticedownload.value) CONS_Printf("Ending file transfer (id %d) for node %d\n", p->fileid, node); + if (transferFiles[p->fileid].file) { if (transferFiles[p->fileid].count > 0) @@ -786,6 +791,7 @@ static void SV_EndFileSend(INT32 node) transferFiles[p->fileid].file = NULL; } } + free(p->id.filename); break; case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free @@ -821,11 +827,12 @@ void SV_FileSendTicker(void) size_t size; filetx_t *f; INT32 packetsent, ram, i, j; - doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); if (!filestosend) // No file to send return; + doomdata_t *netbuffer = DOOMCOM_DATA(doomcom); + packetsent = cv_downloadspeed.value; netbuffer->packettype = PT_FILEFRAGMENT; @@ -957,8 +964,8 @@ void Got_Filetxpak(void) static INT32 filetime = 0; if (!(strcmp(filename, "srb2.srb") - && strcmp(filename, "srb2.wad") - && strcmp(filename, "patch.dta") + //&& strcmp(filename, "srb2.wad") + //&& strcmp(filename, "patch.dta") //&& strcmp(filename, "music.dta") && strcmp(filename, "gfx.kart") && strcmp(filename, "textures.kart") @@ -1001,6 +1008,7 @@ void Got_Filetxpak(void) pos &= ~0x80000000; file->totalsize = pos + size; } + // We can receive packet in the wrong order, anyway all os support gaped file fseek(file->file, pos, SEEK_SET); if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1) @@ -1207,23 +1215,29 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet // if not found at all, just move on without doing anything } - // next, check SRB2's "home" directory - homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); + // next, check SRB2's "home" directory (if non-'.') + if (strcmp(srb2home, ".")) + { + homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10); - if (homecheck == FS_FOUND) // we found the file, so return that we have :) - return FS_FOUND; - else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 - badmd5 = true; - // if not found at all, just move on without doing anything + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + } - // next, check SRB2's "path" directory - homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); + // next, check SRB2's "path" directory (also if non-'.') + if (strcmp(srb2path, ".")) + { + homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10); - if (homecheck == FS_FOUND) // we found the file, so return that we have :) - return FS_FOUND; - else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 - badmd5 = true; - // if not found at all, just move on without doing anything + if (homecheck == FS_FOUND) // we found the file, so return that we have :) + return FS_FOUND; + else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5 + badmd5 = true; + // if not found at all, just move on without doing anything + } // finally check "." directory homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10); diff --git a/src/d_player.h b/src/d_player.h index 8f312ecfa..11ccf8079 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -568,6 +568,8 @@ typedef struct player_s squishdance_t squishdance; fixed_t fovadd; // adjust FOV for hw rendering + + SINT8 driftlevel; // just for controller rumble for now } player_t; #endif diff --git a/src/d_think.h b/src/d_think.h index 1ef2577dc..fc37c64b5 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -30,6 +30,15 @@ // typedef void (*actionf_p1)(void *); +typedef enum +{ + /// The allocation is standard e.g. Z_Malloc + TAT_MALLOC, + + /// The allocation is in the pool allocator (e.g. Z_LevelPoolCalloc) + TAT_LEVELPOOL +} thinker_alloc_type_e; + // Historically, "think_t" is yet another function pointer to a routine // to handle an actor. typedef actionf_p1 think_t; @@ -44,7 +53,9 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; - boolean cachable; + INT32 alloctype; + size_t size; + #ifdef PARANOIA INT32 debug_mobjtype; tic_t debug_time; diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 1fe81e165..b2affd674 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -1223,43 +1223,6 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) #undef WINMUMBLE #endif // NOMUMBLE - -/** \brief empty ticcmd for player 1 -*/ -static ticcmd_t emptycmd; - -ticcmd_t *I_BaseTiccmd(void) -{ - return &emptycmd; -} - -/** \brief empty ticcmd for player 2 -*/ -static ticcmd_t emptycmd2; - -ticcmd_t *I_BaseTiccmd2(void) -{ - return &emptycmd2; -} - -/** \brief empty ticcmd for player 3 - */ -static ticcmd_t emptycmd3; - -ticcmd_t *I_BaseTiccmd3(void) -{ - return &emptycmd3; -} - -/** \brief empty ticcmd for player 4 - */ -static ticcmd_t emptycmd4; - -ticcmd_t *I_BaseTiccmd4(void) -{ - return &emptycmd4; -} - // // I_GetTime // returns time in 1/TICRATE second tics diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c index e2a712995..7a1239507 100644 --- a/src/dedicated/i_video.c +++ b/src/dedicated/i_video.c @@ -35,8 +35,6 @@ consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL static CV_PossibleValue_t keyboardlayout_cons_t[] = {{1,"Default US"}, {2, "Native"}, {3, "AZERTY"}, {0, NULL}}; consvar_t cv_keyboardlayout = {"keyboardlayout", "Default US", CV_SAVE, keyboardlayout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - INT32 numcontrollers = 0; UINT8 graphics_started = 0; // Is used in console.c and screen.c @@ -146,6 +144,10 @@ UINT32 I_GetRefreshRate(void) return 0; } +void I_SetTextInput(void) +{ +} + boolean I_UseNativeKeyboard(void) { return false; diff --git a/src/dehacked.c b/src/dehacked.c index 44f0b5275..442e6d0d4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2631,7 +2631,7 @@ static void readmaincfg(MYFILE *f) } else if (fastcmp(word, "RESETDATA")) { - P_ResetData(value); + CONS_Alert(CONS_WARNING, M_GetText("RESETDATA is obsolete and no longer has any effect.\n")); } else if (fastcmp(word, "CUSTOMVERSION")) { diff --git a/src/doomdef.h b/src/doomdef.h index 1f7dcb4d8..4ba11d590 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -115,8 +115,8 @@ extern char logfilename[1024]; #else #define VERSION 1 // Game version #define SUBVERSION 6 // more precise version number -#define VERSIONSTRING "Saturn v8.3" -#define VERSIONSTRINGW L"Saturn v8.3" +#define VERSIONSTRING "Saturn - Testing" +#define VERSIONSTRINGW L"Saturn - Testing" // Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! // And change CMakeLists.txt (not src/, but in root), for CMake users! // AND appveyor.yml, for the build bots! @@ -626,13 +626,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Most modifications should probably enable this. //#define SAVEGAME_OTHERVERSIONS -/// Allow the use of the SOC RESETINFO command. -/// \note Builds that are tight on memory should disable this. -/// This stops the game from storing backups of the states, sprites, and mobjinfo tables. -/// Though this info is compressed under normal circumstances, it's still a lot of extra -/// memory that never gets touched. -#define ALLOW_RESETDATA - #ifndef NONET /// Display a connection screen on join attempts. #define CLIENT_LOADINGSCREEN diff --git a/src/doomtype.h b/src/doomtype.h index ac41a4413..6ad95c94e 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -148,8 +148,8 @@ int strlwr(char *n); // from dosstr.c #include // for size_t #ifndef SRB2_HAVE_STRLCPY -size_t strlcat(char *dst, const char *src, size_t siz); -size_t strlcpy(char *dst, const char *src, size_t siz); +size_t strlcat(char *dst, const char *src, size_t dsize); +size_t strlcpy(char *dst, const char *src, size_t dsize); #endif // Macro for use with char foo[FOOSIZE+1] type buffers. diff --git a/src/f_finale.c b/src/f_finale.c index 6d062af11..6126b51b6 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -34,6 +34,8 @@ #include "y_inter.h" #include "m_cond.h" +#include "r_fps.h" // R_GetTimeFrac + // Stage of animation: // 0 = text, 1 = art screen static INT32 finalecount; @@ -170,8 +172,8 @@ static void F_SkyScroll(INT32 scrollspeed) w = (vid.width / vid.dupx)<width*16))<width<width*16))<width*16))<width<width*16))< 0) timetonext--; else - D_StartTitle(); + G_EndGame(); } // ============== @@ -1003,7 +1005,7 @@ void F_TitleScreenDrawer(void) if (finalecount >= 20) V_DrawSmallScaledPatch(84, 87, 0, ttkart); else if (finalecount >= 10) - V_DrawSciencePatch((84<date, 0, sizeof(pdemo->date)); @@ -3869,8 +3843,8 @@ static void G_StopTimingDemo(void) D_StartTitle(); } - -boolean G_CheckDemoStatus(void) +// Clean up all ghosts +void G_FreeGhosts(void) { while (ghosts) { @@ -3879,6 +3853,12 @@ boolean G_CheckDemoStatus(void) ghosts = next; } ghosts = NULL; +} + + +boolean G_CheckDemoStatus(void) +{ + G_FreeGhosts(); // DO NOT end metal sonic demos here diff --git a/src/g_demo.h b/src/g_demo.h index de1495e91..905094579 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -174,6 +174,7 @@ void G_ResetDemoRecording(void); void G_DoPlayDemo(char *defdemoname); void G_TimeDemo(const char *name); void G_AddGhost(char *defdemoname); +void G_FreeGhosts(void); void G_UpdateStaffGhostName(lumpnum_t l); void G_DoPlayMetal(void); void G_DoneLevelLoad(void); diff --git a/src/g_game.c b/src/g_game.c index 21749d374..0db5cfc51 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -630,7 +630,6 @@ const char *G_BuildMapName(INT32 map) map = G_RandMap(G_TOLFlag(cv_newgametype.value), map, false, 0, false, NULL)+1; } - if (map < 100 && map >= 0) // ...but why use signed integer in first place? idk but this prevents warning (and potential buffer overflow lol) sprintf(&mapname[3], "%.2d", map); else @@ -808,6 +807,60 @@ static fixed_t forwardmove[2] = {25<>16, 50<>16}; static fixed_t sidemove[2] = {2<>16, 4<>16}; static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +static void G_HandleLocalDriftturn(ticcmd_t *cmd, UINT8 ssplayer) +{ + INT32 axis = 0; + boolean turnleft, turnright; + + const UINT8 forplayer = (ssplayer-1); + + const boolean analogjoystickmove = cv_usejoystick[forplayer].value && !Joystick[forplayer].bGamepadStyle; + const boolean gamepadjoystickmove = cv_usejoystick[forplayer].value && Joystick[forplayer].bGamepadStyle; + + turnright = InputDown(gc_turnright, ssplayer); + turnleft = InputDown(gc_turnleft, ssplayer); + + axis = JoyAxis(AXISTURN, ssplayer); + + if (encoremode) + { + turnright ^= turnleft; // swap these using three XORs + turnleft ^= turnright; + turnright ^= turnleft; + axis = -axis; + } + + if (gamepadjoystickmove && axis != 0) + { + turnright = turnright || (axis > 0); + turnleft = turnleft || (axis < 0); + } + + cmd->driftturn = 0; + + // let movement keys cancel each other out + if (turnright && !(turnleft)) + { + cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[1])); + } + else if (turnleft && !(turnright)) + { + cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[1])); + } + + if (analogjoystickmove && axis != 0) + { + // JOYAXISRANGE should be 1023 (divide by 1024) + cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10))); + } + + if (cv_mouseturn.value) + { + //THIS WORKS WTF???????? + cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8))); + } +} + // // G_BuildLocalTiccmd // extremely basic cut down ticcmd builder @@ -841,6 +894,16 @@ static void G_BuildLocalTiccmd(ticcmd_t *cmd, UINT8 ssplayer, boolean freecam) CHECKINPUT(gc_accelerate, AXISMOVE, BT_ACCELERATE); CHECKINPUT(gc_brake, AXISBRAKE, BT_BRAKE); + // for lua menus during spec + axis = JoyAxis(AXISAIM, ssplayer); + if (InputDown(gc_aimforward, ssplayer) || (usejoystick && axis < 0)) + cmd->buttons |= BT_FORWARD; + if (InputDown(gc_aimbackward, ssplayer) || (usejoystick && axis > 0)) + cmd->buttons |= BT_BACKWARD; + + G_HandleLocalDriftturn(cmd, ssplayer); + // + #undef CHECKINPUT moveinput = (InputDown(gc_turnleft, ssplayer) || InputDown(gc_turnright, ssplayer) @@ -898,22 +961,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) th = turnheld[forplayer]; rd = resetdown[forplayer]; - switch (ssplayer) - { - case 2: - G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); - break; - case 3: - G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1); - break; - case 4: - G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1); - break; - case 1: - default: - G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver - break; - } + memset(cmd, 0, sizeof(ticcmd_t)); // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. @@ -1164,6 +1212,27 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } } +ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) +{ + return M_Memcpy(dest, src, n*sizeof(*src)); +} + +ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) +{ + size_t i; + for (i = 0; i < n; i++) + { + dest[i].forwardmove = src[i].forwardmove; + dest[i].sidemove = src[i].sidemove; + dest[i].angleturn = SHORT(src[i].angleturn); + dest[i].aiming = (INT16)SHORT(src[i].aiming); + dest[i].buttons = (UINT16)SHORT(src[i].buttons); + dest[i].driftturn = (INT16)SHORT(src[i].driftturn); + dest[i].latency = (INT16)SHORT(src[i].latency); + } + return dest; +} + // // G_DoLoadLevel // @@ -1197,7 +1266,7 @@ static void G_DoLoadLevel(boolean resetplayer) } // Setup the level. - if (!P_SetupLevel(false,false)) + if (!P_SetupLevel(false, false)) { // fail so reset game stuff Command_ExitGame_f(); @@ -2357,23 +2426,23 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost) { if (nummapthings) { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_ERROR, "No player spawns found, spawning at the first mapthing!\n"); + } + spawnpoint = &mapthings[0]; } else { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); - //P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL. + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_ERROR, "No player spawns found, spawning at the origin!\n"); + //P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL. + } } } + P_MovePlayerToSpawn(playernum, spawnpoint); LUA_HookPlayer(&players[playernum], HOOK(PlayerSpawn)); // Lua hook for player spawning :) @@ -2385,11 +2454,11 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "No CTF starts in this map!\n"); + } + return NULL; } @@ -2397,11 +2466,11 @@ mapthing_t *G_FindCTFStart(INT32 playernum) { if (!numredctfstarts) { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("No Red Team starts in this map!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "No Red Team starts in this map!\n"); + } + return NULL; } @@ -2412,22 +2481,22 @@ mapthing_t *G_FindCTFStart(INT32 playernum) return redctfstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Red Team starts!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "Could not spawn at any Red Team starts!\n"); + } + return NULL; } else if (!players[playernum].ctfteam || players[playernum].ctfteam == 2) //blue { if (!numbluectfstarts) { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("No Blue Team starts in this map!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "No Blue Team starts in this map!\n"); + } + return NULL; } @@ -2437,11 +2506,12 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (G_CheckSpot(playernum, bluectfstarts[i])) return bluectfstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Blue Team starts!\n")); + + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "Could not spawn at any Blue Team starts!\n"); + } + return NULL; } //should never be reached but it gets stuff to shut up @@ -2460,19 +2530,20 @@ mapthing_t *G_FindMatchStart(INT32 playernum) if (G_CheckSpot(playernum, deathmatchstarts[i])) return deathmatchstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n")); + + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "Could not spawn at any Deathmatch starts!\n"); + } + return NULL; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("No Deathmatch starts in this map!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "No Deathmatch starts in this map!\n"); + } + return NULL; } @@ -2536,19 +2607,19 @@ mapthing_t *G_FindRaceStart(INT32 playernum) // Just spawn there. //return playerstarts[0]; - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Race starts!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "Could not spawn at any Race starts!\n"); + } + return NULL; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) - CONS_Alert(CONS_WARNING, M_GetText("No Race starts in this map!\n")); + if (P_IsLocalPlayerNum(playernum)) + { + CONS_Alert(CONS_WARNING, "No Race starts in this map!\n"); + } + return NULL; } @@ -3313,8 +3384,26 @@ void G_EndGame(void) } } - // 1100 or competitive multiplayer, so go back to title screen. - D_StartTitle(); + if (netgame) + { + G_SetGamestate(GS_WAITINGPLAYERS); // hack to prevent a command repeat + + if (server) + { + char mapname[6]; + + strlcpy(mapname, G_BuildMapName(spstage_start), sizeof (mapname)); + strlwr(mapname); + mapname[5] = '\0'; + + COM_BufAddText(va("map %s\n", mapname)); + } + + return; + } + + // Time to return to the menu. + Command_ExitGame_f(); } // diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c index 28b568c54..5dcbfb4cf 100644 --- a/src/hardware/hw_batching.c +++ b/src/hardware/hw_batching.c @@ -119,8 +119,38 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt polygonArray[polygonArraySize].texture = current_texture; polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target; polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + // default to maximum value so skybox ánd horizon lines come first + polygonArray[polygonArraySize].hash = INT32_MIN+polygonArraySize; polygonArraySize++; + if (!(PolyFlags & PF_NoTexture) && !horizonSpecial) + { + // use FNV-1a to hash polygons for later sorting. + INT32 hash = 0x811c9dc5; +#define DIGEST(h, x) h ^= (x); h *= 0x01000193 + if (current_texture) + { + DIGEST(hash, current_texture->downloaded); + } + + DIGEST(hash, PolyFlags); + DIGEST(hash, pSurf->PolyColor.rgba); + + if (cv_glshaders.value && gl_shadersavailable) + { + DIGEST(hash, shader_target); + DIGEST(hash, pSurf->TintColor.rgba); + DIGEST(hash, pSurf->FadeColor.rgba); + DIGEST(hash, pSurf->LightInfo.light_level); + DIGEST(hash, pSurf->LightInfo.fade_start); + DIGEST(hash, pSurf->LightInfo.fade_end); + DIGEST(hash, pSurf->LightInfo.directional); + } +#undef DIGEST + // remove the sign bit to ensure that skybox and horizon line comes first. + polygonArray[polygonArraySize-1].hash = (hash & INT32_MAX); + } + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); unsortedVertexArraySize += iNumPts; } @@ -346,52 +376,56 @@ void HWR_RenderBatches(void) { // check if a state change is required, set the change bools and next vars const PolygonArrayEntry *nextEntry = polygonArraySorted[polygonReadPos]; - nextShader = nextEntry->shader; - nextTexture = nextEntry->texture; - nextPolyFlags = nextEntry->polyFlags; - nextSurfaceInfo = nextEntry->surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - - if (currentShader != nextShader && HWR_UseShader()) + if (entry->hash != nextEntry->hash) { - changeState = true; - changeShader = true; - } + nextShader = nextEntry->shader; + nextTexture = nextEntry->texture; + nextPolyFlags = nextEntry->polyFlags; + nextSurfaceInfo = nextEntry->surf; - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - - if (HWR_UseShader()) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || - currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) + if (currentShader != nextShader && HWR_UseShader()) { changeState = true; - changeSurfaceInfo = true; + changeShader = true; } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + + if (currentTexture != nextTexture) { changeState = true; - changeSurfaceInfo = true; + changeTexture = true; + } + + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + + if (HWR_UseShader()) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end || + currentSurfaceInfo.LightInfo.directional != nextSurfaceInfo.LightInfo.directional) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } } } } diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h index 1f263d1df..984f0d159 100644 --- a/src/hardware/hw_batching.h +++ b/src/hardware/hw_batching.h @@ -31,6 +31,7 @@ typedef struct int shader; // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls boolean horizonSpecial; + INT32 hash; } PolygonArrayEntry; void HWR_StartBatching(void); diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index 89aa25751..ab2a133b7 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -70,7 +70,7 @@ static INT32 totalsubsecpolys = 0; static poly_t *HWR_AllocPoly(INT32 numpts) { poly_t *p; - size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts; + size_t size = sizeof(poly_t) + sizeof(polyvertex_t) * numpts; p = Z_Malloc(size, PU_HWRPLANE, NULL); p->numpts = numpts; return p; @@ -79,7 +79,7 @@ static poly_t *HWR_AllocPoly(INT32 numpts) static polyvertex_t *HWR_AllocVertex(void) { polyvertex_t *p; - size_t size = sizeof (polyvertex_t); + size_t size = sizeof(polyvertex_t); p = Z_Malloc(size, PU_HWRPLANE, NULL); return p; } @@ -175,9 +175,9 @@ static void SplitPoly (fdivline_t *bsp, //splitting parametric line INT32 ps = -1, pe = -1; INT32 nptfront, nptback; - polyvertex_t vs = {0,0,0}; - polyvertex_t ve = {0,0,0}; - polyvertex_t lastpv = {0,0,0}; + polyvertex_t vs = {}; + polyvertex_t ve = {}; + polyvertex_t lastpv = {}; float fracs = 0.0f, frace = 0.0f; //used to tell which poly is on // the front side of the bsp partition line INT32 psonline = 0, peonline = 0; @@ -349,8 +349,8 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly) INT32 i, j; polyvertex_t *pv; INT32 nump = 0, ps, pe; - polyvertex_t vs = {0, 0, 0}, ve = {0, 0, 0}, - p1 = {0, 0, 0}, p2 = {0, 0, 0}; + polyvertex_t vs = {}, ve = {}, + p1 = {}, p2 = {}; float fracs = 0.0f; fdivline_t cutseg; // x, y, dx, dy as start of node_t struct poly_t *temppoly; @@ -937,22 +937,10 @@ static void AdjustSegs(void) lseg->pv2 = pv; } - // recompute length - { - float x,y; - - const polyvertex_t *pv1 = (polyvertex_t *)lseg->pv1; - const polyvertex_t *pv2 = (polyvertex_t *)lseg->pv2; - - x = pv2->x - pv1->x + 0.5f; - y = pv2->y - pv1->y + 0.5f; - - lseg->flength = hypotf(x, y); - - // BP: debug see this kind of segs - //if (nearv2 > NEARDIST*NEARDIST || nearv1 > NEARDIST*NEARDIST) - // lseg->length = 1; - } + lseg->pv1->x2 = FloatToFixed(lseg->pv1->x); + lseg->pv1->y2 = FloatToFixed(lseg->pv1->y); + lseg->pv2->x2 = FloatToFixed(lseg->pv2->x); + lseg->pv2->y2 = FloatToFixed(lseg->pv2->y); } } } diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index d45d20887..d44ac4f82 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -881,11 +881,17 @@ static void HWR_CacheFlat(GLMipmap_t *glMipmap, lumpnum_t flatlumpnum) size_t steppy; #endif size_t size, pflatsize; + const char *flatname = W_CheckNameForNum(flatlumpnum); // setup the texture info glMipmap->format = GL_TEXFMT_P_8; glMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + if (UNLIKELY(memcmp(flatname, "GBA_RRF5", 8) == 0 && flatname[8] == 0)) + { + glMipmap->flags &= ~TF_CHROMAKEYED; + } + size = W_LumpLength(flatlumpnum); switch (size) @@ -913,8 +919,7 @@ static void HWR_CacheFlat(GLMipmap_t *glMipmap, lumpnum_t flatlumpnum) break; } - glMipmap->width = (UINT16)pflatsize; - glMipmap->height = (UINT16)pflatsize; + glMipmap->width = glMipmap->height = (UINT16)pflatsize; // the flat raw data needn't be converted with palettized textures W_ReadLump(flatlumpnum, Z_Malloc(size, PU_HWRCACHE, &glMipmap->data)); @@ -1386,8 +1391,7 @@ UINT32 HWR_GetLightTableID(extracolormap_t *colormap) // call become invalid and must not be used. void HWR_ClearLightTables(void) { - if (vid.glstate == VID_GL_LIBRARY_LOADED) - GL_ClearLightTables(); + GL_ClearLightTables(); } #endif //HWRENDER diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 1da42770a..7788dce53 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -19,7 +19,7 @@ #ifndef _HWR_DEFS_ #define _HWR_DEFS_ #include "../doomtype.h" -#include "../r_defs.h" +#include "../m_fixed.h" #define ZCLIP_PLANE 4.0f // Used for the actual game drawing #define NZCLIP_PLANE 0.9f // Seems to be only used for the HUD and screen textures @@ -95,9 +95,8 @@ typedef struct // a vertex of a Doom 'plane' polygon typedef struct { - float x; - float y; - float z; + float x, y, z; + fixed_t x2, y2, z2; } polyvertex_t; #ifdef _MSC_VER diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 04d388e81..1be176a42 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -40,7 +40,7 @@ typedef struct gl_vissprite_s boolean flip; UINT8 translucency; //alpha level 0-255 mobj_t *mobj; - boolean precip; // Tails 08-25-2002 + precipmobj_t *precip; // Tails 08-25-2002 boolean vflip; //Hurdler: 25/04/2000: now support colormap in hardware mode UINT8 *colormap; diff --git a/src/hardware/hw_main.cpp b/src/hardware/hw_main.cpp index 0e89f4138..9affc422f 100644 --- a/src/hardware/hw_main.cpp +++ b/src/hardware/hw_main.cpp @@ -66,7 +66,6 @@ // ========================================================================== #define ABS(x) ((x) < 0 ? -(x) : (x)) -#define SOFTLIGHT(llevel) HWR_ShouldUsePaletteRendering() ? ((llevel) >> LIGHTSEGSHIFT) << LIGHTSEGSHIFT : (llevel) // false if shaders have not been initialized yet, or if shaders are not available boolean gl_shadersavailable = false; @@ -413,8 +412,12 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col tint_color.rgba = (colormap != NULL) ? (UINT32)colormap->rgba : GL_DEFAULTMIX; fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; + // Shift the lightlevel for Palette rendering mode to replicate software´s limited 32 lightlevels + if (HWR_ShouldUsePaletteRendering()) + light_level = (light_level >> LIGHTSEGSHIFT) << LIGHTSEGSHIFT; + // Clamp the light level, since it can sometimes go out of the 0-255 range from animations - light_level = CLAMP(SOFTLIGHT(light_level), cv_secbright.value, 255); + light_level = CLAMP(light_level, cv_secbright.value, 255); // Crappy backup coloring if you can't do shaders if (!HWR_UseShader()) @@ -764,8 +767,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool if (line->pv1) { - x1 = ((polyvertex_t *)line->pv1)->x; - y1 = ((polyvertex_t *)line->pv1)->y; + x1 = line->pv1->x; + y1 = line->pv1->y; } else { @@ -774,8 +777,8 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool if (line->pv2) { - xd = ((polyvertex_t *)line->pv2)->x - x1; - yd = ((polyvertex_t *)line->pv2)->y - y1; + xd = line->pv2->x - x1; + yd = line->pv2->y - y1; } else { @@ -845,11 +848,11 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) M_ClearBox(segbbox); M_AddToBox(segbbox, - FloatToFixed(((polyvertex_t *)gl_curline->pv1)->x), - FloatToFixed(((polyvertex_t *)gl_curline->pv1)->y)); + FloatToFixed(gl_curline->pv1->x), + FloatToFixed(gl_curline->pv1->y)); M_AddToBox(segbbox, - FloatToFixed(((polyvertex_t *)gl_curline->pv2)->x), - FloatToFixed(((polyvertex_t *)gl_curline->pv2)->y)); + FloatToFixed(gl_curline->pv2->x), + FloatToFixed(gl_curline->pv2->y)); splat = (wallsplat_t *)gl_curline->linedef->splats; for (; splat; splat = splat->next) @@ -1124,8 +1127,8 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, // Found a break // The heights are clamped to ensure the polygon doesn't cross itself. - bot = CLAMP(bheight, realbot, top); - endbot = CLAMP(endbheight, endrealbot, endtop); + bot = std::max(bheight, realbot); + endbot = std::max(endbheight, endrealbot); Surf->PolyColor.s.alpha = alpha; @@ -1346,10 +1349,10 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (LIKELY(gl_curline->pv1)) { - vs.x = ((polyvertex_t *)gl_curline->pv1)->x; - vs.y = ((polyvertex_t *)gl_curline->pv1)->y; - v1x = FloatToFixed(vs.x); - v1y = FloatToFixed(vs.y); + vs.x = gl_curline->pv1->x; + vs.y = gl_curline->pv1->y; + v1x = gl_curline->pv1->x2; + v1y = gl_curline->pv1->y2; } else { @@ -1361,10 +1364,10 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (LIKELY(gl_curline->pv2)) { - ve.x = ((polyvertex_t *)gl_curline->pv2)->x; - ve.y = ((polyvertex_t *)gl_curline->pv2)->y; - v2x = FloatToFixed(ve.x); - v2y = FloatToFixed(ve.y); + ve.x = gl_curline->pv2->x; + ve.y = gl_curline->pv2->y; + v2x = gl_curline->pv2->x2; + v2y = gl_curline->pv2->y2; } else { @@ -1396,7 +1399,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // x offset the texture const fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; const float cliplow = (float)texturehpeg; - const float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); + const float cliphigh = (float)(texturehpeg + gl_curline->length); FUINT lightnum = gl_frontsector->lightlevel; extracolormap_t *colormap = gl_frontsector->extra_colormap; @@ -1906,6 +1909,19 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { for (rover = gl_backsector->ffloors; rover; rover = rover->next) { + boolean bothsides = false; + // Skip if it exists on both sectors. + ffloor_t * r2; + for (r2 = gl_frontsector->ffloors; r2; r2 = r2->next) + if (rover->master == r2->master) + { + bothsides = true; + break; + } + + if (bothsides) + continue; + const ffloortype_e roverflags = rover->flags; if (!(roverflags & FF_EXISTS) || !(roverflags & FF_RENDERSIDES) || (roverflags & FF_INVERTSIDES)) @@ -2057,6 +2073,17 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { for (rover = gl_frontsector->ffloors; rover; rover = rover->next) { + boolean bothsides = false; + // Skip if it exists on both sectors. + ffloor_t * r2; + for (r2 = gl_backsector->ffloors; r2; r2 = r2->next) + if (rover->master == r2->master) + { + bothsides = true; + break; + } + + if (bothsides) continue; const ffloortype_e roverflags = rover->flags; if (!(roverflags & FF_EXISTS) || !(roverflags & FF_RENDERSIDES) || !(roverflags & FF_ALLSIDES)) @@ -2201,8 +2228,8 @@ static boolean CheckClip(sector_t * afrontsector, sector_t * abacksector) if (LIKELY(gl_curline->pv1)) { - v1x = FloatToFixed(((polyvertex_t *)gl_curline->pv1)->x); - v1y = FloatToFixed(((polyvertex_t *)gl_curline->pv1)->y); + v1x = gl_curline->pv1->x2; + v1y = gl_curline->pv1->y2; } else { @@ -2212,8 +2239,8 @@ static boolean CheckClip(sector_t * afrontsector, sector_t * abacksector) if (LIKELY(gl_curline->pv2)) { - v2x = FloatToFixed(((polyvertex_t *)gl_curline->pv2)->x); - v2y = FloatToFixed(((polyvertex_t *)gl_curline->pv2)->y); + v2x = gl_curline->pv2->x2; + v2y = gl_curline->pv2->y2; } else { @@ -2429,8 +2456,8 @@ static void HWR_AddLine(seg_t *line) if (LIKELY(gl_curline->pv1)) { - v1x = FloatToFixed(((polyvertex_t *)gl_curline->pv1)->x); - v1y = FloatToFixed(((polyvertex_t *)gl_curline->pv1)->y); + v1x = gl_curline->pv1->x2; + v1y = gl_curline->pv1->y2; } else { @@ -2440,8 +2467,8 @@ static void HWR_AddLine(seg_t *line) if (LIKELY(gl_curline->pv2)) { - v2x = FloatToFixed(((polyvertex_t *)gl_curline->pv2)->x); - v2y = FloatToFixed(((polyvertex_t *)gl_curline->pv2)->y); + v2x = gl_curline->pv2->x2; + v2y = gl_curline->pv2->y2; } else { @@ -2558,7 +2585,9 @@ static boolean HWR_CheckBBox(const fixed_t *bspcoord) else // node mindist = 0; } - if (mindist > current_bsp_culling_distance) return false; + + if (mindist > current_bsp_culling_distance) + return false; } angle1 = R_PointToAngle64(px1, py1); @@ -3542,27 +3571,13 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts float basey, lowy; // do interpolation - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist(spr->mobj)) + if (precip) { - if (precip) - { - R_InterpolatePrecipMobjState((precipmobj_t *)spr->mobj, rendertimefrac, &interp); - } - else - { - R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp); - } + R_InterpolatePrecipMobjState(spr->precip, R_GetPrecipMobjTimeFrac(spr->precip), &interp); } else { - if (precip) - { - R_InterpolatePrecipMobjState((precipmobj_t *)spr->mobj, FRACUNIT, &interp); - } - else - { - R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp); - } + R_InterpolateMobjState(spr->mobj, R_GetMobjTimeFrac(spr->mobj), &interp); } if (!precip && P_MobjFlip(spr->mobj) == -1) // precip doesn't have eflags so they can't flip @@ -3816,8 +3831,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr, const boolean papersprite) // Found a break // The heights are clamped to ensure the polygon doesn't cross itself. - bot = CLAMP(bheight, realbot, top); - endbot = CLAMP(endbheight, endrealbot, endtop); + bot = std::max(bheight, realbot); + endbot = std::max(endbheight, endrealbot); wallVerts[3].t = towtop + ((realtop - top) * towmult); wallVerts[2].t = towtop + ((endrealtop - endtop) * towmult); @@ -4058,7 +4073,7 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) INT32 shader = SHADER_NONE; - const mobj_t *sprmo = spr->mobj; + const precipmobj_t *sprmo = spr->precip; if (UNLIKELY(!sprmo || !sprmo->subsector)) return; @@ -4106,7 +4121,7 @@ static void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { INT32 light; - light = R_GetPlaneLight(sector, sprmo->z + sprmo->height, false); // Always use the light at the top instead of whatever I was doing before + light = R_GetPlaneLight(sector, sprmo->z, false); // Always use the light at the top instead of whatever I was doing before if (!(sprmo->frame & FF_FULLBRIGHT)) lightlevel = static_cast(*sector->lightlist[light].lightlevel); @@ -4168,8 +4183,8 @@ static int CompareVisSprites(const void *p1, const void *p2) // "boolean to int" // check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer - const int transparency1 = (!spr1->precip && (spr1->mobj->flags2 & MF2_SHADOW)) || (spr1->mobj->frame & FF_TRANSMASK); - const int transparency2 = (!spr2->precip && (spr2->mobj->flags2 & MF2_SHADOW)) || (spr2->mobj->frame & FF_TRANSMASK); + const int transparency1 = (spr1->precip ? (spr1->precip->frame & FF_TRANSMASK) : ((spr1->mobj->flags2 & MF2_SHADOW)) || (spr1->mobj->frame & FF_TRANSMASK)); + const int transparency2 = (spr2->precip ? (spr2->precip->frame & FF_TRANSMASK) : ((spr2->mobj->flags2 & MF2_SHADOW)) || (spr2->mobj->frame & FF_TRANSMASK)); idiff = transparency1 - transparency2; if (idiff != 0) return idiff; @@ -4685,14 +4700,7 @@ static void HWR_ProjectSprite(mobj_t *thing) // uncapped/interpolation interpmobjstate_t interp = {}; - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist(thing)) - { - R_InterpolateMobjState(thing, rendertimefrac, &interp); - } - else - { - R_InterpolateMobjState(thing, FRACUNIT, &interp); - } + R_InterpolateMobjState(thing, R_GetMobjTimeFrac(thing), &interp); if (interp.spritexscale < 1 || interp.spriteyscale < 1) return; @@ -5008,7 +5016,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->vflip = vflip; - vis->precip = false; + vis->precip = NULL; } // Precipitation projector for hardware mode @@ -5040,21 +5048,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) interpmobjstate_t interp = {}; // do interpolation - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist((mobj_t*)thing)) - { - R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp); - } - else - { - R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp); - } - - // Visibility check by the blend mode. - if (thing->frame & FF_TRANSMASK) - { - if (!R_BlendLevelVisible(thing->blendmode, (thing->frame & FF_TRANSMASK)>>FF_TRANSSHIFT)) - return; - } + R_InterpolatePrecipMobjState(thing, R_GetPrecipMobjTimeFrac(thing), &interp); // transform the origin point tr_x = FixedToFloat(interp.x); @@ -5132,7 +5126,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST vis->gpatch = (patch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); vis->flip = flip; - vis->mobj = (mobj_t *)thing; + vis->mobj = NULL; vis->colormap = NULL; @@ -5145,7 +5139,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gzt = FixedToFloat(interp.z) + (FixedToFloat(spritecachedinfo[lumpoff].topoffset) * this_scale); vis->gz = vis->gzt - (FixedToFloat(spritecachedinfo[lumpoff].height) * this_scale); - vis->precip = true; + vis->precip = thing; } @@ -6042,7 +6036,7 @@ static void HWR_DoPostProcessor(player_t *player) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; - float disStart = (leveltime-1) + FixedToFloat(rendertimefrac); + float disStart = (leveltime-1) + FixedToFloat(R_GetTimeFrac(RTF_LEVEL)); UINT8 x, y; INT32 WAVELENGTH; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 2f4b341ed..94b24b25e 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1176,6 +1176,8 @@ void HWR_DrawMD2(gl_vissprite_t *spr) // Look at HWR_ProjectSprite for more { + md2_t *md2s; + int skinnum; patch_t *gpatch, *blendgpatch; GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL; INT32 durs = spr->mobj->state->tics; @@ -1188,16 +1190,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr) spriteinfo_t *sprinfo; interpmobjstate_t interp; - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist(spr->mobj)) - { - R_InterpolateMobjState(spr->mobj, rendertimefrac, &interp); - } - else - { - R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp); - } - md2_t *md2s; - int skinnum; + R_InterpolateMobjState(spr->mobj, R_GetMobjTimeFrac(spr->mobj), &interp); // Apparently people don't like jump frames like that, so back it goes //if (tics > durs) @@ -1375,7 +1368,7 @@ void HWR_DrawMD2(gl_vissprite_t *spr) #ifdef USE_MODEL_NEXTFRAME // Interpolate the model interpolation. (lol) - tics -= FixedToFloat(rendertimefrac); + tics -= FixedToFloat(R_GetTimeFrac(RTF_LEVEL)); if (cv_glmdls.value == 1 && tics <= durs) { diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 3a903a9af..8947e99c3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -27,6 +27,8 @@ #if defined (HWRENDER) && !defined (NOROPENGL) +#include "../../r_fps.h" // For R_GetTimeFrac, used for the leveltime shader uniform + #include "r_opengl.h" #include "r_vbo.h" @@ -889,7 +891,7 @@ void GL_SetShaderInfo(hwdshaderinfo_t info, INT32 value) switch (info) { case HWD_SHADERINFO_LEVELTIME: - shader_leveltime = (((float)(value-1)) + FIXED_TO_FLOAT(rendertimefrac)) / TICRATE; + shader_leveltime = (((float)(value-1)) + FIXED_TO_FLOAT(R_GetTimeFrac(RTF_LEVEL))) / TICRATE; break; case HWD_SHADERINFO_LIGHT_X: shader_light_x = FixedToFloat(value); diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 062abd0d2..df130d020 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -943,7 +943,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // before we do anything, let's verify the guy isn't spamming, get this easier on us. - //if (stop_spamming[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY)) if (stop_spamming[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & HU_CSAY)) { CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]); @@ -1039,6 +1038,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(adminchar) + 1, PU_STATIC, NULL); else if (IsPlayerAdmin(playernum)) tempchar = (char *)Z_Calloc(strlen(cstart) + strlen(remotechar) + 1, PU_STATIC, NULL); + if (tempchar) { if (playernum == serverplayer) @@ -1073,17 +1073,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } else // To everyone or sayteam, it doesn't change anything. fmt2 = "%s<%s%s%s>\x80 %s%s"; - /*else // To your team - { - if (players[playernum].ctfteam == 1) // red - prefix = "\x85[TEAM]"; - else if (players[playernum].ctfteam == 2) // blue - prefix = "\x84[TEAM]"; - else - prefix = "\x83"; // makes sure this doesn't implode if you sayteam on non-team gamemodes - - fmt2 = "%s<%s%s>\x80%s %s%s"; - }*/ HU_AddChatText(va(fmt2, prefix, cstart, dispname, cend, textcolor, msg), cv_chatnotifications.value); // add to chat @@ -1847,12 +1836,6 @@ static void HU_DrawChat(void) if (teamtalk) { talk = ttalk; -#if 0 - if (players[consoleplayer].ctfteam == 1) - t = 0x500; // Red - else if (players[consoleplayer].ctfteam == 2) - t = 0x400; // Blue -#endif } if (CHAT_MUTE) @@ -2049,6 +2032,7 @@ static void HU_DrawChat(void) V_DrawSmallString(chatx + boxw + 4, p_dispy - (6*count), V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, va("\x82%d\x80 - %s", i, player_names[i])); count++; } + if (count == 0) // no results. { V_DrawFillConsoleMap(chatx + boxw + 2, p_dispy - (6*count), 48, 6, 239 | V_SNAPTOBOTTOM | V_SNAPTOLEFT); // fill it like the chat so the text doesn't become hard to read because of the hud. @@ -2304,7 +2288,7 @@ static void HU_DrawSongCreditsBox(void) INT32 t = cursongcredit.anim; INT32 bgt; - fixed_t interpoffset = FixedMul(BOXCREDITHEIGHT*dup*FRACUNIT/(TICRATE/2), R_GetHudUncap()); + fixed_t interpoffset = FixedMul(BOXCREDITHEIGHT*dup*FRACUNIT/(TICRATE/2), R_GetTimeFrac(RTF_MENU)); if (t > BOXCREDITSLIDEIN) { diff --git a/src/i_system.h b/src/i_system.h index b26db7a82..bef997acf 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -91,27 +91,6 @@ void I_GetEvent(void); */ void I_OsPolling(void); -// Either returns a null ticcmd, -// or calls a loadable driver to build it. -// This ticcmd will then be modified by the gameloop -// for normal input. - -/** \brief Input for the first player -*/ -ticcmd_t *I_BaseTiccmd(void); - -/** \brief Input for the second player -*/ -ticcmd_t *I_BaseTiccmd2(void); - -/** \brief Input for the third player -*/ -ticcmd_t *I_BaseTiccmd3(void); - -/** \brief Input for the fourth player -*/ -ticcmd_t *I_BaseTiccmd4(void); - /** \brief Called by M_Responder when quit is selected, return exit code 0 */ void I_Quit(void) FUNCNORETURN; diff --git a/src/i_video.h b/src/i_video.h index d9bb9e1ce..7850d664a 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -24,6 +24,8 @@ extern "C" { #pragma interface #endif +void I_SetTextInput(void); + typedef enum { /// Software diff --git a/src/info.c b/src/info.c index faf52b057..f7e0306da 100644 --- a/src/info.c +++ b/src/info.c @@ -20176,73 +20176,3 @@ void P_PatchInfoTables(void) for (i = MT_FIRSTFREESLOT; i <= MT_LASTFREESLOT; i++) mobjinfo[i].doomednum = -1; } - -#ifdef ALLOW_RESETDATA -static char *sprnamesbackup; -static state_t *statesbackup; -static mobjinfo_t *mobjinfobackup; -static size_t sprnamesbackupsize, statesbackupsize, mobjinfobackupsize; -#endif - -void P_BackupTables(void) -{ -#ifdef ALLOW_RESETDATA - // Allocate buffers in size equal to that of the uncompressed data to begin with - sprnamesbackup = Z_Malloc(sizeof(sprnames), PU_STATIC, NULL); - statesbackup = Z_Malloc(sizeof(states), PU_STATIC, NULL); - mobjinfobackup = Z_Malloc(sizeof(mobjinfo), PU_STATIC, NULL); - - // Sprite names - sprnamesbackupsize = lzf_compress(sprnames, sizeof(sprnames), sprnamesbackup, sizeof(sprnames)); - if (sprnamesbackupsize > 0) - sprnamesbackup = Z_Realloc(sprnamesbackup, sprnamesbackupsize, PU_STATIC, NULL); - else - M_Memcpy(sprnamesbackup, sprnames, sizeof(sprnames)); - - // States - statesbackupsize = lzf_compress(states, sizeof(states), statesbackup, sizeof(states)); - if (statesbackupsize > 0) - statesbackup = Z_Realloc(statesbackup, statesbackupsize, PU_STATIC, NULL); - else - M_Memcpy(statesbackup, states, sizeof(states)); - - // Mobj info - mobjinfobackupsize = lzf_compress(mobjinfo, sizeof(mobjinfo), mobjinfobackup, sizeof(mobjinfo)); - if (mobjinfobackupsize > 0) - mobjinfobackup = Z_Realloc(mobjinfobackup, mobjinfobackupsize, PU_STATIC, NULL); - else - M_Memcpy(mobjinfobackup, mobjinfo, sizeof(mobjinfo)); -#endif -} - -void P_ResetData(INT32 flags) -{ -#ifndef ALLOW_RESETDATA - (void)flags; - CONS_Alert(CONS_NOTICE, M_GetText("P_ResetData(): not supported in this build.\n")); -#else - if (flags & 1) - { - if (sprnamesbackupsize > 0) - lzf_decompress(sprnamesbackup, sprnamesbackupsize, sprnames, sizeof(sprnames)); - else - M_Memcpy(sprnames, sprnamesbackup, sizeof(sprnamesbackup)); - } - - if (flags & 2) - { - if (statesbackupsize > 0) - lzf_decompress(statesbackup, statesbackupsize, states, sizeof(states)); - else - M_Memcpy(states, statesbackup, sizeof(statesbackup)); - } - - if (flags & 4) - { - if (mobjinfobackupsize > 0) - lzf_decompress(mobjinfobackup, mobjinfobackupsize, mobjinfo, sizeof(mobjinfo)); - else - M_Memcpy(mobjinfo, mobjinfobackup, sizeof(mobjinfobackup)); - } -#endif -} diff --git a/src/info.h b/src/info.h index 69a0a9dcf..4ee851cee 100644 --- a/src/info.h +++ b/src/info.h @@ -5147,8 +5147,4 @@ extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; void P_PatchInfoTables(void); -void P_BackupTables(void); - -void P_ResetData(INT32 flags); - #endif diff --git a/src/k_hud.c b/src/k_hud.c index 56843ca25..f433edcdd 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1073,7 +1073,7 @@ static void K_initKartHUD(void) // K_GetScreenCoords needs the right view* variables R_SetViewContext(stplyrnum); - R_InterpolateView(rendertimefrac_unpaused, !cv_uncappedhud.value); + R_InterpolateView(R_GetTimeFrac(RTF_CAMERA), !cv_uncappedhud.value); } UINT8 K_GetHudColor(void) @@ -1089,6 +1089,11 @@ boolean K_UseColorHud(void) return (cv_colorizedhud.value && clr_hud); } +// Since all our extra Saturn things are in optional files +// we gotta do a bunch of extra checks to determine +// if the according Assets are actually loaded +// see D_CheckSaturnExtraFiles in d_main.c + enum { SPEEDO_VANILLA, @@ -1175,7 +1180,7 @@ boolean K_UseHighResPortraits(void) return (cv_highresportrait.value && K_IsHighResolution()); } -// returns the players faceprefix +// returns the players faceprefix patch // accounts for localskins patch_t *K_GetFacePrefix(player_t *player, INT32 skinnum) { @@ -1766,7 +1771,7 @@ static void K_drawKartItem(void) if (cv_fancyroulette.value && stplyr->kartstuff[k_itemroulette] && !stplyr->deadtimer) { - fixed_t frac = R_GetHudUncap(); + fixed_t frac = R_GetTimeFrac(RTF_LEVEL); UINT8 fancystep = (offset ? 6 : 10); fixed_t fancyoffset = (stplyr->kartstuff[k_itemroulette] % 3)-1; @@ -2490,8 +2495,9 @@ static void K_DrawDialSpeedometer(fixed_t speed, const UINT8 infoidx = (infoactive) ? 1 : 0; patch_t* dialpatch; + const fixed_t spd = FixedDiv(speed, divisor); const angle_t speedangle = - FixedAngle(((min(135 * FRACUNIT, FixedDiv(speed, divisor)) - (45 * FRACUNIT)))); + FixedAngle(((min(135 * FRACUNIT, spd) - (45 * FRACUNIT)))); rot = R_GetRollAngle(speedangle); @@ -2824,7 +2830,7 @@ static void K_drawKartBumpersOrKarma(void) } } -#define lerp(from, to) cv_uncappedhud.value ? from + FixedMul(rendertimefrac, to - from) : to +#define lerp(from, to) cv_uncappedhud.value ? from + FixedMul(R_GetTimeFrac(RTF_LEVEL), to - from) : to // converts mobj coordinates into screen coordinates // NOTE: use with V_NOSCALESTART! @@ -3502,7 +3508,7 @@ static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 fixed_t amnumxpos, amnumypos; INT32 amxpos, amypos; fixed_t scale = FRACUNIT; - patch_t *AutomapPic; + patch_t *AutomapPic = NULL; INT16 w, h; AutomapPic = minimapinfo.minimap_pic; @@ -3559,7 +3565,6 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags) INT32 amxpos, amypos, wntdamxpos, wntdamypos; fixed_t scale = FRACUNIT; patch_t *minimaphead = NULL; - boolean minihead = K_useSmallMinimapHead(mo->player); #ifdef ROTSPRITE angle_t rollangle = 0; @@ -3569,6 +3574,9 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags) skin = K_GetMobjSkin(mo); minimaphead = (skinlocal ? localfacemmapprefix : facemmapprefix)[K_GetMobjSkinNum(skin, skinlocal)]; + if (minimaphead == NULL) + return; + amnumxpos = (FixedMul(lerp(mo->old_x, mo->x), minimapinfo.zoom) - minimapinfo.offs_x); amnumypos = -(FixedMul(lerp(mo->old_y, mo->y), minimapinfo.zoom) - minimapinfo.offs_y); @@ -3583,6 +3591,7 @@ static void K_drawKartMinimapHead(mobj_t *mo, INT32 x, INT32 y, INT32 flags) V_DrawCenteredSmallStringAtFixed(amxpos + (4*FRACUNIT), amypos - (3*FRACUNIT), V_ALLOWLOWERCASE|flags|V_SkinColorToHighlightcolor(mo->color), player_names[player - players]); } + const boolean minihead = K_useSmallMinimapHead(mo->player); // thx wanted reticle for having weird offsets very cool wntdamxpos = minihead ? amxpos + (1<width<kartstuff[k_cardanimation])< x ? xval : x))/TICRATE; + x = (FixedMul(((TICRATE - stplyr->kartstuff[k_cardanimation])< x ? xval : x))/TICRATE; if (splitscreen && stplyrnum == 1) x = -x; @@ -3893,7 +3902,8 @@ static void K_drawBattleFullscreen(void) // fill in the fractional bits if (cardanim && cardanim != 164*FRACUNIT) { - INT32 frac = R_GetHudUncap() * ((164 - stplyr->kartstuff[k_cardanimation])/8 + 1); + INT32 frac = R_GetTimeFrac(RTF_LEVEL) * ((164 - stplyr->kartstuff[k_cardanimation])/8 + 1); + if (stplyr->exiting) cardanim += frac; else @@ -3997,7 +4007,6 @@ static void K_drawBattleFullscreen(void) else V_DrawFixedPatch(x<kartstuff[k_comebacktimer]/TICRATE)); } } @@ -4190,7 +4199,7 @@ static void K_drawInput(void) if (timeinmap < 113) { INT32 count = ((INT32)(timeinmap) - 105); - INT32 frac = count > 0 && count < 6 ? R_GetHudUncap() << (FRACBITS - count - 11) : 0; + INT32 frac = count > 0 && count < 6 ? R_GetTimeFrac(RTF_LEVEL) << (FRACBITS - count - 11) : 0; offs = 64*FRACUNIT; while (count-- > 0) @@ -4380,8 +4389,8 @@ static void K_drawLapStartAnim(void) UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, K_GetHudColor(), GTC_CACHE); INT32 vflags = V_SNAPTOTOP|V_HUDTRANS; - fixed_t slideout = max(0, 32*(((progress - 76)*FRACUNIT) + R_GetHudUncap())); - fixed_t slidein = max(0, 32*(((stplyr->kartstuff[k_lapanimation] - 76)*FRACUNIT) - R_GetHudUncap())); + fixed_t slideout = max(0, 32*(((progress - 76)*FRACUNIT) + R_GetTimeFrac(RTF_LEVEL))); + fixed_t slidein = max(0, 32*(((stplyr->kartstuff[k_lapanimation] - 76)*FRACUNIT) - R_GetTimeFrac(RTF_LEVEL))); // First, draw the emblem and hand INT32 emblemx = (BASEVIDWIDTH << (FRACBITS - 1)) + slidein; @@ -4392,7 +4401,7 @@ static void K_drawLapStartAnim(void) INT32 hand = stplyr->kartstuff[k_laphand]; if (hand >= 1 && hand <= 3) { - y += 4*FRACUNIT - abs((int)(leveltime % 8)*FRACUNIT + R_GetHudUncap() - 4*FRACUNIT); + y += 4*FRACUNIT - abs((int)(leveltime % 8)*FRACUNIT + R_GetTimeFrac(RTF_LEVEL) - 4*FRACUNIT); V_DrawFixedPatch(emblemx, y, FRACUNIT, vflags, kp_lapanim_hand[hand - 1], NULL); } @@ -4718,7 +4727,7 @@ void K_drawKartHUD(void) if (timeinmap < 113) { INT32 count = ((INT32)(timeinmap) - 104); - INT32 frac = count > 0 ? R_GetHudUncap() << max(0, FRACBITS - count - 9) : 0; + INT32 frac = count > 0 ? R_GetTimeFrac(RTF_LEVEL) << max(0, FRACBITS - count - 9) : 0; offs = 256*FRACUNIT; while (count-- > 0) diff --git a/src/k_kart.c b/src/k_kart.c index a699c5603..c94cc7904 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2920,6 +2920,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) mobj_t *dust; mobj_t *truc; INT32 speed, speed2; + fixed_t rand_x, rand_y, rand_z; INT32 i, radius, height; mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); @@ -2942,9 +2943,11 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) dust->scalespeed = source->scale/12; P_InstaThrust(dust, dust->angle, FixedMul(20*FRACUNIT, source->scale)); - truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, - source->y + P_RandomRange(-radius, radius)*FRACUNIT, - source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMEXPLODE); + rand_z = source->z + P_RandomRange(0, height)*FRACUNIT; + rand_y = source->y + P_RandomRange(-radius, radius)*FRACUNIT; + rand_x = source->x + P_RandomRange(-radius, radius)*FRACUNIT; + + truc = P_SpawnMobj(rand_x, rand_y, rand_z, MT_BOOMEXPLODE); K_MatchGenericExtraFlags(truc, source); P_SetScale(truc, source->scale); truc->destscale = source->scale*6; @@ -2961,9 +2964,11 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) for (i = 0; i < 16; i++) { - dust = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, - source->y + P_RandomRange(-radius, radius)*FRACUNIT, - source->z + P_RandomRange(0, height)*FRACUNIT, MT_SMOKE); + rand_z = source->z + P_RandomRange(0, height)*FRACUNIT; + rand_y = source->y + P_RandomRange(-radius, radius)*FRACUNIT; + rand_x = source->x + P_RandomRange(-radius, radius)*FRACUNIT; + + dust = P_SpawnMobj(rand_x, rand_y, rand_z, MT_SMOKE); P_SetMobjState(dust, S_OPAQUESMOKE1); P_SetScale(dust, source->scale); dust->destscale = source->scale*10; @@ -2971,9 +2976,11 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) dust->tics = 30; dust->momz = P_RandomRange(FixedMul(3*FRACUNIT, source->scale)>>FRACBITS, FixedMul(7*FRACUNIT, source->scale)>>FRACBITS)*FRACUNIT; - truc = P_SpawnMobj(source->x + P_RandomRange(-radius, radius)*FRACUNIT, - source->y + P_RandomRange(-radius, radius)*FRACUNIT, - source->z + P_RandomRange(0, height)*FRACUNIT, MT_BOOMPARTICLE); + rand_z = source->z + P_RandomRange(0, height)*FRACUNIT; + rand_y = source->y + P_RandomRange(-radius, radius)*FRACUNIT; + rand_x = source->x + P_RandomRange(-radius, radius)*FRACUNIT; + + truc = P_SpawnMobj(rand_x, rand_y, rand_z, MT_BOOMPARTICLE); K_MatchGenericExtraFlags(truc, source); P_SetScale(truc, source->scale); truc->destscale = source->scale*5; @@ -3630,9 +3637,13 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) else aoff += ANGLE_45; - dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS), - mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS), - mo->z, MT_WIPEOUTTRAIL); + fixed_t rand_x; + fixed_t rand_y; + + rand_y = mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS); + rand_x = mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)) + (P_RandomRange(-8,8) << FRACBITS); + + dust = P_SpawnMobj(rand_x, rand_y, mo->z, MT_WIPEOUTTRAIL); P_SetTarget(&dust->target, mo); dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy); @@ -4878,7 +4889,9 @@ static void K_MoveHeldObjects(player_t *player) mobj_t *cur = player->mo->hnext; mobj_t *targ = player->mo; - if (P_IsObjectOnGround(player->mo) && player->speed > 0) + const boolean ponground = P_IsObjectOnGround(player->mo); + + if (ponground && player->speed > 0) player->kartstuff[k_bananadrag]++; while (!P_MobjWasRemoved(cur)) @@ -4935,13 +4948,18 @@ static void K_MoveHeldObjects(player_t *player) targz -= 8*(2*FRACUNIT)/7; }*/ - if (cv_bananajitter.value && P_IsObjectOnGround(player->mo) && player->speed > 0 && player->kartstuff[k_bananadrag] > TICRATE - && M_RandomChance(min(FRACUNIT/2, FixedDiv(player->speed, K_GetKartSpeed(player, false))/2))) + if (cv_bananajitter.value && ponground + && player->speed > 0 && player->kartstuff[k_bananadrag] > TICRATE) { - if (leveltime & 1) - cur->spriteyoffset += 8*(2*FRACUNIT)/7; - else - cur->spriteyoffset -= 8*(2*FRACUNIT)/7; + const fixed_t halfpspeed = FixedDiv(player->speed, K_GetKartSpeed(player, false))/2; + + if (M_RandomChance(min(FRACUNIT/2, halfpspeed))) + { + if (leveltime & 1) + cur->spriteyoffset += 8*(2*FRACUNIT)/7; + else + cur->spriteyoffset -= 8*(2*FRACUNIT)/7; + } } if (speed > dist) @@ -5419,10 +5437,15 @@ FUNCINLINE static ATTRINLINE void K_SpawnNormalSpeedLines(player_t *player, bool { randomFunc randomfunc = synched ? P_RandomRange : M_RandomRange; - mobj_t *fast = P_SpawnMobj(player->mo->x + (randomfunc(-36,36) * player->mo->scale), - player->mo->y + (randomfunc(-36,36) * player->mo->scale), - player->mo->z + (player->mo->height/2) + (randomfunc(-20,20) * player->mo->scale), - MT_FASTLINE); + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = player->mo->z + (player->mo->height/2) + (randomfunc(-20,20) * player->mo->scale); + rand_y = player->mo->y + (randomfunc(-36,36) * player->mo->scale); + rand_x = player->mo->x + (randomfunc(-36,36) * player->mo->scale); + + mobj_t *fast = P_SpawnMobj(rand_x, rand_y, rand_z, MT_FASTLINE); fast->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); fast->momx = 3*player->mo->momx/4; @@ -6029,14 +6052,27 @@ static void K_KartDrift(player_t *player, boolean onground) if (player->speed > minspeed*2) player->kartstuff[k_getsparks] = 1; + const boolean driftblue = (player->kartstuff[k_driftcharge] < dsone && player->kartstuff[k_driftcharge]+driftadditive >= dsone); + const boolean driftred = (player->kartstuff[k_driftcharge] < dstwo && player->kartstuff[k_driftcharge]+driftadditive >= dstwo); + const boolean driftrainbow = (player->kartstuff[k_driftcharge] < dsthree && player->kartstuff[k_driftcharge]+driftadditive >= dsthree); + // Sound whenever you get a different tier of sparks - if ((player->kartstuff[k_driftcharge] < dsone && player->kartstuff[k_driftcharge]+driftadditive >= dsone) - || (player->kartstuff[k_driftcharge] < dstwo && player->kartstuff[k_driftcharge]+driftadditive >= dstwo) - || (player->kartstuff[k_driftcharge] < dsthree && player->kartstuff[k_driftcharge]+driftadditive >= dsthree)) + if (driftblue + || driftred + || driftrainbow) { //S_StartSound(player->mo, sfx_s3ka2); if (P_IsLocalPlayer(player)) // UGHGHGH... + { S_StartSoundAtVolume(player->mo, sfx_s3ka2, 192); // Ugh... + } + + if (driftrainbow) + player->driftlevel = 3; + else if (driftred) + player->driftlevel = 2; + else if (driftblue) + player->driftlevel = 1; player->driftsparkGrowTimer = DRIFTSPARKGROWTICS; } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 059df924c..fb2b7a36f 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -126,6 +126,7 @@ static int lib_chatprintf(lua_State *L) plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); // retrieve player if (!plr) return LUA_ErrInvalid(L, "player_t"); + if (plr != &players[consoleplayer]) return 0; @@ -236,7 +237,7 @@ static int lib_pRandomChance(lua_State *L) // P_MAPUTIL /////////////// -static int lib_pAproxDistance(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_pAproxDistance(lua_State *L) { fixed_t dx = luaL_checkfixed(L, 1); fixed_t dy = luaL_checkfixed(L, 2); @@ -1110,19 +1111,10 @@ static int lib_pCheckSight(lua_State *L) //HUDSAFE? if (!t1 || !t2) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_CheckSight(t1, t2)); - return 1; -} - -// DONT USE THIS FOR ANYTHING GAMEPLAY, THIS WILL DESYNCH! -static int lib_pCheckSightFast(lua_State *L) -{ - mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - //HUDSAFE? - if (!t1 || !t2) - return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_CheckSightFast(t1, t2)); + if (hud_running) + lua_pushboolean(L, P_CheckSightFast(t1, t2)); + else + lua_pushboolean(L, P_CheckSight(t1, t2)); return 1; } @@ -1643,7 +1635,7 @@ static int lib_evCrumbleChain(lua_State *L) // P_SLOPES //////////// -static int lib_pGetZAt(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_pGetZAt(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); fixed_t x = luaL_checkfixed(L, 2); @@ -1659,7 +1651,7 @@ static int lib_pGetZAt(lua_State *L) // R_DEFS //////////// -static int lib_rPointToAngle(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_rPointToAngle(lua_State *L) { fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); @@ -1668,7 +1660,7 @@ static int lib_rPointToAngle(lua_State *L) return 1; } -static int lib_rPointToAngle2(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_rPointToAngle2(lua_State *L) { fixed_t px2 = luaL_checkfixed(L, 1); fixed_t py2 = luaL_checkfixed(L, 2); @@ -1679,7 +1671,7 @@ static int lib_rPointToAngle2(lua_State *L) return 1; } -static int lib_rPointToDist(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_rPointToDist(lua_State *L) { fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); @@ -1688,7 +1680,7 @@ static int lib_rPointToDist(lua_State *L) return 1; } -static int lib_rPointToDist2(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_rPointToDist2(lua_State *L) { fixed_t px2 = luaL_checkfixed(L, 1); fixed_t py2 = luaL_checkfixed(L, 2); @@ -1699,12 +1691,15 @@ static int lib_rPointToDist2(lua_State *L) return 1; } -static int lib_rPointInSubsector(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_rPointInSubsector(lua_State *L) { fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); //HUDSAFE - LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR); + if (hud_running) + LUA_PushUserdata(L, R_PointInSubsectorFast(x, y), META_SUBSECTOR); + else + LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR); return 1; } @@ -3180,7 +3175,6 @@ static luaL_Reg lib[] = { {"P_SlideMove",lib_pSlideMove}, {"P_BounceMove",lib_pBounceMove}, {"P_CheckSight", lib_pCheckSight}, - {"P_CheckSightFast", lib_pCheckSightFast}, {"P_CheckHoopPosition",lib_pCheckHoopPosition}, {"P_RadiusAttack",lib_pRadiusAttack}, {"P_FloorzAtPos",lib_pFloorzAtPos}, diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index e1e246d28..36c3a6c45 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -136,6 +136,7 @@ void COM_Lua_f(void) lua_pop(gL, 1); // pop command info table return; // can't execute splitscreen command without player 2! } + playernum = displayplayers[1]; } diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 98c873a1a..28055ffeb 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -393,7 +393,7 @@ FUNCINLINE static ATTRINLINE boolean prepare_string_hook return false; } -static boolean prepare_hud_hook +FUNCINLINE static ATTRINLINE boolean prepare_hud_hook ( Hook_State * hook, int hook_type diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index c33b2fca1..c6dbd97d2 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -239,7 +239,7 @@ static int lib_getHudInfo(lua_State *L) return 1; } -static int lib_hudinfolen(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_hudinfolen(lua_State *L) { lua_pushinteger(L, NUMHUDITEMS); return 1; @@ -281,14 +281,14 @@ static int hudinfo_set(lua_State *L) return 0; } -static int hudinfo_num(lua_State *L) +FUNCINLINE static ATTRINLINE int hudinfo_num(lua_State *L) { hudinfo_t *info = *((hudinfo_t **)luaL_checkudata(L, 1, META_HUDINFO)); lua_pushinteger(L, info-hudinfo); return 1; } -static int colormap_get(lua_State *L) +FUNCINLINE static ATTRINLINE int colormap_get(lua_State *L) { return luaL_error(L, "colormap is not a struct."); } @@ -327,7 +327,7 @@ static int patch_get(lua_State *L) return 1; } -static int patch_set(lua_State *L) +FUNCINLINE static ATTRINLINE int patch_set(lua_State *L) { return luaL_error(L, LUA_QL("patch_t") " struct cannot be edited by Lua."); } @@ -395,14 +395,14 @@ static int camera_get(lua_State *L) // lib_draw // -static int libd_patchExists(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_patchExists(lua_State *L) { HUDONLY lua_pushboolean(L, W_LumpExists(luaL_checkstring(L, 1))); return 1; } -static int libd_cachePatch(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_cachePatch(lua_State *L) { HUDONLY LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); @@ -1066,14 +1066,14 @@ static int libd_getColorHudPatch(lua_State *L) return 2; } -static int libd_getHudColor(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_getHudColor(lua_State *L) { HUDONLY lua_pushinteger(L, K_GetHudColor()); return 1; } -static int libd_useColorHud(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_useColorHud(lua_State *L) { HUDONLY lua_pushboolean(L, K_UseColorHud()); @@ -1081,21 +1081,21 @@ static int libd_useColorHud(lua_State *L) } -static int libd_width(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_width(lua_State *L) { HUDONLY lua_pushinteger(L, vid.width); // push screen width return 1; } -static int libd_height(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_height(lua_State *L) { HUDONLY lua_pushinteger(L, vid.height); // push screen height return 1; } -static int libd_dupx(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_dupx(lua_State *L) { HUDONLY lua_pushinteger(L, vid.dupx); // push integral scale (patch scale) @@ -1103,7 +1103,7 @@ static int libd_dupx(lua_State *L) return 2; } -static int libd_dupy(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_dupy(lua_State *L) { HUDONLY lua_pushinteger(L, vid.dupy); // push integral scale (patch scale) @@ -1111,7 +1111,7 @@ static int libd_dupy(lua_State *L) return 2; } -static int libd_renderer(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_renderer(lua_State *L) { HUDONLY switch (rendermode) { @@ -1124,7 +1124,7 @@ static int libd_renderer(lua_State *L) // 30/10/18 Lat': Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int // Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn -static int libd_getlocaltransflag(lua_State *L) +FUNCINLINE static ATTRINLINE int libd_getlocaltransflag(lua_State *L) { HUDONLY lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V @@ -1229,7 +1229,7 @@ static int lib_draw_ref; // // enable vanilla HUD element -static int lib_hudenable(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_hudenable(lua_State *L) { enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); hud_enabled[option/8] |= 1<<(option%8); @@ -1237,7 +1237,7 @@ static int lib_hudenable(lua_State *L) } // disable vanilla HUD element -static int lib_huddisable(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_huddisable(lua_State *L) { enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); hud_enabled[option/8] &= ~(1<<(option%8)); @@ -1245,7 +1245,7 @@ static int lib_huddisable(lua_State *L) } // 30/10/18: Lat': How come this wasn't here before? -static int lib_hudenabled(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_hudenabled(lua_State *L) { enum hud option = luaL_checkoption(L, 1, NULL, hud_disable_options); if (hud_enabled[option/8] & (1<<(option%8))) diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 9a9e472aa..e13e4e099 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -576,7 +576,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) { size_t i; size_t j = 0; - fixed_t frac = R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT; + fixed_t frac = R_GetTimeFrac(RTF_INTER); fixed_t lerpx = 0, lerpy = 0; drawitem_t *latchitem = NULL; drawitem_t *oldlatchitem = NULL; diff --git a/src/lua_infolib.c b/src/lua_infolib.c index e4ea2c009..68ca6b4d0 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -62,7 +62,7 @@ static int lib_getSprname(lua_State *L) } /// \todo Maybe make it tally up the used_spr from dehacked? -static int lib_sprnamelen(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_sprnamelen(lua_State *L) { lua_pushinteger(L, NUMSPRITES); return 1; @@ -122,7 +122,7 @@ static void A_Lua(mobj_t *actor) } // Arbitrary states[] table index -> state_t * -static int lib_getState(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_getState(lua_State *L) { UINT32 i; lua_remove(L, 1); @@ -214,7 +214,7 @@ static int lib_setState(lua_State *L) } // #states -> NUMSTATES -static int lib_statelen(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_statelen(lua_State *L) { lua_pushinteger(L, NUMSTATES); return 1; @@ -482,7 +482,7 @@ static int state_num(lua_State *L) /////////////// // Arbitrary mobjinfo[] table index -> mobjinfo_t * -static int lib_getMobjInfo(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_getMobjInfo(lua_State *L) { UINT32 i; lua_remove(L, 1); @@ -593,7 +593,7 @@ static int lib_setMobjInfo(lua_State *L) } // #mobjinfo -> NUMMOBJTYPES -static int lib_mobjinfolen(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_mobjinfolen(lua_State *L) { lua_pushinteger(L, NUMMOBJTYPES); return 1; @@ -869,7 +869,7 @@ static int mobjinfo_set(lua_State *L) } // mobjinfo_t * -> MT_* -static int mobjinfo_num(lua_State *L) +FUNCINLINE static ATTRINLINE int mobjinfo_num(lua_State *L) { mobjinfo_t *info = *((mobjinfo_t **)luaL_checkudata(L, 1, META_MOBJINFO)); @@ -885,7 +885,7 @@ static int mobjinfo_num(lua_State *L) ////////////// // Arbitrary S_sfx[] table index -> sfxinfo_t * -static int lib_getSfxInfo(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_getSfxInfo(lua_State *L) { UINT32 i; lua_remove(L, 1); @@ -988,7 +988,7 @@ static int lib_setSfxInfo(lua_State *L) return 0; } -static int lib_sfxlen(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_sfxlen(lua_State *L) { lua_pushinteger(L, NUMSFX); return 1; @@ -1062,7 +1062,7 @@ static int sfxinfo_set(lua_State *L) return 0; } -static int sfxinfo_num(lua_State *L) +FUNCINLINE static ATTRINLINE int sfxinfo_num(lua_State *L) { sfxinfo_t *sfx = *((sfxinfo_t **)luaL_checkudata(L, 1, META_SFXINFO)); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index c4718ae90..2931e9a16 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -559,7 +559,7 @@ static int sector_set(lua_State *L) return 0; } -static int sector_num(lua_State *L) +FUNCINLINE static ATTRINLINE int sector_num(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); lua_pushinteger(L, sector-sectors); @@ -598,7 +598,7 @@ static int subsector_get(lua_State *L) return 0; } -static int subsector_num(lua_State *L) +FUNCINLINE static ATTRINLINE int subsector_num(lua_State *L) { subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); lua_pushinteger(L, subsector-subsectors); @@ -698,7 +698,7 @@ static int line_get(lua_State *L) return 0; } -static int line_num(lua_State *L) +FUNCINLINE static ATTRINLINE int line_num(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); lua_pushinteger(L, line-lines); @@ -827,7 +827,7 @@ static int side_set(lua_State *L) return 0; } -static int side_num(lua_State *L) +FUNCINLINE static ATTRINLINE int side_num(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); lua_pushinteger(L, side-sides); @@ -866,7 +866,7 @@ static int vertex_get(lua_State *L) return 0; } -static int vertex_num(lua_State *L) +FUNCINLINE static ATTRINLINE int vertex_num(lua_State *L) { vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); lua_pushinteger(L, vertex-vertexes); @@ -913,7 +913,7 @@ static int lib_getSector(lua_State *L) return 0; } -static int lib_numsectors(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_numsectors(lua_State *L) { lua_pushinteger(L, numsectors); return 1; @@ -959,7 +959,7 @@ static int lib_getSubsector(lua_State *L) return 0; } -static int lib_numsubsectors(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_numsubsectors(lua_State *L) { lua_pushinteger(L, numsubsectors); return 1; @@ -1005,7 +1005,7 @@ static int lib_getLine(lua_State *L) return 0; } -static int lib_numlines(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_numlines(lua_State *L) { lua_pushinteger(L, numlines); return 1; @@ -1051,7 +1051,7 @@ static int lib_getSide(lua_State *L) return 0; } -static int lib_numsides(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_numsides(lua_State *L) { lua_pushinteger(L, numsides); return 1; @@ -1097,7 +1097,7 @@ static int lib_getVertex(lua_State *L) return 0; } -static int lib_numvertexes(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_numvertexes(lua_State *L) { lua_pushinteger(L, numvertexes); return 1; @@ -1467,7 +1467,7 @@ static int lib_getMapheaderinfo(lua_State *L) return 0; } -static int lib_nummapheaders(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_nummapheaders(lua_State *L) { lua_pushinteger(L, NUMMAPS); return 1; diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index bb772cf86..7f94a1cb1 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -23,14 +23,14 @@ // General math ////////////////// -static int lib_abs(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_abs(lua_State *L) { int a = (int)luaL_checkinteger(L, 1); lua_pushinteger(L, abs(a)); return 1; } -static int lib_min(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_min(lua_State *L) { int a = luaL_checkinteger(L, 1); int b = luaL_checkinteger(L, 2); @@ -38,7 +38,7 @@ static int lib_min(lua_State *L) return 1; } -static int lib_max(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_max(lua_State *L) { int a = luaL_checkinteger(L, 1); int b = luaL_checkinteger(L, 2); @@ -49,31 +49,31 @@ static int lib_max(lua_State *L) // Angle math //////////////// -static int lib_fixedangle(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedangle(lua_State *L) { lua_pushangle(L, FixedAngle(luaL_checkfixed(L, 1))); return 1; } -static int lib_anglefixed(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_anglefixed(lua_State *L) { lua_pushfixed(L, AngleFixed(luaL_checkangle(L, 1))); return 1; } -static int lib_invangle(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_invangle(lua_State *L) { lua_pushangle(L, InvAngle(luaL_checkangle(L, 1))); return 1; } -static int lib_finesine(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_finesine(lua_State *L) { lua_pushfixed(L, FINESINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK)); return 1; } -static int lib_finecosine(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_finecosine(lua_State *L) { lua_pushfixed(L, FINECOSINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK)); return 1; @@ -101,19 +101,19 @@ static int lib_finetangent(lua_State *L) // Fixed math //////////////// -static int lib_fixedmul(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedmul(lua_State *L) { lua_pushfixed(L, FixedMul(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); return 1; } -static int lib_fixedint(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedint(lua_State *L) { lua_pushinteger(L, FixedInt(luaL_checkfixed(L, 1))); return 1; } -static int lib_fixeddiv(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixeddiv(lua_State *L) { fixed_t i = luaL_checkfixed(L, 1); fixed_t j = luaL_checkfixed(L, 2); @@ -123,13 +123,13 @@ static int lib_fixeddiv(lua_State *L) return 1; } -static int lib_fixedrem(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedrem(lua_State *L) { lua_pushfixed(L, FixedRem(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); return 1; } -static int lib_fixedsqrt(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedsqrt(lua_State *L) { fixed_t i = luaL_checkfixed(L, 1); if (i < 0) @@ -138,31 +138,31 @@ static int lib_fixedsqrt(lua_State *L) return 1; } -static int lib_fixedhypot(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedhypot(lua_State *L) { lua_pushfixed(L, FixedHypot(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); return 1; } -static int lib_fixedfloor(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedfloor(lua_State *L) { lua_pushfixed(L, FixedFloor(luaL_checkfixed(L, 1))); return 1; } -static int lib_fixedtrunc(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedtrunc(lua_State *L) { lua_pushfixed(L, FixedTrunc(luaL_checkfixed(L, 1))); return 1; } -static int lib_fixedceil(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedceil(lua_State *L) { lua_pushfixed(L, FixedCeil(luaL_checkfixed(L, 1))); return 1; } -static int lib_fixedround(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_fixedround(lua_State *L) { lua_pushfixed(L, FixedRound(luaL_checkfixed(L, 1))); return 1; @@ -172,13 +172,13 @@ static int lib_fixedround(lua_State *L) // (aka extra little funcs that don't quite fit in baselib) ////////////////////////////////////////////////////////////////// -static int lib_getsecspecial(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_getsecspecial(lua_State *L) { lua_pushinteger(L, GETSECSPECIAL(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2))); return 1; } -static int lib_all7emeralds(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_all7emeralds(lua_State *L) { lua_pushboolean(L, ALL7EMERALDS(luaL_checkinteger(L, 1))); return 1; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index ea936d773..5ffbcb34e 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -251,14 +251,15 @@ int mobj_angle_setter(lua_State *L) mobj_t *mo = GETMO(); mo->angle = luaL_checkangle(L, 2); - if (mo->player == &players[consoleplayer]) - localangle[0] = mo->angle; - else if (mo->player == &players[displayplayers[1]]) - localangle[1] = mo->angle; - else if (mo->player == &players[displayplayers[2]]) - localangle[2] = mo->angle; - else if (mo->player == &players[displayplayers[3]]) - localangle[3] = mo->angle; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (mo->player == P_GetLocalPlayerForNum(i)) + { + localangle[i] = mo->angle; + break; + } + } + return 0; } @@ -979,7 +980,7 @@ static int lib_getMapthing(lua_State *L) return 0; } -static int lib_nummapthings(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_nummapthings(lua_State *L) { lua_pushinteger(L, nummapthings); return 1; diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 665512aef..0309c1928 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -267,14 +267,14 @@ int player_aiming_setter(lua_State *L) player_t *plr = GETPLAYER(); plr->aiming = luaL_checkangle(L, 2); - if (plr == &players[consoleplayer]) - localaiming[0] = plr->aiming; - else if (plr == &players[displayplayers[1]]) - localaiming[1] = plr->aiming; - else if (plr == &players[displayplayers[2]]) - localaiming[2] = plr->aiming; - else if (plr == &players[displayplayers[3]]) - localaiming[3] = plr->aiming; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (plr == P_GetLocalPlayerForNum(i)) + { + localangle[i] = plr->aiming; + break; + } + } return 0; } @@ -438,7 +438,7 @@ static int lib_getPlayer(lua_State *L) } // #players -> MAXPLAYERS -static int lib_lenPlayer(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_lenPlayer(lua_State *L) { lua_pushinteger(L, MAXPLAYERS); return 1; @@ -448,47 +448,29 @@ static int lib_lenPlayer(lua_State *L) static int lib_iterateDisplayplayers(lua_State *L) { - INT32 i = -1; - INT32 temp = -1; - INT32 iter = 0; + INT32 i = lua_tonumber(L, lua_upvalueindex(1)); if (lua_gettop(L) < 2) { - //return luaL_error(L, "Don't call displayplayers.iterate() directly, use it as 'for player in displayplayers.iterate do end'."); - lua_pushcfunction(L, lib_iterateDisplayplayers); + lua_pushcclosure(L, lib_iterateDisplayplayers, 1); return 1; } - lua_settop(L, 2); - lua_remove(L, 1); // state is unused. - if (!lua_isnil(L, 1)) + + if (i <= splitscreen) { - temp = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players); // get the player # of the last iterated player. - - // @FIXME: - // I didn't quite find a better way for this; Here, we go back to which player in displayplayers we last iterated to resume the for loop below for this new function call - // I don't understand enough about how the Lua stacks work to get this to work in possibly a single line. - // So anyone feel free to correct this! - - for (; iter < MAXSPLITSCREENPLAYERS; iter++) - { - if (displayplayers[iter] == temp) - { - i = iter; - break; - } - } - } - - for (i++; i < MAXSPLITSCREENPLAYERS; i++) - { - if (i > splitscreen || !playeringame[displayplayers[i]]) - return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers. - - if (!players[displayplayers[i]].mo) - continue; + if (!playeringame[displayplayers[i]]) + return 0; + // Return player and splitscreen index. LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER); - lua_pushinteger(L, i); // push this to recall what number we were on for the next function call. I suppose this also means you can retrieve the splitscreen player number with 'for p, n in displayplayers.iterate'! + lua_pushnumber(L, i); + + // Update splitscreen index value for next iteration. + lua_pushnumber(L, i + 1); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(1)); + lua_pop(L, 1); + return 2; } return 0; @@ -516,14 +498,14 @@ static int lib_getDisplayplayers(lua_State *L) field = luaL_checkstring(L, 2); if (fastcmp(field,"iterate")) { - lua_pushcfunction(L, lib_iterateDisplayplayers); + lua_pushcclosure(L, lib_iterateDisplayplayers, 1); return 1; } return 0; } // #displayplayers -> MAXSPLITSCREENPLAYERS -static int lib_lenDisplayplayers(lua_State *L) +FUNCINLINE static ATTRINLINE int lib_lenDisplayplayers(lua_State *L) { lua_pushinteger(L, MAXSPLITSCREENPLAYERS); return 1; @@ -631,7 +613,7 @@ static int player_set(lua_State *L) #undef NOSET -static int player_num(lua_State *L) +FUNCINLINE static ATTRINLINE int player_num(lua_State *L) { player_t *plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!plr) @@ -668,7 +650,7 @@ static int power_set(lua_State *L) } // #powers -> NUMPOWERS -static int power_len(lua_State *L) +FUNCINLINE static ATTRINLINE int power_len(lua_State *L) { lua_pushinteger(L, NUMPOWERS); return 1; @@ -702,7 +684,7 @@ static int kartstuff_set(lua_State *L) } // #kartstuff -> NUMKARTSTUFF -static int kartstuff_len(lua_State *L) +FUNCINLINE static ATTRINLINE int kartstuff_len(lua_State *L) { lua_pushinteger(L, NUMKARTSTUFF); return 1; diff --git a/src/lua_script.c b/src/lua_script.c index d2cddf125..cd9ba1f85 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -371,7 +371,18 @@ void LUA_DumpFile(const char *filename) } #endif -fixed_t LUA_EvalMath(const char *word) +static void createMathLibState(void) +{ + mL = lua_newstate(LUA_Alloc, NULL); + lua_atpanic(mL, LUA_Panic); + + // open only enum lib + lua_pushcfunction(mL, LUA_EnumLib); + lua_pushboolean(mL, true); + lua_call(mL, 1, 0); +} + +fixed_t LUA_EvalMathEx(const char *word, const char **error) { char buf[1024], *b; const char *p; @@ -380,15 +391,7 @@ fixed_t LUA_EvalMath(const char *word) // make a new state so SOC can't interefere with scripts // allocate state if (mL == NULL) - { - mL = lua_newstate(LUA_Alloc, NULL); - lua_atpanic(mL, LUA_Panic); - - // open only enum lib - lua_pushcfunction(mL, LUA_EnumLib); - lua_pushboolean(mL, true); - lua_call(mL, 1, 0); - } + createMathLibState(); // change ^ into ^^ for Lua. strcpy(buf, "return "); @@ -399,6 +402,9 @@ fixed_t LUA_EvalMath(const char *word) if (*p == '^') *b++ = '^'; } + // length of word is zero!? + if (p == word) + return 0; *b = '\0'; // eval string. @@ -414,7 +420,7 @@ fixed_t LUA_EvalMath(const char *word) p += 3; // "1: " } - CONS_Alert(CONS_WARNING, "%s\n", p); + if (error) *error = p; } else res = lua_tointeger(mL, -1); @@ -422,6 +428,51 @@ fixed_t LUA_EvalMath(const char *word) return res; } +fixed_t LUA_EvalMath(const char *word) +{ + const char *error = NULL; + fixed_t res = LUA_EvalMathEx(word, &error); + + if (error) + CONS_Alert(CONS_WARNING, "%s\n", error); + + return res; +} + +// A hack to prevent lua from crashing game if constant doesn't exist +static int lua_get_constant(lua_State *L) +{ + lua_pushvalue(mL, LUA_GLOBALSINDEX); + lua_pushvalue(L, 1); + lua_gettable(L, -2); + + return 1; +} + +fixed_t LUA_GetConstant(const char *word) +{ + if (mL == NULL) + createMathLibState(); + + fixed_t res = 0; + + lua_pushcfunction(mL, lua_get_constant); + lua_pushstring(mL, word); + + if (lua_pcall(mL, 1, 1, 0) == 0) + { + if (lua_isnumber(mL, -1)) + res = lua_tointeger(mL, -1); + } + else + { + // Pop error message + lua_pop(mL, 1); + } + + return res; +} + void LUA_InvalidateMathlibCache(const char *name) { // No state => no cache => nothing to invalidate :3 diff --git a/src/lua_script.h b/src/lua_script.h index ccbef2b45..af218978d 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -13,6 +13,10 @@ #ifndef LUA_SCRIPT_H #define LUA_SCRIPT_H +#ifdef __cplusplus +extern "C" { +#endif + #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" @@ -48,7 +52,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump); #ifdef LUA_ALLOW_BYTECODE void LUA_DumpFile(const char *filename); #endif +fixed_t LUA_EvalMathEx(const char *word, const char **error); fixed_t LUA_EvalMath(const char *word); +fixed_t LUA_GetConstant(const char *word); // Need better name for this ;-; void LUA_InvalidateMathlibCache(const char *name); @@ -104,4 +110,8 @@ void COM_Lua_f(void); }\ } +#ifdef __cplusplus +} // extern "C" +#endif + #endif/*LUA_SCRIPT_H*/ diff --git a/src/m_aatree.c b/src/m_aatree.c index 56e528f54..e67ab69c0 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -13,6 +13,7 @@ #include "m_aatree.h" #include "z_zone.h" +#include "m_misc.h" // A partial implementation of AA trees, // according to the algorithms given on Wikipedia. @@ -27,6 +28,13 @@ typedef struct aatree_node_s struct aatree_node_s *left, *right; } aatree_node_t; +typedef struct aatree_entry_s +{ + struct aatree_entry_s *next; + char *key; + void *value; +} aatree_entry_t; + struct aatree_s { aatree_node_t *root; @@ -143,9 +151,77 @@ static aatree_node_t *M_AATreeSet_Node(aatree_node_t *node, UINT32 flags, INT32 void M_AATreeSet(aatree_t *aatree, INT32 key, void* value) { + I_Assert((aatree->flags & AATREE_STRING) == 0); aatree->root = M_AATreeSet_Node(aatree->root, aatree->flags, key, value); } +static aatree_node_t *M_AATreeSetString_Node(aatree_node_t *node, UINT32 flags, INT32 hash, const char *key, void* value) +{ + if (!node) + { + // Nothing here, so just add where we are + aatree_entry_t *entry = Z_Malloc(sizeof(aatree_entry_t), PU_STATIC, NULL); + entry->next = NULL; + entry->key = Z_StrDup(key); + if (value && (flags & AATREE_ZUSER)) Z_SetUser(value, &entry->value); + else entry->value = value; + + node = Z_Malloc(sizeof (aatree_node_t), PU_STATIC, NULL); + node->key = hash; + node->value = entry; + node->left = node->right = NULL; + node->depth = 1; + } + else + { + if (hash < node->key) + node->left = M_AATreeSetString_Node(node->left, flags, hash, key, value); + else if (hash > node->key) + node->right = M_AATreeSetString_Node(node->right, flags, hash, key, value); + else + { + aatree_entry_t *entry = node->value; + if (entry != NULL && strcmp(entry->key, key) != 0) + entry = entry->next; + if (entry != NULL) + { + if (value && (flags & AATREE_ZUSER)) Z_SetUser(value, &entry->value); + else entry->value = value; + } + else + { + entry = Z_Malloc(sizeof(aatree_entry_t), PU_STATIC, NULL); + entry->next = node->value; + entry->key = Z_StrDup(key); + if (value && (flags & AATREE_ZUSER)) Z_SetUser(value, &entry->value); + else entry->value = value; + node->value = entry; + } + } + + node = M_AATreeRebalance(node); + if (node->left == NULL && node->right == NULL) + node->depth = 1; + else if (node->left == NULL) + node->depth = node->right->depth + 1; + else if (node->right == NULL) + node->depth = node->left->depth + 1; + else if (node->left->depth > node->right->depth) + node->depth = node->left->depth + 1; + else + node->depth = node->right->depth + 1; + } + + return node; +} + +void M_AATreeSetString(aatree_t *aatree, const char *key, void *value) +{ + I_Assert((aatree->flags & AATREE_STRING) == AATREE_STRING); + UINT32 hash = FNV1a_HashString(key); + aatree->root = M_AATreeSetString_Node(aatree->root, aatree->flags, hash, key, value); +} + // Caveat: we don't distinguish between nodes that don't exists // and nodes with value == NULL. static void *M_AATreeGet_Node(aatree_node_t *node, INT32 key) @@ -165,9 +241,20 @@ static void *M_AATreeGet_Node(aatree_node_t *node, INT32 key) void *M_AATreeGet(aatree_t *aatree, INT32 key) { + I_Assert((aatree->flags & AATREE_STRING) == 0); return M_AATreeGet_Node(aatree->root, key); } +void *M_AATreeGetString(aatree_t *aatree, const char *key) +{ + I_Assert((aatree->flags & AATREE_STRING) == AATREE_STRING); + UINT32 hash = FNV1a_HashString(key); + aatree_entry_t *entry = M_AATreeGet_Node(aatree->root, hash); + while (entry != NULL && strcmp(entry->key, key) != 0) + entry = entry->next; + return entry != NULL ? entry->value : NULL; +} + static void M_AATreeIterate_Node(aatree_node_t *node, aatree_iter_t callback) { if (node->left) M_AATreeIterate_Node(node->left, callback); diff --git a/src/m_aatree.h b/src/m_aatree.h index e7f1eba05..ad4197c78 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -18,6 +18,7 @@ // Flags for AA trees. #define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields +#define AATREE_STRING 2 // Use strings for keys rather than ints typedef struct aatree_s aatree_t; typedef void (*aatree_iter_t)(INT32 key, void *value); @@ -25,7 +26,9 @@ typedef void (*aatree_iter_t)(INT32 key, void *value); aatree_t *M_AATreeAlloc(UINT32 flags); void M_AATreeFree(aatree_t *aatree); void M_AATreeSet(aatree_t *aatree, INT32 key, void* value); +void M_AATreeSetString(aatree_t *aatree, const char *key, void *value); void *M_AATreeGet(aatree_t *aatree, INT32 key); +void *M_AATreeGetString(aatree_t *aatree, const char *key); void M_AATreeIterate(aatree_t *aatree, aatree_iter_t callback); #endif diff --git a/src/m_fixed.c b/src/m_fixed.c index ddd1ce63a..0eeab810f 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -23,7 +23,7 @@ #include "m_fixed.h" #include "tables.h" // ANGLETOFINESHIFT -fixed_t FixedSqrt(fixed_t x) +FUNCMATH fixed_t FixedSqrt(fixed_t x) { #ifdef HAVE_SQRT const float fx = FIXED_TO_FLOAT(x); @@ -61,7 +61,7 @@ fixed_t FixedSqrt(fixed_t x) #endif } -fixed_t FixedHypot(fixed_t x, fixed_t y) +FUNCMATH fixed_t FixedHypot(fixed_t x, fixed_t y) { // Moved the code from R_PointToDist2 to here, // since R_PointToDist2 did the same thing, diff --git a/src/m_menu.c b/src/m_menu.c index ca9f6e175..3ccbed5eb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -683,6 +683,12 @@ static void M_ResetCvars(void) } } +// This is not a particular elegant solution, but it seems to make do for our purposes +static boolean M_CheckTextInput(void) +{ + return (menuactive && currentMenu && (itemOn < currentMenu->numitems) && (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) || (currentMenu->menuitems[itemOn].status == IT_MSGHANDLER && currentMenu->menuitems[itemOn].alphaKey != MM_EVENTHANDLER) || ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER))); +} + // If current menu item is IT_CV_STRING, setup menuinput static void M_CheckStringItem(void) { @@ -1030,7 +1036,6 @@ boolean M_Responder(event_t *ev) // Handle menuitems which need a specific key handling if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER) { - menu_text_input = true; ch = M_ShiftChar(ch); routine(ch); return true; @@ -1070,7 +1075,6 @@ boolean M_Responder(event_t *ev) { if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING) { - menu_text_input = true; if (M_ChangeStringCvar(ch)) return true; else @@ -1725,6 +1729,10 @@ void M_Ticker(void) interpTimerHackAllow = true; + menu_text_input = M_CheckTextInput(); + + I_SetTextInput(); + //added : 30-01-98 : test mode for five seconds if (vidm_testingmode > 0) { @@ -3716,6 +3724,7 @@ static void M_HandleAddons(INT32 choice) default: break; } + if (exitmenu) { closefilemenu(true); @@ -3915,13 +3924,12 @@ static void PrepReplayList(boolean reset) replayquerycheck = replayqueryfound = 0; - if (demolist) - Z_Free(demolist); - + Z_Free(demolist); demolist = Z_Calloc(sizeof(menudemo_t) * sizedirmenu, PU_STATIC, NULL); // If directory didn't change, keep demolist_all - if (!reset) return; + if (!reset) + return; Lock_search_state(); @@ -4577,17 +4585,23 @@ static void M_DrawReplayStartMenu(void) V_DrawSmallString(4, BASEVIDHEIGHT-14, V_SNAPTOBOTTOM|V_SNAPTOLEFT|V_ALLOWLOWERCASE, warning); } +void M_ResetDemoList(void) +{ + Z_Free(demolist_all); + demolist_all = NULL; + + Z_Free(demolist); + demolist = NULL; + + demo.inreplayhut = false; +} + static boolean M_QuitReplayHut(void) { // D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate. menuactive = false; D_StartTitle(); - - if (demolist) - Z_Free(demolist); - demolist = NULL; - - demo.inreplayhut = false; + M_ResetDemoList(); return true; } @@ -6732,7 +6746,7 @@ static void M_DrawConnectMenu(void) { const float ease = serverlistslidex / 2.f; const INT32 offx = serverlistslidex > 0 ? BASEVIDWIDTH : -(BASEVIDWIDTH); - const INT32 x = (FLOAT_TO_FIXED(serverlistslidex) + ease * rendertimefrac) / FRACUNIT; + const INT32 x = (FLOAT_TO_FIXED(serverlistslidex) + ease * R_GetTimeFrac(RTF_MENU)) / FRACUNIT; M_DrawServerLines(currentMenu->x + x - offx, oldserverlistpage); M_DrawServerLines(currentMenu->x + x, serverlistpage); @@ -6991,7 +7005,7 @@ void M_PopupMasterServerConnectError(void) { if (!CV_IsSetToDefault(&cv_masterserver) && cv_masterserver_nagattempts.value > 0) { - M_StartMessage(M_GetText("There was a problem connecting to\ncustom Master Server\n\nYou've changed the Server Browser address.\nUnless you're from the future, this probably isn't what you want.\n\n\x83Press Accel\x80 to fix this and continue.\n"), connect_error_continue == STARTSERVER_MENU ? M_PreStartServerMenuChoice : M_PreConnectMenuChoice,MM_EVENTHANDLER); + M_StartMessage(M_GetText("There was a problem connecting to\ncustom Master Server\n\nYou've changed the Server Browser address.\nUnless you're from the future, this probably isn't what you want.\n\n\x83Press Accel\x80 to fix this and continue.\n"), connect_error_continue == STARTSERVER_MENU ? M_PreStartServerMenuChoice : M_PreConnectMenuChoice, MM_EVENTHANDLER); } else { @@ -9163,7 +9177,6 @@ static void M_DrawControl(void) char tmp[50]; INT32 x, y, i, max, cursory = 0, iter; INT32 keys[2]; - menu_text_input = false; //never use native layout for control setup x = currentMenu->x; y = currentMenu->y; @@ -9263,12 +9276,10 @@ static void M_ChangecontrolResponse(event_t *ev) INT32 control; INT32 found; INT32 ch = ev->data1; - menu_text_input = false; //never use native layout for control setup // ESCAPE cancels; dummy out PAUSE if (ch != KEY_ESCAPE && ch != KEY_PAUSE) { - switch (ev->type) { // ignore mouse/joy movements, just get buttons @@ -9298,6 +9309,7 @@ static void M_ChangecontrolResponse(event_t *ev) found = 0; else if (setupcontrols[control][1] ==ch) found = 1; + if (found >= 0) { // replace mouse and joy clicks by double clicks @@ -9325,9 +9337,11 @@ static void M_ChangecontrolResponse(event_t *ev) found = 0; setupcontrols[control][1] = KEY_NULL; //replace key 1,clear key2 } + (void)G_CheckDoubleUsage(ch, true); setupcontrols[control][found] = ch; } + S_StartSound(NULL, sfx_s221); } else if (ch == KEY_PAUSE) diff --git a/src/m_menu.h b/src/m_menu.h index 06e0273fe..024fd62a0 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -319,6 +319,7 @@ void GameFocus_menu_Onchange (void); void M_UpdateOGLMenu(void); #endif +void M_ResetDemoList(void); void M_ReplayHut(INT32 choice); void M_SetPlaybackMenuPointer(void); diff --git a/src/m_menudefs.c b/src/m_menudefs.c index 9f20b5f91..f9d1e0ea9 100644 --- a/src/m_menudefs.c +++ b/src/m_menudefs.c @@ -1186,8 +1186,6 @@ static menuitem_t OP_FocusOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Background FPS Cap", &cv_fpscapbg, 80}, {IT_STRING|IT_CVAR, NULL, "Show \"FOCUS LOST\"", &cv_showfocuslost, 100}, - - {IT_STRING|IT_CVAR, NULL, "Always Grab Mouse While Focused", &cv_alwaysgrabmouse, 120}, }; static const char* OP_FocusOptionsTooltips[] = @@ -1198,7 +1196,6 @@ static const char* OP_FocusOptionsTooltips[] = "Should the game pause while the game is unfocused?", "Set manual framerate cap while the game is unfocused.", "Should the FOCUS LOST window appear\n while the game is unfocused?", - "Should the mouse cursor be grabbed and hidden\n while the game is in focus?", }; static menuitem_t OP_DataOptionsMenu[] = diff --git a/src/p_ceilng.c b/src/p_ceilng.c index b80656360..8170343c9 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -11,6 +11,7 @@ /// \file p_ceilng.c /// \brief Ceiling aninmation (lowering, crushing, raising) +#include "d_think.h" #include "doomdef.h" #include "p_local.h" #include "r_fps.h" @@ -396,6 +397,7 @@ void T_CrushCeiling(ceiling_t *ceiling) INT32 EV_DoCeiling(line_t *line, ceiling_e type) { INT32 rtn = 0, firstone = 1; + INT32 secnum = -1; sector_t *sec; ceiling_t *ceiling; @@ -409,7 +411,9 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) // new door thinker rtn = 1; - ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); + ceiling = Z_LevelPoolCalloc(sizeof(*ceiling)); + ceiling->thinker.alloctype = TAT_LEVELPOOL; + ceiling->thinker.size = sizeof(*ceiling); P_AddThinker(&ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function = (actionf_p1)T_MoveCeiling; @@ -619,6 +623,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) INT32 EV_DoCrush(line_t *line, ceiling_e type) { INT32 rtn = 0; + INT32 secnum = -1; sector_t *sec; ceiling_t *ceiling; @@ -632,7 +637,9 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) // new door thinker rtn = 1; - ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); + ceiling = Z_LevelPoolCalloc(sizeof(*ceiling)); + ceiling->thinker.alloctype = TAT_LEVELPOOL; + ceiling->thinker.size = sizeof(*ceiling); P_AddThinker(&ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function = (actionf_p1)T_CrushCeiling; diff --git a/src/p_enemy.c b/src/p_enemy.c index f5bf852f8..dbff7842b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8035,8 +8035,15 @@ void A_JawzExplode(void *thing) { INT32 speed, speed2; - truc = P_SpawnMobj(actor->x + P_RandomRange(-8, 8)*FRACUNIT, actor->y + P_RandomRange(-8, 8)*FRACUNIT, - actor->z + P_RandomRange(0, 8)*FRACUNIT, MT_BOOMPARTICLE); + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = actor->z + P_RandomRange(0, 8)*FRACUNIT; + rand_y = actor->y + P_RandomRange(-8, 8)*FRACUNIT; + rand_x = actor->x + P_RandomRange(-8, 8)*FRACUNIT; + + truc = P_SpawnMobj(rand_x, rand_y, rand_z, MT_BOOMPARTICLE); truc->scale = actor->scale*2; speed = FixedMul(7*FRACUNIT, actor->scale)>>FRACBITS; @@ -8205,10 +8212,16 @@ void A_SPBChase(void *thing) : (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target && xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds { - mobj_t *fast = P_SpawnMobj(actor->x + (P_RandomRange(-24,24) * actor->scale), - actor->y + (P_RandomRange(-24,24) * actor->scale), - actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale), - MT_FASTLINE); + + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = actor->z + (actor->height/2) + (P_RandomRange(-24,24) * actor->scale); + rand_y = actor->y + (P_RandomRange(-24,24) * actor->scale); + rand_x = actor->x + (P_RandomRange(-24,24) * actor->scale); + + mobj_t *fast = P_SpawnMobj(rand_x, rand_y, rand_z, MT_FASTLINE); fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); //fast->momx = (3*actor->momx)/4; //fast->momy = (3*actor->momy)/4; @@ -8416,8 +8429,15 @@ void A_FZBoomSmoke(void *thing) for (i = 0; i < 8+(4*var1); i++) { - mobj_t *smoke = P_SpawnMobj(actor->x + (P_RandomRange(-rad, rad)*actor->scale), actor->y + (P_RandomRange(-rad, rad)*actor->scale), - actor->z + (P_RandomRange(0, 72)*actor->scale), MT_THOK); + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = actor->z + (P_RandomRange(0, 72)*actor->scale); + rand_y = actor->y + (P_RandomRange(-rad, rad)*actor->scale); + rand_x = actor->x + (P_RandomRange(-rad, rad)*actor->scale); + + mobj_t *smoke = P_SpawnMobj(rand_x, rand_y, rand_z, MT_THOK); P_SetMobjState(smoke, S_FZEROSMOKE1); smoke->tics += P_RandomRange(-3, 4); @@ -8593,7 +8613,15 @@ void A_MementosTPParticles(void *thing) for (; i < 4; i++) { - particle = P_SpawnMobj(actor->x + (P_RandomRange(-256, 256)<y + (P_RandomRange(-256, 256)<z + (P_RandomRange(48, 256)<z + (P_RandomRange(48, 256)<y + (P_RandomRange(-256, 256)<x + (P_RandomRange(-256, 256)<frame = 0; particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); particle->destscale = 1; @@ -8656,9 +8684,15 @@ void A_ReaperThinker(void *thing) if (actor->scale < 2<x + (P_RandomRange(-60, 60)<y + (P_RandomRange(-60, 60)<z, MT_THOK); + fixed_t rand_x; + fixed_t rand_y; + + rand_y = actor->y + (P_RandomRange(-60, 60)<x + (P_RandomRange(-60, 60)<z, MT_THOK); particle->momz = 20<color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); particle->frame = 0; @@ -8813,11 +8847,15 @@ void A_FlameParticle(void *thing) if (LUA_CallAction(A_FLAMEPARTICLE, actor)) return; - par = P_SpawnMobj( - actor->x + (P_RandomRange(-rad, rad)<y + (P_RandomRange(-rad, rad)<z + (P_RandomRange(hei/2, hei)<info->painchance); + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = actor->z + (P_RandomRange(hei/2, hei)<y + (P_RandomRange(-rad, rad)<x + (P_RandomRange(-rad, rad)<info->painchance); par->momz = actor->scale<<1; } diff --git a/src/p_floor.c b/src/p_floor.c index 86447c5ba..f4cc3e992 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2538,7 +2538,9 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype) // new floor thinker rtn = 1; - dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL); + dofloor = Z_LevelPoolCalloc(sizeof(*dofloor)); + dofloor->thinker.alloctype = TAT_LEVELPOOL; + dofloor->thinker.size = sizeof(*dofloor); P_AddThinker(&dofloor->thinker); // make sure another floor thinker won't get started over this one @@ -2762,7 +2764,9 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) // create and initialize new elevator thinker rtn = 1; - elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); + elevator = Z_LevelPoolCalloc(sizeof(*elevator)); + elevator->thinker.alloctype = TAT_LEVELPOOL; + elevator->thinker.size = sizeof(*elevator); P_AddThinker(&elevator->thinker); sec->floordata = elevator; sec->ceilingdata = elevator; @@ -2951,7 +2955,9 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline) if (sec->ceilingdata) // One at a time, ma'am. return 0; - bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL); + bouncer = Z_LevelPoolCalloc(sizeof(*bouncer)); + bouncer->thinker.alloctype = TAT_LEVELPOOL; + bouncer->thinker.size = sizeof(*bouncer); P_AddThinker(&bouncer->thinker); sec->ceilingdata = bouncer; bouncer->thinker.function = (actionf_p1)T_BounceCheese; @@ -2989,7 +2995,9 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool backsector = sec; // create and initialize new thinker - faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL); + faller = Z_LevelPoolCalloc(sizeof(*faller)); + faller->thinker.alloctype = TAT_LEVELPOOL; + faller->thinker.size = sizeof(*faller); P_AddThinker(&faller->thinker); faller->thinker.function = (actionf_p1)T_ContinuousFalling; @@ -3042,7 +3050,9 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, return 0; // create and initialize new elevator thinker - elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); + elevator = Z_LevelPoolCalloc(sizeof(*elevator)); + elevator->thinker.alloctype = TAT_LEVELPOOL; + elevator->thinker.size = sizeof(*elevator); P_AddThinker(&elevator->thinker); elevator->thinker.function = (actionf_p1)T_StartCrumble; @@ -3118,8 +3128,9 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob { const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR; // create and initialize new elevator thinker - - block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); + block = Z_LevelPoolCalloc(sizeof(*block)); + block->thinker.alloctype = TAT_LEVELPOOL; + block->thinker.size = sizeof(*block); P_AddThinker(&block->thinker); sec->floordata = block; sec->ceilingdata = block; diff --git a/src/p_inter.c b/src/p_inter.c index 5412d3eec..26c9111b9 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -558,7 +558,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { special->momx = toucher->momx; special->momy = toucher->momy; - special->momz = flip * max(P_AproxDistance(toucher->momx, toucher->momy) / 4, FixedMul(special->info->speed, special->scale)); + const fixed_t dist = P_AproxDistance(toucher->momx, toucher->momy) / 4; + const fixed_t scale = FixedMul(special->info->speed, special->scale); + special->momz = flip * max(dist, scale); if (flip * toucher->momz > 0) special->momz += toucher->momz / 8; if ((statenum_t)(special->state-states) != special->info->seestate) @@ -800,10 +802,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_PlayerTouchingSectorSpecial(player, 4, 2 + flagteam)) { CONS_Printf(M_GetText("%s returned the %c%s%c to base.\n"), plname, flagcolor, flagtext, 0x80); - - // The fuse code plays this sound effect - //if (players[consoleplayer].ctfteam == player->ctfteam) - // S_StartSound(NULL, sfx_hoop1); } } } @@ -871,14 +869,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->angle = special->angle; - if (player == &players[consoleplayer]) - localangle[0] = toucher->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = toucher->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = toucher->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = toucher->angle; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (player == P_GetLocalPlayerForNum(i)) + { + localangle[i] = toucher->angle; + break; + } + } P_ResetPlayer(player); @@ -1624,25 +1622,20 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) S_FadeOutStopMusic(cv_respawnfademusicout.value); } - if (target->player == &players[consoleplayer]) + for (UINT8 i = 0; i <= splitscreen; i++) { - // don't die in auto map, - // switch view prior to dying - if (automapactive) - AM_Stop(); + if (target->player == P_GetLocalPlayerForNum(i)) + { + // don't die in auto map, + // switch view prior to dying + if (i == 0 && automapactive) + AM_Stop(); - //added : 22-02-98: recenter view for next life... - localaiming[0] = 0; + // added : 22-02-98: recenter view for next life... + localaiming[i] = 0; + break; + } } - if (target->player == &players[displayplayers[1]]) - { - // added : 22-02-98: recenter view for next life... - localaiming[1] = 0; - } - if (target->player == &players[displayplayers[2]]) - localaiming[2] = 0; - if (target->player == &players[displayplayers[3]]) - localaiming[3] = 0; if (G_BattleGametype()) K_CheckBumpers(); diff --git a/src/p_lights.c b/src/p_lights.c index ba7be57d7..8f033d646 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -74,7 +74,9 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse fireflicker_t *flick; P_RemoveLighting(maxsector); // out with the old, in with the new - flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL); + flick = Z_LevelPoolCalloc(sizeof(*flick)); + flick->thinker.alloctype = TAT_LEVELPOOL; + flick->thinker.size = sizeof(*flick); P_AddThinker(&flick->thinker); @@ -153,7 +155,9 @@ void P_SpawnLightningFlash(sector_t *sector) sector->lightingdata = NULL; - flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); + flash = Z_LevelPoolCalloc(sizeof(*flash)); + flash->thinker.alloctype = TAT_LEVELPOOL; + flash->thinker.size = sizeof(*flash); P_AddThinker(&flash->thinker); @@ -212,7 +216,9 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, strobe_t *flash; P_RemoveLighting(maxsector); // out with the old, in with the new - flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); + flash = Z_LevelPoolCalloc(sizeof(*flash)); + flash->thinker.alloctype = TAT_LEVELPOOL; + flash->thinker.size = sizeof(*flash); P_AddThinker(&flash->thinker); @@ -287,7 +293,9 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, glow_t *g; P_RemoveLighting(maxsector); // out with the old, in with the new - g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL); + g = Z_LevelPoolCalloc(sizeof(*g)); + g->thinker.alloctype = TAT_LEVELPOOL; + g->thinker.size = sizeof(*g); P_AddThinker(&g->thinker); @@ -346,7 +354,9 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) sector = §ors[i]; P_RemoveLighting(sector); // remove the old lighting effect first - ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); + ll = Z_LevelPoolCalloc(sizeof(*ll)); + ll->thinker.alloctype = TAT_LEVELPOOL; + ll->thinker.size = sizeof(*ll); ll->thinker.function = (actionf_p1)T_LightFade; sector->lightingdata = ll; // set it to the lightlevel_t diff --git a/src/p_local.h b/src/p_local.h index 23c6b3a71..d428d59d1 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -14,6 +14,10 @@ #ifndef __P_LOCAL__ #define __P_LOCAL__ +#ifdef __cplusplus +extern "C" { +#endif + #include "command.h" #include "d_player.h" #include "d_think.h" @@ -67,7 +71,6 @@ // both the head and tail of the thinker list extern thinker_t thinkercap; extern thinker_t precipcap; -extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(thinker_t *thinker); @@ -174,7 +177,9 @@ fixed_t P_GetPlayerSpinHeight(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); +#ifndef NOCLIPCAM void P_SlideCameraMove(camera_t *thiscam); +#endif //void P_DemoCameraMovement(camera_t *cam, UINT8 num); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); void P_ResetLocalCamAiming(player_t *player); @@ -184,7 +189,9 @@ boolean P_PlayerInPain(player_t *player); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_ResetPlayer(player_t *player); player_t *P_GetLocalPlayerForNum(UINT8 pnum); +INT32 P_GetLocalPlayerNumForNum(UINT8 pnum); boolean P_IsLocalPlayer(const player_t *player); +boolean P_IsLocalPlayerNum(UINT8 pnum); boolean P_IsDisplayPlayer(const player_t *player); boolean P_SpectatorJoinGame(player_t *player); @@ -256,10 +263,11 @@ void P_PlayVictorySound(mobj_t *source); extern mapthing_t *itemrespawnque[ITEMQUESIZE]; extern tic_t itemrespawntime[ITEMQUESIZE]; extern size_t iquehead, iquetail; -extern consvar_t cv_gravity/*, cv_viewheight*/; +extern consvar_t cv_gravity; void P_RespawnSpecials(void); +mobj_t *P_AllocateMobj(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); mobj_t *P_SpawnShadowMobj(mobj_t * caster); @@ -383,7 +391,6 @@ void P_SetThingPosition(mobj_t *thing); void P_SetUnderlayPosition(mobj_t *thing); boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y); -boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); @@ -483,4 +490,8 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __P_LOCAL__ diff --git a/src/p_map.c b/src/p_map.c index 39d4e5e7f..f1fe307cf 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -225,8 +225,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { for (UINT8 j = 0; j <= splitscreen; ++j) { - INT32 id = (j == 0 ? consoleplayer : displayplayers[j]); - if (object->player == &players[id]) + if (object->player == P_GetLocalPlayerForNum(j)) { localangle[j] = spring->angle; break; @@ -1982,7 +1981,7 @@ void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fix // // P_CheckCameraPosition // -boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) +static boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) { INT32 xl, xh, yl, yh, bx, by; sector_t *newsec; @@ -2396,13 +2395,15 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->player) { + const INT32 special = GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1); + // If using type Section1:13, double the maxstep. if (P_PlayerTouchingSectorSpecial(thing->player, 1, 13) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 13) + || special == 13) maxstep <<= 1; // If using type Section1:12, no maxstep. For ledges you don't want the player to climb! (see: Egg Zeppelin & SMK port walls) else if (P_PlayerTouchingSectorSpecial(thing->player, 1, 12) - || GETSECSPECIAL(R_PointInSubsector(x, y)->sector->special, 1) == 12) + || special == 12) maxstep = 0; } @@ -2614,11 +2615,12 @@ static boolean P_ThingHeightClip(mobj_t *thing) { boolean floormoved; fixed_t oldfloorz = thing->floorz; - boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); if (thing->flags & MF_NOCLIPHEIGHT) return true; + const boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); + P_CheckPosition(thing, thing->x, thing->y); if (P_MobjWasRemoved(thing)) @@ -2686,6 +2688,7 @@ static fixed_t tmxmove, tmymove; // // P_HitCameraSlideLine // +#ifndef NOCLIPCAM static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) { INT32 side; @@ -2705,7 +2708,7 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) } side = P_PointOnLineSide(thiscam->x, thiscam->y, ld); - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + lineangle = ld->angle; if (side == 1) lineangle += ANGLE_180; @@ -2725,6 +2728,7 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); tmymove = FixedMul(newlen, FINESINE(lineangle)); } +#endif // // P_HitSlideLine @@ -2751,7 +2755,7 @@ static void P_HitSlideLine(line_t *ld) side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + lineangle = ld->angle; if (side == 1) lineangle += ANGLE_180; @@ -2784,7 +2788,7 @@ static void P_PlayerHitBounceLine(line_t *ld) fixed_t movelen; side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy)-ANGLE_90; + lineangle = ld->angle-ANGLE_90; if (side == 1) lineangle += ANGLE_180; @@ -2822,7 +2826,7 @@ static void P_HitBounceLine(line_t *ld) return; } - lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + lineangle = ld->angle; if (lineangle >= ANGLE_180) lineangle -= ANGLE_180; @@ -2844,6 +2848,7 @@ static void P_HitBounceLine(line_t *ld) // // PTR_SlideCameraTraverse // +#ifndef NOCLIPCAM static boolean PTR_SlideCameraTraverse(intercept_t *in) { line_t *li; @@ -2890,6 +2895,7 @@ isblocking: return false; // stop } +#endif // // PTR_SlideTraverse @@ -2960,6 +2966,7 @@ isblocking: // // Tries to slide the camera along a wall. // +#ifndef NOCLIPCAM void P_SlideCameraMove(camera_t *thiscam) { fixed_t leadx, leady, trailx, traily, newx, newy; @@ -3053,6 +3060,7 @@ stairstep: if (!retval) goto retry; } +#endif // // P_SlideMove @@ -3815,11 +3823,8 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) Lots of new Boom functions that work faster and add functionality. */ -static msecnode_t *headsecnode = NULL; - void P_Initsecnode(void) { - headsecnode = NULL; } // P_GetSecnode() retrieves a node from the freelist. The calling routine @@ -3827,24 +3832,14 @@ void P_Initsecnode(void) static msecnode_t *P_GetSecnode(void) { - msecnode_t *node; - - if (headsecnode) - { - node = headsecnode; - headsecnode = headsecnode->m_thinglist_next; - } - else - node = Z_Calloc(sizeof (*node), PU_LEVEL, NULL); - return node; + return Z_LevelPoolCalloc(sizeof(msecnode_t)); } // P_PutSecnode() returns a node to the freelist. static inline void P_PutSecnode(msecnode_t *node) { - node->m_thinglist_next = headsecnode; - headsecnode = node; + Z_LevelPoolFree(node, sizeof(msecnode_t)); } // P_AddSecnode() searches the current list to see if this sector is @@ -3949,9 +3944,9 @@ void P_DelSeclist(msecnode_t *node) static inline boolean PIT_GetSectors(line_t *ld) { - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || - tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || - tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || + tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] || + tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) return true; @@ -4071,7 +4066,7 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y) * Must clear tmthing at tic end, as it might contain a pointer to a removed thinker, or the level might have ended/been ended and we clear the objects it was pointing too. Hopefully we don't need to carry this between tics for sync. */ void P_MapStart(void) { - if (tmthing) + if (UNLIKELY(tmthing)) I_Error("P_MapStart: tmthing set!"); } diff --git a/src/p_maputl.c b/src/p_maputl.cpp similarity index 95% rename from src/p_maputl.c rename to src/p_maputl.cpp index baab10b0a..3209f6f51 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.cpp @@ -130,35 +130,12 @@ void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, verte return; } -// -// P_PointOnLineSide -// Returns 0 or 1 -// -INT32 P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line) -{ - fixed_t dx, dy, left, right; - - if (!line->dx) - return x <= line->v1->x ? line->dy > 0 : line->dy < 0; - - if (!line->dy) - return y <= line->v1->y ? line->dx < 0 : line->dx > 0; - - dx = (x - line->v1->x); - dy = (y - line->v1->y); - - left = FixedMul(line->dy>>FRACBITS, dx); - right = FixedMul(dy, line->dx>>FRACBITS); - - return right < left ? 0 : 1; -} - // // P_BoxOnLineSide // Considers the line to be infinite // Returns side 0 or 1, -1 if box crosses the line. // -INT32 P_BoxOnLineSide(fixed_t *tmbox, const line_t *ld) +PUREFUNC INT32 P_BoxOnLineSide(fixed_t *tmbox, const line_t *ld) { INT32 p1, p2; @@ -208,30 +185,15 @@ INT32 P_BoxOnLineSide(fixed_t *tmbox, const line_t *ld) // P_PointOnDivlineSide // Returns 0 or 1. // -static INT32 P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t *line) +FUNCINLINE static ATTRINLINE PUREFUNC INT32 P_PointOnDivlineSide(fixed_t x, fixed_t y, divline_t *line) { - fixed_t dx, dy, left, right; - - if (!line->dx) - return x <= line->x ? line->dy > 0 : line->dy < 0; - - if (!line->dy) - return y <= line->y ? line->dx < 0 : line->dx > 0; - - dx = (x - line->x); - dy = (y - line->y); - - // try to quickly decide by looking at sign bits - if ((line->dy ^ line->dx ^ dx ^ dy) & 0x80000000) - return ((line->dy ^ dx) & 0x80000000) ? 1 : 0; - - left = FixedMul(line->dy>>8, dx>>8); - right = FixedMul(dy>>8, line->dx>>8); - - return right < left ? 0 : 1; + return + !line->dx ? x <= line->x ? line->dy > 0 : line->dy < 0 : + !line->dy ? y <= line->y ? line->dx < 0 : line->dx > 0 : + (line->dy^line->dx^(x -= line->x)^(y -= line->y)) < 0 ? (line->dy^x) < 0 : + FixedMul(y>>8, line->dx>>8) >= FixedMul(line->dy>>8, x>>8); } - // // P_MakeDivline // @@ -248,7 +210,7 @@ void P_MakeDivline(line_t *li, divline_t *dl) // Returns the fractional intercept point along the first divline. // This is only called by the addthings and addlines traversers. // -fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) +PUREFUNC fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) { fixed_t frac, num, den; @@ -768,7 +730,8 @@ void P_UnsetPrecipThingPosition(precipmobj_t *thing) bnext->bprev = bprev; } -static void P_LinkToBlockMap(mobj_t *thing, mobj_t **bmap) +template +static void P_LinkToBlockMap(T *thing, T **bmap) { const INT32 blockx = (unsigned)(thing->x - bmaporgx) >> MAPBLOCKSHIFT; const INT32 blocky = (unsigned)(thing->y - bmaporgy) >> MAPBLOCKSHIFT; @@ -780,8 +743,8 @@ static void P_LinkToBlockMap(mobj_t *thing, mobj_t **bmap) // pointer-to-pointer prev pointers -- // allows head nodes to be treated like everything else - mobj_t **link = &bmap[(blocky * bmapwidth) + blockx]; - mobj_t *bnext = *link; + T **link = &bmap[(blocky * bmapwidth) + blockx]; + T *bnext = *link; thing->bnext = bnext; @@ -909,10 +872,7 @@ void P_SetUnderlayPosition(mobj_t *thing) void P_SetPrecipitationThingPosition(precipmobj_t *thing) { thing->subsector = R_PointInSubsectorFast(thing->x, thing->y); - - // NOTE: this works because bnext/bprev are at the same - // offsets in precipmobj_t and mobj_t - P_LinkToBlockMap((mobj_t*)thing, (mobj_t**)precipblocklinks); + P_LinkToBlockMap(thing, precipblocklinks); } // @@ -1041,7 +1001,7 @@ static void P_CheckIntercepts(void) else max_intercepts *= 2; - intercepts = Z_Realloc(intercepts, sizeof (*intercepts) * max_intercepts, PU_STATIC, NULL); + intercepts = static_cast(Z_Realloc(intercepts, sizeof (*intercepts) * max_intercepts, PU_STATIC, NULL)); intercept_p = intercepts + count; } diff --git a/src/p_maputl.h b/src/p_maputl.h index d2337d007..c6c1a9d13 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -13,6 +13,10 @@ #ifndef __P_MAPUTL__ #define __P_MAPUTL__ +#ifdef __cplusplus +extern "C" { +#endif + #include "doomtype.h" #include "r_defs.h" #include "m_fixed.h" @@ -41,14 +45,26 @@ typedef boolean (*traverser_t)(intercept_t *in); boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, INT32 pflags, traverser_t ptrav); +// +// P_PointOnLineSide +// Returns 0 or 1 +// +FUNCINLINE static ATTRINLINE PUREFUNC INT32 P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line) +{ + return + !line->dx ? x <= line->v1->x ? line->dy > 0 : line->dy < 0 : + !line->dy ? y <= line->v1->y ? line->dx < 0 : line->dx > 0 : + FixedMul(y-line->v1->y, line->dx>>FRACBITS) >= + FixedMul(line->dy>>FRACBITS, x-line->v1->x); +} + #define P_AproxDistance(dx, dy) FixedHypot(dx, dy) void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result); -INT32 P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line); void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); -fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); -INT32 P_BoxOnLineSide(fixed_t *tmbox, const line_t *ld); +PUREFUNC fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); +PUREFUNC INT32 P_BoxOnLineSide(fixed_t *tmbox, const line_t *ld); void P_UnsetPrecipThingPosition(precipmobj_t *thing); void P_SetPrecipitationThingPosition(precipmobj_t *thing); void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y); @@ -74,4 +90,9 @@ extern fixed_t tmbbox[4]; // p_map.c // bbox defined by the radius //boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y, // boolean (*func)(line_t *)); + +#ifdef __cplusplus +} // extern "C" +#endif + #endif // __P_MAPUTL__ diff --git a/src/p_mobj.c b/src/p_mobj.c index ada4dbcdb..c7aa2051a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11,6 +11,7 @@ /// \file p_mobj.c /// \brief Moving object handling. Spawn functions +#include "d_think.h" #include "doomdef.h" #include "g_game.h" #include "g_input.h" @@ -38,8 +39,6 @@ #include "k_kart.h" // protos. -//static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}}; -//consvar_t cv_viewheight = {"viewheight", VIEWHEIGHTS, 0, viewheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef WALLSPLATS consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; #endif @@ -49,7 +48,6 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; mobj_t *waypointcap = NULL; -mobj_t *mobjcache = NULL; void P_InitCachedActions(void) { @@ -145,6 +143,8 @@ static void P_CyclePlayerMobjState(mobj_t *mobj) } } +#define MAX_RECURSION 20 + // // P_SetPlayerMobjState // Returns true if the mobj is still present. @@ -156,12 +156,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) state_t *st; player_t *player = mobj->player; - // remember states seen, to detect cycles: - static statenum_t seenstate_tab[NUMSTATES]; // fast transition table - statenum_t *seenstate = seenstate_tab; // pointer to table - static INT32 recursion; // detects recursion - statenum_t i; // initial state - statenum_t tempstate[NUMSTATES]; // for use with recursion + INT32 recursion = 0; #ifdef PARANOIA if (player == NULL) @@ -196,11 +191,6 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) break; } - if (recursion++) // if recursion detected, - memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table - - i = state; - do { if (UNLIKELY(state == S_NULL)) @@ -234,17 +224,14 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) return false; } - seenstate[state] = 1 + st->nextstate; - state = st->nextstate; - } while (!mobj->tics && !seenstate[state]); - if (UNLIKELY(!mobj->tics)) - CONS_Alert(CONS_WARNING, M_GetText("State cycle detected, exiting.\n")); - - if (!--recursion) - for (;(state = seenstate[i]) > S_NULL; i = state - 1) - seenstate[i] = S_NULL; // erase memory of states + if (++recursion > MAX_RECURSION) + { + CONS_Alert(CONS_WARNING, M_GetText("State cycle detected, exiting.\n")); + break; + } + } while (!mobj->tics); return true; } @@ -254,12 +241,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { state_t *st; - // remember states seen, to detect cycles: - static statenum_t seenstate_tab[NUMSTATES]; // fast transition table - statenum_t *seenstate = seenstate_tab; // pointer to table - static INT32 recursion; // detects recursion - statenum_t i = state; // initial state - statenum_t tempstate[NUMSTATES]; // for use with recursion + INT32 recursion = 0; #ifdef PARANOIA if (mobj->player != NULL) @@ -269,9 +251,6 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) if (mobj->player != NULL) return P_SetPlayerMobjState(mobj, state); - if (recursion++) // if recursion detected, - memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table - do { if (state == S_NULL) @@ -301,17 +280,14 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) return false; } - seenstate[state] = 1 + st->nextstate; - state = st->nextstate; - } while (!mobj->tics && !seenstate[state]); - if (UNLIKELY(!mobj->tics)) - CONS_Alert(CONS_WARNING, M_GetText("State cycle detected, exiting.\n")); - - if (!--recursion) - for (;(state = seenstate[i]) > S_NULL; i = state - 1) - seenstate[i] = S_NULL; // erase memory of states + if (++recursion > MAX_RECURSION) + { + CONS_Alert(CONS_WARNING, M_GetText("State cycle detected, exiting.\n")); + break; + } + } while (!mobj->tics); return true; } @@ -486,6 +462,8 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover) // usage will handle that later. static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, pslope_t *slope, boolean actuallylowest) { + int absval = 0; + // Alright, so we're sitting on a line that contains our slope sector, and need to figure out the highest point we're touching... // The solution is simple! Get the line's vertices, and pull each one in along its line until it touches the object's bounding box // (assuming it isn't already inside), then test each point's slope Z and return the higher of the two. @@ -495,73 +473,94 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, v2.x = line->v2->x; v2.y = line->v2->y; - if (abs(v1.x-x) > radius) + absval = abs(v1.x-x); + + if (absval > radius) { // v1's x is out of range, so rein it in - fixed_t diff = abs(v1.x-x) - radius; + fixed_t diff = absval - radius; - if (v1.x < x) { // Moving right + if (v1.x < x) // Moving right + { v1.x += diff; v1.y += FixedMul(diff, FixedDiv(line->dy, line->dx)); - } else { // Moving left + } + else // Moving left + { v1.x -= diff; v1.y -= FixedMul(diff, FixedDiv(line->dy, line->dx)); } } - if (abs(v1.y-y) > radius) + absval = abs(v1.y-y); + + if (absval > radius) { // v1's y is out of range, so rein it in - fixed_t diff = abs(v1.y-y) - radius; + fixed_t diff = absval - radius; - if (v1.y < y) { // Moving up + if (v1.y < y) // Moving up + { v1.y += diff; v1.x += FixedMul(diff, FixedDiv(line->dx, line->dy)); - } else { // Moving down + } + else // Moving down + { v1.y -= diff; v1.x -= FixedMul(diff, FixedDiv(line->dx, line->dy)); } } - if (abs(v2.x-x) > radius) + absval = abs(v2.x-x); + + if (absval > radius) { // v1's x is out of range, so rein it in - fixed_t diff = abs(v2.x-x) - radius; + fixed_t diff = absval - radius; - if (v2.x < x) { // Moving right + if (v2.x < x) // Moving right + { v2.x += diff; v2.y += FixedMul(diff, FixedDiv(line->dy, line->dx)); - } else { // Moving left + } + else // Moving left + { v2.x -= diff; v2.y -= FixedMul(diff, FixedDiv(line->dy, line->dx)); } } - if (abs(v2.y-y) > radius) + absval = abs(v2.y-y); + + if (absval > radius) { // v2's y is out of range, so rein it in - fixed_t diff = abs(v2.y-y) - radius; + fixed_t diff = absval - radius; - if (v2.y < y) { // Moving up + if (v2.y < y) // Moving up + { v2.y += diff; v2.x += FixedMul(diff, FixedDiv(line->dx, line->dy)); - } else { // Moving down + } + else // Moving down + { v2.y -= diff; v2.x -= FixedMul(diff, FixedDiv(line->dx, line->dy)); } } + const fixed_t v1z = P_GetSlopeZAt(slope, v1.x, v1.y); + const fixed_t v2z = P_GetSlopeZAt(slope, v2.x, v2.y); + // Return the higher of the two points if (actuallylowest) - return min( - P_GetSlopeZAt(slope, v1.x, v1.y), - P_GetSlopeZAt(slope, v2.x, v2.y) - ); + { + return min(v1z, v2z); + } else - return max( - P_GetSlopeZAt(slope, v1.x, v1.y), - P_GetSlopeZAt(slope, v2.x, v2.y) - ); + { + return max(v1z, v2z); + } } fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) @@ -615,6 +614,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t for (i = 0; i < boundsec->linecount; i++) { + fixed_t highline; ld = boundsec->lines[i]; if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] @@ -625,9 +625,15 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, true); + finalheight = min(finalheight, highline); + } else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, false); + finalheight = max(finalheight, highline); + } } return finalheight; @@ -695,6 +701,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed for (i = 0; i < boundsec->linecount; i++) { + fixed_t highline; ld = boundsec->lines[i]; if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] @@ -705,9 +712,15 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, true); + finalheight = min(finalheight, highline); + } else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, false); + finalheight = max(finalheight, highline); + } } return finalheight; @@ -776,6 +789,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix for (i = 0; i < boundsec->linecount; i++) { + fixed_t highline; ld = boundsec->lines[i]; if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] @@ -786,9 +800,15 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, true); + finalheight = min(finalheight, highline); + } else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, false); + finalheight = max(finalheight, highline); + } } return finalheight; @@ -856,6 +876,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f for (i = 0; i < boundsec->linecount; i++) { + fixed_t highline; ld = boundsec->lines[i]; if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT] @@ -866,9 +887,15 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f continue; if (lowest) - finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, true); + finalheight = min(finalheight, highline); + } else - finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); + { + highline = HighestOnLine(mobj->radius, x, y, ld, slope, false); + finalheight = max(finalheight, highline); + } } return finalheight; @@ -986,10 +1013,6 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (mo->player) { - //if ((mo->player->pflags & PF_GLIDING) - //|| (mo->player->charability == CA_FLY && (mo->player->powers[pw_tailsfly] - // || (mo->state >= &states[S_PLAY_SPC1] && mo->state <= &states[S_PLAY_SPC4])))) - // gravityadd = gravityadd/3; // less gravity while flying/gliding if (UNLIKELY(mo->player->climbing || (mo->player->pflags & PF_NIGHTSMODE))) return 0; @@ -1114,8 +1137,10 @@ static void P_SceneryXYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - if (abs(mo->momx) < FixedMul(FRACUNIT/32, mo->scale) - && abs(mo->momy) < FixedMul(FRACUNIT/32, mo->scale)) + const fixed_t fric_scale = FixedMul(FRACUNIT/32, mo->scale); + + if (abs(mo->momx) < fric_scale + && abs(mo->momy) < fric_scale) { mo->momx = 0; mo->momy = 0; @@ -1167,8 +1192,8 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) mo->momx = FixedMul(mo->momx, ns); mo->momy = FixedMul(mo->momy, ns); } - else if (abs(player->rmomx) < FixedMul(FRACUNIT, mo->scale) - && abs(player->rmomy) < FixedMul(FRACUNIT, mo->scale) + else if (abs(player->rmomx) < mo->scale + && abs(player->rmomy) < mo->scale && (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING)) && !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)) ) @@ -1242,7 +1267,7 @@ static void P_PushableCheckBustables(mobj_t *mo) if (rover->master->frontsector->crumblestate) continue; - topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); // Height checks @@ -1321,7 +1346,7 @@ void P_XYMovement(mobj_t *mo) fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls boolean moved; pslope_t *oldslope = NULL; - vector3_t slopemom = {0,0,0}; + vector3_t slopemom = {0, 0, 0}; fixed_t predictedz = 0; I_Assert(mo != NULL); @@ -1353,7 +1378,7 @@ void P_XYMovement(mobj_t *mo) oldy = mo->y; // adjust various things based on slope - if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) + if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT >> 8) { if (!P_IsObjectOnGround(mo)) // We fell off at some point? Do the twisty thing! { @@ -1746,7 +1771,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp || (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? continue; - topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); + topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); if (rover->flags & FF_QUICKSAND) @@ -1770,16 +1795,18 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp } } - delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2)); - delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + const fixed_t mid = (bottomheight + ((topheight - bottomheight) / 2)); - if (topheight > mo->floorz && abs(delta1) < abs(delta2) + delta1 = abs(mo->z - mid); + delta2 = abs(thingtop - mid); + + if (topheight > mo->floorz && delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) { mo->floorz = topheight; } - if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) + if (bottomheight < mo->ceilingz && delta1 >= delta2 && !(rover->flags & FF_PLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below { @@ -1828,13 +1855,15 @@ static void P_AdjustMobjFloorZ_PolyObjs(mobj_t *mo, subsector_t *subsec) polybottom = INT32_MIN; } - delta1 = mo->z - (polybottom + ((polytop - polybottom)/2)); - delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); + const fixed_t mid = polybottom + ((polytop - polybottom) / 2); - if (polytop > mo->floorz && abs(delta1) < abs(delta2)) + delta1 = abs(mo->z - mid); + delta2 = abs(thingtop - mid); + + if (polytop > mo->floorz && delta1 < delta2) mo->floorz = polytop; - if (polybottom < mo->ceilingz && abs(delta1) >= abs(delta2)) + if (polybottom < mo->ceilingz && delta1 >= delta2) mo->ceilingz = polybottom; po = (polyobj_t *)(po->link.next); @@ -3284,9 +3313,10 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSightFast(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. P_ResetCamera(player, thiscam); +#ifndef NOCLIPCAM else P_SlideCameraMove(thiscam); - +#endif if (resetcalled) // Okay this means the camera is fully reset. return true; } @@ -6172,6 +6202,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) fixed_t x = P_RandomRange(-35, 35)*mobj->scale; fixed_t y = P_RandomRange(-35, 35)*mobj->scale; fixed_t z = P_RandomRange(0, 70)*mobj->scale; + mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); P_SetMobjState(smoke, S_OPAQUESMOKE1); K_MatchGenericExtraFlags(smoke, mobj); @@ -6185,6 +6216,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) fixed_t x = P_RandomRange(-16, 16)*mobj->scale; fixed_t y = P_RandomRange(-16, 16)*mobj->scale; fixed_t z = P_RandomRange(0, 32)*mobj->scale*P_MobjFlip(mobj); + if (leveltime % 2 == 0) { mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE); @@ -7541,7 +7573,8 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { if (mobj->tracer->player) { - fixed_t speeddifference = abs(topspeed - min(mobj->tracer->player->speed, K_GetKartSpeed(mobj->tracer->player, false))); + const fixed_t pspeed = K_GetKartSpeed(mobj->tracer->player, false); + fixed_t speeddifference = abs(topspeed - min(mobj->tracer->player->speed, pspeed)); topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); } } @@ -7762,7 +7795,13 @@ static boolean P_MobjRegularThink(mobj_t *mobj) smoke->momy = mobj->target->momy/2; smoke->momz = mobj->target->momz/2; - P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<target->scale); + fixed_t rand_angle; + fixed_t rand_move; + + rand_move = P_RandomRange(0, 8) * mobj->target->scale; + rand_angle = mobj->angle+FixedAngle(P_RandomRange(135, 225)<x + (P_RandomRange(-48,48)*mobj->scale), - mobj->y + (P_RandomRange(-48,48)*mobj->scale), - mobj->z + (24*mobj->scale) + (P_RandomRange(-8,8)*mobj->scale), - MT_SIGNSPARKLE); + fixed_t rand_x; + fixed_t rand_y; + fixed_t rand_z; + + rand_z = mobj->z + (24*mobj->scale) + (P_RandomRange(-8,8)*mobj->scale); + rand_y = mobj->y + (P_RandomRange(-48,48)*mobj->scale); + rand_x = mobj->x + (P_RandomRange(-48,48)*mobj->scale); + + P_SpawnMobj(rand_x, rand_y, rand_z, MT_SIGNSPARKLE); + mobj->flags &= ~MF_NOGRAVITY; + if (abs(mobj->z - mobj->movefactor) <= (512*mobj->scale) && !mobj->cvmem) { if (mobj->info->seesound) @@ -8064,6 +8110,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { angle_t facing = P_RandomRange(0, 90); + if (facing >= 45) facing = InvAngle((facing - 45)*ANG1); else @@ -8096,7 +8143,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj) else // fire + smoke pillar { UINT8 i; - mobj_t *fire = P_SpawnMobj(mobj->x + (P_RandomRange(-32, 32)*mobj->scale), mobj->y + (P_RandomRange(-32, 32)*mobj->scale), mobj->z, MT_THOK); + + fixed_t rand_x; + fixed_t rand_y; + + rand_y = mobj->y + (P_RandomRange(-32, 32)*mobj->scale); + rand_x = mobj->x + (P_RandomRange(-32, 32)*mobj->scale); + + mobj_t *fire = P_SpawnMobj(rand_x, rand_y, mobj->z, MT_THOK); fire->sprite = SPR_FPRT; fire->frame = FF_FULLBRIGHT|FF_TRANS30; @@ -8108,7 +8162,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) for (i = 0; i < 2; i++) { - mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-16, 16)*mobj->scale), mobj->y + (P_RandomRange(-16, 16)*mobj->scale), mobj->z, MT_SMOKE); + rand_y = mobj->y + (P_RandomRange(-16, 16)*mobj->scale); + rand_x = mobj->x + (P_RandomRange(-16, 16)*mobj->scale); + + mobj_t *smoke = P_SpawnMobj(rand_x, rand_y, mobj->z, MT_SMOKE); P_SetMobjState(smoke, S_FZSLOWSMOKE1); smoke->scale = mobj->scale; @@ -8133,8 +8190,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj) cur = cur->hnext; } } + if (!S_SoundPlaying(mobj, mobj->info->seesound)) S_StartSound(mobj, mobj->info->seesound); + break; case MT_FROGGER: { @@ -8332,9 +8391,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (!P_MobjWasRemoved(mobj->tracer) && !(leveltime % 10)) { - mobj_t *dust = P_SpawnMobj(mobj->x + (P_RandomRange(-4, 4)<y + (P_RandomRange(-4, 4)<z + (P_RandomRange(0, 2)<z + (P_RandomRange(0, 2)<y + (P_RandomRange(-4, 4)<x + (P_RandomRange(-4, 4)<scale/2); P_InstaThrust(dust, FixedAngle(P_RandomRange(0,359)<tracer->momz)/2); @@ -9210,7 +9275,7 @@ void P_PushableThinker(mobj_t *mobj) sec = mobj->subsector->sector; - if (GETSECSPECIAL(sec->special, 2) == 1 && mobj->z == sec->floorheight) + if (mobj->z == sec->floorheight && GETSECSPECIAL(sec->special, 2) == 1) P_LinedefExecute(sec->tag, mobj, sec); { sector_t *sec2; @@ -9363,21 +9428,11 @@ void P_SceneryThinker(mobj_t *mobj) // GAME SPAWN FUNCTIONS // -FUNCINLINE static ATTRINLINE mobj_t *P_AllocMobj(void) +mobj_t *P_AllocateMobj(void) { - mobj_t *mobj; - - if (mobjcache != NULL) - { - mobj = mobjcache; - mobjcache = mobjcache->hnext; - memset(mobj, 0, sizeof(*mobj)); - } - else - { - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - } - + mobj_t* mobj = (mobj_t*)Z_LevelPoolCalloc(sizeof(mobj_t)); + mobj->thinker.alloctype = TAT_LEVELPOOL; + mobj->thinker.size = sizeof(mobj_t); return mobj; } @@ -9390,7 +9445,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) state_t *st; mobj_t *mobj; - mobj = P_AllocMobj(); + mobj = P_AllocateMobj(); // this is officially a mobj, declared as soon as possible. mobj->thinker.function = (actionf_p1)P_MobjThinker; @@ -9841,7 +9896,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) state_t *st; mobj_t *mobj; - mobj = P_AllocMobj(); + mobj = P_AllocateMobj(); // this is officially a mobj, declared as soon as possible. mobj->thinker.function = (actionf_p1)P_MobjThinker; @@ -9955,7 +10010,9 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype { const mobjinfo_t *info = &mobjinfo[type]; state_t *st; - precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + precipmobj_t *mobj = Z_LevelPoolCalloc(sizeof(precipmobj_t)); + mobj->thinker.alloctype = TAT_LEVELPOOL; + mobj->thinker.size = sizeof(precipmobj_t); fixed_t starting_floorz; mobj->type = type; @@ -10111,14 +10168,6 @@ void P_RemoveMobj(mobj_t *mobj) // free block if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! - if (!mobj->thinker.references) - { - // no references, dump it directly in the mobj cache - mobj->hnext = mobjcache; - mobjcache = mobj; - return; - } - // Add thinker just to delay removing it until refrences are gone. mobj->flags &= ~MF_NOTHINK; P_AddThinker((thinker_t *)mobj); @@ -10169,8 +10218,7 @@ void P_RemoveSavegameMobj(mobj_t *mobj) R_RemoveMobjInterpolator(mobj); // just set its reference count to 0 to not trigger the assert in P_UnlinkThinker - if (th->references != 0) - th->references = 0; + th->references = 0; // free block // Here we use the same code as R_RemoveThinkerDelayed, but without reference counting (we're removing everything so it shouldn't matter) and without touching currentthinker since we aren't in P_RunThinkers @@ -10225,7 +10273,7 @@ void P_SpawnPrecipitation(void) continue; // Exists, but is too small for reasonable precipitation. - if (FixedDiv(precipsector->sector->ceilingheight - precipsector->sector->floorheight, mapobjectscale) < 64<sector->ceilingheight - precipsector->sector->floorheight, mapobjectscale) < 256<spectator) { - if (playernum == consoleplayer) - camera[0].freecam = false; - else if (splitscreen) + for (UINT8 i = 0; i <= splitscreen; i++) { - for (i = 1; i <= splitscreen; i++) + if (playernum == P_GetLocalPlayerNumForNum(i)) { - if (playernum == displayplayers[i]) - { - camera[i].freecam = false; - break; - } + camera[i].freecam = false; + break; } } } diff --git a/src/p_mobj.h b/src/p_mobj.h index 0967b1dd5..eed259ba3 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -272,6 +272,10 @@ typedef struct mobj_s // List: thinker links. thinker_t thinker; + // More list: links in sector (if needed) + struct mobj_s *bnext; + struct mobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr + // Info for drawing: position. fixed_t x, y, z; fixed_t old_x, old_y, old_z; // position interpolation @@ -280,10 +284,6 @@ typedef struct mobj_s mobjtype_t type; const mobjinfo_t *info; // &mobjinfo[mobj->type] - // More list: links in sector (if needed) - struct mobj_s *bnext; - struct mobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr - // More drawing info: to determine current sprite. angle_t angle, pitch, roll; // orientation angle_t old_angle, old_pitch, old_roll; // orientation interpolation @@ -293,7 +293,7 @@ typedef struct mobj_s UINT32 frame; // frame number, plus bits see p_pspr.h UINT16 anim_duration; // for FF_ANIMATE states - INT32 blendmode; // blend mode + UINT8 blendmode; // blend mode fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; fixed_t old_spritexscale, old_spriteyscale; @@ -329,19 +329,12 @@ typedef struct mobj_s fixed_t momx, momy, momz; fixed_t pmomz; // If you're on a moving floor, its "momz" would be here - INT32 tics; // state tic counter state_t *state; + INT32 tics; // state tic counter UINT32 flags; // flags from mobjinfo tables UINT32 flags2; // MF2_ flags UINT16 eflags; // extra flags - void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) - void *localskin; - boolean skinlocal; - // Player and mobj sprites in multiplayer modes are modified - // using an internal color lookup table for re-indexing. - UINT8 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). - // Interaction info, by BLOCKMAP. // Links in blocks (if needed). struct mobj_s *snext; @@ -351,22 +344,30 @@ typedef struct mobj_s struct mobj_s *hnext; struct mobj_s *hprev; + void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) + void *localskin; + boolean skinlocal; + + // Player and mobj sprites in multiplayer modes are modified + // using an internal color lookup table for re-indexing. + UINT8 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). + INT32 health; // for player this is rings + 1 // Movement direction, movement generation (zig-zagging). angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle INT32 movecount; // when 0, select a new dir - struct mobj_s *target; // Thing being chased/attacked (or NULL), and originator for missiles. - INT32 reactiontime; // If not 0, don't attack yet. - INT32 threshold; // If >0, the target will be chased no matter what. + struct mobj_s *target; // Thing being chased/attacked (or NULL), and originator for missiles. // Additional info record for player avatars only. // Only valid if type == MT_PLAYER struct player_s *player; + INT32 threshold; // If >0, the target will be chased no matter what. + INT32 lastlook; // Player number last looked for. mapthing_t *spawnpoint; // Used for CTF flags, objectplace, and a handful other applications. @@ -429,47 +430,24 @@ typedef struct precipmobj_s // List: thinker links. thinker_t thinker; - // Info for drawing: position. - fixed_t x, y, z; - fixed_t old_x, old_y, old_z; // position interpolation - fixed_t old_x2, old_y2, old_z2; - - mobjtype_t type; - const mobjinfo_t *info; // &mobjinfo[mobj->type] - // More list: links in sector (if needed) struct precipmobj_s *bnext; struct precipmobj_s **bprev; // killough 8/11/98: change to ptr-to-ptr + // Info for drawing: position. + fixed_t x, y, z; + fixed_t old_x, old_y, old_z; // position interpolation + + mobjtype_t type; + const mobjinfo_t *info; // &mobjinfo[mobj->type] + // More drawing info: to determine current sprite. - angle_t angle, pitch, roll; // orientation - angle_t old_angle, old_pitch, old_roll; // orientation interpolation - angle_t old_angle2, old_pitch2, old_roll2; - angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h UINT16 anim_duration; // for FF_ANIMATE states - INT32 blendmode; // blend mode - fixed_t spritexscale, spriteyscale; - fixed_t spritexoffset, spriteyoffset; - fixed_t old_spritexscale, old_spriteyscale; - fixed_t old_spritexscale2, old_spriteyscale2; - fixed_t old_spritexoffset, old_spriteyoffset; - fixed_t old_spritexoffset2, old_spriteyoffset2; INT16 lightlevel; // Add to sector lightlevel, -255 - 255 - fixed_t realxscale, realyscale; // funn-E streeetch - fixed_t realxoffset, realyoffset; - - fixed_t stretchslam; // "squish" effect when you land - - //sloperollangle - angle_t sloperoll, slopepitch; - angle_t old_sloperoll, old_slopepitch; - angle_t old_sloperoll2, old_slopepitch2; - angle_t pitch_sprite, roll_sprite; - struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct subsector_s *subsector; // Subsector the mobj resides in. @@ -478,17 +456,13 @@ typedef struct precipmobj_s fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. - // For movement checking. - fixed_t radius; // Fixed at 2*FRACUNIT - fixed_t height; // Fixed at 4*FRACUNIT - // Momentums, used to update position. fixed_t momx, momy, momz; fixed_t precipflags; // fixed_t so it uses the same spot as "pmomz" even as we use precipflags_t for it - INT32 tics; // state tic counter state_t *state; - INT32 flags; // flags from mobjinfo tables + INT32 tics; // state tic counter + UINT32 flags; // flags from mobjinfo tables tic_t lastThink; } precipmobj_t; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 27463fbac..5e5590ced 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -155,7 +155,6 @@ FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th) thinkercap.next = th; th->references = 0; - th->cachable = false; // not initialising this made the mobjcache die thx! #ifdef PARANOIA th->debug_mobjtype = MT_NULL; #endif @@ -443,8 +442,6 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) if (r != po->segCount) continue; - segs[s].dontrenderme = true; - Polyobj_addSeg(po, &segs[s]); } } @@ -503,7 +500,6 @@ newseg: if (r != po->segCount) continue; - segs[q].dontrenderme = true; Polyobj_addSeg(po, &segs[q]); } } @@ -998,7 +994,7 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) vertex_t closest; // calculate angle of line and subtract 90 degrees to get normal - lineangle = R_PointToAngle2(0, 0, line->dx, line->dy) - ANGLE_90; + lineangle = line->angle - ANGLE_90; lineangle >>= ANGLETOFINESHIFT; momx = FixedMul(po->thrust, FINECOSINE(lineangle)); momy = FixedMul(po->thrust, FINESINE(lineangle)); @@ -1274,6 +1270,8 @@ static void Polyobj_rotateLine(line_t *ld) ld->dx = v2->x - v1->x; ld->dy = v2->y - v1->y; + ld->angle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + // determine slopetype ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL : FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE; @@ -1381,16 +1379,18 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, Polyobj_slideThing(mo, newxoff-oldxoff, newyoff-oldyoff); - if (turnthings == 2 || (turnthings == 1 && !mo->player)) { + if (turnthings == 2 || (turnthings == 1 && !mo->player)) + { mo->angle += delta; - if (mo->player == &players[consoleplayer]) - localangle[0] += delta; - else if (mo->player == &players[displayplayers[1]]) - localangle[1] += delta; - else if (mo->player == &players[displayplayers[2]]) - localangle[2] += delta; - else if (mo->player == &players[displayplayers[3]]) - localangle[3] += delta; + + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (mo->player == P_GetLocalPlayerForNum(i)) + { + localangle[i] += delta; + break; + } + } } } } @@ -2356,7 +2356,9 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata) return 0; // create a new thinker - th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polyrotate_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polyrotate_t); th->thinker.function = (actionf_p1)T_PolyObjRotate; PolyObj_AddThinker(&th->thinker); po->thinker = &th->thinker; @@ -2424,7 +2426,9 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata) return 0; // create a new thinker - th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polymove_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polymove_t); th->thinker.function = (actionf_p1)T_PolyObjMove; PolyObj_AddThinker(&th->thinker); po->thinker = &th->thinker; @@ -2490,7 +2494,9 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) return 0; // create a new thinker - th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polywaypoint_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polywaypoint_t); th->thinker.function = (actionf_p1)T_PolyObjWaypoint; PolyObj_AddThinker(&th->thinker); po->thinker = &th->thinker; @@ -2626,7 +2632,9 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata) INT32 start; // allocate and add a new slide door thinker - th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polyslidedoor_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polyslidedoor_t); th->thinker.function = (actionf_p1)T_PolyDoorSlide; PolyObj_AddThinker(&th->thinker); @@ -2677,7 +2685,9 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata) INT32 start; // allocate and add a new swing door thinker - th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polyswingdoor_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polyswingdoor_t); th->thinker.function = (actionf_p1)T_PolyDoorSwing; PolyObj_AddThinker(&th->thinker); @@ -2762,7 +2772,9 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata) return 0; // create a new thinker - th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polydisplace_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polydisplace_t); th->thinker.function = (actionf_p1)T_PolyObjDisplace; PolyObj_AddThinker(&th->thinker); po->thinker = &th->thinker; @@ -2866,7 +2878,9 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) } // create a new thinker - th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); + th = Z_LevelPoolMalloc(sizeof(polymove_t)); + th->thinker.alloctype = TAT_LEVELPOOL; + th->thinker.size = sizeof(polymove_t); th->thinker.function = (actionf_p1)T_PolyObjFlag; PolyObj_AddThinker(&th->thinker); po->thinker = &th->thinker; @@ -2875,7 +2889,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) th->polyObjNum = pfdata->tag; th->distance = 0; th->speed = P_AproxDistance(pfdata->dx, pfdata->dy)>>FRACBITS; - th->angle = R_PointToAngle2(pfdata->v1->x, pfdata->v1->y, pfdata->v2->x, pfdata->v2->y)>>ANGLETOFINESHIFT; + th->angle = pfdata->angle >> ANGLETOFINESHIFT; th->momx = sides[pfdata->sidenum[0]].textureoffset>>FRACBITS; // save current positions @@ -2899,5 +2913,4 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) return 1; } - // EOF diff --git a/src/p_saveg.c b/src/p_saveg.c index b95e1a09e..e1e280e4b 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -11,6 +11,7 @@ /// \file p_saveg.c /// \brief Archiving: SaveGame I/O +#include "d_think.h" #include "doomdef.h" #include "byteptr.h" #include "d_main.h" @@ -111,7 +112,6 @@ static void P_NetArchivePlayers(savebuffer_t *save, boolean resending) { INT32 i, j; UINT16 flags; -// size_t q; WRITEUINT32(save->p, ARCHIVEBLOCK_PLAYERS); @@ -130,166 +130,168 @@ static void P_NetArchivePlayers(savebuffer_t *save, boolean resending) if (resending) WRITESTRINGN(save->p, player_names[i], MAXPLAYERNAME); - WRITEANGLE(save->p, players[i].aiming); - WRITEANGLE(save->p, players[i].awayviewaiming); - WRITEINT32(save->p, players[i].awayviewtics); - WRITEINT32(save->p, players[i].health); + const player_t *player = &players[i]; - WRITESINT8(save->p, players[i].pity); - WRITEINT32(save->p, players[i].currentweapon); - WRITEINT32(save->p, players[i].ringweapons); + WRITEANGLE(save->p, player->aiming); + WRITEANGLE(save->p, player->awayviewaiming); + WRITEINT32(save->p, player->awayviewtics); + WRITEINT32(save->p, player->health); + + WRITESINT8(save->p, player->pity); + WRITEINT32(save->p, player->currentweapon); + WRITEINT32(save->p, player->ringweapons); for (j = 0; j < NUMPOWERS; j++) - WRITEUINT16(save->p, players[i].powers[j]); + WRITEUINT16(save->p, player->powers[j]); for (j = 0; j < NUMKARTSTUFF; j++) - WRITEINT32(save->p, players[i].kartstuff[j]); + WRITEINT32(save->p, player->kartstuff[j]); - WRITEANGLE(save->p, players[i].frameangle); + WRITEANGLE(save->p, player->frameangle); - WRITEUINT8(save->p, players[i].playerstate); - WRITEUINT32(save->p, players[i].pflags); - WRITEUINT8(save->p, players[i].panim); - WRITEUINT8(save->p, players[i].spectator); + WRITEUINT8(save->p, player->playerstate); + WRITEUINT32(save->p, player->pflags); + WRITEUINT8(save->p, player->panim); + WRITEUINT8(save->p, player->spectator); - WRITEUINT16(save->p, players[i].flashpal); - WRITEUINT16(save->p, players[i].flashcount); + WRITEUINT16(save->p, player->flashpal); + WRITEUINT16(save->p, player->flashcount); if (resending) { - WRITEUINT8(save->p, players[i].skincolor); - WRITEINT32(save->p, players[i].skin); + WRITEUINT8(save->p, player->skincolor); + WRITEINT32(save->p, player->skin); } - WRITEUINT32(save->p, players[i].score); - WRITEFIXED(save->p, players[i].dashspeed); - WRITEINT32(save->p, players[i].dashtime); - WRITESINT8(save->p, players[i].lives); - WRITESINT8(save->p, players[i].continues); - WRITESINT8(save->p, players[i].xtralife); - WRITEUINT8(save->p, players[i].gotcontinue); - WRITEFIXED(save->p, players[i].speed); - WRITEUINT8(save->p, players[i].jumping); - WRITEUINT8(save->p, players[i].secondjump); - WRITEUINT8(save->p, players[i].fly1); - WRITEUINT8(save->p, players[i].scoreadd); - WRITEUINT32(save->p, players[i].glidetime); - WRITEUINT8(save->p, players[i].climbing); - WRITEINT32(save->p, players[i].deadtimer); - WRITEUINT32(save->p, players[i].exiting); - WRITEUINT8(save->p, players[i].homing); - WRITEUINT32(save->p, players[i].skidtime); + WRITEUINT32(save->p, player->score); + WRITEFIXED(save->p, player->dashspeed); + WRITEINT32(save->p, player->dashtime); + WRITESINT8(save->p, player->lives); + WRITESINT8(save->p, player->continues); + WRITESINT8(save->p, player->xtralife); + WRITEUINT8(save->p, player->gotcontinue); + WRITEFIXED(save->p, player->speed); + WRITEUINT8(save->p, player->jumping); + WRITEUINT8(save->p, player->secondjump); + WRITEUINT8(save->p, player->fly1); + WRITEUINT8(save->p, player->scoreadd); + WRITEUINT32(save->p, player->glidetime); + WRITEUINT8(save->p, player->climbing); + WRITEINT32(save->p, player->deadtimer); + WRITEUINT32(save->p, player->exiting); + WRITEUINT8(save->p, player->homing); + WRITEUINT32(save->p, player->skidtime); //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - WRITEFIXED(save->p, players[i].cmomx); // Conveyor momx - WRITEFIXED(save->p, players[i].cmomy); // Conveyor momy - WRITEFIXED(save->p, players[i].rmomx); // "Real" momx (momx - cmomx) - WRITEFIXED(save->p, players[i].rmomy); // "Real" momy (momy - cmomy) + WRITEFIXED(save->p, player->cmomx); // Conveyor momx + WRITEFIXED(save->p, player->cmomy); // Conveyor momy + WRITEFIXED(save->p, player->rmomx); // "Real" momx (momx - cmomx) + WRITEFIXED(save->p, player->rmomy); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - WRITEINT16(save->p, players[i].numboxes); - WRITEINT16(save->p, players[i].totalring); - WRITEUINT32(save->p, players[i].realtime); - WRITEUINT8(save->p, players[i].laps); + WRITEINT16(save->p, player->numboxes); + WRITEINT16(save->p, player->totalring); + WRITEUINT32(save->p, player->realtime); + WRITEUINT8(save->p, player->laps); //////////////////// // CTF Mode Stuff // //////////////////// - WRITEINT32(save->p, players[i].ctfteam); - WRITEUINT16(save->p, players[i].gotflag); + WRITEINT32(save->p, player->ctfteam); + WRITEUINT16(save->p, player->gotflag); - WRITEINT32(save->p, players[i].weapondelay); - WRITEINT32(save->p, players[i].tossdelay); + WRITEINT32(save->p, player->weapondelay); + WRITEINT32(save->p, player->tossdelay); - WRITEUINT32(save->p, players[i].starposttime); - WRITEINT16(save->p, players[i].starpostx); - WRITEINT16(save->p, players[i].starposty); - WRITEINT16(save->p, players[i].starpostz); - WRITEINT32(save->p, players[i].starpostnum); - WRITEANGLE(save->p, players[i].starpostangle); + WRITEUINT32(save->p, player->starposttime); + WRITEINT16(save->p, player->starpostx); + WRITEINT16(save->p, player->starposty); + WRITEINT16(save->p, player->starpostz); + WRITEINT32(save->p, player->starpostnum); + WRITEANGLE(save->p, player->starpostangle); - WRITEANGLE(save->p, players[i].angle_pos); - WRITEANGLE(save->p, players[i].old_angle_pos); + WRITEANGLE(save->p, player->angle_pos); + WRITEANGLE(save->p, player->old_angle_pos); - WRITEINT32(save->p, players[i].flyangle); - WRITEUINT32(save->p, players[i].drilltimer); - WRITEINT32(save->p, players[i].linkcount); - WRITEUINT32(save->p, players[i].linktimer); - WRITEINT32(save->p, players[i].anotherflyangle); - WRITEUINT32(save->p, players[i].nightstime); - WRITEUINT32(save->p, players[i].bumpertime); - WRITEINT32(save->p, players[i].drillmeter); - WRITEUINT8(save->p, players[i].drilldelay); - WRITEUINT8(save->p, players[i].bonustime); - WRITEUINT8(save->p, players[i].mare); + WRITEINT32(save->p, player->flyangle); + WRITEUINT32(save->p, player->drilltimer); + WRITEINT32(save->p, player->linkcount); + WRITEUINT32(save->p, player->linktimer); + WRITEINT32(save->p, player->anotherflyangle); + WRITEUINT32(save->p, player->nightstime); + WRITEUINT32(save->p, player->bumpertime); + WRITEINT32(save->p, player->drillmeter); + WRITEUINT8(save->p, player->drilldelay); + WRITEUINT8(save->p, player->bonustime); + WRITEUINT8(save->p, player->mare); - WRITEUINT32(save->p, players[i].marebegunat); - WRITEUINT32(save->p, players[i].startedtime); - WRITEUINT32(save->p, players[i].finishedtime); - WRITEINT16(save->p, players[i].finishedrings); - WRITEUINT32(save->p, players[i].marescore); - WRITEUINT32(save->p, players[i].lastmarescore); - WRITEUINT8(save->p, players[i].lastmare); - WRITEINT32(save->p, players[i].maxlink); - WRITEUINT8(save->p, players[i].texttimer); - WRITEUINT8(save->p, players[i].textvar); + WRITEUINT32(save->p, player->marebegunat); + WRITEUINT32(save->p, player->startedtime); + WRITEUINT32(save->p, player->finishedtime); + WRITEINT16(save->p, player->finishedrings); + WRITEUINT32(save->p, player->marescore); + WRITEUINT32(save->p, player->lastmarescore); + WRITEUINT8(save->p, player->lastmare); + WRITEINT32(save->p, player->maxlink); + WRITEUINT8(save->p, player->texttimer); + WRITEUINT8(save->p, player->textvar); - if (players[i].capsule) + if (player->capsule) flags |= CAPSULE; - if (players[i].awayviewmobj) + if (player->awayviewmobj) flags |= AWAYVIEW; - if (players[i].axis1) + if (player->axis1) flags |= FIRSTAXIS; - if (players[i].axis2) + if (player->axis2) flags |= SECONDAXIS; - WRITEINT16(save->p, players[i].lastsidehit); - WRITEINT16(save->p, players[i].lastlinehit); + WRITEINT16(save->p, player->lastsidehit); + WRITEINT16(save->p, player->lastlinehit); - WRITEUINT32(save->p, players[i].losstime); + WRITEUINT32(save->p, player->losstime); - WRITEUINT8(save->p, players[i].timeshit); + WRITEUINT8(save->p, player->timeshit); - WRITEINT32(save->p, players[i].onconveyor); + WRITEINT32(save->p, player->onconveyor); - WRITEUINT32(save->p, players[i].jointime); - WRITEUINT32(save->p, players[i].spectatorreentry); + WRITEUINT32(save->p, player->jointime); + WRITEUINT32(save->p, player->spectatorreentry); - WRITEUINT32(save->p, players[i].grieftime); - WRITEUINT8(save->p, players[i].griefstrikes); + WRITEUINT32(save->p, player->grieftime); + WRITEUINT8(save->p, player->griefstrikes); - WRITEUINT8(save->p, players[i].splitscreenindex); + WRITEUINT8(save->p, player->splitscreenindex); WRITEUINT16(save->p, flags); if (flags & CAPSULE) - WRITEUINT32(save->p, players[i].capsule->mobjnum); + WRITEUINT32(save->p, player->capsule->mobjnum); if (flags & FIRSTAXIS) - WRITEUINT32(save->p, players[i].axis1->mobjnum); + WRITEUINT32(save->p, player->axis1->mobjnum); if (flags & SECONDAXIS) - WRITEUINT32(save->p, players[i].axis2->mobjnum); + WRITEUINT32(save->p, player->axis2->mobjnum); if (flags & AWAYVIEW) - WRITEUINT32(save->p, players[i].awayviewmobj->mobjnum); + WRITEUINT32(save->p, player->awayviewmobj->mobjnum); - WRITEUINT32(save->p, players[i].charflags); + WRITEUINT32(save->p, player->charflags); // SRB2kart - WRITEUINT8(save->p, players[i].kartspeed); - WRITEUINT8(save->p, players[i].kartweight); + WRITEUINT8(save->p, player->kartspeed); + WRITEUINT8(save->p, player->kartweight); // for (j = 0; j < MAXPREDICTTICS; j++) { - WRITEINT16(save->p, players[i].lturn_max[j]); - WRITEINT16(save->p, players[i].rturn_max[j]); + WRITEINT16(save->p, player->lturn_max[j]); + WRITEINT16(save->p, player->rturn_max[j]); } } } @@ -321,157 +323,159 @@ static void P_NetUnArchivePlayers(savebuffer_t *save, boolean reloading) if (reloading) READSTRINGN(save->p, player_names[i], MAXPLAYERNAME); - players[i].aiming = READANGLE(save->p); - players[i].awayviewaiming = READANGLE(save->p); - players[i].awayviewtics = READINT32(save->p); - players[i].health = READINT32(save->p); + player_t *player = &players[i]; - players[i].pity = READSINT8(save->p); - players[i].currentweapon = READINT32(save->p); - players[i].ringweapons = READINT32(save->p); + player->aiming = READANGLE(save->p); + player->awayviewaiming = READANGLE(save->p); + player->awayviewtics = READINT32(save->p); + player->health = READINT32(save->p); + + player->pity = READSINT8(save->p); + player->currentweapon = READINT32(save->p); + player->ringweapons = READINT32(save->p); for (j = 0; j < NUMPOWERS; j++) - players[i].powers[j] = READUINT16(save->p); + player->powers[j] = READUINT16(save->p); for (j = 0; j < NUMKARTSTUFF; j++) - players[i].kartstuff[j] = READINT32(save->p); + player->kartstuff[j] = READINT32(save->p); - players[i].frameangle = READANGLE(save->p); + player->frameangle = READANGLE(save->p); - players[i].playerstate = READUINT8(save->p); - players[i].pflags = READUINT32(save->p); - players[i].panim = READUINT8(save->p); - players[i].spectator = READUINT8(save->p); + player->playerstate = READUINT8(save->p); + player->pflags = READUINT32(save->p); + player->panim = READUINT8(save->p); + player->spectator = READUINT8(save->p); - players[i].flashpal = READUINT16(save->p); - players[i].flashcount = READUINT16(save->p); + player->flashpal = READUINT16(save->p); + player->flashcount = READUINT16(save->p); if (reloading) { - players[i].skincolor = READUINT8(save->p); - players[i].skin = READINT32(save->p); + player->skincolor = READUINT8(save->p); + player->skin = READINT32(save->p); } - players[i].score = READUINT32(save->p); - players[i].dashspeed = READFIXED(save->p); // dashing speed - players[i].dashtime = READINT32(save->p); // dashing speed - players[i].lives = READSINT8(save->p); - players[i].continues = READSINT8(save->p); // continues that player has acquired - players[i].xtralife = READSINT8(save->p); // Ring Extra Life counter - players[i].gotcontinue = READUINT8(save->p); // got continue from stage - players[i].speed = READFIXED(save->p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].jumping = READUINT8(save->p); // Jump counter - players[i].secondjump = READUINT8(save->p); - players[i].fly1 = READUINT8(save->p); // Tails flying - players[i].scoreadd = READUINT8(save->p); // Used for multiple enemy attack bonus - players[i].glidetime = READUINT32(save->p); // Glide counter for thrust - players[i].climbing = READUINT8(save->p); // Climbing on the wall - players[i].deadtimer = READINT32(save->p); // End game if game over lasts too long - players[i].exiting = READUINT32(save->p); // Exitlevel timer - players[i].homing = READUINT8(save->p); // Are you homing? - players[i].skidtime = READUINT32(save->p); // Skid timer + player->score = READUINT32(save->p); + player->dashspeed = READFIXED(save->p); // dashing speed + player->dashtime = READINT32(save->p); // dashing speed + player->lives = READSINT8(save->p); + player->continues = READSINT8(save->p); // continues that player has acquired + player->xtralife = READSINT8(save->p); // Ring Extra Life counter + player->gotcontinue = READUINT8(save->p); // got continue from stage + player->speed = READFIXED(save->p); // Player's speed (distance formula of MOMX and MOMY values) + player->jumping = READUINT8(save->p); // Jump counter + player->secondjump = READUINT8(save->p); + player->fly1 = READUINT8(save->p); // Tails flying + player->scoreadd = READUINT8(save->p); // Used for multiple enemy attack bonus + player->glidetime = READUINT32(save->p); // Glide counter for thrust + player->climbing = READUINT8(save->p); // Climbing on the wall + player->deadtimer = READINT32(save->p); // End game if game over lasts too long + player->exiting = READUINT32(save->p); // Exitlevel timer + player->homing = READUINT8(save->p); // Are you homing? + player->skidtime = READUINT32(save->p); // Skid timer //////////////////////////// // Conveyor Belt Movement // //////////////////////////// - players[i].cmomx = READFIXED(save->p); // Conveyor momx - players[i].cmomy = READFIXED(save->p); // Conveyor momy - players[i].rmomx = READFIXED(save->p); // "Real" momx (momx - cmomx) - players[i].rmomy = READFIXED(save->p); // "Real" momy (momy - cmomy) + player->cmomx = READFIXED(save->p); // Conveyor momx + player->cmomy = READFIXED(save->p); // Conveyor momy + player->rmomx = READFIXED(save->p); // "Real" momx (momx - cmomx) + player->rmomy = READFIXED(save->p); // "Real" momy (momy - cmomy) ///////////////////// // Race Mode Stuff // ///////////////////// - players[i].numboxes = READINT16(save->p); // Number of item boxes obtained for Race Mode - players[i].totalring = READINT16(save->p); // Total number of rings obtained for Race Mode - players[i].realtime = READUINT32(save->p); // integer replacement for leveltime - players[i].laps = READUINT8(save->p); // Number of laps (optional) + player->numboxes = READINT16(save->p); // Number of item boxes obtained for Race Mode + player->totalring = READINT16(save->p); // Total number of rings obtained for Race Mode + player->realtime = READUINT32(save->p); // integer replacement for leveltime + player->laps = READUINT8(save->p); // Number of laps (optional) //////////////////// // CTF Mode Stuff // //////////////////// - players[i].ctfteam = READINT32(save->p); // 1 == Red, 2 == Blue - players[i].gotflag = READUINT16(save->p); // 1 == Red, 2 == Blue Do you have the flag? + player->ctfteam = READINT32(save->p); // 1 == Red, 2 == Blue + player->gotflag = READUINT16(save->p); // 1 == Red, 2 == Blue Do you have the flag? - players[i].weapondelay = READINT32(save->p); - players[i].tossdelay = READINT32(save->p); + player->weapondelay = READINT32(save->p); + player->tossdelay = READINT32(save->p); - players[i].starposttime = READUINT32(save->p); - players[i].starpostx = READINT16(save->p); - players[i].starposty = READINT16(save->p); - players[i].starpostz = READINT16(save->p); - players[i].starpostnum = READINT32(save->p); - players[i].starpostangle = READANGLE(save->p); + player->starposttime = READUINT32(save->p); + player->starpostx = READINT16(save->p); + player->starposty = READINT16(save->p); + player->starpostz = READINT16(save->p); + player->starpostnum = READINT32(save->p); + player->starpostangle = READANGLE(save->p); - players[i].angle_pos = READANGLE(save->p); - players[i].old_angle_pos = READANGLE(save->p); + player->angle_pos = READANGLE(save->p); + player->old_angle_pos = READANGLE(save->p); - players[i].flyangle = READINT32(save->p); - players[i].drilltimer = READUINT32(save->p); - players[i].linkcount = READINT32(save->p); - players[i].linktimer = READUINT32(save->p); - players[i].anotherflyangle = READINT32(save->p); - players[i].nightstime = READUINT32(save->p); - players[i].bumpertime = READUINT32(save->p); - players[i].drillmeter = READINT32(save->p); - players[i].drilldelay = READUINT8(save->p); - players[i].bonustime = (boolean)READUINT8(save->p); - players[i].mare = READUINT8(save->p); + player->flyangle = READINT32(save->p); + player->drilltimer = READUINT32(save->p); + player->linkcount = READINT32(save->p); + player->linktimer = READUINT32(save->p); + player->anotherflyangle = READINT32(save->p); + player->nightstime = READUINT32(save->p); + player->bumpertime = READUINT32(save->p); + player->drillmeter = READINT32(save->p); + player->drilldelay = READUINT8(save->p); + player->bonustime = (boolean)READUINT8(save->p); + player->mare = READUINT8(save->p); - players[i].marebegunat = READUINT32(save->p); - players[i].startedtime = READUINT32(save->p); - players[i].finishedtime = READUINT32(save->p); - players[i].finishedrings = READINT16(save->p); - players[i].marescore = READUINT32(save->p); - players[i].lastmarescore = READUINT32(save->p); - players[i].lastmare = READUINT8(save->p); - players[i].maxlink = READINT32(save->p); - players[i].texttimer = READUINT8(save->p); - players[i].textvar = READUINT8(save->p); + player->marebegunat = READUINT32(save->p); + player->startedtime = READUINT32(save->p); + player->finishedtime = READUINT32(save->p); + player->finishedrings = READINT16(save->p); + player->marescore = READUINT32(save->p); + player->lastmarescore = READUINT32(save->p); + player->lastmare = READUINT8(save->p); + player->maxlink = READINT32(save->p); + player->texttimer = READUINT8(save->p); + player->textvar = READUINT8(save->p); - players[i].lastsidehit = READINT16(save->p); - players[i].lastlinehit = READINT16(save->p); + player->lastsidehit = READINT16(save->p); + player->lastlinehit = READINT16(save->p); - players[i].losstime = READUINT32(save->p); + player->losstime = READUINT32(save->p); - players[i].timeshit = READUINT8(save->p); + player->timeshit = READUINT8(save->p); - players[i].onconveyor = READINT32(save->p); + player->onconveyor = READINT32(save->p); - players[i].jointime = READUINT32(save->p); - players[i].spectatorreentry = READUINT32(save->p); + player->jointime = READUINT32(save->p); + player->spectatorreentry = READUINT32(save->p); - players[i].grieftime = READUINT32(save->p); - players[i].griefstrikes = READUINT8(save->p); + player->grieftime = READUINT32(save->p); + player->griefstrikes = READUINT8(save->p); - players[i].splitscreenindex = READUINT8(save->p); + player->splitscreenindex = READUINT8(save->p); flags = READUINT16(save->p); if (flags & CAPSULE) - players[i].capsule = (mobj_t *)(size_t)READUINT32(save->p); + player->capsule = (mobj_t *)(size_t)READUINT32(save->p); if (flags & FIRSTAXIS) - players[i].axis1 = (mobj_t *)(size_t)READUINT32(save->p); + player->axis1 = (mobj_t *)(size_t)READUINT32(save->p); if (flags & SECONDAXIS) - players[i].axis2 = (mobj_t *)(size_t)READUINT32(save->p); + player->axis2 = (mobj_t *)(size_t)READUINT32(save->p); if (flags & AWAYVIEW) - players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save->p); + player->awayviewmobj = (mobj_t *)(size_t)READUINT32(save->p); - players[i].viewheight = 32<viewheight = 32<p); + //SetPlayerSkinByNum(i, player->skin); + player->charflags = READUINT32(save->p); // SRB2kart - players[i].kartspeed = READUINT8(save->p); - players[i].kartweight = READUINT8(save->p); + player->kartspeed = READUINT8(save->p); + player->kartweight = READUINT8(save->p); // for (j = 0; j < MAXPREDICTTICS; j++) { - players[i].lturn_max[j] = READINT16(save->p); - players[i].rturn_max[j] = READINT16(save->p); + player->lturn_max[j] = READINT16(save->p); + player->rturn_max[j] = READINT16(save->p); } } } @@ -514,259 +518,311 @@ static void P_NetUnArchivePlayers(savebuffer_t *save, boolean reloading) #define LD_S2BOTTEX 0x04 #define LD_S2MIDTEX 0x08 -// -// P_NetArchiveWorld -// -static void P_NetArchiveWorld(savebuffer_t *save) +#define FD_FLAGS 0x01 +#define FD_ALPHA 0x02 + +// Check if any of the sector's FOFs differ from how they spawned +static boolean CheckFFloorDiff(const sector_t *ss) +{ + ffloor_t *rover; + + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (rover->flags != rover->spawnflags + || rover->alpha != rover->spawnalpha) + { + return true; // we found an FOF that changed! + // don't bother checking for more, we do that later + } + } + + return false; +} + +// Special case: save the stats of all modified ffloors along with their ffloor "number"s +// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed +static void ArchiveFFloors(savebuffer_t *save, const sector_t *ss) +{ + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + UINT8 fflr_diff; + + for (rover = ss->ffloors; rover; rover = rover->next) + { + fflr_diff = 0; // reset diff flags + + if (rover->flags != rover->spawnflags) + fflr_diff |= FD_FLAGS; + if (rover->alpha != rover->spawnalpha) + fflr_diff |= FD_ALPHA; + + if (fflr_diff) + { + WRITEUINT16(save->p, j); // save ffloor "number" + WRITEUINT8(save->p, fflr_diff); + + if (fflr_diff & FD_FLAGS) + WRITEUINT32(save->p, rover->flags); + if (fflr_diff & FD_ALPHA) + WRITEINT16(save->p, rover->alpha); + } + + j++; + } + + WRITEUINT16(save->p, 0xffff); +} + +static void ArchiveSectors(savebuffer_t *save) { size_t i; - const line_t *li = lines; - const side_t *si; - UINT8 *put; - - // reload the map just to see difference - virtres_t* virt = vres_GetMap(lastloadedmaplumpnum); - mapsector_t *ms = (mapsector_t*) vres_Find(virt, "SECTORS")->data; - mapsidedef_t *msd = (mapsidedef_t*) vres_Find(virt, "SIDEDEFS")->data; - maplinedef_t *mld = (maplinedef_t*) vres_Find(virt, "LINEDEFS")->data; const sector_t *ss = sectors; + const sector_t *spawnss = spawnsectors; UINT8 diff, diff2; - WRITEUINT32(save->p, ARCHIVEBLOCK_WORLD); - put = save->p; - - for (i = 0; i < numsectors; i++, ss++, ms++) + for (i = 0; i < numsectors; i++, ss++, spawnss++) { diff = diff2 = 0; - if (ss->floorheight != SHORT(ms->floorheight)<floorheight != spawnss->floorheight) diff |= SD_FLOORHT; - if (ss->ceilingheight != SHORT(ms->ceilingheight)<ceilingheight != spawnss->ceilingheight) diff |= SD_CEILHT; + // // flats // - if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) + if (ss->floorpic != spawnss->floorpic) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) + if (ss->ceilingpic != spawnss->ceilingpic) diff |= SD_CEILPIC; - if (ss->lightlevel != SHORT(ms->lightlevel)) + if (ss->lightlevel != spawnss->lightlevel) diff |= SD_LIGHT; - if (ss->special != SHORT(ms->special)) + if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != ss->spawn_flr_xoffs) + if (ss->floor_xoffs != spawnss->floor_xoffs) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != ss->spawn_flr_yoffs) + if (ss->floor_yoffs != spawnss->floor_yoffs) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != ss->spawn_ceil_xoffs) + if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != ss->spawn_ceil_yoffs) + if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != ss->spawn_flrpic_angle) + if (ss->floorpic_angle != spawnss->floorpic_angle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != ss->spawn_flrpic_angle) + if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) diff2 |= SD_CEILANG; - if (ss->tag != SHORT(ms->tag)) + if (ss->tag != spawnss->tag) diff2 |= SD_TAG; - if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) + if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag) diff2 |= SD_TAGLIST; - // Check if any of the sector's FOFs differ from how they spawned - if (ss->ffloors) - { - ffloor_t *rover; - for (rover = ss->ffloors; rover; rover = rover->next) - { - if (rover->flags != rover->spawnflags - || rover->alpha != rover->spawnalpha) - { - diff |= SD_FFLOORS; // we found an FOF that changed! - break; // don't bother checking for more, we do that later - } - } - } + if (ss->ffloors && CheckFFloorDiff(ss)) + diff |= SD_FFLOORS; if (diff2) diff |= SD_DIFF2; if (diff) { - WRITEUINT16(put, i); - WRITEUINT8(put, diff); + WRITEUINT16(save->p, i); + WRITEUINT8(save->p, diff); + if (diff & SD_DIFF2) - WRITEUINT8(put, diff2); + WRITEUINT8(save->p, diff2); if (diff & SD_FLOORHT) - WRITEFIXED(put, ss->floorheight); + WRITEFIXED(save->p, ss->floorheight); if (diff & SD_CEILHT) - WRITEFIXED(put, ss->ceilingheight); + WRITEFIXED(save->p, ss->ceilingheight); if (diff & SD_FLOORPIC) - WRITEMEM(put, levelflats[ss->floorpic].name, 8); + WRITEMEM(save->p, levelflats[ss->floorpic].name, 8); if (diff & SD_CEILPIC) - WRITEMEM(put, levelflats[ss->ceilingpic].name, 8); + WRITEMEM(save->p, levelflats[ss->ceilingpic].name, 8); if (diff & SD_LIGHT) - WRITEINT16(put, ss->lightlevel); + WRITEINT16(save->p, ss->lightlevel); if (diff & SD_SPECIAL) - WRITEINT16(put, ss->special); + WRITEINT16(save->p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(put, ss->floor_xoffs); + WRITEFIXED(save->p, ss->floor_xoffs); if (diff2 & SD_FYOFFS) - WRITEFIXED(put, ss->floor_yoffs); + WRITEFIXED(save->p, ss->floor_yoffs); if (diff2 & SD_CXOFFS) - WRITEFIXED(put, ss->ceiling_xoffs); + WRITEFIXED(save->p, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) - WRITEFIXED(put, ss->ceiling_yoffs); + WRITEFIXED(save->p, ss->ceiling_yoffs); if (diff2 & SD_TAG) // save only the tag - WRITEINT16(put, ss->tag); + WRITEINT16(save->p, ss->tag); if (diff2 & SD_FLOORANG) - WRITEANGLE(put, ss->floorpic_angle); + WRITEANGLE(save->p, ss->floorpic_angle); if (diff2 & SD_CEILANG) - WRITEANGLE(put, ss->ceilingpic_angle); + WRITEANGLE(save->p, ss->ceilingpic_angle); if (diff2 & SD_TAGLIST) // save both firsttag and nexttag { // either of these could be changed even if tag isn't - WRITEINT32(put, ss->firsttag); - WRITEINT32(put, ss->nexttag); + WRITEINT32(save->p, ss->firsttag); + WRITEINT32(save->p, ss->nexttag); } - // Special case: save the stats of all modified ffloors along with their ffloor "number"s - // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed if (diff & SD_FFLOORS) - { - size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - ffloor_t *rover; - UINT8 fflr_diff; - for (rover = ss->ffloors; rover; rover = rover->next) - { - fflr_diff = 0; // reset diff flags - if (rover->flags != rover->spawnflags) - fflr_diff |= 1; - if (rover->alpha != rover->spawnalpha) - fflr_diff |= 2; - - if (fflr_diff) - { - WRITEUINT16(put, j); // save ffloor "number" - WRITEUINT8(put, fflr_diff); - if (fflr_diff & 1) - WRITEUINT32(put, rover->flags); - if (fflr_diff & 2) - WRITEINT16(put, rover->alpha); - } - j++; - } - WRITEUINT16(put, 0xffff); - } + ArchiveFFloors(save, ss); } } - WRITEUINT16(put, 0xffff); + WRITEUINT16(save->p, 0xffff); +} - // do lines - for (i = 0; i < numlines; i++, mld++, li++) +static void ArchiveLines(savebuffer_t *save) +{ + size_t i; + const line_t *li = lines; + const line_t *spawnli = spawnlines; + const side_t *si; + const side_t *spawnsi; + UINT8 diff, diff2; + + for (i = 0; i < numlines; i++, spawnli++, li++) { diff = diff2 = 0; - if (li->special != SHORT(mld->special)) + if (li->special != spawnli->special) diff |= LD_SPECIAL; - if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved + if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved diff |= LD_CLLCOUNT; if (li->sidenum[0] != 0xffff) { si = &sides[li->sidenum[0]]; - if (si->textureoffset != SHORT(msd[li->sidenum[0]].textureoffset)<sidenum[0]]; + + if (si->textureoffset != spawnsi->textureoffset) diff |= LD_S1TEXOFF; //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. - if (R_CheckTextureNumForName(msd[li->sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff |= LD_S1TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff |= LD_S1BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff |= LD_S1MIDTEX; } if (li->sidenum[1] != 0xffff) { si = &sides[li->sidenum[1]]; - if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<sidenum[1]]; + + if (si->textureoffset != spawnsi->textureoffset) diff2 |= LD_S2TEXOFF; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) + if (si->toptexture != spawnsi->toptexture) diff2 |= LD_S2TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) + if (si->bottomtexture != spawnsi->bottomtexture) diff2 |= LD_S2BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) + if (si->midtexture != spawnsi->midtexture) diff2 |= LD_S2MIDTEX; + if (diff2) diff |= LD_DIFF2; } if (diff) { - WRITEINT16(put, i); - WRITEUINT8(put, diff); + WRITEINT16(save->p, i); + WRITEUINT8(save->p, diff); if (diff & LD_DIFF2) - WRITEUINT8(put, diff2); + WRITEUINT8(save->p, diff2); if (diff & LD_FLAG) - WRITEINT16(put, li->flags); + WRITEINT16(save->p, li->flags); if (diff & LD_SPECIAL) - WRITEINT16(put, li->special); + WRITEINT16(save->p, li->special); if (diff & LD_CLLCOUNT) - WRITEINT16(put, li->callcount); + WRITEINT16(save->p, li->callcount); si = &sides[li->sidenum[0]]; if (diff & LD_S1TEXOFF) - WRITEFIXED(put, si->textureoffset); + WRITEFIXED(save->p, si->textureoffset); if (diff & LD_S1TOPTEX) - WRITEINT32(put, si->toptexture); + WRITEINT32(save->p, si->toptexture); if (diff & LD_S1BOTTEX) - WRITEINT32(put, si->bottomtexture); + WRITEINT32(save->p, si->bottomtexture); if (diff & LD_S1MIDTEX) - WRITEINT32(put, si->midtexture); + WRITEINT32(save->p, si->midtexture); si = &sides[li->sidenum[1]]; if (diff2 & LD_S2TEXOFF) - WRITEFIXED(put, si->textureoffset); + WRITEFIXED(save->p, si->textureoffset); if (diff2 & LD_S2TOPTEX) - WRITEINT32(put, si->toptexture); + WRITEINT32(save->p, si->toptexture); if (diff2 & LD_S2BOTTEX) - WRITEINT32(put, si->bottomtexture); + WRITEINT32(save->p, si->bottomtexture); if (diff2 & LD_S2MIDTEX) - WRITEINT32(put, si->midtexture); + WRITEINT32(save->p, si->midtexture); } } - WRITEUINT16(put, 0xffff); - R_ClearTextureNumCache(false); - vres_Free(virt); - save->p = put; + WRITEUINT16(save->p, 0xffff); } // -// P_NetUnArchiveWorld +// P_NetArchiveWorld // -static void P_NetUnArchiveWorld(savebuffer_t *save) +static void P_NetArchiveWorld(savebuffer_t *save) { + WRITEUINT32(save->p, ARCHIVEBLOCK_WORLD); + + ArchiveSectors(save); + ArchiveLines(save); + R_ClearTextureNumCache(false); +} + +static void UnArchiveFFloors(savebuffer_t *save, const sector_t *ss) +{ + UINT16 j = 0; // number of current ffloor in loop + UINT16 fflr_i; // saved ffloor "number" of next modified ffloor + UINT16 fflr_diff; // saved ffloor diff + ffloor_t *rover; + + rover = ss->ffloors; + if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... + I_Error("Sector does not have any ffloors!"); + + fflr_i = READUINT16(save->p); // get first modified ffloor's number ready + for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? + { + if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already + break; + // should NEVER need to be checked + //if (rover == NULL) + //break; + if (j != fflr_i) // this ffloor was not modified + { + j++; + rover = rover->next; + continue; + } + + fflr_diff = READUINT8(save->p); + + if (fflr_diff & FD_FLAGS) + rover->flags = (ffloortype_e)READUINT32(save->p); + if (fflr_diff & FD_ALPHA) + rover->alpha = READINT16(save->p); + + fflr_i = READUINT16(save->p); // get next ffloor "number" ready + + j++; + rover = rover->next; + } +} + +static void UnArchiveSectors(savebuffer_t *save) +{ + sector_t *ss; UINT16 i; - line_t *li; - side_t *si; - UINT8 *get; UINT8 diff, diff2; - if (READUINT32(save->p) != ARCHIVEBLOCK_WORLD) - I_Error("Bad $$$.sav at archive block World"); - - get = save->p; - for (;;) { - i = READUINT16(get); + i = READUINT16(save->p); if (i == 0xffff) break; @@ -774,137 +830,120 @@ static void P_NetUnArchiveWorld(savebuffer_t *save) if (i > numsectors) I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - diff = READUINT8(get); + diff = READUINT8(save->p); if (diff & SD_DIFF2) - diff2 = READUINT8(get); + diff2 = READUINT8(save->p); else diff2 = 0; + ss = §ors[i]; + if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(get); + ss->floorheight = READFIXED(save->p); if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(get); + ss->ceilingheight = READFIXED(save->p); if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get); - get += 8; + ss->floorpic = P_AddLevelFlatRuntime((char *)save->p); + save->p += 8; } if (diff & SD_CEILPIC) { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get); - get += 8; + ss->ceilingpic = P_AddLevelFlatRuntime((char *)save->p); + save->p += 8; } if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(get); + ss->lightlevel = READINT16(save->p); if (diff & SD_SPECIAL) - sectors[i].special = READINT16(get); + ss->special = READINT16(save->p); if (diff2 & SD_FXOFFS) - sectors[i].floor_xoffs = READFIXED(get); + ss->floor_xoffs = READFIXED(save->p); if (diff2 & SD_FYOFFS) - sectors[i].floor_yoffs = READFIXED(get); + ss->floor_yoffs = READFIXED(save->p); if (diff2 & SD_CXOFFS) - sectors[i].ceiling_xoffs = READFIXED(get); + ss->ceiling_xoffs = READFIXED(save->p); if (diff2 & SD_CYOFFS) - sectors[i].ceiling_yoffs = READFIXED(get); + ss->ceiling_yoffs = READFIXED(save->p); if (diff2 & SD_TAG) - sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag + ss->tag = READINT16(save->p); // DON'T use P_ChangeSectorTag if (diff2 & SD_TAGLIST) { - sectors[i].firsttag = READINT32(get); - sectors[i].nexttag = READINT32(get); + ss->firsttag = READINT32(save->p); + ss->nexttag = READINT32(save->p); } if (diff2 & SD_FLOORANG) - sectors[i].floorpic_angle = READANGLE(get); + ss->floorpic_angle = READANGLE(save->p); if (diff2 & SD_CEILANG) - sectors[i].ceilingpic_angle = READANGLE(get); + ss->ceilingpic_angle = READANGLE(save->p); if (diff & SD_FFLOORS) - { - UINT16 j = 0; // number of current ffloor in loop - UINT16 fflr_i; // saved ffloor "number" of next modified ffloor - UINT16 fflr_diff; // saved ffloor diff - ffloor_t *rover; - - rover = sectors[i].ffloors; - if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... - I_Error("Sector does not have any ffloors!"); - - fflr_i = READUINT16(get); // get first modified ffloor's number ready - for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? - { - if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already - break; - // should NEVER need to be checked - //if (rover == NULL) - //break; - if (j != fflr_i) // this ffloor was not modified - { - j++; - rover = rover->next; - continue; - } - - fflr_diff = READUINT8(get); - - if (fflr_diff & 1) - rover->flags = READUINT32(get); - if (fflr_diff & 2) - rover->alpha = READINT16(get); - - fflr_i = READUINT16(get); // get next ffloor "number" ready - - j++; - rover = rover->next; - } - } + UnArchiveFFloors(save, ss); } +} + +static void UnArchiveLines(savebuffer_t *save) +{ + UINT16 i; + line_t *li; + side_t *si; + UINT8 diff, diff2; for (;;) { - i = READUINT16(get); + i = READUINT16(save->p); if (i == 0xffff) break; if (i > numlines) I_Error("Invalid line number %u from server", i); - diff = READUINT8(get); + diff = READUINT8(save->p); li = &lines[i]; if (diff & LD_DIFF2) - diff2 = READUINT8(get); + diff2 = READUINT8(save->p); else diff2 = 0; if (diff & LD_FLAG) - li->flags = READINT16(get); + li->flags = READINT16(save->p); if (diff & LD_SPECIAL) - li->special = READINT16(get); + li->special = READINT16(save->p); if (diff & LD_CLLCOUNT) - li->callcount = READINT16(get); + li->callcount = READINT16(save->p); si = &sides[li->sidenum[0]]; if (diff & LD_S1TEXOFF) - si->textureoffset = READFIXED(get); + si->textureoffset = READFIXED(save->p); if (diff & LD_S1TOPTEX) - si->toptexture = READINT32(get); + si->toptexture = READINT32(save->p); if (diff & LD_S1BOTTEX) - si->bottomtexture = READINT32(get); + si->bottomtexture = READINT32(save->p); if (diff & LD_S1MIDTEX) - si->midtexture = READINT32(get); + si->midtexture = READINT32(save->p); si = &sides[li->sidenum[1]]; if (diff2 & LD_S2TEXOFF) - si->textureoffset = READFIXED(get); + si->textureoffset = READFIXED(save->p); if (diff2 & LD_S2TOPTEX) - si->toptexture = READINT32(get); + si->toptexture = READINT32(save->p); if (diff2 & LD_S2BOTTEX) - si->bottomtexture = READINT32(get); + si->bottomtexture = READINT32(save->p); if (diff2 & LD_S2MIDTEX) - si->midtexture = READINT32(get); + si->midtexture = READINT32(save->p); } +} - save->p = get; +// +// P_NetUnArchiveWorld +// +static void P_NetUnArchiveWorld(savebuffer_t *save) +{ + if (READUINT32(save->p) != ARCHIVEBLOCK_WORLD) + I_Error("Bad $$$.sav at archive block World"); + + UnArchiveSectors(save); + UnArchiveLines(save); } // @@ -1393,7 +1432,7 @@ static void SaveGlowThinker(savebuffer_t *save, const thinker_t *th, const UINT8 // // Saves a fireflicker_t thinker // -static inline void SaveFireflickerThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) +static void SaveFireflickerThinker(savebuffer_t *save, const thinker_t *th, const UINT8 type) { const fireflicker_t *ht = (const void *)th; WRITEUINT8(save->p, type); @@ -1926,22 +1965,19 @@ static inline player_t *LoadPlayer(UINT32 player) // Loads a mobj_t from a save game // -FUNCINLINE static ATTRINLINE mobj_t *AllocMobj(void) +static mobjtype_t g_doomednum_to_mobjtype[UINT16_MAX]; + +static void CalculateDoomednumToMobjtype(void) { - mobj_t *mobj; + memset(g_doomednum_to_mobjtype, MT_NULL, sizeof(g_doomednum_to_mobjtype)); - if (mobjcache != NULL) + for (size_t i = MT_NULL+1; i < NUMMOBJTYPES; i++) { - mobj = mobjcache; - mobjcache = mobjcache->hnext; - memset(mobj, 0, sizeof(*mobj)); + if (mobjinfo[i].doomednum > 0 && mobjinfo[i].doomednum <= UINT16_MAX) + { + g_doomednum_to_mobjtype[ mobjinfo[i].doomednum ] = i; + } } - else - { - mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - } - - return mobj; } static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) @@ -1975,12 +2011,12 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) return; } - mobj = AllocMobj(); + mobj = P_AllocateMobj(); mobj->spawnpoint = &mapthings[spawnpointnum]; mapthings[spawnpointnum].mobj = mobj; } else - mobj = AllocMobj(); + mobj = P_AllocateMobj(); // declare this as a valid mobj as soon as possible. mobj->thinker.function = thinker; @@ -1993,18 +2029,23 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) mobj->type = READUINT32(save->p); else { - for (i = 0; i < NUMMOBJTYPES; i++) - if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum) - break; - if (i == NUMMOBJTYPES) + mobjtype_t new_type = MT_NULL; + if (mobj->spawnpoint) + { + new_type = g_doomednum_to_mobjtype[mobj->spawnpoint->type]; + } + + if (new_type <= MT_NULL || new_type >= NUMMOBJTYPES) { if (mobj->spawnpoint) - CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type); + CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum %d\n", mobj->spawnpoint->type); else - CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n"); + CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing doomednum NULL\n"); + I_Error("Savegame corrupted"); } - mobj->type = i; + + mobj->type = new_type; } mobj->info = &mobjinfo[mobj->type]; @@ -2081,15 +2122,12 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) i = READUINT8(save->p); mobj->player = &players[i]; mobj->player->mo = mobj; + // added for angle prediction - if (consoleplayer == i) - localangle[0] = mobj->angle; - if (displayplayers[1] == i) - localangle[1] = mobj->angle; - if (displayplayers[2] == i) - localangle[2] = mobj->angle; - if (displayplayers[3] == i) - localangle[3] = mobj->angle; + if (i == P_GetLocalPlayerNumForNum(i)) + { + localangle[i] = mobj->angle; + } } if (diff & MD_MOVEDIR) mobj->movedir = READANGLE(save->p); @@ -2214,9 +2252,13 @@ static void LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadSpecialLevelThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 floorOrCeiling) { - levelspecthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + levelspecthink_t *ht = (levelspecthink_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); + size_t i; ht->thinker.function = thinker; + for (i = 0; i < 16; i++) { ht->vars[i] = READFIXED(save->p); //var[16] @@ -2236,10 +2278,13 @@ static void LoadSpecialLevelThinker(savebuffer_t *save, actionf_p1 thinker, UINT P_AddThinker(&ht->thinker); // interpolation - if (floorOrCeiling & 2) - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); - if (floorOrCeiling & 1) - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); + if (ht->sector) + { + if (floorOrCeiling & 2) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); + if (floorOrCeiling & 1) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); + } } // @@ -2249,7 +2294,9 @@ static void LoadSpecialLevelThinker(savebuffer_t *save, actionf_p1 thinker, UINT // static void LoadCeilingThinker(savebuffer_t *save, actionf_p1 thinker) { - ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ceiling_t *ht = (ceiling_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->type = READUINT8(save->p); ht->sector = LoadSector(READUINT32(save->p)); @@ -2271,7 +2318,8 @@ static void LoadCeilingThinker(savebuffer_t *save, actionf_p1 thinker) P_AddThinker(&ht->thinker); // interpolation - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); + if (ht->sector) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); } // @@ -2281,7 +2329,9 @@ static void LoadCeilingThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadFloormoveThinker(savebuffer_t *save, actionf_p1 thinker) { - floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + floormove_t *ht = (floormove_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->type = READUINT8(save->p); ht->crush = READUINT8(save->p); @@ -2298,7 +2348,8 @@ static void LoadFloormoveThinker(savebuffer_t *save, actionf_p1 thinker) P_AddThinker(&ht->thinker); // interpolation - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); + if (ht->sector) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); } // @@ -2308,7 +2359,9 @@ static void LoadFloormoveThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadLightflashThinker(savebuffer_t *save, actionf_p1 thinker) { - lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + lightflash_t *ht = (lightflash_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->maxlight = READINT32(save->p); @@ -2325,7 +2378,9 @@ static void LoadLightflashThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadStrobeThinker(savebuffer_t *save, actionf_p1 thinker) { - strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + strobe_t *ht = (strobe_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->count = READINT32(save->p); @@ -2345,7 +2400,9 @@ static void LoadStrobeThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadGlowThinker(savebuffer_t *save, actionf_p1 thinker) { - glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + glow_t *ht = (glow_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->minlight = READINT32(save->p); @@ -2364,7 +2421,9 @@ static void LoadGlowThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadFireflickerThinker(savebuffer_t *save, actionf_p1 thinker) { - fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + fireflicker_t *ht = (fireflicker_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->count = READINT32(save->p); @@ -2383,7 +2442,9 @@ static void LoadFireflickerThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadElevatorThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 floorOrCeiling) { - elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + elevator_t *ht = (elevator_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->type = READUINT8(save->p); ht->sector = LoadSector(READUINT32(save->p)); @@ -2414,10 +2475,13 @@ static void LoadElevatorThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 fl P_AddThinker(&ht->thinker); // interpolation - if (floorOrCeiling & 2) - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); - if (floorOrCeiling & 1) - R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); + if (ht->sector) + { + if (floorOrCeiling & 2) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, true); + if (floorOrCeiling & 1) + R_CreateInterpolator_SectorPlane(&ht->thinker, ht->sector, false); + } } // @@ -2427,7 +2491,9 @@ static void LoadElevatorThinker(savebuffer_t *save, actionf_p1 thinker, UINT8 fl // static void LoadScrollThinker(savebuffer_t *save, actionf_p1 thinker) { - scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + scroll_t *ht = (scroll_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->dx = READFIXED(save->p); ht->dy = READFIXED(save->p); @@ -2465,7 +2531,9 @@ static void LoadScrollThinker(savebuffer_t *save, actionf_p1 thinker) // static inline void LoadFrictionThinker(savebuffer_t *save, actionf_p1 thinker) { - friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + friction_t *ht = (friction_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->friction = READINT32(save->p); ht->movefactor = READINT32(save->p); @@ -2482,7 +2550,9 @@ static inline void LoadFrictionThinker(savebuffer_t *save, actionf_p1 thinker) // static void LoadPusherThinker(savebuffer_t *save, actionf_p1 thinker) { - pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + pusher_t *ht = (pusher_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->type = READUINT8(save->p); ht->x_mag = READINT32(save->p); @@ -2508,16 +2578,22 @@ static void LoadPusherThinker(savebuffer_t *save, actionf_p1 thinker) // static inline void LoadLaserThinker(savebuffer_t *save, actionf_p1 thinker) { - laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + laserthink_t *ht = (laserthink_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ffloor_t *rover = NULL; ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->sec = LoadSector(READUINT32(save->p)); ht->sourceline = LoadLine(READUINT32(save->p)); + for (rover = ht->sector->ffloors; rover; rover = rover->next) + { if (rover->secnum == (size_t)(ht->sec - sectors) && rover->master == ht->sourceline) ht->ffloor = rover; + } + P_AddThinker(&ht->thinker); } @@ -2528,7 +2604,9 @@ static inline void LoadLaserThinker(savebuffer_t *save, actionf_p1 thinker) // FUNCINLINE static ATTRINLINE void LoadLightlevelThinker(savebuffer_t *save, actionf_p1 thinker) { - lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + lightlevel_t *ht = (lightlevel_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->sector = LoadSector(READUINT32(save->p)); ht->destlevel = READINT32(save->p); @@ -2545,7 +2623,9 @@ FUNCINLINE static ATTRINLINE void LoadLightlevelThinker(savebuffer_t *save, acti // static inline void LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) { - executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + executor_t *ht = (executor_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->line = LoadLine(READUINT32(save->p)); ht->caller = LoadMobj(READUINT32(save->p)); @@ -2561,7 +2641,9 @@ static inline void LoadExecutorThinker(savebuffer_t *save, actionf_p1 thinker) // static inline void LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) { - disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + disappear_t *ht = (disappear_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->appeartime = READUINT32(save->p); ht->disappeartime = READUINT32(save->p); @@ -2580,7 +2662,9 @@ static inline void LoadDisappearThinker(savebuffer_t *save, actionf_p1 thinker) // static inline void LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker) { - polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polyrotate_t *ht = (polyrotate_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->speed = READINT32(save->p); @@ -2593,7 +2677,7 @@ static inline void LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolyrotatetThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2607,7 +2691,9 @@ static inline void LoadPolyrotatetThinker(savebuffer_t *save, actionf_p1 thinker // static void LoadPolymoveThinker(savebuffer_t *save, actionf_p1 thinker) { - polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polymove_t *ht = (polymove_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->speed = READINT32(save->p); @@ -2622,7 +2708,7 @@ static void LoadPolymoveThinker(savebuffer_t *save, actionf_p1 thinker) if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolymoveThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2636,7 +2722,9 @@ static void LoadPolymoveThinker(savebuffer_t *save, actionf_p1 thinker) // static inline void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinker) { - polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polywaypoint_t *ht = (polywaypoint_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->speed = READINT32(save->p); @@ -2659,7 +2747,7 @@ static inline void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinke if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolywaypointThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2690,7 +2778,9 @@ static inline void LoadPolywaypointThinker(savebuffer_t *save, actionf_p1 thinke // static inline void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 thinker) { - polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polyslidedoor_t *ht = (polyslidedoor_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->delay = READINT32(save->p); @@ -2712,7 +2802,7 @@ static inline void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 think if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolyslidedoorThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2726,7 +2816,9 @@ static inline void LoadPolyslidedoorThinker(savebuffer_t *save, actionf_p1 think // static inline void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 thinker) { - polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polyswingdoor_t *ht = (polyswingdoor_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->delay = READINT32(save->p); @@ -2743,7 +2835,7 @@ static inline void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 think if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolyswingdoorThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2757,7 +2849,9 @@ static inline void LoadPolyswingdoorThinker(savebuffer_t *save, actionf_p1 think // static inline void LoadPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinker) { - polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polydisplace_t *ht = (polydisplace_t*)Z_LevelPoolMalloc(sizeof (*ht)); + ht->thinker.alloctype = TAT_LEVELPOOL; + ht->thinker.size = sizeof (*ht); ht->thinker.function = thinker; ht->polyObjNum = READINT32(save->p); ht->controlSector = LoadSector(READUINT32(save->p)); @@ -2771,7 +2865,7 @@ static inline void LoadPolydisplaceThinker(savebuffer_t *save, actionf_p1 thinke if (!(po = Polyobj_GetForNum(ht->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", ht->polyObjNum); + CONS_Debug(DBG_POLYOBJ, "LoadPolydisplaceThinker: bad polyobj %d\n", ht->polyObjNum); return; } @@ -2793,6 +2887,10 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save) if (READUINT32(save->p) != ARCHIVEBLOCK_THINKERS) I_Error("Bad $$$.sav at archive block Thinkers"); + // Pre-calculate this lookup, because it was wasting + // a shit ton of time loading mobj thinkers. + CalculateDoomednumToMobjtype(); + // remove all the current thinkers currentthinker = thinkercap.next; for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = next) @@ -2805,7 +2903,14 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save) { (next->prev = currentthinker->prev)->next = next; R_DestroyLevelInterpolators(currentthinker); - Z_Free(currentthinker); + if (currentthinker->alloctype == TAT_LEVELPOOL) + { + Z_LevelPoolFree(currentthinker, currentthinker->size); + } + else + { + Z_Free(currentthinker); + } } } @@ -3408,11 +3513,92 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) WRITEUINT8(save->p, 0x2e); } +static void P_ReloadSaveLevelData(void) +{ + size_t i; + + // Only reload stuff that can we modify in the save states themselves. + // This is still orders of magnitude faster than a full level reload. + // Considered memcpy, but it's complicated -- save that for local saves. + + sector_t *ss = sectors; + sector_t *spawnss = spawnsectors; + + for (i = 0; i < numsectors; i++, ss++, spawnss++) + { + ss->floorheight = spawnss->floorheight; + ss->ceilingheight = spawnss->ceilingheight; + ss->floorpic = spawnss->floorpic; + ss->ceilingpic = spawnss->ceilingpic; + ss->lightlevel = spawnss->lightlevel; + ss->special = spawnss->special; + ss->floor_xoffs = spawnss->floor_xoffs; + ss->floor_yoffs = spawnss->floor_yoffs; + ss->ceiling_xoffs = spawnss->ceiling_xoffs; + ss->ceiling_yoffs = spawnss->ceiling_yoffs; + ss->floorpic_angle = spawnss->floorpic_angle; + ss->ceilingpic_angle = spawnss->ceilingpic_angle; + ss->tag = spawnss->tag; + ss->firsttag = ss->nexttag = -1; + + if (ss->ffloors) + { + ffloor_t *rover; + + for (rover = ss->ffloors; rover; rover = rover->next) + { + rover->flags = rover->spawnflags; + rover->alpha = rover->spawnalpha; + } + } + } + + line_t *li = lines; + line_t *spawnli = spawnlines; + side_t *si = NULL; + side_t *spawnsi = NULL; + + for (i = 0; i < numlines; i++, spawnli++, li++) + { + li->special = spawnli->special; + li->callcount = 0; + + li->tag = spawnli->tag; + li->firsttag = li->nexttag = -1; + + if (li->sidenum[0] != 0xffff) + { + si = &sides[li->sidenum[0]]; + spawnsi = &spawnsides[li->sidenum[0]]; + + si->textureoffset = spawnsi->textureoffset; + si->toptexture = spawnsi->toptexture; + si->bottomtexture = spawnsi->bottomtexture; + si->midtexture = spawnsi->midtexture; + } + + if (li->sidenum[1] != 0xffff) + { + si = &sides[li->sidenum[1]]; + spawnsi = &spawnsides[li->sidenum[1]]; + + si->textureoffset = spawnsi->textureoffset; + si->toptexture = spawnsi->toptexture; + si->bottomtexture = spawnsi->bottomtexture; + si->midtexture = spawnsi->midtexture; + } + } + + P_InitTagLists(); +} + FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) { UINT32 pig; INT32 i; + const INT16 prevgamemap = gamemap; + if (READUINT32(save->p) != ARCHIVEBLOCK_MISC) I_Error("Bad $$$.sav at archive block Misc"); @@ -3423,7 +3609,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool // gamemap changed; we assume that its map header is always valid, // so make it so - if(!mapheaderinfo[gamemap-1]) + if (!mapheaderinfo[gamemap-1]) P_AllocMapHeader(gamemap-1); // tell the sound code to reset the music since we're skipping what @@ -3449,10 +3635,23 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool encoremode = (boolean)READUINT8(save->p); - if (!P_SetupLevel(true, reloading)) + // Only reload the level during a gamestate reload + // if the map is horribly mismatched somehow. Minor + // differences in level state are already handled + // by other parts of the reload, so doing this + // on *every* reload wastes lots of time that we + // will need for rollback down the road. + if (!reloading || prevgamemap != gamemap) { - CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); - return false; + if (!P_SetupLevel(true, reloading)) + { + CONS_Alert(CONS_ERROR, M_GetText("Can't load the level!\n")); + return false; + } + } + else + { + P_ReloadSaveLevelData(); } // get the time diff --git a/src/p_setup.c b/src/p_setup.c index cb4b9060d..17debbde0 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -111,9 +111,11 @@ node_t *nodes; line_t *lines; side_t *sides; mapthing_t *mapthings; +sector_t *spawnsectors; +line_t *spawnlines; +side_t *spawnsides; INT32 numstarposts; boolean levelloading; -UINT8 levelfadecol; virtres_t *curmapvirt; @@ -367,7 +369,7 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) } // Loads the vertexes for a level. -FUNCINLINE static ATTRINLINE void P_LoadRawVertexes(UINT8 *data) +FUNCINLINE static ATTRINLINE void P_LoadVertices(UINT8 *data) { mapvertex_t *ml = (mapvertex_t *)data; vertex_t *li = vertexes; @@ -397,25 +399,6 @@ static inline fixed_t P_SegLength(seg_t *seg) return FixedHypot(dx, dy)<<1; } -#ifdef HWRENDER -/** Computes the length of a seg as a float. - * This is needed for OpenGL. - * - * \param seg Seg to compute length for. - * \return Length as a float. - */ -static inline float P_SegLengthFloat(seg_t *seg) -{ - float dx, dy; - - // make a vector (start at origin) - dx = FIXED_TO_FLOAT(seg->v2->x - seg->v1->x); - dy = FIXED_TO_FLOAT(seg->v2->y - seg->v1->y); - - return hypotf(dx, dy); -} -#endif - /** Updates the light offset * * \param li Seg to update the light offsets of @@ -546,7 +529,7 @@ static void P_SetupDirectionalLight(void) } // Loads the SEGS resource from a level. -static void P_LoadRawSegs(UINT8 *data) +static void P_LoadSegs(UINT8 *data) { INT32 rawlinedef, rawside; mapseg_t *ml = (mapseg_t*)data; @@ -563,12 +546,6 @@ static void P_LoadRawSegs(UINT8 *data) li->v2 = &vertexes[SHORT(ml->v2)]; li->length = P_SegLength(li); -#ifdef HWRENDER - if (rendermode == render_opengl) - li->flength = P_SegLengthFloat(li); - li->pv1 = li->pv2 = NULL; -#endif - li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); @@ -577,17 +554,16 @@ static void P_LoadRawSegs(UINT8 *data) li->side = rawside = SHORT(ml->side); li->sidedef = &sides[ldef->sidenum[rawside]]; li->frontsector = sides[ldef->sidenum[rawside]].sector; + if (ldef->flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[rawside^1]].sector; - else - li->backsector = 0; P_UpdateSegLightOffset(li); } } // Loads the SSECTORS resource from a level. -FUNCINLINE static ATTRINLINE void P_LoadRawSubsectors(void *data) +FUNCINLINE static ATTRINLINE void P_LoadSubsectors(void *data) { mapsubsector_t *ms = (mapsubsector_t*)data; subsector_t *ss = subsectors; @@ -595,13 +571,8 @@ FUNCINLINE static ATTRINLINE void P_LoadRawSubsectors(void *data) for (i = 0; i < numsubsectors; i++, ss++, ms++) { - ss->sector = NULL; ss->numlines = SHORT(ms->numsegs); ss->firstline = (UINT16)SHORT(ms->firstseg); -#ifdef FLOORSPLATS - ss->splats = NULL; -#endif - ss->validcount = 0; } } @@ -777,8 +748,19 @@ INT32 P_CheckLevelFlat(const char *flatname) return (INT32)i; } +static const sector_t sector_default = { + .nexttag = -1, + .firsttag = -1, + .heightsec = -1, + .camsec = -1, + .floorlightsec = -1, + .ceilinglightsec = -1, + .maxattached = 1, + .moved = true, +}; + // Sets up the ingame sectors structures. -static void P_LoadRawSectors(UINT8 *data) +static void P_LoadSectors(UINT8 *data) { mapsector_t *ms = (mapsector_t *)data; sector_t *ss = sectors; @@ -797,6 +779,7 @@ static void P_LoadRawSectors(UINT8 *data) // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. for (i = 0; i < numsectors; i++, ss++, ms++) { + *ss = sector_default; ss->floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<lightlevel = SHORT(ms->lightlevel); ss->special = SHORT(ms->special); ss->tag = SHORT(ms->tag); - ss->nexttag = ss->firsttag = -1; - ss->spawn_nexttag = ss->spawn_firsttag = -1; - memset(&ss->soundorg, 0, sizeof(ss->soundorg)); - ss->validcount = 0; - - ss->thinglist = NULL; - ss->touching_thinglist = NULL; - - ss->floordata = NULL; - ss->ceilingdata = NULL; - ss->lightingdata = NULL; - - ss->linecount = 0; - ss->lines = NULL; - - ss->heightsec = -1; - ss->camsec = -1; - ss->floorlightsec = -1; - ss->ceilinglightsec = -1; - ss->crumblestate = 0; - ss->ffloors = NULL; - ss->lightlist = NULL; - ss->numlights = 0; - ss->attached = NULL; - ss->attachedsolid = NULL; - ss->numattached = 0; - ss->maxattached = 1; - ss->moved = true; - - ss->extra_colormap = NULL; - - ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; - ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; - ss->bottommap = ss->midmap = ss->topmap = -1; - ss->gravity = NULL; - ss->cullheight = NULL; - ss->verticalflip = false; - ss->flags = 0; ss->flags |= SF_FLIPSPECIAL_FLOOR; - - ss->floorspeed = 0; - ss->ceilspeed = 0; } // set the sky flat num @@ -867,7 +807,7 @@ static void P_LoadRawSectors(UINT8 *data) // // P_LoadNodes // -static void P_LoadRawNodes(UINT8 *data) +static void P_LoadNodes(UINT8 *data) { UINT8 j, k; mapnode_t *mn = (mapnode_t*)data; @@ -894,15 +834,12 @@ static void P_LoadRawNodes(UINT8 *data) // P_LoadThings // -static void P_PrepareRawThings(UINT8 *data) +static void P_LoadThings(UINT8 *data) { mapthing_t *mt; size_t i; - // Spawn axis points first so they are - // at the front of the list for fast searching. - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { mt->x = READINT16(data); mt->y = READINT16(data); @@ -912,7 +849,19 @@ static void P_PrepareRawThings(UINT8 *data) mt->extrainfo = (UINT8)(mt->type >> 12); mt->type &= 4095; + } +} +static void P_SpawnMapThings(void) +{ + size_t i; + mapthing_t *mt; + + numhuntemeralds = 0; + + // Spawn axis points first so they are at the front of the list for fast searching. + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { switch (mt->type) { case 1700: // MT_AXIS @@ -925,19 +874,8 @@ static void P_PrepareRawThings(UINT8 *data) break; } } -} -static void P_LoadThings(void) -{ - size_t i; - mapthing_t *mt; - - // Loading the things lump itself into memory is now handled in P_PrepareThings, above - - mt = mapthings; - numhuntemeralds = 0; - - for (i = 0; i < nummapthings; i++, mt++) + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { sector_t *mtsector = R_PointInSubsector((mt->x << FRACBITS), (mt->y << FRACBITS))->sector; @@ -1004,8 +942,7 @@ static void P_LoadThings(void) return; // Run through the list of mapthings again to spawn hoops and rings - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { if (mt->type == 300 || mt->type == 308 || mt->type == 309 || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) @@ -1017,16 +954,20 @@ static void P_LoadThings(void) mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings (mt); + P_SpawnHoopsAndRings(mt); } } } -static inline void P_SpawnEmblems(void) +static void P_SpawnEmblems(boolean loademblems) { INT32 i, color; mobj_t *emblemmobj; + // Now let's spawn those funky emblem things! Tails 12-08-2002 + if (!loademblems || netgame || multiplayer) // No cheating!! + return; + for (i = 0; i < numemblems; i++) { if (emblemlocations[i].level != gamemap || emblemlocations[i].type > ET_SKIN) @@ -1058,16 +999,6 @@ static inline void P_SpawnEmblems(void) } } -static void P_SpawnSecretItems(boolean loademblems) -{ - // Now let's spawn those funky emblem things! Tails 12-08-2002 - if (netgame || multiplayer) // No cheating!! - return; - - if (loademblems) - P_SpawnEmblems(); -} - // Experimental groovy write function! void P_WriteThings(lumpnum_t lumpnum) { @@ -1087,8 +1018,7 @@ void P_WriteThings(lumpnum_t lumpnum) return; } - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { WRITEINT16(save.p, mt->x); WRITEINT16(save.p, mt->y); @@ -1111,7 +1041,86 @@ void P_WriteThings(lumpnum_t lumpnum) CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); } -static void P_LoadRawLineDefs(UINT8 *data) +static void P_InitializeLinedef(line_t *ld) +{ + UINT8 j; + + vertex_t *v1 = ld->v1; + vertex_t *v2 = ld->v2; + + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + ld->angle = R_PointToAngle2(0, 0, ld->dx, ld->dy); + + ld->alpha = FRACUNIT; + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else if ((ld->dy > 0) == (ld->dx > 0)) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + + // cph 2006/09/30 - fix sidedef errors right away. + // cph 2002/07/20 - these errors are fatal if not fixed, so apply them + for (j = 0; j < 2; j++) + { + if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) + { + ld->sidenum[j] = 0xffff; + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines))); + } + } + + ld->firsttag = ld->nexttag = -1; + + // killough 11/98: fix common wad errors (missing sidedefs): + if (ld->sidenum[0] == 0xffff) + { + ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) + { + ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if (ld->sidenum[0] != 0xffff && ld->special) + sides[ld->sidenum[0]].special = ld->special; + if (ld->sidenum[1] != 0xffff && ld->special) + sides[ld->sidenum[1]].special = ld->special; +} + +static void P_LoadLinedefs(UINT8 *data) { maplinedef_t *mld = (maplinedef_t *)data; line_t *ld = lines; @@ -1127,100 +1136,8 @@ static void P_LoadRawLineDefs(UINT8 *data) ld->sidenum[0] = SHORT(mld->sidenum[0]); ld->sidenum[1] = SHORT(mld->sidenum[1]); - } -} -static void P_SetupLines(void) -{ - line_t *ld = lines; - size_t i; - - for (i = 0; i < numlines; i++, ld++) - { - vertex_t *v1 = ld->v1; - vertex_t *v2 = ld->v2; - -#ifdef WALLSPLATS - ld->splats = NULL; -#endif - - ld->polyobj = NULL; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - - ld->alpha = FRACUNIT; - ld->blendmode = 0; - - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else if ((ld->dy > 0) == (ld->dx > 0)) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - - { - // cph 2006/09/30 - fix sidedef errors right away. - // cph 2002/07/20 - these errors are fatal if not fixed, so apply them - UINT8 j; - - for (j=0; j < 2; j++) - { - if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) - { - ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); - } - } - } - - ld->frontsector = ld->backsector = NULL; - ld->validcount = 0; - ld->firsttag = ld->nexttag = -1; - ld->callcount = 0; - - // killough 11/98: fix common wad errors (missing sidedefs): - if (ld->sidenum[0] == 0xffff) - { - ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "Linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); - } - - if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) - { - ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); - } - - if (ld->sidenum[0] != 0xffff && ld->special) - sides[ld->sidenum[0]].special = ld->special; - if (ld->sidenum[1] != 0xffff && ld->special) - sides[ld->sidenum[1]].special = ld->special; + P_InitializeLinedef(ld); } } @@ -1228,7 +1145,8 @@ static void P_LoadLineDefs2(void) { size_t i = numlines; register line_t *ld = lines; - for (;i--;ld++) + + for (; i--; ld++) { ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; @@ -1243,172 +1161,138 @@ static void P_LoadLineDefs2(void) } // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. - switch(ld->special) + switch (ld->special) { - case 443: // Calls a named Lua function - if (sides[ld->sidenum[0]].text) - { - size_t len = strlen(sides[ld->sidenum[0]].text)+1; - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - len += strlen(sides[ld->sidenum[1]].text); - ld->text = Z_Malloc(len, PU_LEVEL, NULL); - M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); - } - break; + case 443: // Calls a named Lua function + if (sides[ld->sidenum[0]].text) + { + size_t len = strlen(sides[ld->sidenum[0]].text)+1; + + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + len += strlen(sides[ld->sidenum[1]].text); + + ld->text = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); + + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); + } + break; + + // Set alpha for translucent walls + case 900 ... 908: + ld->alpha = ((909 - ld->special) << FRACBITS)/10; + break; + // Set alpha for additive/subtractive/reverse subtractive walls + case 910 ... 919: // additive + ld->alpha = ((10 - ld->special % 10) << FRACBITS)/10; + ld->blendmode = AST_ADD; + break; + case 920 ... 929: // subtractive + ld->alpha = ((10 - ld->special % 10) << FRACBITS)/10; + ld->blendmode = AST_SUBTRACT; + break; + case 930 ... 939: // reverse subtractive + ld->alpha = ((10 - ld->special % 10) << FRACBITS)/10; + ld->blendmode = AST_REVERSESUBTRACT; + break; + case 940: // modulate + ld->blendmode = AST_MODULATE; + break; } - - // Set alpha for translucent walls - if (ld->special >= 900 && ld->special < 909) - ld->alpha = ((909 - ld->special) << FRACBITS)/10; - - // Set alpha for additive/subtractive/reverse subtractive walls - if (ld->special >= 910 && ld->special <= 939) - ld->alpha = ((10 - ld->special % 10) << FRACBITS)/10; - - if (ld->special >= 910 && ld->special <= 919) // additive - ld->blendmode = AST_ADD; - - if (ld->special >= 920 && ld->special <= 929) // subtractive - ld->blendmode = AST_SUBTRACT; - - if (ld->special >= 930 && ld->special <= 939) // reverse subtractive - ld->blendmode = AST_REVERSESUBTRACT; - - if (ld->special == 940) // modulate - ld->blendmode = AST_MODULATE; } } +#ifdef HWRENDER +static void P_LoadSideColormapsGL(char *colorstr, INT32 *rgba) +{ + RGBA_t color; + size_t j; + +#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) +#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) + + // encore mode colormaps! + // do it like software by aproximating a color to a palette index, and then convert it to its encore variant and then back to a color code. + // do this for both the start and fade colormaps. + color.s.red = (HEX2INT(colorstr[1]) << 4) + HEX2INT(colorstr[2]); + color.s.green = (HEX2INT(colorstr[3]) << 4) + HEX2INT(colorstr[4]); + color.s.blue = (HEX2INT(colorstr[5]) << 4) + HEX2INT(colorstr[6]); +#ifdef GLENCORE + if (encoremap) + { + j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)]; + color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below + } +#endif + color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly + *rgba = color.rgba; + + // alpha + if (colorstr[7]) + *rgba += (ALPHA2INT(colorstr[7]) << 24); + else + *rgba += (25 << 24); + +#undef ALPHA2INT +#undef HEX2INT +} +#endif + static void P_LoadSideColormaps(mapsidedef_t *msd, side_t *sd, sector_t *sec) { INT32 num; #ifdef HWRENDER - if (rendermode == render_opengl) - { - // for now, full support of toptexture only - if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])) - { - char *col; - RGBA_t color; - size_t j; - - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; -#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) -#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) - sec->extra_colormap = &extra_colormaps[sec->midmap]; - - if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - { - col = msd->toptexture; - - // encore mode colormaps! - // do it like software by aproximating a color to a palette index, and then convert it to its encore variant and then back to a color code. - // do this for both the start and fade colormaps. - - color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]); - color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]); - color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]); - -#ifdef GLENCORE - if (encoremap) - { - j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)]; - color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below - } + const boolean docolor = (rendermode == render_opengl) ? + (msd->toptexture[0] == '#' && strlen(msd->toptexture) >= 7) : (msd->toptexture[0] == '#'); + const boolean doalpha = (rendermode == render_opengl) ? + (msd->bottomtexture[0] == '#' && strlen(msd->bottomtexture) >= 7) : (msd->bottomtexture[0] == '#'); +#else + const boolean docolor = (msd->toptexture[0] == '#'); + const boolean doalpha = (msd->bottomtexture[0] == '#'); #endif - color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly - sec->extra_colormap->rgba = color.rgba; - // alpha - if (msd->toptexture[7]) - sec->extra_colormap->rgba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->rgba += (25 << 24); + if (docolor || doalpha) + { + sec->extra_colormap = &extra_colormaps[R_CreateColormap(msd->toptexture, msd->midtexture, msd->bottomtexture)]; + sd->toptexture = sd->bottomtexture = 0; + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + if (docolor) + { + P_LoadSideColormapsGL(msd->toptexture, &sec->extra_colormap->rgba); } else sec->extra_colormap->rgba = 0; - if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) + if (doalpha) { - col = msd->bottomtexture; - - // do the exact same thing as above here. - - color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]); - color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]); - color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]); - -#ifdef GLENCORE - if (encoremap) - { - j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)]; - color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below - } -#endif - color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly - sec->extra_colormap->fadergba = color.rgba; - - // alpha - if (msd->bottomtexture[7]) - sec->extra_colormap->fadergba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->fadergba += (25 << 24); + P_LoadSideColormapsGL(msd->bottomtexture, &sec->extra_colormap->fadergba); } else sec->extra_colormap->fadergba = 0x19000000; // default alpha, (25 << 24) -#undef ALPHA2INT -#undef HEX2INT - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; } +#endif } -#endif -#ifdef HWRENDER else -#endif { - if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') - { - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } + if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) + sd->toptexture = 0; else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } + sd->toptexture = num; + + if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) + sd->midtexture = 0; + else + sd->midtexture = num; + + if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) + sd->bottomtexture = 0; + else + sd->bottomtexture = num; } } @@ -1452,34 +1336,27 @@ static void P_LoadSideChangeMusic(boolean firstside, mapsidedef_t *msd, side_t * sd->text[0] = 0; } -static void P_LoadRawSideDefs2(void *data) +static void P_LoadSidedefs(void *data) { - UINT16 i; + mapsidedef_t *msd = (mapsidedef_t *)data; + side_t *sd = sides; + size_t i; - for (i = 0; i < numsides; i++) + for (i = 0; i < numsides; i++, sd++, msd++) { - register mapsidedef_t *msd = (mapsidedef_t *)data + i; - register side_t *sd = sides + i; - register sector_t *sec; - sd->textureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<sector); + UINT16 sector_num = SHORT(msd->sector); - if (sector_num >= numsectors) - { - CONS_Debug(DBG_SETUP, "P_LoadRawSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num); - sector_num = 0; - } - sd->sector = sec = §ors[sector_num]; + // cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead + if (sector_num >= numsectors) + { + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num); + sector_num = 0; } - // refined to allow colormaps to work as wall textures if invalid as colormaps - // but valid as textures. - - sd->sector = sec = §ors[SHORT(msd->sector)]; + sd->sector = §ors[sector_num]; // Colormaps! switch (sd->special) @@ -1488,7 +1365,7 @@ static void P_LoadRawSideDefs2(void *data) case 606: //SoM: 4/4/2000: Just colormap transfer // SoM: R_CreateColormap will only create a colormap in software mode... // Perhaps we should just call it instead of doing the calculations here. - P_LoadSideColormaps(msd, sd, sec); + P_LoadSideColormaps(msd, sd, sd->sector); break; case 413: // Change music P_LoadSideChangeMusic((i == 1), msd, sd); @@ -1690,7 +1567,8 @@ static void P_CreateBlockMap(void) bmap_t *bmap = calloc(tot, sizeof (*bmap)); // array of blocklists boolean straight; - if (bmap == NULL) I_Error("%s: Out of memory making blockmap", "P_CreateBlockMap"); + if (bmap == NULL) + I_Error("%s: Out of memory making blockmap", "P_CreateBlockMap"); for (i = 0; i < numlines; i++) { @@ -1766,7 +1644,9 @@ static void P_CreateBlockMap(void) bmap[b].nalloc = 8; else bmap[b].nalloc *= 2; + bmap[b].list = Z_Realloc(bmap[b].list, bmap[b].nalloc * sizeof (*bmap->list), PU_CACHE, &bmap[b].list); + if (!bmap[b].list) I_Error("Out of Memory in P_CreateBlockMap"); } @@ -1802,6 +1682,7 @@ static void P_CreateBlockMap(void) blockmaplump[ndx++] = -1; // (Used for compression) for (i = 4; i < tot; i++, bp++) + { if (bp->n) // Non-empty blocklist { blockmaplump[blockmaplump[i] = (INT32)(ndx++)] = 0; // Store index & header @@ -1813,6 +1694,7 @@ static void P_CreateBlockMap(void) } else // Empty blocklist: point to reserved empty blocklist blockmaplump[i] = (INT32)tot; + } free(bmap); // Free uncompressed blockmap } @@ -1990,12 +1872,12 @@ static void P_GroupLines(void) // PK3 version // -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count) +static void P_LoadReject(UINT8 *data, size_t count) { if (!count) // zero length, someone probably used ZDBSP { rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n"); + CONS_Debug(DBG_SETUP, "P_LoadReject: REJECT lump has size 0, will not be loaded\n"); } else { @@ -2026,9 +1908,9 @@ static void P_LoadMapBSP(const virtres_t* virt) segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); // Nodes - P_LoadRawSubsectors(virtssectors->data); - P_LoadRawNodes(virtnodes->data); - P_LoadRawSegs(virtsegs->data); + P_LoadSubsectors(virtssectors->data); + P_LoadNodes(virtnodes->data); + P_LoadSegs(virtsegs->data); } static void P_LoadMapLUT(const virtres_t* virt) @@ -2038,7 +1920,7 @@ static void P_LoadMapLUT(const virtres_t* virt) // Lookup tables if (virtreject) - P_LoadRawReject(virtreject->data, virtreject->size); + P_LoadReject(virtreject->data, virtreject->size); else rejectmatrix = NULL; @@ -2069,10 +1951,10 @@ static void P_LoadMapData(const virtres_t* virt) I_Error("LINEDEFS lump not found"); // Traditional doom map format just assumes the number of elements from the lump sizes. - numvertexes = virtvertexes->size / sizeof (mapvertex_t); - numsectors = virtsectors->size / sizeof (mapsector_t); - numsides = virtsidedefs->size / sizeof (mapsidedef_t); - numlines = virtlinedefs->size / sizeof (maplinedef_t); + numvertexes = virtvertexes->size / sizeof(mapvertex_t); + numsectors = virtsectors->size / sizeof(mapsector_t); + numsides = virtsidedefs->size / sizeof(mapsidedef_t); + numlines = virtlinedefs->size / sizeof(maplinedef_t); nummapthings = virtthings->size / (5 * sizeof (INT16)); if (numvertexes <= 0) @@ -2084,18 +1966,27 @@ static void P_LoadMapData(const virtres_t* virt) if (numlines <= 0) I_Error("Level has no linedefs"); - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + vertexes = Z_Calloc(numvertexes * sizeof(*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + mapthings = Z_Calloc(nummapthings * sizeof(*mapthings), PU_LEVEL, NULL); // Strict map data - P_LoadRawVertexes(virtvertexes->data); - P_LoadRawSectors(virtsectors->data); - P_LoadRawLineDefs(virtlinedefs->data); - P_SetupLines(); - P_LoadRawSideDefs2(virtsidedefs->data); + P_LoadVertices(virtvertexes->data); + P_LoadSectors(virtsectors->data); + P_LoadLinedefs(virtlinedefs->data); + P_LoadSidedefs(virtsidedefs->data); + P_LoadThings(virtthings->data); + + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof(*sectors)); + memcpy(spawnlines, lines, numlines * sizeof(*lines)); + memcpy(spawnsides, sides, numsides * sizeof(*sides)); } /** Sets up a sky texture to use for the level. @@ -2141,9 +2032,7 @@ static void P_LevelInitStuff(boolean reloadinggamestate) // special stage tokens, emeralds, and ring total tokenbits = 0; runemeraldmanager = false; - nummaprings = 0; - nummapboxes = 0; - numgotboxes = 0; + nummaprings = nummapboxes = numgotboxes = 0; // emerald hunt hunt1 = hunt2 = hunt3 = NULL; @@ -2153,6 +2042,7 @@ static void P_LevelInitStuff(boolean reloadinggamestate) countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE; else countdowntimer = 0; + countdowntimeup = false; // clear ctf pointers @@ -2169,8 +2059,6 @@ static void P_LevelInitStuff(boolean reloadinggamestate) // special stage stagefailed = false; - // Reset temporary record data - //memset(&ntemprecords, 0, sizeof(nightsdata_t)); // earthquake camera memset(&quake,0,sizeof(struct quake)); @@ -2181,52 +2069,54 @@ static void P_LevelInitStuff(boolean reloadinggamestate) for (i = 0; i < MAXPLAYERS; i++) { - players[i].lives = 1; // SRB2Kart + player_t *player = &players[i]; - players[i].realtime = racecountdown = exitcountdown = 0; + player->lives = 1; // SRB2Kart + + player->realtime = racecountdown = exitcountdown = 0; for (INT32 j = 0; j < LAP__MAX; j++) { - players[i].laptime[j] = 0; + player->laptime[j] = 0; } - players[i].driftsparkGrowTimer = 0; + player->driftsparkGrowTimer = 0; - players[i].gotcontinue = false; + player->gotcontinue = false; - players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0; - players[i].health = 1; - players[i].aiming = 0; - players[i].pflags &= ~PF_TIMEOVER; + player->xtralife = player->deadtimer = player->numboxes = player->totalring = player->laps = 0; + player->health = 1; + player->aiming = 0; + player->pflags &= ~PF_TIMEOVER; - players[i].losstime = 0; - players[i].timeshit = 0; + player->losstime = 0; + player->timeshit = 0; - players[i].marescore = players[i].lastmarescore = players[i].maxlink = 0; - players[i].startedtime = players[i].finishedtime = players[i].finishedrings = 0; - players[i].lastmare = players[i].marebegunat = 0; + player->marescore = player->lastmarescore = player->maxlink = 0; + player->startedtime = player->finishedtime = player->finishedrings = 0; + player->lastmare = player->marebegunat = 0; // Don't show anything - players[i].textvar = players[i].texttimer = 0; + player->textvar = player->texttimer = 0; - players[i].linkcount = players[i].linktimer = 0; - players[i].flyangle = players[i].anotherflyangle = 0; - players[i].nightstime = players[i].mare = 0; - P_SetTarget(&players[i].capsule, NULL); - players[i].drillmeter = 40*20; + player->linkcount = player->linktimer = 0; + player->flyangle = player->anotherflyangle = 0; + player->nightstime = player->mare = 0; + P_SetTarget(&player->capsule, NULL); + player->drillmeter = 40*20; - players[i].exiting = 0; - P_ResetPlayer(&players[i]); + player->exiting = 0; + P_ResetPlayer(player); - players[i].spectatorreentry = 0; // SRB2Kart 1.4 + player->spectatorreentry = 0; // SRB2Kart 1.4 - players[i].mo = NULL; + player->mo = NULL; // we must unset axis details too - players[i].axis1 = players[i].axis2 = NULL; + player->axis1 = player->axis2 = NULL; // and this stupid flag as a result - players[i].pflags &= ~PF_TRANSFERTOCLOSEST; + player->pflags &= ~PF_TRANSFERTOCLOSEST; } // SRB2Kart: map load variables @@ -2317,19 +2207,7 @@ static void P_LoadMapFromFile(void) P_LoadLineDefs2(); P_GroupLines(); - P_PrepareRawThings(vres_Find(curmapvirt, "THINGS")->data); - P_MakeMapMD5(curmapvirt, &mapmd5); - - // We do the following silly - // construction because vres_Free - // no-sells deletions of pointers - // that are == curmapvirt. - { - virtres_t *temp = curmapvirt; - curmapvirt = NULL; - vres_Free(temp); - } } static void P_RunLevelScript(const char *scriptname) @@ -2510,14 +2388,13 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) switch (gametype) { - case GT_MATCH: - case GT_TAG: - thing = deathmatchstarts[0]; - break; - - default: - thing = playerstarts[0]; - break; + case GT_MATCH: + case GT_TAG: + thing = deathmatchstarts[0]; + break; + default: + thing = playerstarts[0]; + break; } if (!thing) @@ -2568,12 +2445,14 @@ static void P_InitMinimapInfo(void) node_t *bsp = &nodes[numnodes-1]; + if (minimapinfo.minimap_pic) + Patch_Free(minimapinfo.minimap_pic); minimapinfo.minimap_pic = NULL; lumpnum = W_CheckNumForName(va("%sR", G_BuildMapName(gamemap))); if (lumpnum != LUMPERROR) - minimapinfo.minimap_pic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_HUDGFX); + minimapinfo.minimap_pic = W_CachePatchName(va("%sR", G_BuildMapName(gamemap)), PU_PATCH); minimapinfo.min_x = bsp->bbox[0][BOXLEFT]; minimapinfo.max_x = bsp->bbox[0][BOXRIGHT]; @@ -2753,12 +2632,15 @@ static void P_SetupPlayer(void) } else if (G_RaceGametype() && server) - CV_StealthSetValue(&cv_numlaps, - ((netgame || multiplayer) && cv_basenumlaps.value - && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) - || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))) - ? cv_basenumlaps.value - : mapheaderinfo[gamemap - 1]->numlaps); + { + INT32 numLaps = ((netgame || multiplayer) && cv_basenumlaps.value + && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) + || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))) + ? cv_basenumlaps.value + : mapheaderinfo[gamemap - 1]->numlaps; + + CV_StealthSetValue(&cv_numlaps, numLaps); + } // Start recording replay in multiplayer with a temp filename // Ensure dedis only record a replay if there is a player at the start of the map, otherwise we get invalid replays! @@ -2804,6 +2686,55 @@ static void P_SetupPlayer(void) } } +void P_FreeLevelState(void) +{ + sector_t *ss; + + if (numsectors) + { + LUA_InvalidateLevel(); + + for (ss = sectors; sectors+numsectors != ss; ss++) + { + Z_Free(ss->attached); + Z_Free(ss->attachedsolid); + } + + // This is the simplest guard against double frees. + // No valid map has zero sectors. Or, come to think + // of it, less than two in general! ~toast 310525 + numsectors = 0; + } + + // Clear pointers that would be left dangling by the purge + R_FlushTranslationColormapCache(); + +#ifdef HWRENDER + // Free GPU textures before freeing patches. + if (vid.glstate == VID_GL_LIBRARY_LOADED) + { + if (rendermode == render_opengl) + HWR_ClearAllTextures(); + + // Delete light table textures + HWR_ClearLightTables(); + } +#endif + + G_FreeGhosts(); // ghosts are allocated with PU_LEVEL + + Patch_FreeTag(PU_PATCH_LOWPRIORITY); + //Patch_FreeTag(PU_PATCH_ROTATED); // we keep those ty! + Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); + + Y_VoteClear(); + +#if defined (WALLSPLATS) || defined (FLOORSPLATS) + // clear the splats from previous level + R_ClearLevelSplats(); +#endif +} + /** Loads a level from a lump or external wad. * * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. @@ -2816,7 +2747,14 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) // Map header should always be in place at this point INT32 i; boolean ranspecialwipe = false; - sector_t *ss; + lumpnum_t encoreLump = LUMPERROR; + UINT8 levelfadecol; + + // HACK: this doesent reset if you change the map from within a replay and may cause crashes or the replayhut to be non functional + if (!demo.playback && demo.inreplayhut) + { + M_ResetDemoList(); + } midgamejoin = fromnetsave; // makes dynslopes run in P_Ticker/P_PreTicker to avoid synch issues and other stuff @@ -2916,38 +2854,7 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) I_UpdateNoVsync(); }*/ - LUA_InvalidateLevel(); - - for (ss = sectors; sectors+numsectors != ss; ss++) - { - Z_Free(ss->attached); - Z_Free(ss->attachedsolid); - } - - // Clear pointers that would be left dangling by the purge - R_FlushTranslationColormapCache(); - -#ifdef HWRENDER - // Free GPU textures before freeing patches. - if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED)) - HWR_ClearAllTextures(); - - // Delete light table textures - HWR_ClearLightTables(); -#endif - - Patch_FreeTag(PU_PATCH_LOWPRIORITY); - //Patch_FreeTag(PU_PATCH_ROTATED); // we keep those ty! - Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1); - - Y_VoteClear(); - -#if defined (WALLSPLATS) || defined (FLOORSPLATS) - // clear the splats from previous level - R_ClearLevelSplats(); -#endif - - mobjcache = NULL; + P_FreeLevelState(); R_InitializeLevelInterpolators(); @@ -2958,13 +2865,14 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) // internal game map maplumpname = G_BuildMapName(gamemap); lastloadedmaplumpnum = W_CheckNumForName(maplumpname); - if (lastloadedmaplumpnum == INT16_MAX) + if (lastloadedmaplumpnum == LUMPERROR) I_Error("Map %s not found.\n", maplumpname); curmapvirt = vres_GetMap(lastloadedmaplumpnum); - R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, - W_CheckNumForName(va("%s%c", maplumpname, (encoremode ? 'E' : 'T')))); + encoreLump = W_CheckNumForName(va("%s%c", maplumpname, (encoremode ? 'E' : 'T'))); + R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, encoreLump); + CON_SetupBackColormap(); // SRB2 determines the sky texture to be used depending on the map header. @@ -2978,14 +2886,13 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) P_MapStart(); - if (lastloadedmaplumpnum) - P_LoadMapFromFile(); + P_LoadMapFromFile(); P_ResetDynamicSlopes(); - P_LoadThings(); + P_SpawnMapThings(); - P_SpawnSecretItems(!fromnetsave); + P_SpawnEmblems(!fromnetsave); P_InitMinimapInfo(); @@ -3017,6 +2924,17 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) if (!fromnetsave) P_SetupPlayer(); + // Now safe to free. + // We do the following silly + // construction because vres_Free + // no-sells deletions of pointers + // that are == curmapvirt. + { + virtres_t *temp = curmapvirt; + curmapvirt = NULL; + vres_Free(temp); + } + if (!reloadinggamestate) { P_InitCamera(); @@ -3071,7 +2989,9 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) + { G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + } } P_PreTicker(2); @@ -3088,6 +3008,8 @@ boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate) G_AddMapToBuffer(gamemap-1); + D_ResetDeviceLED(); + return true; } @@ -3266,7 +3188,7 @@ UINT16 P_PartialAddWadFile(const char *wadfilename, boolean local) sreplaces = mreplaces = digmreplaces = 0; - if ((numlumps = W_InitFile(wadfilename, local)) == INT16_MAX) + if ((numlumps = W_InitFile(wadfilename, local, false)) == INT16_MAX) { refreshdirmenu |= REFRESHDIR_NOTLOADED; CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); diff --git a/src/p_setup.h b/src/p_setup.h index 5d4a3b9da..02f3238c6 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -35,7 +35,6 @@ extern mapthing_t *deathmatchstarts[MAX_DM_STARTS]; extern INT32 numdmstarts, numcoopstarts, numredctfstarts, numbluectfstarts; extern boolean levelloading; -extern UINT8 levelfadecol; extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame extern virtres_t *curmapvirt; @@ -63,8 +62,12 @@ INT32 P_CheckLevelFlat(const char *flatname); extern size_t nummapthings; extern mapthing_t *mapthings; +extern sector_t *spawnsectors; +extern line_t *spawnlines; +extern side_t *spawnsides; void P_SetupLevelSky(INT32 skynum, boolean global); +void P_FreeLevelState(void); boolean P_SetupLevel(boolean fromnetsave, boolean reloadinggamestate); #ifdef HWRENDER diff --git a/src/p_slopes.c b/src/p_slopes.c index d4c033eeb..850813331 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -10,6 +10,7 @@ /// \file p_slopes.c /// \brief ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron +#include "d_think.h" #include "doomdef.h" #include "r_defs.h" #include "r_state.h" @@ -84,7 +85,8 @@ static void P_UpdateSlopeLightOffset(pslope_t *slope) light = FixedDiv(R_PointToAngle2(0, 0, abs(slope->d.x), abs(slope->d.y)), ANGLE_90); } - zMul = min(FRACUNIT, abs(slope->zdelta)*3/2); // *3/2, to make 60 degree slopes match walls. + const int delta = abs(slope->zdelta)*3/2; // *3/2, to make 60 degree slopes match walls. + zMul = min(FRACUNIT, delta); contrastFixed = FixedMul(contrastFixed, zMul); extralight = -contrastFixed + FixedMul(light, contrastFixed * 2); @@ -123,10 +125,14 @@ static void P_ReconfigureVertexSlope(pslope_t *slope) vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS; // ugggggggh fixed-point maaaaaaath + const int absx1 = abs(vec1.x); const int absy1 = abs(vec1.y); const int absz1 = abs(vec1.z); + const int absx2 = abs(vec2.x); const int absy2 = abs(vec2.y); const int absz2 = abs(vec2.z); + slope->extent = max( - max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)), - max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z)) + max(max(absx1, absy1), absz1), + max(max(absx2, absy2), absz2) ) >> (FRACBITS+5); + vec1.x /= slope->extent; vec1.y /= slope->extent; vec1.z /= slope->extent; @@ -618,7 +624,7 @@ void P_SpawnSlope_Line(int linenum) } } - if(!line->tag) + if (!line->tag) return; } diff --git a/src/p_spec.c b/src/p_spec.c index a7a7f89f3..f9073c026 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -15,6 +15,7 @@ /// utility functions, etc. /// Line Tag handling. Line and Sector triggers. +#include "d_think.h" #include "doomdef.h" #include "g_game.h" #include "p_local.h" @@ -974,7 +975,7 @@ static boolean PolyDoor(line_t *line) case 480: // Polyobj_DoorSlide pdd.doorType = POLY_DOOR_SLIDE; pdd.speed = sides[line->sidenum[0]].textureoffset / 8; - pdd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); // angle of motion + pdd.angle = line->angle; // angle of motion pdd.distance = sides[line->sidenum[0]].rowoffset; if (line->sidenum[1] != 0xffff) @@ -1010,7 +1011,7 @@ static boolean PolyMove(line_t *line) pmd.polyObjNum = line->tag; pmd.speed = sides[line->sidenum[0]].textureoffset / 8; - pmd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + pmd.angle = line->angle; pmd.distance = sides[line->sidenum[0]].rowoffset; pmd.overRide = (line->special == 483); // Polyobj_OR_Move @@ -1232,7 +1233,7 @@ void P_ChangeSectorTag(UINT32 sector, INT16 newtag) * \sa P_FindSectorFromTag, P_ChangeSectorTag * \author Lee Killough */ -static inline void P_InitTagLists(void) +void P_InitTagLists(void) { register size_t i; @@ -1241,8 +1242,6 @@ static inline void P_InitTagLists(void) size_t j = (unsigned)sectors[i].tag % numsectors; sectors[i].nexttag = sectors[j].firsttag; sectors[j].firsttag = (INT32)i; - sectors[i].spawn_nexttag = sectors[i].nexttag; - sectors[j].spawn_firsttag = sectors[j].firsttag; } for (i = numlines - 1; i != (size_t)-1; i--) @@ -1300,7 +1299,9 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) if (!line->backsector) I_Error("P_AddExecutorDelay: Line has no backsector!\n"); - e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL); + e = Z_LevelPoolCalloc(sizeof (*e)); + e->thinker.alloctype = TAT_LEVELPOOL; + e->thinker.size = sizeof (*e); e->thinker.function = (actionf_p1)T_ExecutorDelay; e->line = line; @@ -1693,11 +1694,9 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 306 // Character ability - Each time || lines[masterline].special == 310 // CTF Red team - Each time || lines[masterline].special == 312 // CTF Blue team - Each time - || lines[masterline].special == 322) // Trigger on X calls - Each Time - continue; - - if (lines[masterline].special < 300 - || lines[masterline].special > 399) + || lines[masterline].special == 322 // Trigger on X calls - Each Time + || lines[masterline].special < 300 + || lines[masterline].special > 399) continue; if (!P_RunTriggerLinedef(&lines[masterline], actor, caller)) @@ -1715,7 +1714,6 @@ static boolean is_rain_type (INT32 weathernum) case PRECIP_STORM_NOSTRIKES: case PRECIP_BLANK: return true; - default: return false; } @@ -3523,7 +3521,7 @@ DoneSection2: angle_t lineangle; fixed_t linespeed; - lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); + lineangle = lines[i].angle; linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); player->mo->angle = lineangle; @@ -3537,9 +3535,7 @@ DoneSection2: { for (UINT8 j = 0; j <= splitscreen; ++j) { - INT32 id = (j == 0 ? consoleplayer : displayplayers[j]); - - if (player == &players[id]) + if (player == P_GetLocalPlayerForNum(j)) { localangle[j] = player->mo->angle; break; @@ -4767,6 +4763,11 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f ffloor->t_slope = &sec2->c_slope; ffloor->b_slope = &sec2->f_slope; + // mark the target sector as having slopes, if the FOF has any of its own + // (this fixes FOF slopes glitching initially at level load in software mode) + if (sec2->hasslope) + sec->hasslope = true; + if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only flags &= ~FF_BLOCKOTHERS; @@ -4904,7 +4905,10 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer) levelspecthink_t *spikes; // create and initialize new thinker - spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL); + spikes = Z_LevelPoolCalloc(sizeof (*spikes)); + spikes->thinker.alloctype = TAT_LEVELPOOL; + spikes->thinker.size = sizeof (*spikes); + P_AddThinker(&spikes->thinker); spikes->thinker.function = (actionf_p1)T_SpikeSector; @@ -4926,7 +4930,9 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline) levelspecthink_t *floater; // create and initialize new thinker - floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL); + floater = Z_LevelPoolCalloc(sizeof (*floater)); + floater->thinker.alloctype = TAT_LEVELPOOL; + floater->thinker.size = sizeof (*floater); P_AddThinker(&floater->thinker); floater->thinker.function = (actionf_p1)T_FloatSector; @@ -4955,7 +4961,9 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) levelspecthink_t *block; // create and initialize new elevator thinker - block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); + block = Z_LevelPoolCalloc(sizeof (*block)); + block->thinker.alloctype = TAT_LEVELPOOL; + block->thinker.size = sizeof (*block); P_AddThinker(&block->thinker); block->thinker.function = (actionf_p1)T_MarioBlockChecker; @@ -4984,7 +4992,9 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline) { levelspecthink_t *raise; - raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); + raise = Z_LevelPoolCalloc(sizeof (*raise)); + raise->thinker.alloctype = TAT_LEVELPOOL; + raise->thinker.size = sizeof (*raise); P_AddThinker(&raise->thinker); raise->thinker.function = (actionf_p1)T_RaiseSector; @@ -5027,7 +5037,9 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust) { levelspecthink_t *airbob; - airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL); + airbob = Z_LevelPoolCalloc(sizeof (*airbob)); + airbob->thinker.alloctype = TAT_LEVELPOOL; + airbob->thinker.size = sizeof (*airbob); P_AddThinker(&airbob->thinker); airbob->thinker.function = (actionf_p1)T_RaiseSector; @@ -5092,7 +5104,9 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin return; // create and initialize new elevator thinker - thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL); + thwomp = Z_LevelPoolCalloc(sizeof (*thwomp)); + thwomp->thinker.alloctype = TAT_LEVELPOOL; + thwomp->thinker.size = sizeof (*thwomp); P_AddThinker(&thwomp->thinker); thwomp->thinker.function = (actionf_p1)T_ThwompSector; @@ -5133,7 +5147,9 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) levelspecthink_t *nobaddies; // create and initialize new thinker - nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); + nobaddies = Z_LevelPoolCalloc(sizeof (*nobaddies)); + nobaddies->thinker.alloctype = TAT_LEVELPOOL; + nobaddies->thinker.size = sizeof (*nobaddies); P_AddThinker(&nobaddies->thinker); nobaddies->thinker.function = (actionf_p1)T_NoEnemiesSector; @@ -5155,7 +5171,9 @@ static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline) levelspecthink_t *eachtime; // create and initialize new thinker - eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL); + eachtime = Z_LevelPoolCalloc(sizeof (*eachtime)); + eachtime->thinker.alloctype = TAT_LEVELPOOL; + eachtime->thinker.size = sizeof (*eachtime); P_AddThinker(&eachtime->thinker); eachtime->thinker.function = (actionf_p1)T_EachTimeThinker; @@ -5177,7 +5195,9 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto elevator_t *elevator; // Why not? LOL // create and initialize new elevator thinker - elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); + elevator = Z_LevelPoolCalloc(sizeof (*elevator)); + elevator->thinker.alloctype = TAT_LEVELPOOL; + elevator->thinker.size = sizeof (*elevator); P_AddThinker(&elevator->thinker); elevator->thinker.function = (actionf_p1)T_CameraScanner; @@ -5259,13 +5279,14 @@ void T_LaserFlash(laserthink_t *flash) */ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers) { - laserthink_t *flash; ffloor_t *ffloor = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers); if (!ffloor) return; - flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); + laserthink_t *flash = Z_LevelPoolCalloc(sizeof (*flash)); + flash->thinker.alloctype = TAT_LEVELPOOL; + flash->thinker.size = sizeof (*flash); P_AddThinker(&flash->thinker); @@ -5466,7 +5487,7 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate) case 5: // Change camera info sec = sides[*lines[i].sidenum].sector - sectors; for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); + P_AddCameraScanner(§ors[sec], §ors[s], lines[i].angle); break; #ifdef PARANOIA @@ -5477,7 +5498,7 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate) case 7: // Flat alignment - redone by toast if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something... { - angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); + angle_t flatangle = InvAngle(lines[i].angle); fixed_t xoffs; fixed_t yoffs; @@ -5496,22 +5517,16 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate) { if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set { - sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle; + sectors[s].floorpic_angle = flatangle; sectors[s].floor_xoffs += xoffs; sectors[s].floor_yoffs += yoffs; - // saved for netgames - sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs; - sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs; } if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set { - sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle; + sectors[s].ceilingpic_angle = flatangle; sectors[s].ceiling_xoffs += xoffs; sectors[s].ceiling_yoffs += yoffs; - // saved for netgames - sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs; - sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs; } } } @@ -6278,7 +6293,7 @@ void P_SpawnSpecials(INT32 fromnetsave, boolean reloadinggamestate) case 606: // HACK! Copy colormaps. Just plain colormaps. for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].midmap = lines[i].frontsector->midmap; + sectors[s].extra_colormap = lines[i].frontsector->extra_colormap; break; case 720: @@ -6632,8 +6647,11 @@ void T_Scroll(scroll_t *s) */ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT32 affectee, INT32 accel, INT32 exclusive) { - scroll_t *s = Z_Calloc(sizeof *s, PU_LEVSPEC, NULL); + scroll_t *s = Z_LevelPoolCalloc(sizeof (*s)); + s->thinker.alloctype = TAT_LEVELPOOL; + s->thinker.size = sizeof (*s); s->thinker.function = (actionf_p1)T_Scroll; + s->type = type; s->dx = dx; s->dy = dy; @@ -6801,7 +6819,9 @@ static void P_SpawnScrollers(void) */ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline) { - disappear_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + disappear_t *d = Z_LevelPoolCalloc(sizeof (*d)); + d->thinker.alloctype = TAT_LEVELPOOL; + d->thinker.size = sizeof (*d); d->thinker.function = (actionf_p1)T_Disappear; d->appeartime = appeartime; @@ -6886,7 +6906,9 @@ void T_Disappear(disappear_t *d) */ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer) { - friction_t *f = Z_Calloc(sizeof *f, PU_LEVSPEC, NULL); + friction_t *f = Z_LevelPoolCalloc(sizeof (*f)); + f->thinker.alloctype = TAT_LEVELPOOL; + f->thinker.size = sizeof (*f); f->thinker.function = (actionf_p1)T_Friction; f->friction = friction; @@ -7041,7 +7063,9 @@ static void P_SpawnFriction(void) */ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider) { - pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL); + pusher_t *p = Z_LevelPoolCalloc(sizeof (*p)); + p->thinker.alloctype = TAT_LEVELPOOL; + p->thinker.size = sizeof (*p); p->thinker.function = (actionf_p1)T_Pusher; p->source = source; @@ -7477,8 +7501,7 @@ void T_Pusher(pusher_t *p) { for (UINT8 i = 0; i <= splitscreen; ++i) { - INT32 id = (i == 0 ? consoleplayer : displayplayers[i]); - if (thing->player == &players[id]) + if (thing->player == P_GetLocalPlayerForNum(i)) { if (thing->angle - localangle[i] > ANGLE_180) localangle[i] -= (localangle[i] - thing->angle) / 8; diff --git a/src/p_spec.h b/src/p_spec.h index 60b10a8f4..7b763c498 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -80,6 +80,7 @@ void P_SwitchWeather(INT32 weathernum); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); void P_ChangeSectorTag(UINT32 sector, INT16 newtag); +void P_InitTagLists(void); // // P_LIGHTS diff --git a/src/p_telept.c b/src/p_telept.c index ceed7dc93..539e0050b 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -65,17 +65,12 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, thing->reactiontime = TICRATE/2; // don't move for about half a second // absolute angle position - if (thing == players[consoleplayer].mo) - localangle[0] = angle; - else if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - for (i = 1; i <= splitscreen; i++) + if (thing == P_GetLocalPlayerForNum(i)->mo) { - if (thing == players[displayplayers[i]].mo) - { - localangle[i] = angle; - break; - } + localangle[i] = angle; + break; } } diff --git a/src/p_tick.c b/src/p_tick.c index 752e60794..e6755fec7 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -15,6 +15,7 @@ #include "dehacked.h" // MOBJTYPE_LIST #endif +#include "d_think.h" #include "doomstat.h" #include "dehacked.h" #include "g_game.h" @@ -207,8 +208,6 @@ void P_AddThinker(thinker_t *thinker) thinkercap.prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 - - thinker->cachable = (thinker->function == (actionf_p1)P_MobjThinker); #ifdef PARANOIA thinker->debug_mobjtype = MT_NULL; #endif @@ -226,8 +225,6 @@ void P_AddPrecipThinker(thinker_t *thinker) precipcap.prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 - - thinker->cachable = false; #ifdef PARANOIA thinker->debug_mobjtype = MT_NULL; #endif @@ -345,11 +342,9 @@ void P_UnlinkThinker(thinker_t *thinker) (next->prev = thinker->prev)->next = next; - if (thinker->cachable == true) + if (thinker->alloctype == TAT_LEVELPOOL) { - // put cachable thinkers in the mobj cache, so we can avoid allocations - ((mobj_t *)thinker)->hnext = mobjcache; - mobjcache = (mobj_t *)thinker; + Z_LevelPoolFree(thinker, thinker->size); } else { @@ -546,6 +541,19 @@ static void P_DeviceRumbleTick(void) high = CLAMP((high + FRACUNIT / 256), 0, UINT16_MAX); } + // pulse when gettin new driftlevel + // let this come last + if (player->kartstuff[k_driftcharge] + && player->driftlevel) + { + high = CLAMP((high + FRACUNIT / 256), 0, UINT16_MAX); + + if (player->driftlevel == 2) + lenght = 114; + else if (player->driftlevel == 3) + lenght = 174; + } + // hack alert! i just dont want this thing constantly resetting the rumble lol if (low == 0 && high == 0) { diff --git a/src/p_user.c b/src/p_user.c index 24fdb0b01..670db91d8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -795,7 +795,7 @@ boolean P_IsObjectInGoop(mobj_t *mo) // boolean P_IsObjectOnGround(mobj_t *mo) { - if (P_IsObjectInGoop(mo)) + if (UNLIKELY(P_IsObjectInGoop(mo))) { // but I don't want you to ever 'stand' while submerged in goo. // You're in constant vertical momentum, even if you get stuck on something. @@ -980,7 +980,18 @@ fixed_t P_GetPlayerSpinHeight(player_t *player) // player_t *P_GetLocalPlayerForNum(UINT8 pnum) { - return (pnum == 0 ? &players[consoleplayer] : &players[displayplayers[pnum]]); + return (&players[P_GetLocalPlayerNumForNum(pnum)]); +} + +// +// P_GetLocalPlayerNumForNum +// +// Returns the player number +// on the local machine for given number. +// +INT32 P_GetLocalPlayerNumForNum(UINT8 pnum) +{ + return (pnum == 0 ? consoleplayer : displayplayers[pnum]); } // @@ -993,15 +1004,29 @@ boolean P_IsLocalPlayer(const player_t *player) { UINT8 i; - if (player == &players[consoleplayer]) - return true; - else if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - for (i = 1; i <= splitscreen; i++) // Skip P1 - { - if (player == &players[displayplayers[i]]) - return true; - } + if (player == P_GetLocalPlayerForNum(i)) + return true; + } + + return false; +} + +// +// P_IsLocalPlayer +// +// Returns true if playernum is +// on the local machine. +// +boolean P_IsLocalPlayerNum(UINT8 pnum) +{ + UINT8 i; + + for (i = 0; i <= splitscreen; i++) + { + if (pnum == P_GetLocalPlayerNumForNum(i)) + return true; } return false; @@ -2575,14 +2600,14 @@ static void P_DoZoomTube(player_t *player) { player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (player == P_GetLocalPlayerForNum(i)) + { + localangle[i] = player->mo->angle; + break; + } + } } } @@ -2768,14 +2793,14 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target if (source->player) { - if (source->player == &players[consoleplayer]) - localangle[0] = source->angle; - else if (source->player == &players[displayplayers[1]]) - localangle[1] = source->angle; - else if (source->player == &players[displayplayers[2]]) - localangle[2] = source->angle; - else if (source->player == &players[displayplayers[3]]) - localangle[3] = source->angle; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (source->player == P_GetLocalPlayerForNum(i)) + { + localangle[i] = source->angle; + break; + } + } } // change slope @@ -3140,23 +3165,6 @@ static ticcmd_t *P_CameraCmd(camera_t *cam, UINT8 num) lang = cam->localangle; laim = cam->localaiming; - switch (forplayer) - { - case 2: - G_CopyTiccmd(cmd, I_BaseTiccmd2(), 1); - break; - case 3: - G_CopyTiccmd(cmd, I_BaseTiccmd3(), 1); - break; - case 4: - G_CopyTiccmd(cmd, I_BaseTiccmd4(), 1); - break; - case 1: - default: - G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver - break; - } - cmd->angleturn = (INT16)(lang >> 16); cmd->aiming = G_ClipAimingPitch(&laim); @@ -3966,7 +3974,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->kartstuff[k_drift] != 0) { fixed_t panmax = (dist/5); - pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], K_GetKartDriftSparkValue(player)), panmax), K_GetKartDriftSparkValue(player)); + const INT32 sparkval = K_GetKartDriftSparkValue(player); + pan = FixedDiv(FixedMul(min((fixed_t)player->kartstuff[k_driftcharge], sparkval), panmax), sparkval); if (pan > panmax) pan = panmax; if (player->kartstuff[k_drift] < 0) @@ -4131,19 +4140,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall void P_ResetLocalCamAiming(player_t *player) { - UINT8 i; - - if (player == &players[consoleplayer]) - localaiming[0] = 0; - else if (splitscreen) + for (UINT8 i = 0; i <= splitscreen; i++) { - for (i = 1; i <= splitscreen; i++) // Skip P1 + if (player == P_GetLocalPlayerForNum(i)) { - if (player == &players[displayplayers[i]]) - { - localaiming[i] = 0; - break; - } + localangle[i] = 0; + break; } } } @@ -4531,6 +4533,8 @@ void P_PlayerThink(player_t *player) I_Error("p_playerthink: players[%s].mo == NULL", sizeu1(playeri)); #endif + player->driftlevel = 0; // idk where to put this + // todo: Figure out what is actually causing these problems in the first place... if ((player->health <= 0 || player->mo->health <= 0) && player->playerstate == PST_LIVE) //you should be DEAD! { @@ -5166,14 +5170,14 @@ void P_PlayerAfterThink(player_t *player) player->mo->tracer->target->health += cmd->sidemove; player->mo->angle += cmd->sidemove << ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; // Adjust the local control angle. - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; + for (UINT8 i = 0; i <= splitscreen; i++) + { + if (player == P_GetLocalPlayerForNum(i)) + { + localangle[i] = player->mo->angle; // Adjust the local control angle. + break; + } + } } } diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index a05bf70c4..ae89109db 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -48,7 +48,7 @@ boolean g_walloffscreen; boolean R_NoEncore(sector_t *sector, boolean ceiling) { - boolean invertencore = (GETSECSPECIAL(sector->special, 2) == 15); + boolean invertencore = (GETSECSPECIAL(sector->special, 2) == 12 || GETSECSPECIAL(sector->special, 2) == 15); // keeping this incase its used #if 0 // perfect implementation INT32 val = GETSECSPECIAL(sector->special, 3); if (val != 1 && val != 3 // spring panel @@ -177,8 +177,6 @@ void R_PortalClearClipSegs(INT32 start, INT32 end) sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back) { - INT32 mapnum = -1; - if (floorlightlevel) *floorlightlevel = sec->floorlightsec == -1 ? sec->lightlevel : sectors[sec->floorlightsec].lightlevel; @@ -187,10 +185,10 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, *ceilinglightlevel = sec->ceilinglightsec == -1 ? sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; - // If the sector has a midmap, it's probably from 280 type - if (sec->midmap != -1) - mapnum = sec->midmap; - else if (sec->heightsec != -1) + // if (sec->midmap != -1) + // mapnum = sec->midmap; + // In original colormap code, this block did not run if sec->midmap was set + if (!sec->extra_colormap && sec->heightsec != -1) { const sector_t *s = §ors[sec->heightsec]; mobj_t *pviewmobj = viewplayer->mo; @@ -214,8 +212,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floorheight = s->floorheight; tempsec->ceilingheight = s->ceilingheight; - mapnum = s->midmap; - if ((underwater && (tempsec-> floorheight = sec->floorheight, tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) { // head-below-floor hack @@ -241,7 +237,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceilingpic_angle = s->ceilingpic_angle; } - mapnum = s->bottommap; } tempsec->lightlevel = s->lightlevel; @@ -265,8 +260,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle; - mapnum = s->topmap; - if (s->floorpic == skyflatnum) // SKYFIX? { tempsec->ceilingheight = tempsec->floorheight-1; @@ -297,11 +290,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sec = tempsec; } - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; - return sec; } @@ -826,8 +814,9 @@ static void R_Subsector(size_t num) sub->sector->extra_colormap = frontsector->extra_colormap; - if ((P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz || (frontsector->heightsec != -1 - && sectors[frontsector->heightsec].ceilingpic == skyflatnum))) + if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz + || frontsector->floorpic == skyflatnum + || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum)) { floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL @@ -838,9 +827,9 @@ static void R_Subsector(size_t num) else floorplane = NULL; - if ((P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz || frontsector->ceilingpic == skyflatnum - || (frontsector->heightsec != -1 - && sectors[frontsector->heightsec].floorpic == skyflatnum))) + if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz + || frontsector->ceilingpic == skyflatnum + || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, @@ -889,12 +878,15 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); - ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, - *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, - *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover + ffloor[numffloors].plane = R_FindPlane( + *rover->bottomheight, *rover->bottompic, + *frontsector->lightlist[light].lightlevel, + *rover->bottomxoffs, *rover->bottomyoffs, *rover->bottomangle, + frontsector->lightlist[light].extra_colormap, rover , NULL , *rover->b_slope - , R_NoEncore(rover->master->frontsector, true), true, frontsector); + , R_NoEncore(rover->master->frontsector, true), true, frontsector + ); ffloor[numffloors].slope = *rover->b_slope; @@ -923,12 +915,15 @@ static void R_Subsector(size_t num) { light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); - ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, - *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, + ffloor[numffloors].plane = R_FindPlane( + *rover->topheight, *rover->toppic, + *frontsector->lightlist[light].lightlevel, + *rover->topxoffs, *rover->topyoffs, *rover->topangle, frontsector->lightlist[light].extra_colormap, rover , NULL , *rover->t_slope - , R_NoEncore(rover->master->frontsector, false), false, frontsector); + , R_NoEncore(rover->master->frontsector, false), false, frontsector + ); ffloor[numffloors].slope = *rover->t_slope; @@ -1056,7 +1051,7 @@ void R_Prep3DFloors(sector_t *sector) ffloor_t *rover; ffloor_t *best; fixed_t bestheight, maxheight; - INT32 count, i, mapnum; + INT32 count, i; sector_t *sec; pslope_t *bestslope = NULL; fixed_t heighttest; // I think it's better to check the Z height at the sector's center @@ -1139,12 +1134,6 @@ void R_Prep3DFloors(sector_t *sector) sector->lightlist[i].flags = best->flags; sector->lightlist[i].slope = bestslope; sec = §ors[best->secnum]; - mapnum = sec->midmap; - - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; if (best->flags & FF_NOSHADE) { diff --git a/src/r_data.c b/src/r_data.c index 4c93bfe25..8bd532d83 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -463,15 +463,8 @@ void R_CheckTextureCache(INT32 tex) R_GenerateTexture(tex); } -// -// R_GetColumn -// -UINT8 *R_GetColumn(fixed_t tex, INT32 col) +static inline INT32 wrap_column(fixed_t tex, INT32 col) { - UINT8 *data; - - data = texturecache[tex]; - if (texturewidthmask[tex]) col &= texturewidthmask[tex]; // set by load textures else @@ -484,14 +477,22 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col) col = ((col % texwidth) + texwidth) % texwidth; } - if (!data) + return col; +} + +// +// R_GetColumn +// +UINT8 *R_GetColumn(fixed_t tex, INT32 col) +{ + if (!texturecache[tex]) { // This must be here because cache can be freed by other operations. // To prevent must lock individual texture cache on every draw. - data = R_GenerateTexture(tex); + R_GenerateTexture(tex); } - return data + LONG(texturecolumnofs[tex][col]); + return texturecache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]); } // convert flats to hicolor as they are requested @@ -523,7 +524,7 @@ void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); static INT32 Rloadtextures (INT32 i, INT32 w) { - UINT16 j; + UINT16 j, numlumps = 0; INT32 k; UINT16 texstart, texend, texturesLumpPos; softwarepatch_t *patchlump; @@ -554,8 +555,10 @@ Rloadtextures (INT32 i, INT32 w) if (texstart == INT16_MAX || texend == INT16_MAX) return i; + numlumps = texend - texstart; + // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); j++) + for (j = 0; j < numlumps; j++) { UINT16 wadnum = (UINT16)w; lumpnum_t lumpnum = texstart + j; @@ -1778,6 +1781,20 @@ void R_ClearTextureNumCache(boolean btell) tidcachelen = 0; } +static void AddTextureToCache(const char *name, UINT32 hash, INT32 id) +{ + tidcachelen++; + Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); + strncpy(tidcache[tidcachelen-1].name, name, 8); + tidcache[tidcachelen-1].name[8] = '\0'; +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); +#endif + tidcache[tidcachelen-1].hash = hash; + tidcache[tidcachelen-1].id = id; +} + + // // R_CheckTextureNumForName // @@ -1799,19 +1816,10 @@ INT32 R_CheckTextureNumForName(const char *name) return tidcache[i].id; // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier - //for (i = 0; i < numtextures; i++) <- old - for (i = (numtextures - 1); i >= 0; i--) // <- new + for (i = (numtextures - 1); i >= 0; i--) if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8)) { - tidcachelen++; - Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); - strncpy(tidcache[tidcachelen-1].name, name, 8); - tidcache[tidcachelen-1].name[8] = '\0'; -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); -#endif - tidcache[tidcachelen-1].hash = hash; - tidcache[tidcachelen-1].id = i; + AddTextureToCache(name, hash, i); return i; } diff --git a/src/r_defs.h b/src/r_defs.h index 37a06c03d..4b3121d75 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -15,6 +15,7 @@ #define __R_DEFS__ // Some more or less basic data types we depend on. +#include "hardware/hw_defs.h" #include "m_fixed.h" // We rely on the thinker data struct to handle sound origins in sectors. @@ -361,8 +362,6 @@ typedef struct sector_s INT32 crumblestate; // used for crumbling and bobbing - INT32 bottommap, midmap, topmap; // dynamic colormaps - // list of mobjs that are at least partially in the sector // thinglist is a subset of touching_thinglist struct msecnode_s *touching_thinglist; @@ -398,17 +397,6 @@ typedef struct sector_s // Eternity engine slope boolean hasslope; // The sector, or one of its visible FOFs, contains a slope - - // these are saved for netgames, so do not let Lua touch these! - INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed - - // offsets sector spawned with (via linedef type 7) - fixed_t spawn_flr_xoffs, spawn_flr_yoffs; - fixed_t spawn_ceil_xoffs, spawn_ceil_yoffs; - - // flag angles sector spawned with (via linedef type 7) - angle_t spawn_flrpic_angle; - angle_t spawn_ceilpic_angle; } sector_t; // @@ -432,6 +420,7 @@ typedef struct line_s vertex_t *v2; fixed_t dx, dy; // Precalculated v2 - v1 for side checking. + angle_t angle; // Precalculated angle between dx and dy // Animation related. INT16 flags; @@ -454,7 +443,7 @@ typedef struct line_s sector_t *backsector; size_t validcount; // if == validcount, already checked -#if 1//#ifdef WALLSPLATS +#ifdef WALLSPLATS void *splats; // wallsplat_t list #endif INT32 firsttag, nexttag; // improves searches for tags. @@ -501,7 +490,7 @@ typedef struct subsector_s INT16 numlines; UINT32 firstline; struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects -#if 1//#ifdef FLOORSPLATS +#ifdef FLOORSPLATS void *splats; // floorsplat_t list #endif size_t validcount; @@ -555,15 +544,14 @@ typedef struct seg_s sector_t *backsector; fixed_t length; // precalculated seg length + #ifdef HWRENDER // new pointers so that AdjustSegs doesn't mess with v1/v2 - void *pv1; // polyvertex_t - void *pv2; // polyvertex_t - float flength; // length of the seg, used by hardware renderer + polyvertex_t *pv1; + polyvertex_t *pv2; #endif polyobj_t *polyseg; - boolean dontrenderme; // Fake contrast calculated on level load SINT8 lightOffset; @@ -651,15 +639,6 @@ typedef struct drawseg_s vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes } drawseg_t; -typedef enum -{ - PALETTE = 0, // 1 byte is the index in the doom palette (as usual) - INTENSITY = 1, // 1 byte intensity - INTENSITY_ALPHA = 2, // 2 byte: alpha then intensity - RGB24 = 3, // 24 bit rgb - RGBA32 = 4, // 32 bit rgba -} pic_mode_t; - // rotsprite #ifdef ROTSPRITE typedef struct @@ -704,26 +683,6 @@ typedef struct // the [0] is &columnofs[width] } ATTRPACK softwarepatch_t; -#ifdef _MSC_VER -#pragma warning(disable : 4200) -#endif - -// a pic is an unmasked block of pixels, stored in horizontal way -typedef struct -{ - INT16 width; - UINT8 zero; // set to 0 allow autodetection of pic_t - // mode instead of patch or raw - UINT8 mode; // see pic_mode_t above - INT16 height; - INT16 reserved1; // set to 0 - UINT8 data[0]; -} ATTRPACK pic_t; - -#ifdef _MSC_VER -#pragma warning(default : 4200) -#endif - #if defined(_MSC_VER) #pragma pack() #endif diff --git a/src/r_draw.cpp b/src/r_draw.cpp index e399fab0e..7064424f3 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -29,6 +29,7 @@ #include "z_zone.h" #include "console.h" // Until buffering gets finished #include "k_kart.h" // SRB2kart +#include "i_threads.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -110,7 +111,25 @@ static UINT8 **localtranslationtablecache[MAXLOCALSKINS] = {NULL}; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; -static void R_GenerateBlendTables(void); +struct GenerateBlendTables_State +{ + RGBA_t *LocalPalette; +}; + +static void R_GenerateBlendTables_Core(struct GenerateBlendTables_State *state); +static void R_AllocateBlendTables(void); + +#ifdef HAVE_THREADS +static void R_GenerateBlendTables_Thread(void *userdata) +{ + struct GenerateBlendTables_State *state = static_cast(userdata); + + R_GenerateBlendTables_Core(state); + + free(state->LocalPalette); + free(state); +} +#endif /** \brief Initializes the translucency tables used by the Software renderer. */ @@ -131,6 +150,7 @@ void R_InitTranslucencyTables(void) W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); + R_AllocateBlendTables(); R_GenerateBlendTables(); } @@ -241,14 +261,36 @@ static void BlendTab_GenerateMaps(INT32 tab, INT32 style, void (*genfunc)(UINT8 } } -static void R_GenerateBlendTables(void) +static void R_AllocateBlendTables(void) { INT32 i; for (i = 0; i < NUMBLENDMAPS; i++) + { blendtables[i] = static_cast(Z_Malloc(BlendTab_Count[i] * 0x10000, PU_STATIC, NULL)); + } +} - InitColorLUT(&transtab_lut, pLocalPalette, false); +void R_GenerateBlendTables(void) +{ +#ifdef HAVE_THREADS + // Allocate copies for the worker thread since the originals can be freed in the main thread. + struct GenerateBlendTables_State *state = static_cast(malloc(sizeof *state)); + size_t palsize = 256 * sizeof(RGBA_t); + + state->LocalPalette = static_cast(memcpy(malloc(palsize), pLocalPalette, palsize)); + + I_spawn_thread("blend-tables", + R_GenerateBlendTables_Thread, state); +#else + struct GenerateBlendTables_State state = {pLocalPalette, pGammaCorrectedPalette}; + R_GenerateBlendTables_Core(&state); +#endif +} + +static void R_GenerateBlendTables_Core(struct GenerateBlendTables_State *state) +{ + InitColorLUT(&transtab_lut, state->LocalPalette, false); // Additive BlendTab_GenerateMaps(blendtab_add, AST_ADD, BlendTab_Translucent); diff --git a/src/r_draw.h b/src/r_draw.h index 763375709..bcd734e50 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -212,6 +212,7 @@ enum extern UINT8 *blendtables[NUMBLENDMAPS]; void R_InitTranslucencyTables(void); +void R_GenerateBlendTables(void); UINT8 *R_GetTranslucencyTable(INT32 alphalevel); UINT8 *R_GetBlendTable(int style, INT32 alphalevel); diff --git a/src/r_fps.c b/src/r_fps.cpp similarity index 83% rename from src/r_fps.c rename to src/r_fps.cpp index 6bd385066..d2665ac21 100644 --- a/src/r_fps.c +++ b/src/r_fps.cpp @@ -14,21 +14,25 @@ #include "r_fps.h" +#include + +#include "p_mobj.h" #include "r_main.h" #include "g_game.h" #include "k_kart.h" // saltyhop stuffs #include "i_video.h" #include "r_plane.h" -#include "p_spec.h" #include "r_state.h" #include "z_zone.h" -#include "console.h" // con_startup_loadprogress #include "i_time.h" #ifdef HWRENDER #include "hardware/hw_main.h" // for cv_grshearing #endif +// The fraction of a tic being drawn (for interpolation between two tics) +static fixed_t rendertimefrac; + static CV_PossibleValue_t fpscap_cons_t[] = { #ifdef DEVELOP // Lower values are actually pretty useful for debugging interp problems! @@ -47,8 +51,8 @@ consvar_t cv_fpscapbg = {"fpscapbackground", "Match refresh rate", CV_SAVE, fpsc consvar_t cv_precipinterp = {"precipinterpolation", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -ps_metric_t ps_interp_frac = {0}; -ps_metric_t ps_interp_lag = {0}; +ps_metric_t ps_interp_frac = {}; +ps_metric_t ps_interp_lag = {}; static boolean R_UseBackgroundFramerateCap(void) { @@ -106,6 +110,27 @@ boolean R_UsingFrameInterpolation(void) return (R_GetFramerateCap() != TICRATE || cv_timescale.value < FRACUNIT); } +// this wacky function exists now because rendertimefrac is stopped outside levels +// just for the sake of the intermission background... +fixed_t R_GetTimeFrac(timefrac_e level) +{ + // level interp. pauses if level isn't active + if ((level <= RTF_LEVEL || level == RTF_CAMERA) && gamestate != GS_LEVEL) // !G_GamestateUsesLevel() + return FRACUNIT; + + // intermission interp. pauses if game is paused + if (level <= RTF_INTER && (paused || P_AutoPause())) + return FRACUNIT; + + // menu interp. interpolates no matter what + return rendertimefrac; +} + +void R_SetTimeFrac(fixed_t frac) +{ + rendertimefrac = frac; +} + static viewvars_t pview_old[MAXSPLITSCREENPLAYERS]; static viewvars_t pview_new[MAXSPLITSCREENPLAYERS]; static viewvars_t skyview_old[MAXSPLITSCREENPLAYERS]; @@ -116,22 +141,9 @@ static tic_t last_view_update; static int oldview_invalid[MAXSPLITSCREENPLAYERS] = {0, 0, 0, 0}; viewvars_t *newview = &pview_new[0]; - enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1; -static levelinterpolator_t **levelinterpolators; -static size_t levelinterpolators_len; -static size_t levelinterpolators_size; - -static inline fixed_t R_LerpFixedView(fixed_t from, fixed_t to, fixed_t frac) -{ - return from + FixedMul(frac, to - from); -} - -static inline angle_t R_LerpAngleView(angle_t from, angle_t to, fixed_t frac) -{ - return from + FixedMul(frac, to - from); -} +static std::vector levelinterpolators; static inline fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac) { @@ -190,7 +202,7 @@ static void R_SetupFreelook(void) void R_InterpolateViewRollAngle(fixed_t frac) { - viewroll = R_LerpAngleView(oldview->roll, newview->roll, frac); + viewroll = R_LerpAngle(oldview->roll, newview->roll, frac); } void R_InterpolateView(fixed_t frac, boolean forceinvalid) @@ -208,13 +220,13 @@ void R_InterpolateView(fixed_t frac, boolean forceinvalid) prevview = newview; } - viewx = R_LerpFixedView(prevview->x, newview->x, frac); - viewy = R_LerpFixedView(prevview->y, newview->y, frac); - viewz = R_LerpFixedView(prevview->z, newview->z, frac); + viewx = R_LerpFixed(prevview->x, newview->x, frac); + viewy = R_LerpFixed(prevview->y, newview->y, frac); + viewz = R_LerpFixed(prevview->z, newview->z, frac); - viewangle = R_LerpAngleView(prevview->angle, newview->angle, frac); - aimingangle = R_LerpAngleView(prevview->aim, newview->aim, frac); - viewroll = R_LerpAngleView(prevview->roll, newview->roll, frac); + viewangle = R_LerpAngle(prevview->angle, newview->angle, frac); + aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac); + viewroll = R_LerpAngle(prevview->roll, newview->roll, frac); viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); @@ -301,22 +313,12 @@ void R_SetViewContext(enum viewcontext_e _viewcontext) /*fixed_t R_InterpolateFixed(fixed_t from, fixed_t to) { - if (!R_UsingFrameInterpolation()) - { - return to; - } - - return (R_LerpFixed(from, to, rendertimefrac)); + return R_LerpFixed(from, to, R_GetTimeFrac(RTF_LEVEL)); }*/ angle_t R_InterpolateAngle(angle_t from, angle_t to) { - if (!R_UsingFrameInterpolation()) - { - return to; - } - - return (R_LerpAngle(from, to, rendertimefrac)); + return R_LerpAngle(from, to, R_GetTimeFrac(RTF_LEVEL)); } void R_InterpolateMobjState(mobj_t *mobj, fixed_t frac, interpmobjstate_t *out) @@ -397,48 +399,22 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst //out->angle = R_LerpAngle(mobj->old_angle, mobj->angle, frac); } -static void AddInterpolator(levelinterpolator_t* interpolator) -{ - if (levelinterpolators_len >= levelinterpolators_size) - { - if (levelinterpolators_size == 0) - { - levelinterpolators_size = 128; - } - else - { - levelinterpolators_size *= 2; - } - - levelinterpolators = Z_Realloc( - (void*) levelinterpolators, - sizeof(levelinterpolator_t*) * levelinterpolators_size, - PU_LEVEL, - NULL - ); - } - - levelinterpolators[levelinterpolators_len] = interpolator; - levelinterpolators_len += 1; -} - static levelinterpolator_t *CreateInterpolator(levelinterpolator_type_e type, thinker_t *thinker) { - levelinterpolator_t *ret = (levelinterpolator_t*) Z_Calloc( - sizeof(levelinterpolator_t), PU_LEVEL, NULL - ); - - ret->type = type; - ret->thinker = thinker; - - AddInterpolator(ret); + if (rendermode == render_none) + return NULL; + auto* ret = &levelinterpolators.emplace_back(levelinterpolator_t{ type, thinker, {} }); return ret; } void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, boolean ceiling) { levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorPlane, thinker); + + if (interp == NULL) + return; + interp->sectorplane.sector = sector; interp->sectorplane.ceiling = ceiling; if (ceiling) @@ -454,6 +430,10 @@ void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, bool void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling) { levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SectorScroll, thinker); + + if (interp == NULL) + return; + interp->sectorscroll.sector = sector; interp->sectorscroll.ceiling = ceiling; if (ceiling) @@ -471,6 +451,10 @@ void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boo void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side) { levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_SideScroll, thinker); + + if (interp == NULL) + return; + interp->sidescroll.side = side; interp->sidescroll.oldtextureoffset = interp->sidescroll.baktextureoffset = side->textureoffset; interp->sidescroll.oldrowoffset = interp->sidescroll.bakrowoffset = side->rowoffset; @@ -479,11 +463,15 @@ void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side) void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj) { levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_Polyobj, thinker); + + if (interp == NULL) + return; + interp->polyobj.polyobj = polyobj; interp->polyobj.vertices_size = polyobj->numVertices; - interp->polyobj.oldvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL); - interp->polyobj.bakvertices = Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL); + interp->polyobj.oldvertices = static_cast(Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL)); + interp->polyobj.bakvertices = static_cast(Z_Calloc(sizeof(fixed_t) * 2 * polyobj->numVertices, PU_LEVEL, NULL)); for (size_t i = 0; i < polyobj->numVertices; i++) { interp->polyobj.oldvertices[i * 2 ] = interp->polyobj.bakvertices[i * 2 ] = polyobj->vertices[i]->x; @@ -498,6 +486,10 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj) /*void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope) { levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_DynSlope, thinker); + + if (interp == NULL) + return; + interp->dynslope.slope = slope; FV3_Copy(&interp->dynslope.oldo, &slope->o); @@ -511,9 +503,7 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj) void R_InitializeLevelInterpolators(void) { - levelinterpolators_len = 0; - levelinterpolators_size = 0; - levelinterpolators = NULL; + levelinterpolators.clear(); } static void RecalculatePolyobjectSegAngles(polyobj_t *polyobj) @@ -578,40 +568,32 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp) void R_UpdateLevelInterpolators(void) { - size_t i; - - for (i = 0; i < levelinterpolators_len; i++) + for (levelinterpolator_t& interp : levelinterpolators) { - levelinterpolator_t *interp = levelinterpolators[i]; - - UpdateLevelInterpolatorState(interp); + UpdateLevelInterpolatorState(&interp); } } void R_ClearLevelInterpolatorState(thinker_t *thinker) { - size_t i; - - for (i = 0; i < levelinterpolators_len; i++) + for (levelinterpolator_t& interp : levelinterpolators) { - levelinterpolator_t *interp = levelinterpolators[i]; - - if (interp->thinker == thinker) + if (interp.thinker == thinker) { // Do it twice to make the old state match the new - UpdateLevelInterpolatorState(interp); - UpdateLevelInterpolatorState(interp); + UpdateLevelInterpolatorState(&interp); + UpdateLevelInterpolatorState(&interp); } } } void R_ApplyLevelInterpolators(fixed_t frac) { - size_t i, ii; + size_t ii; - for (i = 0; i < levelinterpolators_len; i++) + for (levelinterpolator_t& i : levelinterpolators) { - levelinterpolator_t *interp = levelinterpolators[i]; + levelinterpolator_t* interp = &i; switch (interp->type) { @@ -661,11 +643,11 @@ void R_ApplyLevelInterpolators(fixed_t frac) void R_RestoreLevelInterpolators(void) { - size_t i, ii; + size_t ii; - for (i = 0; i < levelinterpolators_len; i++) + for (levelinterpolator_t& i : levelinterpolators) { - levelinterpolator_t *interp = levelinterpolators[i]; + levelinterpolator_t* interp = &i; switch (interp->type) { @@ -721,51 +703,30 @@ void R_DestroyLevelInterpolators(thinker_t *thinker) { size_t i; - for (i = 0; i < levelinterpolators_len; i++) + for (i = 0; i < levelinterpolators.size(); i++) { - levelinterpolator_t *interp = levelinterpolators[i]; + levelinterpolator_t* interp = &levelinterpolators[i]; if (interp->thinker == thinker) { // Swap the tail of the level interpolators to this spot - levelinterpolators[i] = levelinterpolators[levelinterpolators_len - 1]; - levelinterpolators_len -= 1; + levelinterpolators[i] = *levelinterpolators.rbegin(); - Z_Free(interp); - i -= 1; + levelinterpolators.pop_back(); } } } -static mobj_t **interpolated_mobjs = NULL; -static size_t interpolated_mobjs_len = 0; -static size_t interpolated_mobjs_capacity = 0; +static std::vector interpolated_mobjs; // NOTE: This will NOT check that the mobj has already been added, for perf // reasons. void R_AddMobjInterpolator(mobj_t *mobj) { - if (interpolated_mobjs_len >= interpolated_mobjs_capacity) - { - if (interpolated_mobjs_capacity == 0) - { - interpolated_mobjs_capacity = 256; - } - else - { - interpolated_mobjs_capacity *= 2; - } + if (rendermode == render_none) + return; - interpolated_mobjs = Z_Realloc( - interpolated_mobjs, - sizeof(mobj_t *) * interpolated_mobjs_capacity, - PU_LEVEL, - NULL - ); - } - - interpolated_mobjs[interpolated_mobjs_len] = mobj; - interpolated_mobjs_len += 1; + interpolated_mobjs.push_back(mobj); R_ResetMobjInterpolationState(mobj); mobj->resetinterp = true; @@ -773,18 +734,12 @@ void R_AddMobjInterpolator(mobj_t *mobj) void R_RemoveMobjInterpolator(mobj_t *mobj) { - size_t i; - - if (interpolated_mobjs_len == 0) return; - - for (i = 0; i < interpolated_mobjs_len; i++) + for (size_t i = 0; i < interpolated_mobjs.size(); i++) { if (interpolated_mobjs[i] == mobj) { - interpolated_mobjs[i] = interpolated_mobjs[ - interpolated_mobjs_len - 1 - ]; - interpolated_mobjs_len -= 1; + interpolated_mobjs[i] = *interpolated_mobjs.rbegin(); + interpolated_mobjs.pop_back(); return; } } @@ -792,19 +747,13 @@ void R_RemoveMobjInterpolator(mobj_t *mobj) void R_InitMobjInterpolators(void) { - // apparently it's not acceptable to free something already unallocated - // Z_Free(interpolated_mobjs); - interpolated_mobjs = NULL; - interpolated_mobjs_len = 0; - interpolated_mobjs_capacity = 0; + interpolated_mobjs.clear(); } void R_UpdateMobjInterpolators(void) { - size_t i; - for (i = 0; i < interpolated_mobjs_len; i++) + for (mobj_t* mobj : interpolated_mobjs) { - mobj_t *mobj = interpolated_mobjs[i]; if (!P_MobjWasRemoved(mobj)) R_ResetMobjInterpolationState(mobj); } @@ -817,6 +766,9 @@ void R_UpdateMobjInterpolators(void) // void R_ResetMobjInterpolationState(mobj_t *mobj) { + if (rendermode == render_none) + return; + mobj->old_x2 = mobj->old_x; mobj->old_y2 = mobj->old_y; mobj->old_z2 = mobj->old_z; @@ -883,16 +835,7 @@ void R_ResetMobjInterpolationState(mobj_t *mobj) // void R_ResetPrecipitationMobjInterpolationState(precipmobj_t *mobj) { - mobj->old_x2 = mobj->old_x; - mobj->old_y2 = mobj->old_y; - mobj->old_z2 = mobj->old_z; - mobj->old_angle2 = mobj->old_angle; mobj->old_x = mobj->x; mobj->old_y = mobj->y; mobj->old_z = mobj->z; - mobj->old_angle = mobj->angle; - mobj->old_spritexscale = mobj->spritexscale; - mobj->old_spriteyscale = mobj->spriteyscale; - mobj->old_spritexoffset = mobj->spritexoffset; - mobj->old_spriteyoffset = mobj->spriteyoffset; } diff --git a/src/r_fps.h b/src/r_fps.h index cbcde0db8..64903a5b5 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -22,6 +22,7 @@ extern "C" { #include "m_fixed.h" #include "p_local.h" #include "r_state.h" +#include "r_things.h" #include "m_perfstats.h" extern consvar_t cv_fpscap, cv_fpscapbg; @@ -30,9 +31,30 @@ extern consvar_t cv_precipinterp; extern ps_metric_t ps_interp_frac; extern ps_metric_t ps_interp_lag; -UINT32 R_GetFramerateCap(void); +typedef enum +{ + RTF_LEVEL, + RTF_INTER, + RTF_CAMERA, + RTF_MENU, +} timefrac_e; + boolean R_UsingFrameInterpolation(void); +UINT32 R_GetFramerateCap(void); +fixed_t R_GetTimeFrac(timefrac_e level); +void R_SetTimeFrac(fixed_t frac); + +static inline fixed_t R_GetMobjTimeFrac(mobj_t *mo) +{ + return R_CheckMobjInterpDist(mo) ? R_GetTimeFrac(RTF_LEVEL) : FRACUNIT; +} + +static inline fixed_t R_GetPrecipMobjTimeFrac(precipmobj_t *mo) +{ + return R_CheckPrecipMobjInterpDist(mo) ? R_GetTimeFrac(RTF_LEVEL) : FRACUNIT; +} + enum viewcontext_e { VIEWCONTEXT_PLAYER1 = 0, diff --git a/src/r_main.cpp b/src/r_main.cpp index 4e0b59126..00fdf4204 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -70,8 +70,6 @@ boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisibl sector_t *viewsector; player_t *viewplayer; -fixed_t rendertimefrac; -fixed_t rendertimefrac_unpaused; fixed_t renderdeltatics; boolean renderisnewtic; @@ -414,16 +412,6 @@ angle_t R_PlayerSliptideAngle(player_t *player) return FixedMul(FINECOSINE((ang) >> ANGLETOFINESHIFT), mo->player->sliproll * mo->player->kartstuff[k_aizdriftstrat]); } -INT32 R_GetHudUncap(void) -{ - return cv_uncappedhud.value ? rendertimefrac & FRACMASK : 0; -} - -INT32 R_GetMenuUncap(void) -{ - return cv_uncappedhud.value ? rendertimefrac_unpaused & FRACMASK : 0; -} - // // R_ScaleFromGlobalAngle // Returns the texture mapping scale for the current line (horizontal span) @@ -800,13 +788,13 @@ void R_CheckViewMorph(void) void R_ApplyViewMorph(void) { + if (!viewmorph.use) + return; + UINT8 *tmpscr = vid.screens[4]; UINT8 *srcscr = vid.screens[0]; INT32 p, end = vid.width * vid.height; - if (!viewmorph.use) - return; - if (cv_debug & DBG_VIEWMORPH) { UINT8 border = 32; @@ -1045,7 +1033,7 @@ void R_Init(void) R_InitLightTables(); //I_OutputMsg("\nR_InitTranslucencyTables\n"); - R_InitTranslucencyTables(); + //R_InitTranslucencyTables(); R_InitDrawNodes(); @@ -1100,7 +1088,7 @@ static void R_SetupCommonFrame(player_t * player, sector_t * sector) else newview->sector = R_PointInSubsectorFast(newview->x, newview->y)->sector; - R_InterpolateView(rendertimefrac_unpaused, false); + R_InterpolateView(R_GetTimeFrac(RTF_CAMERA), false); } static void R_SetupAimingFrame(player_t *player, camera_t *thiscam) @@ -1608,10 +1596,6 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_ripplewater); - // Default viewheight is changeable, - // initialized to standard viewheight - //CV_RegisterVar(&cv_viewheight); - // Frame interpolation/uncapped CV_RegisterVar(&cv_fpscap); CV_RegisterVar(&cv_fpscapbg); diff --git a/src/r_main.h b/src/r_main.h index 3f815d083..af77a4ecd 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -38,10 +38,6 @@ extern fixed_t fovtan; // field of view extern size_t validcount, linecount, loopcount, framecount; -// The fraction of a tic being drawn (for interpolation between two tics) -extern fixed_t rendertimefrac; -// Same as rendertimefrac but not suspended when the game is paused -extern fixed_t rendertimefrac_unpaused; // Evaluated delta tics for this frame (how many tics since the last frame) extern fixed_t renderdeltatics; // The current render is a new logical tic @@ -230,11 +226,6 @@ void R_RenderPlayerView(player_t *player); // add commands related to engine, at game startup void R_RegisterEngineStuff(void); -// return multiplier for HUD uncap -INT32 R_GetHudUncap(void); -// same as above but keeps interpolation during pause -INT32 R_GetMenuUncap(void); - #ifdef __cplusplus } // extern "C" #endif diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 94fbcae4b..0ccf1cc48 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -165,7 +165,7 @@ static void R_CalculatePlaneRipple(drawspandata_t* ds, angle_t angle) static void R_UpdatePlaneRipple(drawspandata_t* ds) { ds->waterofs = (leveltime & 1)*16384; - ds->planeripple.offset = ((leveltime-1)*140) + ((rendertimefrac*140) / FRACUNIT); + ds->planeripple.offset = ((leveltime-1)*140) + ((R_GetTimeFrac(RTF_LEVEL)*140) / FRACUNIT); } static bool R_CheckMapPlane(const char* funcname, INT32 y, INT32 x1, INT32 x2) diff --git a/src/r_segs.cpp b/src/r_segs.cpp index e6e9dfb1f..d8cef4129 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2211,6 +2211,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) for (r2 = frontsector->ffloors; r2; r2 = r2->next) { + if (r2->master == rover->master) // Skip if same control line. + break; + if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) continue; @@ -2267,6 +2270,9 @@ void R_StoreWallRange(INT32 start, INT32 stop) for (r2 = backsector->ffloors; r2; r2 = r2->next) { + if (r2->master == rover->master) // Skip if same control line. + break; + if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)) continue; diff --git a/src/r_skins.c b/src/r_skins.c index 6bda9e263..c19e34a74 100644 --- a/src/r_skins.c +++ b/src/r_skins.c @@ -230,7 +230,7 @@ boolean SetPlayerSkin(INT32 playernum, const char *skinname) if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); SetPlayerSkinByNum(playernum, 0); @@ -335,7 +335,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (P_IsLocalPlayer(player)) CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) + else if (server || IsPlayerAdmin(consoleplayer)) CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin @@ -684,7 +684,7 @@ next_token: // skip to end of this skin's frames lastlump = lump; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) + while (W_CheckNameForNumPwad(wadnum, lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump), csprname,4)==0) lastlump++; // allocate (or replace) sprite frames, and set spritedef R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump); @@ -711,10 +711,10 @@ next_token: UINT16 localllump = 0, lstart = UINT16_MAX, lend = UINT16_MAX; const char *lname; - while ((lname = W_CheckNameForNumPwad(wadnum,localllump))) + while ((lname = W_CheckNameForNumPwad(wadnum, localllump))) { // If this is a valid sprite... - if (!memcmp(lname,sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') + if (!memcmp(lname, sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') { if (lstart == UINT16_MAX) lstart = localllump; diff --git a/src/r_things.cpp b/src/r_things.cpp index 9ece0d515..1164072db 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1148,6 +1148,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) *shadowslope = groundslope; return groundz; + #undef CHECKZ } @@ -1241,14 +1242,7 @@ static void R_ProjectSprite(mobj_t *thing) interpmobjstate_t interp = {}; // do interpolation - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist(oldthing)) - { - R_InterpolateMobjState(oldthing, rendertimefrac, &interp); - } - else - { - R_InterpolateMobjState(oldthing, FRACUNIT, &interp); - } + R_InterpolateMobjState(oldthing, R_GetMobjTimeFrac(oldthing), &interp); this_scale = interp.scale; @@ -1268,7 +1262,7 @@ static void R_ProjectSprite(mobj_t *thing) tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (!papersprite && abs(tx) > (INT64)FixedMul(tz, fovtan)<<2) // papersprite clipping is handled later + if (!papersprite && abs(tx) > (INT64)FixedMul(tz, fovtan) << 2) // papersprite clipping is handled later return; // aspect ratio stuff @@ -1832,7 +1826,7 @@ static void R_ProjectSprite(mobj_t *thing) #endif vis->patch = static_cast(W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE)); - vis->precip = false; + vis->precip = NULL; vis->vflip = vflip; @@ -1879,14 +1873,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) interpmobjstate_t interp = {}; // do interpolation - if (R_UsingFrameInterpolation() && !paused && R_CheckInterpDist((mobj_t*)thing)) - { - R_InterpolatePrecipMobjState(thing, rendertimefrac, &interp); - } - else - { - R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp); - } + R_InterpolatePrecipMobjState(thing, R_GetPrecipMobjTimeFrac(thing), &interp); this_scale = interp.scale; @@ -2015,7 +2002,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->patch = static_cast(W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE)); // specific translucency - if ((thing->blendmode != AST_COPY) && cv_translucency.value) + if (thing->frame & FF_TRANSMASK) vis->transmap = R_GetTranslucencyTable((thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT); else vis->transmap = NULL; @@ -2027,7 +2014,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // Fullbright vis->colormap = colormaps; - vis->precip = true; + vis->precip = thing; vis->vflip = false; vis->isScaled = false; } @@ -2967,16 +2954,30 @@ fixed_t R_DoPlayerFade(mobj_t *thing) return fadealpha; } -boolean R_CheckInterpDist(mobj_t *thing) +template +static boolean R_CheckInterpDist(T *thing) { if (!cv_maxinterpdist.value) return true; + if (!R_UsingFrameInterpolation()) + return false; + const INT32 dist = R_QuickCamDist(thing->x, thing->y); return (dist < cv_maxinterpdist.value); } +boolean R_CheckPrecipMobjInterpDist(precipmobj_t *thing) +{ + return R_CheckInterpDist(thing); +} + +boolean R_CheckMobjInterpDist(mobj_t *thing) +{ + return R_CheckInterpDist(thing); +} + boolean R_ThingIsFullBright(mobj_t *thing) { return ((thing->frame & FF_BRIGHTMASK) == FF_FULLBRIGHT); diff --git a/src/r_things.h b/src/r_things.h index 5eb383e93..9cba7340d 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -42,8 +42,10 @@ extern "C" { #ifdef __cplusplus #define R_QuickCamDist(x, y) std::max(std::abs(((x)>>FRACBITS) - (viewx>>FRACBITS)), std::abs(((y)>>FRACBITS) - (viewy>>FRACBITS))) +#define R_QuickDist(x1, y1, x, y) std::max(std::abs(((x)>>FRACBITS) - (x1>>FRACBITS)), std::abs(((y)>>FRACBITS) - (y1>>FRACBITS))) #else #define R_QuickCamDist(x, y) max(abs(((x)>>FRACBITS) - (viewx>>FRACBITS)), abs(((y)>>FRACBITS) - (viewy>>FRACBITS))) +#define R_QuickDist(x1, y1, x, y) max(abs(((x)>>FRACBITS) - (x1>>FRACBITS)), abs(((y)>>FRACBITS) - (y1>>FRACBITS))) #endif // Constant arrays used for psprite clipping @@ -91,7 +93,8 @@ transnum_t R_GetThingTransTable(fixed_t alpha, transnum_t transmap); boolean R_ThingVisible(mobj_t *thing); boolean R_ThingWithinDist(mobj_t *thing, INT32 limit_dist); -boolean R_CheckInterpDist(mobj_t *thing); +boolean R_CheckPrecipMobjInterpDist(precipmobj_t *thing); +boolean R_CheckMobjInterpDist(mobj_t *thing); fixed_t R_DoPlayerFade(mobj_t *thing); boolean R_ThingIsFullBright(mobj_t *thing); @@ -168,7 +171,8 @@ typedef struct vissprite_s INT16 *clipbot, *cliptop; - boolean precip; + precipmobj_t *precip; + boolean vflip; // Flip vertically boolean isScaled; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing diff --git a/src/screen.h b/src/screen.h index 42bc6c144..7cde5a6dc 100644 --- a/src/screen.h +++ b/src/screen.h @@ -95,8 +95,6 @@ extern consvar_t cv_highreshudscale; extern consvar_t cv_vidwait; extern consvar_t cv_timescale; -extern consvar_t cv_alwaysgrabmouse; - extern consvar_t cv_votebgscaling; void R_SetColumnFunc(size_t id); diff --git a/src/sdl/Sourcefile b/src/sdl/Sourcefile index 82d5ce073..f919a1334 100644 --- a/src/sdl/Sourcefile +++ b/src/sdl/Sourcefile @@ -1,5 +1,5 @@ i_net.c -i_system.c +i_system.cpp i_main.c i_video.c dosstr.c diff --git a/src/sdl/i_system.cpp b/src/sdl/i_system.cpp index e2c7801f2..3dc47a28e 100644 --- a/src/sdl/i_system.cpp +++ b/src/sdl/i_system.cpp @@ -149,16 +149,32 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif -// Locations for searching the srb2.srb +// Locations to directly check for srb2.pk3 in +const char *wadDefaultPaths[] = { #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#define DEFAULTWADLOCATION1 "/usr/local/share/games/SRB2Kart" -#define DEFAULTWADLOCATION2 "/usr/local/games/SRB2Kart" -#define DEFAULTWADLOCATION3 "/usr/share/games/SRB2Kart" -#define DEFAULTWADLOCATION4 "/usr/games/SRB2Kart" -#define DEFAULTSEARCHPATH1 "/usr/local/games" -#define DEFAULTSEARCHPATH2 "/usr/games" -#define DEFAULTSEARCHPATH3 "/usr/local" + "/usr/local/share/games/SRB2Kart", + "/usr/local/games/SRB2Kart", + "/usr/share/games/SRB2Kart", + "/usr/games/SRB2Kart", +#elif defined (_WIN32) + "c:\\games\\srb2kart", + "\\games\\srb2kart", #endif + NULL +}; + +// Folders to recurse through looking for srb2.pk3 +const char *wadSearchPaths[] = { +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + "/usr/local/games", + "/usr/games", + "/usr/local", +#elif defined (_WIN32) + "c:\\games", + "\\games", +#endif + NULL +}; /** \brief WAD file to look for */ @@ -506,6 +522,8 @@ static void I_ReportSignal(int num, int coredumped) #ifndef NEWSIGNALHANDLER FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { + g_in_exiting_signal_handler = true; + #ifdef HAVE_THREADS if (g_main_thread_id != std::this_thread::get_id()) { @@ -516,8 +534,6 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) } #endif - g_in_exiting_signal_handler = true; - D_QuitNetGame(); // Fix server freezes #ifdef HAVE_LIBBACKTRACE @@ -1647,7 +1663,7 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) { UINT8 *p = mumble->context; WRITEMEM(p, server_context, 8); - WRITEINT16_2(p, gamemap); + WRITEINT16(p, gamemap); mumble->context_len = (UINT32)(p - mumble->context); } @@ -1685,42 +1701,6 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) #undef WINMUMBLE #endif // NOMUMBLE -/** \brief empty ticcmd for player 1 -*/ -static ticcmd_t emptycmd; - -ticcmd_t *I_BaseTiccmd(void) -{ - return &emptycmd; -} - -/** \brief empty ticcmd for player 2 -*/ -static ticcmd_t emptycmd2; - -ticcmd_t *I_BaseTiccmd2(void) -{ - return &emptycmd2; -} - -/** \brief empty ticcmd for player 3 -*/ -static ticcmd_t emptycmd3; - -ticcmd_t *I_BaseTiccmd3(void) -{ - return &emptycmd3; -} - -/** \brief empty ticcmd for player 4 -*/ -static ticcmd_t emptycmd4; - -ticcmd_t *I_BaseTiccmd4(void) -{ - return &emptycmd4; -} - // // I_GetTime // returns time in 1/TICRATE second tics @@ -1960,6 +1940,11 @@ INT32 I_StartupSystem(void) SDLcompiled.major, SDLcompiled.minor, SDLcompiled.patch); I_OutputMsg("Linked with SDL version: %d.%d.%d\n", SDLlinked.major, SDLlinked.minor, SDLlinked.patch); + +#if (SDL_VERSION_ATLEAST(2, 0, 18)) + SDL_SetHint(SDL_HINT_APP_NAME, "SRB2Kart Saturn"); +#endif + if (SDL_Init(0) < 0) I_Error("SRB2: SDL System Error: %s", SDL_GetError()); //Alam: Oh no.... #ifndef NOMUMBLE @@ -1977,7 +1962,7 @@ void I_Quit(void) /* prevent recursive I_Quit() */ if (quiting) goto death; - SDLforceUngrabMouse(); + SDL_ShowCursor(SDL_TRUE); quiting = SDL_FALSE; I_ShutdownConsole(); M_SaveConfig(NULL); //save game config, cvars.. @@ -2056,8 +2041,6 @@ void I_Error(const char *error, ...) if (shutdowning) { errorcount++; - if (errorcount == 1) - SDLforceUngrabMouse(); // try to shutdown each subsystem separately if (errorcount == 2) I_ShutdownMusic(); @@ -2447,14 +2430,6 @@ static boolean isWadPathOk(const char *path) return true; } - sprintf(wad3path, pandf, path, WADKEYWORD2); - - if (FIL_ReadFileOK(wad3path)) - { - free(wad3path); - return true; - } - free(wad3path); return false; } @@ -2493,24 +2468,32 @@ static const char *searchWad(const char *searchDir) return tempsw; } - strcpy(tempsw, WADKEYWORD2); - fstemp = filesearch(tempsw, searchDir, NULL, true, 20); - if (fstemp == FS_FOUND) - { - pathonly(tempsw); - return tempsw; - } return NULL; } -/** \brief go through all possible paths and look for srb2.srb +#define CHECKWADPATH(ret) \ +do { \ + I_OutputMsg(",%s", ret); \ + if (isWadPathOk(ret)) \ + return ret; \ +} while (0) - \return path to srb2.srb if any +#define SEARCHWAD(str) \ +do { \ + WadPath = searchWad(str); \ + if (WadPath) \ + return WadPath; \ +} while (0) + +/** \brief go through all possible paths and look for srb2.pk3 + + \return path to srb2.pk3 if any */ static const char *locateWad(void) { const char *envstr; const char *WadPath; + int i; I_OutputMsg("SRB2WADDIR"); // does SRB2WADDIR exist? @@ -2518,89 +2501,25 @@ static const char *locateWad(void) return envstr; #ifndef NOCWD - I_OutputMsg(",."); // examine current dir strcpy(returnWadPath, "."); + I_OutputMsg(",%s", returnWadPath); if (isWadPathOk(returnWadPath)) return NULL; #endif - -#ifdef DEFAULTDIR - I_OutputMsg(",HOME/" DEFAULTDIR); - // examine user jart directory - if ((envstr = I_GetEnv("HOME")) != NULL) - { - sprintf(returnWadPath, "%s" PATHSEP DEFAULTDIR, envstr); - if (isWadPathOk(returnWadPath)) - return returnWadPath; - } -#endif - - -#ifdef CMAKECONFIG -#ifndef NDEBUG - I_OutputMsg(","CMAKE_ASSETS_DIR); - strcpy(returnWadPath, CMAKE_ASSETS_DIR); - if (isWadPathOk(returnWadPath)) - { - return returnWadPath; - } -#endif -#endif - #ifdef __APPLE__ OSX_GetResourcesPath(returnWadPath); - I_OutputMsg(",%s", returnWadPath); - if (isWadPathOk(returnWadPath)) - { - return returnWadPath; - } + CHECKWADPATH(returnWadPath); #endif // examine default dirs -#ifdef DEFAULTWADLOCATION1 - I_OutputMsg("," DEFAULTWADLOCATION1); - strcpy(returnWadPath, DEFAULTWADLOCATION1); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION2 - I_OutputMsg("," DEFAULTWADLOCATION2); - strcpy(returnWadPath, DEFAULTWADLOCATION2); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION3 - I_OutputMsg("," DEFAULTWADLOCATION3); - strcpy(returnWadPath, DEFAULTWADLOCATION3); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION4 - I_OutputMsg("," DEFAULTWADLOCATION4); - strcpy(returnWadPath, DEFAULTWADLOCATION4); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION5 - I_OutputMsg("," DEFAULTWADLOCATION5); - strcpy(returnWadPath, DEFAULTWADLOCATION5); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION6 - I_OutputMsg("," DEFAULTWADLOCATION6); - strcpy(returnWadPath, DEFAULTWADLOCATION6); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif -#ifdef DEFAULTWADLOCATION7 - I_OutputMsg("," DEFAULTWADLOCATION7); - strcpy(returnWadPath, DEFAULTWADLOCATION7); - if (isWadPathOk(returnWadPath)) - return returnWadPath; -#endif + for (i = 0; wadDefaultPaths[i]; i++) + { + strcpy(returnWadPath, wadDefaultPaths[i]); + CHECKWADPATH(returnWadPath); + } + #ifndef NOHOME // find in $HOME I_OutputMsg(",HOME/" DEFAULTDIR); @@ -2610,33 +2529,18 @@ static const char *locateWad(void) strcpy(tmp, envstr); strcat(tmp, PATHSEP); strcat(tmp, DEFAULTDIR); - WadPath = searchWad(tmp); + CHECKWADPATH(tmp); free(tmp); - if (WadPath) - return WadPath; } #endif -#ifdef DEFAULTSEARCHPATH1 - // find in /usr/local - I_OutputMsg(", in:" DEFAULTSEARCHPATH1); - WadPath = searchWad(DEFAULTSEARCHPATH1); - if (WadPath) - return WadPath; -#endif -#ifdef DEFAULTSEARCHPATH2 - // find in /usr/games - I_OutputMsg(", in:" DEFAULTSEARCHPATH2); - WadPath = searchWad(DEFAULTSEARCHPATH2); - if (WadPath) - return WadPath; -#endif -#ifdef DEFAULTSEARCHPATH3 - // find in ??? - I_OutputMsg(", in:" DEFAULTSEARCHPATH3); - WadPath = searchWad(DEFAULTSEARCHPATH3); - if (WadPath) - return WadPath; -#endif + + // search paths + for (i = 0; wadSearchPaths[i]; i++) + { + I_OutputMsg(", in:%s", wadSearchPaths[i]); + SEARCHWAD(wadSearchPaths[i]); + } + // if nothing was found return NULL; } @@ -2653,8 +2557,10 @@ const char *I_LocateWad(void) { // change to the directory where we found srb2.srb #if defined (_WIN32) + waddir = _fullpath(NULL, waddir, MAX_PATH); SetCurrentDirectoryA(waddir); #else + waddir = realpath(waddir, NULL); if (chdir(waddir) == -1) I_OutputMsg("Couldn't change working directory\n"); #endif diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 389e086e2..159b49d7a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -115,6 +115,8 @@ boolean a2c = false; static void KeyboardLayout_OnChange(void) { + if (cv_keyboardlayout.value != 2) + SDL_StopTextInput(); HU_Shiftform(); } @@ -136,9 +138,6 @@ static void I_CheckDesktopRes(void); consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, Impl_SetVsync, 0, NULL, NULL, 0, 0, NULL}; static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static void mousegrabOnChange(void); -consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE|CV_CALL, CV_OnOff, mousegrabOnChange, 0, NULL, NULL, 0, 0, NULL}; - // these cant be used since config is read after window creation, so need to use command line parameter instead //static CV_PossibleValue_t msaa_cons_t[] = {{0, "Off"}, {2, "2X"}, {4, "4X"}, {8, "8X"}, {16, "16X"}, {0, NULL}}; //consvar_t cv_msaa = {"msaa", "Off", CV_SAVE, msaa_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -165,8 +164,6 @@ static SDL_Surface *icoSurface = NULL; static UINT32 localPalette[256]; Uint16 realwidth = BASEVIDWIDTH; Uint16 realheight = BASEVIDHEIGHT; -static SDL_bool mousegrabok = SDL_TRUE; -static SDL_bool wrapmouseok = SDL_FALSE; #define HalfWarpMouse(x,y) if (wrapmouseok) SDL_WarpMouseInWindow(window, (Uint16)(x/2),(Uint16)(y/2)) static SDL_bool exposevideo = SDL_FALSE; static SDL_bool usesdl2soft = SDL_FALSE; @@ -214,9 +211,6 @@ static void Impl_VideoSetupBuffer(void); static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); static void Impl_SetWindowIcon(void); -static void SDLdoGrabMouse(void); -static void SDLdoUngrabMouse(void); - #ifdef USE_FBO_OGL boolean downsample = false; void RefreshOGLSDLSurface(void) @@ -226,21 +220,21 @@ void RefreshOGLSDLSurface(void) } #endif -static void mousegrabOnChange(void) +void I_SetTextInput(void) { - static SDL_bool firsttimeonmouse = SDL_TRUE; + static boolean input_active = false; + boolean use_native = I_UseNativeKeyboard(); - if (!firsttimeonmouse) + if (use_native && !input_active) { - HalfWarpMouse(realwidth, realheight); // warp to center + SDL_StartTextInput(); + input_active = true; + } + else if (!use_native && input_active) + { + SDL_StopTextInput(); + input_active = false; } - else - firsttimeonmouse = SDL_FALSE; - - if (cv_usemouse.value || cv_alwaysgrabmouse.value) - SDLdoGrabMouse(); - else - SDLdoUngrabMouse(); } static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) @@ -357,7 +351,9 @@ static INT32 GetTypedChar(SDL_Keysym keysym) if (SDL_PeepEvents(&next_event, 1, SDL_PEEKEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) == 1 && next_event.type == SDL_TEXTINPUT) { if (next_event.text.text[1] == '\0') // limit to ASCII + { return next_event.text.text[0]; + } } } @@ -442,34 +438,6 @@ static INT32 Impl_SDL_Keysym_To_Keycode(SDL_Keysym keysym) return Impl_SDL_Scancode_To_Keycode(scancode); } -static void SDLdoGrabMouse(void) -{ - SDL_ShowCursor(SDL_DISABLE); - SDL_SetWindowGrab(window, SDL_TRUE); - - if (SDL_SetRelativeMouseMode(SDL_TRUE) == 0) // already warps mouse if successful - wrapmouseok = SDL_TRUE; // TODO: is wrapmouseok or HalfWarpMouse needed anymore? -} - -static void SDLdoUngrabMouse(void) -{ - SDL_ShowCursor(SDL_ENABLE); - SDL_SetWindowGrab(window, SDL_FALSE); - wrapmouseok = SDL_FALSE; - SDL_SetRelativeMouseMode(SDL_FALSE); -} - -void SDLforceUngrabMouse(void) -{ - if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO && window != NULL) - { - SDL_ShowCursor(SDL_ENABLE); - SDL_SetWindowGrab(window, SDL_FALSE); - wrapmouseok = SDL_FALSE; - SDL_SetRelativeMouseMode(SDL_FALSE); - } -} - static void VID_Command_NumModes_f (void) { CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes()); @@ -571,7 +539,7 @@ static void I_CheckDesktopRes(void) return; } - if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &curmode) != 0) + if (SDL_GetDesktopDisplayMode(currentDisplayIndex, &curmode) != 0) { return; } @@ -645,10 +613,12 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) case SDL_WINDOWEVENT_FOCUS_GAINED: kbfocus = SDL_TRUE; mousefocus = SDL_TRUE; + SDL_ShowCursor(SDL_FALSE); break; case SDL_WINDOWEVENT_FOCUS_LOST: kbfocus = SDL_FALSE; mousefocus = SDL_FALSE; + SDL_ShowCursor(SDL_TRUE); break; case SDL_WINDOWEVENT_MAXIMIZED: break; @@ -695,17 +665,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (!cv_playsoundifunfocused.value) S_StopSounds(); - if (!disable_mouse) - { - SDLforceUngrabMouse(); - } - memset(gamekeydown, 0, NUMKEYS); // TODO this is a scary memset - - if (MOUSE_MENU) - { - SDLdoUngrabMouse(); - } } #undef FOCUSUNION } @@ -745,58 +705,48 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) { - if (USE_MOUSEINPUT) + if (!USE_MOUSEINPUT) + return; + + const boolean windowinfocus = (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window); + + if (!windowinfocus) { - const boolean windowinfocus = (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window); + SDL_ShowCursor(SDL_ENABLE); + SDL_SetWindowGrab(window, SDL_FALSE); + SDL_SetRelativeMouseMode(SDL_FALSE); + return; + } - if (!windowinfocus) - { - SDLdoUngrabMouse(); - return; - } - - // If using relative mouse mode, don't post an event_t just now, - // add on the offsets so we can make an overall event later. - if (SDL_GetRelativeMouseMode()) - { - if (windowinfocus) - { - mousemovex += evt.xrel; - mousemovey += -evt.yrel; - SDL_SetWindowGrab(window, SDL_TRUE); - } - return; - } - - // If the event is from warping the pointer to middle - // of the screen then ignore it. - if ((evt.x == realwidth/2) && (evt.y == realheight/2)) - { - return; - } - - // Don't send an event_t if not in relative mouse mode anymore, - // just grab and set relative mode - // this fixes the stupid camera jerk on mouse entering bug - // -- Monster Iestyn + // If using relative mouse mode, don't post an event_t just now, + // add on the offsets so we can make an overall event later. + if (SDL_GetRelativeMouseMode()) + { if (windowinfocus) { - SDLdoGrabMouse(); + mousemovex += evt.xrel; + mousemovey += -evt.yrel; + SDL_SetWindowGrab(window, SDL_TRUE); } + return; } - else if (cv_alwaysgrabmouse.value) - { - const boolean windowinfocus = (SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window); - if (!windowinfocus) - { - SDLdoUngrabMouse(); - return; - } - else if (windowinfocus) - { - SDLdoGrabMouse(); - } + // If the event is from warping the pointer to middle + // of the screen then ignore it. + if ((evt.x == realwidth/2) && (evt.y == realheight/2)) + { + return; + } + + // Don't send an event_t if not in relative mouse mode anymore, + // just grab and set relative mode + // this fixes the stupid camera jerk on mouse entering bug + // -- Monster Iestyn + if (windowinfocus) + { + SDL_ShowCursor(SDL_DISABLE); + SDL_SetWindowGrab(window, SDL_TRUE); + SDL_SetRelativeMouseMode(SDL_TRUE); } } @@ -1242,22 +1192,12 @@ void I_GetEvent(void) void I_StartupMouse(void) { - static SDL_bool firsttimeonmouse = SDL_TRUE; - if (disable_mouse) return; - if (!firsttimeonmouse) - { - HalfWarpMouse(realwidth, realheight); // warp to center - } - else - firsttimeonmouse = SDL_FALSE; - - if (cv_usemouse.value || cv_alwaysgrabmouse.value) - SDLdoGrabMouse(); - else - SDLdoUngrabMouse(); + SDL_ShowCursor(SDL_FALSE); + SDL_SetWindowGrab(window, SDL_FALSE); + SDL_SetRelativeMouseMode(SDL_FALSE); } // @@ -1568,7 +1508,7 @@ static UINT32 VID_GetRefreshRate(void) return 0; } - if (SDL_GetCurrentDisplayMode(index, &m) != 0) + if (SDL_GetDesktopDisplayMode(index, &m) != 0) { // Error has occurred. return 0; @@ -1579,8 +1519,6 @@ static UINT32 VID_GetRefreshRate(void) INT32 VID_SetMode(INT32 modeNum) { - SDLdoUngrabMouse(); - vid.recalc = true; if (modeNum >= 0 && modeNum < MAXWINMODES) @@ -1787,7 +1725,6 @@ void I_StartupGraphics(void) COM_AddCommand ("vid_mode", VID_Command_Mode_f); CV_RegisterVar (&cv_vidwait); CV_RegisterVar (&cv_stretch); - CV_RegisterVar (&cv_alwaysgrabmouse); disable_mouse = M_CheckParm("-nomouse"); disable_fullscreen = M_CheckParm("-win") ? 1 : 0; @@ -1804,14 +1741,10 @@ void I_StartupGraphics(void) { const char *vd = SDL_GetCurrentVideoDriver(); //CONS_Printf(M_GetText("Starting up with video driver: %s\n"), vd); - if (vd && ( - strncasecmp(vd, "gcvideo", 8) == 0 || - strncasecmp(vd, "fbcon", 6) == 0 || - strncasecmp(vd, "wii", 4) == 0 || - strncasecmp(vd, "psl1ght", 8) == 0 - )) + if (vd && (strncasecmp(vd, "fbcon", 6) == 0)) framebuffer = SDL_TRUE; } + if (M_CheckParm("-software")) rendermode = render_soft; #ifdef HWRENDER @@ -1978,22 +1911,14 @@ void I_StartupGraphics(void) VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); - if (M_CheckParm("-nomousegrab")) - mousegrabok = SDL_FALSE; - realwidth = (Uint16)vid.width; realheight = (Uint16)vid.height; - SDLdoUngrabMouse(); - SDL_RaiseWindow(window); - if (mousegrabok && !disable_mouse) - { - SDLdoGrabMouse(); - } - graphics_started = true; + + SDL_StopTextInput(); } void I_ShutdownGraphics(void) diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 0c5bfaeff..ac204ea99 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -83,8 +83,6 @@ void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer); void I_GetConsoleEvents(void); -void SDLforceUngrabMouse(void); - // Needed for some WIN32 functions extern SDL_Window *window; diff --git a/src/st_stuff.c b/src/st_stuff.c index aa1d6a81e..976de5686 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -478,7 +478,7 @@ static void ST_drawLevelTitle(void) // uh... "fill in the bits" of sub, or something... no idea what I came up with // VERY janky, but doesn't require m_easing - INT32 frac = (FixedMul(R_GetHudUncap(), FixedDiv(dupcalc, BASEVIDWIDTH)) >> (count + 4))/13; // these two magic numbers seem to do the trick + INT32 frac = (FixedMul(R_GetTimeFrac(RTF_LEVEL), FixedDiv(dupcalc, BASEVIDWIDTH)) >> (count + 4))/13; // these two magic numbers seem to do the trick sub = dupcalc; while (count-- > 0) diff --git a/src/string.c b/src/string.c index c919ec804..9b67f3148 100644 --- a/src/string.c +++ b/src/string.c @@ -18,36 +18,90 @@ #ifndef SRB2_HAVE_STRLCPY -// Like the OpenBSD version, but it doesn't check for src not being a valid -// C string. -size_t strlcat(char *dst, const char *src, size_t siz) +/* + * Imported from OpenBSD + * strlcpy/strlcat implementation by Todd C. Miller, see license below. + */ + +/* + * Copyright (c) 1998, 2015 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= dsize, truncation occurred. + */ + +size_t strlcat(char *dst, const char *src, size_t dsize) { - size_t dstlen, n = siz; - char *p = dst; + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; - dstlen = strlen(dst); - n -= dstlen; - p += dstlen; + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; - while (n > 1 && *src != '\0') - { - *p++ = *src++; - n--; + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; } + *dst = '\0'; - if (n >= 1) - *p = '\0'; - - return strlen(src) + dstlen; + return(dlen + (src - osrc)); /* count does not include NUL */ } -size_t strlcpy(char *dst, const char *src, size_t siz) -{ - if (siz == 0) - return strlen(dst); +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ - dst[0] = '\0'; - return strlcat(dst, src, siz); +size_t strlcpy(char *dst, const char *src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ } #endif diff --git a/src/v_video.c b/src/v_video.c index 15eb653ab..3bde9bd3d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -1764,9 +1764,8 @@ void V_DrawVhsEffect(boolean rewind) if (rewind) V_DrawVhsEffect(false); // experimentation - fixed_t frac = R_UsingFrameInterpolation() ? renderdeltatics : FRACUNIT; - upbary -= frac * (vid.dupy * (rewind ? 3 : 1.8f)); - downbary += frac * (vid.dupy * (rewind ? 2 : 1)); + upbary -= renderdeltatics * (vid.dupy * (rewind ? 3 : 1.8f)); + downbary += renderdeltatics * (vid.dupy * (rewind ? 2 : 1)); if (upbary < -barsize*FRACUNIT) upbary = vid.height< vid.height<filename); + + for (; posStart < posEnd; posStart++) { lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart]; - size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name + + size_t length = len + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; CONS_Printf(M_GetText("Loading SOC from %s\n"), name); @@ -269,6 +275,7 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) // Find Lua scripts before SOCs to allow new A_Actions in SOC editing. { lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo; + for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) if (memcmp(lump_p->name,"LUA_",4)==0) LUA_LoadLump(wadnum, lump); @@ -276,11 +283,15 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) { lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo; + size_t len = strlen(wadfiles[wadnum]->filename); + for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) - if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump + { + if (memcmp(lump_p->name,"SOC_",4) == 0) // Check for generic SOC lump { // shameless copy+paste of code from LUA_LoadLump - size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name + size_t length = len + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; @@ -288,16 +299,17 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum) DEH_LoadDehackedLumpPwad(wadnum, lump); free(name); } - else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG + else if (memcmp(lump_p->name,"MAINCFG",8) == 0) // Check for MAINCFG { CONS_Printf(M_GetText("Loading main config from %s\n"), wadfiles[wadnum]->filename); DEH_LoadDehackedLumpPwad(wadnum, lump); } - else if (memcmp(lump_p->name,"OBJCTCFG",8)==0) // Check for OBJCTCFG + else if (memcmp(lump_p->name,"OBJCTCFG",8) == 0) // Check for OBJCTCFG { CONS_Printf(M_GetText("Loading object config from %s\n"), wadfiles[wadnum]->filename); DEH_LoadDehackedLumpPwad(wadnum, lump); } + } } } @@ -321,14 +333,18 @@ static inline INT32 W_MakeFileMD5(const char *filename, void *resblock) if ((fhandle = fopen(filename, "rb")) != NULL) { tic_t t = I_GetTime(); + CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",filename); + 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; } @@ -350,13 +366,15 @@ UINT32 W_HashLumpName(const char *name) /** Detect a file type. * \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions. */ -static restype_t ResourceFileDetect (const char* filename) +static restype_t ResourceFileDetect(const char* filename) { - if (!stricmp(&filename[strlen(filename) - 4], ".pk3")) + size_t len = strlen(filename) - 4; + + if (!stricmp(&filename[len], ".pk3")) return RET_PK3; - if (!stricmp(&filename[strlen(filename) - 4], ".soc")) + if (!stricmp(&filename[len], ".soc")) return RET_SOC; - if (!stricmp(&filename[strlen(filename) - 4], ".lua")) + if (!stricmp(&filename[len], ".lua")) return RET_LUA; return RET_WAD; @@ -364,9 +382,10 @@ static restype_t ResourceFileDetect (const char* filename) /** Create a 1-lump lumpinfo_t for standalone files. */ -static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname) +static lumpinfo_t* ResGetLumpsStandalone(FILE* handle, UINT16* numlumps, const char* lumpname) { lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); + lumpinfo->position = 0; fseek(handle, 0, SEEK_END); lumpinfo->size = ftell(handle); @@ -416,7 +435,9 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen } if (memcmp(header.identification, "ZWAD", 4) == 0) + { compressed = 1; + } else if (memcmp(header.identification, "IWAD", 4) != 0 && memcmp(header.identification, "PWAD", 4) != 0 && memcmp(header.identification, "SDLL", 4) != 0) @@ -431,6 +452,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen // read wad file directory i = header.numlumps * sizeof (*fileinfo); fileinfov = fileinfo = malloc(i); + if (fseek(handle, header.infotableofs, SEEK_SET) == -1 || fread(fileinfo, 1, i, handle) < i) { @@ -443,13 +465,16 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen // fill in lumpinfo for this wad lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); + for (i = 0; i < numlumps; i++, lump_p++, fileinfo++) { lump_p->position = LONG(fileinfo->filepos); lump_p->size = lump_p->disksize = LONG(fileinfo->size); + if (compressed) // wad is compressed, lump might be { UINT32 realsize = 0; + if (fseek(handle, lump_p->position, SEEK_SET) == -1 || fread(&realsize, 1, sizeof realsize, handle) < sizeof realsize) @@ -457,6 +482,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout? filename, M_FileError(handle)); } + realsize = LONG(realsize); if (realsize != 0) { @@ -473,7 +499,10 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen lump_p->disksize -= 4; } else + { lump_p->compression = CM_NOCOMPRESSION; + } + memset(lump_p->name, 0x00, 9); strncpy(lump_p->name, fileinfo->name, 8); lump_p->namelength = strlen(lump_p->name); @@ -521,12 +550,15 @@ static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos) char* buffer = (char*)(malloc(buffer_size)); size_t bytes_read = 0; - while ((bytes_read = fread(buffer, 1, buffer_size, handle)) > 0) { - for (size_t i = 0; i < bytes_read; i++) { + while ((bytes_read = fread(buffer, 1, buffer_size, handle)) > 0) + { + for (size_t i = 0; i < bytes_read; i++) + { c = (int)buffer[i]; if (*s != c && s > endPat) // No match? s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array. + if (*s == c) { s++; @@ -541,6 +573,7 @@ static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos) } } } + chunkpos += bytes_read; } @@ -605,7 +638,7 @@ typedef struct zlentry_s /** Create a lumpinfo_t array for a PKZip file. */ -static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) +static lumpinfo_t* ResGetLumpsZip(FILE* handle, UINT16* nlmp) { zend_t zend; zlentry_t zlentry; @@ -615,13 +648,14 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) lumpinfo_t *lump_p; size_t i; - char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; - char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + static const char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + static char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; // Look for central directory end signature near end of file. // Contains entry number (number of lumps), and central directory start offset. fseek(handle, 0, SEEK_END); - if (!ResFindSignature(handle, pat_end, max(0, ftell(handle) - (22 + 65536)))) + const long startpos = ftell(handle) - (22 + 65536); + if (!ResFindSignature(handle, pat_end, max(0, startpos))) { CONS_Alert(CONS_ERROR, "Missing central directory\n"); return NULL; @@ -741,6 +775,23 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) return lumpinfo; } +static UINT16 W_InitFileError (const char *filename, boolean exitworthy) +{ + if (exitworthy) + { +#ifdef _DEBUG + CONS_Error(va("%s was not found or not valid.\nCheck the log for more details.\n", filename)); +#else + I_Error("%s was not found or not valid.\nCheck the log for more details.\n", filename); +#endif + } + else + CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), filename); + + return INT16_MAX; +} + + // Allocate a wadfile, setup the lumpinfo (directory) and // lumpcache, add the wadfile to the current active wadfiles // @@ -752,7 +803,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) // // Can now load dehacked files (.soc) // -UINT16 W_InitFile(const char *filename, boolean local) +UINT16 W_InitFile(const char *filename, boolean local, boolean startup) { FILE *handle; lumpinfo_t *lumpinfo = NULL; @@ -768,8 +819,8 @@ UINT16 W_InitFile(const char *filename, boolean local) if (!(refreshdirmenu & REFRESHDIR_ADDFILE)) refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier - if (refreshdirname) - Z_Free(refreshdirname); + Z_Free(refreshdirname); + if (dirmenu) { refreshdirname = Z_StrDup(filename); @@ -779,6 +830,7 @@ UINT16 W_InitFile(const char *filename, boolean local) refreshdirname = NULL; CONS_Printf("Loading %s\n", filename); + // // check if limit of active wadfiles // @@ -786,14 +838,14 @@ UINT16 W_InitFile(const char *filename, boolean local) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); refreshdirmenu |= REFRESHDIR_MAX; - return INT16_MAX; + return W_InitFileError(filename, startup); } // open wad file if ((handle = W_OpenWadFile(&filename, true)) == NULL) - return INT16_MAX; + return W_InitFileError(filename, startup); - important = !local && !W_VerifyNMUSlumps(filename); + important = !local && !W_VerifyNMUSlumps(filename, handle, startup); #ifndef NOMD5 // @@ -810,33 +862,33 @@ UINT16 W_InitFile(const char *filename, boolean local) CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); if (handle) fclose(handle); - return INT16_MAX; + return W_InitFileError(filename, false); } } #endif switch(type = ResourceFileDetect(filename)) { - case RET_SOC: - lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG"); - break; - case RET_LUA: - lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT"); - break; - case RET_PK3: - lumpinfo = ResGetLumpsZip(handle, &numlumps); - break; - case RET_WAD: - lumpinfo = ResGetLumpsWad(handle, &numlumps, filename); - break; - default: - CONS_Alert(CONS_ERROR, "Unsupported file format\n"); + case RET_SOC: + lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG"); + break; + case RET_LUA: + lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT"); + break; + case RET_PK3: + lumpinfo = ResGetLumpsZip(handle, &numlumps); + break; + case RET_WAD: + lumpinfo = ResGetLumpsWad(handle, &numlumps, filename); + break; + default: + CONS_Alert(CONS_ERROR, "Unsupported file format\n"); } if (lumpinfo == NULL) { fclose(handle); - return INT16_MAX; + return W_InitFileError(filename, startup); } // @@ -851,8 +903,8 @@ UINT16 W_InitFile(const char *filename, boolean local) fseek(handle, 0, SEEK_END); wadfile->filesize = (unsigned)ftell(handle); wadfile->type = type; - wadfile->startfolders = M_AATreeAlloc(0); - wadfile->endfolders = M_AATreeAlloc(0); + wadfile->startfolders = M_AATreeAlloc(AATREE_STRING); + wadfile->endfolders = M_AATreeAlloc(AATREE_STRING); // already generated, just copy it over M_Memcpy(&wadfile->md5sum, &md5sum, 16); @@ -883,21 +935,21 @@ UINT16 W_InitFile(const char *filename, boolean local) // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. switch (wadfile->type) { - case RET_WAD: - W_LoadDehackedLumps(numwadfiles - 1); - break; - case RET_PK3: - W_LoadDehackedLumpsPK3(numwadfiles - 1); - break; - case RET_SOC: - CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename); - DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0); - break; - case RET_LUA: - LUA_LoadLump(numwadfiles - 1, 0); - break; - default: - break; + case RET_WAD: + W_LoadDehackedLumps(numwadfiles - 1); + break; + case RET_PK3: + W_LoadDehackedLumpsPK3(numwadfiles - 1); + break; + case RET_SOC: + CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename); + DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0); + break; + case RET_LUA: + LUA_LoadLump(numwadfiles - 1, 0); + break; + default: + break; } if (refreshdirmenu & REFRESHDIR_GAMEDATA) @@ -924,14 +976,16 @@ INT32 W_InitMultipleFiles(char **filenames, boolean addons) INT32 rc = 1; INT32 overallrc = 1; + (void)addons; + // will be realloced as lumps are added for (; *filenames; filenames++) { - if (addons && !W_VerifyNMUSlumps(*filenames)) - G_SetGameModified(true, false); + // Previously, W_VerifyNMUSlumps was called to mark game modified + // for addons... but W_InitFile already does exactly that! //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); - rc = W_InitFile(*filenames, false); + rc = W_InitFile(*filenames, false, true); if (rc == INT16_MAX) CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), *filenames); @@ -1031,11 +1085,14 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) if (startlump < wadfiles[wad]->numlumps) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + { if (lump_p->namelength == namelen && lump_p->hash.name == hash && !memcmp(lump_p->name, uname, sizeof(uname) - 1)) return i; + } } // not found. @@ -1066,11 +1123,14 @@ UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) if (startlump < wadfiles[wad]->numlumps) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + { if (lump_p->longnamelength == namelen && lump_p->hash.longname == hash && !stricmp(lump_p->longname, name)) return i; + } } // not found. @@ -1093,9 +1153,8 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum INT32 i; lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; name_length = strlen(name); - UINT32 hash = quickncasehash(name, name_length); - void *val = M_AATreeGet(wadfiles[wad]->startfolders, hash); + void *val = M_AATreeGetString(wadfiles[wad]->startfolders, name); if (val != NULL) return (uintptr_t)val; @@ -1107,14 +1166,12 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum if (strlen(lump_p->fullname) == name_length) i++; - M_AATreeSet(wadfiles[wad]->startfolders, hash, (void *)(uintptr_t)i); - + M_AATreeSetString(wadfiles[wad]->startfolders, name, (void *)(uintptr_t)i); return i; } } - M_AATreeSet(wadfiles[wad]->startfolders, hash, (void *)INT16_MAX); - + M_AATreeSetString(wadfiles[wad]->startfolders, name, (void *)INT16_MAX); return INT16_MAX; } @@ -1126,9 +1183,8 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) INT32 i; lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; size_t name_length = strlen(name); - UINT32 hash = quickncasehash(name, name_length); - void *val = M_AATreeGet(wadfiles[wad]->endfolders, hash); + void *val = M_AATreeGetString(wadfiles[wad]->endfolders, name); if (val != NULL) return (uintptr_t)val; @@ -1138,8 +1194,7 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) break; } - M_AATreeSet(wadfiles[wad]->endfolders, hash, (void *)(uintptr_t)i); - + M_AATreeSetString(wadfiles[wad]->endfolders, name, (void *)(uintptr_t)i); return i; } @@ -1161,6 +1216,63 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) return INT16_MAX; } +static lumpnum_t CheckLumpInCache(const char *name, boolean longname) +{ + if (longname) + { + UINT32 hash = quickncasehash(name, 32); + + // Loop backwards so that we check most recent entries first + for (INT32 i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].hash == hash + && stricmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + } + else + { + UINT32 hash = quickncasehash(name, 8); + + // Loop backwards so that we check most recent entries first + for (INT32 i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].hash == hash + && lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] == '\0' + && strnicmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + } + + return LUMPERROR; +} + +static void AddLumpToCache(lumpnum_t lumpnum, const char *name, boolean longname) +{ + if (longname && strlen(name) >= LUMPNUMCACHENAME) + return; + + lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', LUMPNUMCACHENAME); + if (longname) + { + strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, LUMPNUMCACHENAME); + lumpnumcache[lumpnumcacheindex].hash = quickncasehash(name, LUMPNUMCACHENAME); + } + else + { + strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); + lumpnumcache[lumpnumcacheindex].hash = quickncasehash(name, 8); + } + lumpnumcache[lumpnumcacheindex].lumpnum = lumpnum; +} + // // W_CheckNumForName // Returns LUMPERROR if name not found. @@ -1173,22 +1285,15 @@ lumpnum_t W_CheckNumForName(const char *name) if (!*name) // some doofus gave us an empty string? return LUMPERROR; - // Check the lumpnumcache first. Loop backwards so that we check - // most recent entries first - for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) - { - if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] - && strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) - { - lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); - return lumpnumcache[lumpnumcacheindex].lumpnum; - } - } + // Check the lumpnumcache first. + lumpnum_t cachenum = CheckLumpInCache(name, false); + if (cachenum != LUMPERROR) + return cachenum; // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) { - check = W_CheckNumForNamePwad(name,(UINT16)i,0); + check = W_CheckNumForNamePwad(name, (UINT16)i, 0); if (check != INT16_MAX) break; //found it } @@ -1200,12 +1305,11 @@ lumpnum_t W_CheckNumForName(const char *name) else { // Update the cache. - lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); - memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', LUMPNUMCACHENAME); - strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); - lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check; + lumpnum_t lumpnum = (i << 16) + check; - return lumpnumcache[lumpnumcacheindex].lumpnum; + AddLumpToCache(lumpnum, name, false); + + return lumpnum; } } @@ -1223,23 +1327,17 @@ lumpnum_t W_CheckNumForLongName(const char *name) if (!*name) // some doofus gave us an empty string? return LUMPERROR; - // Check the lumpnumcache first. Loop backwards so that we check - // most recent entries first - for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) - { - if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) - { - lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); - return lumpnumcache[lumpnumcacheindex].lumpnum; - } - } + // Check the lumpnumcache first. + lumpnum_t cachenum = CheckLumpInCache(name, true); + if (cachenum != LUMPERROR) + return cachenum; if (check == INT16_MAX) { // scan wad files backwards so patch lump files take precedence for (i = numwadfiles - 1; i >= 0; i--) { - check = W_CheckNumForLongNamePwad(name,(UINT16)i,0); + check = W_CheckNumForLongNamePwad(name, (UINT16)i, 0); if (check != INT16_MAX) break; //found it } @@ -1251,16 +1349,12 @@ lumpnum_t W_CheckNumForLongName(const char *name) } else { - if (strlen(name) < LUMPNUMCACHENAME) - { - // Update the cache. - lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); - memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', LUMPNUMCACHENAME); - strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, LUMPNUMCACHENAME); - lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check; - } + // Update the cache. + lumpnum_t lumpnum = (i << 16) + check; - return (i << 16) + check; + AddLumpToCache(lumpnum, name, true); + + return lumpnum; } } @@ -1391,9 +1485,11 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) { const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname; - if (strlen(lumpfullName) < 4) + size_t len = strlen(lumpfullName); + + if (len < 4) return false; // can't possibly be a WAD can it? - return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4); + return !strnicmp(lumpfullName + len - 4, ".wad", 4); } return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned @@ -1419,26 +1515,27 @@ boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) /* report a zlib or i/o error */ void zerr(int ret) { - CONS_Printf("zpipe: "); - switch (ret) { - case Z_ERRNO: - if (ferror(stdin)) - CONS_Printf("error reading stdin\n"); - if (ferror(stdout)) - CONS_Printf("error writing stdout\n"); - break; - case Z_STREAM_ERROR: - CONS_Printf("invalid compression level\n"); - break; - case Z_DATA_ERROR: - CONS_Printf("invalid or incomplete deflate data\n"); - break; - case Z_MEM_ERROR: - CONS_Printf("out of memory\n"); - break; - case Z_VERSION_ERROR: - CONS_Printf("zlib version mismatch!\n"); - } + CONS_Printf("zpipe: "); + switch (ret) + { + case Z_ERRNO: + if (ferror(stdin)) + CONS_Printf("error reading stdin\n"); + if (ferror(stdout)) + CONS_Printf("error writing stdout\n"); + break; + case Z_STREAM_ERROR: + CONS_Printf("invalid compression level\n"); + break; + case Z_DATA_ERROR: + CONS_Printf("invalid or incomplete deflate data\n"); + break; + case Z_MEM_ERROR: + CONS_Printf("out of memory\n"); + break; + case Z_VERSION_ERROR: + CONS_Printf("zlib version mismatch!\n"); + } } #endif @@ -1447,15 +1544,15 @@ void zerr(int ret) #ifdef NO_PNG_LUMPS static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l) { - if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ - return; - // Check for PNG file signature using memcmp - // As it may be faster on CPUs with slow unaligned memory access - // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature - if (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0) - { - I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .PNG - please convert to either Doom or Flat (raw) image format.", l, f); - } + if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return; + // Check for PNG file signature using memcmp + // As it may be faster on CPUs with slow unaligned memory access + // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature + if (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0) + { + I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .PNG - please convert to either Doom or Flat (raw) image format.", l, f); + } } #endif @@ -1501,7 +1598,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si #ifdef NO_PNG_LUMPS { size_t bytesread = fread(dest, 1, size, handle); - ErrorIfPNG(dest, bytesread, wadfiles[wad]->filename, l->fullname); + ErrorIfPNG((UINT8 *)dest, bytesread, wadfiles[wad]->filename, l->fullname); return bytesread; } #else @@ -1542,7 +1639,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si Z_Free(rawData); Z_Free(decData); #ifdef NO_PNG_LUMPS - ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->fullname); + ErrorIfPNG((UINT8 *)dest, size, wadfiles[wad]->filename, l->fullname); #endif return size; #else @@ -1560,10 +1657,10 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si int zErr; // Helper var. z_stream strm; unsigned long rawSize = l->disksize; - unsigned long decSize = l->size; + unsigned long decSize = size; rawData = Z_Malloc(rawSize, PU_STATIC, NULL); - decData = Z_Malloc(decSize, PU_STATIC, NULL); + decData = dest; if (fread(rawData, 1, rawSize, handle) < rawSize) I_Error("wad %d, lump %d: cannot read compressed data", wad, lump); @@ -1581,12 +1678,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si zErr = inflateInit2(&strm, -15); if (zErr == Z_OK) { - zErr = inflate(&strm, Z_FINISH); - if (zErr == Z_STREAM_END) - { - M_Memcpy(dest, decData, size); - } - else + zErr = inflate(&strm, Z_SYNC_FLUSH); + if (zErr != Z_OK && zErr != Z_STREAM_END) { size = 0; zerr(zErr); @@ -1601,10 +1694,9 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si } Z_Free(rawData); - Z_Free(decData); #ifdef NO_PNG_LUMPS - ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->fullname); + ErrorIfPNG((UINT8 *)dest, size, wadfiles[wad]->filename, l->fullname); #endif return size; } @@ -1793,7 +1885,7 @@ void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) ptr = lumpdata; dest = Z_Calloc(sizeof(patch_t), tag, &lumpcache[lump]); - Patch_Create(ptr, len, dest); + Patch_Create((softwarepatch_t*)(ptr), len, dest); Z_Free(ptr); } @@ -1905,7 +1997,7 @@ void *W_CachePatchNameRotated(const char *name, INT32 rotationangle, INT32 tag) { INT32 xpivot = 0, ypivot = 0; - ptr = W_CachePatchNum(num, PU_PATCH); + ptr = (patch_t *)W_CachePatchNum(num, PU_PATCH); // >y pivot centered // >x pivot not centered @@ -2096,7 +2188,8 @@ static int W_VerifyPK3(FILE *fp, lumpchecklist_t *checklist, boolean status) fseek(fp, 0, SEEK_END); file_size = ftell(fp); - if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536)))) + const long size = file_size - (22 + 65536); + if (!ResFindSignature(fp, pat_end, max(0, size))) return true; fseek(fp, -4, SEEK_CUR); @@ -2203,38 +2296,6 @@ static int W_VerifyPK3(FILE *fp, lumpchecklist_t *checklist, boolean status) } } -// Note: This never opens lumps themselves and therefore doesn't have to -// deal with compressed lumps. -static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, - boolean status) -{ - FILE *handle; - int goodfile = false; - - if (!checklist) - I_Error("No checklist for %s\n", filename); - // open wad file - if ((handle = W_OpenWadFile(&filename, false)) == NULL) - return -1; - - if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) - goodfile = W_VerifyPK3(handle, checklist, status); - else - { - // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") - && stricmp(&filename[strlen(filename) - 4], ".lua")) - { - goodfile = W_VerifyWAD(handle, checklist, status); - } - } - - fclose(handle); - - return goodfile; -} - - /** Checks a wad for lumps other than music and sound. * Used during game load to verify music.dta is a good file and during a * netgame join (on the server side) to see if a wad is important enough to @@ -2246,7 +2307,7 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, * file exists with that filename * \author Alam Arias */ -int W_VerifyNMUSlumps(const char *filename) +int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error) { lumpchecklist_t NMUSlist[] = { @@ -2283,7 +2344,31 @@ int W_VerifyNMUSlumps(const char *filename) #endif {NULL, 0}, }; - return W_VerifyFile(filename, NMUSlist, false); + + int status = 0; + size_t len = strlen(filename) - 4; + + if (stricmp(&filename[len], ".pk3") == 0) + { + status = W_VerifyPK3(handle, NMUSlist, false); + } + else + { + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[len], ".soc") + && stricmp(&filename[len], ".lua")) + { + status = W_VerifyWAD(handle, NMUSlist, false); + + // repair file handle in this specific case + fseek(handle, 0, SEEK_SET); + } + } + + if (status == -1) + W_InitFileError(filename, exit_on_error); + + return status; } static int W_NameStartsWith(const char *name, lumpchecklist_t *checklist) @@ -2369,7 +2454,8 @@ static int W_CheckPK3Contains(FILE *fp, lumpchecklist_t *checklist) fseek(fp, 0, SEEK_END); file_size = ftell(fp); - if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536)))) + const long startpos = file_size - (22 + 65536); + if (!ResFindSignature(fp, pat_end, max(0, startpos))) return true; fseek(fp, -4, SEEK_CUR); @@ -2491,13 +2577,15 @@ static int W_CheckFileContains(const char *filename, lumpchecklist_t *checklist) if ((handle = W_OpenWadFile(&filename, false)) == NULL) return -1; - if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + size_t len = strlen(filename) - 4; + + if (stricmp(&filename[len], ".pk3") == 0) contains = W_CheckPK3Contains(handle, checklist); else { // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") - && stricmp(&filename[strlen(filename) - 4], ".lua")) + if (stricmp(&filename[len], ".soc") + && stricmp(&filename[len], ".lua")) { contains = W_CheckWADContains(handle, checklist); } @@ -2576,6 +2664,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum) vlumps[i].size = vsizecache[realentry]; const char *name = (fileinfo + realentry)->name; + if (strlen(name) == 5 && memcmp(name, "MAP", 3) == 0) { numlumps--; // We skip map marker, so 1 of entries becomes empty @@ -2613,6 +2702,7 @@ virtres_t* vres_GetMap(lumpnum_t lumpnum) { // Check if it is map marker. It is not always first lump sadly, so we need to expect it anywhere const char *name = W_CheckNameForNum(lumpnum); + if (strlen(name) == 5 && memcmp(name, "MAP", 3) == 0) { --i; // Decrement so on next iteration we write on same i, so we don't leave corrupted vlumps entry @@ -2679,7 +2769,10 @@ virtlump_t* vres_Find(const virtres_t* vres, const char* name) { UINT32 i; for (i = 0; i < vres->numlumps; i++) + { if (fastcmp(name, vres->vlumps[i].name)) return &vres->vlumps[i]; + } + return NULL; } diff --git a/src/w_wad.h b/src/w_wad.h index 196fd7893..e0faedab5 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -171,7 +171,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors); // // if local is true, it wouldn't check if file adds complex things, therefore // allowing to still join server without the "you have wrong addons loaded" error -UINT16 W_InitFile(const char *filename, boolean local); +UINT16 W_InitFile(const char *filename, boolean local, boolean startup); // 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. @@ -249,7 +249,7 @@ void W_UnlockCachedPatch(void *patch); void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5); -int W_VerifyNMUSlumps(const char *filename); +int W_VerifyNMUSlumps(const char *filename, FILE *handle, boolean exit_on_error); int W_CheckPostLoadList(const char *filename); diff --git a/src/y_inter.c b/src/y_inter.c index 892187d85..c22a3728d 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -45,6 +45,8 @@ #include "lua_hook.h" // IntermissionThinker hook #include "lua_hud.h" // intermission hud hook +#include "r_fps.h" // R_GetTimeFrac + #ifdef HWRENDER #include "hardware/hw_main.h" #endif @@ -471,9 +473,9 @@ void Y_IntermissionDrawer(void) INT64 count = (intertic - sorttic); if (count < 8) - x -= ((((count<>FRACBITS) / (8 * vid.dupx); + x -= ((((count<>FRACBITS) / (8 * vid.dupx); else if (count < 16) - x += (((((16 - count)<>FRACBITS) / (8 * vid.dupx); + x += (((((16 - count)<>FRACBITS) / (8 * vid.dupx); } if (intertype == int_race || intertype == int_match) @@ -1367,21 +1369,7 @@ void Y_VoteTicker(void) UINT8 p; boolean pressed = false; - switch (i) - { - case 1: - p = displayplayers[1]; - break; - case 2: - p = displayplayers[2]; - break; - case 3: - p = displayplayers[3]; - break; - default: - p = consoleplayer; - break; - } + p = P_GetLocalPlayerNumForNum(i); if (voteclient.playerinfo[i].delay) voteclient.playerinfo[i].delay--; diff --git a/src/z_zone.c b/src/z_zone.cpp similarity index 88% rename from src/z_zone.c rename to src/z_zone.cpp index b9150115a..8ed23e4a7 100644 --- a/src/z_zone.c +++ b/src/z_zone.cpp @@ -28,6 +28,7 @@ #include #include +#include "core/memory.h" #include "doomdef.h" #include "doomstat.h" #include "r_patch.h" @@ -56,11 +57,12 @@ static boolean Z_calloc = false; typedef struct memblock_s { void **user; - INT32 tag; // purgelevel - UINT32 id; // Should be ZONEID + size_t size; // excluding the block - size_t size; // including the header and blocks - size_t realsize; // size of real data only +#ifdef PARANOIA + UINT32 id; // Should be ZONEID +#endif + UINT8 tag; // purgelevel #ifdef ZDEBUG const char *ownerfile; @@ -77,6 +79,16 @@ typedef struct memblock_s // both the head and tail of the zone memory block list static memblock_t head; +static constexpr size_t kLevelLargePoolBlockSize = sizeof(mobj_t); +static constexpr size_t kLevelMedPoolBlockSize = sizeof(precipmobj_t); +static constexpr size_t kLevelSmallPoolBlockSize = 128; +static constexpr size_t kLevelTinyPoolBlockSize = 64; + +static srb2::PoolAllocator g_level_large_pool { kLevelLargePoolBlockSize, 1024, PU_LEVEL }; +static srb2::PoolAllocator g_level_med_pool { kLevelMedPoolBlockSize, 32768, PU_LEVEL }; +static srb2::PoolAllocator g_level_small_pool { kLevelSmallPoolBlockSize, 4096, PU_LEVEL }; +static srb2::PoolAllocator g_level_tiny_pool { kLevelTinyPoolBlockSize, 8192, PU_LEVEL }; + // // Function prototypes // @@ -230,7 +242,7 @@ void *Z_Malloc(size_t size, INT32 tag, void *user) CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line); #endif - block = xm(sizeof (memblock_t) + ALIGNPAD + size); + block = (memblock_t*)xm(sizeof (memblock_t) + ALIGNPAD + size); ptr = MEMORY(block); I_Assert((intptr_t)ptr % alignof (max_align_t) == 0); @@ -249,18 +261,19 @@ void *Z_Malloc(size_t size, INT32 tag, void *user) block->ownerline = line; block->ownerfile = file; #endif - block->size = sizeof (memblock_t) + size; - block->realsize = size; + block->size = size; #ifdef VALGRIND_CREATE_MEMPOOL VALGRIND_CREATE_MEMPOOL(block, size, Z_calloc); #endif +#ifdef PARANOIA block->id = ZONEID; +#endif if (user != NULL) { - block->user = user; + block->user = (void**)user; *(void **)user = ptr; } else if (tag >= PU_PURGELEVEL) @@ -365,10 +378,10 @@ void *Z_Realloc(void *ptr, size_t size, INT32 tag, void *user) rez = Z_Malloc(size, tag, user); #endif - if (size < block->realsize) + if (size < block->size) copysize = size; else - copysize = block->realsize; + copysize = block->size; M_Memcpy(rez, ptr, copysize); @@ -407,6 +420,16 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) #else Z_CheckHeap(420); #endif + + // First, release all pools, since they can make allocations in zones. + if (PU_LEVEL >= lowtag && PU_LEVEL <= hightag) + { + g_level_large_pool.release(); + g_level_med_pool.release(); + g_level_small_pool.release(); + g_level_tiny_pool.release(); + } + for (block = head.next; block != &head; block = next) { next = block->next; // get link before freeing @@ -572,6 +595,7 @@ void Z_CheckHeap(INT32 tag) #endif ); } +#ifdef PARANOIA if (block->id != ZONEID) { I_Error("Z_CheckHeap :" @@ -592,6 +616,7 @@ void Z_CheckHeap(INT32 tag) #endif ); } +#endif } } @@ -661,7 +686,7 @@ void Z_SetUser(void *ptr, void **newuser) I_Error("Internal memory management error: " "tried to make block purgable but it has no owner"); - block->user = (void*)newuser; + block->user = (void**)newuser; *newuser = ptr; } @@ -685,7 +710,7 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) { if (rover->tag < lowtag || rover->tag > hightag) continue; - cnt += rover->size + sizeof *rover; + cnt += rover->size + sizeof(memblock_t); } return cnt; @@ -759,8 +784,8 @@ static void Command_Memdump_f(void) for (block = head.next; block != &head; block = block->next) if (block->tag >= mintag && block->tag <= maxtag) { - char *filename = strrchr(block->ownerfile, PATHSEP[0]); - CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline); + const char *filename = strrchr(block->ownerfile, PATHSEP[0]); + CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size + sizeof(memblock_t)), sizeu2(block->size), filename ? filename + 1 : block->ownerfile, block->ownerline); } } #endif @@ -772,5 +797,61 @@ static void Command_Memdump_f(void) */ char *Z_StrDup(const char *s) { - return strcpy(ZZ_Alloc(strlen(s) + 1), s); + return strcpy((char*)ZZ_Alloc(strlen(s) + 1), s); +} + +void* Z_LevelPoolMalloc(size_t size) +{ + void* p = nullptr; + if (size <= kLevelTinyPoolBlockSize) + { + p = g_level_tiny_pool.allocate(); + } + else if (size <= kLevelSmallPoolBlockSize) + { + p = g_level_small_pool.allocate(); + } + else if (size <= kLevelMedPoolBlockSize) + { + p = g_level_med_pool.allocate(); + } + else if (size <= kLevelLargePoolBlockSize) + { + p = g_level_large_pool.allocate(); + } + + if (p == nullptr) + { + p = Z_Malloc(size, PU_LEVEL, nullptr); + } + + return p; +} + +void* Z_LevelPoolCalloc(size_t size) +{ + void* p = Z_LevelPoolMalloc(size); + memset(p, 0, size); + return p; +} + +void Z_LevelPoolFree(void* p, size_t size) +{ + if (size <= kLevelTinyPoolBlockSize) + { + return g_level_tiny_pool.deallocate(p); + } + if (size <= kLevelSmallPoolBlockSize) + { + return g_level_small_pool.deallocate(p); + } + if (size <= kLevelMedPoolBlockSize) + { + return g_level_med_pool.deallocate(p); + } + if (size <= kLevelLargePoolBlockSize) + { + return g_level_large_pool.deallocate(p); + } + return Z_Free(p); } diff --git a/src/z_zone.h b/src/z_zone.h index adbabb37e..709fa1d96 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -164,6 +164,13 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); // char *Z_StrDup(const char *in); +// +// Specialty allocation functions +// +void *Z_LevelPoolMalloc(size_t size); +void *Z_LevelPoolCalloc(size_t size); +void Z_LevelPoolFree(void *p, size_t size); + #ifdef __cplusplus } // extern "C" #endif