Ball-busting true client-server multiplayer prototype/alpha/whatever

git-svn-id: https://svn.eduke32.com/eduke32@1552 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2009-12-05 09:22:43 +00:00
parent 0bd458fa42
commit 44575d7e2c
64 changed files with 7858 additions and 2771 deletions

View file

@ -51,6 +51,9 @@ endif
JAUDIOLIBDIR=$(SRC)/jaudiolib JAUDIOLIBDIR=$(SRC)/jaudiolib
JAUDIOLIB=libjfaudiolib.a JAUDIOLIB=libjfaudiolib.a
ENETDIR=$(SRC)/enet
ENETLIB=libenet.a
CC=gcc CC=gcc
CXX=g++ CXX=g++
AS=nasm AS=nasm
@ -73,7 +76,7 @@ endif
OURCFLAGS=$(debug) -W -Wall -Wimplicit -Werror-implicit-function-declaration \ OURCFLAGS=$(debug) -W -Wall -Wimplicit -Werror-implicit-function-declaration \
-funsigned-char -fno-strict-aliasing -DNO_GCC_BUILTINS \ -funsigned-char -fno-strict-aliasing -DNO_GCC_BUILTINS \
-I$(INC) -I$(EINC) -I$(SRC)/jmact -I$(JAUDIOLIBDIR)/include -D_FORTIFY_SOURCE=2 \ -I$(INC) -I$(EINC) -I$(SRC)/jmact -I$(JAUDIOLIBDIR)/include -I$(ENETDIR)/include -D_FORTIFY_SOURCE=2 \
-fjump-tables -fno-stack-protector -fjump-tables -fno-stack-protector
# -march=pentium3 -mtune=generic -mmmx -m3dnow -msse -mfpmath=sse # -march=pentium3 -mtune=generic -mmmx -m3dnow -msse -mfpmath=sse
OURCXXFLAGS=-fno-exceptions -fno-rtti OURCXXFLAGS=-fno-exceptions -fno-rtti
@ -168,6 +171,7 @@ ifeq ($(PLATFORM),WINDOWS)
GAMEOBJS+= $(OBJ)/gameres.$o $(OBJ)/winbits.$o $(OBJ)/startwin.game.$o $(OBJ)/music.$o $(OBJ)/midi.$o $(OBJ)/mpu401.$o GAMEOBJS+= $(OBJ)/gameres.$o $(OBJ)/winbits.$o $(OBJ)/startwin.game.$o $(OBJ)/music.$o $(OBJ)/midi.$o $(OBJ)/mpu401.$o
EDITOROBJS+= $(OBJ)/buildres.$o EDITOROBJS+= $(OBJ)/buildres.$o
JAUDIOLIB=libjfaudiolib_win32.a JAUDIOLIB=libjfaudiolib_win32.a
ENETLIB=libenet_win32.a
else else
ifeq ($(RENDERTYPE),SDL) ifeq ($(RENDERTYPE),SDL)
ifeq (0,$(SDL_FRAMEWORK)) ifeq (0,$(SDL_FRAMEWORK))
@ -198,7 +202,7 @@ OURCXXFLAGS+= $(BUILDCFLAGS)
ifeq ($(PRETTY_OUTPUT),1) ifeq ($(PRETTY_OUTPUT),1)
.SILENT: .SILENT:
endif endif
.PHONY: clean all engine $(EOBJ)/$(ENGINELIB) $(EOBJ)/$(EDITORLIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) .PHONY: clean all engine $(EOBJ)/$(ENGINELIB) $(EOBJ)/$(EDITORLIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) $(ENETDIR)/$(ENETLIB)
# TARGETS # TARGETS
@ -212,7 +216,7 @@ all:
notice: notice:
$(BUILD_STARTED) $(BUILD_STARTED)
eduke32$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)/$(ENGINELIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) eduke32$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)/$(ENGINELIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) $(ENETDIR)/$(ENETLIB)
$(LINK_STATUS) $(LINK_STATUS)
if $(CC) -o $@ $^ $(LIBS) $(STDCPPLIB); then $(LINK_OK); else $(LINK_FAILED); fi if $(CC) -o $@ $^ $(LIBS) $(STDCPPLIB); then $(LINK_OK); else $(LINK_FAILED); fi
ifeq (1,$(RELEASE)) ifeq (1,$(RELEASE))
@ -221,7 +225,7 @@ ifeq (1,$(RELEASE))
endif endif
endif endif
mapster32$(EXESUFFIX): $(EDITOROBJS) $(EOBJ)/$(EDITORLIB) $(EOBJ)/$(ENGINELIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) mapster32$(EXESUFFIX): $(EDITOROBJS) $(EOBJ)/$(EDITORLIB) $(EOBJ)/$(ENGINELIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) $(ENETDIR)/$(ENETLIB)
$(LINK_STATUS) $(LINK_STATUS)
if $(CC) $(CFLAGS) $(OURCFLAGS) -o $@ $^ $(LIBS) $(STDCPPLIB); then $(LINK_OK); else $(LINK_FAILED); fi if $(CC) $(CFLAGS) $(OURCFLAGS) -o $@ $^ $(LIBS) $(STDCPPLIB); then $(LINK_OK); else $(LINK_FAILED); fi
ifeq (1,$(RELEASE)) ifeq (1,$(RELEASE))
@ -268,6 +272,16 @@ ifeq ($(PRETTY_OUTPUT),1)
printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)\033[0;35m \033[0m\n" printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)\033[0;35m \033[0m\n"
endif endif
$(ENETDIR)/$(ENETLIB):
ifeq ($(PRETTY_OUTPUT),1)
printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)/$(ENETDIR)\033[0;35m \033[0m\n"
endif
$(MAKE) -C $(ENETDIR) PRETTY_OUTPUT=$(PRETTY_OUTPUT) EROOT=$(EROOT) RELEASE=$(RELEASE) OPTLEVEL=$(OPTLEVEL)
ifeq ($(PRETTY_OUTPUT),1)
printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)\033[0;35m \033[0m\n"
endif
# RULES # RULES
$(OBJ)/%.$o: $(SRC)/%.nasm $(OBJ)/%.$o: $(SRC)/%.nasm
$(COMPILE_STATUS) $(COMPILE_STATUS)
@ -309,7 +323,7 @@ $(RSRC)/editor_banner.c: $(RSRC)/build.bmp
# PHONIES # PHONIES
clean: clean:
-rm -f $(OBJ)/* eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) core* duke3d_w32$(EXESUFFIX) && $(MAKE) -C $(JAUDIOLIBDIR) clean -rm -f $(OBJ)/* eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) core* duke3d_w32$(EXESUFFIX) && $(MAKE) -C $(JAUDIOLIBDIR) clean && $(MAKE) -C $(ENETDIR) clean
veryclean: clean veryclean: clean
-rm -f $(EOBJ)/* $(RSRC)/*banner* -rm -f $(EOBJ)/* $(RSRC)/*banner*

View file

@ -12,6 +12,9 @@ o=obj
JAUDIOLIBDIR=$(SRC)\jaudiolib JAUDIOLIBDIR=$(SRC)\jaudiolib
JAUDIOLIB=libjfaudiolib.lib JAUDIOLIB=libjfaudiolib.lib
ENETDIR=$(SRC)\enet
ENETLIB=libenet.lib
ENGINELIB=engine.lib ENGINELIB=engine.lib
EDITORLIB=build.lib EDITORLIB=build.lib
@ -37,7 +40,7 @@ AS=ml
LINK=link /nologo /opt:ref LINK=link /nologo /opt:ref
MT=mt MT=mt
CFLAGS= /MT /J /nologo $(flags_cl) \ CFLAGS= /MT /J /nologo $(flags_cl) \
/I$(INC) /I$(EINC)\msvc /I$(EINC)\ /I$(SRC)\jmact /I$(JAUDIOLIBDIR)\include /I$(MSSDKROOT)\include" /I$(PLATFORMSDK)\include" \ /I$(INC) /I$(EINC)\msvc /I$(EINC)\ /I$(SRC)\jmact /I$(JAUDIOLIBDIR)\include /I$(ENETDIR)\include /I$(MSSDKROOT)\include" /I$(PLATFORMSDK)\include" \
/D "_CRT_SECURE_NO_DEPRECATE" /W2 $(ENGINEOPTS) \ /D "_CRT_SECURE_NO_DEPRECATE" /W2 $(ENGINEOPTS) \
/I$(DXROOT)\include" /DRENDERTYPEWIN=1 /I$(DXROOT)\include" /DRENDERTYPEWIN=1
LIBS=user32.lib gdi32.lib shell32.lib dxguid.lib winmm.lib wsock32.lib comctl32.lib \ LIBS=user32.lib gdi32.lib shell32.lib dxguid.lib winmm.lib wsock32.lib comctl32.lib \
@ -131,7 +134,7 @@ EDITOROBJS=$(OBJ)\astub.$o \
# TARGETS # TARGETS
all: eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) # duke3d_w32$(EXESUFFIX); all: eduke32$(EXESUFFIX) mapster32$(EXESUFFIX) # duke3d_w32$(EXESUFFIX);
eduke32$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)\$(ENGINELIB) $(JAUDIOLIBDIR)\$(JAUDIOLIB) eduke32$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)\$(ENGINELIB) $(JAUDIOLIBDIR)\$(JAUDIOLIB) $(ENETDIR)\$(ENETLIB)
$(LINK) /OUT:$@ /SUBSYSTEM:WINDOWS /LIBPATH:$(DXROOT)\lib\x86" /LIBPATH:$(PLATFORMSDK)\lib" /LIBPATH:$(MSSDKROOT)\lib" $(flags_link) /MAP $** $(LIBS) $(LINK) /OUT:$@ /SUBSYSTEM:WINDOWS /LIBPATH:$(DXROOT)\lib\x86" /LIBPATH:$(PLATFORMSDK)\lib" /LIBPATH:$(MSSDKROOT)\lib" $(flags_link) /MAP $** $(LIBS)
$(MT) -manifest $(RSRC)\manifest.game.xml -hashupdate -outputresource:$@ -out:$@.manifest $(MT) -manifest $(RSRC)\manifest.game.xml -hashupdate -outputresource:$@ -out:$@.manifest
@ -158,11 +161,16 @@ jaudiolib:
nmake /f Makefile.msvc nmake /f Makefile.msvc
cd $(MAKEDIR) cd $(MAKEDIR)
enet:
cd $(ENETDIR)
nmake /f Makefile.msvc
cd $(MAKEDIR)
AlwaysBuild: ; AlwaysBuild: ;
$(EOBJ)\$(EDITORLIB): editorlib ; $(EOBJ)\$(EDITORLIB): editorlib ;
$(EOBJ)\$(ENGINELIB): enginelib ; $(EOBJ)\$(ENGINELIB): enginelib ;
$(JAUDIOLIBDIR)\$(JAUDIOLIB): jaudiolib ; $(JAUDIOLIBDIR)\$(JAUDIOLIB): jaudiolib ;
$(ENETDIR)\$(ENETLIB): enet ;
# PHONIES # PHONIES
clean: clean:
@ -170,6 +178,8 @@ clean:
*.pdb *.map *.manifest *.pdb *.map *.manifest
cd $(JAUDIOLIBDIR) cd $(JAUDIOLIBDIR)
nmake /f Makefile.msvc clean nmake /f Makefile.msvc clean
cd $(MAKEDIR)\$(ENETDIR)
nmake /f Makefile.msvc clean
cd $(MAKEDIR) cd $(MAKEDIR)
veryclean: clean veryclean: clean

View file

@ -127,7 +127,7 @@ ENGINEOBJS+= \
$(OBJ)/textfont.$o \ $(OBJ)/textfont.$o \
$(OBJ)/smalltextfont.$o \ $(OBJ)/smalltextfont.$o \
$(OBJ)/kplib.$o \ $(OBJ)/kplib.$o \
$(OBJ)/fastlz.$o \ $(OBJ)/quicklz.$o \
$(OBJ)/md4.$o \ $(OBJ)/md4.$o \
$(OBJ)/osd.$o \ $(OBJ)/osd.$o \
$(OBJ)/pragmas.$o \ $(OBJ)/pragmas.$o \

View file

@ -10,14 +10,14 @@ $(OBJ)/config.$o: $(SRC)/config.c $(INC)/compat.h $(INC)/osd.h $(INC)/editor.h
$(OBJ)/crc32.$o: $(SRC)/crc32.c $(INC)/crc32.h $(OBJ)/crc32.$o: $(SRC)/crc32.c $(INC)/crc32.h
$(OBJ)/defs.$o: $(SRC)/defs.c $(INC)/build.h $(INC)/baselayer.h $(INC)/scriptfile.h $(INC)/compat.h $(OBJ)/defs.$o: $(SRC)/defs.c $(INC)/build.h $(INC)/baselayer.h $(INC)/scriptfile.h $(INC)/compat.h
$(OBJ)/engine.$o: $(SRC)/engine.c $(INC)/compat.h $(INC)/build.h $(INC)/pragmas.h $(INC)/cache1d.h $(INC)/a.h $(INC)/osd.h $(INC)/baselayer.h $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h $(INC)/polymer.h $(OBJ)/engine.$o: $(SRC)/engine.c $(INC)/compat.h $(INC)/build.h $(INC)/pragmas.h $(INC)/cache1d.h $(INC)/a.h $(INC)/osd.h $(INC)/baselayer.h $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h $(INC)/polymer.h
$(OBJ)/polymost.$o: $(SRC)/polymost.c $(INC)/md4.h $(INC)/fastlz.h $(INC)/lzwnew.h $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h $(OBJ)/polymost.$o: $(SRC)/polymost.c $(INC)/md4.h $(INC)/quicklz.h $(INC)/lzwnew.h $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h
$(OBJ)/hightile.$o: $(SRC)/hightile.c $(INC)/kplib.h $(INC)/hightile.h $(OBJ)/hightile.$o: $(SRC)/hightile.c $(INC)/kplib.h $(INC)/hightile.h
$(OBJ)/mdsprite.$o: $(SRC)/mdsprite.c $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h $(OBJ)/mdsprite.$o: $(SRC)/mdsprite.c $(SRC)/engine_priv.h $(INC)/polymost.h $(INC)/hightile.h $(INC)/mdsprite.h
$(OBJ)/textfont.$o: $(SRC)/textfont.c $(OBJ)/textfont.$o: $(SRC)/textfont.c
$(OBJ)/smalltextfont.$o: $(SRC)/smalltextfont.c $(OBJ)/smalltextfont.$o: $(SRC)/smalltextfont.c
$(OBJ)/glbuild.$o: $(SRC)/glbuild.c $(INC)/glbuild.h $(INC)/baselayer.h $(OBJ)/glbuild.$o: $(SRC)/glbuild.c $(INC)/glbuild.h $(INC)/baselayer.h
$(OBJ)/kplib.$o: $(SRC)/kplib.c $(INC)/compat.h $(OBJ)/kplib.$o: $(SRC)/kplib.c $(INC)/compat.h
$(OBJ)/fastlz.$o: $(SRC)/fastlz.c $(INC)/fastlz.h $(OBJ)/quicklz.$o: $(SRC)/quicklz.c $(INC)/quicklz.h
$(OBJ)/lzwnew.$o: $(SRC)/lzwnew.c $(OBJ)/lzwnew.$o: $(SRC)/lzwnew.c
$(OBJ)/md4.$o: $(SRC)/md4.c $(INC)/md4.h $(INC)/compat.h $(OBJ)/md4.$o: $(SRC)/md4.c $(INC)/md4.h $(INC)/compat.h
$(OBJ)/mmulti_unstable.$o: $(SRC)/mmulti_unstable.c $(INC)/mmulti_unstable.h $(OBJ)/mmulti_unstable.$o: $(SRC)/mmulti_unstable.c $(INC)/mmulti_unstable.h

View file

@ -72,7 +72,7 @@ ENGINEOBJS= \
$(OBJ)\smalltextfont.$o \ $(OBJ)\smalltextfont.$o \
$(OBJ)\glbuild.$o \ $(OBJ)\glbuild.$o \
$(OBJ)\kplib.$o \ $(OBJ)\kplib.$o \
$(OBJ)\fastlz.$o \ $(OBJ)\quicklz.$o \
$(OBJ)\lzwnew.$o \ $(OBJ)\lzwnew.$o \
$(OBJ)\md4.$o \ $(OBJ)\md4.$o \
$(OBJ)\mmulti_unstable.$o \ $(OBJ)\mmulti_unstable.$o \

View file

@ -3,8 +3,8 @@
ENGINELIB=libengine.a ENGINELIB=libengine.a
EDITORLIB=libbuild.a EDITORLIB=libbuild.a
SDLCONFIG = /usr/local/bin/sdl-config # SDLCONFIG = /usr/local/bin/sdl-config
# SDLCONFIG = sdl-config SDLCONFIG = sdl-config
ifeq ($(wildcard $(SDLCONFIG)),$(SDLCONFIG)) ifeq ($(wildcard $(SDLCONFIG)),$(SDLCONFIG))
SDLROOT = /usr/local SDLROOT = /usr/local

View file

@ -40,7 +40,7 @@ extern "C" {
#define MAXSPRITESONSCREEN 4096 #define MAXSPRITESONSCREEN 4096
#define MAXUNIQHUDID 256 //Extra slots so HUD models can store animation state without messing game sprites #define MAXUNIQHUDID 256 //Extra slots so HUD models can store animation state without messing game sprites
#define RESERVEDPALS 2 // don't forget to increment this when adding reserved pals #define RESERVEDPALS 4 // don't forget to increment this when adding reserved pals
#define DETAILPAL (MAXPALOOKUPS - 1) #define DETAILPAL (MAXPALOOKUPS - 1)
#define GLOWPAL (MAXPALOOKUPS - 2) #define GLOWPAL (MAXPALOOKUPS - 2)
#define SPECULARPAL (MAXPALOOKUPS - 3) #define SPECULARPAL (MAXPALOOKUPS - 3)

View file

@ -36,8 +36,9 @@
#endif #endif
#define USE_ALLOCATOR 1 #define USE_ALLOCATOR 1
// #define REPLACE_SYSTEM_ALLOCATOR #define USE_MAGIC_HEADERS 1
#define USE_MAGIC_HEADERS 0 #define ENABLE_FAST_HEAP_DETECTION 1
#include "nedmalloc.h" #include "nedmalloc.h"
#ifndef TRUE #ifndef TRUE

View file

@ -1,100 +0,0 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
#if defined (__cplusplus)
extern "C" {
#endif
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
*/
int fastlz_compress(const void* input, int length, void* output);
/**
Decompress a block of compressed data and returns the size of the
decompressed block. If error occurs, e.g. the compressed data is
corrupted or the output buffer is not large enough, then 0 (zero)
will be returned instead.
The input buffer and the output buffer can not overlap.
Decompression is memory safe and guaranteed not to write the output buffer
more than what is specified in maxout.
*/
int fastlz_decompress(const void* input, int length, void* output, int maxout);
/**
Compress a block of data in the input buffer and returns the size of
compressed block. The size of input buffer is specified by length. The
minimum input buffer size is 16.
The output buffer must be at least 5% larger than the input buffer
and can not be smaller than 66 bytes.
If the input is not compressible, the return value might be larger than
length (input buffer size).
The input buffer and the output buffer can not overlap.
Compression level can be specified in parameter level. At the moment,
only level 1 and level 2 are supported.
Level 1 is the fastest compression and generally useful for short data.
Level 2 is slightly slower but it gives better compression ratio.
Note that the compressed data, regardless of the level, can always be
decompressed using the function fastlz_decompress above.
*/
int fastlz_compress_level(int level, const void* input, int length, void* output);
#if defined (__cplusplus)
}
#endif
#endif /* FASTLZ_H */

View file

@ -502,7 +502,6 @@ MAX_RELEASE_CHECK_RATE default: 4095 unless not HAVE_MMAP
*/ */
/* Version identifier to allow people to support multiple versions */ /* Version identifier to allow people to support multiple versions */
#ifndef DLMALLOC_VERSION #ifndef DLMALLOC_VERSION
#define DLMALLOC_VERSION 20804 #define DLMALLOC_VERSION 20804
#endif /* DLMALLOC_VERSION */ #endif /* DLMALLOC_VERSION */
@ -1543,9 +1542,7 @@ unsigned char _BitScanReverse(unsigned long *index, unsigned long mask);
initialized in init_mparams. Note that the non-zeroness of "magic" initialized in init_mparams. Note that the non-zeroness of "magic"
also serves as an initialization flag. also serves as an initialization flag.
*/ */
typedef unsigned int flag_t;
typedef unsigned int flag_t; /* The type of various bit flag sets */
struct malloc_params { struct malloc_params {
volatile size_t magic; volatile size_t magic;
size_t page_size; size_t page_size;
@ -1634,16 +1631,14 @@ static void* lastWin32mmap; /* Used as a hint */
#endif /* DEFAULT_GRANULARITY_ALIGNED */ #endif /* DEFAULT_GRANULARITY_ALIGNED */
#ifdef ENABLE_LARGE_PAGES #ifdef ENABLE_LARGE_PAGES
int largepagesavailable = 1; int largepagesavailable = 1;
#ifndef MEM_LARGE_PAGES
#define MEM_LARGE_PAGES 0x20000000
#endif
#endif /* ENABLE_LARGE_PAGES */ #endif /* ENABLE_LARGE_PAGES */
static FORCEINLINE void* win32mmap(size_t size) { static FORCEINLINE void* win32mmap(size_t size) {
void* baseaddress = 0; void* baseaddress = 0;
void* ptr = 0; void* ptr = 0;
#ifdef ENABLE_LARGE_PAGES #ifdef ENABLE_LARGE_PAGES
#ifndef MEM_LARGE_PAGES
#define MEM_LARGE_PAGES 0x20000000
#endif
/* Note that large pages are *always* allocated on a large page boundary. /* Note that large pages are *always* allocated on a large page boundary.
If however granularity is small then don't waste a kernel call if size If however granularity is small then don't waste a kernel call if size
isn't around the size of a large page */ isn't around the size of a large page */
@ -1677,7 +1672,11 @@ static FORCEINLINE void* win32mmap(size_t size) {
#endif #endif
} }
#if DEBUG #if DEBUG
#ifdef ENABLE_LARGE_PAGES
printf("VirtualAlloc returns %p size %u. LargePagesAvailable=%d\n", ptr, size, largepagesavailable);
#else
printf("VirtualAlloc returns %p size %u\n", ptr, size); printf("VirtualAlloc returns %p size %u\n", ptr, size);
#endif
#endif #endif
return (ptr != 0)? ptr: MFAIL; return (ptr != 0)? ptr: MFAIL;
} }
@ -1825,6 +1824,7 @@ static FORCEINLINE int win32munmap(void* ptr, size_t size) {
/* Custom pthread-style spin locks on x86 and x64 for gcc */ /* Custom pthread-style spin locks on x86 and x64 for gcc */
struct pthread_mlock_t { struct pthread_mlock_t {
volatile unsigned int l; volatile unsigned int l;
char cachelinepadding[64];
unsigned int c; unsigned int c;
pthread_t threadid; pthread_t threadid;
}; };
@ -1836,7 +1836,7 @@ struct pthread_mlock_t {
#define TRY_LOCK(sl) pthread_try_lock(sl) #define TRY_LOCK(sl) pthread_try_lock(sl)
#define SPINS_PER_YIELD 63 #define SPINS_PER_YIELD 63
static MLOCK_T malloc_global_mutex = { 0, 0, 0}; static MLOCK_T malloc_global_mutex = { 0, "", 0, 0};
static FORCEINLINE int pthread_acquire_lock (MLOCK_T *sl) { static FORCEINLINE int pthread_acquire_lock (MLOCK_T *sl) {
int spins = 0; int spins = 0;
@ -1924,6 +1924,7 @@ static FORCEINLINE int pthread_try_lock (MLOCK_T *sl) {
/* Custom win32-style spin locks on x86 and x64 for MSC */ /* Custom win32-style spin locks on x86 and x64 for MSC */
struct win32_mlock_t { struct win32_mlock_t {
volatile long l; volatile long l;
char cachelinepadding[64];
unsigned int c; unsigned int c;
long threadid; long threadid;
}; };

View file

@ -1,65 +0,0 @@
#ifndef __MMULTIMSGS_H__
#define __MMULTIMSGS_H__
/*
* Ok, so this header file defines the message bytes and outlines the basic
* message descriptions for out-of-band messages that are common to all games
* that utilize my net code. Once a game determines that it is indeed talking
* to another peer of the same genus, the rest is up to the game itself to
* decide, but for basic stuff, the interfaces will be identical.
*
* Why am I not choosing to implement all this engine-side? Because all the
* games are different and about the only thing they are guaranteed to use in
* common that I can be certain of is the services my net code will provide.
* So, since I can't code anything in particular with every Build game in mind,
* I'm putting handling all the game-visible messages into the game's domain.
* The engine will still handle its own internal messages because the game
* never sees them. Ever.
*
* CMDs are messages sent by a peer to another, and RSPs are the replies.
*
* The master of the network game, regardless if the eventual game is talking
* with a peer-to-peer design or not, shall enumerate each peer as it joins
* and the master will always assign itself peer number 0. This simplifies
* things all-round because each peer that joins automatically knows that
* id 0 is its master and it already knows the master's address. Technically
* every other peer who joins may get a sequential number for its id so maybe
* even transmitting the peer unique ids is unnecessary and we'd be easier
* just sending a number of players, but the less craftiness at this point
* in time, the better.
*
* -- Jonathon
*/
#define MSGPROTOVER 0x00
// 0x00 20031209
#define MSG_CMD_GETGAMEINFO 0x10
// char MSG_CMD_GETGAMEINFO
// char MSGPROTOVER
#define MSG_RSP_BADPROTO 0x11
// char MSG_RSP_BADPROTO
#define MSG_RSP_NOGAME 0x12
// char MSG_RSP_NOGAME
// char[8] gamename
#define MSG_RSP_GAMEINFO 0x13
// char MSG_RSP_GAMEINFO
// char[8] gamename eg. DUKE3DSW/DUKE3D\x00\x00/DUKE3DAT
// ... other information particular to the game
#define MSG_CMD_JOINGAME 0x20
// char MSG_CMD_JOINGAME
#define MSG_RSP_GAMEINPROG 0x21
// char MSG_RSP_GAMEINPROG
#define MSG_RSP_JOINACCEPTED 0x22
// char MSG_RSP_JOINACCEPTED
// short uniqueid
// char numtofollow
// short[numtofollow] peeruid
// ... other information particular to the game
#define MSG_RSP_GAMEFULL 0x23
// char MSG_RSP_GAMEFULL
#endif

View file

@ -32,8 +32,10 @@ DEALINGS IN THE SOFTWARE.
/* See malloc.c.h for what each function does. /* See malloc.c.h for what each function does.
REPLACE_SYSTEM_ALLOCATOR causes nedalloc's functions to be called malloc, REPLACE_SYSTEM_ALLOCATOR on POSIX causes nedalloc's functions to be called
free etc. instead of nedmalloc, nedfree etc. You may or may not want this. malloc, free etc. instead of nedmalloc, nedfree etc. You may or may not want
this. On Windows it causes nedmalloc to patch all loaded DLLs and binaries
to replace usage of the system allocator.
NO_NED_NAMESPACE prevents the functions from being defined in the nedalloc NO_NED_NAMESPACE prevents the functions from being defined in the nedalloc
namespace when in C++ (uses the global namespace instead). namespace when in C++ (uses the global namespace instead).
@ -51,25 +53,62 @@ to each block. nedpfree() and nedprealloc() can then automagically know when
to free a system allocated block. Enabling this typically adds 20-50% to to free a system allocated block. Enabling this typically adds 20-50% to
application memory usage. application memory usage.
USE_ALLOCATOR can be one of these settings: ENABLE_TOLERANT_NEDMALLOC is automatically turned on if REPLACE_SYSTEM_ALLOCATOR
is set or the Windows DLL is being built. This causes nedmalloc to detect when a
system allocator block is passed to it and to handle it appropriately. Note that
without USE_MAGIC_HEADERS there is a very tiny chance that nedmalloc will segfault
on non-Windows builds (it uses Win32 SEH to trap segfaults on Windows and there
is no comparable system on POSIX).
USE_ALLOCATOR can be one of these settings (it defaults to 1):
0: System allocator (nedmalloc now simply acts as a threadcache). 0: System allocator (nedmalloc now simply acts as a threadcache).
WARNING: Intended for DEBUG USE ONLY - not all functions work correctly. WARNING: Intended for DEBUG USE ONLY - not all functions work correctly.
1: dlmalloc 1: dlmalloc
ENABLE_LARGE_PAGES enables support for requesting memory from the system in large
(typically >=2Mb) pages if the host OS supports this. These occupy just a single
TLB entry and can significantly improve performance in large working set applications.
ENABLE_FAST_HEAP_DETECTION enables special logic to detect blocks allocated
by the system heap. This avoids 1.5%-2% overhead when checking for non-nedmalloc
blocks, but it assumes that the NT and glibc heaps function in a very specific
fashion which may not hold true across OS upgrades.
*/ */
#include <stddef.h> /* for size_t */ #include <stddef.h> /* for size_t */
#ifndef NEDMALLOCEXTSPEC #ifndef NEDMALLOCEXTSPEC
#ifdef NEDMALLOC_DLL_EXPORTS #ifdef NEDMALLOC_DLL_EXPORTS
#define NEDMALLOCEXTSPEC extern __declspec(dllexport) #ifdef WIN32
#define NEDMALLOCEXTSPEC extern __declspec(dllexport)
#elif defined(__GNUC__)
#define NEDMALLOCEXTSPEC extern __attribute__ ((visibility("default")))
#endif
#ifndef ENABLE_TOLERANT_NEDMALLOC
#define ENABLE_TOLERANT_NEDMALLOC 1
#endif
#else #else
#define NEDMALLOCEXTSPEC extern #define NEDMALLOCEXTSPEC extern
#endif #endif
#endif #endif
#if __STDC_VERSION__ >= 199901L /* C99 or better */
#define RESTRICT restrict
#else
#if defined(_MSC_VER) && _MSC_VER>=1400
#define RESTRICT __restrict
#endif
#ifdef __GNUC__
#define RESTRICT __restrict
#endif
#endif
#ifndef RESTRICT
#define RESTRICT
#endif
#if defined(_MSC_VER) && _MSC_VER>=1400 #if defined(_MSC_VER) && _MSC_VER>=1400
#define NEDMALLOCPTRATTR __declspec(restrict) #define NEDMALLOCPTRATTR __declspec(restrict)
#define NEDMALLOCNOALIASATTR __declspec(noalias)
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
#define NEDMALLOCPTRATTR __attribute__ ((malloc)) #define NEDMALLOCPTRATTR __attribute__ ((malloc))
@ -77,6 +116,9 @@ USE_ALLOCATOR can be one of these settings:
#ifndef NEDMALLOCPTRATTR #ifndef NEDMALLOCPTRATTR
#define NEDMALLOCPTRATTR #define NEDMALLOCPTRATTR
#endif #endif
#ifndef NEDMALLOCNOALIASATTR
#define NEDMALLOCNOALIASATTR
#endif
#ifndef USE_MAGIC_HEADERS #ifndef USE_MAGIC_HEADERS
#define USE_MAGIC_HEADERS 0 #define USE_MAGIC_HEADERS 0
@ -94,7 +136,10 @@ USE_ALLOCATOR can be one of these settings:
#if USE_ALLOCATOR==0 #if USE_ALLOCATOR==0
#error Cannot combine using the system allocator with replacing the system allocator #error Cannot combine using the system allocator with replacing the system allocator
#endif #endif
#ifndef _WIN32 /* We have a dedidicated patcher for Windows */ #ifndef ENABLE_TOLERANT_NEDMALLOC
#define ENABLE_TOLERANT_NEDMALLOC 1
#endif
#ifndef WIN32 /* We have a dedicated patcher for Windows */
#define nedmalloc malloc #define nedmalloc malloc
#define nedcalloc calloc #define nedcalloc calloc
#define nedrealloc realloc #define nedrealloc realloc
@ -107,23 +152,30 @@ USE_ALLOCATOR can be one of these settings:
#define nedmalloc_footprint malloc_footprint #define nedmalloc_footprint malloc_footprint
#define nedindependent_calloc independent_calloc #define nedindependent_calloc independent_calloc
#define nedindependent_comalloc independent_comalloc #define nedindependent_comalloc independent_comalloc
#ifdef _MSC_VER
#define nedblksize _msize
#endif
#endif #endif
#endif #endif
#ifndef NO_MALLINFO
#define NO_MALLINFO 0
#endif
#if !NO_MALLINFO
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
struct mallinfo; struct nedmallinfo {
size_t arena; /* non-mmapped space allocated from system */
size_t ordblks; /* number of free chunks */
size_t smblks; /* always 0 */
size_t hblks; /* always 0 */
size_t hblkhd; /* space in mmapped regions */
size_t usmblks; /* maximum total allocated space */
size_t fsmblks; /* always 0 */
size_t uordblks; /* total allocated space */
size_t fordblks; /* total free space */
size_t keepcost; /* releasable (via malloc_trim) space */
};
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif
#endif
#if defined(__cplusplus) #if defined(__cplusplus)
#if !defined(NO_NED_NAMESPACE) #if !defined(NO_NED_NAMESPACE)
@ -139,11 +191,11 @@ extern "C" {
/* These are the global functions */ /* These are the global functions */
/* Gets the usable size of an allocated block. Note this will always be bigger than what was /* Gets the usable size of an allocated block. Note this will always be bigger than what was
asked for due to rounding etc. Tries to return zero if this is not a nedmalloc block (though asked for due to rounding etc. Optionally returns 1 in isforeign if the block came from the
one could see a segfault up to 6.25% of the time). On Win32 SEH is used to guarantee that a system allocator - note that there is a small (>0.01%) but real chance of segfault on non-Windows
segfault never happens. systems when passing non-nedmalloc blocks if you don't use USE_MAGIC_HEADERS.
*/ */
NEDMALLOCEXTSPEC size_t nedblksize(void *mem) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem) THROWSPEC;
NEDMALLOCEXTSPEC void nedsetvalue(void *v) THROWSPEC; NEDMALLOCEXTSPEC void nedsetvalue(void *v) THROWSPEC;
@ -152,9 +204,7 @@ NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROW
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC;
NEDMALLOCEXTSPEC void nedfree(void *mem) THROWSPEC; NEDMALLOCEXTSPEC void nedfree(void *mem) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC;
#if !NO_MALLINFO NEDMALLOCEXTSPEC struct nedmallinfo nedmallinfo(void) THROWSPEC;
NEDMALLOCEXTSPEC struct mallinfo nedmallinfo(void) THROWSPEC;
#endif
NEDMALLOCEXTSPEC int nedmallopt(int parno, int value) THROWSPEC; NEDMALLOCEXTSPEC int nedmallopt(int parno, int value) THROWSPEC;
NEDMALLOCEXTSPEC void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC; NEDMALLOCEXTSPEC void* nedmalloc_internals(size_t *granularity, size_t *magic) THROWSPEC;
NEDMALLOCEXTSPEC int nedmalloc_trim(size_t pad) THROWSPEC; NEDMALLOCEXTSPEC int nedmalloc_trim(size_t pad) THROWSPEC;
@ -187,12 +237,20 @@ NEDMALLOCEXTSPEC NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int th
*/ */
NEDMALLOCEXTSPEC void neddestroypool(nedpool *p) THROWSPEC; NEDMALLOCEXTSPEC void neddestroypool(nedpool *p) THROWSPEC;
/* Returns a zero terminated snapshot of threadpools existing at the time of call. Call
nedfree() on the returned list when you are done. Returns zero if there is only the
system pool in existence.
*/
NEDMALLOCEXTSPEC nedpool **nedpoollist() THROWSPEC;
/* Sets a value to be associated with a pool. You can retrieve this value by passing /* Sets a value to be associated with a pool. You can retrieve this value by passing
any memory block allocated from that pool. any memory block allocated from that pool.
*/ */
NEDMALLOCEXTSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC; NEDMALLOCEXTSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC;
/* Gets a previously set value using nedpsetvalue() or zero if memory is unknown. /* Gets a previously set value using nedpsetvalue() or zero if memory is unknown.
Optionally can also retrieve pool. Optionally can also retrieve pool. You can detect an unknown block by the return
being zero and *p being unmodifed.
*/ */
NEDMALLOCEXTSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC; NEDMALLOCEXTSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC;
@ -208,14 +266,13 @@ system pool.
*/ */
NEDMALLOCEXTSPEC void neddisablethreadcache(nedpool *p) THROWSPEC; NEDMALLOCEXTSPEC void neddisablethreadcache(nedpool *p) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmalloc(nedpool *p, size_t size) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPEC;
NEDMALLOCEXTSPEC void nedpfree(nedpool *p, void *mem) THROWSPEC; NEDMALLOCEXTSPEC void nedpfree(nedpool *p, void *mem) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC;
#if !NO_MALLINFO NEDMALLOCEXTSPEC struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC;
NEDMALLOCEXTSPEC struct mallinfo nedpmallinfo(nedpool *p) THROWSPEC;
#endif
NEDMALLOCEXTSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC; NEDMALLOCEXTSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC;
NEDMALLOCEXTSPEC int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC; NEDMALLOCEXTSPEC int nedpmalloc_trim(nedpool *p, size_t pad) THROWSPEC;
NEDMALLOCEXTSPEC void nedpmalloc_stats(nedpool *p) THROWSPEC; NEDMALLOCEXTSPEC void nedpmalloc_stats(nedpool *p) THROWSPEC;
@ -223,6 +280,7 @@ NEDMALLOCEXTSPEC size_t nedpmalloc_footprint(nedpool *p) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_t elemsize, void **chunks) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC;
NEDMALLOCEXTSPEC NEDMALLOCPTRATTR char * nedstrdup(const char *str) THROWSPEC; NEDMALLOCEXTSPEC NEDMALLOCPTRATTR char * nedstrdup(const char *str) THROWSPEC;
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View file

@ -0,0 +1,150 @@
#ifndef QLZ_HEADER
#define QLZ_HEADER
// Fast data compression library
// Copyright (C) 2006-2009 Lasse Mikkel Reinhold
// lar@quicklz.com
//
// QuickLZ can be used for free under the GPL-1 or GPL-2 license (where anything
// released into public must be open source) or under a commercial license if such
// has been acquired (see http://www.quicklz.com/order.html). The commercial license
// does not cover derived or ported versions created by third parties under GPL.
// You can edit following user settings. Data must be decompressed with the same
// setting of QLZ_COMPRESSION_LEVEL and QLZ_STREAMING_BUFFER as it was compressed
// (see manual). If QLZ_STREAMING_BUFFER > 0, scratch buffers must be initially
// zeroed out (see manual). First #ifndef makes it possible to define settings from
// the outside like the compiler command line.
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// 1.5.0 BETA 2
#ifndef QLZ_COMPRESSION_LEVEL
#define QLZ_COMPRESSION_LEVEL 1
//#define QLZ_COMPRESSION_LEVEL 2
//#define QLZ_COMPRESSION_LEVEL 3
#define QLZ_STREAMING_BUFFER 0
//#define QLZ_STREAMING_BUFFER 100000
//#define QLZ_STREAMING_BUFFER 1000000
//#define QLZ_MEMORY_SAFE
#endif
#define QLZ_VERSION_MAJOR 1
#define QLZ_VERSION_MINOR 5
#define QLZ_VERSION_REVISION 0
// Using size_t, memset() and memcpy()
#include <string.h>
// Verify compression level
#if QLZ_COMPRESSION_LEVEL != 1 && QLZ_COMPRESSION_LEVEL != 2 && QLZ_COMPRESSION_LEVEL != 3
#error QLZ_COMPRESSION_LEVEL must be 1, 2 or 3
#endif
typedef unsigned int ui32;
typedef unsigned short int ui16;
// Decrease QLZ_POINTERS for level 3 to increase compression speed. Do not touch any other values!
#if QLZ_COMPRESSION_LEVEL == 1
#define QLZ_POINTERS 1
#define QLZ_HASH_VALUES 4096
#elif QLZ_COMPRESSION_LEVEL == 2
#define QLZ_POINTERS 4
#define QLZ_HASH_VALUES 2048
#elif QLZ_COMPRESSION_LEVEL == 3
#define QLZ_POINTERS 16
#define QLZ_HASH_VALUES 4096
#endif
// Detect if pointer size is 64-bit. It's not fatal if some 64-bit target is not detected because this is only for adding an optional 64-bit optimization.
#if defined _LP64 || defined __LP64__ || defined __64BIT__ || _ADDR64 || defined _WIN64 || defined __arch64__ || __WORDSIZE == 64 || (defined __sparc && defined __sparcv9) || defined __x86_64 || defined __amd64 || defined __x86_64__ || defined _M_X64 || defined _M_IA64 || defined __ia64 || defined __IA64__
#define QLZ_PTR_64
#endif
// hash entry
typedef struct
{
#if QLZ_COMPRESSION_LEVEL == 1
ui32 cache;
#if defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0
unsigned int offset;
#else
const unsigned char *offset;
#endif
#else
const unsigned char *offset[QLZ_POINTERS];
#endif
} qlz_hash_compress;
typedef struct
{
#if QLZ_COMPRESSION_LEVEL == 1
const unsigned char *offset;
#else
const unsigned char *offset[QLZ_POINTERS];
#endif
} qlz_hash_decompress;
// states
typedef struct
{
#if QLZ_STREAMING_BUFFER > 0
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
#endif
size_t stream_counter;
qlz_hash_compress hash[QLZ_HASH_VALUES];
unsigned char hash_counter[QLZ_HASH_VALUES];
} qlz_state_compress;
#if QLZ_COMPRESSION_LEVEL == 1 || QLZ_COMPRESSION_LEVEL == 2
typedef struct
{
#if QLZ_STREAMING_BUFFER > 0
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
#endif
qlz_hash_decompress hash[QLZ_HASH_VALUES];
unsigned char hash_counter[QLZ_HASH_VALUES];
size_t stream_counter;
} qlz_state_decompress;
#elif QLZ_COMPRESSION_LEVEL == 3
typedef struct
{
#if QLZ_STREAMING_BUFFER > 0
unsigned char stream_buffer[QLZ_STREAMING_BUFFER];
#endif
qlz_hash_decompress hash[QLZ_HASH_VALUES];
size_t stream_counter;
} qlz_state_decompress;
#endif
#if defined (__cplusplus)
extern "C" {
#endif
// Public functions of QuickLZ
size_t qlz_size_decompressed(const char *source);
size_t qlz_size_compressed(const char *source);
size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state);
size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state);
int qlz_get_setting(int setting);
extern qlz_state_compress *state_compress;
extern qlz_state_decompress *state_decompress;
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -11,7 +11,7 @@
#include "scriptfile.h" #include "scriptfile.h"
#include "cache1d.h" #include "cache1d.h"
#include "kplib.h" #include "kplib.h"
#include "fastlz.h" #include "quicklz.h"
enum enum
{ {
@ -677,7 +677,7 @@ static int32_t defsparser(scriptfile *script)
tilesizx[tile] = xsiz; tilesizx[tile] = xsiz;
tilesizy[tile] = ysiz; tilesizy[tile] = ysiz;
faketilesiz[tile] = fastlz_compress(ftd, xsiz*ysiz, faketiledata[tile]); faketilesiz[tile] = qlz_compress(ftd, faketiledata[tile], xsiz*ysiz, state_compress);
xoffset = clamp(xoffset, -128, 127); xoffset = clamp(xoffset, -128, 127);
picanm[tile] = (picanm[tile]&0xffff00ff)+((xoffset&255)<<8); picanm[tile] = (picanm[tile]&0xffff00ff)+((xoffset&255)<<8);
@ -728,7 +728,7 @@ static int32_t defsparser(scriptfile *script)
{ {
tilesizx[tile] = xsiz; tilesizx[tile] = xsiz;
tilesizy[tile] = ysiz; tilesizy[tile] = ysiz;
faketilesiz[tile] = fastlz_compress(ftd, xsiz*ysiz, faketiledata[tile]); faketilesiz[tile] = qlz_compress(ftd, faketiledata[tile], xsiz*ysiz, state_compress);
picanm[tile] = 0; picanm[tile] = 0;
j = 15; while ((j > 1) && (pow2long[j] > xsiz)) j--; j = 15; while ((j > 1) && (pow2long[j] > xsiz)) j--;

View file

@ -17,7 +17,7 @@
#include "a.h" #include "a.h"
#include "osd.h" #include "osd.h"
#include "crc32.h" #include "crc32.h"
#include "fastlz.h" #include "quicklz.h"
#include "baselayer.h" #include "baselayer.h"
#include "scriptfile.h" #include "scriptfile.h"
@ -132,6 +132,9 @@ int32_t circlewall=-1;
char cachedebug = 0; char cachedebug = 0;
qlz_state_compress *state_compress = NULL;
qlz_state_decompress *state_decompress = NULL;
#if defined(_MSC_VER) && !defined(NOASM) #if defined(_MSC_VER) && !defined(NOASM)
// //
@ -5493,6 +5496,9 @@ int32_t preinitengine(void)
// this shite is to help get around data segment size limits on some platforms // this shite is to help get around data segment size limits on some platforms
state_compress = (qlz_state_compress *)Bmalloc(sizeof(qlz_state_compress));
state_decompress = (qlz_state_decompress *)Bmalloc(sizeof(qlz_state_decompress));
#ifdef DYNALLOC_ARRAYS #ifdef DYNALLOC_ARRAYS
sector = Bcalloc(MAXSECTORS,sizeof(sectortype)); sector = Bcalloc(MAXSECTORS,sizeof(sectortype));
wall = Bcalloc(MAXWALLS,sizeof(walltype)); wall = Bcalloc(MAXWALLS,sizeof(walltype));
@ -5657,6 +5663,9 @@ void uninitengine(void)
if (spritesmooth != NULL) if (spritesmooth != NULL)
Bfree(spritesmooth); Bfree(spritesmooth);
#endif #endif
if (state_compress) Bfree(state_compress);
if (state_decompress) Bfree(state_decompress);
} }
@ -7967,7 +7976,7 @@ void loadtile(int16_t tilenume)
if (faketilesiz[tilenume] == -1) if (faketilesiz[tilenume] == -1)
Bmemset((char *)waloff[tilenume],0,dasiz); Bmemset((char *)waloff[tilenume],0,dasiz);
else if (faketiledata[tilenume] != NULL) else if (faketiledata[tilenume] != NULL)
fastlz_decompress(faketiledata[tilenume], faketilesiz[tilenume], (char *)waloff[tilenume], dasiz); qlz_decompress(faketiledata[tilenume], (char *)waloff[tilenume], state_decompress);
faketimerhandler(); faketimerhandler();
return; return;
} }

View file

@ -1,551 +0,0 @@
/*
FastLZ - lightning-fast lossless compression library
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2006 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2005 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR)
/*
* Always check for bound when decompressing.
* Generally it is best to leave it defined.
*/
#define FASTLZ_SAFE
/*
* Give hints to the compiler for branch prediction optimization.
*/
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
/*
* Prevent accessing more than 8-bit at once, except on x86 architectures.
*/
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_STRICT_ALIGN
#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */
#undef FASTLZ_STRICT_ALIGN
#elif defined(_M_IX86) /* Intel, MSVC */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__386)
#undef FASTLZ_STRICT_ALIGN
#elif defined(_X86_) /* MinGW */
#undef FASTLZ_STRICT_ALIGN
#elif defined(__I86__) /* Digital Mars */
#undef FASTLZ_STRICT_ALIGN
#endif
#endif
/*
* FIXME: use preprocessor magic to set this on different platforms!
*/
typedef unsigned char flzuint8;
typedef unsigned short flzuint16;
typedef unsigned int flzuint32;
/* prototypes */
int fastlz_compress(const void* input, int length, void* output);
int fastlz_compress_level(int level, const void* input, int length, void* output);
int fastlz_decompress(const void* input, int length, void* output, int maxout);
#define MAX_COPY 32
#define MAX_LEN 264 /* 256 + 8 */
#define MAX_DISTANCE 8192
#if !defined(FASTLZ_STRICT_ALIGN)
#define FASTLZ_READU16(p) *((const flzuint16*)(p))
#else
#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8)
#endif
#define HASH_LOG 13
#define HASH_SIZE (1<< HASH_LOG)
#define HASH_MASK (HASH_SIZE-1)
#define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; }
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 1
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz1_compress
#define FASTLZ_DECOMPRESSOR fastlz1_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
#undef FASTLZ_LEVEL
#define FASTLZ_LEVEL 2
#undef MAX_DISTANCE
#define MAX_DISTANCE 8191
#define MAX_FARDISTANCE (65535+MAX_DISTANCE-1)
#undef FASTLZ_COMPRESSOR
#undef FASTLZ_DECOMPRESSOR
#define FASTLZ_COMPRESSOR fastlz2_compress
#define FASTLZ_DECOMPRESSOR fastlz2_decompress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output);
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout);
#include "fastlz.c"
int fastlz_compress(const void* input, int length, void* output)
{
/* for short block, choose fastlz1 */
if(length < 65536)
return fastlz1_compress(input, length, output);
/* else... */
return fastlz2_compress(input, length, output);
}
int fastlz_decompress(const void* input, int length, void* output, int maxout)
{
/* magic identifier for compression level */
int level = ((*(const flzuint8*)input) >> 5) + 1;
if(level == 1)
return fastlz1_decompress(input, length, output, maxout);
if(level == 2)
return fastlz2_decompress(input, length, output, maxout);
/* unknown level, trigger error */
return 0;
}
int fastlz_compress_level(int level, const void* input, int length, void* output)
{
if(level == 1)
return fastlz1_compress(input, length, output);
if(level == 2)
return fastlz2_compress(input, length, output);
return 0;
}
#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_bound = ip + length - 2;
const flzuint8* ip_limit = ip + length - 12;
flzuint8* op = (flzuint8*) output;
const flzuint8* htab[HASH_SIZE];
const flzuint8** hslot;
flzuint32 hval;
flzuint32 copy;
/* sanity check */
if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
{
if(length)
{
/* create literal copy only */
*op++ = length-1;
ip_bound++;
while(ip <= ip_bound)
*op++ = *ip++;
return length+1;
}
else
return 0;
}
/* initializes hash table */
for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
*hslot = ip;
/* we start with literal copy */
copy = 2;
*op++ = MAX_COPY-1;
*op++ = *ip++;
*op++ = *ip++;
/* main loop */
while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
{
const flzuint8* ref;
flzuint32 distance;
/* minimum match length */
flzuint32 len = 3;
/* comparison starting-point */
const flzuint8* anchor = ip;
/* check for a run */
#if FASTLZ_LEVEL==2
if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
{
distance = 1;
ip += 3;
ref = anchor - 1 + 3;
goto match;
}
#endif
/* find potential match */
HASH_FUNCTION(hval,ip);
hslot = htab + hval;
ref = htab[hval];
/* calculate distance to the match */
distance = anchor - ref;
/* update hash table */
*hslot = anchor;
/* is this a match? check the first 3 bytes */
if(distance==0 ||
#if FASTLZ_LEVEL==1
(distance >= MAX_DISTANCE) ||
#else
(distance >= MAX_FARDISTANCE) ||
#endif
*ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
goto literal;
#if FASTLZ_LEVEL==2
/* far, needs at least 5-byte match */
if(distance >= MAX_DISTANCE)
{
if(*ip++ != *ref++ || *ip++!= *ref++)
goto literal;
len += 2;
}
match:
#endif
/* last matched byte */
ip = anchor + len;
/* distance is biased */
distance--;
if(!distance)
{
/* zero distance means a run */
flzuint8 x = ip[-1];
while(ip < ip_bound)
if(*ref++ != x) break; else ip++;
}
else
for(;;)
{
/* safe because the outer check against ip limit */
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
if(*ref++ != *ip++) break;
while(ip < ip_bound)
if(*ref++ != *ip++) break;
break;
}
/* if we have copied something, adjust the copy count */
if(copy)
/* copy is biased, '0' means 1 byte copy */
*(op-copy-1) = copy-1;
else
/* back, to overwrite the copy count */
op--;
/* reset literal counter */
copy = 0;
/* length is biased, '1' means a match of 3 bytes */
ip -= 3;
len = ip - anchor;
/* encode the match */
#if FASTLZ_LEVEL==2
if(distance < MAX_DISTANCE)
{
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = (distance & 255);
}
}
else
{
/* far away, but not yet in the another galaxy... */
if(len < 7)
{
distance -= MAX_DISTANCE;
*op++ = (len << 5) + 31;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
else
{
distance -= MAX_DISTANCE;
*op++ = (7 << 5) + 31;
for(len-=7; len >= 255; len-= 255)
*op++ = 255;
*op++ = len;
*op++ = 255;
*op++ = distance >> 8;
*op++ = distance & 255;
}
}
#else
if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
while(len > MAX_LEN-2)
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = MAX_LEN - 2 - 7 -2;
*op++ = (distance & 255);
len -= MAX_LEN-2;
}
if(len < 7)
{
*op++ = (len << 5) + (distance >> 8);
*op++ = (distance & 255);
}
else
{
*op++ = (7 << 5) + (distance >> 8);
*op++ = len - 7;
*op++ = (distance & 255);
}
#endif
/* update the hash at match boundary */
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
HASH_FUNCTION(hval,ip);
htab[hval] = ip++;
/* assuming literal copy */
*op++ = MAX_COPY-1;
continue;
literal:
*op++ = *anchor++;
ip = anchor;
copy++;
if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* left-over as literal copy */
ip_bound++;
while(ip <= ip_bound)
{
*op++ = *ip++;
copy++;
if(copy == MAX_COPY)
{
copy = 0;
*op++ = MAX_COPY-1;
}
}
/* if we have copied something, adjust the copy length */
if(copy)
*(op-copy-1) = copy-1;
else
op--;
#if FASTLZ_LEVEL==2
/* marker for fastlz2 */
*(flzuint8*)output |= (1 << 5);
#endif
return op - (flzuint8*)output;
}
static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout)
{
const flzuint8* ip = (const flzuint8*) input;
const flzuint8* ip_limit = ip + length;
flzuint8* op = (flzuint8*) output;
flzuint8* op_limit = op + maxout;
flzuint32 ctrl = (*ip++) & 31;
int loop = 1;
do
{
const flzuint8* ref = op;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 8;
if(ctrl >= 32)
{
#if FASTLZ_LEVEL==2
flzuint8 code;
#endif
len--;
ref -= ofs;
if (len == 7-1)
#if FASTLZ_LEVEL==1
len += *ip++;
ref -= *ip++;
#else
do
{
code = *ip++;
len += code;
} while (code==255);
code = *ip++;
ref -= code;
/* match from 16-bit distance */
if(FASTLZ_UNEXPECT_CONDITIONAL(code==255))
if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8)))
{
ofs = (*ip++) << 8;
ofs += *ip++;
ref = op - ofs - MAX_DISTANCE;
}
#endif
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output))
return 0;
#endif
if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
ctrl = *ip++;
else
loop = 0;
if(ref == op)
{
/* optimize copy for a run */
flzuint8 b = ref[-1];
*op++ = b;
*op++ = b;
*op++ = b;
for(; len; --len)
*op++ = b;
}
else
{
#if !defined(FASTLZ_STRICT_ALIGN)
const flzuint16* p;
flzuint16* q;
#endif
/* copy from reference */
ref--;
*op++ = *ref++;
*op++ = *ref++;
*op++ = *ref++;
#if !defined(FASTLZ_STRICT_ALIGN)
/* copy a byte, so that now it's word aligned */
if(len & 1)
{
*op++ = *ref++;
len--;
}
/* copy 16-bit at once */
q = (flzuint16*) op;
op += len;
p = (const flzuint16*) ref;
for(len>>=1; len > 4; len-=4)
{
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
*q++ = *p++;
}
for(; len; --len)
*q++ = *p++;
#else
for(; len; --len)
*op++ = *ref++;
#endif
}
}
else
{
ctrl++;
#ifdef FASTLZ_SAFE
if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit))
return 0;
if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit))
return 0;
#endif
*op++ = *ip++;
for(--ctrl; ctrl; ctrl--)
*op++ = *ip++;
loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit);
if(loop)
ctrl = *ip++;
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
return op - (flzuint8*)output;
}
#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */

View file

@ -22,26 +22,23 @@ char hicfirstinit = 0;
// //
hicreplctyp * hicfindsubst(int32_t picnum, int32_t palnum, int32_t skybox) hicreplctyp * hicfindsubst(int32_t picnum, int32_t palnum, int32_t skybox)
{ {
hicreplctyp *hr; if (!hicfirstinit || (uint32_t)picnum >= (uint32_t)MAXTILES) return NULL;
if (!hicfirstinit) return NULL;
if ((uint32_t)picnum >= (uint32_t)MAXTILES) return NULL;
do do
{ {
for (hr = hicreplc[picnum]; hr; hr = hr->next) if (skybox)
{ {
if (hr->palnum == palnum) hicreplctyp *hr = hicreplc[picnum];
{ for (; hr; hr = hr->next)
if (skybox) if (hr->palnum == palnum && hr->skybox && !hr->skybox->ignore)
{ return hr;
if (hr->skybox && !hr->skybox->ignore) return hr; }
} else
else {
{ hicreplctyp *hr = hicreplc[picnum];
if (!hr->ignore) return hr; for (; hr; hr = hr->next)
} if (hr->palnum == palnum && !hr->ignore)
} return hr;
} }
if (!palnum || palnum >= (MAXPALOOKUPS - RESERVEDPALS)) break; if (!palnum || palnum >= (MAXPALOOKUPS - RESERVEDPALS)) break;

View file

@ -35,20 +35,25 @@ DEALINGS IN THE SOFTWARE.
#pragma warning(disable:4706) /* assignment within conditional expression */ #pragma warning(disable:4706) /* assignment within conditional expression */
#endif #endif
/*#define FULLSANITYCHECKS*/
#define USE_ALLOCATOR 1 #define USE_ALLOCATOR 1
// #define REPLACE_SYSTEM_ALLOCATOR #define USE_MAGIC_HEADERS 1
#define USE_MAGIC_HEADERS 0
#define MAXTHREADSINPOOL 1 #define MAXTHREADSINPOOL 1
#define FINEGRAINEDBINS 1 #define FINEGRAINEDBINS 1
#define ENABLE_LARGE_PAGES #define ENABLE_LARGE_PAGES 1
#define ENABLE_FAST_HEAP_DETECTION 1
#ifndef UNREFERENCED_PARAMETER /*#define ENABLE_TOLERANT_NEDMALLOC 1*/
#define UNREFERENCED_PARAMETER(x) x=x /*#define ENABLE_FAST_HEAP_DETECTION 1*/
/*#define FULLSANITYCHECKS*/
/* If link time code generation is on, don't force or prevent inlining */
#if defined(_MSC_VER) && defined(NEDMALLOC_DLL_EXPORTS)
#define FORCEINLINE
#define NOINLINE
#endif #endif
#include "nedmalloc.h" #include "nedmalloc.h"
#ifdef _WIN32 #ifdef WIN32
#include <malloc.h> #include <malloc.h>
#include <stddef.h> #include <stddef.h>
#endif #endif
@ -85,7 +90,6 @@ DEALINGS IN THE SOFTWARE.
/*#define USE_SPIN_LOCKS 0*/ /*#define USE_SPIN_LOCKS 0*/
/*#define FORCEINLINE*/
#include "malloc.c.h" #include "malloc.c.h"
#ifdef NDEBUG /* Disable assert checking on release builds */ #ifdef NDEBUG /* Disable assert checking on release builds */
#undef DEBUG #undef DEBUG
@ -118,7 +122,8 @@ DEALINGS IN THE SOFTWARE.
#define THREADCACHEMAXFREESPACE (512*1024*4) #define THREADCACHEMAXFREESPACE (512*1024*4)
#endif #endif
#ifdef _WIN32
#ifdef WIN32
#define TLSVAR DWORD #define TLSVAR DWORD
#define TLSALLOC(k) (*(k)=TlsAlloc(), TLS_OUT_OF_INDEXES==*(k)) #define TLSALLOC(k) (*(k)=TlsAlloc(), TLS_OUT_OF_INDEXES==*(k))
#define TLSFREE(k) (!TlsFree(k)) #define TLSFREE(k) (!TlsFree(k))
@ -159,11 +164,14 @@ static void *unsupported_operation(const char *opname) THROWSPEC
} }
static size_t mspacecounter=(size_t) 0xdeadbeef; static size_t mspacecounter=(size_t) 0xdeadbeef;
#endif #endif
#ifndef ENABLE_FAST_HEAP_DETECTION
static void *RESTRICT leastusedaddress;
static size_t largestusedblock;
#endif
static FORCEINLINE void *CallMalloc(void *mspace, size_t size, size_t alignment) THROWSPEC static FORCEINLINE void *CallMalloc(void *RESTRICT mspace, size_t size, size_t alignment) THROWSPEC
{ {
void *ret=0; void *RESTRICT ret=0;
UNREFERENCED_PARAMETER(alignment);
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
size_t *_ret=0; size_t *_ret=0;
size+=alignment+3*sizeof(size_t); size+=alignment+3*sizeof(size_t);
@ -172,6 +180,14 @@ static FORCEINLINE void *CallMalloc(void *mspace, size_t size, size_t alignment)
ret=malloc(size); ret=malloc(size);
#elif USE_ALLOCATOR==1 #elif USE_ALLOCATOR==1
ret=mspace_malloc((mstate) mspace, size); ret=mspace_malloc((mstate) mspace, size);
#ifndef ENABLE_FAST_HEAP_DETECTION
if(ret)
{
size_t truesize=chunksize(mem2chunk(ret));
if(!leastusedaddress || (void *)((mstate) mspace)->least_addr<leastusedaddress) leastusedaddress=(void *)((mstate) mspace)->least_addr;
if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1);
}
#endif
#endif #endif
if(!ret) return 0; if(!ret) return 0;
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
@ -180,23 +196,30 @@ static FORCEINLINE void *CallMalloc(void *mspace, size_t size, size_t alignment)
if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1)); if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1));
for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *)"NEDMALOC"; for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *)"NEDMALOC";
_ret[0]=(size_t) mspace; _ret[0]=(size_t) mspace;
_ret[1]=size; _ret[1]=size-3*sizeof(size_t);
#endif #endif
return ret; return ret;
} }
static FORCEINLINE void *CallCalloc(void *mspace, size_t no, size_t size, size_t alignment) THROWSPEC static FORCEINLINE void *CallCalloc(void *RESTRICT mspace, size_t size, size_t alignment) THROWSPEC
{ {
void *ret=0; void *RESTRICT ret=0;
UNREFERENCED_PARAMETER(alignment);
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
size_t *_ret=0; size_t *_ret=0;
size+=alignment+3*sizeof(size_t); size+=alignment+3*sizeof(size_t);
#endif #endif
#if USE_ALLOCATOR==0 #if USE_ALLOCATOR==0
ret=calloc(no, size); ret=calloc(1, size);
#elif USE_ALLOCATOR==1 #elif USE_ALLOCATOR==1
ret=mspace_calloc((mstate) mspace, no, size); ret=mspace_calloc((mstate) mspace, 1, size);
#ifndef ENABLE_FAST_HEAP_DETECTION
if(ret)
{
size_t truesize=chunksize(mem2chunk(ret));
if(!leastusedaddress || (void *)((mstate) mspace)->least_addr<leastusedaddress) leastusedaddress=(void *)((mstate) mspace)->least_addr;
if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1);
}
#endif
#endif #endif
if(!ret) return 0; if(!ret) return 0;
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
@ -205,39 +228,52 @@ static FORCEINLINE void *CallCalloc(void *mspace, size_t no, size_t size, size_t
if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1)); if(alignment) ret=(void *)(((size_t) ret+alignment-1)&~(alignment-1));
for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC"; for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC";
_ret[0]=(size_t) mspace; _ret[0]=(size_t) mspace;
_ret[1]=size; _ret[1]=size-3*sizeof(size_t);
#endif #endif
return ret; return ret;
} }
static FORCEINLINE void *CallRealloc(void *mspace, void *mem, size_t size) THROWSPEC static FORCEINLINE void *CallRealloc(void *RESTRICT mspace, void *RESTRICT mem, int isforeign, size_t oldsize, size_t newsize) THROWSPEC
{ {
void *ret=0; void *RESTRICT ret=0;
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
mstate oldmspace=0; mstate oldmspace=0;
size_t *_ret=0, *_mem=(size_t *) mem-3, oldsize=0; size_t *_ret=0, *_mem=(size_t *) mem-3;
if(_mem[0]!=*(size_t *) "NEDMALOC") #endif
if(isforeign)
{ /* Transfer */ { /* Transfer */
if((ret=CallMalloc(mspace, size, 0))) #if USE_MAGIC_HEADERS
{ /* It's probably safe to copy size bytes from mem - can't do much different */ assert(_mem[0]!=*(size_t *) "NEDMALOC");
#endif
if((ret=CallMalloc(mspace, newsize, 0)))
{
#if defined(DEBUG) #if defined(DEBUG)
printf("*** nedmalloc frees system allocated block %p\n", mem); printf("*** nedmalloc frees system allocated block %p\n", mem);
#endif #endif
memcpy(ret, mem, size); memcpy(ret, mem, oldsize<newsize ? oldsize : newsize);
free(mem); free(mem);
} }
return ret; return ret;
} }
size+=3*sizeof(size_t); #if USE_MAGIC_HEADERS
assert(_mem[0]==*(size_t *) "NEDMALOC");
newsize+=3*sizeof(size_t);
oldmspace=(mstate) _mem[1]; oldmspace=(mstate) _mem[1];
oldsize=_mem[2]; assert(oldsize>=_mem[2]);
for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=0); for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=*(size_t *) "nedmaloc");
mem=(void *)(++_mem); mem=(void *)(++_mem);
#endif #endif
#if USE_ALLOCATOR==0 #if USE_ALLOCATOR==0
ret=realloc(mem, size); ret=realloc(mem, newsize);
#elif USE_ALLOCATOR==1 #elif USE_ALLOCATOR==1
ret=mspace_realloc((mstate) mspace, mem, size); ret=mspace_realloc((mstate) mspace, mem, newsize);
#ifndef ENABLE_FAST_HEAP_DETECTION
if(ret)
{
size_t truesize=chunksize(mem2chunk(ret));
if(!largestusedblock || truesize>largestusedblock) largestusedblock=(truesize+mparams.page_size) & ~(mparams.page_size-1);
}
#endif
#endif #endif
if(!ret) if(!ret)
{ /* Put it back the way it was */ { /* Put it back the way it was */
@ -251,27 +287,33 @@ static FORCEINLINE void *CallRealloc(void *mspace, void *mem, size_t size) THROW
ret=(void *)(_ret+3); ret=(void *)(_ret+3);
for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC"; for(; _ret<(size_t *)ret-2; _ret++) *_ret=*(size_t *) "NEDMALOC";
_ret[0]=(size_t) mspace; _ret[0]=(size_t) mspace;
_ret[1]=size; _ret[1]=newsize-3*sizeof(size_t);
#endif #endif
return ret; return ret;
} }
static FORCEINLINE void CallFree(void *mspace, void *mem) THROWSPEC static FORCEINLINE void CallFree(void *RESTRICT mspace, void *RESTRICT mem, int isforeign) THROWSPEC
{ {
#if USE_MAGIC_HEADERS #if USE_MAGIC_HEADERS
mstate oldmspace=0; mstate oldmspace=0;
size_t *_mem=(size_t *) mem-3, oldsize=0; size_t *_mem=(size_t *) mem-3, oldsize=0;
if(_mem[0]!=*(size_t *) "NEDMALOC") #endif
if(isforeign)
{ {
#if USE_MAGIC_HEADERS
assert(_mem[0]!=*(size_t *) "NEDMALOC");
#endif
#if defined(DEBUG) #if defined(DEBUG)
printf("*** nedmalloc frees system allocated block %p\n", mem); printf("*** nedmalloc frees system allocated block %p\n", mem);
#endif #endif
free(mem); free(mem);
return; return;
} }
#if USE_MAGIC_HEADERS
assert(_mem[0]==*(size_t *) "NEDMALOC");
oldmspace=(mstate) _mem[1]; oldmspace=(mstate) _mem[1];
oldsize=_mem[2]; oldsize=_mem[2];
for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=0); for(; *_mem==*(size_t *) "NEDMALOC"; *_mem--=*(size_t *) "nedmaloc");
mem=(void *)(++_mem); mem=(void *)(++_mem);
#endif #endif
#if USE_ALLOCATOR==0 #if USE_ALLOCATOR==0
@ -281,7 +323,7 @@ static FORCEINLINE void CallFree(void *mspace, void *mem) THROWSPEC
#endif #endif
} }
size_t nedblksize(void *mem) THROWSPEC static NEDMALLOCNOALIASATTR mstate nedblkmstate(void *RESTRICT mem) THROWSPEC
{ {
if(mem) if(mem)
{ {
@ -289,9 +331,7 @@ size_t nedblksize(void *mem) THROWSPEC
size_t *_mem=(size_t *) mem-3; size_t *_mem=(size_t *) mem-3;
if(_mem[0]==*(size_t *) "NEDMALOC") if(_mem[0]==*(size_t *) "NEDMALOC")
{ {
// mstate mspace=(mstate) _mem[1]; return (mstate) _mem[1];
size_t size=_mem[2];
return size-3*sizeof(size_t);
} }
else return 0; else return 0;
#else #else
@ -299,6 +339,58 @@ size_t nedblksize(void *mem) THROWSPEC
/* Fail everything */ /* Fail everything */
return 0; return 0;
#elif USE_ALLOCATOR==1 #elif USE_ALLOCATOR==1
#ifdef ENABLE_FAST_HEAP_DETECTION
#ifdef WIN32
/* On Windows for RELEASE both x86 and x64 the NT heap precedes each block with an eight byte header
which looks like:
normal: 4 bytes of size, 4 bytes of [char < 64, char < 64, char < 64 bit 0 always set, char random ]
mmaped: 4 bytes of size 4 bytes of [zero, zero, 0xb, zero ]
On Windows for DEBUG both x86 and x64 the preceding four bytes is always 0xfdfdfdfd (no man's land).
*/
#pragma pack(push, 1)
struct _HEAP_ENTRY
{
USHORT Size;
USHORT PreviousSize;
UCHAR Cookie; /* SegmentIndex */
UCHAR Flags; /* always bit 0 (HEAP_ENTRY_BUSY). bit 1=(HEAP_ENTRY_EXTRA_PRESENT), bit 2=normal block (HEAP_ENTRY_FILL_PATTERN), bit 3=mmap block (HEAP_ENTRY_VIRTUAL_ALLOC). Bit 4 (HEAP_ENTRY_LAST_ENTRY) could be set */
UCHAR UnusedBytes;
UCHAR SmallTagIndex; /* fastbin index. Always one of 0x02, 0x03, 0x04 < 0x80 */
} *RESTRICT he=((struct _HEAP_ENTRY *) mem)-1;
#pragma pack(pop)
unsigned int header=((unsigned int *)mem)[-1], mask1=0x8080E100, result1, mask2=0xFFFFFF06, result2;
result1=header & mask1; /* Positive testing for NT heap */
result2=header & mask2; /* Positive testing for dlmalloc */
if(result1==0x00000100 && result2!=0x00000102)
{ /* This is likely a NT heap block */
return 0;
}
#endif
#ifdef __linux__
/* On Linux glibc uses ptmalloc2 (really dlmalloc) just as we do, but prev_foot contains rubbish
when the preceding block is allocated because ptmalloc2 finds the local mstate by rounding the ptr
down to the nearest megabyte. It's like dlmalloc with FOOTERS disabled. */
mchunkptr p=mem2chunk(mem);
mstate fm=get_mstate_for(p);
/* If it's a ptmalloc2 block, fm is likely to be some crazy value */
if(!is_aligned(fm)) return 0;
if((size_t)mem-(size_t)fm>=(size_t)1<<(SIZE_T_BITSIZE-1)) return 0;
if(ok_magic(fm))
return fm;
else
return 0;
if(1) { }
#endif
else
{
mchunkptr p=mem2chunk(mem);
mstate fm=get_mstate_for(p);
assert(ok_magic(fm)); /* If this fails, someone tried to free a block twice */
if(ok_magic(fm))
return fm;
}
#else
#ifdef _MSC_VER #ifdef _MSC_VER
__try __try
#endif #endif
@ -309,44 +401,109 @@ size_t nedblksize(void *mem) THROWSPEC
mchunkptr->prev_foot = mem-(2*size_t) = mstate ^ mparams.magic for PRECEDING block; mchunkptr->prev_foot = mem-(2*size_t) = mstate ^ mparams.magic for PRECEDING block;
mchunkptr->head = mem-(1*size_t) = 8 multiple size of this block with bottom three bits = FLAG_BITS mchunkptr->head = mem-(1*size_t) = 8 multiple size of this block with bottom three bits = FLAG_BITS
FLAG_BITS = bit 0 is CINUSE (currently in use unless is mmap), bit 1 is PINUSE (previous block currently
in use unless mmap), bit 2 is UNUSED and currently is always zero.
*/ */
mchunkptr p=mem2chunk(mem); register void *RESTRICT leastusedaddress_=leastusedaddress; /* Cache these to avoid register reloading */
mstate fm=0; register size_t largestusedblock_=largestusedblock;
if(!is_inuse(p)) return 0; if(!is_aligned(mem)) return 0; /* Would fail very rarely as all allocators return aligned blocks */
/* The following isn't safe but is probably true: unlikely to allocate if(mem<leastusedaddress_) return 0; /* Simple but effective */
a 2Gb block on a 32bit system or a 8Eb block on a 64 bit system */ {
if(p->head & ((size_t)1)<<(SIZE_T_BITSIZE-SIZE_T_ONE)) return 0; mchunkptr p=mem2chunk(mem);
/* We have now reduced our chances of being wrong to 0.5^4 = 6.25%. mstate fm=0;
We could start comparing prev_foot's for similarity but it starts getting slow. */ int ismmapped=is_mmapped(p);
fm = get_mstate_for(p); if((!ismmapped && !is_inuse(p)) || (p->head & FLAG4_BIT)) return 0;
assert(ok_magic(fm)); /* If this fails, someone tried to free a block twice */ /* Reduced uncertainty by 0.5^2 = 25.0% */
if(ok_magic(fm)) /* size should never exceed largestusedblock */
return chunksize(p)-overhead_for(p); if(chunksize(p)>largestusedblock_) return 0;
/* Reduced uncertainty by a minimum of 0.5^3 = 12.5%, maximum 0.5^16 = 0.0015% */
/* Having sanity checked prev_foot and head, check next block */
if(!ismmapped && (!next_pinuse(p) || (next_chunk(p)->head & FLAG4_BIT))) return 0;
/* Reduced uncertainty by 0.5^5 = 3.13% or 0.5^18 = 0.00038% */
#if 0
/* If previous block is free, check that its next block pointer equals us */
if(!ismmapped && !pinuse(p))
if(next_chunk(prev_chunk(p))!=p) return 0;
/* We could start comparing prev_foot's for similarity but it starts getting slow. */
#endif
fm = get_mstate_for(p);
if(!is_aligned(fm) || (void *)fm<leastusedaddress_) return 0;
if((size_t)mem-(size_t)fm>=(size_t)1<<(SIZE_T_BITSIZE-1)) return 0;
assert(ok_magic(fm)); /* If this fails, someone tried to free a block twice */
if(ok_magic(fm))
return fm;
}
} }
#ifdef _MSC_VER #ifdef _MSC_VER
__except(1) { } __except(1) { }
#endif #endif
#endif #endif
#endif
#endif
}
return 0;
}
NEDMALLOCNOALIASATTR size_t nedblksize(int *RESTRICT isforeign, void *RESTRICT mem) THROWSPEC
{
if(mem)
{
if(isforeign) *isforeign=1;
#if USE_MAGIC_HEADERS
{
size_t *_mem=(size_t *) mem-3;
if(_mem[0]==*(size_t *) "NEDMALOC")
{
mstate mspace=(mstate) _mem[1];
size_t size=_mem[2];
if(isforeign) *isforeign=0;
return size;
}
}
#elif USE_ALLOCATOR==1
if(nedblkmstate(mem))
{
mchunkptr p=mem2chunk(mem);
if(isforeign) *isforeign=0;
return chunksize(p)-overhead_for(p);
}
#ifdef DEBUG
else
{
int a=1; /* Set breakpoints here if needed */
}
#endif
#endif
#if defined(ENABLE_TOLERANT_NEDMALLOC) || USE_ALLOCATOR==0
#ifdef WIN32
/* This is the MSVCRT equivalent */
return _msize(mem);
#elif defined(__linux__)
/* This is the glibc/ptmalloc2/dlmalloc equivalent. */
return malloc_usable_size(mem);
#elif defined(__FreeBSD__) || defined(__APPLE__)
/* This is the BSD libc equivalent. */
return malloc_size(mem);
#else
#error Cannot tolerate the memory allocator of an unknown system!
#endif
#endif #endif
} }
return 0; return 0;
} }
void nedsetvalue(void *v) THROWSPEC { nedpsetvalue((nedpool *) 0, v); } void nedsetvalue(void *v) THROWSPEC { nedpsetvalue((nedpool *) 0, v); }
NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC { return nedpmalloc((nedpool *) 0, size); } NEDMALLOCPTRATTR void * nedmalloc(size_t size) THROWSPEC { return nedpmalloc((nedpool *) 0, size); }
NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC { return nedpcalloc((nedpool *) 0, no, size); } NEDMALLOCPTRATTR void * nedcalloc(size_t no, size_t size) THROWSPEC { return nedpcalloc((nedpool *) 0, no, size); }
NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC { return nedprealloc((nedpool *) 0, mem, size); } NEDMALLOCPTRATTR void * nedrealloc(void *mem, size_t size) THROWSPEC { return nedprealloc((nedpool *) 0, mem, size); }
void nedfree(void *mem) THROWSPEC { nedpfree((nedpool *) 0, mem); } void nedfree(void *mem) THROWSPEC { nedpfree((nedpool *) 0, mem); }
NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC { return nedpmemalign((nedpool *) 0, alignment, bytes); } NEDMALLOCPTRATTR void * nedmemalign(size_t alignment, size_t bytes) THROWSPEC { return nedpmemalign((nedpool *) 0, alignment, bytes); }
#if !NO_MALLINFO struct nedmallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo((nedpool *) 0); }
struct mallinfo nedmallinfo(void) THROWSPEC { return nedpmallinfo((nedpool *) 0); } int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt((nedpool *) 0, parno, value); }
#endif int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim((nedpool *) 0, pad); }
int nedmallopt(int parno, int value) THROWSPEC { return nedpmallopt((nedpool *) 0, parno, value); } void nedmalloc_stats() THROWSPEC { nedpmalloc_stats((nedpool *) 0); }
int nedmalloc_trim(size_t pad) THROWSPEC { return nedpmalloc_trim((nedpool *) 0, pad); } size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint((nedpool *) 0); }
void nedmalloc_stats() THROWSPEC { nedpmalloc_stats((nedpool *) 0); }
size_t nedmalloc_footprint() THROWSPEC { return nedpmalloc_footprint((nedpool *) 0); }
NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc((nedpool *) 0, elemsno, elemsize, chunks); } NEDMALLOCPTRATTR void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC { return nedpindependent_calloc((nedpool *) 0, elemsno, elemsize, chunks); }
NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc((nedpool *) 0, elems, sizes, chunks); } // NEDMALLOCPTRATTR void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC { return nedpindependent_comalloc((nedpool *) 0, elems, sizes, chunks); }
struct threadcacheblk_t; struct threadcacheblk_t;
typedef struct threadcacheblk_t threadcacheblk; typedef struct threadcacheblk_t threadcacheblk;
@ -383,7 +540,7 @@ struct nedpool_t
}; };
static nedpool syspool; static nedpool syspool;
static FORCEINLINE unsigned int size2binidx(size_t _size) THROWSPEC static FORCEINLINE NEDMALLOCNOALIASATTR unsigned int size2binidx(size_t _size) THROWSPEC
{ /* 8=1000 16=10000 20=10100 24=11000 32=100000 48=110000 4096=1000000000000 */ { /* 8=1000 16=10000 20=10100 24=11000 32=100000 48=110000 4096=1000000000000 */
unsigned int topbit, size=(unsigned int)(_size>>4); unsigned int topbit, size=(unsigned int)(_size>>4);
/* 16=1 20=1 24=1 32=10 48=11 64=100 96=110 128=1000 4096=100000000 */ /* 16=1 20=1 24=1 32=10 48=11 64=100 96=110 128=1000 4096=100000000 */
@ -467,9 +624,8 @@ static void tcfullsanitycheck(threadcache *tc) THROWSPEC
} }
#endif #endif
static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned int age) THROWSPEC static NOINLINE void RemoveCacheEntries(nedpool *RESTRICT p, threadcache *RESTRICT tc, unsigned int age) THROWSPEC
{ {
UNREFERENCED_PARAMETER(p);
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
tcfullsanitycheck(tc); tcfullsanitycheck(tc);
#endif #endif
@ -485,7 +641,7 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in
{ {
threadcacheblk *f=*tcb; threadcacheblk *f=*tcb;
size_t blksize=f->size; /*nedblksize(f);*/ size_t blksize=f->size; /*nedblksize(f);*/
assert(blksize<=nedblksize(f)); assert(blksize<=nedblksize(0, f));
assert(blksize); assert(blksize);
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
assert(*(unsigned int *) "NEDN"==(*tcb)->magic); assert(*(unsigned int *) "NEDN"==(*tcb)->magic);
@ -497,7 +653,7 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in
*tcbptr=0; *tcbptr=0;
tc->freeInCache-=blksize; tc->freeInCache-=blksize;
assert((long) tc->freeInCache>=0); assert((long) tc->freeInCache>=0);
CallFree(0, f); CallFree(0, f, 0);
/*tcsanitycheck(tcbptr);*/ /*tcsanitycheck(tcbptr);*/
} }
} }
@ -506,7 +662,7 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in
tcfullsanitycheck(tc); tcfullsanitycheck(tc);
#endif #endif
} }
static void DestroyCaches(nedpool *p) THROWSPEC static void DestroyCaches(nedpool *RESTRICT p) THROWSPEC
{ {
if(p->caches) if(p->caches)
{ {
@ -521,14 +677,14 @@ static void DestroyCaches(nedpool *p) THROWSPEC
assert(!tc->freeInCache); assert(!tc->freeInCache);
tc->mymspace=-1; tc->mymspace=-1;
tc->threadid=0; tc->threadid=0;
CallFree(0, tc); CallFree(0, tc, 0);
p->caches[n]=0; p->caches[n]=0;
} }
} }
} }
} }
static NOINLINE threadcache *AllocCache(nedpool *p) THROWSPEC static NOINLINE threadcache *AllocCache(nedpool *RESTRICT p) THROWSPEC
{ {
threadcache *tc=0; threadcache *tc=0;
int n, end; int n, end;
@ -539,7 +695,7 @@ static NOINLINE threadcache *AllocCache(nedpool *p) THROWSPEC
RELEASE_LOCK(&p->mutex); RELEASE_LOCK(&p->mutex);
return 0; return 0;
} }
tc=p->caches[n]=(threadcache *) CallCalloc(p->m[0], 1, sizeof(threadcache), 0); tc=p->caches[n]=(threadcache *) CallCalloc(p->m[0], sizeof(threadcache), 0);
if(!tc) if(!tc)
{ {
RELEASE_LOCK(&p->mutex); RELEASE_LOCK(&p->mutex);
@ -557,14 +713,13 @@ static NOINLINE threadcache *AllocCache(nedpool *p) THROWSPEC
return tc; return tc;
} }
static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROWSPEC static void *threadcache_malloc(nedpool *RESTRICT p, threadcache *RESTRICT tc, size_t *RESTRICT _size) THROWSPEC
{ {
void *ret=0; void *RESTRICT ret=0;
size_t size=*_size, blksize=0;
unsigned int bestsize; unsigned int bestsize;
unsigned int idx=size2binidx(*size); unsigned int idx=size2binidx(size);
size_t blksize=0; threadcacheblk *RESTRICT blk, **RESTRICT binsptr;
threadcacheblk *blk, **binsptr;
UNREFERENCED_PARAMETER(p);
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
tcfullsanitycheck(tc); tcfullsanitycheck(tc);
#endif #endif
@ -573,31 +728,31 @@ static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROW
#ifdef FINEGRAINEDBINS #ifdef FINEGRAINEDBINS
/* Finer grained bin fit */ /* Finer grained bin fit */
idx<<=1; idx<<=1;
if(*size>bestsize) if(size>bestsize)
{ {
idx++; idx++;
bestsize+=bestsize>>1; bestsize+=bestsize>>1;
} }
if(*size>bestsize) if(size>bestsize)
{ {
idx++; idx++;
bestsize=1<<(4+(idx>>1)); bestsize=1<<(4+(idx>>1));
} }
#else #else
if(*size>bestsize) if(size>bestsize)
{ {
idx++; idx++;
bestsize<<=1; bestsize<<=1;
} }
#endif #endif
assert(bestsize>=*size); assert(bestsize>=size);
if(*size<bestsize) *size=bestsize; if(size<bestsize) size=bestsize;
assert(*size<=THREADCACHEMAX); assert(size<=THREADCACHEMAX);
assert(idx<=THREADCACHEMAXBINS); assert(idx<=THREADCACHEMAXBINS);
binsptr=&tc->bins[idx*2]; binsptr=&tc->bins[idx*2];
/* Try to match close, but move up a bin if necessary */ /* Try to match close, but move up a bin if necessary */
blk=*binsptr; blk=*binsptr;
if(!blk || blk->size<*size) if(!blk || blk->size<size)
{ /* Bump it up a bin */ { /* Bump it up a bin */
if(idx<THREADCACHEMAXBINS) if(idx<THREADCACHEMAXBINS)
{ {
@ -609,8 +764,8 @@ static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROW
if(blk) if(blk)
{ {
blksize=blk->size; /*nedblksize(blk);*/ blksize=blk->size; /*nedblksize(blk);*/
assert(nedblksize(blk)>=blksize); assert(nedblksize(0, blk)>=blksize);
assert(blksize>=*size); assert(blksize>=size);
if(blk->next) if(blk->next)
blk->next->prev=0; blk->next->prev=0;
*binsptr=blk->next; *binsptr=blk->next;
@ -620,14 +775,14 @@ static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROW
blk->magic=0; blk->magic=0;
#endif #endif
assert(binsptr[0]!=blk && binsptr[1]!=blk); assert(binsptr[0]!=blk && binsptr[1]!=blk);
assert(nedblksize(blk)>=sizeof(threadcacheblk) && nedblksize(blk)<=THREADCACHEMAX+CHUNK_OVERHEAD); assert(nedblksize(0, blk)>=sizeof(threadcacheblk) && nedblksize(0, blk)<=THREADCACHEMAX+CHUNK_OVERHEAD);
/*printf("malloc: %p, %p, %p, %lu\n", p, tc, blk, (long) size);*/ /*printf("malloc: %p, %p, %p, %lu\n", p, tc, blk, (long) _size);*/
ret=(void *) blk; ret=(void *) blk;
} }
++tc->mallocs; ++tc->mallocs;
if(ret) if(ret)
{ {
assert(blksize>=*size); assert(blksize>=size);
++tc->successes; ++tc->successes;
tc->freeInCache-=blksize; tc->freeInCache-=blksize;
assert((long) tc->freeInCache>=0); assert((long) tc->freeInCache>=0);
@ -642,13 +797,13 @@ static void *threadcache_malloc(nedpool *p, threadcache *tc, size_t *size) THROW
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
tcfullsanitycheck(tc); tcfullsanitycheck(tc);
#endif #endif
*_size=size;
return ret; return ret;
} }
static NOINLINE void ReleaseFreeInCache(nedpool *p, threadcache *tc, int mymspace) THROWSPEC static NOINLINE void ReleaseFreeInCache(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace) THROWSPEC
{ {
unsigned int age=THREADCACHEMAXFREESPACE/8192; unsigned int age=THREADCACHEMAXFREESPACE/8192;
/*ACQUIRE_LOCK(&p->m[mymspace]->mutex);*/ /*ACQUIRE_LOCK(&p->m[mymspace]->mutex);*/
UNREFERENCED_PARAMETER(mymspace);
while(age && tc->freeInCache>=THREADCACHEMAXFREESPACE) while(age && tc->freeInCache>=THREADCACHEMAXFREESPACE)
{ {
RemoveCacheEntries(p, tc, age); RemoveCacheEntries(p, tc, age);
@ -657,15 +812,15 @@ static NOINLINE void ReleaseFreeInCache(nedpool *p, threadcache *tc, int mymspac
} }
/*RELEASE_LOCK(&p->m[mymspace]->mutex);*/ /*RELEASE_LOCK(&p->m[mymspace]->mutex);*/
} }
static void threadcache_free(nedpool *p, threadcache *tc, int mymspace, void *mem, size_t size) THROWSPEC static void threadcache_free(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace, void *RESTRICT mem, size_t size) THROWSPEC
{ {
unsigned int bestsize; unsigned int bestsize;
unsigned int idx=size2binidx(size); unsigned int idx=size2binidx(size);
threadcacheblk **binsptr, *tck=(threadcacheblk *) mem; threadcacheblk **RESTRICT binsptr, *RESTRICT tck=(threadcacheblk *) mem;
assert(size>=sizeof(threadcacheblk) && size<=THREADCACHEMAX+CHUNK_OVERHEAD); assert(size>=sizeof(threadcacheblk) && size<=THREADCACHEMAX+CHUNK_OVERHEAD);
#ifdef DEBUG #ifdef DEBUG
/* Make sure this is a valid memory block */ /* Make sure this is a valid memory block */
assert(nedblksize(mem)); assert(nedblksize(0, mem));
#endif #endif
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
tcfullsanitycheck(tc); tcfullsanitycheck(tc);
@ -677,7 +832,7 @@ static void threadcache_free(nedpool *p, threadcache *tc, int mymspace, void *me
idx<<=1; idx<<=1;
if(size>bestsize) if(size>bestsize)
{ {
unsigned int biggerbestsize=bestsize+(bestsize<<1); unsigned int biggerbestsize=bestsize+bestsize<<1;
if(size>=biggerbestsize) if(size>=biggerbestsize)
{ {
idx++; idx++;
@ -723,7 +878,7 @@ static void threadcache_free(nedpool *p, threadcache *tc, int mymspace, void *me
static NOINLINE int InitPool(nedpool *p, size_t capacity, int threads) THROWSPEC static NOINLINE int InitPool(nedpool *RESTRICT p, size_t capacity, int threads) THROWSPEC
{ /* threads is -1 for system pool */ { /* threads is -1 for system pool */
ensure_initialization(); ensure_initialization();
ACQUIRE_MALLOC_GLOBAL_LOCK(); ACQUIRE_MALLOC_GLOBAL_LOCK();
@ -759,7 +914,7 @@ err:
RELEASE_MALLOC_GLOBAL_LOCK(); RELEASE_MALLOC_GLOBAL_LOCK();
return 0; return 0;
} }
static NOINLINE mstate FindMSpace(nedpool *p, threadcache *tc, int *lastUsed, size_t size) THROWSPEC static NOINLINE mstate FindMSpace(nedpool *RESTRICT p, threadcache *RESTRICT tc, int *RESTRICT lastUsed, size_t size) THROWSPEC
{ /* Gets called when thread's last used mspace is in use. The strategy { /* Gets called when thread's last used mspace is in use. The strategy
is to run through the list of all available mspaces looking for an is to run through the list of all available mspaces looking for an
unlocked one and if we fail, we create a new one so long as we don't unlocked one and if we fail, we create a new one so long as we don't
@ -818,20 +973,57 @@ found:
return p->m[n]; return p->m[n];
} }
typedef struct PoolList_t
{
size_t size; /* Size of list */
size_t length; /* Actual entries in list */
#ifdef DEBUG
nedpool *list[1]; /* Force testing of list expansion */
#else
nedpool *list[16];
#endif
} PoolList;
static MLOCK_T poollistlock;
static PoolList *poollist;
NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC NEDMALLOCPTRATTR nedpool *nedcreatepool(size_t capacity, int threads) THROWSPEC
{ {
nedpool *ret; nedpool *ret=0;
if(!(ret=(nedpool *) nedpcalloc(0, 1, sizeof(nedpool)))) return 0; if(!poollist)
{
PoolList *newpoollist=0;
if(!(newpoollist=(PoolList *) nedpcalloc(0, 1, sizeof(PoolList)+sizeof(nedpool *)))) return 0;
INITIAL_LOCK(&poollistlock);
ACQUIRE_LOCK(&poollistlock);
poollist=newpoollist;
poollist->size=sizeof(poollist->list)/sizeof(nedpool *);
}
else
ACQUIRE_LOCK(&poollistlock);
if(poollist->length==poollist->size)
{
PoolList *newpoollist=0;
size_t newsize=0;
newsize=sizeof(PoolList)+(poollist->size+1)*sizeof(nedpool *);
if(!(newpoollist=(PoolList *) nedprealloc(0, poollist, newsize))) goto badexit;
poollist=newpoollist;
memset(&poollist->list[poollist->size], 0, newsize-((size_t)&poollist->list[poollist->size]-(size_t)&poollist->list[0]));
poollist->size=((newsize-((char *)&poollist->list[0]-(char *)poollist))/sizeof(nedpool *))-1;
assert(poollist->size>poollist->length);
}
if(!(ret=(nedpool *) nedpcalloc(0, 1, sizeof(nedpool)))) goto badexit;
if(!InitPool(ret, capacity, threads)) if(!InitPool(ret, capacity, threads))
{ {
nedpfree(0, ret); nedpfree(0, ret);
return 0; goto badexit;
} }
poollist->list[poollist->length++]=ret;
badexit:
RELEASE_LOCK(&poollistlock);
return ret; return ret;
} }
void neddestroypool(nedpool *p) THROWSPEC void neddestroypool(nedpool *p) THROWSPEC
{ {
int n; unsigned int n;
ACQUIRE_LOCK(&p->mutex); ACQUIRE_LOCK(&p->mutex);
DestroyCaches(p); DestroyCaches(p);
for(n=0; p->m[n]; n++) for(n=0; p->m[n]; n++)
@ -844,6 +1036,18 @@ void neddestroypool(nedpool *p) THROWSPEC
RELEASE_LOCK(&p->mutex); RELEASE_LOCK(&p->mutex);
if(TLSFREE(p->mycache)) abort(); if(TLSFREE(p->mycache)) abort();
nedpfree(0, p); nedpfree(0, p);
ACQUIRE_LOCK(&poollistlock);
assert(poollist);
for(n=0; n<poollist->length && poollist->list[n]!=p; n++);
assert(n!=poollist->length);
memmove(&poollist->list[n], &poollist->list[n+1], (size_t)&poollist->list[poollist->length]-(size_t)&poollist->list[n]);
if(!--poollist->length)
{
assert(!poollist->list[0]);
nedpfree(0, poollist);
poollist=0;
}
RELEASE_LOCK(&poollistlock);
} }
void neddestroysyspool() THROWSPEC void neddestroysyspool() THROWSPEC
{ {
@ -860,35 +1064,36 @@ void neddestroysyspool() THROWSPEC
} }
/* Render syspool unusable */ /* Render syspool unusable */
for(n=0; n<THREADCACHEMAXCACHES; n++) for(n=0; n<THREADCACHEMAXCACHES; n++)
p->caches[n]=(threadcache *)0xdeadbeef; p->caches[n]=(threadcache *)(size_t)(sizeof(size_t)>4 ? 0xdeadbeefdeadbeefULL : 0xdeadbeefUL);
for(n=0; n<MAXTHREADSINPOOL+1; n++) for(n=0; n<MAXTHREADSINPOOL+1; n++)
p->m[n]=(mstate)0xdeadbeef; p->m[n]=(mstate)(size_t)(sizeof(size_t)>4 ? 0xdeadbeefdeadbeefULL : 0xdeadbeefUL);
if(TLSFREE(p->mycache)) abort(); if(TLSFREE(p->mycache)) abort();
RELEASE_LOCK(&p->mutex); RELEASE_LOCK(&p->mutex);
} }
nedpool **nedpoollist() THROWSPEC
{
nedpool **ret=0;
if(poollist)
{
ACQUIRE_LOCK(&poollistlock);
if(!(ret=(nedpool **) nedmalloc((poollist->length+1)*sizeof(nedpool *)))) goto badexit;
memcpy(ret, poollist->list, (poollist->length+1)*sizeof(nedpool *));
badexit:
RELEASE_LOCK(&poollistlock);
}
return ret;
}
void nedpsetvalue(nedpool *p, void *v) THROWSPEC void nedpsetvalue(nedpool *p, void *v) THROWSPEC
{ {
if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
p->uservalue=v; p->uservalue=v;
} }
void *nedgetvalue(nedpool **p, void *mem) THROWSPEC void *nedgetvalue(nedpool **p, void *mem) THROWSPEC
{ {
nedpool *np=0; nedpool *np=0;
mchunkptr mcp=mem2chunk(mem); mstate fm=nedblkmstate(mem);
mstate fm; if(!fm || !fm->extp) return 0;
if(!(is_aligned(chunk2mem(mcp))) && mcp->head != FENCEPOST_HEAD) return 0;
if(!cinuse(mcp)) return 0;
if(!next_pinuse(mcp)) return 0;
if(!is_mmapped(mcp) && !pinuse(mcp))
{
if(next_chunk(prev_chunk(mcp))!=mcp) return 0;
}
fm=get_mstate_for(mcp);
if(!ok_magic(fm)) return 0;
if(!ok_address(fm, mcp)) return 0;
if(!fm->extp) return 0;
np=(nedpool *) fm->extp; np=(nedpool *) fm->extp;
if(p) *p=np; if(p) *p=np;
return np->uservalue; return np->uservalue;
@ -922,7 +1127,7 @@ void nedtrimthreadcache(nedpool *p, int disable) THROWSPEC
{ {
tc->mymspace=-1; tc->mymspace=-1;
tc->threadid=0; tc->threadid=0;
CallFree(0, p->caches[mycache-1]); CallFree(0, p->caches[mycache-1], 0);
p->caches[mycache-1]=0; p->caches[mycache-1]=0;
} }
} }
@ -940,7 +1145,7 @@ void neddisablethreadcache(nedpool *p) THROWSPEC
if(USE_ALLOCATOR==1) { RELEASE_LOCK(&m->mutex); } \ if(USE_ALLOCATOR==1) { RELEASE_LOCK(&m->mutex); } \
} while (0) } while (0)
static FORCEINLINE mstate GetMSpace(nedpool *p, threadcache *tc, int mymspace, size_t size) THROWSPEC static FORCEINLINE mstate GetMSpace(nedpool *RESTRICT p, threadcache *RESTRICT tc, int mymspace, size_t size) THROWSPEC
{ /* Returns a locked and ready for use mspace */ { /* Returns a locked and ready for use mspace */
mstate m=p->m[mymspace]; mstate m=p->m[mymspace];
assert(m); assert(m);
@ -950,22 +1155,14 @@ static FORCEINLINE mstate GetMSpace(nedpool *p, threadcache *tc, int mymspace, s
#endif #endif
return m; return m;
} }
static FORCEINLINE void GetThreadCache(nedpool **p, threadcache **tc, int *mymspace, size_t *size) THROWSPEC static NOINLINE void GetThreadCache_cold1(nedpool *RESTRICT *RESTRICT p) THROWSPEC
{ {
int mycache; *p=&syspool;
if(size && *size<sizeof(threadcacheblk)) *size=sizeof(threadcacheblk); if(!syspool.threads) InitPool(&syspool, 0, -1);
if(!*p) }
{ static NOINLINE void GetThreadCache_cold2(nedpool *RESTRICT *RESTRICT p, threadcache *RESTRICT *RESTRICT tc, int *RESTRICT mymspace, int mycache) THROWSPEC
*p=&syspool; {
if(!syspool.threads) InitPool(&syspool, 0, -1); if(!mycache)
}
mycache=(int)(size_t) TLSGET((*p)->mycache);
if(mycache>0)
{ /* Already have a cache */
*tc=(*p)->caches[mycache-1];
*mymspace=(*tc)->mymspace;
}
else if(!mycache)
{ /* Need to allocate a new cache */ { /* Need to allocate a new cache */
*tc=AllocCache(*p); *tc=AllocCache(*p);
if(!*tc) if(!*tc)
@ -981,6 +1178,20 @@ static FORCEINLINE void GetThreadCache(nedpool **p, threadcache **tc, int *mymsp
*tc=0; *tc=0;
*mymspace=-mycache-1; *mymspace=-mycache-1;
} }
}
static FORCEINLINE void GetThreadCache(nedpool *RESTRICT *RESTRICT p, threadcache *RESTRICT *RESTRICT tc, int *RESTRICT mymspace, size_t *RESTRICT size) THROWSPEC
{
int mycache;
if(size && *size<sizeof(threadcacheblk)) *size=sizeof(threadcacheblk);
if(!*p)
GetThreadCache_cold1(p);
mycache=(int)(size_t) TLSGET((*p)->mycache);
if(mycache>0)
{ /* Already have a cache */
*tc=(*p)->caches[mycache-1];
*mymspace=(*tc)->mymspace;
}
else GetThreadCache_cold2(p, tc, mymspace, mycache);
assert(*mymspace>=0); assert(*mymspace>=0);
assert(!(*tc) || (long)(size_t)CURRENT_THREAD==(*tc)->threadid); assert(!(*tc) || (long)(size_t)CURRENT_THREAD==(*tc)->threadid);
#ifdef FULLSANITYCHECKS #ifdef FULLSANITYCHECKS
@ -1030,7 +1241,7 @@ NEDMALLOCPTRATTR void * nedpcalloc(nedpool *p, size_t no, size_t size) THROWSPEC
if(!ret) if(!ret)
{ /* Use this thread's mspace */ { /* Use this thread's mspace */
GETMSPACE(m, p, tc, mymspace, rsize, GETMSPACE(m, p, tc, mymspace, rsize,
ret=CallCalloc(m, 1, rsize, 0)); ret=CallCalloc(m, rsize, 0));
} }
return ret; return ret;
} }
@ -1038,35 +1249,42 @@ NEDMALLOCPTRATTR void * nedprealloc(nedpool *p, void *mem, size_t size) THROWSPE
{ {
void *ret=0; void *ret=0;
threadcache *tc; threadcache *tc;
int mymspace; int mymspace, isforeign=1;
size_t memsize;
if(!mem) return nedpmalloc(p, size); if(!mem) return nedpmalloc(p, size);
memsize=nedblksize(&isforeign, mem);
assert(memsize);
if(!memsize)
{
fprintf(stderr, "nedmalloc: nedprealloc() called with a block not created by nedmalloc!\n");
abort();
}
else if(size<=memsize && memsize-size<
#ifdef DEBUG
32
#else
1024
#endif
) /* If realloc size is within 1Kb smaller than existing, noop it */
return mem;
GetThreadCache(&p, &tc, &mymspace, &size); GetThreadCache(&p, &tc, &mymspace, &size);
#if THREADCACHEMAX #if THREADCACHEMAX
if(tc && size && size<=THREADCACHEMAX) if(tc && size && size<=THREADCACHEMAX)
{ /* Use the thread cache */ { /* Use the thread cache */
size_t memsize=nedblksize(mem);
#if !USE_MAGIC_HEADERS
assert(memsize);
if(!memsize)
{
fprintf(stderr, "nedmalloc: nedprealloc() called with a block not created by nedmalloc!\n");
abort();
}
#endif
if((ret=threadcache_malloc(p, tc, &size))) if((ret=threadcache_malloc(p, tc, &size)))
{ {
memcpy(ret, mem, memsize<size ? memsize : size); memcpy(ret, mem, memsize<size ? memsize : size);
if(memsize && memsize<=THREADCACHEMAX) if(memsize>=sizeof(threadcacheblk) && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD))
threadcache_free(p, tc, mymspace, mem, memsize); threadcache_free(p, tc, mymspace, mem, memsize);
else else
CallFree(0, mem); CallFree(0, mem, isforeign);
} }
} }
#endif #endif
if(!ret) if(!ret)
{ /* Reallocs always happen in the mspace they happened in, so skip { /* Reallocs always happen in the mspace they happened in, so skip
locking the preferred mspace for this thread */ locking the preferred mspace for this thread */
ret=CallRealloc(0, mem, size); ret=CallRealloc(p->m[mymspace], mem, isforeign, memsize, size);
} }
return ret; return ret;
} }
@ -1074,30 +1292,29 @@ void nedpfree(nedpool *p, void *mem) THROWSPEC
{ /* Frees always happen in the mspace they happened in, so skip { /* Frees always happen in the mspace they happened in, so skip
locking the preferred mspace for this thread */ locking the preferred mspace for this thread */
threadcache *tc; threadcache *tc;
int mymspace; int mymspace, isforeign=1;
size_t memsize; size_t memsize;
if(!mem) if(!mem)
{ /* You'd be surprised the number of times this happens as so many { /* If you tried this on FreeBSD you'd be sorry! */
allocators are non-conformant here */ #ifdef DEBUG
// fprintf(stderr, "nedmalloc: WARNING nedpfree() called with zero. This is not portable behaviour!\n"); fprintf(stderr, "nedmalloc: WARNING nedpfree() called with zero. This is not portable behaviour!\n");
#endif
return; return;
} }
GetThreadCache(&p, &tc, &mymspace, 0); memsize=nedblksize(&isforeign, mem);
#if THREADCACHEMAX
memsize=nedblksize(mem);
#if !USE_MAGIC_HEADERS
assert(memsize); assert(memsize);
if(!memsize) if(!memsize)
{ {
fprintf(stderr, "nedmalloc: nedpfree() called with a block not created by nedmalloc!\n"); fprintf(stderr, "nedmalloc: nedpfree() called with a block not created by nedmalloc!\n");
abort(); abort();
} }
#endif GetThreadCache(&p, &tc, &mymspace, 0);
if(mem && tc && memsize && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD)) #if THREADCACHEMAX
if(mem && tc && memsize>=sizeof(threadcacheblk) && memsize<=(THREADCACHEMAX+CHUNK_OVERHEAD))
threadcache_free(p, tc, mymspace, mem, memsize); threadcache_free(p, tc, mymspace, mem, memsize);
else else
#endif #endif
CallFree(0, mem); CallFree(0, mem, isforeign);
} }
NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes) THROWSPEC
{ {
@ -1111,15 +1328,14 @@ NEDMALLOCPTRATTR void * nedpmemalign(nedpool *p, size_t alignment, size_t bytes)
} }
return ret; return ret;
} }
#if !NO_MALLINFO struct nedmallinfo nedpmallinfo(nedpool *p) THROWSPEC
struct mallinfo nedpmallinfo(nedpool *p) THROWSPEC
{ {
int n; int n;
struct mallinfo ret={0,0,0,0,0,0,0,0,0,0}; struct nedmallinfo ret={0};
if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); } if(!p) { p=&syspool; if(!syspool.threads) InitPool(&syspool, 0, -1); }
for(n=0; p->m[n]; n++) for(n=0; p->m[n]; n++)
{ {
#if USE_ALLOCATOR==1 #if USE_ALLOCATOR==1 && !NO_MALLINFO
struct mallinfo t=mspace_mallinfo(p->m[n]); struct mallinfo t=mspace_mallinfo(p->m[n]);
ret.arena+=t.arena; ret.arena+=t.arena;
ret.ordblks+=t.ordblks; ret.ordblks+=t.ordblks;
@ -1132,10 +1348,8 @@ struct mallinfo nedpmallinfo(nedpool *p) THROWSPEC
} }
return ret; return ret;
} }
#endif
int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC int nedpmallopt(nedpool *p, int parno, int value) THROWSPEC
{ {
UNREFERENCED_PARAMETER(p);
#if USE_ALLOCATOR==1 #if USE_ALLOCATOR==1
return mspace_mallopt(parno, value); return mspace_mallopt(parno, value);
#else #else
@ -1205,6 +1419,8 @@ NEDMALLOCPTRATTR void **nedpindependent_calloc(nedpool *p, size_t elemsno, size_
#endif #endif
return ret; return ret;
} }
#if 0
NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_t *sizes, void **chunks) THROWSPEC
{ {
void **ret; void **ret;
@ -1224,6 +1440,7 @@ NEDMALLOCPTRATTR void **nedpindependent_comalloc(nedpool *p, size_t elems, size_
#endif #endif
return ret; return ret;
} }
#endif // 0
// cheap replacement for strdup so we aren't feeding system allocated blocks into nedmalloc // cheap replacement for strdup so we aren't feeding system allocated blocks into nedmalloc

View file

@ -4290,109 +4290,84 @@ static void polymer_getscratchmaterial(_prmaterial* material)
static void polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade) static void polymer_getbuildmaterial(_prmaterial* material, int16_t tilenum, char pal, int8_t shade)
{ {
pthtyp* pth; pthtyp* pth;
pthtyp* detailpth;
pthtyp* glowpth;
polymer_getscratchmaterial(material); polymer_getscratchmaterial(material);
// PR_BIT_NORMAL_MAP
if (hicfindsubst(tilenum, NORMALPAL, 0))
{
glowpth = NULL;
glowpth = gltexcache(tilenum, NORMALPAL, 0);
if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == NORMALPAL)) {
material->normalmap = glowpth->glpic;
material->normalbias[0] = glowpth->hicr->specpower;
material->normalbias[1] = glowpth->hicr->specfactor;
}
}
// PR_BIT_DIFFUSE_MAP // PR_BIT_DIFFUSE_MAP
if (!waloff[tilenum]) if (!waloff[tilenum])
loadtile(tilenum); loadtile(tilenum);
pth = NULL; if ((pth = gltexcache(tilenum, pal, (material == &spriteplane.material) ? 4 : 0)))
pth = gltexcache(tilenum, pal, (material == &spriteplane.material) ? 4 : 0); {
if (pth)
material->diffusemap = pth->glpic; material->diffusemap = pth->glpic;
if (pth->hicr) if (pth->hicr)
{
material->diffusescale[0] = pth->hicr->xscale;
material->diffusescale[1] = pth->hicr->yscale;
}
// PR_BIT_DIFFUSE_DETAIL_MAP
if (hicfindsubst(tilenum, DETAILPAL, 0))
{
detailpth = NULL;
detailpth = gltexcache(tilenum, DETAILPAL, 0);
if (detailpth && detailpth->hicr && (detailpth->hicr->palnum == DETAILPAL))
{ {
material->detailmap = detailpth->glpic; material->diffusescale[0] = pth->hicr->xscale;
material->diffusescale[1] = pth->hicr->yscale;
material->detailscale[0] = detailpth->hicr->xscale; // PR_BIT_SPECULAR_MATERIAL
material->detailscale[1] = detailpth->hicr->yscale; if (pth->hicr->specpower != 1.0f)
material->specmaterial[0] = pth->hicr->specpower;
material->specmaterial[1] = pth->hicr->specfactor;
} }
}
// PR_BIT_DIFFUSE_MODULATION // PR_BIT_DIFFUSE_MODULATION
material->diffusemodulation[0] = material->diffusemodulation[0] =
material->diffusemodulation[1] = material->diffusemodulation[1] =
material->diffusemodulation[2] = material->diffusemodulation[2] =
((float)(numpalookups-min(max(shade*shadescale,0),numpalookups)))/((float)numpalookups); ((float)(numpalookups-min(max(shade*shadescale,0),numpalookups)))/((float)numpalookups);
if (pth && (pth->flags & 2)) if (pth->flags & 2)
{
if (pth->palnum != pal)
{ {
material->diffusemodulation[0] *= (float)hictinting[pal].r / 255.0; if (pth->palnum != pal)
material->diffusemodulation[1] *= (float)hictinting[pal].g / 255.0; {
material->diffusemodulation[2] *= (float)hictinting[pal].b / 255.0; material->diffusemodulation[0] *= (float)hictinting[pal].r / 255.0;
} material->diffusemodulation[1] *= (float)hictinting[pal].g / 255.0;
// fullscreen tint on global palette change material->diffusemodulation[2] *= (float)hictinting[pal].b / 255.0;
if (hictinting[MAXPALOOKUPS-1].r != 255 || }
hictinting[MAXPALOOKUPS-1].g != 255 ||
hictinting[MAXPALOOKUPS-1].b != 255) // fullscreen tint on global palette change... this is used for nightvision and underwater tinting
{ // if ((hictinting[MAXPALOOKUPS-1].r + hictinting[MAXPALOOKUPS-1].g + hictinting[MAXPALOOKUPS-1].b) != 0x2FD)
material->diffusemodulation[0] *= hictinting[MAXPALOOKUPS-1].r / 255.0; if (((uint32_t)hictinting[MAXPALOOKUPS-1].r & 0xFFFFFF00) != 0xFFFFFF00)
material->diffusemodulation[1] *= hictinting[MAXPALOOKUPS-1].g / 255.0; {
material->diffusemodulation[2] *= hictinting[MAXPALOOKUPS-1].b / 255.0; material->diffusemodulation[0] *= hictinting[MAXPALOOKUPS-1].r / 255.0;
material->diffusemodulation[1] *= hictinting[MAXPALOOKUPS-1].g / 255.0;
material->diffusemodulation[2] *= hictinting[MAXPALOOKUPS-1].b / 255.0;
}
} }
// PR_BIT_GLOW_MAP
if (r_fullbrights && pth->flags & 16)
material->glowmap = pth->ofb->glpic;
} }
// PR_BIT_DIFFUSE_DETAIL_MAP
if (hicfindsubst(tilenum, DETAILPAL, 0) && (pth = gltexcache(tilenum, DETAILPAL, 0)) &&
pth->hicr && (pth->hicr->palnum == DETAILPAL))
{
material->detailmap = pth->glpic;
material->detailscale[0] = pth->hicr->xscale;
material->detailscale[1] = pth->hicr->yscale;
}
// PR_BIT_GLOW_MAP
if (hicfindsubst(tilenum, GLOWPAL, 0) && (pth = gltexcache(tilenum, GLOWPAL, 0)) &&
pth->hicr && (pth->hicr->palnum == GLOWPAL))
material->glowmap = pth->glpic;
// PR_BIT_SPECULAR_MAP // PR_BIT_SPECULAR_MAP
if (hicfindsubst(tilenum, SPECULARPAL, 0)) if (hicfindsubst(tilenum, SPECULARPAL, 0) && (pth = gltexcache(tilenum, SPECULARPAL, 0)) &&
pth->hicr && (pth->hicr->palnum == SPECULARPAL))
material->specmap = pth->glpic;
// PR_BIT_NORMAL_MAP
if (hicfindsubst(tilenum, NORMALPAL, 0) && (pth = gltexcache(tilenum, NORMALPAL, 0)) &&
pth->hicr && (pth->hicr->palnum == NORMALPAL))
{ {
glowpth = NULL; material->normalmap = pth->glpic;
glowpth = gltexcache(tilenum, SPECULARPAL, 0); material->normalbias[0] = pth->hicr->specpower;
material->normalbias[1] = pth->hicr->specfactor;
if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == SPECULARPAL))
material->specmap = glowpth->glpic;
}
// PR_BIT_SPECULAR_MATERIAL
if (pth->hicr)
{
if (pth->hicr->specpower != 1.0f)
material->specmaterial[0] = pth->hicr->specpower;
material->specmaterial[1] = pth->hicr->specfactor;
}
// PR_BIT_GLOW_MAP
if (r_fullbrights && pth && pth->flags & 16)
material->glowmap = pth->ofb->glpic;
if (hicfindsubst(tilenum, GLOWPAL, 0))
{
glowpth = NULL;
glowpth = gltexcache(tilenum, GLOWPAL, 0);
if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == GLOWPAL))
material->glowmap = glowpth->glpic;
} }
} }

View file

@ -247,7 +247,7 @@ void drawline2d(float x0, float y0, float x1, float y1, char col)
#define USEKENFILTER 1 #define USEKENFILTER 1
#ifdef USELZF #ifdef USELZF
# include "fastlz.h" # include "quicklz.h"
#else #else
# include "lzwnew.h" # include "lzwnew.h"
#endif #endif
@ -4283,8 +4283,8 @@ void polymost_drawrooms()
w2d = -w2d; w2d = -w2d;
if ((w1d==0 && w2d==0) || (w1d<0 || w2d<0)) if ((w1d==0 && w2d==0) || (w1d<0 || w2d<0))
continue; continue;
ptonline[0] = w2[0]+(w2d/(w1d+w2d))*w21[0]; ptonline[0] = (int32_t)(w2[0]+(w2d/(w1d+w2d))*w21[0]);
ptonline[1] = w2[1]+(w2d/(w1d+w2d))*w21[1]; ptonline[1] = (int32_t)(w2[1]+(w2d/(w1d+w2d))*w21[1]);
scrp[0] = ptonline[0]-vect.x; scrp[0] = ptonline[0]-vect.x;
scrp[1] = ptonline[1]-vect.y; scrp[1] = ptonline[1]-vect.y;
if (scrv[0]*scrp[0] + scrv[1]*scrp[1] <= 0) if (scrv[0]*scrp[0] + scrv[1]*scrp[1] <= 0)
@ -6096,7 +6096,7 @@ int32_t dxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf, c
if (glusetexcache == 2) if (glusetexcache == 2)
{ {
#ifdef USELZF #ifdef USELZF
cleng = fastlz_compress(pic, miplen, packbuf/*, miplen-1*/); cleng = qlz_compress(pic, packbuf, miplen, state_compress);
if (cleng == 0 || cleng > j-1) if (cleng == 0 || cleng > j-1)
{ {
// failed to compress // failed to compress
@ -6138,7 +6138,7 @@ int32_t dxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf, c
{ {
#ifdef USELZF #ifdef USELZF
j = (miplen/stride)<<3; j = (miplen/stride)<<3;
cleng = fastlz_compress(midbuf,j,packbuf/*,j-1*/); cleng = qlz_compress(midbuf,packbuf,j,state_compress);
if (cleng == 0 || cleng > j-1) if (cleng == 0 || cleng > j-1)
{ {
cleng = j; cleng = j;
@ -6169,7 +6169,7 @@ int32_t dxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf, c
{ {
#ifdef USELZF #ifdef USELZF
j = (miplen/stride)<<2; j = (miplen/stride)<<2;
cleng = fastlz_compress(midbuf,j,packbuf/*,j-1*/); cleng = qlz_compress(midbuf,packbuf,j,state_compress);
if (cleng == 0 || cleng > j-1) if (cleng == 0 || cleng > j-1)
{ {
cleng = j; cleng = j;
@ -6205,7 +6205,7 @@ int32_t dxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf, c
{ {
#ifdef USELZF #ifdef USELZF
j = (miplen/stride)<<2; j = (miplen/stride)<<2;
cleng = fastlz_compress(midbuf,j,packbuf/*,j-1*/); cleng = qlz_compress(midbuf,packbuf,j,state_compress);
if (cleng == 0 || cleng > j-1) if (cleng == 0 || cleng > j-1)
{ {
cleng = j; cleng = j;
@ -6239,7 +6239,7 @@ int32_t dedxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf,
if (ispacked && cleng < pict->size) inbuf = packbuf; else inbuf = pic; if (ispacked && cleng < pict->size) inbuf = packbuf; else inbuf = pic;
if (kread(fil, inbuf, cleng) != cleng) return -1; if (kread(fil, inbuf, cleng) != cleng) return -1;
if (ispacked && cleng < pict->size) if (ispacked && cleng < pict->size)
if (fastlz_decompress(packbuf, cleng, pic, pict->size) == 0) return -1; if (qlz_decompress(packbuf, pic, state_decompress) == 0) return -1;
#else #else
if (ispacked) inbuf = packbuf; else inbuf = pic; if (ispacked) inbuf = packbuf; else inbuf = pic;
if (kread(fil, inbuf, cleng) != cleng) return -1; if (kread(fil, inbuf, cleng) != cleng) return -1;
@ -6266,7 +6266,7 @@ int32_t dedxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf,
if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf; if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf;
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && cleng < j) if (ispacked && cleng < j)
if (fastlz_decompress(packbuf,cleng,midbuf,j) == 0) return -1; if (qlz_decompress(packbuf,midbuf,state_decompress) == 0) return -1;
#else #else
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1; if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1;
@ -6284,7 +6284,7 @@ int32_t dedxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf,
if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf; if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf;
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && cleng < j) if (ispacked && cleng < j)
if (fastlz_decompress(packbuf,cleng,midbuf,j) == 0) return -1; if (qlz_decompress(packbuf,midbuf,state_decompress) == 0) return -1;
#else #else
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1; if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1;
@ -6304,7 +6304,7 @@ int32_t dedxtfilter(int32_t fil, texcachepicture *pict, char *pic, void *midbuf,
if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf; if (ispacked && cleng < j) inbuf = packbuf; else inbuf = midbuf;
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && cleng < j) if (ispacked && cleng < j)
if (fastlz_decompress(packbuf,cleng,midbuf,j) == 0) return -1; if (qlz_decompress(packbuf,midbuf,state_decompress) == 0) return -1;
#else #else
if (Bread(fil,inbuf,cleng) < cleng) return -1; if (Bread(fil,inbuf,cleng) < cleng) return -1;
if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1; if (ispacked && lzwuncompress(packbuf,cleng,midbuf,j) != j) return -1;

View file

@ -0,0 +1,854 @@
// Fast data compression library
// Copyright (C) 2006-2009 Lasse Mikkel Reinhold
// lar@quicklz.com
//
// QuickLZ can be used for free under the GPL-1 or GPL-2 license (where anything
// released into public must be open source) or under a commercial license if such
// has been acquired (see http://www.quicklz.com/order.html). The commercial license
// does not cover derived or ported versions created by third parties under GPL.
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION BETA VERSION
// 1.5.0 BETA 2
#include "quicklz.h"
#if QLZ_VERSION_MAJOR != 1 || QLZ_VERSION_MINOR != 5 || QLZ_VERSION_REVISION != 0
#error quicklz.c and quicklz.h have different versions
#endif
#if (defined(__X86__) || defined(__i386__) || defined(i386) || defined(_M_IX86) || defined(__386__) || defined(__x86_64__) || defined(_M_X64))
#define X86X64
#endif
#define MINOFFSET 2
#define UNCONDITIONAL_MATCHLEN 6
#define UNCOMPRESSED_END 4
#define CWORD_LEN 4
#if QLZ_COMPRESSION_LEVEL == 1 && defined QLZ_PTR_64 && QLZ_STREAMING_BUFFER == 0
#define OFFSET_BASE source
#define CAST (ui32)(size_t)
#else
#define OFFSET_BASE 0
#define CAST
#endif
int qlz_get_setting(int setting)
{
switch (setting)
{
case 0: return QLZ_COMPRESSION_LEVEL;
case 1: return sizeof(qlz_state_compress);
case 2: return sizeof(qlz_state_decompress);
case 3: return QLZ_STREAMING_BUFFER;
#ifdef QLZ_MEMORY_SAFE
case 6: return 1;
#else
case 6: return 0;
#endif
case 7: return QLZ_VERSION_MAJOR;
case 8: return QLZ_VERSION_MINOR;
case 9: return QLZ_VERSION_REVISION;
}
return -1;
}
#if QLZ_COMPRESSION_LEVEL == 1
static int same(const unsigned char *src, size_t n)
{
while(n > 0 && *(src + n) == *src)
n--;
return n == 0 ? 1 : 0;
}
#endif
static void reset_table_compress(qlz_state_compress *state)
{
int i;
for(i = 0; i < QLZ_HASH_VALUES; i++)
{
#if QLZ_COMPRESSION_LEVEL == 1
state->hash[i].offset = 0;
#else
state->hash_counter[i] = 0;
#endif
}
}
static void reset_table_decompress(qlz_state_decompress *state)
{
int i;
(void)state;
(void)i;
#if QLZ_COMPRESSION_LEVEL == 2
for(i = 0; i < QLZ_HASH_VALUES; i++)
{
state->hash_counter[i] = 0;
}
#endif
}
static __inline ui32 hash_func(ui32 i)
{
#if QLZ_COMPRESSION_LEVEL == 2
return ((i >> 9) ^ (i >> 13) ^ i) & (QLZ_HASH_VALUES - 1);
#else
return ((i >> 12) ^ i) & (QLZ_HASH_VALUES - 1);
#endif
}
static __inline ui32 fast_read(void const *src, ui32 bytes)
{
#ifndef X86X64
unsigned char *p = (unsigned char*)src;
switch (bytes)
{
case 4:
return(*p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24);
case 3:
return(*p | *(p + 1) << 8 | *(p + 2) << 16);
case 2:
return(*p | *(p + 1) << 8);
case 1:
return(*p);
}
return 0;
#else
if (bytes >= 1 && bytes <= 4)
return *((ui32*)src);
else
return 0;
#endif
}
static __inline ui32 hashat(const unsigned char *src)
{
ui32 fetch, hash;
fetch = fast_read(src, 3);
hash = hash_func(fetch);
return hash;
}
static __inline void fast_write(ui32 f, void *dst, size_t bytes)
{
#ifndef X86X64
unsigned char *p = (unsigned char*)dst;
switch (bytes)
{
case 4:
*p = (unsigned char)f;
*(p + 1) = (unsigned char)(f >> 8);
*(p + 2) = (unsigned char)(f >> 16);
*(p + 3) = (unsigned char)(f >> 24);
return;
case 3:
*p = (unsigned char)f;
*(p + 1) = (unsigned char)(f >> 8);
*(p + 2) = (unsigned char)(f >> 16);
return;
case 2:
*p = (unsigned char)f;
*(p + 1) = (unsigned char)(f >> 8);
return;
case 1:
*p = (unsigned char)f;
return;
}
#else
switch (bytes)
{
case 4:
*((ui32*)dst) = f;
return;
case 3:
*((ui32*)dst) = f;
return;
case 2:
*((ui16 *)dst) = (ui16)f;
return;
case 1:
*((unsigned char*)dst) = (unsigned char)f;
return;
}
#endif
}
size_t qlz_size_decompressed(const char *source)
{
ui32 n, r;
n = (((*source) & 2) == 2) ? 4 : 1;
r = fast_read(source + 1 + n, n);
r = r & (0xffffffff >> ((4 - n)*8));
return r;
}
size_t qlz_size_compressed(const char *source)
{
ui32 n, r;
n = (((*source) & 2) == 2) ? 4 : 1;
r = fast_read(source + 1, n);
r = r & (0xffffffff >> ((4 - n)*8));
return r;
}
size_t qlz_size_header(const char *source)
{
size_t n = 2*((((*source) & 2) == 2) ? 4 : 1) + 1;
return n;
}
static __inline void memcpy_up(unsigned char *dst, const unsigned char *src, ui32 n)
{
// Caution if modifying memcpy_up! Overlap of dst and src must be special handled.
#ifndef X86X64
unsigned char *end = dst + n;
while(dst < end)
{
*dst = *src;
dst++;
src++;
}
#else
ui32 f = 0;
do
{
*(ui32 *)(dst + f) = *(ui32 *)(src + f);
f += MINOFFSET + 1;
}
while (f < n);
#endif
}
static __inline void update_hash(qlz_state_decompress *state, const unsigned char *s)
{
#if QLZ_COMPRESSION_LEVEL == 1
ui32 hash;
hash = hashat(s);
state->hash[hash].offset = s;
state->hash_counter[hash] = 1;
#elif QLZ_COMPRESSION_LEVEL == 2
ui32 hash;
unsigned char c;
hash = hashat(s);
c = state->hash_counter[hash];
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = s;
c++;
state->hash_counter[hash] = c;
#endif
(void)state;
(void)s;
}
#if QLZ_COMPRESSION_LEVEL <= 2
static void update_hash_upto(qlz_state_decompress *state, unsigned char **lh, const unsigned char *max)
{
while(*lh < max)
{
(*lh)++;
update_hash(state, *lh);
}
}
#endif
static size_t qlz_compress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_compress *state)
{
const unsigned char *last_byte = source + size - 1;
const unsigned char *src = source;
unsigned char *cword_ptr = destination;
unsigned char *dst = destination + CWORD_LEN;
ui32 cword_val = 1U << 31;
const unsigned char *last_matchstart = last_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END;
ui32 fetch = 0;
unsigned int lits = 0;
(void) lits;
if(src <= last_matchstart)
fetch = fast_read(src, 3);
while(src <= last_matchstart)
{
if ((cword_val & 1) == 1)
{
// store uncompressed if compression ratio is too low
if (src > source + (size >> 1) && dst - destination > src - source - ((src - source) >> 5))
return 0;
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
cword_ptr = dst;
dst += CWORD_LEN;
cword_val = 1U << 31;
fetch = fast_read(src, 3);
}
#if QLZ_COMPRESSION_LEVEL == 1
{
const unsigned char *o;
ui32 hash, cached;
hash = hash_func(fetch);
cached = fetch ^ state->hash[hash].cache;
state->hash[hash].cache = fetch;
o = state->hash[hash].offset + OFFSET_BASE;
state->hash[hash].offset = CAST(src - OFFSET_BASE);
#ifdef X86X64
if ((cached & 0xffffff) == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6))))
{
if(cached != 0)
{
#else
if (cached == 0 && o != OFFSET_BASE && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > source + 3 && same(src - 3, 6))))
{
if (*(o + 3) != *(src + 3))
{
#endif
hash <<= 4;
cword_val = (cword_val >> 1) | (1U << 31);
fast_write((3 - 2) | hash, dst, 2);
src += 3;
dst += 2;
}
else
{
const unsigned char *old_src = src;
size_t matchlen;
hash <<= 4;
cword_val = (cword_val >> 1) | (1U << 31);
src += 4;
if(*(o + (src - old_src)) == *src)
{
src++;
if(*(o + (src - old_src)) == *src)
{
size_t q = last_byte - UNCOMPRESSED_END - (src - 5) + 1;
size_t remaining = q > 255 ? 255 : q;
src++;
while(*(o + (src - old_src)) == *src && (size_t)(src - old_src) < remaining)
src++;
}
}
matchlen = src - old_src;
if (matchlen < 18)
{
fast_write((ui32)(matchlen - 2) | hash, dst, 2);
dst += 2;
}
else
{
fast_write((ui32)(matchlen << 16) | hash, dst, 3);
dst += 3;
}
}
fetch = fast_read(src, 3);
lits = 0;
}
else
{
lits++;
*dst = *src;
src++;
dst++;
cword_val = (cword_val >> 1);
#ifdef X86X64
fetch = fast_read(src, 3);
#else
fetch = (fetch >> 8 & 0xffff) | (*(src + 2) << 16);
#endif
}
}
#elif QLZ_COMPRESSION_LEVEL >= 2
{
const unsigned char *o, *offset2;
ui32 hash, matchlen, k, m, best_k = 0;
unsigned char c;
size_t remaining = (last_byte - UNCOMPRESSED_END - src + 1) > 255 ? 255 : (last_byte - UNCOMPRESSED_END - src + 1);
(void)best_k;
//hash = hashat(src);
fetch = fast_read(src, 3);
hash = hash_func(fetch);
c = state->hash_counter[hash];
offset2 = state->hash[hash].offset[0];
if(offset2 < src - MINOFFSET && c > 0 && ((fast_read(offset2, 3) ^ fetch) & 0xffffff) == 0)
{
matchlen = 3;
if(*(offset2 + matchlen) == *(src + matchlen))
{
matchlen = 4;
while(*(offset2 + matchlen) == *(src + matchlen) && matchlen < remaining)
matchlen++;
}
}
else
matchlen = 0;
for(k = 1; k < QLZ_POINTERS && c > k; k++)
{
o = state->hash[hash].offset[k];
#if QLZ_COMPRESSION_LEVEL == 3
if(((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET)
#elif QLZ_COMPRESSION_LEVEL == 2
if(*(src + matchlen) == *(o + matchlen) && ((fast_read(o, 3) ^ fetch) & 0xffffff) == 0 && o < src - MINOFFSET)
#endif
{
m = 3;
while(*(o + m) == *(src + m) && m < remaining)
m++;
#if QLZ_COMPRESSION_LEVEL == 3
if ((m > matchlen) || (m == matchlen && o > offset2))
#elif QLZ_COMPRESSION_LEVEL == 2
if (m > matchlen)
#endif
{
offset2 = o;
matchlen = m;
best_k = k;
}
}
}
o = offset2;
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src;
c++;
state->hash_counter[hash] = c;
#if QLZ_COMPRESSION_LEVEL == 3
if(matchlen > 2 && src - o < 131071)
{
ui32 u;
size_t offset = src - o;
for(u = 1; u < matchlen; u++)
{
hash = hashat(src + u);
c = state->hash_counter[hash]++;
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src + u;
}
cword_val = (cword_val >> 1) | (1U << 31);
src += matchlen;
if(matchlen == 3 && offset <= 63)
{
*dst = (unsigned char)(offset << 2);
dst++;
}
else if (matchlen == 3 && offset <= 16383)
{
ui32 f = (ui32)((offset << 2) | 1);
fast_write(f, dst, 2);
dst += 2;
}
else if (matchlen <= 18 && offset <= 1023)
{
ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2;
fast_write(f, dst, 2);
dst += 2;
}
else if(matchlen <= 33)
{
ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3;
fast_write(f, dst, 3);
dst += 3;
}
else
{
ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3;
fast_write(f, dst, 4);
dst += 4;
}
}
else
{
*dst = *src;
src++;
dst++;
cword_val = (cword_val >> 1);
}
#elif QLZ_COMPRESSION_LEVEL == 2
if(matchlen > 2)
{
cword_val = (cword_val >> 1) | (1U << 31);
src += matchlen;
if (matchlen < 10)
{
ui32 f = best_k | ((matchlen - 2) << 2) | (hash << 5);
fast_write(f, dst, 2);
dst += 2;
}
else
{
ui32 f = best_k | (matchlen << 16) | (hash << 5);
fast_write(f, dst, 3);
dst += 3;
}
}
else
{
*dst = *src;
src++;
dst++;
cword_val = (cword_val >> 1);
}
#endif
}
#endif
}
while (src <= last_byte)
{
if ((cword_val & 1) == 1)
{
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
cword_ptr = dst;
dst += CWORD_LEN;
cword_val = 1U << 31;
}
#if QLZ_COMPRESSION_LEVEL < 3
if (src <= last_byte - 3)
{
#if QLZ_COMPRESSION_LEVEL == 1
ui32 hash, fetch;
fetch = fast_read(src, 3);
hash = hash_func(fetch);
state->hash[hash].offset = CAST(src - OFFSET_BASE);
state->hash[hash].cache = fetch;
#elif QLZ_COMPRESSION_LEVEL == 2
ui32 hash;
unsigned char c;
hash = hashat(src);
c = state->hash_counter[hash];
state->hash[hash].offset[c & (QLZ_POINTERS - 1)] = src;
c++;
state->hash_counter[hash] = c;
#endif
}
#endif
*dst = *src;
src++;
dst++;
cword_val = (cword_val >> 1);
}
while((cword_val & 1) != 1)
cword_val = (cword_val >> 1);
fast_write((cword_val >> 1) | (1U << 31), cword_ptr, CWORD_LEN);
// min. size must be 9 bytes so that the qlz_size functions can take 9 bytes as argument
return dst - destination < 9 ? 9 : dst - destination;
}
static size_t qlz_decompress_core(const unsigned char *source, unsigned char *destination, size_t size, qlz_state_decompress *state, const unsigned char *history)
{
const unsigned char *src = source + qlz_size_header((const char *)source);
unsigned char *dst = destination;
const unsigned char *last_destination_byte = destination + size - 1;
ui32 cword_val = 1;
const unsigned char *last_matchstart = last_destination_byte - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END;
unsigned char *last_hashed = destination - 1;
const unsigned char *last_source_byte = source + qlz_size_compressed((const char *)source) - 1;
static const ui32 bitlut[16] = {4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
(void) last_source_byte;
(void) last_hashed;
(void) state;
(void) history;
for(;;)
{
ui32 fetch;
if (cword_val == 1)
{
#ifdef QLZ_MEMORY_SAFE
if(src + CWORD_LEN - 1 > last_source_byte)
return 0;
#endif
cword_val = fast_read(src, CWORD_LEN);
src += CWORD_LEN;
}
#ifdef QLZ_MEMORY_SAFE
if(src + 4 - 1 > last_source_byte)
return 0;
#endif
fetch = fast_read(src, 4);
if ((cword_val & 1) == 1)
{
ui32 matchlen;
const unsigned char *offset2;
#if QLZ_COMPRESSION_LEVEL == 1
ui32 hash;
cword_val = cword_val >> 1;
hash = (fetch >> 4) & 0xfff;
offset2 = (const unsigned char *)(size_t)state->hash[hash].offset;
if((fetch & 0xf) != 0)
{
matchlen = (fetch & 0xf) + 2;
src += 2;
}
else
{
matchlen = *(src + 2);
src += 3;
}
#elif QLZ_COMPRESSION_LEVEL == 2
ui32 hash;
unsigned char c;
cword_val = cword_val >> 1;
hash = (fetch >> 5) & 0x7ff;
c = (unsigned char)(fetch & 0x3);
offset2 = state->hash[hash].offset[c];
if((fetch & (28)) != 0)
{
matchlen = ((fetch >> 2) & 0x7) + 2;
src += 2;
}
else
{
matchlen = *(src + 2);
src += 3;
}
#elif QLZ_COMPRESSION_LEVEL == 3
ui32 offset;
cword_val = cword_val >> 1;
if ((fetch & 3) == 0)
{
offset = (fetch & 0xff) >> 2;
matchlen = 3;
src++;
}
else if ((fetch & 2) == 0)
{
offset = (fetch & 0xffff) >> 2;
matchlen = 3;
src += 2;
}
else if ((fetch & 1) == 0)
{
offset = (fetch & 0xffff) >> 6;
matchlen = ((fetch >> 2) & 15) + 3;
src += 2;
}
else if ((fetch & 127) != 3)
{
offset = (fetch >> 7) & 0x1ffff;
matchlen = ((fetch >> 2) & 0x1f) + 2;
src += 3;
}
else
{
offset = (fetch >> 15);
matchlen = ((fetch >> 7) & 255) + 3;
src += 4;
}
offset2 = dst - offset;
#endif
#ifdef QLZ_MEMORY_SAFE
if(offset2 < history || offset2 > dst - MINOFFSET - 1)
return 0;
if(matchlen > (ui32)(last_destination_byte - dst - UNCOMPRESSED_END + 1))
return 0;
#endif
memcpy_up(dst, offset2, matchlen);
dst += matchlen;
#if QLZ_COMPRESSION_LEVEL <= 2
update_hash_upto(state, &last_hashed, dst - matchlen);
last_hashed = dst - 1;
#endif
}
else
{
if (dst < last_matchstart)
{
unsigned int n = bitlut[cword_val & 0xf];
#ifdef X86X64
*(ui32 *)dst = *(ui32 *)src;
#else
memcpy_up(dst, src, 4);
#endif
cword_val = cword_val >> n;
dst += n;
src += n;
#if QLZ_COMPRESSION_LEVEL <= 2
update_hash_upto(state, &last_hashed, dst - 3);
#endif
}
else
{
while(dst <= last_destination_byte)
{
if (cword_val == 1)
{
src += CWORD_LEN;
cword_val = 1U << 31;
}
#ifdef QLZ_MEMORY_SAFE
if(src >= last_source_byte + 1)
return 0;
#endif
*dst = *src;
dst++;
src++;
cword_val = cword_val >> 1;
}
#if QLZ_COMPRESSION_LEVEL <= 2
update_hash_upto(state, &last_hashed, last_destination_byte - 3); // todo, use constant
#endif
return size;
}
}
}
}
size_t qlz_compress(const void *source, char *destination, size_t size, qlz_state_compress *state)
{
size_t r;
ui32 compressed;
size_t base;
if(size == 0 || size > 0xffffffff - 400)
return 0;
if(size < 216)
base = 3;
else
base = 9;
#if QLZ_STREAMING_BUFFER > 0
if (state->stream_counter + size - 1 >= QLZ_STREAMING_BUFFER)
#endif
{
reset_table_compress(state);
r = base + qlz_compress_core((const unsigned char *)source, (unsigned char*)destination + base, size, state);
#if QLZ_STREAMING_BUFFER > 0
reset_table_compress(state);
#endif
if(r == base)
{
memcpy(destination + base, source, size);
r = size + base;
compressed = 0;
}
else
{
compressed = 1;
}
state->stream_counter = 0;
}
#if QLZ_STREAMING_BUFFER > 0
else
{
unsigned char *src = state->stream_buffer + state->stream_counter;
memcpy(src, source, size);
r = base + qlz_compress_core(src, (unsigned char*)destination + base, size, state);
if(r == base)
{
memcpy(destination + base, src, size);
r = size + base;
compressed = 0;
reset_table_compress(state);
}
else
{
compressed = 1;
}
state->stream_counter += size;
}
#endif
if(base == 3)
{
*destination = (unsigned char)(0 | compressed);
*(destination + 1) = (unsigned char)r;
*(destination + 2) = (unsigned char)size;
}
else
{
*destination = (unsigned char)(2 | compressed);
fast_write((ui32)r, destination + 1, 4);
fast_write((ui32)size, destination + 5, 4);
}
*destination |= (QLZ_COMPRESSION_LEVEL << 2);
*destination |= (1 << 6);
*destination |= ((QLZ_STREAMING_BUFFER == 0 ? 0 : (QLZ_STREAMING_BUFFER == 100000 ? 1 : (QLZ_STREAMING_BUFFER == 1000000 ? 2 : 3))) << 4);
// 76543210
// 01SSLLHC
return r;
}
size_t qlz_decompress(const char *source, void *destination, qlz_state_decompress *state)
{
size_t dsiz = qlz_size_decompressed(source);
#if QLZ_STREAMING_BUFFER > 0
if (state->stream_counter + qlz_size_decompressed(source) - 1 >= QLZ_STREAMING_BUFFER)
#endif
{
if((*source & 1) == 1)
{
reset_table_decompress(state);
dsiz = qlz_decompress_core((const unsigned char *)source, (unsigned char *)destination, dsiz, state, (const unsigned char *)destination);
}
else
{
memcpy(destination, source + qlz_size_header(source), dsiz);
}
state->stream_counter = 0;
reset_table_decompress(state);
}
#if QLZ_STREAMING_BUFFER > 0
else
{
unsigned char *dst = state->stream_buffer + state->stream_counter;
if((*source & 1) == 1)
{
dsiz = qlz_decompress_core((const unsigned char *)source, dst, dsiz, state, (const unsigned char *)state->stream_buffer);
}
else
{
memcpy(dst, source + qlz_size_header(source), dsiz);
reset_table_decompress(state);
}
memcpy(destination, dst, dsiz);
state->stream_counter += dsiz;
}
#endif
return dsiz;
}

View file

@ -89,7 +89,7 @@ static char keytranslation[SDL_NUM_SCANCODES];
static int32_t buildkeytranslationtable(void); static int32_t buildkeytranslationtable(void);
//static SDL_Surface * loadtarga(const char *fn); // for loading the icon //static SDL_Surface * loadtarga(const char *fn); // for loading the icon
static SDL_Surface * appicon; static SDL_Surface * appicon = NULL;
static SDL_Surface * loadappicon(void); static SDL_Surface * loadappicon(void);
int32_t wm_msgbox(char *name, char *fmt, ...) int32_t wm_msgbox(char *name, char *fmt, ...)
@ -337,7 +337,10 @@ void uninitsystem(void)
uninittimer(); uninittimer();
if (appicon) if (appicon)
{
SDL_FreeSurface(appicon); SDL_FreeSurface(appicon);
appicon = NULL;
}
SDL_Quit(); SDL_Quit();

View file

@ -3405,6 +3405,8 @@ static int32_t SetupOpenGL(int32_t width, int32_t height, int32_t bitspp)
{ {
if (!Bstrcmp(glinfo.renderer,"Intel 865G")) if (!Bstrcmp(glinfo.renderer,"Intel 865G"))
err = 0; err = 0;
else if (!Bstrcmp(glinfo.renderer,"Intel 915G"))
err = 0;
else if (!Bstrcmp(glinfo.renderer,"Intel 945GM")) else if (!Bstrcmp(glinfo.renderer,"Intel 945GM"))
err = 0; err = 0;
else if (!Bstrcmp(glinfo.renderer,"Intel 965/963 Graphics Media Accelerator")) else if (!Bstrcmp(glinfo.renderer,"Intel 965/963 Graphics Media Accelerator"))

View file

@ -108,10 +108,6 @@
RelativePath=".\build\include\enet_mmulti.h" RelativePath=".\build\include\enet_mmulti.h"
> >
</File> </File>
<File
RelativePath=".\build\include\fastlz.h"
>
</File>
<File <File
RelativePath=".\build\include\glbuild.h" RelativePath=".\build\include\glbuild.h"
> >
@ -152,10 +148,6 @@
RelativePath=".\build\include\mmulti_unstable.h" RelativePath=".\build\include\mmulti_unstable.h"
> >
</File> </File>
<File
RelativePath=".\build\include\mmultimsgs.h"
>
</File>
<File <File
RelativePath=".\build\include\nedmalloc.h" RelativePath=".\build\include\nedmalloc.h"
> >
@ -184,6 +176,10 @@
RelativePath=".\build\include\pragmas.h" RelativePath=".\build\include\pragmas.h"
> >
</File> </File>
<File
RelativePath=".\build\include\quicklz.h"
>
</File>
<File <File
RelativePath=".\build\include\scriptfile.h" RelativePath=".\build\include\scriptfile.h"
> >
@ -260,10 +256,6 @@
RelativePath=".\build\src\engine_priv.h" RelativePath=".\build\src\engine_priv.h"
> >
</File> </File>
<File
RelativePath=".\build\src\fastlz.c"
>
</File>
<File <File
RelativePath=".\build\src\glbuild.c" RelativePath=".\build\src\glbuild.c"
> >
@ -316,6 +308,10 @@
RelativePath=".\build\src\pragmas.c" RelativePath=".\build\src\pragmas.c"
> >
</File> </File>
<File
RelativePath=".\build\src\quicklz.c"
>
</File>
<File <File
RelativePath=".\build\src\scriptfile.c" RelativePath=".\build\src\scriptfile.c"
> >
@ -778,6 +774,86 @@
Name="Misc" Name="Misc"
> >
</Filter> </Filter>
<Filter
Name="enet"
>
<Filter
Name="source"
>
<File
RelativePath=".\source\enet\src\callbacks.c"
>
</File>
<File
RelativePath=".\source\enet\src\host.c"
>
</File>
<File
RelativePath=".\source\enet\src\list.c"
>
</File>
<File
RelativePath=".\source\enet\src\packet.c"
>
</File>
<File
RelativePath=".\source\enet\src\peer.c"
>
</File>
<File
RelativePath=".\source\enet\src\protocol.c"
>
</File>
<File
RelativePath=".\source\enet\src\unix.c"
>
</File>
<File
RelativePath=".\source\enet\src\win32.c"
>
</File>
</Filter>
<Filter
Name="headers"
>
<File
RelativePath=".\source\enet\include\enet\callbacks.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\enet.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\list.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\protocol.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\time.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\types.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\unix.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\utility.h"
>
</File>
<File
RelativePath=".\source\enet\include\enet\win32.h"
>
</File>
</Filter>
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>

View file

@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern int32_t g_numEnvSoundsPlaying; extern int32_t g_numEnvSoundsPlaying;
extern int32_t g_noEnemies; extern int32_t g_noEnemies;
extern int32_t ticrandomseed;
inline void G_UpdateInterpolations(void) //Stick at beginning of G_DoMoveThings inline void G_UpdateInterpolations(void) //Stick at beginning of G_DoMoveThings
{ {
@ -4832,6 +4833,9 @@ static void G_MoveMisc(void) // STATNUM 5
ActorExtra[i].floorz = s->z = getflorzofslope(s->sectnum,s->x,s->y); ActorExtra[i].floorz = s->z = getflorzofslope(s->sectnum,s->x,s->y);
else switch (DynamicTileMap[switchpicnum]) else switch (DynamicTileMap[switchpicnum])
{ {
case APLAYER__STATIC:
s->cstat = 32768;
goto BOLT;
case NEON1__STATIC: case NEON1__STATIC:
case NEON2__STATIC: case NEON2__STATIC:
case NEON3__STATIC: case NEON3__STATIC:
@ -5670,7 +5674,7 @@ static void G_MoveEffectors(void) //STATNUM 3
m = (s->xvel*sintable[(s->ang+512)&2047])>>14; m = (s->xvel*sintable[(s->ang+512)&2047])>>14;
x = (s->xvel*sintable[s->ang&2047])>>14; x = (s->xvel*sintable[s->ang&2047])>>14;
for (p = connecthead; p >= 0; p=connectpoint2[p]) TRAVERSE_CONNECT(p)
if (sector[g_player[p].ps->cursectnum].lotag != 2) if (sector[g_player[p].ps->cursectnum].lotag != 2)
{ {
if (g_playerSpawnPoints[p].os == s->sectnum) if (g_playerSpawnPoints[p].os == s->sectnum)
@ -5849,7 +5853,7 @@ static void G_MoveEffectors(void) //STATNUM 3
} }
} }
for (p = connecthead; p >= 0; p = connectpoint2[p]) TRAVERSE_CONNECT(p)
{ {
if (sprite[g_player[p].ps->i].sectnum == s->sectnum) if (sprite[g_player[p].ps->i].sectnum == s->sectnum)
{ {
@ -7135,7 +7139,7 @@ static void G_MoveEffectors(void) //STATNUM 3
fricyv += x<<5; fricyv += x<<5;
} }
for (p = connecthead; p >= 0; p = connectpoint2[p]) TRAVERSE_CONNECT(p)
if (sprite[g_player[p].ps->i].sectnum == s->sectnum && g_player[p].ps->on_ground) if (sprite[g_player[p].ps->i].sectnum == s->sectnum && g_player[p].ps->on_ground)
g_player[p].ps->posz += s->zvel; g_player[p].ps->posz += s->zvel;

View file

@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "fx_man.h" #include "fx_man.h"
#include "macros.h" #include "macros.h"
#include "fastlz.h" #include "quicklz.h"
#include "m32script.h" #include "m32script.h"
#include "m32def.h" #include "m32def.h"
@ -244,8 +244,8 @@ void create_map_snapshot(void)
else else
{ {
mapstate->sectors = (sectortype *)Bcalloc(1, sizeof(sectortype) * numsectors); mapstate->sectors = (sectortype *)Bcalloc(1, sizeof(sectortype) * numsectors);
mapstate->sectsiz = j = fastlz_compress(&sector[0], sizeof(sectortype) * numsectors, mapstate->sectsiz = j = qlz_compress(&sector[0], (char *)&mapstate->sectors[0],
&mapstate->sectors[0]/*, sizeof(sectortype) * numsectors*/); sizeof(sectortype) * numsectors, state_compress);
mapstate->sectors = (sectortype *)Brealloc(mapstate->sectors, j); mapstate->sectors = (sectortype *)Brealloc(mapstate->sectors, j);
mapstate->sectcrc = tempcrc; mapstate->sectcrc = tempcrc;
} }
@ -265,8 +265,8 @@ void create_map_snapshot(void)
else else
{ {
mapstate->walls = (walltype *)Bcalloc(1, sizeof(walltype) * numwalls); mapstate->walls = (walltype *)Bcalloc(1, sizeof(walltype) * numwalls);
mapstate->wallsiz = j = fastlz_compress(&wall[0], sizeof(walltype) * numwalls, mapstate->wallsiz = j = qlz_compress(&wall[0], (char *)&mapstate->walls[0],
&mapstate->walls[0]/*, sizeof(walltype) * numwalls*/); sizeof(walltype) * numwalls, state_compress);
mapstate->walls = (walltype *)Brealloc(mapstate->walls, j); mapstate->walls = (walltype *)Brealloc(mapstate->walls, j);
mapstate->wallcrc = tempcrc; mapstate->wallcrc = tempcrc;
} }
@ -298,8 +298,8 @@ void create_map_snapshot(void)
i++; i++;
} }
} }
mapstate->spritesiz = j = fastlz_compress(&tspri[0], sizeof(spritetype) * numsprites, mapstate->spritesiz = j = qlz_compress(&tspri[0], (char *)&mapstate->sprites[0],
&mapstate->sprites[0]/*, sizeof(spritetype) * numsprites*/); sizeof(spritetype) * numsprites, state_compress);
mapstate->sprites = (spritetype *)Brealloc(mapstate->sprites, j); mapstate->sprites = (spritetype *)Brealloc(mapstate->sprites, j);
mapstate->spritecrc = tempcrc; mapstate->spritecrc = tempcrc;
Bfree(tspri); Bfree(tspri);
@ -370,13 +370,13 @@ int32_t map_undoredo(int32_t dir)
if (mapstate->numsectors) if (mapstate->numsectors)
{ {
fastlz_decompress(&mapstate->sectors[0], mapstate->sectsiz, &sector[0], sizeof(sectortype) * numsectors); qlz_decompress((const char *)&mapstate->sectors[0], &sector[0], state_decompress);
if (mapstate->numwalls) if (mapstate->numwalls)
fastlz_decompress(&mapstate->walls[0], mapstate->wallsiz, &wall[0], sizeof(walltype) * numwalls); qlz_decompress((const char *)&mapstate->walls[0], &wall[0], state_decompress);
if (mapstate->numsprites) if (mapstate->numsprites)
fastlz_decompress(&mapstate->sprites[0], mapstate->spritesiz, &sprite[0], sizeof(spritetype) * numsprites); qlz_decompress((const char *)&mapstate->sprites[0], &sprite[0], state_decompress);
} }
updatenumsprites(); updatenumsprites();

View file

@ -47,6 +47,12 @@ extern "C" {
#include "macros.h" #include "macros.h"
#include "enet/enet.h"
extern ENetHost * net_server;
extern ENetHost * net_client;
extern ENetPeer * net_peer;
#define APPNAME "EDuke32" #define APPNAME "EDuke32"
#define VERSION " 2.0.0devel" #define VERSION " 2.0.0devel"
// this is checked against http://eduke32.com/VERSION // this is checked against http://eduke32.com/VERSION
@ -83,7 +89,7 @@ extern int32_t g_scriptVersion, g_Shareware, g_gameType;
#define AUTO_AIM_ANGLE 48 #define AUTO_AIM_ANGLE 48
#define RECSYNCBUFSIZ 2520 //2520 is the (LCM of 1-8)*3 #define RECSYNCBUFSIZ 2520 //2520 is the (LCM of 1-8)*3
#define MOVEFIFOSIZ 256 #define MOVEFIFOSIZ 2
#define FOURSLEIGHT (1<<8) #define FOURSLEIGHT (1<<8)
@ -422,9 +428,9 @@ extern int32_t fricxv,fricyv;
// mywhatever type globals // mywhatever type globals
typedef struct { typedef struct {
int32_t posx, posy, posz, horiz, ohoriz, ohorizoff, invdisptime; int32_t posx, posy, posz, oposx, oposy, oposz, posxv, posyv, poszv;
int32_t bobposx, bobposy, oposx, oposy, oposz, pyoff, opyoff; int32_t bobposx, bobposy, pyoff, opyoff, horiz, ohoriz, ohorizoff, invdisptime;
int32_t posxv, posyv, poszv, last_pissed_time, truefz, truecz; int32_t last_pissed_time, truefz, truecz;
int32_t player_par, visibility; int32_t player_par, visibility;
int32_t bobcounter, weapon_sway; int32_t bobcounter, weapon_sway;
int32_t pals_time, randomflamex, crack_time; int32_t pals_time, randomflamex, crack_time;
@ -485,7 +491,7 @@ typedef struct {
char name[32]; char name[32];
} DukePlayer_t; } DukePlayer_t;
extern char tempbuf[2048], packbuf[576], menutextbuf[128]; extern char tempbuf[2048], packbuf[4096], menutextbuf[128];
extern int32_t g_spriteGravity; extern int32_t g_spriteGravity;
@ -559,9 +565,9 @@ typedef struct {
void *lightptr; void *lightptr;
#endif #endif
int8_t filler[16]; // pad struct to 128 bytes
projectile_t *projectile; //4b/8b projectile_t *projectile; //4b/8b
int8_t filler[16]; // pad struct to 128 bytes
} ActorData_t; } ActorData_t;
extern ActorData_t ActorExtra[MAXSPRITES]; extern ActorData_t ActorExtra[MAXSPRITES];
@ -638,8 +644,6 @@ extern char boardfilename[BMAX_PATH];
extern uint8_t waterpal[768],slimepal[768],titlepal[768],drealms[768],endingpal[768],animpal[768]; extern uint8_t waterpal[768],slimepal[768],titlepal[768],drealms[768],endingpal[768],animpal[768];
extern char currentboardfilename[BMAX_PATH]; extern char currentboardfilename[BMAX_PATH];
extern char cachedebug,g_earthquakeTime; extern char cachedebug,g_earthquakeTime;
// 0: master/slave, 1: peer-to-peer
extern int32_t g_networkBroadcastMode;
extern char lumplockbyte[11]; extern char lumplockbyte[11];
//DUKE3D.H - replace the end "my's" with this //DUKE3D.H - replace the end "my's" with this
@ -670,7 +674,6 @@ typedef struct {
extern DukeStatus_t sbar; extern DukeStatus_t sbar;
extern int32_t g_cameraDistance, g_cameraClock, g_playerFriction,g_showShareware; extern int32_t g_cameraDistance, g_cameraClock, g_playerFriction,g_showShareware;
extern int32_t g_networkBroadcastMode, g_movesPerPacket;
extern int32_t g_gameQuit; extern int32_t g_gameQuit;
extern int32_t playerswhenstarted; extern int32_t playerswhenstarted;
@ -1042,6 +1045,9 @@ typedef struct {
walltype wall[MAXWALLS]; walltype wall[MAXWALLS];
} mapstate_t; } mapstate_t;
extern void G_SaveMapState(mapstate_t *save);
extern void G_RestoreMapState(mapstate_t *save);
typedef struct { typedef struct {
int32_t partime, designertime; int32_t partime, designertime;
char *name, *filename, *musicfn, *alt_musicfn; char *name, *filename, *musicfn, *alt_musicfn;
@ -1088,12 +1094,13 @@ enum DukePacket_t
{ {
PACKET_MASTER_TO_SLAVE, PACKET_MASTER_TO_SLAVE,
PACKET_SLAVE_TO_MASTER, PACKET_SLAVE_TO_MASTER,
PACKET_BROADCAST,
SERVER_GENERATED_BROADCAST,
PACKET_VERSION, PACKET_VERSION,
/* don't change anything above this line */ /* don't change anything above this line */
PACKET_NUM_PLAYERS,
PACKET_PLAYER_INDEX,
PACKET_PLAYER_DISCONNECTED,
PACKET_MESSAGE, PACKET_MESSAGE,
PACKET_NEW_GAME, PACKET_NEW_GAME,
@ -1103,6 +1110,7 @@ enum DukePacket_t
PACKET_PLAYER_OPTIONS, PACKET_PLAYER_OPTIONS,
PACKET_PLAYER_NAME, PACKET_PLAYER_NAME,
PACKET_REQUEST_GAMESTATE,
PACKET_USER_MAP, PACKET_USER_MAP,
PACKET_MAP_VOTE, PACKET_MAP_VOTE,

View file

@ -0,0 +1,60 @@
CC=gcc
OBJ=obj
OBJNAME?=libenet.a
PRETTY_OUTPUT?=1
EROOT?=build
RELEASE?=1
OPTLEVEL?=2
SRC=src
include ../../$(EROOT)/Makefile.shared
ifneq (0,$(RELEASE))
# Debugging disabled
debug=-fomit-frame-pointer -funswitch-loops -O$(OPTLEVEL)
else
# Debugging enabled
debug=-ggdb -O0 -DDEBUGGINGAIDS
endif
ifneq (0,$(DEBUGANYWAY))
debug+=-ggdb
endif
CFLAGS=$(debug) -W -Wall -Wimplicit -Werror-implicit-function-declaration \
-funsigned-char -fno-strict-aliasing -DNO_GCC_BUILTINS -D_FORTIFY_SOURCE=2 \
-fjump-tables -fno-stack-protector
CPPFLAGS=-Iinclude -Isrc -DHAVE_VORBIS
OBJECTS=$(OBJ)/callbacks.o \
$(OBJ)/host.o \
$(OBJ)/list.o \
$(OBJ)/packet.o \
$(OBJ)/peer.o \
$(OBJ)/protocol.o
ifeq ($(PLATFORM),WINDOWS)
OBJECTS+= $(OBJ)/win32.o
OBJNAME=libenet_win32.a
OBJ=obj_win
else
OBJECTS+= $(OBJ)/unix.o
endif
# OBJECTS=$(SOURCES:%.c=$(OBJ)/%.o)
$(OBJNAME): $(OBJECTS)
$(AR) cr $@ $^
$(OBJECTS): $(OBJ)/%.o: $(SRC)/%.c
-mkdir -p $(OBJ)
$(COMPILE_STATUS)
if $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@; then $(COMPILE_OK); else $(COMPILE_FAILED); fi
ifeq ($(PRETTY_OUTPUT),1)
.SILENT:
endif
.PHONY: clean
clean:
-rm -f $(OBJECTS) $(OBJNAME)

View file

@ -0,0 +1,45 @@
OBJ=obj.msc
INC=include
SRC=src
ENETLIB=libenet.lib
!ifdef DEBUG
# debugging options
flags_cl=/Od /Zi
flags_link=/DEBUG
flags_lib=
!else
# release options
flags_cl=/Ox /GL /arch:SSE
flags_link=/RELEASE /LTCG
flags_lib=/LTCG
!endif
CC=cl
LINK=link /opt:ref /nologo
CFLAGS=$(CFLAGS) /nologo /MT /J $(flags_cl) $(TARGETOPTS) /I$(INC) /I$(SRC)
!ifdef DEBUG
CFLAGS=$(CFLAGS) /DDEBUGGINGAIDS
!endif
CFLAGS=$(CFLAGS) /DRENDERTYPE$(RENDERTYPE)=1 /D "_CRT_SECURE_NO_DEPRECATE" /W2 /DHAVE_VORBIS /Iinclude/msvc /DWIN32
OBJECTS=$(OBJ)\callbacks.o \
$(OBJ)\host.o \
$(OBJ)\list.o \
$(OBJ)\packet.o \
$(OBJ)\peer.o \
$(OBJ)\protocol.o \
$(OBJ)\win32.o
{$(SRC)}.c{$(OBJ)}.o:
$(CC) /c $(CFLAGS) /Fo$@ $<
enet: $(ENETLIB)
$(ENETLIB): $(OBJECTS)
lib $(flags_lib) /out:$@ /nologo $**
clean:
-del /Q $(OBJ)\* $(ENETLIB)

View file

@ -0,0 +1,28 @@
/**
@file callbacks.h
@brief ENet callbacks
*/
#ifndef __ENET_CALLBACKS_H__
#define __ENET_CALLBACKS_H__
#include <stdlib.h>
typedef struct
{
void * (ENET_CALLBACK * malloc) (size_t size);
void (ENET_CALLBACK * free) (void * memory);
int (ENET_CALLBACK * rand) (void);
} ENetCallbacks;
/** @defgroup callbacks ENet internal callbacks
@{
@ingroup private
*/
extern void * enet_malloc (size_t);
extern void enet_free (void *);
extern int enet_rand (void);
/** @} */
#endif /* __ENET_CALLBACKS_H__ */

View file

@ -0,0 +1,492 @@
/**
@file enet.h
@brief ENet public header file
*/
#ifndef __ENET_ENET_H__
#define __ENET_ENET_H__
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdlib.h>
#ifdef WIN32
#include "enet/win32.h"
#else
#include "enet/unix.h"
#endif
#include "enet/types.h"
#include "enet/protocol.h"
#include "enet/list.h"
#include "enet/callbacks.h"
typedef enum
{
ENET_VERSION = 1
} ENetVersion;
typedef enum
{
ENET_SOCKET_TYPE_STREAM = 1,
ENET_SOCKET_TYPE_DATAGRAM = 2
} ENetSocketType;
typedef enum
{
ENET_SOCKET_WAIT_NONE = 0,
ENET_SOCKET_WAIT_SEND = (1 << 0),
ENET_SOCKET_WAIT_RECEIVE = (1 << 1)
} ENetSocketWait;
typedef enum
{
ENET_SOCKOPT_NONBLOCK = 1,
ENET_SOCKOPT_BROADCAST = 2,
ENET_SOCKOPT_RCVBUF = 3,
ENET_SOCKOPT_SNDBUF = 4,
ENET_SOCKOPT_REUSEADDR = 5
} ENetSocketOption;
enum
{
ENET_HOST_ANY = 0, /**< specifies the default server host */
ENET_HOST_BROADCAST = 0xFFFFFFFF, /**< specifies a subnet-wide broadcast */
ENET_PORT_ANY = 0 /**< specifies that a port should be automatically chosen */
};
/**
* Portable internet address structure.
*
* The host must be specified in network byte-order, and the port must be in host
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
* but not for enet_host_create. Once a server responds to a broadcast, the
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
*/
typedef struct _ENetAddress
{
enet_uint32 host;
enet_uint16 port;
} ENetAddress;
/**
* Packet flag bit constants.
*
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum
{
/** packet must be received by the target peer and resend attempts should be
* made until the packet is delivered */
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
/** packet will not be sequenced with other packets
* not supported for reliable packets
*/
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
/** packet will not allocate data, and user must supply it instead */
ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2)
} ENetPacketFlag;
struct _ENetPacket;
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
*
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
@sa ENetPacketFlag
*/
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
} ENetPacket;
typedef struct _ENetAcknowledgement
{
ENetListNode acknowledgementList;
enet_uint32 sentTime;
ENetProtocol command;
} ENetAcknowledgement;
typedef struct _ENetOutgoingCommand
{
ENetListNode outgoingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 roundTripTimeoutLimit;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
enet_uint16 sendAttempts;
ENetProtocol command;
ENetPacket * packet;
} ENetOutgoingCommand;
typedef struct _ENetIncomingCommand
{
ENetListNode incomingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
ENetProtocol command;
enet_uint32 fragmentCount;
enet_uint32 fragmentsRemaining;
enet_uint32 * fragments;
ENetPacket * packet;
} ENetIncomingCommand;
typedef enum
{
ENET_PEER_STATE_DISCONNECTED = 0,
ENET_PEER_STATE_CONNECTING = 1,
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
ENET_PEER_STATE_CONNECTION_PENDING = 3,
ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4,
ENET_PEER_STATE_CONNECTED = 5,
ENET_PEER_STATE_DISCONNECT_LATER = 6,
ENET_PEER_STATE_DISCONNECTING = 7,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
ENET_PEER_STATE_ZOMBIE = 9
} ENetPeerState;
#ifndef ENET_BUFFER_MAXIMUM
#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
#endif
enum
{
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1400,
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
ENET_PEER_TIMEOUT_LIMIT = 32,
ENET_PEER_TIMEOUT_MINIMUM = 5000,
ENET_PEER_TIMEOUT_MAXIMUM = 30000,
ENET_PEER_PING_INTERVAL = 500,
ENET_PEER_UNSEQUENCED_WINDOWS = 64,
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024,
ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32,
ENET_PEER_RELIABLE_WINDOWS = 16,
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000,
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
};
typedef struct _ENetChannel
{
enet_uint16 outgoingReliableSequenceNumber;
enet_uint16 outgoingUnreliableSequenceNumber;
enet_uint16 usedReliableWindows;
enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
enet_uint16 incomingReliableSequenceNumber;
ENetList incomingReliableCommands;
ENetList incomingUnreliableCommands;
} ENetChannel;
/**
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
enet_uint16 incomingPeerID;
enet_uint32 sessionID;
ENetAddress address; /**< Internet address of the peer */
void * data; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
size_t channelCount; /**< Number of channels allocated for communication with peer */
enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
enet_uint32 incomingBandwidthThrottleEpoch;
enet_uint32 outgoingBandwidthThrottleEpoch;
enet_uint32 incomingDataTotal;
enet_uint32 outgoingDataTotal;
enet_uint32 lastSendTime;
enet_uint32 lastReceiveTime;
enet_uint32 nextTimeout;
enet_uint32 earliestTimeout;
enet_uint32 packetLossEpoch;
enet_uint32 packetsSent;
enet_uint32 packetsLost;
enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
enet_uint32 packetLossVariance;
enet_uint32 packetThrottle;
enet_uint32 packetThrottleLimit;
enet_uint32 packetThrottleCounter;
enet_uint32 packetThrottleEpoch;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 packetThrottleInterval;
enet_uint32 lastRoundTripTime;
enet_uint32 lowestRoundTripTime;
enet_uint32 lastRoundTripTimeVariance;
enet_uint32 highestRoundTripTimeVariance;
enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
enet_uint32 roundTripTimeVariance;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 reliableDataInTransit;
enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList sentUnreliableCommands;
ENetList outgoingReliableCommands;
ENetList outgoingUnreliableCommands;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 disconnectData;
} ENetPeer;
/** An ENet host for communicating with peers.
*
* No fields should be modified.
@sa enet_host_create()
@sa enet_host_destroy()
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_broadcast()
@sa enet_host_bandwidth_limit()
@sa enet_host_bandwidth_throttle()
*/
typedef struct _ENetHost
{
ENetSocket socket;
ENetAddress address; /**< Internet address of the host */
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
enet_uint32 bandwidthThrottleEpoch;
enet_uint32 mtu;
int recalculateBandwidthLimits;
ENetPeer * peers; /**< array of peers allocated for this host */
size_t peerCount; /**< number of peers allocated for this host */
enet_uint32 serviceTime;
ENetPeer * lastServicedPeer;
int continueSending;
size_t packetSize;
enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
size_t commandCount;
ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
size_t bufferCount;
ENetAddress receivedAddress;
enet_uint8 receivedData [ENET_PROTOCOL_MAXIMUM_MTU];
size_t receivedDataLength;
} ENetHost;
/**
* An ENet event type, as specified in @ref ENetEvent.
*/
typedef enum
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_pper_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
* number upon which the packet was received. The packet field contains
* the packet that was received; this packet must be destroyed with
* enet_packet_destroy after use.
*/
ENET_EVENT_TYPE_RECEIVE = 3
} ENetEventType;
/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
enet_uint32 data; /**< data associated with the event, if appropriate */
ENetPacket * packet; /**< packet associated with the event, if appropriate */
} ENetEvent;
/** @defgroup global ENet global functions
@{
*/
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize (void);
/**
Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant.
@param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
@param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
ENET_API void enet_deinitialize (void);
/** @} */
/** @defgroup private ENet private implementation functions */
/**
Returns the wall-time in milliseconds. Its initial value is unspecified
unless otherwise set.
*/
ENET_API enet_uint32 enet_time_get (void);
/**
Sets the current wall-time in milliseconds.
*/
ENET_API void enet_time_set (enet_uint32);
/** @defgroup socket ENet socket functions
@{
*/
ENET_API ENetSocket enet_socket_create (ENetSocketType);
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_listen (ENetSocket, int);
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
ENET_API void enet_socket_destroy (ENetSocket);
ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
/** @} */
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@param hostName host name to lookup
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
/** Gives the printable form of the ip address specified in the address parameter.
@param address address printed
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
/** Attempts to do a reverse lookup of the host field in the address parameter.
@param address address used for reverse lookup
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
/** @} */
ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
ENET_API void enet_packet_destroy (ENetPacket *);
ENET_API int enet_packet_resize (ENetPacket *, size_t);
extern enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, enet_uint32, enet_uint32);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t);
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8);
ENET_API void enet_peer_ping (ENetPeer *);
ENET_API void enet_peer_reset (ENetPeer *);
ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32);
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32);
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
extern size_t enet_protocol_command_size (enet_uint8);
#ifdef __cplusplus
}
#endif
#endif /* __ENET_ENET_H__ */

View file

@ -0,0 +1,42 @@
/**
@file list.h
@brief ENet list management
*/
#ifndef __ENET_LIST_H__
#define __ENET_LIST_H__
#include <stdlib.h>
typedef struct _ENetListNode
{
struct _ENetListNode * next;
struct _ENetListNode * previous;
} ENetListNode;
typedef ENetListNode * ENetListIterator;
typedef struct _ENetList
{
ENetListNode sentinel;
} ENetList;
extern void enet_list_clear (ENetList *);
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
extern void * enet_list_remove (ENetListIterator);
extern size_t enet_list_size (ENetList *);
#define enet_list_begin(list) ((list) -> sentinel.next)
#define enet_list_end(list) (& (list) -> sentinel)
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
#define enet_list_next(iterator) ((iterator) -> next)
#define enet_list_previous(iterator) ((iterator) -> previous)
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
#endif /* __ENET_LIST_H__ */

View file

@ -0,0 +1,174 @@
/**
@file protocol.h
@brief ENet protocol
*/
#ifndef __ENET_PROTOCOL_H__
#define __ENET_PROTOCOL_H__
#include "enet/types.h"
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 32768,
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0x7FFF
};
typedef enum
{
ENET_PROTOCOL_COMMAND_NONE = 0,
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
ENET_PROTOCOL_COMMAND_CONNECT = 2,
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
ENET_PROTOCOL_COMMAND_PING = 5,
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
ENET_PROTOCOL_COMMAND_COUNT = 12,
ENET_PROTOCOL_COMMAND_MASK = 0x0F
} ENetProtocolCommand;
typedef enum
{
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
ENET_PROTOCOL_HEADER_FLAG_MASK = 0x8000
} ENetProtocolFlag;
typedef struct
{
enet_uint32 checksum;
enet_uint16 peerID;
enet_uint16 sentTime;
} ENetProtocolHeader;
typedef struct
{
enet_uint8 command;
enet_uint8 channelID;
enet_uint16 reliableSequenceNumber;
} ENetProtocolCommandHeader;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 receivedReliableSequenceNumber;
enet_uint16 receivedSentTime;
} ENetProtocolAcknowledge;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 sessionID;
} ENetProtocolConnect;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint16 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENetProtocolVerifyConnect;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
} ENetProtocolBandwidthLimit;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENetProtocolThrottleConfigure;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint32 data;
} ENetProtocolDisconnect;
typedef struct
{
ENetProtocolCommandHeader header;
} ENetProtocolPing;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 dataLength;
} ENetProtocolSendReliable;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 unreliableSequenceNumber;
enet_uint16 dataLength;
} ENetProtocolSendUnreliable;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 unsequencedGroup;
enet_uint16 dataLength;
} ENetProtocolSendUnsequenced;
typedef struct
{
ENetProtocolCommandHeader header;
enet_uint16 startSequenceNumber;
enet_uint16 dataLength;
enet_uint32 fragmentCount;
enet_uint32 fragmentNumber;
enet_uint32 totalLength;
enet_uint32 fragmentOffset;
} ENetProtocolSendFragment;
typedef union
{
ENetProtocolCommandHeader header;
ENetProtocolAcknowledge acknowledge;
ENetProtocolConnect connect;
ENetProtocolVerifyConnect verifyConnect;
ENetProtocolDisconnect disconnect;
ENetProtocolPing ping;
ENetProtocolSendReliable sendReliable;
ENetProtocolSendUnreliable sendUnreliable;
ENetProtocolSendUnsequenced sendUnsequenced;
ENetProtocolSendFragment sendFragment;
ENetProtocolBandwidthLimit bandwidthLimit;
ENetProtocolThrottleConfigure throttleConfigure;
} ENetProtocol;
#endif /* __ENET_PROTOCOL_H__ */

View file

@ -0,0 +1,18 @@
/**
@file time.h
@brief ENet time constants and macros
*/
#ifndef __ENET_TIME_H__
#define __ENET_TIME_H__
#define ENET_TIME_OVERFLOW 86400000
#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
#endif /* __ENET_TIME_H__ */

View file

@ -0,0 +1,13 @@
/**
@file types.h
@brief type definitions for ENet
*/
#ifndef __ENET_TYPES_H__
#define __ENET_TYPES_H__
typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
#endif /* __ENET_TYPES_H__ */

View file

@ -0,0 +1,45 @@
/**
@file unix.h
@brief ENet Unix header
*/
#ifndef __ENET_UNIX_H__
#define __ENET_UNIX_H__
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
typedef int ENetSocket;
enum
{
ENET_SOCKET_NULL = -1
};
#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
typedef struct
{
void * data;
size_t dataLength;
} ENetBuffer;
#define ENET_CALLBACK
#define ENET_API extern
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_UNIX_H__ */

View file

@ -0,0 +1,12 @@
/**
@file utility.h
@brief ENet utility header
*/
#ifndef __ENET_UTILITY_H__
#define __ENET_UTILITY_H__
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#endif /* __ENET_UTILITY_H__ */

View file

@ -0,0 +1,58 @@
/**
@file win32.h
@brief ENet Win32 header
*/
#ifndef __ENET_WIN32_H__
#define __ENET_WIN32_H__
#ifdef ENET_BUILDING_LIB
#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
#pragma warning (disable: 4267) // size_t to int conversion
#pragma warning (disable: 4244) // 64bit to 32bit int
#pragma warning (disable: 4018) // signed/unsigned mismatch
#endif
#include <stdlib.h>
#include <winsock2.h>
typedef SOCKET ENetSocket;
enum
{
ENET_SOCKET_NULL = INVALID_SOCKET
};
#define ENET_HOST_TO_NET_16(value) (htons (value))
#define ENET_HOST_TO_NET_32(value) (htonl (value))
#define ENET_NET_TO_HOST_16(value) (ntohs (value))
#define ENET_NET_TO_HOST_32(value) (ntohl (value))
typedef struct
{
size_t dataLength;
void * data;
} ENetBuffer;
#define ENET_CALLBACK __cdecl
#if defined ENET_DLL
#if defined ENET_BUILDING_LIB
#define ENET_API __declspec( dllexport )
#else
#define ENET_API __declspec( dllimport )
#endif /* ENET_BUILDING_LIB */
#else /* !ENET_DLL */
#define ENET_API extern
#endif /* ENET_DLL */
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_WIN32_H__ */

View file

@ -0,0 +1,53 @@
/**
@file callbacks.c
@brief ENet callback functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static ENetCallbacks callbacks = { malloc, free, rand };
int
enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
{
if (version != ENET_VERSION)
return -1;
if (inits -> malloc != NULL || inits -> free != NULL)
{
if (inits -> malloc == NULL || inits -> free == NULL)
return -1;
callbacks.malloc = inits -> malloc;
callbacks.free = inits -> free;
}
if (inits -> rand != NULL)
callbacks.rand = inits -> rand;
return enet_initialize ();
}
void *
enet_malloc (size_t size)
{
void * memory = callbacks.malloc (size);
if (memory == NULL)
abort ();
return memory;
}
void
enet_free (void * memory)
{
callbacks.free (memory);
}
int
enet_rand (void)
{
return callbacks.rand ();
}

View file

@ -0,0 +1,401 @@
/**
@file host.c
@brief ENet host management functions
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
/** @defgroup host ENet host functions
@{
*/
/** Creates a host for communicating to peers.
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@returns the host on success and NULL on failure
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
the window size of a connection which limits the amount of reliable packets that may be in transit
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
ENetHost * host = (ENetHost *) enet_malloc (sizeof (ENetHost));
ENetPeer * currentPeer;
if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
return NULL;
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
enet_socket_destroy (host -> socket);
enet_free (host -> peers);
enet_free (host);
return NULL;
}
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
if (address != NULL)
host -> address = * address;
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> bandwidthThrottleEpoch = 0;
host -> recalculateBandwidthLimits = 0;
host -> mtu = ENET_HOST_DEFAULT_MTU;
host -> peerCount = peerCount;
host -> lastServicedPeer = host -> peers;
host -> commandCount = 0;
host -> bufferCount = 0;
host -> receivedAddress.host = ENET_HOST_ANY;
host -> receivedAddress.port = 0;
host -> receivedDataLength = 0;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
currentPeer -> host = host;
currentPeer -> incomingPeerID = currentPeer - host -> peers;
currentPeer -> data = NULL;
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> sentUnreliableCommands);
enet_list_clear (& currentPeer -> outgoingReliableCommands);
enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
enet_peer_reset (currentPeer);
}
return host;
}
/** Destroys the host and all resources associated with it.
@param host pointer to the host to destroy
*/
void
enet_host_destroy (ENetHost * host)
{
ENetPeer * currentPeer;
enet_socket_destroy (host -> socket);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
enet_peer_reset (currentPeer);
}
enet_free (host -> peers);
enet_free (host);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@param channelCount number of channels to allocate
@returns a peer representing the foreign host on success, NULL on failure
@remarks The peer returned will have not completed the connection until enet_host_service()
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
*/
ENetPeer *
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount)
{
ENetPeer * currentPeer;
ENetChannel * channel;
ENetProtocol command;
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
else
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
break;
}
if (currentPeer >= & host -> peers [host -> peerCount])
return NULL;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
currentPeer -> channelCount = channelCount;
currentPeer -> sessionID = (enet_uint32) enet_rand ();
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
else
currentPeer -> windowSize = (host -> outgoingBandwidth /
ENET_PEER_WINDOW_SIZE_SCALE) *
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
else
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
for (channel = currentPeer -> channels;
channel < & currentPeer -> channels [channelCount];
++ channel)
{
channel -> outgoingReliableSequenceNumber = 0;
channel -> outgoingUnreliableSequenceNumber = 0;
channel -> incomingReliableSequenceNumber = 0;
enet_list_clear (& channel -> incomingReliableCommands);
enet_list_clear (& channel -> incomingUnreliableCommands);
channel -> usedReliableWindows = 0;
memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
}
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
command.connect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
command.connect.sessionID = currentPeer -> sessionID;
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
return currentPeer;
}
/** Queues a packet to be sent to all peers associated with the host.
@param host host on which to broadcast the packet
@param channelID channel on which to broadcast
@param packet packet to broadcast
*/
void
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
{
ENetPeer * currentPeer;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
continue;
enet_peer_send (currentPeer, channelID, packet);
}
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
/** Adjusts the bandwidth limits of a host.
@param host host to adjust
@param incomingBandwidth new incoming bandwidth
@param outgoingBandwidth new outgoing bandwidth
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
specified in enet_host_create().
*/
void
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> recalculateBandwidthLimits = 1;
}
void
enet_host_bandwidth_throttle (ENetHost * host)
{
enet_uint32 timeCurrent = enet_time_get (),
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
peersTotal = 0,
dataTotal = 0,
peersRemaining,
bandwidth,
throttle = 0,
bandwidthLimit = 0;
int needsAdjustment;
ENetPeer * peer;
ENetProtocol command;
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
return;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
++ peersTotal;
dataTotal += peer -> outgoingDataTotal;
}
if (peersTotal == 0)
return;
peersRemaining = peersTotal;
needsAdjustment = 1;
if (host -> outgoingBandwidth == 0)
bandwidth = ~0;
else
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
if (dataTotal < bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
enet_uint32 peerBandwidth;
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidth == 0 ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
continue;
peer -> packetThrottleLimit = (peerBandwidth *
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
if (peer -> packetThrottleLimit == 0)
peer -> packetThrottleLimit = 1;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peerBandwidth;
dataTotal -= peerBandwidth;
}
}
if (peersRemaining > 0)
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peer -> packetThrottleLimit = throttle;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
}
if (host -> recalculateBandwidthLimits)
{
host -> recalculateBandwidthLimits = 0;
peersRemaining = peersTotal;
bandwidth = host -> incomingBandwidth;
needsAdjustment = 1;
if (bandwidth == 0)
bandwidthLimit = 0;
else
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
bandwidthLimit = bandwidth / peersRemaining;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
continue;
if (peer -> outgoingBandwidth > 0 &&
peer -> outgoingBandwidth >= bandwidthLimit)
continue;
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peer -> outgoingBandwidth;
}
}
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
else
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
}
host -> bandwidthThrottleEpoch = timeCurrent;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
}
}
/** @} */

View file

@ -0,0 +1,57 @@
/**
@file list.c
@brief ENet linked list functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/list.h"
/**
@defgroup list ENet linked list utility functions
@ingroup private
@{
*/
void
enet_list_clear (ENetList * list)
{
list -> sentinel.next = & list -> sentinel;
list -> sentinel.previous = & list -> sentinel;
}
ENetListIterator
enet_list_insert (ENetListIterator position, void * data)
{
ENetListIterator result = (ENetListIterator) data;
result -> previous = position -> previous;
result -> next = position;
result -> previous -> next = result;
position -> previous = result;
return result;
}
void *
enet_list_remove (ENetListIterator position)
{
position -> previous -> next = position -> next;
position -> next -> previous = position -> previous;
return position;
}
size_t
enet_list_size (ENetList * list)
{
size_t size = 0;
ENetListIterator position;
for (position = enet_list_begin (list);
position != enet_list_end (list);
position = enet_list_next (position))
++ size;
return size;
}
/** @} */

View file

@ -0,0 +1,155 @@
/**
@file packet.c
@brief ENet packet management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup Packet ENet packet functions
@{
*/
/** Creates a packet that may be sent to a peer.
@param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL.
@param dataLength size of the data allocated for this packet
@param flags flags for this packet as described for the ENetPacket structure.
@returns the packet on success, NULL on failure
*/
ENetPacket *
enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
{
ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
if (flags & ENET_PACKET_FLAG_NO_ALLOCATE)
packet -> data = (enet_uint8 *) data;
else
{
packet -> data = (enet_uint8 *) enet_malloc (dataLength);
if (packet -> data == NULL)
{
enet_free (packet);
return NULL;
}
if (data != NULL)
memcpy (packet -> data, data, dataLength);
}
packet -> referenceCount = 0;
packet -> flags = flags;
packet -> dataLength = dataLength;
packet -> freeCallback = NULL;
return packet;
}
/** Destroys the packet and deallocates its data.
@param packet packet to be destroyed
*/
void
enet_packet_destroy (ENetPacket * packet)
{
if (packet -> freeCallback != NULL)
(* packet -> freeCallback) (packet);
if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
enet_free (packet -> data);
enet_free (packet);
}
/** Attempts to resize the data in the packet to length specified in the
dataLength parameter
@param packet packet to resize
@param dataLength new size for the packet data
@returns 0 on success, < 0 on failure
*/
int
enet_packet_resize (ENetPacket * packet, size_t dataLength)
{
enet_uint8 * newData;
if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
{
packet -> dataLength = dataLength;
return 0;
}
newData = (enet_uint8 *) enet_malloc (dataLength);
if (newData == NULL)
return -1;
memcpy (newData, packet -> data, packet -> dataLength);
enet_free (packet -> data);
packet -> data = newData;
packet -> dataLength = dataLength;
return 0;
}
static int initializedCRC32 = 0;
static enet_uint32 crcTable [256];
static enet_uint32
reflect_crc (int val, int bits)
{
int result = 0, bit;
for (bit = 0; bit < bits; bit ++)
{
if(val & 1) result |= 1 << (bits - 1 - bit);
val >>= 1;
}
return result;
}
static void
initialize_crc32 ()
{
int byte;
for (byte = 0; byte < 256; ++ byte)
{
enet_uint32 crc = reflect_crc (byte, 8) << 24;
int offset;
for(offset = 0; offset < 8; ++ offset)
{
if (crc & 0x80000000)
crc = (crc << 1) ^ 0x04c11db7;
else
crc <<= 1;
}
crcTable [byte] = reflect_crc (crc, 32);
}
initializedCRC32 = 1;
}
enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{
enet_uint32 crc = 0xFFFFFFFF;
if (! initializedCRC32) initialize_crc32 ();
while (bufferCount -- > 0)
{
const enet_uint8 * data = (const enet_uint8 *) buffers -> data,
* dataEnd = & data [buffers -> dataLength];
while (data < dataEnd)
{
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
}
++ buffers;
}
return ENET_HOST_TO_NET_32 (~ crc);
}
/** @} */

View file

@ -0,0 +1,700 @@
/**
@file peer.c
@brief ENet peer management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup peer ENet peer functions
@{
*/
/** Configures throttle parameter for a peer.
Unreliable packets are dropped by ENet in response to the varying conditions
of the Internet connection to the peer. The throttle represents a probability
that an unreliable packet should not be dropped and thus sent by ENet to the peer.
The lowest mean round trip time from the sending of a reliable packet to the
receipt of its acknowledgement is measured over an amount of time specified by
the interval parameter in milliseconds. If a measured round trip time happens to
be significantly less than the mean round trip time measured over the interval,
then the throttle probability is increased to allow more traffic by an amount
specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
constant. If a measured round trip time happens to be significantly greater than
the mean round trip time measured over the interval, then the throttle probability
is decreased to limit traffic by an amount specified in the deceleration parameter, which
is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by
ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
packets will be sent. Intermediate values for the throttle represent intermediate
probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
limits of the local and foreign hosts are taken into account to determine a
sensible limit for the throttle probability above which it should not raise even in
the best of conditions.
@param peer peer to configure
@param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
@param acceleration rate at which to increase the throttle probability as mean RTT declines
@param deceleration rate at which to decrease the throttle probability as mean RTT increases
*/
void
enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
{
ENetProtocol command;
peer -> packetThrottleInterval = interval;
peer -> packetThrottleAcceleration = acceleration;
peer -> packetThrottleDeceleration = deceleration;
command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
int
enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
{
if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
{
peer -> packetThrottle = peer -> packetThrottleLimit;
}
else
if (rtt < peer -> lastRoundTripTime)
{
peer -> packetThrottle += peer -> packetThrottleAcceleration;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
return 1;
}
else
if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
{
if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
peer -> packetThrottle -= peer -> packetThrottleDeceleration;
else
peer -> packetThrottle = 0;
return -1;
}
return 0;
}
/** Queues a packet to be sent.
@param peer destination for the packet
@param channelID channel on which to send
@param packet packet to send
@retval 0 on success
@retval < 0 on failure
*/
int
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{
ENetChannel * channel = & peer -> channels [channelID];
ENetProtocol command;
size_t fragmentLength;
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
channelID >= peer -> channelCount)
return -1;
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
if (packet -> dataLength > fragmentLength)
{
enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength),
fragmentNumber,
fragmentOffset;
packet -> flags |= ENET_PACKET_FLAG_RELIABLE;
packet -> flags &= ~ENET_PACKET_FLAG_UNSEQUENCED;
for (fragmentNumber = 0,
fragmentOffset = 0;
fragmentOffset < packet -> dataLength;
++ fragmentNumber,
fragmentOffset += fragmentLength)
{
if (packet -> dataLength - fragmentOffset < fragmentLength)
fragmentLength = packet -> dataLength - fragmentOffset;
command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = channelID;
command.sendFragment.startSequenceNumber = startSequenceNumber;
command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
command.sendFragment.fragmentCount = fragmentCount;
command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
enet_peer_queue_outgoing_command (peer, & command, packet, fragmentOffset, fragmentLength);
}
return 0;
}
command.header.channelID = channelID;
if (! (packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) && channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
packet -> flags |= ENET_PACKET_FLAG_RELIABLE;
if (packet -> flags & ENET_PACKET_FLAG_RELIABLE)
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
}
else
if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED)
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1);
command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
}
else
{
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
}
enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength);
return 0;
}
/** Attempts to dequeue any incoming queued packet.
@param peer peer to dequeue packets from
@param channelID channel on which to receive
@returns a pointer to the packet, or NULL if there are no available incoming queued packets
*/
ENetPacket *
enet_peer_receive (ENetPeer * peer, enet_uint8 channelID)
{
ENetChannel * channel = & peer -> channels [channelID];
ENetIncomingCommand * incomingCommand = NULL;
ENetPacket * packet;
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
{
incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingUnreliableCommands);
if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE)
{
if (incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber)
incomingCommand = NULL;
}
}
if (incomingCommand == NULL &&
! enet_list_empty (& channel -> incomingReliableCommands))
{
incomingCommand = (ENetIncomingCommand *) enet_list_front (& channel -> incomingReliableCommands);
if (incomingCommand -> fragmentsRemaining > 0 ||
incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
return NULL;
channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
if (incomingCommand -> fragmentCount > 0)
channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
}
if (incomingCommand == NULL)
return NULL;
enet_list_remove (& incomingCommand -> incomingCommandList);
packet = incomingCommand -> packet;
-- packet -> referenceCount;
if (incomingCommand -> fragments != NULL)
enet_free (incomingCommand -> fragments);
enet_free (incomingCommand);
return packet;
}
static void
enet_peer_reset_outgoing_commands (ENetList * queue)
{
ENetOutgoingCommand * outgoingCommand;
while (! enet_list_empty (queue))
{
outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
if (outgoingCommand -> packet != NULL)
{
-- outgoingCommand -> packet -> referenceCount;
if (outgoingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (outgoingCommand -> packet);
}
enet_free (outgoingCommand);
}
}
static void
enet_peer_reset_incoming_commands (ENetList * queue)
{
ENetIncomingCommand * incomingCommand;
while (! enet_list_empty (queue))
{
incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue));
if (incomingCommand -> packet != NULL)
{
-- incomingCommand -> packet -> referenceCount;
if (incomingCommand -> packet -> referenceCount == 0)
enet_packet_destroy (incomingCommand -> packet);
}
if (incomingCommand -> fragments != NULL)
enet_free (incomingCommand -> fragments);
enet_free (incomingCommand);
}
}
void
enet_peer_reset_queues (ENetPeer * peer)
{
ENetChannel * channel;
while (! enet_list_empty (& peer -> acknowledgements))
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
if (peer -> channels != NULL && peer -> channelCount > 0)
{
for (channel = peer -> channels;
channel < & peer -> channels [peer -> channelCount];
++ channel)
{
enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
}
enet_free (peer -> channels);
}
peer -> channels = NULL;
peer -> channelCount = 0;
}
/** Forcefully disconnects a peer.
@param peer peer to forcefully disconnect
@remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
on its connection to the local host.
*/
void
enet_peer_reset (ENetPeer * peer)
{
peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
peer -> sessionID = 0;
peer -> state = ENET_PEER_STATE_DISCONNECTED;
peer -> incomingBandwidth = 0;
peer -> outgoingBandwidth = 0;
peer -> incomingBandwidthThrottleEpoch = 0;
peer -> outgoingBandwidthThrottleEpoch = 0;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
peer -> lastSendTime = 0;
peer -> lastReceiveTime = 0;
peer -> nextTimeout = 0;
peer -> earliestTimeout = 0;
peer -> packetLossEpoch = 0;
peer -> packetsSent = 0;
peer -> packetsLost = 0;
peer -> packetLoss = 0;
peer -> packetLossVariance = 0;
peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
peer -> packetThrottleCounter = 0;
peer -> packetThrottleEpoch = 0;
peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> lastRoundTripTimeVariance = 0;
peer -> highestRoundTripTimeVariance = 0;
peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
peer -> roundTripTimeVariance = 0;
peer -> mtu = peer -> host -> mtu;
peer -> reliableDataInTransit = 0;
peer -> outgoingReliableSequenceNumber = 0;
peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
peer -> incomingUnsequencedGroup = 0;
peer -> outgoingUnsequencedGroup = 0;
peer -> disconnectData = 0;
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
enet_peer_reset_queues (peer);
}
/** Sends a ping request to a peer.
@param peer destination for the ping request
@remarks ping requests factor into the mean round trip time as designated by the
roundTripTime field in the ENetPeer structure. Enet automatically pings all connected
peers at regular intervals, however, this function may be called to ensure more
frequent ping requests.
*/
void
enet_peer_ping (ENetPeer * peer)
{
ENetProtocol command;
if (peer -> state != ENET_PEER_STATE_CONNECTED)
return;
command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
/** Force an immediate disconnection from a peer.
@param peer peer to disconnect
@param data data describing the disconnection
@remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
guarenteed to receive the disconnect notification, and is reset immediately upon
return from this function.
*/
void
enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
{
ENetProtocol command;
if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
return;
if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
peer -> state != ENET_PEER_STATE_DISCONNECTING)
{
enet_peer_reset_queues (peer);
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
command.header.channelID = 0xFF;
command.disconnect.data = ENET_HOST_TO_NET_32 (data);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
enet_host_flush (peer -> host);
}
enet_peer_reset (peer);
}
/** Request a disconnection from a peer.
@param peer peer to request a disconnection
@param data data describing the disconnection
@remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
once the disconnection is complete.
*/
void
enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
{
ENetProtocol command;
if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
peer -> state == ENET_PEER_STATE_DISCONNECTED ||
peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
peer -> state == ENET_PEER_STATE_ZOMBIE)
return;
enet_peer_reset_queues (peer);
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
command.header.channelID = 0xFF;
command.disconnect.data = ENET_HOST_TO_NET_32 (data);
if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
else
command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
peer -> state = ENET_PEER_STATE_DISCONNECTING;
else
{
enet_host_flush (peer -> host);
enet_peer_reset (peer);
}
}
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
@param peer peer to request a disconnection
@param data data describing the disconnection
@remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
once the disconnection is complete.
*/
void
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
{
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
! (enet_list_empty (& peer -> outgoingReliableCommands) &&
enet_list_empty (& peer -> outgoingUnreliableCommands) &&
enet_list_empty (& peer -> sentReliableCommands)))
{
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
peer -> disconnectData = data;
}
else
enet_peer_disconnect (peer, data);
}
ENetAcknowledgement *
enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
{
ENetAcknowledgement * acknowledgement;
if (command -> header.channelID < peer -> channelCount)
{
ENetChannel * channel = & peer -> channels [command -> header.channelID];
enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
return NULL;
}
peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
acknowledgement -> sentTime = sentTime;
acknowledgement -> command = * command;
enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
return acknowledgement;
}
ENetOutgoingCommand *
enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
{
ENetChannel * channel = & peer -> channels [command -> header.channelID];
ENetOutgoingCommand * outgoingCommand;
peer -> outgoingDataTotal += enet_protocol_command_size (command -> header.command) + length;
outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
if (command -> header.channelID == 0xFF)
{
++ peer -> outgoingReliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
{
++ channel -> outgoingReliableSequenceNumber;
channel -> outgoingUnreliableSequenceNumber = 0;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
{
++ peer -> outgoingUnsequencedGroup;
outgoingCommand -> reliableSequenceNumber = 0;
outgoingCommand -> unreliableSequenceNumber = 0;
}
else
{
++ channel -> outgoingUnreliableSequenceNumber;
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
}
outgoingCommand -> sendAttempts = 0;
outgoingCommand -> sentTime = 0;
outgoingCommand -> roundTripTimeout = 0;
outgoingCommand -> roundTripTimeoutLimit = 0;
outgoingCommand -> fragmentOffset = offset;
outgoingCommand -> fragmentLength = length;
outgoingCommand -> packet = packet;
outgoingCommand -> command = * command;
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
if (packet != NULL)
++ packet -> referenceCount;
if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
else
enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
return outgoingCommand;
}
ENetIncomingCommand *
enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
{
ENetChannel * channel = & peer -> channels [command -> header.channelID];
enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber;
enet_uint16 reliableWindow, currentWindow;
ENetIncomingCommand * incomingCommand;
ENetListIterator currentCommand;
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
goto freePacket;
if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
{
reliableSequenceNumber = command -> header.reliableSequenceNumber;
reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
goto freePacket;
}
switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
{
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
goto freePacket;
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
currentCommand != enet_list_end (& channel -> incomingReliableCommands);
currentCommand = enet_list_previous (currentCommand))
{
incomingCommand = (ENetIncomingCommand *) currentCommand;
if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
{
if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
continue;
}
else
if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
break;
if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
{
if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
break;
goto freePacket;
}
}
break;
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
currentCommand = enet_list_previous (currentCommand))
{
incomingCommand = (ENetIncomingCommand *) currentCommand;
if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE)
continue;
if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
{
if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
continue;
}
else
if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
break;
if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
break;
if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
continue;
if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
{
if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
break;
goto freePacket;
}
}
break;
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
break;
default:
goto freePacket;
}
incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
incomingCommand -> command = * command;
incomingCommand -> fragmentCount = fragmentCount;
incomingCommand -> fragmentsRemaining = fragmentCount;
incomingCommand -> packet = packet;
incomingCommand -> fragments = NULL;
if (fragmentCount > 0)
{
incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
}
if (packet != NULL)
++ packet -> referenceCount;
enet_list_insert (enet_list_next (currentCommand), incomingCommand);
return incomingCommand;
freePacket:
if (packet != NULL)
{
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
return NULL;
}
/** @} */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,438 @@
/**
@file unix.c
@brief ENet Unix system specific functions
*/
#ifndef WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef HAS_FCNTL
#include <fcntl.h>
#endif
#ifdef __APPLE__
#undef HAS_POLL
#endif
#ifdef HAS_POLL
#include <sys/poll.h>
#endif
#ifndef HAS_SOCKLEN_T
// typedef int socklen_t;
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
return 0;
}
void
enet_deinitialize (void)
{
}
enet_uint32
enet_time_get (void)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYNAME_R
struct hostent hostData;
char buffer [2048];
int errnum;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
hostEntry = gethostbyname (name);
#endif
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
}
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_INET_NTOP
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
#else
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr != NULL)
strncpy (name, addr, nameLength);
else
#endif
return -1;
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYADDR_R
struct hostent hostData;
char buffer [2048];
int errnum;
in.s_addr = address -> host;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
#endif
if (hostEntry == NULL)
return enet_address_get_host_ip (address, name, nameLength);
strncpy (name, hostEntry -> h_name, nameLength);
return 0;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in));
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = -1;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
#ifdef HAS_FCNTL
result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
#else
result = ioctl (socket, FIONBIO, & value);
#endif
break;
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == -1 ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
int result;
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
void
enet_socket_destroy (ENetSocket socket)
{
close (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int sentLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (sentLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int recvLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (recvLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
return -1;
#endif
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
#ifdef HAS_POLL
struct pollfd pollSocket;
int pollCount;
pollSocket.fd = socket;
pollSocket.events = 0;
if (* condition & ENET_SOCKET_WAIT_SEND)
pollSocket.events |= POLLOUT;
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;
pollCount = poll (& pollSocket, 1, timeout);
if (pollCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (pollCount == 0)
return 0;
if (pollSocket.revents & POLLOUT)
* condition |= ENET_SOCKET_WAIT_SEND;
if (pollSocket.revents & POLLIN)
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#else
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#endif
}
#endif

View file

@ -0,0 +1,348 @@
/**
@file win32.c
@brief ENet Win32 system specific functions
*/
#ifdef WIN32
#include <time.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (1, 1);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
if (LOBYTE (wsaData.wVersion) != 1||
HIBYTE (wsaData.wVersion) != 1)
{
WSACleanup ();
return -1;
}
timeBeginPeriod (1);
return 0;
}
void
enet_deinitialize (void)
{
timeEndPeriod (1);
WSACleanup ();
}
enet_uint32
enet_time_get (void)
{
return (enet_uint32) timeGetTime () - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry;
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
{
unsigned long host = inet_addr (name);
if (host == INADDR_NONE)
return -1;
address -> host = host;
return 0;
}
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr == NULL)
return -1;
strncpy (name, addr, nameLength);
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry;
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
if (hostEntry == NULL)
return enet_address_get_host_ip (address, name, nameLength);
strncpy (name, hostEntry -> h_name, nameLength);
return 0;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = SOCKET_ERROR;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
{
u_long nonBlocking = (u_long) value;
result = ioctlsocket (socket, FIONBIO, & nonBlocking);
break;
}
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
SOCKET result;
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == INVALID_SOCKET)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
void
enet_socket_destroy (ENetSocket socket)
{
closesocket (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength;
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : 0,
address != NULL ? sizeof (struct sockaddr_in) : 0,
NULL,
NULL) == SOCKET_ERROR)
{
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
return -1;
}
return (int) sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength;
struct sockaddr_in sin;
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
case WSAECONNRESET:
return 0;
}
return -1;
}
if (flags & MSG_PARTIAL)
return -1;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return (int) recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
}
#endif

View file

@ -183,6 +183,7 @@ extern int32_t A_IncurDamage(int32_t sn);
extern void G_MoveWorld(void); extern void G_MoveWorld(void);
extern void A_MoveCyclers(void); extern void A_MoveCyclers(void);
extern void A_MoveDummyPlayers(void); extern void A_MoveDummyPlayers(void);
extern void P_ResetStatus(int32_t snum);
// game.c // game.c
extern inline void G_SetStatusBarScale(int32_t sc); extern inline void G_SetStatusBarScale(int32_t sc);

File diff suppressed because it is too large Load diff

View file

@ -5358,8 +5358,6 @@ repeatcase:
else if ((Bstrlen(tempbuf)+1) > sizeof(MapInfo[j*MAXLEVELS+k].filename)) else if ((Bstrlen(tempbuf)+1) > sizeof(MapInfo[j*MAXLEVELS+k].filename))
MapInfo[j*MAXLEVELS+k].filename = Brealloc(MapInfo[j*MAXLEVELS+k].filename,(Bstrlen(tempbuf)+1)); MapInfo[j*MAXLEVELS+k].filename = Brealloc(MapInfo[j*MAXLEVELS+k].filename,(Bstrlen(tempbuf)+1));
/* initprintf("level file name string len: %d\n",Bstrlen(tempbuf)); */
Bstrcpy(MapInfo[j*MAXLEVELS+k].filename,tempbuf); Bstrcpy(MapInfo[j*MAXLEVELS+k].filename,tempbuf);
C_SkipComments(); C_SkipComments();
@ -5581,19 +5579,15 @@ repeatcase:
C_GetNextValue(LABEL_DEFINE); C_GetNextValue(LABEL_DEFINE);
g_sounds[k].ps = *(g_scriptPtr-1); g_sounds[k].ps = *(g_scriptPtr-1);
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE); C_GetNextValue(LABEL_DEFINE);
g_sounds[k].pe = *(g_scriptPtr-1); g_sounds[k].pe = *(g_scriptPtr-1);
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE); C_GetNextValue(LABEL_DEFINE);
g_sounds[k].pr = *(g_scriptPtr-1); g_sounds[k].pr = *(g_scriptPtr-1);
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE); C_GetNextValue(LABEL_DEFINE);
g_sounds[k].m = *(g_scriptPtr-1); g_sounds[k].m = *(g_scriptPtr-1);
g_scriptPtr--;
C_GetNextValue(LABEL_DEFINE); C_GetNextValue(LABEL_DEFINE);
g_sounds[k].vo = *(g_scriptPtr-1); g_sounds[k].vo = *(g_scriptPtr-1);
g_scriptPtr--; g_scriptPtr -= 5;
if (k > g_maxSoundPos) if (k > g_maxSoundPos)
g_maxSoundPos = k; g_maxSoundPos = k;
@ -5627,8 +5621,7 @@ repeatcase:
*(g_scriptPtr++) = CON_ENDEVENT; *(g_scriptPtr++) = CON_ENDEVENT;
previous_event = NULL; previous_event = NULL;
} }
g_parsingEventPtr = 0; g_parsingEventPtr = g_parsingActorPtr = 0;
g_parsingActorPtr = 0;
g_currentEvent = -1; g_currentEvent = -1;
Bsprintf(g_szCurrentBlockName,"(none)"); Bsprintf(g_szCurrentBlockName,"(none)");
return 0; return 0;

View file

@ -105,10 +105,6 @@ extern "C" {
#define MAXJOYAXES 8 #define MAXJOYAXES 8
// Number of GAMEPAD axes
#define MAXGAMEPADAXES 2
// MIN/MAX scale value for controller scales // MIN/MAX scale value for controller scales
#define MAXCONTROLSCALEVALUE (1<<19) #define MAXCONTROLSCALEVALUE (1<<19)

View file

@ -39,6 +39,7 @@ vmstate_t vm;
int32_t g_errorLineNum; int32_t g_errorLineNum;
int32_t g_tw; int32_t g_tw;
extern int32_t ticrandomseed;
static int32_t X_DoExecute(int32_t once); static int32_t X_DoExecute(int32_t once);
@ -1824,7 +1825,7 @@ nullquote:
ud.m_volume_number = ud.volume_number = volnume; ud.m_volume_number = ud.volume_number = volnume;
ud.m_level_number = ud.level_number = levnume; ud.m_level_number = ud.level_number = levnume;
if (numplayers > 1 && myconnectindex == connecthead) if (numplayers > 1 && net_server)
Net_NewGame(volnume,levnume); Net_NewGame(volnume,levnume);
else else
{ {
@ -2712,7 +2713,7 @@ nullquote:
g_lastSaveSlot = *insptr++; g_lastSaveSlot = *insptr++;
if ((g_movesPerPacket == 4 && connecthead != myconnectindex) || g_lastSaveSlot > 9) if (g_lastSaveSlot > 9)
continue; continue;
if ((tw == CON_SAVE) || !(ud.savegame[g_lastSaveSlot][0])) if ((tw == CON_SAVE) || !(ud.savegame[g_lastSaveSlot][0]))
{ {
@ -4703,6 +4704,9 @@ void A_Execute(int32_t iActor,int32_t iPlayer,int32_t lDist)
// if (actorscrptr[sprite[iActor].picnum] == 0) return; // if (actorscrptr[sprite[iActor].picnum] == 0) return;
if (net_server || net_client)
randomseed = ticrandomseed;
vm.g_i = iActor; // Sprite ID vm.g_i = iActor; // Sprite ID
vm.g_p = iPlayer; // Player ID vm.g_p = iPlayer; // Player ID
vm.g_x = lDist; // ? vm.g_x = lDist; // ?
@ -4996,9 +5000,15 @@ void G_RestoreMapState(mapstate_t *save)
{ {
if (aGameVars[i].dwFlags & GAMEVAR_NORESET) continue; if (aGameVars[i].dwFlags & GAMEVAR_NORESET) continue;
if (aGameVars[i].dwFlags & GAMEVAR_PERPLAYER) if (aGameVars[i].dwFlags & GAMEVAR_PERPLAYER)
{
if (!save->vars[i]) continue;
Bmemcpy(&aGameVars[i].val.plValues[0],&save->vars[i][0],sizeof(intptr_t) * MAXPLAYERS); Bmemcpy(&aGameVars[i].val.plValues[0],&save->vars[i][0],sizeof(intptr_t) * MAXPLAYERS);
}
else if (aGameVars[i].dwFlags & GAMEVAR_PERACTOR) else if (aGameVars[i].dwFlags & GAMEVAR_PERACTOR)
{
if (!save->vars[i]) continue;
Bmemcpy(&aGameVars[i].val.plValues[0],&save->vars[i][0],sizeof(intptr_t) * MAXSPRITES); Bmemcpy(&aGameVars[i].val.plValues[0],&save->vars[i][0],sizeof(intptr_t) * MAXSPRITES);
}
else aGameVars[i].val.lValue = (intptr_t)save->vars[i]; else aGameVars[i].val.lValue = (intptr_t)save->vars[i];
} }
@ -5082,7 +5092,6 @@ void G_RestoreMapState(mapstate_t *save)
Net_ResetPrediction(); Net_ResetPrediction();
Net_WaitForEverybody(); Net_WaitForEverybody();
mmulti_flushpackets();
clearfifo(); clearfifo();
G_ResetTimers(); G_ResetTimers();
} }

View file

@ -49,7 +49,7 @@ int16_t cyclers[MAXCYCLERS][6],g_numCyclers;
char *ScriptQuotes[MAXQUOTES], *ScriptQuoteRedefinitions[MAXQUOTES]; char *ScriptQuotes[MAXQUOTES], *ScriptQuoteRedefinitions[MAXQUOTES];
char tempbuf[2048], packbuf[576], menutextbuf[128], buf[1024]; char tempbuf[2048], packbuf[4096], menutextbuf[128], buf[1024];
int16_t camsprite; int16_t camsprite;
int16_t g_mirrorWall[64], g_mirrorSector[64], g_mirrorCount; int16_t g_mirrorWall[64], g_mirrorSector[64], g_mirrorCount;
@ -163,7 +163,7 @@ int32_t myhorizbak[MOVEFIFOSIZ],g_playerFriction = 0xcc00, g_showShareware;
int16_t myangbak[MOVEFIFOSIZ]; int16_t myangbak[MOVEFIFOSIZ];
char szPlayerName[32]; char szPlayerName[32];
int32_t g_damageCameras,g_freezerSelfDamage=0,g_tripbombLaserMode=0; int32_t g_damageCameras,g_freezerSelfDamage=0,g_tripbombLaserMode=0;
int32_t g_networkBroadcastMode = 255, g_movesPerPacket = 1,g_gameQuit = 0,everyothertime; int32_t g_gameQuit = 0,everyothertime;
int32_t g_numFreezeBounces=3,g_rpgBlastRadius,g_pipebombBlastRadius,g_tripbombBlastRadius, int32_t g_numFreezeBounces=3,g_rpgBlastRadius,g_pipebombBlastRadius,g_tripbombBlastRadius,
g_shrinkerBlastRadius,g_morterBlastRadius,g_bouncemineBlastRadius,g_seenineBlastRadius; g_shrinkerBlastRadius,g_morterBlastRadius,g_bouncemineBlastRadius,g_seenineBlastRadius;
DukeStatus_t sbar; DukeStatus_t sbar;
@ -185,7 +185,6 @@ projectile_t ProjectileData[MAXTILES], DefaultProjectileData[MAXTILES], SpritePr
char CheatKeys[2] = { sc_D, sc_N }; char CheatKeys[2] = { sc_D, sc_N };
char setupfilename[BMAX_PATH]= SETUPFILENAME; char setupfilename[BMAX_PATH]= SETUPFILENAME;
// char datetimestring[] = ""__DATE__" "__TIME__"";
int32_t g_doQuickSave = 0; int32_t g_doQuickSave = 0;
uint32_t g_moveThingsCount = 0; uint32_t g_moveThingsCount = 0;

View file

@ -318,7 +318,10 @@ int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, int32_t
memset(&bufdesc, 0, sizeof(DSBUFFERDESC)); memset(&bufdesc, 0, sizeof(DSBUFFERDESC));
bufdesc.dwSize = sizeof(DSBUFFERDESC); bufdesc.dwSize = sizeof(DSBUFFERDESC);
bufdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE |
DSBCAPS_PRIMARYBUFFER |
DSBCAPS_GETCURRENTPOSITION2 |
DSBCAPS_STICKYFOCUS ;
err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0); err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbprimary, 0);
if (FAILED( err )) { if (FAILED( err )) {
@ -344,8 +347,9 @@ int32_t DirectSoundDrv_PCM_Init(int32_t *mixrate, int32_t *numchannels, int32_t
bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE | bufdesc.dwFlags = DSBCAPS_LOCSOFTWARE |
DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLPOSITIONNOTIFY |
DSBCAPS_GETCURRENTPOSITION2; DSBCAPS_GETCURRENTPOSITION2 |
bufdesc.dwBufferBytes = wfex.nBlockAlign * 2048 * 2; DSBCAPS_STICKYFOCUS ;
bufdesc.dwBufferBytes = wfex.nBlockAlign * 2560 * 2;
bufdesc.lpwfxFormat = &wfex; bufdesc.lpwfxFormat = &wfex;
err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0); err = IDirectSound_CreateSoundBuffer(lpds, &bufdesc, &lpdsbsec, 0);

View file

@ -159,22 +159,18 @@ uint32_t MV_MixPosition;
int32_t MV_ErrorCode = MV_Ok; int32_t MV_ErrorCode = MV_Ok;
static int32_t lockdepth = 0; static int32_t lockdepth = 0;
static int32_t DisableInterrupts(void) static void DisableInterrupts(void)
{ {
if (lockdepth++ > 0) if (lockdepth++ > 0)
{ return;
return 0;
}
SoundDriver_Lock(); SoundDriver_Lock();
return 0; return;
} }
static void RestoreInterrupts(int32_t a) static void RestoreInterrupts(void)
{ {
if (--lockdepth > 0) if (--lockdepth > 0)
{
return; return;
}
SoundDriver_Unlock(); SoundDriver_Unlock();
} }
@ -361,12 +357,11 @@ void MV_PlayVoice
) )
{ {
int32_t flags;
flags = DisableInterrupts(); DisableInterrupts();
LL_SortedInsertion(&VoiceList, voice, prev, next, VoiceNode, priority); LL_SortedInsertion(&VoiceList, voice, prev, next, VoiceNode, priority);
RestoreInterrupts(flags); RestoreInterrupts();
} }
@ -382,15 +377,13 @@ void MV_StopVoice
) )
{ {
int32_t flags; DisableInterrupts();
flags = DisableInterrupts();
// move the voice from the play list to the free list // move the voice from the play list to the free list
LL_Remove(voice, next, prev); LL_Remove(voice, next, prev);
LL_Add((VoiceNode*) &VoicePool, voice, next, prev); LL_Add((VoiceNode*) &VoicePool, voice, next, prev);
RestoreInterrupts(flags); RestoreInterrupts();
if (voice->wavetype == Vorbis) if (voice->wavetype == Vorbis)
{ {
@ -501,49 +494,47 @@ void MV_ServiceVoc
} }
// Play any waiting voices // Play any waiting voices
//flags = DisableInterrupts(); //DisableInterrupts();
if (!VoiceList.next) if (!VoiceList.next || (voice = VoiceList.next) == &VoiceList)
return; return;
for (voice = VoiceList.next; voice != &VoiceList; voice = next) do
{ {
if ( voice->Paused ) next = voice->next;
{
next = voice->next; if (voice->Paused)
continue; continue;
}
MV_BufferEmpty[ MV_MixPage ] = FALSE; MV_BufferEmpty[ MV_MixPage ] = FALSE;
// if (!voice->Paused) MV_MixFunction(voice, MV_MixPage);
MV_MixFunction(voice, MV_MixPage);
next = voice->next;
// Is this voice done? // Is this voice done?
if (!voice->Playing/* && !voice->Paused*/) if (!voice->Playing)
{ {
//JBF: prevent a deadlock caused by MV_StopVoice grabbing the mutex again //JBF: prevent a deadlock caused by MV_StopVoice grabbing the mutex again
//MV_StopVoice( voice ); //MV_StopVoice( voice );
LL_Remove(voice, next, prev); LL_Remove(voice, next, prev);
LL_Add((VoiceNode*) &VoicePool, voice, next, prev); LL_Add((VoiceNode*) &VoicePool, voice, next, prev);
if (voice->wavetype == Vorbis)
MV_ReleaseVorbisVoice(voice);
if (MV_CallBackFunc) if (MV_CallBackFunc)
{
MV_CallBackFunc(voice->callbackval); MV_CallBackFunc(voice->callbackval);
}
} }
} }
while ((voice = next) != &VoiceList);
//RestoreInterrupts(flags); //RestoreInterrupts();
} }
/*--------------------------------------------------------------------- /*---------------------------------------------------------------------
Function: MV_GetNextVOCBlock Function: MV_GetNextVOCBlock
Interperate the information of a VOC format sound file. Interpret the information of a VOC format sound file.
---------------------------------------------------------------------*/ ---------------------------------------------------------------------*/
playbackstatus MV_GetNextVOCBlock playbackstatus MV_GetNextVOCBlock
@ -585,7 +576,8 @@ playbackstatus MV_GetNextVOCBlock
packtype = 0; packtype = 0;
done = FALSE; done = FALSE;
while (!done)
do
{ {
// Stop playing if we get a NULL pointer // Stop playing if we get a NULL pointer
if (ptr == NULL) if (ptr == NULL)
@ -753,6 +745,7 @@ playbackstatus MV_GetNextVOCBlock
lastblocktype = blocktype; lastblocktype = blocktype;
} }
while (!done);
if (voice->Playing) if (voice->Playing)
{ {
@ -963,9 +956,8 @@ VoiceNode *MV_GetVoice
{ {
VoiceNode *voice; VoiceNode *voice;
int32_t flags;
flags = DisableInterrupts(); DisableInterrupts();
for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
{ {
@ -975,7 +967,7 @@ VoiceNode *MV_GetVoice
} }
} }
RestoreInterrupts(flags); RestoreInterrupts();
if (voice == &VoiceList) if (voice == &VoiceList)
{ {
@ -1031,8 +1023,7 @@ int32_t MV_KillAllVoices
) )
{ {
VoiceNode * voice, * next; VoiceNode * voice = VoiceList.prev;
int32_t flags;
if (!MV_Installed) if (!MV_Installed)
{ {
@ -1040,19 +1031,25 @@ int32_t MV_KillAllVoices
return(MV_Error); return(MV_Error);
} }
flags = DisableInterrupts(); if (&VoiceList == VoiceList.next)
return(MV_Ok);
DisableInterrupts();
// Remove all the voices from the list // Remove all the voices from the list
for (voice = VoiceList.next; voice != &VoiceList; voice = next) while (voice != &VoiceList)
{ {
next = voice->next; if (voice->priority == MV_MUSIC_PRIORITY)
if (voice->priority < MV_MUSIC_PRIORITY)
{ {
MV_Kill(voice->handle); voice = voice->prev;
continue;
} }
MV_Kill(voice->handle);
voice = VoiceList.prev;
} }
RestoreInterrupts(flags); RestoreInterrupts();
return(MV_Ok); return(MV_Ok);
} }
@ -1071,7 +1068,6 @@ int32_t MV_Kill
{ {
VoiceNode *voice; VoiceNode *voice;
int32_t flags;
uint32_t callbackval; uint32_t callbackval;
if (!MV_Installed) if (!MV_Installed)
@ -1080,12 +1076,12 @@ int32_t MV_Kill
return(MV_Error); return(MV_Error);
} }
flags = DisableInterrupts(); DisableInterrupts();
voice = MV_GetVoice(handle); voice = MV_GetVoice(handle);
if (voice == NULL) if (voice == NULL)
{ {
RestoreInterrupts(flags); RestoreInterrupts();
MV_SetErrorCode(MV_VoiceNotFound); MV_SetErrorCode(MV_VoiceNotFound);
return(MV_Error); return(MV_Error);
} }
@ -1094,7 +1090,7 @@ int32_t MV_Kill
MV_StopVoice(voice); MV_StopVoice(voice);
RestoreInterrupts(flags); RestoreInterrupts();
if (MV_CallBackFunc) if (MV_CallBackFunc)
{ {
@ -1119,7 +1115,6 @@ int32_t MV_VoicesPlaying
{ {
VoiceNode *voice; VoiceNode *voice;
int32_t NumVoices = 0; int32_t NumVoices = 0;
int32_t flags;
if (!MV_Installed) if (!MV_Installed)
{ {
@ -1127,14 +1122,14 @@ int32_t MV_VoicesPlaying
return(0); return(0);
} }
flags = DisableInterrupts(); DisableInterrupts();
for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next) for (voice = VoiceList.next; voice != &VoiceList; voice = voice->next)
{ {
NumVoices++; NumVoices++;
} }
RestoreInterrupts(flags); RestoreInterrupts();
return(NumVoices); return(NumVoices);
} }
@ -1154,15 +1149,13 @@ VoiceNode *MV_AllocVoice
{ {
VoiceNode *voice; VoiceNode *voice;
VoiceNode *node; VoiceNode *node;
int32_t flags;
//return( NULL );
if (MV_Recording) if (MV_Recording)
{ {
return(NULL); return(NULL);
} }
flags = DisableInterrupts(); DisableInterrupts();
// Check if we have any free voices // Check if we have any free voices
if (LL_Empty(&VoicePool, next, prev)) if (LL_Empty(&VoicePool, next, prev))
@ -1187,13 +1180,13 @@ VoiceNode *MV_AllocVoice
if (LL_Empty(&VoicePool, next, prev)) if (LL_Empty(&VoicePool, next, prev))
{ {
// No free voices // No free voices
RestoreInterrupts(flags); RestoreInterrupts();
return(NULL); return(NULL);
} }
voice = VoicePool.next; voice = VoicePool.next;
LL_Remove(voice, next, prev); LL_Remove(voice, next, prev);
RestoreInterrupts(flags); RestoreInterrupts();
// Find a free voice handle // Find a free voice handle
do do
@ -1226,7 +1219,6 @@ int32_t MV_VoiceAvailable
{ {
VoiceNode *voice; VoiceNode *voice;
VoiceNode *node; VoiceNode *node;
int32_t flags;
// Check if we have any free voices // Check if we have any free voices
if (!LL_Empty(&VoicePool, next, prev)) if (!LL_Empty(&VoicePool, next, prev))
@ -1234,7 +1226,7 @@ int32_t MV_VoiceAvailable
return(TRUE); return(TRUE);
} }
flags = DisableInterrupts(); DisableInterrupts();
// check if we have a higher priority than a voice that is playing. // check if we have a higher priority than a voice that is playing.
voice = VoiceList.next; voice = VoiceList.next;
@ -1246,7 +1238,7 @@ int32_t MV_VoiceAvailable
} }
} }
RestoreInterrupts(flags); RestoreInterrupts();
if ((voice != &VoiceList) && (priority >= voice->priority)) if ((voice != &VoiceList) && (priority >= voice->priority))
{ {
@ -1411,7 +1403,7 @@ void MV_SetVoiceMixMode
//int32_t flags; //int32_t flags;
int32_t test; int32_t test;
//flags = DisableInterrupts(); //DisableInterrupts();
test = T_DEFAULT; test = T_DEFAULT;
if (MV_Bits == 8) if (MV_Bits == 8)
@ -1608,7 +1600,6 @@ int32_t MV_PauseVoice
{ {
VoiceNode *voice; VoiceNode *voice;
int32_t flags;
if (!MV_Installed) if (!MV_Installed)
{ {
@ -1616,19 +1607,19 @@ int32_t MV_PauseVoice
return(MV_Error); return(MV_Error);
} }
flags = DisableInterrupts(); DisableInterrupts();
voice = MV_GetVoice(handle); voice = MV_GetVoice(handle);
if (voice == NULL) if (voice == NULL)
{ {
RestoreInterrupts(flags); RestoreInterrupts();
MV_SetErrorCode(MV_VoiceNotFound); MV_SetErrorCode(MV_VoiceNotFound);
return(MV_Warning); return(MV_Warning);
} }
voice->Paused = pause; voice->Paused = pause;
RestoreInterrupts(flags); RestoreInterrupts();
return(MV_Ok); return(MV_Ok);
} }
@ -1648,7 +1639,6 @@ int32_t MV_EndLooping
{ {
VoiceNode *voice; VoiceNode *voice;
int32_t flags;
if (!MV_Installed) if (!MV_Installed)
{ {
@ -1656,12 +1646,12 @@ int32_t MV_EndLooping
return(MV_Error); return(MV_Error);
} }
flags = DisableInterrupts(); DisableInterrupts();
voice = MV_GetVoice(handle); voice = MV_GetVoice(handle);
if (voice == NULL) if (voice == NULL)
{ {
RestoreInterrupts(flags); RestoreInterrupts();
MV_SetErrorCode(MV_VoiceNotFound); MV_SetErrorCode(MV_VoiceNotFound);
return(MV_Warning); return(MV_Warning);
} }
@ -1670,7 +1660,7 @@ int32_t MV_EndLooping
voice->LoopStart = NULL; voice->LoopStart = NULL;
voice->LoopEnd = NULL; voice->LoopEnd = NULL;
RestoreInterrupts(flags); RestoreInterrupts();
return(MV_Ok); return(MV_Ok);
} }
@ -1974,13 +1964,12 @@ void MV_StopPlayback
{ {
VoiceNode *voice; VoiceNode *voice;
VoiceNode *next; VoiceNode *next;
int32_t flags;
// Stop sound playback // Stop sound playback
SoundDriver_StopPlayback(); SoundDriver_StopPlayback();
// Make sure all callbacks are done. // Make sure all callbacks are done.
flags = DisableInterrupts(); DisableInterrupts();
for (voice = VoiceList.next; voice != &VoiceList; voice = next) for (voice = VoiceList.next; voice != &VoiceList; voice = next)
{ {
@ -1994,7 +1983,7 @@ void MV_StopPlayback
} }
} }
RestoreInterrupts(flags); RestoreInterrupts();
} }

View file

@ -94,15 +94,7 @@ extern "C" {
// Number of JOY axes // Number of JOY axes
#define MAXJOYAXES 6 #define MAXJOYAXES 8
// Number of GamePad axes
#define MAXGAMEPADAXES 2
// Number of axes
#define MAXAXES 6
// NORMAL axis scale // NORMAL axis scale

View file

@ -50,7 +50,7 @@ static int32_t CONTROL_MouseButtonClicked[MAXMOUSEBUTTONS], CONTROL_JoyButt
static uint8_t CONTROL_MouseButtonClickedCount[MAXMOUSEBUTTONS], CONTROL_JoyButtonClickedCount[MAXJOYBUTTONS]; static uint8_t CONTROL_MouseButtonClickedCount[MAXMOUSEBUTTONS], CONTROL_JoyButtonClickedCount[MAXJOYBUTTONS];
static int32_t CONTROL_UserInputCleared[3]; static int32_t CONTROL_UserInputCleared[3];
static int32_t(*GetTime)(void); static int32_t(*GetTime)(void);
static int32_t CONTROL_Started = FALSE; int32_t CONTROL_Started = FALSE;
static int32_t ticrate; static int32_t ticrate;
static int32_t CONTROL_DoubleClickSpeed; static int32_t CONTROL_DoubleClickSpeed;

View file

@ -132,6 +132,7 @@ typedef enum
// //
//*************************************************************************** //***************************************************************************
extern int32_t CONTROL_Started;
extern int32_t CONTROL_MousePresent; extern int32_t CONTROL_MousePresent;
extern int32_t CONTROL_JoyPresent; extern int32_t CONTROL_JoyPresent;
extern int32_t CONTROL_MouseEnabled; extern int32_t CONTROL_MouseEnabled;

View file

@ -4,7 +4,7 @@
#define TRAVERSE_SPRITE_SECT(l, o, n) for ((o) = (l); (n) = nextspritesect[o], (o) != -1; (o) = (n)) #define TRAVERSE_SPRITE_SECT(l, o, n) for ((o) = (l); (n) = nextspritesect[o], (o) != -1; (o) = (n))
#define TRAVERSE_SPRITE_STAT(l, o, n) for ((o) = (l); (n) = nextspritestat[o], (o) != -1; (o) = (n)) #define TRAVERSE_SPRITE_STAT(l, o, n) for ((o) = (l); (n) = nextspritestat[o], (o) != -1; (o) = (n))
#define TRAVERSE_CONNECT(i) for (i = connecthead; i != -1; i = connectpoint2[i]) #define TRAVERSE_CONNECT(i) for (i = 0; i != -1; i = connectpoint2[i])
#define TEST(flags,mask) ((flags) & (mask)) #define TEST(flags,mask) ((flags) & (mask))
#define SET(flags,mask) ((flags) |= (mask)) #define SET(flags,mask) ((flags) |= (mask))

View file

@ -1460,11 +1460,12 @@ void M_DisplayMenus(void)
tempbuf[0] = PACKET_LOAD_GAME; tempbuf[0] = PACKET_LOAD_GAME;
tempbuf[1] = g_lastSaveSlot; tempbuf[1] = g_lastSaveSlot;
tempbuf[2] = myconnectindex; tempbuf[2] = myconnectindex;
TRAVERSE_CONNECT(x)
{ if (net_client)
if (x != myconnectindex) mmulti_sendpacket(x,tempbuf,3); enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 3, ENET_PACKET_FLAG_RELIABLE));
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master else if (net_server)
} enet_host_broadcast(net_server, 0, enet_packet_create(tempbuf, 3, ENET_PACKET_FLAG_RELIABLE));
Net_GetPackets(); Net_GetPackets();
G_LoadPlayer(g_lastSaveSlot); G_LoadPlayer(g_lastSaveSlot);
@ -1789,26 +1790,25 @@ void M_DisplayMenus(void)
cheat_for_port_credits: cheat_for_port_credits:
if (g_scriptVersion == 13) l = (-2); if (g_scriptVersion == 13) l = (-2);
mgametext(160,38-l,"GAME PROGRAMMING",0,2+8+16); mgametext(160,38-l,"PROGRAMMING AND PROJECT MANAGEMENT",0,2+8+16);
p = "Richard \"TerminX\" Gobeille"; p = "Richard \"TerminX\" Gobeille";
minitext(161-(Bstrlen(p)<<1), 39+10-l, p, 4, 10+16+128); minitext(161-(Bstrlen(p)<<1), 39+10-l, p, 4, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 38+10-l, p, 8, 10+16+128); minitext(160-(Bstrlen(p)<<1), 38+10-l, p, 8, 10+16+128);
mgametext(160,57-l,"\"JFDUKE3D\" AND \"JFBUILD\" CODE",0,2+8+16); mgametext(160,57-l,"POLYMER RENDERING SYSTEM",0,2+8+16);
p = "Jonathon \"JonoF\" Fowler"; p = "Pierre-Loup \"Plagman\" Griffais";
minitext(161-(Bstrlen(p)<<1), 58+10-l, p, 4, 10+16+128); minitext(161-(Bstrlen(p)<<1), 58+10-l, p, 4, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 57+10-l, p, 8, 10+16+128); minitext(160-(Bstrlen(p)<<1), 57+10-l, p, 8, 10+16+128);
mgametext(160,76-l,"BUILD ENGINE, \"POLYMOST\" RENDERER",0,2+8+16); mgametext(160,76-l,"ENGINE AND GAME PORTING WORK",0,2+8+16);
mgametext(160,76+8-l,"NETWORKING, OTHER CODE",0,2+8+16); p = "Jonathon \"JonoF\" Fowler";
p = "Ken \"Awesoken\" Silverman"; minitext(161-(Bstrlen(p)<<1), 77+10-l, p, 4, 10+16+128);
minitext(161-(Bstrlen(p)<<1), 77+8+10-l, p, 4, 10+16+128); minitext(160-(Bstrlen(p)<<1), 76+10-l, p, 8, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 76+8+10-l, p, 8, 10+16+128);
mgametext(160,103-l,"ADDITIONAL RENDERING FEATURES",0,2+8+16); mgametext(160,95-l,"BUILD ENGINE AND POLYMOST RENDERER",0,2+8+16);
p = "Pierre-Loup \"Plagman\" Griffais"; p = "Ken \"Awesoken\" Silverman";
minitext(161-(Bstrlen(p)<<1), 104+10-l, p, 4, 10+16+128); minitext(161-(Bstrlen(p)<<1), 96+10-l, p, 4, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 103+10-l, p, 8, 10+16+128); minitext(160-(Bstrlen(p)<<1), 95+10-l, p, 8, 10+16+128);
mgametext(160,122-l,"LICENSE AND OTHER CONTRIBUTORS",0,2+8+16); mgametext(160,122-l,"LICENSE AND OTHER CONTRIBUTORS",0,2+8+16);
{ {
@ -1836,11 +1836,15 @@ cheat_for_port_credits:
"Ozkan Sezer", // SDL/GTK version checking improvements "Ozkan Sezer", // SDL/GTK version checking improvements
"Peter Green", // dynamic remapping, custom gametypes "Peter Green", // dynamic remapping, custom gametypes
"Peter Veenstra", // port to 64-bit "Peter Veenstra", // port to 64-bit
"Randy Heit", // random snippets of ZDoom here and there
"Robin Green", // CON array support
"Philipp Kutin", // Mapster32 improvements "Philipp Kutin", // Mapster32 improvements
"Ryan Gordon", // icculus.org Duke3D port sound code "Ryan Gordon", // icculus.org Duke3D port sound code
"Stephen Anthony", // early 64-bit porting work "Stephen Anthony", // early 64-bit porting work
" ", " ",
"EDuke originally by Matt Saettler", "EDuke originally by Matt Saettler.",
" ",
"BUILD engine technology available under BUILDLIC.",
" ", " ",
"--x--", "--x--",
" ", " ",
@ -1862,9 +1866,6 @@ cheat_for_port_credits:
p = "Visit www.eduke32.com for news and updates"; p = "Visit www.eduke32.com for news and updates";
minitext(161-(Bstrlen(p)<<1), 136+10+10+10+10+4-l, p, 4, 10+16+128); minitext(161-(Bstrlen(p)<<1), 136+10+10+10+10+4-l, p, 4, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 135+10+10+10+10+4-l, p, 8, 10+16+128); minitext(160-(Bstrlen(p)<<1), 135+10+10+10+10+4-l, p, 8, 10+16+128);
p = "See wiki.eduke32.com/stuff for new releases";
minitext(161-(Bstrlen(p)<<1), 143+10+10+10+10+4-l, p, 4, 10+16+128);
minitext(160-(Bstrlen(p)<<1), 142+10+10+10+10+4-l, p, 8, 10+16+128);
} }
break; break;
@ -1878,9 +1879,6 @@ cheat_for_port_credits:
{ {
if (ud.multimode > 1 && x == 0 && ud.recstat != 2) if (ud.multimode > 1 && x == 0 && ud.recstat != 2)
{ {
if (g_movesPerPacket == 4 && myconnectindex != connecthead)
break;
last_zero = 0; last_zero = 0;
ChangeToMenu(600); ChangeToMenu(600);
} }
@ -1897,8 +1895,6 @@ cheat_for_port_credits:
ChangeToMenu(202); ChangeToMenu(202);
break; // JBF 20031205: was 200 break; // JBF 20031205: was 200
case 2: case 2:
if (g_movesPerPacket == 4 && connecthead != myconnectindex)
break;
ChangeToMenu(300); ChangeToMenu(300);
break; break;
case 3: case 3:
@ -1927,23 +1923,13 @@ cheat_for_port_credits:
} }
} }
if (g_movesPerPacket == 4) menutext(c,67,MENUHIGHLIGHT(0),PHX(-2),"NEW GAME");
{
if (myconnectindex == connecthead)
menutext(c,67,MENUHIGHLIGHT(0),PHX(-2),"NEW GAME");
else
menutext(c,67,MENUHIGHLIGHT(0),1,"NEW GAME");
}
else
menutext(c,67,MENUHIGHLIGHT(0),PHX(-2),"NEW GAME");
// menutext(c,67+16,0,1,"NETWORK GAME"); // menutext(c,67+16,0,1,"NETWORK GAME");
menutext(c,67+16/*+16*/,MENUHIGHLIGHT(1),PHX(-3),"OPTIONS"); menutext(c,67+16/*+16*/,MENUHIGHLIGHT(1),PHX(-3),"OPTIONS");
if (g_movesPerPacket == 4 && connecthead != myconnectindex) menutext(c,67+16+16/*+16*/,MENUHIGHLIGHT(2),PHX(-4),"LOAD GAME");
menutext(c,67+16+16/*+16*/,MENUHIGHLIGHT(2),1,"LOAD GAME");
else menutext(c,67+16+16/*+16*/,MENUHIGHLIGHT(2),PHX(-4),"LOAD GAME");
if (!VOLUMEALL) if (!VOLUMEALL)
{ {
@ -1971,8 +1957,6 @@ cheat_for_port_credits:
switch (x) switch (x)
{ {
case 0: case 0:
if (g_movesPerPacket == 4 && myconnectindex != connecthead)
break;
if (ud.multimode < 2 || ud.recstat == 2) if (ud.multimode < 2 || ud.recstat == 2)
ChangeToMenu(1500); ChangeToMenu(1500);
else else
@ -1982,8 +1966,6 @@ cheat_for_port_credits:
} }
break; break;
case 1: case 1:
if (g_movesPerPacket == 4 && connecthead != myconnectindex)
break;
if (ud.recstat != 2) if (ud.recstat != 2)
{ {
last_fifty = 1; last_fifty = 1;
@ -1992,8 +1974,6 @@ cheat_for_port_credits:
} }
break; break;
case 2: case 2:
if (g_movesPerPacket == 4 && connecthead != myconnectindex)
break;
last_fifty = 2; last_fifty = 2;
ChangeToMenu(300); ChangeToMenu(300);
break; break;
@ -2030,18 +2010,9 @@ cheat_for_port_credits:
if (KB_KeyPressed(sc_Q)) if (KB_KeyPressed(sc_Q))
ChangeToMenu(500); ChangeToMenu(500);
if (g_movesPerPacket == 4 && connecthead != myconnectindex) menutext(c,67 ,MENUHIGHLIGHT(0),PHX(-2),"NEW GAME");
{ menutext(c,67+16 ,MENUHIGHLIGHT(1),PHX(-3),"SAVE GAME");
menutext(c,67 ,MENUHIGHLIGHT(0),1,"NEW GAME"); menutext(c,67+16+16 ,MENUHIGHLIGHT(2),PHX(-4),"LOAD GAME");
menutext(c,67+16 ,MENUHIGHLIGHT(1),1,"SAVE GAME");
menutext(c,67+16+16 ,MENUHIGHLIGHT(2),1,"LOAD GAME");
}
else
{
menutext(c,67 ,MENUHIGHLIGHT(0),PHX(-2),"NEW GAME");
menutext(c,67+16 ,MENUHIGHLIGHT(1),PHX(-3),"SAVE GAME");
menutext(c,67+16+16 ,MENUHIGHLIGHT(2),PHX(-4),"LOAD GAME");
}
menutext(c,67+16+16+16 ,MENUHIGHLIGHT(3),PHX(-5),"OPTIONS"); menutext(c,67+16+16+16 ,MENUHIGHLIGHT(3),PHX(-5),"OPTIONS");
if (!VOLUMEALL) if (!VOLUMEALL)
@ -5102,11 +5073,11 @@ VOLUME_ALL_40x:
tempbuf[0] = PACKET_MAP_VOTE_CANCEL; tempbuf[0] = PACKET_MAP_VOTE_CANCEL;
tempbuf[1] = myconnectindex; tempbuf[1] = myconnectindex;
TRAVERSE_CONNECT(c) if (net_client)
{ enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 2, ENET_PACKET_FLAG_RELIABLE));
if (c != myconnectindex) mmulti_sendpacket(c,tempbuf,2); else if (net_server)
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master enet_host_broadcast(net_server, 0, enet_packet_create(tempbuf, 2, ENET_PACKET_FLAG_RELIABLE));
}
voting = -1; voting = -1;
} }
ChangeToMenu(0); ChangeToMenu(0);
@ -5117,9 +5088,9 @@ VOLUME_ALL_40x:
plrvotes += g_player[i].vote; plrvotes += g_player[i].vote;
j += g_player[i].gotvote; j += g_player[i].gotvote;
} }
if (j == numplayers || !g_player[myconnectindex].ps->i || (plrvotes > (numplayers>>1)) || (!g_networkBroadcastMode && myconnectindex == connecthead)) if (j == numplayers || !g_player[myconnectindex].ps->i || (plrvotes > (numplayers>>1)) || (net_server))
{ {
if (plrvotes > (numplayers>>1) || !g_player[myconnectindex].ps->i || (!g_networkBroadcastMode && myconnectindex == connecthead)) if (plrvotes > (numplayers>>1) || !g_player[myconnectindex].ps->i || (net_server))
{ {
if (ud.m_player_skill == 3) ud.m_respawn_monsters = 1; if (ud.m_player_skill == 3) ud.m_respawn_monsters = 1;
else ud.m_respawn_monsters = 0; else ud.m_respawn_monsters = 0;
@ -5138,7 +5109,7 @@ VOLUME_ALL_40x:
Net_NewGame(ud.m_volume_number,ud.m_level_number); Net_NewGame(ud.m_volume_number,ud.m_level_number);
if (voting == myconnectindex && !(!g_networkBroadcastMode && myconnectindex == connecthead)) if (voting == myconnectindex && !(net_server))
G_AddUserQuote("VOTE SUCCEEDED"); G_AddUserQuote("VOTE SUCCEEDED");
G_NewGame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill+1); G_NewGame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill+1);
@ -5159,12 +5130,12 @@ VOLUME_ALL_40x:
tempbuf[0] = PACKET_MAP_VOTE_CANCEL; tempbuf[0] = PACKET_MAP_VOTE_CANCEL;
tempbuf[1] = myconnectindex; tempbuf[1] = myconnectindex;
tempbuf[2] = 1; tempbuf[2] = 1;
tempbuf[3] = myconnectindex;
TRAVERSE_CONNECT(c) if (net_client)
{ enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 4, ENET_PACKET_FLAG_RELIABLE));
if (c != myconnectindex) mmulti_sendpacket(c,tempbuf,3); else if (net_server)
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master enet_host_broadcast(net_server, 0, enet_packet_create(tempbuf, 4, ENET_PACKET_FLAG_RELIABLE));
}
Bsprintf(ScriptQuotes[116],"VOTE FAILED"); Bsprintf(ScriptQuotes[116],"VOTE FAILED");
P_DoQuote(116,g_player[myconnectindex].ps); P_DoQuote(116,g_player[myconnectindex].ps);
@ -5290,7 +5261,7 @@ VOLUME_ALL_40x:
break; break;
case 7: case 7:
// master does whatever it wants // master does whatever it wants
if (!g_networkBroadcastMode && myconnectindex == connecthead) if (net_server)
{ {
ChangeToMenu(603); ChangeToMenu(603);
break; break;
@ -5311,12 +5282,12 @@ VOLUME_ALL_40x:
tempbuf[1] = myconnectindex; tempbuf[1] = myconnectindex;
tempbuf[2] = ud.m_volume_number; tempbuf[2] = ud.m_volume_number;
tempbuf[3] = ud.m_level_number; tempbuf[3] = ud.m_level_number;
tempbuf[4] = myconnectindex;
TRAVERSE_CONNECT(c) if (net_client)
{ enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 5, ENET_PACKET_FLAG_RELIABLE));
if (c != myconnectindex) mmulti_sendpacket(c,tempbuf,4); else if (net_server)
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master enet_host_broadcast(net_server, 0, enet_packet_create(tempbuf, 5, ENET_PACKET_FLAG_RELIABLE));
}
} }
if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM)) if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM))
ud.m_noexits = 0; ud.m_noexits = 0;

View file

@ -102,7 +102,7 @@ static int32_t osdcmd_changelevel(const osdfuncparm_t *parm)
if (numplayers > 1) if (numplayers > 1)
{ {
if (myconnectindex == connecthead && g_networkBroadcastMode == 0) if (net_server)
Net_NewGame(volume,level); Net_NewGame(volume,level);
else if (voting == -1) else if (voting == -1)
{ {
@ -128,11 +128,7 @@ static int32_t osdcmd_changelevel(const osdfuncparm_t *parm)
tempbuf[2] = ud.m_volume_number; tempbuf[2] = ud.m_volume_number;
tempbuf[3] = ud.m_level_number; tempbuf[3] = ud.m_level_number;
TRAVERSE_CONNECT(i) enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 4, ENET_PACKET_FLAG_RELIABLE));
{
if (i != myconnectindex) mmulti_sendpacket(i,tempbuf,4);
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master
}
} }
if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM)) if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM))
ud.m_noexits = 0; ud.m_noexits = 0;
@ -254,7 +250,7 @@ static int32_t osdcmd_map(const osdfuncparm_t *parm)
if (numplayers > 1) if (numplayers > 1)
{ {
if (myconnectindex == connecthead && g_networkBroadcastMode == 0) if (net_server)
{ {
Net_SendUserMapName(); Net_SendUserMapName();
ud.m_volume_number = 0; ud.m_volume_number = 0;
@ -286,11 +282,7 @@ static int32_t osdcmd_map(const osdfuncparm_t *parm)
tempbuf[2] = ud.m_volume_number; tempbuf[2] = ud.m_volume_number;
tempbuf[3] = ud.m_level_number; tempbuf[3] = ud.m_level_number;
TRAVERSE_CONNECT(i) enet_peer_send(net_peer, 0, enet_packet_create(tempbuf, 4, ENET_PACKET_FLAG_RELIABLE));
{
if (i != myconnectindex) mmulti_sendpacket(i,tempbuf,4);
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master
}
} }
if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM)) if ((GametypeFlags[ud.m_coop] & GAMETYPE_PLAYERSFRIENDLY) && !(GametypeFlags[ud.m_coop] & GAMETYPE_TDM))
ud.m_noexits = 0; ud.m_noexits = 0;
@ -1115,9 +1107,6 @@ static int32_t osdcmd_screenshot(const osdfuncparm_t *parm)
return OSDCMD_OK; return OSDCMD_OK;
} }
extern void G_SaveMapState(mapstate_t *save);
extern void G_RestoreMapState(mapstate_t *save);
/* /*
static int32_t osdcmd_savestate(const osdfuncparm_t *parm) static int32_t osdcmd_savestate(const osdfuncparm_t *parm)
{ {

View file

@ -3317,9 +3317,11 @@ void getinput(int32_t snum)
return; return;
} }
if (numplayers > 1) /*
daang = myang; if (numplayers > 1)
else daang = p->ang; daang = myang;
else*/
daang = p->ang;
momx = mulscale9(vel,sintable[(daang+2560)&2047]); momx = mulscale9(vel,sintable[(daang+2560)&2047]);
momy = mulscale9(vel,sintable[(daang+2048)&2047]); momy = mulscale9(vel,sintable[(daang+2048)&2047]);
@ -4142,14 +4144,6 @@ void P_ProcessInput(int32_t snum)
G_AddUserQuote(tempbuf); G_AddUserQuote(tempbuf);
} }
} }
if (myconnectindex == connecthead)
{
Bsprintf(tempbuf,"frag %d killed %d\n",p->frag_ps+1,snum+1);
sendscore(tempbuf);
// printf(tempbuf);
}
p->frag_ps = snum; p->frag_ps = snum;
pus = NUMPAGES; pus = NUMPAGES;
} }

View file

@ -621,7 +621,7 @@ void P_RandomSpawnPoint(int32_t snum)
p->cursectnum = g_playerSpawnPoints[i].os; p->cursectnum = g_playerSpawnPoints[i].os;
} }
static void P_ResetStatus(int32_t snum) void P_ResetStatus(int32_t snum)
{ {
DukePlayer_t *p = g_player[snum].ps; DukePlayer_t *p = g_player[snum].ps;
@ -1304,20 +1304,6 @@ quick:
display_mirror = 0; display_mirror = 0;
if (ud.multimode > 1)
{
if (numplayers < 2)
{
connecthead = 0;
for (i=0; i<MAXPLAYERS; i++) connectpoint2[i] = i+1;
connectpoint2[ud.multimode-1] = -1;
}
}
else
{
connecthead = 0;
connectpoint2[0] = -1;
}
X_OnEvent(EVENT_NEWGAME, g_player[screenpeek].ps->i, screenpeek, -1); X_OnEvent(EVENT_NEWGAME, g_player[screenpeek].ps->i, screenpeek, -1);
} }
@ -1333,7 +1319,7 @@ static void resetpspritevars(char g)
APLAYER,0,0,0,g_player[0].ps->ang,0,0,0,10); APLAYER,0,0,0,g_player[0].ps->ang,0,0,0,10);
if (ud.recstat != 2) if (ud.recstat != 2)
for (i=0; i<ud.multimode; i++) TRAVERSE_CONNECT(i)
{ {
aimmode[i] = g_player[i].ps->aim_mode; aimmode[i] = g_player[i].ps->aim_mode;
autoaim[i] = g_player[i].ps->auto_aim; autoaim[i] = g_player[i].ps->auto_aim;
@ -1362,11 +1348,11 @@ static void resetpspritevars(char g)
P_ResetStatus(0); P_ResetStatus(0);
for (i=1; i<ud.multimode; i++) TRAVERSE_CONNECT(i)
Bmemcpy(g_player[i].ps,g_player[0].ps,sizeof(DukePlayer_t)); Bmemcpy(g_player[i].ps,g_player[0].ps,sizeof(DukePlayer_t));
if (ud.recstat != 2) if (ud.recstat != 2)
for (i=0; i<ud.multimode; i++) TRAVERSE_CONNECT(i)
{ {
g_player[i].ps->aim_mode = aimmode[i]; g_player[i].ps->aim_mode = aimmode[i];
g_player[i].ps->auto_aim = autoaim[i]; g_player[i].ps->auto_aim = autoaim[i];
@ -1396,7 +1382,7 @@ static void resetpspritevars(char g)
circ = 2048/ud.multimode; circ = 2048/ud.multimode;
g_whichPalForPlayer = 9; g_whichPalForPlayer = 9;
j = connecthead; j = 0;
i = headspritestat[STAT_PLAYER]; i = headspritestat[STAT_PLAYER];
while (i >= 0) while (i >= 0)
{ {
@ -1419,73 +1405,76 @@ static void resetpspritevars(char g)
g_playerSpawnPoints[(uint8_t)g_numPlayerSprites].os = s->sectnum; g_playerSpawnPoints[(uint8_t)g_numPlayerSprites].os = s->sectnum;
g_numPlayerSprites++; g_numPlayerSprites++;
if (j >= 0)
if (j < MAXPLAYERS)
{ {
s->owner = i; s->owner = i;
s->shade = 0; s->shade = 0;
s->xrepeat = 42; s->xrepeat = 42;
s->yrepeat = 36; s->yrepeat = 36;
s->cstat = 1+256; s->cstat = j < numplayers ? 1+256 : 32768;
s->xoffset = 0; s->xoffset = 0;
s->clipdist = 64; s->clipdist = 64;
if ((g&MODE_EOL) != MODE_EOL || g_player[j].ps->last_extra == 0) // if (j < playerswhenstarted)
{ {
g_player[j].ps->last_extra = g_player[j].ps->max_player_health; if ((g&MODE_EOL) != MODE_EOL || g_player[j].ps->last_extra == 0)
s->extra = g_player[j].ps->max_player_health;
g_player[j].ps->runspeed = g_playerFriction;
}
else s->extra = g_player[j].ps->last_extra;
s->yvel = j;
if (!g_player[j].pcolor && ud.multimode > 1 && !(GametypeFlags[ud.coop] & GAMETYPE_TDM))
{
if (s->pal == 0)
{ {
int32_t k = 0; g_player[j].ps->last_extra = g_player[j].ps->max_player_health;
s->extra = g_player[j].ps->max_player_health;
g_player[j].ps->runspeed = g_playerFriction;
}
else s->extra = g_player[j].ps->last_extra;
for (; k<ud.multimode; k++) s->yvel = j;
if (!g_player[j].pcolor && ud.multimode > 1 && !(GametypeFlags[ud.coop] & GAMETYPE_TDM))
{
if (s->pal == 0)
{ {
if (g_whichPalForPlayer == g_player[k].ps->palookup) int32_t k = 0;
for (; k<ud.multimode; k++)
{ {
g_whichPalForPlayer++; if (g_whichPalForPlayer == g_player[k].ps->palookup)
if (g_whichPalForPlayer >= 17) {
g_whichPalForPlayer = 9; g_whichPalForPlayer++;
k=0; if (g_whichPalForPlayer >= 17)
g_whichPalForPlayer = 9;
k=0;
}
} }
g_player[j].pcolor = s->pal = g_player[j].ps->palookup = g_whichPalForPlayer++;
if (g_whichPalForPlayer >= 17)
g_whichPalForPlayer = 9;
} }
g_player[j].pcolor = s->pal = g_player[j].ps->palookup = g_whichPalForPlayer++; else g_player[j].pcolor = g_player[j].ps->palookup = s->pal;
if (g_whichPalForPlayer >= 17)
g_whichPalForPlayer = 9;
} }
else g_player[j].pcolor = g_player[j].ps->palookup = s->pal; else
}
else
{
int32_t k = g_player[j].pcolor;
if (GametypeFlags[ud.coop] & GAMETYPE_TDM)
{ {
k = G_GetTeamPalette(g_player[j].pteam); int32_t k = g_player[j].pcolor;
g_player[j].ps->team = g_player[j].pteam;
if (GametypeFlags[ud.coop] & GAMETYPE_TDM)
{
k = G_GetTeamPalette(g_player[j].pteam);
g_player[j].ps->team = g_player[j].pteam;
}
s->pal = g_player[j].ps->palookup = k;
} }
s->pal = g_player[j].ps->palookup = k;
g_player[j].ps->i = i;
g_player[j].ps->frag_ps = j;
ActorExtra[i].owner = i;
ActorExtra[i].bposx = g_player[j].ps->bobposx = g_player[j].ps->oposx = g_player[j].ps->posx = s->x;
ActorExtra[i].bposy = g_player[j].ps->bobposy = g_player[j].ps->oposy = g_player[j].ps->posy = s->y;
ActorExtra[i].bposz = g_player[j].ps->oposz = g_player[j].ps->posz = s->z;
g_player[j].ps->oang = g_player[j].ps->ang = s->ang;
updatesector(s->x,s->y,&g_player[j].ps->cursectnum);
} }
g_player[j].ps->i = i; j++;
g_player[j].ps->frag_ps = j;
ActorExtra[i].owner = i;
ActorExtra[i].bposx = g_player[j].ps->bobposx = g_player[j].ps->oposx = g_player[j].ps->posx = s->x;
ActorExtra[i].bposy = g_player[j].ps->bobposy = g_player[j].ps->oposy = g_player[j].ps->posy = s->y;
ActorExtra[i].bposz = g_player[j].ps->oposz = g_player[j].ps->posz = s->z;
g_player[j].ps->oang = g_player[j].ps->ang = s->ang;
updatesector(s->x,s->y,&g_player[j].ps->cursectnum);
j = connectpoint2[j];
} }
else deletesprite(i); else deletesprite(i);
i = nexti; i = nexti;
@ -1518,20 +1507,15 @@ void G_ResetTimers(void)
void Net_WaitForEverybody(void) void Net_WaitForEverybody(void)
{ {
int32_t i; int32_t server_ready = g_player[0].playerreadyflag;
if (numplayers < 2 || net_server) return;
if (numplayers < 2) return;
packbuf[0] = PACKET_PLAYER_READY; packbuf[0] = PACKET_PLAYER_READY;
packbuf[1] = myconnectindex;
g_player[myconnectindex].playerreadyflag++; if (net_client)
enet_peer_send(net_peer, 0, enet_packet_create(packbuf, 2, ENET_PACKET_FLAG_RELIABLE));
// if we're a peer or slave, not a master
if ((g_networkBroadcastMode == 1) || (!g_networkBroadcastMode && (myconnectindex != connecthead)))
TRAVERSE_CONNECT(i)
{
if (i != myconnectindex) mmulti_sendpacket(i,packbuf,1);
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead)) break; //slaves in M/S mode only send to master
}
if (ud.multimode > 1) if (ud.multimode > 1)
{ {
@ -1543,7 +1527,7 @@ void Net_WaitForEverybody(void)
if (PLUTOPAK) // JBF 20030804 if (PLUTOPAK) // JBF 20030804
rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1); rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1);
gametext(160,190,"WAITING FOR PLAYERS",14,2); gametext(160,190,"WAITING FOR SERVER",14,2);
nextpage(); nextpage();
} }
@ -1551,28 +1535,11 @@ void Net_WaitForEverybody(void)
{ {
if (quitevent || keystatus[1]) G_GameExit(""); if (quitevent || keystatus[1]) G_GameExit("");
handleevents();
Net_GetPackets(); Net_GetPackets();
TRAVERSE_CONNECT(i) if (g_player[0].playerreadyflag > server_ready)
{ {
if (g_player[i].playerreadyflag < g_player[myconnectindex].playerreadyflag) break;
if ((!g_networkBroadcastMode) && (myconnectindex != connecthead))
{
// we're a slave
i = -1; break;
}
//slaves in M/S mode only wait for master
}
if (i < 0)
{
// master sends ready packet once it hears from all slaves
if (!g_networkBroadcastMode && myconnectindex == connecthead)
TRAVERSE_CONNECT(i)
{
packbuf[0] = PACKET_PLAYER_READY;
if (i != myconnectindex) mmulti_sendpacket(i,packbuf,1);
}
P_SetGamePalette(g_player[myconnectindex].ps, palette, 11); P_SetGamePalette(g_player[myconnectindex].ps, palette, 11);
return; return;
} }
@ -1580,8 +1547,6 @@ void Net_WaitForEverybody(void)
} }
extern int32_t jump_input; extern int32_t jump_input;
extern char g_szfirstSyncMsg[MAXSYNCBYTES][60];
extern int32_t g_foundSyncError;
void clearfifo(void) void clearfifo(void)
{ {
@ -1590,8 +1555,6 @@ void clearfifo(void)
syncvaltail = 0L; syncvaltail = 0L;
syncvaltottail = 0L; syncvaltottail = 0L;
memset(&syncstat, 0, sizeof(syncstat)); memset(&syncstat, 0, sizeof(syncstat));
memset(&g_szfirstSyncMsg, 0, sizeof(g_szfirstSyncMsg));
g_foundSyncError = 0;
bufferjitter = 1; bufferjitter = 1;
mymaxlag = otherminlag = 0; mymaxlag = otherminlag = 0;
jump_input = 0; jump_input = 0;
@ -1952,7 +1915,7 @@ int32_t G_EnterLevel(int32_t g)
if (!premap_quickenterlevel) if (!premap_quickenterlevel)
{ {
Net_WaitForEverybody(); Net_WaitForEverybody();
mmulti_flushpackets(); // mmulti_flushpackets();
G_FadePalette(0,0,0,0); G_FadePalette(0,0,0,0);
G_UpdateScreenArea(); G_UpdateScreenArea();
@ -1961,8 +1924,6 @@ int32_t G_EnterLevel(int32_t g)
G_DrawRooms(myconnectindex,65536); G_DrawRooms(myconnectindex,65536);
} }
for (i=0; i<ud.multimode; i++)
clearbufbyte(&g_player[i].playerquitflag,1,0x01010101);
g_player[myconnectindex].ps->over_shoulder_on = 0; g_player[myconnectindex].ps->over_shoulder_on = 0;
clearfrags(); clearfrags();

View file

@ -190,8 +190,8 @@ int32_t isanearoperator(int32_t lotag)
inline int32_t G_CheckPlayerInSector(int32_t sect) inline int32_t G_CheckPlayerInSector(int32_t sect)
{ {
int32_t i = connecthead; int32_t i;
for (; i>=0; i=connectpoint2[i]) TRAVERSE_CONNECT(i)
if (sprite[g_player[i].ps->i].sectnum == sect) return i; if (sprite[g_player[i].ps->i].sectnum == sect) return i;
return -1; return -1;
} }
@ -310,7 +310,7 @@ void G_DoSectorAnimations(void)
{ {
my.z += v; my.z += v;
myvel.z = 0; myvel.z = 0;
myzbak[((movefifoplc-1)&(MOVEFIFOSIZ-1))] = g_player[p].ps->posz; myzbak[0] = g_player[p].ps->posz;
} }
} }

View file

@ -386,7 +386,7 @@ void Net_GetSyncData(char *packbuf, int32_t packbufleng, int32_t *j, int32_t oth
while (1) while (1)
{ {
for (i = connectpoint2[connecthead]; i >= 0; i = connectpoint2[i]) TRAVERSE_CONNECT(i)
{ {
for (sb = 0; sb < g_numSyncBytes; sb++) for (sb = 0; sb < g_numSyncBytes; sb++)
{ {