diff --git a/source/core/interpolate.cpp b/source/core/interpolate.cpp new file mode 100644 index 000000000..9a27d84f0 --- /dev/null +++ b/source/core/interpolate.cpp @@ -0,0 +1,142 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 1997, 2005 - 3D Realms Entertainment + +This file is part of Shadow Warrior version 1.2 + +Shadow Warrior is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +Original Source: 1997 - Frank Maddin and Jim Norwood +Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms +*/ +//------------------------------------------------------------------------- + +#include "ns.h" + +#include "interp.h" +#include "m_fixed.h" + +#define (MAXINTERPOLATIONS 16384 + 256) +static int recursions = 0; +static int numinterpolations = 0; + +// Not used yet. The entire interpolation feature as-is is highly serialization unfriendly because it only stores pointers without context, meaning there is no safe way to store them in a savegame without constantly risking breakage. + +// Todo: This really needs to be made serialization friendly +struct Interpolation +{ + int oldipos; + int bakipos; + void *curipos; + bool isshort; +}; + +static Interpolation interpolations[MAXINTERPOLATIONS]; + + +void setinterpolation(void *posptr, bool isshort) +{ + if (numinterpolations >= MAXINTERPOLATIONS) + return; + + for (int i = numinterpolations - 1; i >= 0; i--) + { + if (interpolations[i].curipos == posptr) + return; + } + + interpolations[numinterpolations].curipos = posptr; + interpolations[numinterpolations].oldipos = *posptr; + numinterpolations++; +} + +void setinterpolation(int *posptr) +{ + setinterpolation(posptr, false); +} + +// only used by SW to interpolate floorheinum and ceilingheinum +void setinterpolation(short *posptr) +{ + setinterpolation(posptr, true); +} + +void stopinterpolation(void *posptr) +{ + for (int i = numinterpolations - 1; i >= 0; i--) + { + if (curipos[i] == posptr) + { + numinterpolations--; + interpolations[i] = interpolations[numinterpolations]; + } + } +} + +void updateinterpolations(void) // Stick at beginning of domovethings +{ + int i; + + for (int i = numinterpolations - 1; i >= 0; i--) + interpolations[i].oldipos = interpolations[i].isshort? *(short*)interpolations[i].curipos : *(int*)interpolations[i].curipos; +} + +// must call restore for every do interpolations +// make sure you don't exit +void dointerpolations(int smoothratio) // Stick at beginning of drawscreen +{ + if (recursions++) + return; + + int i, j, odelta, ndelta; + + ndelta = 0; + j = 0; + + for (i = numinterpolations - 1; i >= 0; i--) + { + bakipos[i] = *curipos[i]; + + odelta = ndelta; + ndelta = (*curipos[i]) - oldipos[i]; + + if (odelta != ndelta) + j = FixedMul(ndelta, smoothratio); + + *curipos[i] = oldipos[i] + j; + } +} + +void restoreinterpolations(bool force) // Stick at end of drawscreen +{ + int i; + + if (!force && --recursions) + return; + + recursions = 0; // if interpolations are forcibly restored, the recursion counter must also be reset. + for (i = numinterpolations - 1; i >= 0; i--) + *curipos[i] = bakipos[i]; +} + +void togglespriteinterpolation(spritetype *sp, int set) +{ + auto func = set ? setinterpolation : stopinterpolation; + func(&sp->x); + func(&sp->y); + func(&sp->z); +} + diff --git a/source/games/duke/CMakeLists.txt b/source/games/duke/CMakeLists.txt index e52f1828b..4c760d937 100644 --- a/source/games/duke/CMakeLists.txt +++ b/source/games/duke/CMakeLists.txt @@ -14,6 +14,7 @@ set( PCH_SOURCES src/gameexec.cpp src/gamevars.cpp src/global.cpp + src/interpolate.cpp src/namesdyn.cpp src/net.cpp src/osdcmds.cpp diff --git a/source/games/duke/src/actors_e.cpp b/source/games/duke/src/actors_e.cpp index cc7bf0827..01a5df7d8 100644 --- a/source/games/duke/src/actors_e.cpp +++ b/source/games/duke/src/actors_e.cpp @@ -38,51 +38,6 @@ BEGIN_DUKE_NS int32_t otherp; -int G_SetInterpolation(int32_t *const posptr) -{ - if (g_interpolationCnt >= MAXINTERPOLATIONS) - return 1; - - for (bssize_t i = 0; i < g_interpolationCnt; ++i) - if (curipos[i] == posptr) - return 0; - - curipos[g_interpolationCnt] = posptr; - oldipos[g_interpolationCnt] = *posptr; - g_interpolationCnt++; - return 0; -} - -void G_StopInterpolation(const int32_t * const posptr) -{ - for (bssize_t i = 0; i < g_interpolationCnt; ++i) - if (curipos[i] == posptr) - { - g_interpolationCnt--; - oldipos[i] = oldipos[g_interpolationCnt]; - bakipos[i] = bakipos[g_interpolationCnt]; - curipos[i] = curipos[g_interpolationCnt]; - } -} - -void G_DoInterpolations(int smoothRatio) -{ - if (g_interpolationLock++) - return; - - int32_t ndelta = 0; - - for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i) - { - int32_t const odelta = ndelta; - bakipos[i] = *curipos[i]; - ndelta = (*curipos[i]) - oldipos[i]; - if (odelta != ndelta) - j = mulscale16(ndelta, smoothRatio); - *curipos[i] = oldipos[i] + j; - } -} - void G_ClearCameraView(DukePlayer_t *ps) { ps->newowner = -1; diff --git a/source/games/duke/src/global.h b/source/games/duke/src/global.h index 9278b4a23..745d0c130 100644 --- a/source/games/duke/src/global.h +++ b/source/games/duke/src/global.h @@ -51,13 +51,6 @@ BEGIN_DUKE_NS // duke3d global soup :( -G_EXTERN int32_t g_interpolationCnt; -G_EXTERN int32_t g_interpolationLock; -G_EXTERN int32_t oldipos[MAXINTERPOLATIONS]; -G_EXTERN int32_t *curipos[MAXINTERPOLATIONS]; -G_EXTERN int32_t bakipos[MAXINTERPOLATIONS]; - - G_EXTERN int32_t duke3d_globalflags; // KEEPINSYNC astub.c (used values only) @@ -284,27 +277,38 @@ enum EF_HIDEFROMSP = 1<<0, }; -EXTERN_INLINE_HEADER void G_UpdateInterpolations(void); -EXTERN_INLINE_HEADER void G_RestoreInterpolations(void); +// Interpolation code is the same in all games with slightly different naming - this needs to be unified and cleaned up. +extern int32_t g_interpolationCnt; +extern int32_t* curipos[MAXINTERPOLATIONS]; +extern int32_t bakipos[MAXINTERPOLATIONS]; +void G_UpdateInterpolations(void); +void G_RestoreInterpolations(void); +int G_SetInterpolation(int32_t* const posptr); +void G_StopInterpolation(const int32_t* const posptr); +void G_DoInterpolations(int smoothRatio); -#if defined global_c_ || !defined DISABLE_INLINING - -EXTERN_INLINE void G_UpdateInterpolations(void) //Stick at beginning of G_DoMoveThings +// old names as porting help. +inline void updateinterpolations() { - for (bssize_t i=g_interpolationCnt-1; i>=0; i--) oldipos[i] = *curipos[i]; + G_UpdateInterpolations(); +} +inline void restoreinterpolations() +{ + G_RestoreInterpolations(); +} +inline int setinterpolation(int32_t* posptr) +{ + G_SetInterpolation(posptr); +} +inline int stopinterpolation(int32_t* posptr) +{ + G_SetInterpolation(posptr); +} +inline int dointerpolations(int smoothratio) +{ + G_DoInterpolations(smoothratio); } -EXTERN_INLINE void G_RestoreInterpolations(void) //Stick at end of drawscreen -{ - int32_t i=g_interpolationCnt-1; - - if (--g_interpolationLock) - return; - - for (; i>=0; i--) *curipos[i] = bakipos[i]; -} - -#endif // Hack struct to allow old code to access the EDuke-style player data without changing it. struct psaccess diff --git a/source/games/duke/src/interpolate.cpp b/source/games/duke/src/interpolate.cpp new file mode 100644 index 000000000..6886e1102 --- /dev/null +++ b/source/games/duke/src/interpolate.cpp @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------- +/* +Copyright (C) 2016 EDuke32 developers and contributors + +This file is part of EDuke32. + +EDuke32 is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License version 2 +as published by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +//------------------------------------------------------------------------- +#include "ns.h" // Must come before everything else! +#include "global.h" + +BEGIN_DUKE_NS + +// No need to revert this to the original state - to be robust this needs to be redone entirely, so this code will disappear anyway. + +#define MAXINTERPOLATIONS MAXSPRITES + +int32_t g_interpolationCnt; +int32_t g_interpolationLock; +int32_t oldipos[MAXINTERPOLATIONS]; +int32_t *curipos[MAXINTERPOLATIONS]; +int32_t bakipos[MAXINTERPOLATIONS]; + +int G_SetInterpolation(int32_t *const posptr) +{ + if (g_interpolationCnt >= MAXINTERPOLATIONS) + return 1; + + for (bssize_t i = 0; i < g_interpolationCnt; ++i) + if (curipos[i] == posptr) + return 0; + + curipos[g_interpolationCnt] = posptr; + oldipos[g_interpolationCnt] = *posptr; + g_interpolationCnt++; + return 0; +} + +void G_StopInterpolation(const int32_t * const posptr) +{ + for (bssize_t i = 0; i < g_interpolationCnt; ++i) + if (curipos[i] == posptr) + { + g_interpolationCnt--; + oldipos[i] = oldipos[g_interpolationCnt]; + bakipos[i] = bakipos[g_interpolationCnt]; + curipos[i] = curipos[g_interpolationCnt]; + } +} + +void G_DoInterpolations(int smoothRatio) +{ + if (g_interpolationLock++) + return; + + int32_t ndelta = 0; + + for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i) + { + int32_t const odelta = ndelta; + bakipos[i] = *curipos[i]; + ndelta = (*curipos[i]) - oldipos[i]; + if (odelta != ndelta) + j = mulscale16(ndelta, smoothRatio); + *curipos[i] = oldipos[i] + j; + } +} + + +void G_UpdateInterpolations(void) //Stick at beginning of G_DoMoveThings +{ + for (bssize_t i=g_interpolationCnt-1; i>=0; i--) oldipos[i] = *curipos[i]; +} + +void G_RestoreInterpolations(void) //Stick at end of drawscreen +{ + int32_t i=g_interpolationCnt-1; + + if (--g_interpolationLock) + return; + + for (; i>=0; i--) *curipos[i] = bakipos[i]; +} + + +END_DUKE_NS