Merge branch 'fuzzfixer' into 'master'

HUGE crash fixes (super hyper fuzzer + ASAN)

See merge request KartKrew/Kart!1908
This commit is contained in:
AJ Martinez 2024-02-09 22:49:22 +00:00
commit bd9511424a
17 changed files with 165 additions and 100 deletions

View file

@ -856,6 +856,7 @@ void D_SRB2Loop(void)
precise_t enterprecise = I_GetPreciseTime();
precise_t finishprecise = enterprecise;
g_dc = {};
Z_Frame_Reset();
{

View file

@ -301,6 +301,7 @@ void DRPC_RemoveRequest(discordRequest_t *removeRequest)
}
Z_Free(removeRequest->username);
Z_Free(removeRequest->discriminator);
Z_Free(removeRequest->userID);
Z_Free(removeRequest);
}
@ -412,6 +413,7 @@ void DRPC_UpdatePresence(void)
#endif
boolean joinSecretSet = false;
char *clientJoinSecret = NULL;
DiscordRichPresence discordPresence;
memset(&discordPresence, 0, sizeof(discordPresence));
@ -447,7 +449,8 @@ void DRPC_UpdatePresence(void)
// Grab the host's IP for joining.
if ((join = DRPC_GetServerIP()) != NULL)
{
discordPresence.joinSecret = DRPC_XORIPString(join);
clientJoinSecret = DRPC_XORIPString(join);
discordPresence.joinSecret = clientJoinSecret;
joinSecretSet = true;
}
else
@ -650,6 +653,7 @@ void DRPC_UpdatePresence(void)
}
Discord_UpdatePresence(&discordPresence);
free(clientJoinSecret);
}
#endif // HAVE_DISCORDRPC

View file

@ -500,7 +500,7 @@ char *M_GetToken(const char *inputString);
void M_UnGetToken(void);
UINT32 M_GetTokenPos(void);
void M_TokenizerOpen(const char *inputString);
void M_TokenizerOpen(const char *inputString, size_t inputLength);
void M_TokenizerClose(void);
const char *M_TokenizerRead(UINT32 i);
UINT32 M_TokenizerGetEndPos(void);

View file

@ -32,6 +32,7 @@ void PaletteManager::update(Rhi& rhi, Handle<GraphicsContext> ctx)
palette_ = rhi.create_texture({TextureFormat::kRGBA, kPaletteSize, 1, TextureWrapMode::kClamp, TextureWrapMode::kClamp});
}
#if 0
if (!lighttable_)
{
lighttable_ = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp});
@ -41,6 +42,7 @@ void PaletteManager::update(Rhi& rhi, Handle<GraphicsContext> ctx)
{
encore_lighttable_ = rhi.create_texture({TextureFormat::kLuminance, kPaletteSize, kLighttableRows, TextureWrapMode::kClamp, TextureWrapMode::kClamp});
}
#endif
if (!default_colormap_)
{
@ -57,6 +59,7 @@ void PaletteManager::update(Rhi& rhi, Handle<GraphicsContext> ctx)
rhi.update_texture(ctx, palette_, {0, 0, kPaletteSize, 1}, PixelFormat::kRGBA8, tcb::as_bytes(tcb::span(palette_32)));
}
#if 0
// Lighttables
{
if (colormaps != nullptr)
@ -65,12 +68,15 @@ void PaletteManager::update(Rhi& rhi, Handle<GraphicsContext> ctx)
rhi.update_texture(ctx, lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, colormap_bytes);
}
// FIXME: This is broken, encoremap should not be used directly.
// Instead, use colormaps + COLORMAP_REMAPOFFSET. See R_ReInitColormaps.
if (encoremap != nullptr)
{
tcb::span<const std::byte> encoremap_bytes = tcb::as_bytes(tcb::span(encoremap, kPaletteSize * kLighttableRows));
rhi.update_texture(ctx, encore_lighttable_, {0, 0, kPaletteSize, kLighttableRows}, PixelFormat::kR8, encoremap_bytes);
}
}
#endif
// Default colormap
{

View file

@ -20,8 +20,10 @@ namespace srb2::hwr2
class PaletteManager
{
rhi::Handle<rhi::Texture> palette_;
#if 0
rhi::Handle<rhi::Texture> lighttable_;
rhi::Handle<rhi::Texture> encore_lighttable_;
#endif
rhi::Handle<rhi::Texture> default_colormap_;
std::unordered_map<const uint8_t*, rhi::Handle<rhi::Texture>> colormaps_;
@ -36,8 +38,10 @@ public:
PaletteManager& operator=(PaletteManager&&);
rhi::Handle<rhi::Texture> palette() const noexcept { return palette_; }
#if 0
rhi::Handle<rhi::Texture> lighttable() const noexcept { return lighttable_; }
rhi::Handle<rhi::Texture> encore_lighttable() const noexcept { return encore_lighttable_; }
#endif
rhi::Handle<rhi::Texture> default_colormap() const noexcept { return default_colormap_; }
void update(rhi::Rhi& rhi, rhi::Handle<rhi::GraphicsContext> ctx);

View file

@ -1042,6 +1042,10 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
return false;
}
// What the fuck is calling this with stale refs? Whatever, validation's cheap.
if (P_MobjWasRemoved(t1) || P_MobjWasRemoved(t2) || !t1->player || !t2->player)
return false;
// Clash instead of damage if both parties have any of these conditions
auto canClash = [](mobj_t *t1, mobj_t *t2)
{

View file

@ -212,6 +212,12 @@ private:
}
}
if (playerstat[0].sorted == -1)
{
maxdist = -1;
return;
}
maxdist = P_ScaleFromMap(players[playerstat[0].sorted].distancetofinish, FRACUNIT);
}

View file

@ -1255,7 +1255,15 @@ static void K_DrawDraftCombiring(player_t *player, mobj_t *victim, fixed_t curdi
}
else
{
c = FixedMul((CHAOTIXBANDCOLORS - 1)<<FRACBITS, FixedDiv(curdist-minimumdist, maxdist-minimumdist)) >> FRACBITS;
fixed_t num = curdist - minimumdist;
fixed_t den = maxdist - minimumdist;
if (den < 1)
den = 1;
if (num < 0)
num = 0;
if (num > den)
num = den;
c = FixedMul((CHAOTIXBANDCOLORS - 1)<<FRACBITS, FixedDiv(num, den)) >> FRACBITS;
}
stepx = (victim->x - player->mo->x) / CHAOTIXBANDLEN;
@ -7235,7 +7243,7 @@ void K_RepairOrbitChain(mobj_t *orbit)
}
// Then recount to make sure item amount is correct
if (orbit->target && orbit->target->player)
if (orbit->target && orbit->target->player && !P_MobjWasRemoved(orbit->target))
{
INT32 num = 0;
@ -7252,7 +7260,7 @@ void K_RepairOrbitChain(mobj_t *orbit)
prev->movedir = num;
}
if (orbit->target->player->itemamount != num)
if (orbit->target && !P_MobjWasRemoved(orbit->target) && orbit->target->player->itemamount != num)
orbit->target->player->itemamount = num;
}
}
@ -9763,6 +9771,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
adddist = (UINT32)disttowaypoint;
}
*/
Z_Free(pathBackwards.array);
}
/*
else

View file

@ -199,7 +199,7 @@ static boolean RankCapsules_LoadMapData(const virtres_t *virt)
if (g_rankCapsules_udmf) // Count how many entries for each type we got in textmap.
{
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
M_TokenizerOpen((char *)textmap->data);
M_TokenizerOpen((char *)textmap->data, textmap->size);
if (!RankCapsules_TextmapCount(textmap->size))
{
M_TokenizerClose();

View file

@ -2276,7 +2276,7 @@ static UINT32 tokenizerInputLength = 0;
static UINT8 tokenizerInComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */
static boolean tokenizerIsString = false; // did we strip quotes from this token?
void M_TokenizerOpen(const char *inputString)
void M_TokenizerOpen(const char *inputString, size_t inputLength)
{
size_t i;
@ -2286,7 +2286,7 @@ void M_TokenizerOpen(const char *inputString)
tokenCapacity[i] = 1024;
tokenizerToken[i] = (char*)Z_Malloc(tokenCapacity[i] * sizeof(char), PU_STATIC, NULL);
}
tokenizerInputLength = strlen(tokenizerInput);
tokenizerInputLength = inputLength;
}
void M_TokenizerClose(void)

View file

@ -12139,7 +12139,12 @@ void A_SSMineExplode(mobj_t *actor)
return;
delay = K_MineExplodeAttack(actor, (3*actor->info->painchance)>>1, (boolean)locvar1);
K_SpawnMineExplosion(actor, (actor->target && actor->target->player) ? actor->target->player->skincolor : SKINCOLOR_KETCHUP, delay);
skincolornum_t color = SKINCOLOR_KETCHUP;
if (!P_MobjWasRemoved(actor->target) && actor->target->player)
color = actor->target->player->skincolor;
K_SpawnMineExplosion(actor, color, delay);
}
void A_SSMineFlash(mobj_t *actor)

View file

@ -1643,7 +1643,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// SRB2kart
// I wish I knew a better way to do this
if (target->target && target->target->player && target->target->player->mo)
if (!P_MobjWasRemoved(target->target) && target->target->player && !P_MobjWasRemoved(target->target->player->mo))
{
if ((target->target->player->itemflags & IF_EGGMANOUT) && target->type == MT_EGGMANITEM_SHIELD)
target->target->player->itemflags &= ~IF_EGGMANOUT;
@ -2698,6 +2698,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator)
return false;
// source is checked without a removal guard in so many places that it's genuinely less work to do it here.
if (source && P_MobjWasRemoved(source))
source = NULL;
if (source && source->player && source->player->spectator)
return false;

View file

@ -3459,7 +3459,7 @@ static boolean P_LoadMapData(const virtres_t *virt)
if (udmf) // Count how many entries for each type we got in textmap.
{
virtlump_t *textmap = vres_Find(virt, "TEXTMAP");
M_TokenizerOpen((char *)textmap->data);
M_TokenizerOpen((char *)textmap->data, textmap->size);
if (!TextmapCount(textmap->size))
{
M_TokenizerClose();

View file

@ -396,13 +396,10 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc->x]) - 3);
}
for (i = 0; i < dc->numlights; i++)
auto set_light_vars = [&](INT32 i)
{
rlight = &dc->lightlist[i];
if ((rlight->flags & FOF_NOSHADE))
continue;
lightnum = R_AdjustLightLevel(rlight->lightnum);
if (lightnum < 0)
@ -421,20 +418,38 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
};
auto set_colormap_below_light = [&]
{
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(ldef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
};
// Use the base sector's light level above the first FOF.
// You can imagine it as the sky casting its light on top of the highest FOF.
set_light_vars(0);
set_colormap_below_light();
for (i = 0; i < dc->numlights; i++)
{
if ((dc->lightlist[i].flags & FOF_NOSHADE))
continue;
set_light_vars(i);
height = rlight->height;
rlight->height += rlight->heightstep;
if (height <= windowtop)
{
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(ldef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
set_colormap_below_light();
continue;
}
@ -453,14 +468,7 @@ static void R_RenderMaskedSegLoop(drawcolumndata_t* dc, drawseg_t *drawseg, INT3
}
colfunc_2s(dc, col, bmCol, -1);
windowtop = windowbottom + 1;
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(ldef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
set_colormap_below_light();
}
windowbottom = realbot;
if (windowtop < windowbottom)
@ -1158,42 +1166,64 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t bheight = 0;
INT32 solid = 0;
auto set_light_vars = [&](INT32 i)
{
rlight = &dc->lightlist[i];
lightnum = R_AdjustLightLevel(rlight->lightnum);
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
if (pfloor->fofflags & FOF_FOG)
{
if (pfloor->master->frontsector->extra_colormap)
rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
else
{
if (rlight->extra_colormap)
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
};
auto set_colormap_below_light = [&]
{
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(curline->linedef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
};
// Use the base sector's light level above the first FOF.
// You can imagine it as the sky casting its light on top of the highest FOF.
set_light_vars(0);
set_colormap_below_light();
for (i = 0; i < dc->numlights; i++)
{
// Check if the current light effects the colormap/lightlevel
rlight = &dc->lightlist[i];
xwalllights = NULL;
if (!(dc->lightlist[i].flags & FOF_NOSHADE))
{
lightnum = R_AdjustLightLevel(rlight->lightnum);
if (lightnum < 0)
xwalllights = scalelight[0];
else if (lightnum >= LIGHTLEVELS)
xwalllights = scalelight[LIGHTLEVELS-1];
else
xwalllights = scalelight[lightnum];
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE-1;
if (pfloor->fofflags & FOF_FOG)
{
if (pfloor->master->frontsector->extra_colormap)
rlight->rcolormap = pfloor->master->frontsector->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
else
{
if (rlight->extra_colormap)
rlight->rcolormap = rlight->extra_colormap->colormap + (xwalllights[pindex] - colormaps);
else
rlight->rcolormap = xwalllights[pindex];
}
}
set_light_vars(i);
solid = 0; // don't carry over solid-cutting flag from the previous light
@ -1227,16 +1257,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (height <= windowtop)
{
if (xwalllights)
{
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(curline->linedef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
}
set_colormap_below_light();
if (solid && windowtop < bheight)
windowtop = bheight;
continue;
@ -1264,16 +1285,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
else
windowtop = windowbottom + 1;
if (xwalllights)
{
dc->colormap = rlight->rcolormap;
dc->lightmap = xwalllights[pindex];
dc->fullbright = colormaps;
if (remap && !(curline->linedef->flags & ML_TFERLINE))
{
dc->colormap += COLORMAP_REMAPOFFSET;
dc->fullbright += COLORMAP_REMAPOFFSET;
}
}
set_colormap_below_light();
}
windowbottom = sprbotscreen;
// draw the texture, if there is any space left
@ -2049,11 +2061,17 @@ void R_StoreWallRange(INT32 start, INT32 stop)
ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
}
auto get_flat_tex = [](INT32 texnum)
{
texnum = R_GetTextureNum(texnum);
return textures[texnum]->holes ? 0 : texnum; // R_DrawWallColumn cannot render holey textures
};
if (!backsector)
{
fixed_t texheight;
// single sided line
midtexture = R_GetTextureNum(sidedef->midtexture);
midtexture = get_flat_tex(sidedef->midtexture);
midbrightmapped = R_TextureHasBrightmap(midtexture);
midremap = wantremap && R_TextureCanRemap(sidedef->midtexture);
texheight = textureheight[midtexture];
@ -2246,7 +2264,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
fixed_t texheight;
// top texture
toptexture = R_GetTextureNum(sidedef->toptexture);
toptexture = get_flat_tex(sidedef->toptexture);
topbrightmapped = R_TextureHasBrightmap(toptexture);
topremap = wantremap && R_TextureCanRemap(sidedef->toptexture);
texheight = textureheight[toptexture];
@ -2276,7 +2294,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
&& (worldlow > worldbottom || worldlowslope > worldbottomslope)) // Only if VISIBLE!!!
{
// bottom texture
bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
bottomtexture = get_flat_tex(sidedef->bottomtexture);
bottombrightmapped = R_TextureHasBrightmap(bottomtexture);
bottomremap = wantremap && R_TextureCanRemap(sidedef->bottomtexture);

View file

@ -255,7 +255,7 @@ static UINT8 *R_AllocateTextureBlock(size_t blocksize, UINT8 **user)
{
texturememory += blocksize;
return Z_Malloc(blocksize, PU_CACHE, user);
return Z_Malloc(blocksize, PU_LEVEL, user);
}
static UINT8 *R_AllocateDummyTextureBlock(size_t width, UINT8 **user)
@ -351,7 +351,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
return block;
}
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL);
realpatch = (softwarepatch_t *)pdata;
#ifndef NO_PNG_LUMPS
@ -392,7 +392,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
texture->holes = true;
texture->flip = patch->flip;
blocksize = lumplength;
block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
block = Z_Calloc(blocksize, PU_LEVEL, // will change tag at end of this function
&texturecache[texnum]);
M_Memcpy(block, realpatch, blocksize);
texturememory += blocksize;
@ -423,7 +423,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
texture->flip = 0;
blocksize = (texture->width * 4) + (texture->width * texture->height);
texturememory += blocksize;
block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);
block = Z_Malloc(blocksize+1, PU_LEVEL, &texturecache[texnum]);
memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack
@ -446,7 +446,7 @@ UINT8 *R_GenerateTexture(size_t texnum)
wadnum = patch->wad;
lumpnum = patch->lump;
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_LEVEL);
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = (softwarepatch_t *)pdata;
dealloc = true;
@ -515,8 +515,6 @@ UINT8 *R_GenerateTexture(size_t texnum)
}
done:
// Now that the texture has been built in column cache, it is purgable from zone memory.
Z_ChangeTag(block, PU_CACHE);
return blocktex;
}
@ -535,7 +533,7 @@ UINT8 *R_GenerateTextureAsFlat(size_t texnum)
if (!texture->flat)
{
// Well, let's do it now, then.
texture->flat = Z_Malloc(size, PU_STATIC, NULL);
Z_Malloc(size, PU_LEVEL, &texture->flat);
// Picture_TextureToFlat handles everything for us.
converted = (UINT8 *)Picture_TextureToFlat(texnum);
@ -895,7 +893,7 @@ UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col)
void *R_GetFlat(lumpnum_t flatlumpnum)
{
return W_CacheLumpNum(flatlumpnum, PU_CACHE);
return W_CacheLumpNum(flatlumpnum, PU_LEVEL);
}
//
@ -941,7 +939,7 @@ void *R_GetLevelFlat(drawspandata_t* ds, levelflat_t *levelflat)
{
INT32 pngwidth, pngheight;
levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_LEVEL), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0);
levelflat->width = (UINT16)pngwidth;
levelflat->height = (UINT16)pngheight;
@ -954,7 +952,7 @@ void *R_GetLevelFlat(drawspandata_t* ds, levelflat_t *levelflat)
{
UINT8 *converted;
size_t size;
softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE);
softwarepatch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_LEVEL);
levelflat->width = ds->flatwidth = SHORT(patch->width);
levelflat->height = ds->flatheight = SHORT(patch->height);

View file

@ -685,10 +685,11 @@ void R_DrawMaskedColumn(drawcolumndata_t* dc, column_t *column, column_t *bright
if (dc->yh >= baseclip && baseclip != -1)
dc->yh = baseclip;
if (dc->yl <= dc->yh && dc->yh > 0)
if (dc->yl <= dc->yh && dc->yh > 0 && column->length != 0)
{
dc->source = (UINT8 *)column + 3;
dc->sourcelength = column->length;
dc->texheight = column->length;
if (brightmap != NULL)
{
dc->brightmap = (UINT8 *)brightmap + 3;
@ -771,10 +772,11 @@ void R_DrawFlippedMaskedColumn(drawcolumndata_t* dc, column_t *column, column_t
if (dc->yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop
dc->yh = vid.height - 1;
if (dc->yl <= dc->yh && dc->yh > 0)
if (dc->yl <= dc->yh && dc->yh > 0 && column->length != 0)
{
dc->source = static_cast<UINT8*>(ZZ_Alloc(column->length));
dc->sourcelength = column->length;
dc->texheight = column->length;
for (s = (UINT8 *)column+2+column->length, d = dc->source; d < dc->source+column->length; --s)
*d++ = *s;
@ -2841,7 +2843,7 @@ void R_AddPrecipitationSprites(void)
const fixed_t drawdist = cv_drawdist_precip.value * mapobjectscale;
INT32 xl, xh, yl, yh, bx, by;
precipmobj_t *th;
precipmobj_t *th, *next;
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
if (drawdist == 0)
@ -2861,8 +2863,11 @@ void R_AddPrecipitationSprites(void)
{
for (by = yl; by <= yh; by++)
{
for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext)
for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = next)
{
// Store this beforehand because R_ProjectPrecipitionSprite may free th (see P_PrecipThinker)
next = th->bnext;
if (R_PrecipThingVisible(th))
{
R_ProjectPrecipitationSprite(th);

View file

@ -986,7 +986,8 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32
if (sfxinfo->pitch & SF_OUTSIDESOUND) // Rain special case
{
fixed_t x, y, yl, yh, xl, xh, newdist;
INT64 x, y, yl, yh, xl, xh;
fixed_t newdist;
if (R_PointInSubsector(listensource.x, listensource.y)->sector->ceilingpic == skyflatnum)
approx_dist = 0;