diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 727eba4a..2656d997 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2905,6 +2905,12 @@ void D_LoadBan(boolean warning) address = strtok(buffer, " /\t\r\n"); mask = strtok(NULL, " \t\r\n"); + if (!address) + { + malformed = true; + continue; + } + if (i == 0 && !strncmp(address, "BANFORMAT", 9)) { if (mask) diff --git a/src/d_main.c b/src/d_main.c index b2591b94..0d36fc8e 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1311,7 +1311,7 @@ void D_SRB2Main(void) // // search for maps // - for (wadnum = 4; wadnum < 6; wadnum++) // fucking arbitrary numbers + for (wadnum = 0; wadnum < mainwads; wadnum++) { lumpinfo = wadfiles[wadnum]->lumpinfo; for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++) diff --git a/src/d_net.c b/src/d_net.c index 8fa218cd..1dcbb379 100644 --- a/src/d_net.c +++ b/src/d_net.c @@ -1464,7 +1464,7 @@ void Command_Ping_f(void) if (!server && playeringame[consoleplayer]) { - CONS_Printf("\nYour ping is %d frames (%d ms)\n", playerpingtable[consoleplayer], (INT32)(playerpingtable[i] * (1000.00f / TICRATE))); + CONS_Printf("\nYour ping is %d frames (%d ms)\n", playerpingtable[consoleplayer], (INT32)(playerpingtable[consoleplayer] * (1000.00f / TICRATE))); } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index b36ab33a..002eb844 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -251,7 +251,7 @@ consvar_t cv_ingamecap = {"ingamecap", "0", CV_NETVAR, ingamecap_cons_t, NULL, 0 static CV_PossibleValue_t spectatorreentry_cons_t[] = {{0, "MIN"}, {10*60, "MAX"}, {0, NULL}}; consvar_t cv_spectatorreentry = {"spectatorreentry", "30", CV_NETVAR, spectatorreentry_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t antigrief_cons_t[] = {{20, "MIN"}, {60, "MAX"}, {0, "Off"}, {0, NULL}}; +static CV_PossibleValue_t antigrief_cons_t[] = {{20, "MIN"}, {180, "MAX"}, {0, "Off"}, {0, NULL}}; consvar_t cv_antigrief = {"antigrief", "30", CV_NETVAR, antigrief_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_startinglives = {"startinglives", "3", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, startingliveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/d_netfil.c b/src/d_netfil.c index 663bcc86..881b7b5b 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -94,10 +94,20 @@ typedef struct filetran_s { filetx_t *txlist; // Linked list of all files for the node UINT32 position; // The current position in the file - FILE *currentfile; // The file currently being sent/received + boolean init; // false if we want to reset position / open a new file } filetran_t; static filetran_t transfer[MAXNETNODES]; +// The files currently being sent/received +typedef struct fileused_s +{ + FILE *file; + UINT8 count; + UINT32 position; +} fileused_t; + +static fileused_t transferFiles[UINT8_MAX + 1]; + // Read time of file: stat _stmtime // Write time of file: utime @@ -760,8 +770,19 @@ static void SV_EndFileSend(INT32 node) case SF_FILE: // It's a file, close it and free its filename if (cv_noticedownload.value) CONS_Printf("Ending file transfer (id %d) for node %d\n", p->fileid, node); - if (transfer[node].currentfile) - fclose(transfer[node].currentfile); + if (transferFiles[p->fileid].file) + { + if (transferFiles[p->fileid].count > 0) + { + transferFiles[p->fileid].count--; + } + + if (transferFiles[p->fileid].count == 0) + { + fclose(transferFiles[p->fileid].file); + transferFiles[p->fileid].file = NULL; + } + } free(p->id.filename); break; case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free @@ -778,7 +799,7 @@ static void SV_EndFileSend(INT32 node) free(p); // Indicate that the transmission is over - transfer[node].currentfile = NULL; + transfer[node].init = false; filestosend--; } @@ -842,21 +863,31 @@ void SV_FileSendTicker(void) ram = f->ram; // Open the file if it isn't open yet, or - if (!transfer[i].currentfile) + if (transfer[i].init == false) { if (!ram) // Sending a file { long filesize; - transfer[i].currentfile = - fopen(f->id.filename, "rb"); + if (transferFiles[f->fileid].count == 0) + { + // It needs opened. + transferFiles[f->fileid].file = + fopen(f->id.filename, "rb"); - if (!transfer[i].currentfile) - I_Error("File %s does not exist", - f->id.filename); + if (!transferFiles[f->fileid].file) + { + I_Error("Can't open file %s: %s", + f->id.filename, strerror(errno)); + } + } - fseek(transfer[i].currentfile, 0, SEEK_END); - filesize = ftell(transfer[i].currentfile); + // Increment number of nodes using this file. + I_Assert(transferFiles[f->fileid].count < UINT8_MAX); + transferFiles[f->fileid].count++; + + fseek(transferFiles[f->fileid].file, 0, SEEK_END); + filesize = ftell(transferFiles[f->fileid].file); // Nobody wants to transfer a file bigger // than 4GB! @@ -865,23 +896,43 @@ void SV_FileSendTicker(void) if (filesize == -1) I_Error("Error getting filesize of %s", f->id.filename); - f->size = (UINT32)filesize; - fseek(transfer[i].currentfile, 0, SEEK_SET); + f->size = transferFiles[f->fileid].position = (UINT32)filesize; } - else // Sending RAM - transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open + transfer[i].position = 0; + transfer[i].init = true; // Indicate that it is open + } + + if (!ram) + { + // Seek to the right position if we aren't already there. + if (transferFiles[f->fileid].position != transfer[i].position) + { + fseek(transferFiles[f->fileid].file, transfer[i].position, SEEK_SET); + } } // Build a packet containing a file fragment p = &netbuffer->u.filetxpak; size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE); - if (f->size-transfer[i].position < size) - size = f->size-transfer[i].position; + + if (f->size - transfer[i].position < size) + { + size = f->size - transfer[i].position; + } + if (ram) + { M_Memcpy(p->data, &f->id.ram[transfer[i].position], size); - else if (fread(p->data, 1, size, transfer[i].currentfile) != size) - I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile)); + } + else if (fread(p->data, 1, size, transferFiles[f->fileid].file) != size) + { + I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", + sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transferFiles[f->fileid].file)); + + transferFiles[f->fileid].position = (UINT32)(transferFiles[f->fileid].position + size); + } + p->position = LONG(transfer[i].position); // Put flag so receiver knows the total size if (transfer[i].position + size == f->size) @@ -891,15 +942,18 @@ void SV_FileSendTicker(void) // Send the packet if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND - { // Success + { + // Success transfer[i].position = (UINT32)(transfer[i].position + size); + if (transfer[i].position == f->size) // Finish? + { SV_EndFileSend(i); + } } else - { // Not sent for some odd reason, retry at next call - if (!ram) - fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET); + { + // Not sent for some odd reason, retry at next call // Exit the while (can't send this one so why should i send the next?) break; } diff --git a/src/discord.c b/src/discord.c index 3ca9e40b..6926b4e1 100644 --- a/src/discord.c +++ b/src/discord.c @@ -529,8 +529,10 @@ void DRPC_UpdatePresence(void) else { // Map name on tool tip - snprintf(mapname, 48, "Map: %s", G_BuildMapTitle(gamemap)); + char *title = G_BuildMapTitle(gamemap); + snprintf(mapname, 48, "Map: %s", title); discordPresence.largeImageText = mapname; + Z_Free(title); } if (gamestate == GS_LEVEL && Playing()) diff --git a/src/doomtype.h b/src/doomtype.h index 4660e876..27278f0c 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -164,6 +164,15 @@ char *strcasestr(const char *in, const char *what); #define HAVE_DOSSTR_FUNCS #endif +#if defined (__APPLE__) + #define SRB2_HAVE_STRLCPY +#elif defined (__GLIBC_PREREQ) + // glibc 2.38: added strlcpy and strlcat to _DEFAULT_SOURCE + #if __GLIBC_PREREQ(2, 38) + #define SRB2_HAVE_STRLCPY + #endif +#endif + #ifndef HAVE_DOSSTR_FUNCS int strupr(char *n); // from dosstr.c int strlwr(char *n); // from dosstr.c @@ -171,7 +180,7 @@ int strlwr(char *n); // from dosstr.c #include // for size_t -#ifndef __APPLE__ +#ifndef SRB2_HAVE_STRLCPY size_t strlcat(char *dst, const char *src, size_t siz); size_t strlcpy(char *dst, const char *src, size_t siz); #endif diff --git a/src/g_game.c b/src/g_game.c index c6b633ce..9e5fabd4 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1503,22 +1503,20 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { cmd->buttons |= BT_ACCELERATE; // JOYAXISRANGE is supposed to be 1023 (divide by 1024) - forward += ((axis * forwardmove[1]) >> 10)*2; + forward += ((axis * forwardmove[1]) / (JOYAXISRANGE-1)); } axis = JoyAxis(AXISBRAKE, ssplayer); if (InputDown(gc_brake, ssplayer) || (gamepadjoystickmove && axis > 0)) { cmd->buttons |= BT_BRAKE; - if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0) - forward -= forwardmove[0]; // 25 - Halved value so clutching is possible + forward -= forwardmove[0]; // 25 - Halved value so clutching is possible } else if (analogjoystickmove && axis > 0) { cmd->buttons |= BT_BRAKE; // JOYAXISRANGE is supposed to be 1023 (divide by 1024) - if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0) - forward -= ((axis * forwardmove[0]) >> 10); + forward -= ((axis * forwardmove[0]) / (JOYAXISRANGE-1)); } // But forward/backward IS used for aiming. @@ -6747,7 +6745,11 @@ void G_BeginRecording(void) // Full replay title demo_p += 64; - snprintf(demo.titlename, 64, "%s - %s", G_BuildMapTitle(gamemap), modeattacking ? "Time Attack" : connectedservername); + { + char *title = G_BuildMapTitle(gamemap); + snprintf(demo.titlename, 64, "%s - %s", title, modeattacking ? "Time Attack" : connectedservername); + Z_Free(title); + } // demo checksum demo_p += 16; diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index eed592af..5d03c416 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -479,14 +479,43 @@ void HWR_InitTextureCache(void) // Callback function for HWR_FreeTextureCache. static void FreeMipmapColormap(INT32 patchnum, void *patch) { - GLPatch_t* const grpatch = patch; + GLPatch_t* const pat = patch; (void)patchnum; //unused - while (grpatch->mipmap->nextcolormap) + + // The patch must be valid, obviously + if (!pat) + return; + + // The mipmap must be valid, obviously + while (pat->mipmap) { - GLMipmap_t *grmip = grpatch->mipmap->nextcolormap; - grpatch->mipmap->nextcolormap = grmip->nextcolormap; - if (grmip->grInfo.data) Z_Free(grmip->grInfo.data); - free(grmip); + // Confusing at first, but pat->mipmap->nextcolormap + // at the beginning of the loop is the first colormap + // from the linked list of colormaps. + GLMipmap_t *next = NULL; + + // No mipmap in this patch, break out of the loop. + if (!pat->mipmap) + break; + + // No colormap mipmaps either. + if (!pat->mipmap->nextcolormap) + break; + + // Set the first colormap to the one that comes after it. + next = pat->mipmap->nextcolormap; + if (!next) + break; + + pat->mipmap->nextcolormap = next->nextcolormap; + + // Free image data from memory. + if (next->grInfo.data) + Z_Free(next->grInfo.data); + next->grInfo.data = NULL; + + // Free the old colormap mipmap from memory. + free(next); } } @@ -503,7 +532,7 @@ void HWR_FreeTextureCache(void) // Alam: free the Z_Blocks before freeing it's users - // free all skin after each level: must be done after pfnClearMipMapCache! + // free all patch colormaps after each level: must be done after ClearMipMapCache! for (i = 0; i < numwadfiles; i++) M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 86dd7c34..ba221646 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1639,7 +1639,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; + size_t linenum = min((size_t)(gr_curline->linedef-gr_backsector->lines[0]), rover->master->frontsector->linecount); newline = rover->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } @@ -1798,10 +1798,11 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; + size_t linenum = min((size_t)(gr_curline->linedef-gr_backsector->lines[0]), rover->master->frontsector->linecount); newline = rover->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } + #ifdef ESLOPE //backsides h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight; @@ -4538,7 +4539,7 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) #endif // set top/bottom coords - vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); + vis->ty = FIXED_TO_FLOAT(interp.z + spritecachedinfo[lumpoff].topoffset); vis->precip = true; } diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 60b1d14d..a639b5a8 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1116,6 +1116,10 @@ void HU_Ticker(void) } if (cechotimer > 0) --cechotimer; + + // Animate the desynch dots + if (hu_resynching) + resynch_ticker++; //tic tic tic tic tic HU_TickSongCredits(); } diff --git a/src/k_kart.c b/src/k_kart.c index 7cafa491..146120f7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4021,6 +4021,7 @@ void K_RepairOrbitChain(mobj_t *orbit) // Then recount to make sure item amount is correct if (orbit->target && orbit->target->player) { + player_t *player = orbit->target->player; INT32 num = 0; mobj_t *cur = orbit->target->hnext; @@ -4030,14 +4031,14 @@ void K_RepairOrbitChain(mobj_t *orbit) { prev = cur; cur = cur->hnext; - if (++num > orbit->target->player->kartstuff[k_itemamount]) + if (++num > player->kartstuff[k_itemamount]) P_RemoveMobj(prev); else prev->movedir = num; } - if (orbit->target->player->kartstuff[k_itemamount] != num) - orbit->target->player->kartstuff[k_itemamount] = num; + if (player->kartstuff[k_itemamount] != num) + player->kartstuff[k_itemamount] = num; } } diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 3869fdc7..52154693 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -382,7 +382,7 @@ static int lib_cvRegisterVar(lua_State *L) cvar->PossibleValue = cvpv; } else FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) - } else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) { + } else if ((i == 5 || (k && fasticmp(k, "func")))) { if (!lua_isfunction(L, 4)) TYPEERROR("func", LUA_TFUNCTION) lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 41875ea9..ae9dd4e9 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -258,6 +258,8 @@ static int lib_iterateSectorThinglist(lua_State *L) if (!lua_isnil(L, 1)) { thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + if (P_MobjWasRemoved(thing)) + return luaL_error(L, "current entry in thinglist was removed; avoid calling P_RemoveMobj on entries!"); thing = thing->snext; } else diff --git a/src/m_menu.c b/src/m_menu.c index 4bdc6ee0..7a6bebf9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -5577,7 +5577,11 @@ static void DrawReplayHutReplayInfo(void) x += 85; if (mapheaderinfo[demolist[dir_on[menudepthleft]].map-1]) - V_DrawString(x, y, V_SNAPTOTOP, G_BuildMapTitle(demolist[dir_on[menudepthleft]].map)); + { + char *title = G_BuildMapTitle(demolist[dir_on[menudepthleft]].map); + V_DrawString(x, y, V_SNAPTOTOP, title); + Z_Free(title); + } else V_DrawString(x, y, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT, "Level is not loaded."); @@ -6513,16 +6517,36 @@ static char *M_GetConditionString(condition_t cond) G_TicsToMinutes(cond.requirement, false), G_TicsToSeconds(cond.requirement)); case UC_MAPVISITED: - return va("Visit %s", G_BuildMapTitle(cond.requirement-1)); + { + char *title = G_BuildMapTitle(cond.requirement-1); + char *response = va("Visit %s", title); + Z_Free(title); + return response; + } case UC_MAPBEATEN: - return va("Beat %s", G_BuildMapTitle(cond.requirement-1)); + { + char *title = G_BuildMapTitle(cond.requirement-1); + char *response = va("Beat %s", title); + Z_Free(title); + return response; + } case UC_MAPALLEMERALDS: - return va("Beat %s w/ all emeralds", G_BuildMapTitle(cond.requirement-1)); + { + char *title = G_BuildMapTitle(cond.requirement-1); + char *response = va("Beat %s w/ all emeralds", title); + Z_Free(title); + return response; + } case UC_MAPTIME: - return va("Beat %s in %i:%02i.%02i", G_BuildMapTitle(cond.extrainfo1-1), + { + char *title = G_BuildMapTitle(cond.extrainfo1-1); + char *response = va("Beat %s in %i:%02i.%02i", title, G_TicsToMinutes(cond.requirement, true), G_TicsToSeconds(cond.requirement), G_TicsToCentiseconds(cond.requirement)); + Z_Free(title); + return response; + } case UC_TOTALEMBLEMS: return va("Get %d medals", cond.requirement); case UC_EXTRAEMBLEM: @@ -10154,7 +10178,7 @@ static void M_DrawJoystick(void) compareval4 = cv_usejoystick4.value; compareval3 = cv_usejoystick3.value; compareval2 = cv_usejoystick2.value; - compareval = cv_usejoystick.value + compareval = cv_usejoystick.value; #endif if ((setupcontrolplayer == 4 && (i == compareval4)) diff --git a/src/p_inter.c b/src/p_inter.c index db321541..d4dca95f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3142,6 +3142,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed + if (P_MobjWasRemoved(source)) + source = NULL; if (shouldForce == 1) force = true; else if (shouldForce == 2) @@ -3468,6 +3470,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da break; } + if (P_MobjWasRemoved(target)) + return false; + if (!P_MobjWasRemoved(target)) { target->reactiontime = 0; // we're awake now... diff --git a/src/p_local.h b/src/p_local.h index cef7e736..642a1a64 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -150,6 +150,7 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); void P_DemoCameraMovement(camera_t *cam); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); +void P_ResetLocalCamAiming(player_t *player); void P_InitCameraCmd(void); boolean P_PlayerInPain(player_t *player); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); diff --git a/src/p_mobj.c b/src/p_mobj.c index 7978d0f3..f0ca3ed6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -263,6 +263,9 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) I_Error("P_SetMobjState used for player mobj. Use P_SetPlayerMobjState instead!\n(State called: %d)", state); #endif + if (mobj->player != NULL) + return P_SetPlayerMobjState(mobj, state); + if (recursion++) // if recursion detected, memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table @@ -590,29 +593,41 @@ void P_ExplodeMissile(mobj_t *mo) P_RadiusAttack(mo, mo, 96*FRACUNIT); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_pop); + if (!P_MobjWasRemoved(explodemo)) + { + P_SetScale(explodemo, mo->scale); + explodemo->destscale = mo->destscale; + explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); + explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); + S_StartSound(explodemo, sfx_pop); + } explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_dmpain); + if (!P_MobjWasRemoved(explodemo)) + { + P_SetScale(explodemo, mo->scale); + explodemo->destscale = mo->destscale; + explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); + explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); + S_StartSound(explodemo, sfx_dmpain); + } explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_pop); + if (!P_MobjWasRemoved(explodemo)) + { + P_SetScale(explodemo, mo->scale); + explodemo->destscale = mo->destscale; + explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); + explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); + S_StartSound(explodemo, sfx_pop); + } explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_cybdth); + if (!P_MobjWasRemoved(explodemo)) + { + P_SetScale(explodemo, mo->scale); + explodemo->destscale = mo->destscale; + explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); + explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); + S_StartSound(explodemo, sfx_cybdth); + } // Hack: Release an animal. P_DamageMobj(mo, NULL, NULL, 10000); @@ -3584,6 +3599,9 @@ static void P_PlayerMobjThinker(mobj_t *mobj) I_Assert(mobj->player != NULL); I_Assert(!P_MobjWasRemoved(mobj)); + if (P_MobjWasRemoved(mobj)) + return; + P_MobjCheckWater(mobj); P_ButteredSlope(mobj); @@ -7051,6 +7069,9 @@ void P_MobjThinker(mobj_t *mobj) // separate thinker if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) { + if (P_MobjWasRemoved(mobj)) + return; + P_MobjCheckWater(mobj); P_PushableThinker(mobj); @@ -10235,6 +10256,10 @@ void P_RemoveMobj(mobj_t *mobj) } } + // clear the reference from the mapthing + if (mobj->spawnpoint) + mobj->spawnpoint->mobj = NULL; + // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) @@ -10751,6 +10776,7 @@ void P_SpawnPlayer(INT32 playernum) } mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); + I_Assert(mobj != NULL); (mobj->player = p)->mo = mobj; mobj->angle = 0; @@ -11363,6 +11389,13 @@ void P_SpawnMapThing(mapthing_t *mthing) } mobj = P_SpawnMobj(x, y, z, i); + + if (!mobj || P_MobjWasRemoved(mobj)) + { + CONS_Alert(CONS_WARNING, "Failed to spawn map thing #%d at %d, %d\n", mthing->type, x>>FRACBITS, y>>FRACBITS); + return; + } + mobj->spawnpoint = mthing; switch(mobj->type) diff --git a/src/p_tick.c b/src/p_tick.c index 45fefa81..90ae479d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -895,6 +895,8 @@ void P_PreTicker(INT32 frames) // Run shield positioning //P_RunShields(); P_RunOverlays(); + + P_RunShadows(); P_UpdateSpecials(); P_RespawnSpecials(); diff --git a/src/p_user.c b/src/p_user.c index 94169754..45a65668 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -829,6 +829,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) // boolean P_PlayerInPain(player_t *player) { + // If the player doesn't have a mobj, it can't be in pain. + if (!player->mo) + return false; + // no silly, sliding isn't pain if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) return true; @@ -8005,6 +8009,18 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); } +void P_ResetLocalCamAiming(player_t *player) +{ + for (int i = 0; i <= splitscreen; i++) + { + UINT8 id = (i == 0) ? consoleplayer : displayplayers[i]; + if (player - players == id) + { + localaiming[i] = 0; + } + } +} + boolean P_SpectatorJoinGame(player_t *player) { // Team changing isn't allowed. @@ -8055,6 +8071,9 @@ boolean P_SpectatorJoinGame(player_t *player) player->ctfteam = changeto; player->playerstate = PST_REBORN; + //center camera + P_ResetLocalCamAiming(player); + //Reset away view if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer) displayplayers[0] = consoleplayer; @@ -8079,6 +8098,9 @@ boolean P_SpectatorJoinGame(player_t *player) player->kartstuff[k_spectatewait] = 0; player->playerstate = PST_REBORN; + //center camera + P_ResetLocalCamAiming(player); + //Reset away view if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer) displayplayers[0] = consoleplayer; diff --git a/src/r_fps.c b/src/r_fps.c index 9cbee9c0..7b23ce6d 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -23,6 +23,10 @@ #include "z_zone.h" #include "console.h" // con_startup_loadprogress +#ifdef HWRENDER +#include "hardware/hw_main.h" // for cv_grshearing +#endif + static CV_PossibleValue_t fpscap_cons_t[] = { #ifdef DEVELOP // Lower values are actually pretty useful for debugging interp problems! @@ -119,7 +123,11 @@ static void R_SetupFreelook(player_t *player, boolean skybox) // clip it in the case we are looking a hardware 90 degrees full aiming // (lmps, network and use F12...) - if (rendermode == render_soft) + if (rendermode == render_soft +#ifdef HWRENDER + || (rendermode == render_opengl && cv_grshearing.value) +#endif + ) { G_SoftwareClipAimingPitch((INT32 *)&aimingangle); } diff --git a/src/r_segs.c b/src/r_segs.c index c531be52..d3ed70c9 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -681,7 +681,7 @@ static void R_DrawRepeatMaskedColumn(column_t *col) { while (sprtopscreen < sprbotscreen) { R_DrawMaskedColumn(col); - if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow + if (sprtopscreen + (INT64)dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else sprtopscreen += dc_texheight*spryscale; @@ -733,7 +733,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = curline->linedef-backsector->lines[0]; + size_t linenum = min((size_t)(curline->linedef-backsector->lines[0]), pfloor->master->frontsector->linecount); newline = pfloor->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } diff --git a/src/s_sound.c b/src/s_sound.c index ea0a1bbe..d80fa1ca 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -46,7 +46,7 @@ extern INT32 msg_id; // 3D Sound Interface #include "hardware/hw3sound.h" #else -static INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); +static boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); #endif CV_PossibleValue_t soundvolume_cons_t[] = {{0, "MIN"}, {31, "MAX"}, {0, NULL}}; @@ -189,8 +189,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) // channel number to use INT32 cnum; - channel_t *c; - // Find an open channel for (cnum = 0; cnum < numofchannels; cnum++) { @@ -202,7 +200,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) else if (sfxinfo == channels[cnum].sfxinfo && (sfxinfo->pitch & SF_NOMULTIPLESOUND)) { return -1; - break; } else if (sfxinfo == channels[cnum].sfxinfo && sfxinfo->singularity == true) { @@ -246,12 +243,6 @@ static INT32 S_getChannel(const void *origin, sfxinfo_t *sfxinfo) } } - c = &channels[cnum]; - - // channel is decided to be cnum. - c->sfxinfo = sfxinfo; - c->origin = origin; - return cnum; } @@ -407,7 +398,6 @@ void S_StopSoundByID(void *origin, sfxenum_t sfx_id) if (channels[cnum].sfxinfo == &S_sfx[sfx_id] && channels[cnum].origin == origin) { S_StopChannel(cnum); - break; } } } @@ -428,28 +418,42 @@ void S_StopSoundByNum(sfxenum_t sfxnum) if (channels[cnum].sfxinfo == &S_sfx[sfxnum]) { S_StopChannel(cnum); - break; } } } +static INT32 S_ScaleVolumeWithSplitscreen(INT32 volume) +{ + fixed_t root = INT32_MAX; + + if (splitscreen == 0) + { + return volume; + } + + root = FixedSqrt((splitscreen + 1) * (FRACUNIT/3)); + + return FixedDiv( + volume * FRACUNIT, + root + ) / FRACUNIT; +} + + void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { - const INT32 initial_volume = volume; - INT32 sep, pitch, priority, cnum; - sfxinfo_t *sfx; - const boolean reverse = (stereoreverse.value ^ encoremode); const mobj_t *origin = (const mobj_t *)origin_p; + const boolean reverse = (stereoreverse.value ^ encoremode); + const INT32 initial_volume = (origin ? S_ScaleVolumeWithSplitscreen(volume) : volume); - listener_t listener = {0,0,0,0}; - listener_t listener2 = {0,0,0,0}; - listener_t listener3 = {0,0,0,0}; - listener_t listener4 = {0,0,0,0}; + sfxinfo_t *sfx; + INT32 sep, pitch, priority, cnum; + boolean anyListeners = false; + boolean itsUs = false; + INT32 i; - mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; - mobj_t *listenmobj2 = NULL; - mobj_t *listenmobj3 = NULL; - mobj_t *listenmobj4 = NULL; + listener_t listener[MAXSPLITSCREENPLAYERS]; + mobj_t *listenmobj[MAXSPLITSCREENPLAYERS]; if (sound_disabled || !sound_started) return; @@ -458,27 +462,29 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) if (sfx_id == sfx_None) return; - if (players[displayplayers[0]].awayviewtics) - listenmobj = players[displayplayers[0]].awayviewmobj; - - if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - listenmobj2 = players[displayplayers[1]].mo; - if (players[displayplayers[1]].awayviewtics) - listenmobj2 = players[displayplayers[1]].awayviewmobj; + player_t *player = &players[displayplayers[i]]; - if (splitscreen > 1) + memset(&listener[i], 0, sizeof (listener[i])); + listenmobj[i] = NULL; + + if (i == 0 && democam.soundmobj) { - listenmobj3 = players[displayplayers[2]].mo; - if (players[displayplayers[2]].awayviewtics) - listenmobj3 = players[displayplayers[2]].awayviewmobj; + listenmobj[i] = democam.soundmobj; + } + else if (player->awayviewtics) + { + listenmobj[i] = player->awayviewmobj; + } + else + { + listenmobj[i] = player->mo; + } - if (splitscreen > 2) - { - listenmobj4 = players[displayplayers[3]].mo; - if (players[displayplayers[3]].awayviewtics) - listenmobj4 = players[displayplayers[3]].awayviewmobj; - } + if (origin && origin == listenmobj[i]) + { + itsUs = true; } } @@ -490,75 +496,32 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) }; #endif - if (camera[0].chase && !players[displayplayers[0]].awayviewtics) + for (i = 0; i <= splitscreen; i++) { - listener.x = camera[0].x; - listener.y = camera[0].y; - listener.z = camera[0].z; - listener.angle = camera[0].angle; + player_t *player = &players[displayplayers[i]]; + + if (camera[i].chase && !player->awayviewtics) + { + listener[i].x = camera[i].x; + listener[i].y = camera[i].y; + listener[i].z = camera[i].z; + listener[i].angle = camera[i].angle; + anyListeners = true; + } + else if (listenmobj[i]) + { + listener[i].x = listenmobj[i]->x; + listener[i].y = listenmobj[i]->y; + listener[i].z = listenmobj[i]->z; + listener[i].angle = listenmobj[i]->angle; + anyListeners = true; + } } - else if (listenmobj) + + if (origin && anyListeners == false) { - listener.x = listenmobj->x; - listener.y = listenmobj->y; - listener.z = listenmobj->z; - listener.angle = listenmobj->angle; - } - else if (origin) + // If a mobj is trying to make a noise, and no one is around to hear it, does it make a sound? return; - - if (listenmobj2) - { - if (camera[1].chase && !players[displayplayers[1]].awayviewtics) - { - listener2.x = camera[1].x; - listener2.y = camera[1].y; - listener2.z = camera[1].z; - listener2.angle = camera[1].angle; - } - else - { - listener2.x = listenmobj2->x; - listener2.y = listenmobj2->y; - listener2.z = listenmobj2->z; - listener2.angle = listenmobj2->angle; - } - } - - if (listenmobj3) - { - if (camera[2].chase && !players[displayplayers[2]].awayviewtics) - { - listener3.x = camera[2].x; - listener3.y = camera[2].y; - listener3.z = camera[2].z; - listener3.angle = camera[2].angle; - } - else - { - listener3.x = listenmobj3->x; - listener3.y = listenmobj3->y; - listener3.z = listenmobj3->z; - listener3.angle = listenmobj3->angle; - } - } - - if (listenmobj4) - { - if (camera[3].chase && !players[displayplayers[3]].awayviewtics) - { - listener4.x = camera[3].x; - listener4.y = camera[3].y; - listener4.z = camera[3].z; - listener4.angle = camera[3].angle; - } - else - { - listener4.x = listenmobj4->x; - listener4.y = listenmobj4->y; - listener4.z = listenmobj4->z; - listener4.angle = listenmobj4->angle; - } } // check for bogus sound # @@ -577,37 +540,51 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) // Initialize sound parameters pitch = NORM_PITCH; priority = NORM_PRIORITY; + sep = NORM_SEP; - if (splitscreen && origin) - volume = FixedDiv(volume<>FRACBITS; + i = 0; // sensible default - if (splitscreen && listenmobj2) // Copy the sound for the split player { // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj2) + if (origin && !itsUs) { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj2, origin, &volume, &sep, &pitch, sfx); + boolean audible = false; + if (splitscreen > 0) + { + fixed_t recdist = INT32_MAX; + UINT8 j = 0; - if (!rc) - goto dontplay; // Maybe the other player can hear it... + for (; j <= splitscreen; j++) + { + fixed_t thisdist = INT32_MAX; - if (origin->x == listener2.x && origin->y == listener2.y) - sep = NORM_SEP; + if (!listenmobj[j]) + { + continue; + } + + thisdist = P_AproxDistance(listener[j].x - origin->x, listener[j].y - origin->y); + + if (thisdist >= recdist) + { + continue; + } + + recdist = thisdist; + i = j; + } + } + + if (listenmobj[i]) + { + audible = S_AdjustSoundParams(listenmobj[i], origin, &volume, &sep, &pitch, sfx); + } + + if (!audible) + { + return; + } } - else if (!origin) - // Do not play origin-less sounds for the second player. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - goto dontplay; - else - sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. // This is supposed to handle the loading/caching. // For some odd reason, the caching is done nearly @@ -616,185 +593,40 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) // cache data if necessary // NOTE: set sfx->data NULL sfx->lump -1 to force a reload if (!sfx->data) + { sfx->data = I_GetSfx(sfx); + } // increase the usefulness if (sfx->usefulness++ < 0) + { sfx->usefulness = -1; + } // Avoid channel reverse if surround if (reverse #ifdef SURROUND && sep != SURROUND_SEP #endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); - } - -dontplay: - - if (splitscreen > 1 && listenmobj3) // Copy the sound for the third player - { - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj3) + ) { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj3, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - goto dontplay3; // Maybe the other player can hear it... - - if (origin->x == listener3.x && origin->y == listener3.y) - sep = NORM_SEP; + sep = (~sep) & 255; } - else if (!origin) - // Do not play origin-less sounds for the second player. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - goto dontplay3; - else - sep = NORM_SEP; - // try to find a channel + // At this point it is determined that a sound can and should be played, so find a free channel to play it on cnum = S_getChannel(origin, sfx); if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); - } - -dontplay3: - - if (splitscreen > 2 && listenmobj4) // Copy the sound for the split player - { - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj4) { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj4, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - goto dontplay4; // Maybe the other player can hear it... - - if (origin->x == listener4.x && origin->y == listener4.y) - sep = NORM_SEP; + return; // If there's no free channels, there won't be any for anymore players either } - else if (!origin) - // Do not play origin-less sounds for the second player. - // The first player will be able to hear it just fine, - // we really don't want it playing twice. - goto dontplay4; - else - sep = NORM_SEP; - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; // If there's no free channels, it's not gonna be free for player 1, either. - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. + // Now that we know we are going to play a sound, fill out this info + channels[cnum].sfxinfo = sfx; + channels[cnum].origin = origin; + channels[cnum].volume = initial_volume; channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } - -dontplay4: - - // Check to see if it is audible, and if not, modify the params - if (origin && origin != listenmobj) - { - INT32 rc; - rc = S_AdjustSoundParams(listenmobj, origin, &volume, &sep, &pitch, sfx); - - if (!rc) - return; - - if (origin->x == listener.x && origin->y == listener.y) - sep = NORM_SEP; - } - else - sep = NORM_SEP; - - // try to find a channel - cnum = S_getChannel(origin, sfx); - - if (cnum < 0) - return; - - // This is supposed to handle the loading/caching. - // For some odd reason, the caching is done nearly - // each time the sound is needed? - - // cache data if necessary - // NOTE: set sfx->data NULL sfx->lump -1 to force a reload - if (!sfx->data) - sfx->data = I_GetSfx(sfx); - - // increase the usefulness - if (sfx->usefulness++ < 0) - sfx->usefulness = -1; - - // Avoid channel reverse if surround - if (reverse -#ifdef SURROUND - && sep != SURROUND_SEP -#endif - ) - sep = (~sep) & 255; - - // Assigns the handle to one of the channels in the - // mix/output buffer. - channels[cnum].volume = initial_volume; - channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } void S_StartSound(const void *origin, sfxenum_t sfx_id) @@ -884,7 +716,6 @@ void S_StopSound(void *origin) if (channels[cnum].sfxinfo && channels[cnum].origin == origin) { S_StopChannel(cnum); - break; } } } @@ -900,23 +731,13 @@ static INT32 actualmidimusicvolume; void S_UpdateSounds(void) { - INT32 audible, cnum, volume, sep, pitch; + INT32 cnum, volume, sep, pitch; + boolean audible = false; channel_t *c; + INT32 i; - listener_t listener; - listener_t listener2; - listener_t listener3; - listener_t listener4; - - mobj_t *listenmobj = democam.soundmobj ? : players[displayplayers[0]].mo; - mobj_t *listenmobj2 = NULL; - mobj_t *listenmobj3 = NULL; - mobj_t *listenmobj4 = NULL; - - memset(&listener, 0, sizeof(listener_t)); - memset(&listener2, 0, sizeof(listener_t)); - memset(&listener3, 0, sizeof(listener_t)); - memset(&listener4, 0, sizeof(listener_t)); + listener_t listener[MAXSPLITSCREENPLAYERS]; + mobj_t *listenmobj[MAXSPLITSCREENPLAYERS]; // Update sound/music volumes, if changed manually at console if (actualsfxvolume != cv_soundvolume.value) @@ -933,7 +754,7 @@ void S_UpdateSounds(void) { #ifndef NOMUMBLE // Stop Mumble cutting out. I'm sick of it. - I_UpdateMumble(NULL, listener); + I_UpdateMumble(NULL, listener[0]); #endif // Stop cutting FMOD out. WE'RE sick of it. @@ -944,47 +765,31 @@ void S_UpdateSounds(void) if (dedicated || sound_disabled) return; - if (players[displayplayers[0]].awayviewtics) - listenmobj = players[displayplayers[0]].awayviewmobj; - - if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - listenmobj2 = players[displayplayers[1]].mo; - if (players[displayplayers[1]].awayviewtics) - listenmobj2 = players[displayplayers[1]].awayviewmobj; + player_t *player = &players[displayplayers[i]]; - if (splitscreen > 1) + memset(&listener[i], 0, sizeof (listener[i])); + listenmobj[i] = NULL; + + if (i == 0 && democam.soundmobj) { - listenmobj3 = players[displayplayers[2]].mo; - if (players[displayplayers[2]].awayviewtics) - listenmobj3 = players[displayplayers[2]].awayviewmobj; + listenmobj[i] = democam.soundmobj; + continue; + } - if (splitscreen > 2) - { - listenmobj4 = players[displayplayers[3]].mo; - if (players[displayplayers[3]].awayviewtics) - listenmobj4 = players[displayplayers[3]].awayviewmobj; - } + if (player->awayviewtics) + { + listenmobj[i] = player->awayviewmobj; + } + else + { + listenmobj[i] = player->mo; } } - if (camera[0].chase && !players[displayplayers[0]].awayviewtics) - { - listener.x = camera[0].x; - listener.y = camera[0].y; - listener.z = camera[0].z; - listener.angle = camera[0].angle; - } - else if (listenmobj) - { - listener.x = listenmobj->x; - listener.y = listenmobj->y; - listener.z = listenmobj->z; - listener.angle = listenmobj->angle; - } - #ifndef NOMUMBLE - I_UpdateMumble(players[consoleplayer].mo, listener); + I_UpdateMumble(players[consoleplayer].mo, listener[0]); #endif #ifdef HW3SOUND @@ -996,57 +801,23 @@ void S_UpdateSounds(void) } #endif - if (listenmobj2) + for (i = 0; i <= splitscreen; i++) { - if (camera[1].chase && !players[displayplayers[1]].awayviewtics) - { - listener2.x = camera[1].x; - listener2.y = camera[1].y; - listener2.z = camera[1].z; - listener2.angle = camera[1].angle; - } - else - { - listener2.x = listenmobj2->x; - listener2.y = listenmobj2->y; - listener2.z = listenmobj2->z; - listener2.angle = listenmobj2->angle; - } - } + player_t *player = &players[displayplayers[i]]; - if (listenmobj3) - { - if (camera[2].chase && !players[displayplayers[2]].awayviewtics) + if (camera[i].chase && !player->awayviewtics) { - listener3.x = camera[2].x; - listener3.y = camera[2].y; - listener3.z = camera[2].z; - listener3.angle = camera[2].angle; + listener[i].x = camera[i].x; + listener[i].y = camera[i].y; + listener[i].z = camera[i].z; + listener[i].angle = camera[i].angle; } - else + else if (listenmobj[i]) { - listener3.x = listenmobj3->x; - listener3.y = listenmobj3->y; - listener3.z = listenmobj3->z; - listener3.angle = listenmobj3->angle; - } - } - - if (listenmobj4) - { - if (camera[3].chase && !players[displayplayers[3]].awayviewtics) - { - listener4.x = camera[3].x; - listener4.y = camera[3].y; - listener4.z = camera[3].z; - listener4.angle = camera[3].angle; - } - else - { - listener4.x = listenmobj4->x; - listener4.y = listenmobj4->y; - listener4.z = listenmobj4->z; - listener4.angle = listenmobj4->angle; + listener[i].x = listenmobj[i]->x; + listener[i].y = listenmobj[i]->y; + listener[i].z = listenmobj[i]->z; + listener[i].angle = listenmobj[i]->angle; } } @@ -1063,83 +834,60 @@ void S_UpdateSounds(void) pitch = NORM_PITCH; sep = NORM_SEP; - if (splitscreen && c->origin) - volume = FixedDiv(volume<>FRACBITS; - // check non-local sounds for distance clipping // or modify their params - if (c->origin && ((c->origin != players[consoleplayer].mo) - || (splitscreen && c->origin != players[displayplayers[1]].mo) - || (splitscreen > 1 && c->origin != players[displayplayers[2]].mo) - || (splitscreen > 2 && c->origin != players[displayplayers[3]].mo))) + if (c->origin) { - // Whomever is closer gets the sound, but only in splitscreen. - if (splitscreen) + boolean itsUs = false; + + for (i = splitscreen; i >= 0; i--) { - const mobj_t *soundmobj = c->origin; - fixed_t recdist = -1; - INT32 i, p = -1; + if (c->origin != listenmobj[i]) + continue; - for (i = 0; i <= splitscreen; i++) - { - fixed_t thisdist = -1; - - if (i == 0 && listenmobj) - thisdist = P_AproxDistance(listener.x-soundmobj->x, listener.y-soundmobj->y); - else if (i == 1 && listenmobj2) - thisdist = P_AproxDistance(listener2.x-soundmobj->x, listener2.y-soundmobj->y); - else if (i == 2 && listenmobj3) - thisdist = P_AproxDistance(listener3.x-soundmobj->x, listener3.y-soundmobj->y); - else if (i == 3 && listenmobj4) - thisdist = P_AproxDistance(listener4.x-soundmobj->x, listener4.y-soundmobj->y); - else - continue; - - if (recdist == -1 || (thisdist != -1 && thisdist < recdist)) - { - recdist = thisdist; - p = i; - } - } - - if (p != -1) - { - if (p == 1) - { - // Player 2 gets the sound - audible = S_AdjustSoundParams(listenmobj2, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else if (p == 2) - { - // Player 3 gets the sound - audible = S_AdjustSoundParams(listenmobj3, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else if (p == 3) - { - // Player 4 gets the sound - audible = S_AdjustSoundParams(listenmobj4, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - else - { - // Player 1 gets the sound - audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch, - c->sfxinfo); - } - - if (audible) - I_UpdateSoundParams(c->handle, volume, sep, pitch); - else - S_StopChannel(cnum); - } + itsUs = true; } - else if (listenmobj && !splitscreen) + + if (itsUs == false) { - // In the case of a single player, he or she always should get updated sound. - audible = S_AdjustSoundParams(listenmobj, c->origin, &volume, &sep, &pitch, - c->sfxinfo); + const mobj_t *origin = c->origin; + + i = 0; + + if (splitscreen > 0) + { + fixed_t recdist = INT32_MAX; + UINT8 j = 0; + + for (; j <= splitscreen; j++) + { + fixed_t thisdist = INT32_MAX; + + if (!listenmobj[j]) + { + continue; + } + + thisdist = P_AproxDistance(listener[j].x - origin->x, listener[j].y - origin->y); + + if (thisdist >= recdist) + { + continue; + } + + recdist = thisdist; + i = j; + } + } + + if (listenmobj[i]) + { + audible = S_AdjustSoundParams( + listenmobj[i], c->origin, + &volume, &sep, &pitch, + c->sfxinfo + ); + } if (audible) I_UpdateSoundParams(c->handle, volume, sep, pitch); @@ -1242,54 +990,38 @@ fixed_t S_CalculateSoundDistance(fixed_t sx1, fixed_t sy1, fixed_t sz1, fixed_t // If the sound is not audible, returns a 0. // Otherwise, modifies parameters and returns 1. // -INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, +boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo) { - fixed_t approx_dist; - angle_t angle; - - listener_t listensource; - const boolean reverse = (stereoreverse.value ^ encoremode); + fixed_t approx_dist; + + listener_t listensource; + INT32 i; + (void)pitch; + if (!listener) return false; - if (listener == players[displayplayers[0]].mo && camera[0].chase) + // Init listensource with default listener + listensource.x = listener->x; + listensource.y = listener->y; + listensource.z = listener->z; + listensource.angle = listener->angle; + + for (i = 0; i <= splitscreen; i++) { - listensource.x = camera[0].x; - listensource.y = camera[0].y; - listensource.z = camera[0].z; - listensource.angle = camera[0].angle; - } - else if (splitscreen && listener == players[displayplayers[1]].mo && camera[1].chase) - { - listensource.x = camera[1].x; - listensource.y = camera[1].y; - listensource.z = camera[1].z; - listensource.angle = camera[1].angle; - } - else if (splitscreen > 1 && listener == players[displayplayers[2]].mo && camera[2].chase) - { - listensource.x = camera[2].x; - listensource.y = camera[2].y; - listensource.z = camera[2].z; - listensource.angle = camera[2].angle; - } - else if (splitscreen > 2 && listener == players[displayplayers[3]].mo && camera[3].chase) - { - listensource.x = camera[3].x; - listensource.y = camera[3].y; - listensource.z = camera[3].z; - listensource.angle = camera[3].angle; - } - else - { - listensource.x = listener->x; - listensource.y = listener->y; - listensource.z = listener->z; - listensource.angle = listener->angle; + // If listener is a chasecam player, use the camera instead + if (listener == players[displayplayers[i]].mo && camera[i].chase) + { + listensource.x = camera[i].x; + listensource.y = camera[i].y; + listensource.z = camera[i].z; + listensource.angle = camera[i].angle; + break; + } } if (sfxinfo->pitch & SF_OUTSIDESOUND) // Rain special case @@ -1339,30 +1071,37 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v approx_dist = FixedDiv(approx_dist,2*FRACUNIT); if (approx_dist > S_CLIPPING_DIST) - return 0; + return false; - // angle of source to listener - angle = R_PointToAngle2(listensource.x, listensource.y, source->x, source->y); - - if (angle > listensource.angle) - angle = angle - listensource.angle; + if (source->x == listensource.x && source->y == listensource.y) + { + *sep = NORM_SEP; + } else - angle = angle + InvAngle(listensource.angle); + { + // angle of source to listener + angle_t angle = R_PointToAngle2(listensource.x, listensource.y, source->x, source->y); - if (reverse) - angle = InvAngle(angle); + if (angle > listensource.angle) + angle = angle - listensource.angle; + else + angle = angle + InvAngle(listensource.angle); + + if (reverse) + angle = InvAngle(angle); #ifdef SURROUND - // Produce a surround sound for angle from 105 till 255 - if (surround.value == 1 && (angle > ANG105 && angle < ANG255 )) - *sep = SURROUND_SEP; - else + // Produce a surround sound for angle from 105 till 255 + if (surround.value == 1 && (angle > ANG105 && angle < ANG255 )) + *sep = SURROUND_SEP; + else #endif - { - angle >>= ANGLETOFINESHIFT; + { + angle >>= ANGLETOFINESHIFT; - // stereo separation - *sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS); + // stereo separation + *sep = 128 - (FixedMul(S_STEREO_SWING, FINESINE(angle))>>FRACBITS); + } } // volume calculation @@ -1374,9 +1113,6 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v *vol = FixedMul(*vol * FRACUNIT / 255, n) / S_ATTENUATOR; } - if (splitscreen) - *vol = FixedDiv((*vol)<>FRACBITS; - return (*vol > 0); } diff --git a/src/sdl/MakeNIX.cfg b/src/sdl/MakeNIX.cfg index 6998a03a..86c8521c 100644 --- a/src/sdl/MakeNIX.cfg +++ b/src/sdl/MakeNIX.cfg @@ -53,7 +53,7 @@ ifdef FREEBSD OPTS+=-DLINUX -DFREEBSD -I/usr/X11R6/include SDL_CONFIG?=sdl11-config LDFLAGS+=-L/usr/X11R6/lib - LIBS+=-lipx -lkvm + LIBS+=-lkvm -lexecinfo endif # diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 50204f3f..e44f21b8 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -90,7 +90,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif #include -#include +#include #endif #endif @@ -3804,40 +3804,17 @@ static long get_entry(const char* name, const char* buf) UINT32 I_GetFreeMem(UINT32 *total) { #ifdef FREEBSD - struct vmmeter sum; - kvm_t *kd; - struct nlist namelist[] = - { -#define X_SUM 0 - {"_cnt"}, - {NULL} - }; - if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "kvm_open")) == NULL) - { - if (total) - *total = 0L; - return 0; - } - if (kvm_nlist(kd, namelist) != 0) - { - kvm_close (kd); - if (total) - *total = 0L; - return 0; - } - if (kvm_read(kd, namelist[X_SUM].n_value, &sum, - sizeof (sum)) != sizeof (sum)) - { - kvm_close(kd); - if (total) - *total = 0L; - return 0; - } - kvm_close(kd); + u_int v_free_count, v_page_size, v_page_count; + size_t size = sizeof(v_free_count); + sysctlbyname("vm.stats.vm.v_free_count", &v_free_count, &size, NULL, 0); + size = sizeof(v_page_size); + sysctlbyname("vm.stats.vm.v_page_size", &v_page_size, &size, NULL, 0); + size = sizeof(v_page_count); + sysctlbyname("vm.stats.vm.v_page_count", &v_page_count, &size, NULL, 0); if (total) - *total = sum.v_page_count * sum.v_page_size; - return sum.v_free_count * sum.v_page_size; + *total = v_page_count * v_page_size; + return v_free_count * v_page_size; #elif defined (SOLARIS) /* Just guess */ if (total) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 30a88737..8cbd95cb 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -42,7 +42,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif 1 +#elif (!defined(__APPLE__)) #define LOAD_XPM //I want XPM! #include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so #define HAVE_IMAGE //I have SDL_Image, sortof diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index c5650192..b2f6ec50 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -90,6 +90,7 @@ static UINT32 fading_timer; static UINT32 fading_duration; static INT32 fading_id; static void (*fading_callback)(void); +static boolean fading_do_callback; #ifdef HAVE_LIBGME static Music_Emu *gme; @@ -106,6 +107,7 @@ static void var_cleanup(void) is_fading = false; fading_callback = NULL; + fading_do_callback = false; internal_volume = 100; } @@ -202,6 +204,13 @@ void I_ShutdownSound(void) void I_UpdateSound(void) { + if (fading_do_callback) + { + if (fading_callback) + (*fading_callback)(); + fading_callback = NULL; + fading_do_callback = false; + } } /// ------------------------ @@ -526,9 +535,8 @@ static UINT32 get_adjusted_position(UINT32 position) static void do_fading_callback(void) { - if (fading_callback) - (*fading_callback)(); - fading_callback = NULL; + // TODO: Should I use a mutex here or something? + fading_do_callback = true; } /// ------------------------ diff --git a/src/string.c b/src/string.c index c415e524..c919ec80 100644 --- a/src/string.c +++ b/src/string.c @@ -16,7 +16,7 @@ #include #include "doomdef.h" -#if !defined (__APPLE__) +#ifndef SRB2_HAVE_STRLCPY // Like the OpenBSD version, but it doesn't check for src not being a valid // C string. diff --git a/src/stun.c b/src/stun.c index dbcfe58e..1ff4dc96 100644 --- a/src/stun.c +++ b/src/stun.c @@ -11,7 +11,7 @@ /* https://tools.ietf.org/html/rfc5389 */ -#if defined (__linux__) +#if defined (__unix__) #include #elif defined (_WIN32) #define _CRT_RAND_S diff --git a/src/w_wad.c b/src/w_wad.c index 1bfee515..04023348 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -1862,7 +1862,7 @@ static int W_VerifyWAD(FILE *fp, lumpchecklist_t *checklist, boolean status) continue; for (j = 0; j < NUMSPRITES; j++) - if (sprnames[j] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites + if (!strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites continue; if (! W_VerifyName(lumpinfo.name, checklist, status)) diff --git a/src/z_zone.c b/src/z_zone.c index dae7dff0..10755608 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -242,7 +242,7 @@ void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif { - size_t extrabytes = (1< (UINT32) alignbits); // only subtract 1 if the bit shift did not cause an overflow size_t padsize = 0; memblock_t *block; void *ptr;