mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-18 14:41:55 +00:00
Classic: fix oob read of frame buffer when leftmost vline has a mirror.
In the mirror reversing code, get rid of the padding. This may produce seams, but they appear to be extremely transient and shouldn't be noticeable. In game.c, add a debugging compilation switch DEBUG_MIRRORS_ONLY. git-svn-id: https://svn.eduke32.com/eduke32@3726 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
6deabcdb5d
commit
1ec058a47f
3 changed files with 39 additions and 20 deletions
|
@ -8912,9 +8912,11 @@ int32_t drawrooms(int32_t daposx, int32_t daposy, int32_t daposz,
|
|||
mirrorsx1 = xdimen-1; mirrorsx2 = 0;
|
||||
for (i=numscans-1; i>=0; i--)
|
||||
{
|
||||
if (wall[thewall[i]].nextsector < 0) continue;
|
||||
if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
|
||||
if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
|
||||
if (wall[thewall[i]].nextsector >= 0)
|
||||
{
|
||||
if (xb1[i] < mirrorsx1) mirrorsx1 = xb1[i];
|
||||
if (xb2[i] > mirrorsx2) mirrorsx2 = xb2[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<mirrorsx1; i++)
|
||||
|
@ -14603,41 +14605,51 @@ void preparemirror(int32_t dax, int32_t day, int16_t daang, int16_t dawall,
|
|||
void completemirror(void)
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (rendmode) return;
|
||||
if (rendmode)
|
||||
return;
|
||||
#endif
|
||||
|
||||
//Can't reverse with uninitialized data
|
||||
// Can't reverse when the world has not yet been drawn from the other side.
|
||||
if (inpreparemirror) { inpreparemirror = 0; return; }
|
||||
|
||||
if (mirrorsx1 > 0)
|
||||
mirrorsx1--;
|
||||
if (mirrorsx2 < windowx2-windowx1-1)
|
||||
mirrorsx2++;
|
||||
// The mirroring code maps the rightmost pixel to the right neighbor of the
|
||||
// leftmost one (see copybufreverse() call below). Thus, the leftmost would
|
||||
// be mapped to the right neighbor of the rightmost one, which would be out
|
||||
// of bounds.
|
||||
if (mirrorsx1 == 0)
|
||||
mirrorsx1 = 1;
|
||||
|
||||
// Require that the mirror is at least one pixel wide before padding.
|
||||
if (mirrorsx1 > mirrorsx2)
|
||||
return;
|
||||
|
||||
// Variables mirrorsx{1,2} refer to the source scene here, the one drawn
|
||||
// from the inside of the mirror.
|
||||
|
||||
begindrawing();
|
||||
{
|
||||
// Address of the mirror's top left corner:
|
||||
intptr_t p = frameplace + ylookup[windowy1+mirrorsy1] + windowx1+mirrorsx1;
|
||||
|
||||
const int32_t mirrofs = windowx2-windowx1-mirrorsx2-mirrorsx1;
|
||||
// Width in pixels (screen x's are inclusive on both sides):
|
||||
const int32_t width = mirrorsx2-mirrorsx1+1;
|
||||
// Height in pixels (screen y's are half-open because they come from umost/dmost):
|
||||
const int32_t height = mirrorsy2-mirrorsy1;
|
||||
|
||||
// Address of the mirror wall's top left corner in the source scene:
|
||||
intptr_t p = frameplace + ylookup[windowy1+mirrorsy1] + windowx1+mirrorsx1;
|
||||
|
||||
// Offset (wrt p) of a mirror line's left corner in the destination:
|
||||
// p+destof == frameplace + ylookup[...] + windowx2-mirrorsx2
|
||||
const int32_t destofs = windowx2-mirrorsx2-windowx1-mirrorsx1;
|
||||
|
||||
int32_t y;
|
||||
|
||||
for (y=0; y<height; y++)
|
||||
{
|
||||
#if 0
|
||||
if ((p-frameplace)+1 + width-1 >= bytesperline*ydim)
|
||||
if ((p-frameplace) + width-1 >= bytesperline*ydim)
|
||||
printf("oob read: mirrorsx1=%d, mirrorsx2=%d\n", mirrorsx1, mirrorsx2);
|
||||
#endif
|
||||
copybufbyte((void *)(p+1), tempbuf, width);
|
||||
tempbuf[width-1] = tempbuf[width-2]; // FIXME: with GEKKO, array subscripts are below array bounds
|
||||
copybufreverse(&tempbuf[width-1], (void *)(p+mirrofs), width);
|
||||
copybufbyte((void *)p, tempbuf, width);
|
||||
copybufreverse(&tempbuf[width-1], (void *)(p+destofs+1), width);
|
||||
|
||||
p += ylookup[1];
|
||||
faketimerhandler();
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#define MAXNODESPERLINE (MAXYSAVES/MAXYDIM) // 307
|
||||
#define MAXCLIPDIST 1024
|
||||
|
||||
// uncomment to clear the screen before each top-level draw
|
||||
// (classic only)
|
||||
// Uncomment to clear the screen before each top-level draw (classic only).
|
||||
// FIXME: doesn't work with mirrors.
|
||||
//#define ENGINE_CLEAR_SCREEN
|
||||
|
||||
#ifdef YAX_ENABLE
|
||||
|
|
|
@ -64,6 +64,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
# include "lunatic_game.h"
|
||||
#endif
|
||||
|
||||
// Uncomment to prevent anything except mirrors from drawing. It is sensible to
|
||||
// also uncomment ENGINE_CLEAR_SCREEN in build/include/engine_priv.h.
|
||||
//#define DEBUG_MIRRORS_ONLY
|
||||
|
||||
#if KRANDDEBUG
|
||||
# define GAME_INLINE
|
||||
# define GAME_STATIC
|
||||
|
@ -3881,7 +3885,9 @@ void G_DrawRooms(int32_t snum, int32_t smoothratio)
|
|||
// for G_PrintCoords
|
||||
dr_viewingrange = viewingrange;
|
||||
dr_yxaspect = yxaspect;
|
||||
|
||||
#ifdef DEBUG_MIRRORS_ONLY
|
||||
gotpic[MIRROR>>3] |= (1<<(MIRROR&7));
|
||||
#else
|
||||
yax_preparedrawrooms();
|
||||
drawrooms(CAMERA(pos.x),CAMERA(pos.y),CAMERA(pos.z),CAMERA(ang),CAMERA(horiz),CAMERA(sect));
|
||||
yax_drawrooms(G_DoSpriteAnimations, CAMERA(sect), 0, smoothratio);
|
||||
|
@ -3892,6 +3898,7 @@ void G_DrawRooms(int32_t snum, int32_t smoothratio)
|
|||
|
||||
drawing_ror = 0;
|
||||
drawmasks();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_screenCapture)
|
||||
|
|
Loading…
Reference in a new issue