Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 1392-2-2-15-attempting-to-draw-a-hud-graphic-with-the-same-lump-name-as-a-lua-script-crashes-the
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
117 results
Select Git revision
Show changes
Showing with 774 additions and 426 deletions
......@@ -444,12 +444,11 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
#if defined(__linux__) || defined(__FreeBSD__)
if (dent->d_type == DT_UNKNOWN)
if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode))
if (dent->d_type == DT_UNKNOWN || dent->d_type == DT_LNK)
if (stat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode))
dent->d_type = DT_DIR;
// Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups.
// FIXME: should we also follow symlinks?
if (dent->d_type == DT_DIR && depthleft)
#else
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
......@@ -699,6 +698,15 @@ static void initdirpath(char *dirpath, size_t *dirpathindex, int depthleft)
dirpathindex[depthleft]--;
}
//sortdir by name?
static int lumpnamecompare(const void *A, const void *B)
{
const lumpinfo_t *pA = A;
const lumpinfo_t *pB = B;
return strcmp((pA->fullname), (pB->fullname));
}
lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
{
DIR **dirhandle;
......@@ -889,6 +897,9 @@ lumpinfo_t *getdirectoryfiles(const char *path, UINT16 *nlmp, UINT16 *nfolders)
free(dirpathindex);
free(dirhandle);
//sort files and directories
qsort (lumpinfo, numlumps, sizeof(lumpinfo_t), lumpnamecompare);
(*nlmp) = numlumps;
return lumpinfo;
}
......@@ -1179,7 +1190,7 @@ boolean preparefilemenu(boolean samedepth)
size_t i;
if (filenamebuf == NULL)
filenamebuf = calloc(sizeof(char) * MAX_WADPATH, numwadfiles);
filenamebuf = calloc(numwadfiles, sizeof(char) * MAX_WADPATH);
for (i = 0; i < numwadfiles; i++)
{
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -67,6 +67,8 @@ static UINT8 *metalbuffer = NULL;
static UINT8 *metal_p;
static UINT16 metalversion;
consvar_t cv_resyncdemo = CVAR_INIT("resyncdemo", "On", 0, CV_OnOff, NULL);
// extra data stuff (events registered this frame while recording)
static struct {
UINT8 flags; // EZT flags
......@@ -98,7 +100,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x0012
#define DEMOVERSION 0x0011
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!
......@@ -183,11 +185,7 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
if (ziptic & ZT_ANGLE)
oldcmd.angleturn = READINT16(demo_p);
if (ziptic & ZT_BUTTONS)
{
oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT));
if (demoversion < 0x0012 && oldcmd.buttons & BT_SPIN)
oldcmd.buttons |= BT_SHIELD; // Copy BT_SPIN to BT_SHIELD for pre-Shield-button demos
}
if (ziptic & ZT_AIMING)
oldcmd.aiming = READINT16(demo_p);
if (ziptic & ZT_LATENCY)
......@@ -549,6 +547,9 @@ void G_ConsGhostTic(void)
testmo = players[0].mo;
if (P_MobjWasRemoved(testmo))
return; // No valid mobj exists, probably because of unexpected quit
// Grab ghost data.
ziptic = READUINT8(demo_p);
if (ziptic & GZT_XYZ)
......@@ -609,7 +610,7 @@ void G_ConsGhostTic(void)
mobj = NULL;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mobj = (mobj_t *)th;
if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
......@@ -664,11 +665,14 @@ void G_ConsGhostTic(void)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
demosynced = false;
P_UnsetThingPosition(testmo);
testmo->x = oldghost.x;
testmo->y = oldghost.y;
P_SetThingPosition(testmo);
testmo->z = oldghost.z;
if (cv_resyncdemo.value)
{
P_UnsetThingPosition(testmo);
testmo->x = oldghost.x;
testmo->y = oldghost.y;
P_SetThingPosition(testmo);
testmo->z = oldghost.z;
}
}
if (*demo_p == DEMOMARKER)
......@@ -1446,6 +1450,7 @@ void G_BeginRecording(void)
char *filename;
UINT16 totalfiles;
UINT8 *m;
save_t savebuffer;
if (demo_p)
return;
......@@ -1595,7 +1600,11 @@ void G_BeginRecording(void)
}
// Save netvar data
CV_SaveDemoVars(&demo_p);
savebuffer.buf = demo_p;
savebuffer.size = demoend - demo_p;
savebuffer.pos = 0;
CV_SaveDemoVars(&savebuffer);
demo_p = &savebuffer.buf[savebuffer.pos];
memset(&oldcmd,0,sizeof(oldcmd));
memset(&oldghost,0,sizeof(oldghost));
......@@ -2228,10 +2237,24 @@ void G_DoPlayDemo(char *defdemoname)
// net var data
#ifdef OLD22DEMOCOMPAT
if (demoversion < 0x000d)
CV_LoadOldDemoVars(&demo_p);
{
save_t savebuffer;
savebuffer.buf = demo_p;
savebuffer.size = demoend - demo_p;
savebuffer.pos = 0;
CV_LoadOldDemoVars(&savebuffer);
demo_p = &savebuffer.buf[savebuffer.pos];
}
else
#endif
CV_LoadDemoVars(&demo_p);
{
save_t savebuffer;
savebuffer.buf = demo_p;
savebuffer.size = demoend - demo_p;
savebuffer.pos = 0;
CV_LoadDemoVars(&savebuffer);
demo_p = &savebuffer.buf[savebuffer.pos];
}
// Sigh ... it's an empty demo.
if (*demo_p == DEMOMARKER)
......@@ -2669,7 +2692,7 @@ void G_DoPlayMetal(void)
// find metal sonic
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo = (mobj_t *)th;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -35,6 +35,7 @@ typedef enum
} demo_file_override_e;
extern demo_file_override_e demofileoverride;
extern consvar_t cv_resyncdemo;
// Quit after playing a demo from cmdline.
extern boolean singledemo;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -256,8 +256,6 @@ boolean precache = true; // if true, load all graphics at start
INT16 prevmap, nextmap;
static UINT8 *savebuffer;
// Analog Control
static void UserAnalog_OnChange(void);
static void UserAnalog2_OnChange(void);
......@@ -403,29 +401,27 @@ consvar_t cv_cam_lockonboss[2] = {
CVAR_INIT ("cam2_lockaimassist", "Full", CV_SAVE|CV_ALLOWLUA, lockedassist_cons_t, NULL),
};
consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_shieldaxis = CVAR_INIT ("joyaxis_shield", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_shieldaxis2 = CVAR_INIT ("joyaxis2_shield", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_moveaxis = CVAR_INIT ("joyaxis_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis = CVAR_INIT ("joyaxis_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis = CVAR_INIT ("joyaxis_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_turnaxis = CVAR_INIT ("joyaxis_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis = CVAR_INIT ("joyaxis_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis = CVAR_INIT ("joyaxis_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis = CVAR_INIT ("joyaxis_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis = CVAR_INIT ("joyaxis_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone = CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone = CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_moveaxis2 = CVAR_INIT ("joyaxis2_move", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_sideaxis2 = CVAR_INIT ("joyaxis2_side", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_lookaxis2 = CVAR_INIT ("joyaxis2_look", "X-Rudder-", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_turnaxis2 = CVAR_INIT ("joyaxis2_turn", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_jumpaxis2 = CVAR_INIT ("joyaxis2_jump", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_spinaxis2 = CVAR_INIT ("joyaxis2_spin", "None", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_fireaxis2 = CVAR_INIT ("joyaxis2_fire", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_firenaxis2 = CVAR_INIT ("joyaxis2_firenormal", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL);
consvar_t cv_deadzone2 = CVAR_INIT ("joy_deadzone2", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
consvar_t cv_digitaldeadzone2 = CVAR_INIT ("joy_digdeadzone2", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL);
player_t *seenplayer; // player we're aiming at right now
......@@ -896,9 +892,6 @@ INT32 JoyAxis(joyaxis_e axissel)
case JA_SPIN:
axisval = cv_spinaxis.value;
break;
case JA_SHIELD:
axisval = cv_shieldaxis.value;
break;
case JA_FIRE:
axisval = cv_fireaxis.value;
break;
......@@ -972,9 +965,6 @@ INT32 Joy2Axis(joyaxis_e axissel)
case JA_SPIN:
axisval = cv_spinaxis2.value;
break;
case JA_SHIELD:
axisval = cv_shieldaxis2.value;
break;
case JA_FIRE:
axisval = cv_fireaxis2.value;
break;
......@@ -1342,10 +1332,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (PLAYERINPUTDOWN(ssplayer, GC_WEAPONPREV))
cmd->buttons |= BT_WEAPONPREV; // Previous Weapon
#if NUM_WEAPONS > 7
"Add extra inputs to g_input.h/gamecontrols_e, and fix conflicts in d_ticcmd.h/ticcmd_t/buttons"
#if NUM_WEAPONS > 10
"Add extra inputs to g_input.h/gamecontrols_e"
#endif
//use the three avaliable bits to determine the weapon.
//use the four avaliable bits to determine the weapon.
cmd->buttons &= ~BT_WEAPONMASK;
for (i = 0; i < NUM_WEAPONS; ++i)
if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i))
......@@ -1363,15 +1353,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
cmd->buttons |= BT_FIRENORMAL;
// Toss flag button
if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
cmd->buttons |= BT_TOSSFLAG;
// Shield button
axis = PlayerJoyAxis(ssplayer, JA_SHIELD);
if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD) || (usejoystick && axis > 0))
cmd->buttons |= BT_SHIELD;
// Lua scriptable buttons
if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1))
......@@ -1386,6 +1370,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (PLAYERINPUTDOWN(ssplayer, GC_SPIN) || (usejoystick && axis > 0))
cmd->buttons |= BT_SPIN;
if (gamestate == GS_INTRO) // prevent crash in intro
{
cmd->angleturn = ticcmd_oldangleturn[forplayer];
cmd->aiming = G_ClipAimingPitch(myaiming);
return;
}
// Centerview can be a toggle in simple mode!
{
static boolean last_centerviewdown[2], centerviewhold[2]; // detect taps for toggle behavior
......@@ -1420,7 +1411,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
ticcmd_centerviewdown[forplayer] = true;
}
else if (ticcmd_centerviewdown[forplayer])
else if (ticcmd_centerviewdown[forplayer] || (leveltime < 5))
{
if (controlstyle == CS_SIMPLE)
{
......@@ -1435,6 +1426,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
if (
P_MobjWasRemoved(ticcmd_ztargetfocus[forplayer]) ||
(leveltime < 5) ||
(player->playerstate != PST_LIVE) ||
player->exiting ||
!ticcmd_ztargetfocus[forplayer]->health ||
(ticcmd_ztargetfocus[forplayer]->type == MT_EGGMOBILE3 && !ticcmd_ztargetfocus[forplayer]->movecount) // Sea Egg is moving around underground and shouldn't be tracked
)
......@@ -1466,7 +1460,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
P_SetTarget(&newtarget->target, ticcmd_ztargetfocus[forplayer]);
newtarget->drawonlyforplayer = player; // Hide it from the other player in splitscreen, and yourself when spectating
if (player->mo && P_AproxDistance(
if (player->mo && R_PointToDist2(0, 0,
player->mo->x - ticcmd_ztargetfocus[forplayer]->x,
player->mo->y - ticcmd_ztargetfocus[forplayer]->y
) > 50*player->mo->scale)
......@@ -1926,6 +1920,8 @@ void G_DoLoadLevel(boolean resetplayer)
//
void G_StartTitleCard(void)
{
ST_stopTitleCard();
// The title card has been disabled for this map.
// Oh well.
if (!G_IsTitleCardAvailable())
......@@ -2274,6 +2270,11 @@ boolean G_LuaResponder(event_t *ev)
cancelled = LUA_HookKey(ev, HOOK(KeyUp));
LUA_InvalidateUserdata(ev);
}
else if (ev->type == ev_text)
{
cancelled = LUA_HookText(ev, HOOK(TextInput));
LUA_InvalidateUserdata(ev);
}
return cancelled;
}
......@@ -2614,6 +2615,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
boolean spectator;
boolean outofcoop;
boolean removing;
boolean muted;
INT16 bot;
SINT8 pity;
INT16 rings;
......@@ -2631,6 +2633,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
spectator = players[player].spectator;
outofcoop = players[player].outofcoop;
removing = players[player].removing;
muted = players[player].muted;
pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
playerangleturn = players[player].angleturn;
oldrelangleturn = players[player].oldrelangleturn;
......@@ -2708,6 +2711,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->spectator = spectator;
p->outofcoop = outofcoop;
p->removing = removing;
p->muted = muted;
p->angleturn = playerangleturn;
p->oldrelangleturn = oldrelangleturn;
......@@ -2764,7 +2768,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->pflags |= PF_SPINDOWN;
p->pflags |= PF_ATTACKDOWN;
p->pflags |= PF_JUMPDOWN;
p->pflags |= PF_SHIELDDOWN;
p->playerstate = PST_LIVE;
p->panim = PA_IDLE; // standing animation
......@@ -3059,7 +3062,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
// scan all thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -3342,7 +3345,7 @@ void G_AddPlayer(INT32 playernum)
p->playerstate = PST_REBORN;
p->height = mobjinfo[MT_PLAYER].height;
p->height = skins[p->skin]->height;
if (G_GametypeUsesLives() || ((netgame || multiplayer) && (gametyperules & GTR_FRIENDLY)))
p->lives = cv_startinglives.value;
......@@ -4018,7 +4021,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
INT32 i;
INT16 newmapnum;
boolean spec = G_IsSpecialStage(gamemap);
// go to next level
// newmapnum is 0-based, unlike gamemap
if (nextmapoverride != 0)
......@@ -4122,7 +4125,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
if (spec && (!gottoken || ignoretokens) && !nextmapoverride)
newmapnum = lastmap; // Exiting from a special stage? Go back to the game. Tails 08-11-2001
if (!(gametyperules & GTR_CAMPAIGN))
{
if (cv_advancemap.value == 0) // Stay on same map.
......@@ -4130,7 +4133,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
else if (cv_advancemap.value == 2) // Go to random map.
newmapnum = RandMap(G_TOLFlag(gametype_to_use), prevmap);
}
return newmapnum;
}
......@@ -4140,7 +4143,7 @@ INT16 G_GetNextMap(boolean ignoretokens, boolean silent)
static void G_DoCompleted(void)
{
INT32 i;
tokenlist = 0; // Reset the list
if (modeattacking && pausedelay)
......@@ -4168,7 +4171,7 @@ static void G_DoCompleted(void)
//Get and set prevmap/nextmap
prevmap = (INT16)(gamemap-1);
nextmap = G_GetNextMap(false, false);
automapactive = false;
// We are committed to this map now.
......@@ -4386,7 +4389,7 @@ void G_LoadGameSettings(void)
// Loads the main data file, which stores information such as emblems found, etc.
void G_LoadGameData(gamedata_t *data)
{
size_t length;
save_t savebuffer;
INT32 i, j;
UINT32 versionID;
......@@ -4428,18 +4431,18 @@ void G_LoadGameData(gamedata_t *data)
return;
}
length = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer);
if (!length)
savebuffer.size = FIL_ReadFile(va(pandf, srb2home, gamedatafilename), &savebuffer.buf);
if (!savebuffer.size)
{
// No gamedata. We can save a new one.
data->loaded = true;
return;
}
save_p = savebuffer;
savebuffer.pos = 0;
// Version check
versionID = READUINT32(save_p);
versionID = P_ReadUINT32(&savebuffer);
if (versionID != GAMEDATA_ID
#ifdef COMPAT_GAMEDATA_ID // backwards compat behavior
&& versionID != COMPAT_GAMEDATA_ID
......@@ -4450,8 +4453,7 @@ void G_LoadGameData(gamedata_t *data)
if (strcmp(srb2home,"."))
gdfolder = srb2home;
Z_Free(savebuffer);
save_p = NULL;
Z_Free(savebuffer.buf);
I_Error("Game data is from another version of SRB2.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
}
......@@ -4463,14 +4465,14 @@ void G_LoadGameData(gamedata_t *data)
}
#endif
data->totalplaytime = READUINT32(save_p);
data->totalplaytime = P_ReadUINT32(&savebuffer);
#ifdef COMPAT_GAMEDATA_ID
if (versionID == COMPAT_GAMEDATA_ID)
{
// We'll temporarily use the old condition when loading an older file.
// The proper mod-specific hash will get saved in afterwards.
boolean modded = READUINT8(save_p);
boolean modded = P_ReadUINT8(&savebuffer);
if (modded && !savemoddata)
{
......@@ -4490,13 +4492,13 @@ void G_LoadGameData(gamedata_t *data)
strcpy(currentfilename, gamedatafilename);
STRBUFCPY(backupfilename, strcat(currentfilename, bak));
FIL_WriteFile(va(pandf, srb2home, backupfilename), savebuffer, length);
FIL_WriteFile(va(pandf, srb2home, backupfilename), &savebuffer.buf, savebuffer.size);
}
else
#endif
{
// Quick & dirty hash for what mod this save file is for.
UINT32 modID = READUINT32(save_p);
UINT32 modID = P_ReadUINT32(&savebuffer);
UINT32 expectedID = quickncasehash(timeattackfolder, sizeof timeattackfolder);
if (modID != expectedID)
......@@ -4508,50 +4510,50 @@ void G_LoadGameData(gamedata_t *data)
// TODO put another cipher on these things? meh, I don't care...
for (i = 0; i < NUMMAPS; i++)
if ((data->mapvisited[i] = READUINT8(save_p)) > MV_MAX)
if ((data->mapvisited[i] = P_ReadUINT8(&savebuffer)) > MV_MAX)
goto datacorrupt;
// To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < max_emblems;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(&savebuffer);
for (j = 0; j < 8 && j+i < max_emblems; ++j)
data->collected[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < max_extraemblems;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(&savebuffer);
for (j = 0; j < 8 && j+i < max_extraemblems; ++j)
data->extraCollected[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < max_unlockables;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(&savebuffer);
for (j = 0; j < 8 && j+i < max_unlockables; ++j)
data->unlocked[j+i] = ((rtemp >> j) & 1);
i += j;
}
for (i = 0; i < max_conditionsets;)
{
rtemp = READUINT8(save_p);
rtemp = P_ReadUINT8(&savebuffer);
for (j = 0; j < 8 && j+i < max_conditionsets; ++j)
data->achieved[j+i] = ((rtemp >> j) & 1);
i += j;
}
data->timesBeaten = READUINT32(save_p);
data->timesBeatenWithEmeralds = READUINT32(save_p);
data->timesBeatenUltimate = READUINT32(save_p);
data->timesBeaten = P_ReadUINT32(&savebuffer);
data->timesBeatenWithEmeralds = P_ReadUINT32(&savebuffer);
data->timesBeatenUltimate = P_ReadUINT32(&savebuffer);
// Main records
for (i = 0; i < NUMMAPS; ++i)
{
recscore = READUINT32(save_p);
rectime = (tic_t)READUINT32(save_p);
recrings = READUINT16(save_p);
save_p++; // compat
recscore = P_ReadUINT32(&savebuffer);
rectime = (tic_t)P_ReadUINT32(&savebuffer);
recrings = P_ReadUINT16(&savebuffer);
P_ReadUINT8(&savebuffer); // compat
if (recrings > 10000 || recscore > MAXSCORE)
goto datacorrupt;
......@@ -4568,16 +4570,16 @@ void G_LoadGameData(gamedata_t *data)
// Nights records
for (i = 0; i < NUMMAPS; ++i)
{
if ((recmares = READUINT8(save_p)) == 0)
if ((recmares = P_ReadUINT8(&savebuffer)) == 0)
continue;
G_AllocNightsRecordData((INT16)i, data);
for (curmare = 0; curmare < (recmares+1); ++curmare)
{
data->nightsrecords[i]->score[curmare] = READUINT32(save_p);
data->nightsrecords[i]->grade[curmare] = READUINT8(save_p);
data->nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p);
data->nightsrecords[i]->score[curmare] = P_ReadUINT32(&savebuffer);
data->nightsrecords[i]->grade[curmare] = P_ReadUINT8(&savebuffer);
data->nightsrecords[i]->time[curmare] = (tic_t)P_ReadUINT32(&savebuffer);
if (data->nightsrecords[i]->grade[curmare] > GRADE_S)
{
......@@ -4589,8 +4591,7 @@ void G_LoadGameData(gamedata_t *data)
}
// done
Z_Free(savebuffer);
save_p = NULL;
Z_Free(savebuffer.buf);
// Don't consider loaded until it's a success!
// It used to do this much earlier, but this would cause the gamedata to
......@@ -4611,8 +4612,7 @@ void G_LoadGameData(gamedata_t *data)
if (strcmp(srb2home,"."))
gdfolder = srb2home;
Z_Free(savebuffer);
save_p = NULL;
Z_Free(savebuffer.buf);
I_Error("Corrupt game data file.\nDelete %s(maybe in %s) and try again.", gamedatafilename, gdfolder);
}
......@@ -4622,9 +4622,8 @@ void G_LoadGameData(gamedata_t *data)
// Saves the main data file, which stores information such as emblems found, etc.
void G_SaveGameData(gamedata_t *data)
{
UINT8 *data_p;
save_t savebuffer;
size_t length;
INT32 i, j;
UINT8 btemp;
......@@ -4636,30 +4635,31 @@ void G_SaveGameData(gamedata_t *data)
if (!data->loaded)
return; // If never loaded (-nodata), don't save
data_p = savebuffer = (UINT8 *)malloc(GAMEDATASIZE);
if (!data_p)
savebuffer.size = GAMEDATASIZE;
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
if (!savebuffer.buf)
{
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
return;
}
savebuffer.pos = 0;
if (usedCheats)
{
free(savebuffer);
savebuffer = NULL;
free(savebuffer.buf);
return;
}
// Version test
WRITEUINT32(data_p, GAMEDATA_ID);
P_WriteUINT32(&savebuffer, GAMEDATA_ID);
WRITEUINT32(data_p, data->totalplaytime);
P_WriteUINT32(&savebuffer, data->totalplaytime);
WRITEUINT32(data_p, quickncasehash(timeattackfolder, sizeof timeattackfolder));
P_WriteUINT32(&savebuffer, quickncasehash(timeattackfolder, sizeof timeattackfolder));
// TODO put another cipher on these things? meh, I don't care...
for (i = 0; i < NUMMAPS; i++)
WRITEUINT8(data_p, (data->mapvisited[i] & MV_MAX));
P_WriteUINT8(&savebuffer, (data->mapvisited[i] & MV_MAX));
// To save space, use one bit per collected/achieved/unlocked flag
for (i = 0; i < MAXEMBLEMS;)
......@@ -4667,7 +4667,7 @@ void G_SaveGameData(gamedata_t *data)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEMBLEMS; ++j)
btemp |= (data->collected[j+i] << j);
WRITEUINT8(data_p, btemp);
P_WriteUINT8(&savebuffer, btemp);
i += j;
}
for (i = 0; i < MAXEXTRAEMBLEMS;)
......@@ -4675,7 +4675,7 @@ void G_SaveGameData(gamedata_t *data)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXEXTRAEMBLEMS; ++j)
btemp |= (data->extraCollected[j+i] << j);
WRITEUINT8(data_p, btemp);
P_WriteUINT8(&savebuffer, btemp);
i += j;
}
for (i = 0; i < MAXUNLOCKABLES;)
......@@ -4683,7 +4683,7 @@ void G_SaveGameData(gamedata_t *data)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXUNLOCKABLES; ++j)
btemp |= (data->unlocked[j+i] << j);
WRITEUINT8(data_p, btemp);
P_WriteUINT8(&savebuffer, btemp);
i += j;
}
for (i = 0; i < MAXCONDITIONSETS;)
......@@ -4691,30 +4691,30 @@ void G_SaveGameData(gamedata_t *data)
btemp = 0;
for (j = 0; j < 8 && j+i < MAXCONDITIONSETS; ++j)
btemp |= (data->achieved[j+i] << j);
WRITEUINT8(data_p, btemp);
P_WriteUINT8(&savebuffer, btemp);
i += j;
}
WRITEUINT32(data_p, data->timesBeaten);
WRITEUINT32(data_p, data->timesBeatenWithEmeralds);
WRITEUINT32(data_p, data->timesBeatenUltimate);
P_WriteUINT32(&savebuffer, data->timesBeaten);
P_WriteUINT32(&savebuffer, data->timesBeatenWithEmeralds);
P_WriteUINT32(&savebuffer, data->timesBeatenUltimate);
// Main records
for (i = 0; i < NUMMAPS; i++)
{
if (data->mainrecords[i])
{
WRITEUINT32(data_p, data->mainrecords[i]->score);
WRITEUINT32(data_p, data->mainrecords[i]->time);
WRITEUINT16(data_p, data->mainrecords[i]->rings);
P_WriteUINT32(&savebuffer, data->mainrecords[i]->score);
P_WriteUINT32(&savebuffer, data->mainrecords[i]->time);
P_WriteUINT16(&savebuffer, data->mainrecords[i]->rings);
}
else
{
WRITEUINT32(data_p, 0);
WRITEUINT32(data_p, 0);
WRITEUINT16(data_p, 0);
P_WriteUINT32(&savebuffer, 0);
P_WriteUINT32(&savebuffer, 0);
P_WriteUINT16(&savebuffer, 0);
}
WRITEUINT8(data_p, 0); // compat
P_WriteUINT8(&savebuffer, 0); // compat
}
// NiGHTS records
......@@ -4722,25 +4722,22 @@ void G_SaveGameData(gamedata_t *data)
{
if (!data->nightsrecords[i] || !data->nightsrecords[i]->nummares)
{
WRITEUINT8(data_p, 0);
P_WriteUINT8(&savebuffer, 0);
continue;
}
WRITEUINT8(data_p, data->nightsrecords[i]->nummares);
P_WriteUINT8(&savebuffer, data->nightsrecords[i]->nummares);
for (curmare = 0; curmare < (data->nightsrecords[i]->nummares + 1); ++curmare)
{
WRITEUINT32(data_p, data->nightsrecords[i]->score[curmare]);
WRITEUINT8(data_p, data->nightsrecords[i]->grade[curmare]);
WRITEUINT32(data_p, data->nightsrecords[i]->time[curmare]);
P_WriteUINT32(&savebuffer, data->nightsrecords[i]->score[curmare]);
P_WriteUINT8(&savebuffer, data->nightsrecords[i]->grade[curmare]);
P_WriteUINT32(&savebuffer, data->nightsrecords[i]->time[curmare]);
}
}
length = data_p - savebuffer;
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length);
free(savebuffer);
savebuffer = NULL;
FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer.buf, savebuffer.pos);
free(savebuffer.buf);
}
#define VERSIONSIZE 16
......@@ -4751,7 +4748,7 @@ void G_SaveGameData(gamedata_t *data)
//
void G_LoadGame(UINT32 slot, INT16 mapoverride)
{
size_t length;
save_t savebuffer;
char vcheck[VERSIONSIZE];
char savename[255];
......@@ -4768,18 +4765,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
else
sprintf(savename, savegamename, slot);
length = FIL_ReadFile(savename, &savebuffer);
if (!length)
savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
if (!savebuffer.size)
{
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
return;
}
save_p = savebuffer;
savebuffer.pos = 0;
memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck))
if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck))
{
#ifdef SAVEGAME_OTHERVERSIONS
M_StartMessage(M_GetText("Save game from different version.\nYou can load this savegame, but\nsaving afterwards will be disabled.\n\nDo you want to continue anyway?\n\n(Press 'Y' to confirm)\n"),
......@@ -4789,15 +4786,14 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
M_ClearMenus(true); // so ESC backs out to title
M_StartMessage(M_GetText("Save game from different version\n\nPress ESC\n"), NULL, MM_NOTHING);
Command_ExitGame_f();
Z_Free(savebuffer);
save_p = savebuffer = NULL;
Z_Free(savebuffer.buf);
// no cheating!
memset(&savedata, 0, sizeof(savedata));
#endif
return; // bad version
}
save_p += VERSIONSIZE;
savebuffer.pos += VERSIONSIZE;
// if (demoplayback) // reset game engine
// G_StopDemo();
......@@ -4806,13 +4802,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
// automapactive = false;
// dearchive all the modifications
if (!P_LoadGame(mapoverride))
if (!P_LoadGame(&savebuffer, mapoverride))
{
M_ClearMenus(true); // so ESC backs out to title
M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING);
Command_ExitGame_f();
Z_Free(savebuffer);
save_p = savebuffer = NULL;
Z_Free(savebuffer.buf);
// no cheating!
memset(&savedata, 0, sizeof(savedata));
......@@ -4820,13 +4815,12 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
}
if (marathonmode)
{
marathontime = READUINT32(save_p);
marathonmode |= READUINT8(save_p);
marathontime = P_ReadUINT32(&savebuffer);
marathonmode |= P_ReadUINT8(&savebuffer);
}
// done
Z_Free(savebuffer);
save_p = savebuffer = NULL;
Z_Free(savebuffer.buf);
displayplayer = consoleplayer;
multiplayer = splitscreen = false;
......@@ -4844,6 +4838,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
//
void G_SaveGame(UINT32 slot, INT16 mapnum)
{
save_t savebuffer;
boolean saved;
char savename[256] = "";
const char *backup;
......@@ -4857,33 +4852,32 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
gameaction = ga_nothing;
{
char name[VERSIONSIZE];
size_t length;
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
if (!save_p)
savebuffer.size = SAVEGAMESIZE;
savebuffer.buf = (UINT8 *)malloc(savebuffer.size);
if (!savebuffer.buf)
{
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for saving game data\n"));
return;
}
savebuffer.pos = 0;
memset(name, 0, sizeof (name));
sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION);
WRITEMEM(save_p, name, VERSIONSIZE);
P_WriteMem(&savebuffer, name, VERSIONSIZE);
P_SaveGame(mapnum);
P_SaveGame(&savebuffer, mapnum);
if (marathonmode)
{
UINT32 writetime = marathontime;
if (!(marathonmode & MA_INGAME))
writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map
WRITEUINT32(save_p, writetime);
WRITEUINT8(save_p, (marathonmode & ~MA_INIT));
P_WriteUINT32(&savebuffer, writetime);
P_WriteUINT8(&savebuffer, (marathonmode & ~MA_INIT));
}
length = save_p - savebuffer;
saved = FIL_WriteFile(backup, savebuffer, length);
free(savebuffer);
save_p = savebuffer = NULL;
saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.pos);
free(savebuffer.buf);
}
gameaction = ga_nothing;
......@@ -4895,11 +4889,10 @@ void G_SaveGame(UINT32 slot, INT16 mapnum)
}
#define BADSAVE goto cleanup;
#define CHECKPOS if (save_p >= end_p) BADSAVE
void G_SaveGameOver(UINT32 slot, boolean modifylives)
{
save_t savebuffer;
boolean saved = false;
size_t length;
char vcheck[VERSIONSIZE];
char savename[255];
const char *backup;
......@@ -4910,42 +4903,38 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
sprintf(savename, savegamename, slot);
backup = va("%s",savename);
length = FIL_ReadFile(savename, &savebuffer);
if (!length)
savebuffer.size = FIL_ReadFile(savename, &savebuffer.buf);
if (!savebuffer.size)
{
CONS_Printf(M_GetText("Couldn't read file %s\n"), savename);
return;
}
savebuffer.pos = 0;
{
char temp[sizeof(timeattackfolder)];
UINT8 *end_p = savebuffer + length;
UINT8 *lives_p;
SINT8 pllives;
#ifdef NEWSKINSAVES
INT16 backwardsCompat = 0;
#endif
save_p = savebuffer;
// Version check
memset(vcheck, 0, sizeof (vcheck));
sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION);
if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE
save_p += VERSIONSIZE;
if (strcmp((const char *)&savebuffer.buf[savebuffer.pos], (const char *)vcheck)) BADSAVE
savebuffer.pos += VERSIONSIZE;
// P_UnArchiveMisc()
(void)READINT16(save_p);
CHECKPOS
(void)READUINT16(save_p); // emeralds
CHECKPOS
READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to
(void)P_ReadINT16(&savebuffer);
(void)P_ReadUINT16(&savebuffer); // emeralds
P_ReadStringN(&savebuffer, temp, sizeof(temp)); // mod it belongs to
if (strcmp(temp, timeattackfolder)) BADSAVE
// P_UnArchivePlayer()
CHECKPOS
#ifdef NEWSKINSAVES
backwardsCompat = READUINT16(save_p);
CHECKPOS
backwardsCompat = P_ReadUINT16(&savebuffer);
if (backwardsCompat == NEWSKINSAVES) // New save, read skin names
#endif
......@@ -4953,47 +4942,37 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
char ourSkinName[SKINNAMESIZE+1];
char botSkinName[SKINNAMESIZE+1];
READSTRINGN(save_p, ourSkinName, SKINNAMESIZE);
CHECKPOS
P_ReadStringN(&savebuffer, ourSkinName, SKINNAMESIZE);
READSTRINGN(save_p, botSkinName, SKINNAMESIZE);
CHECKPOS
P_ReadStringN(&savebuffer, botSkinName, SKINNAMESIZE);
}
WRITEUINT8(save_p, numgameovers);
CHECKPOS
P_WriteUINT8(&savebuffer, numgameovers);
lives_p = save_p;
pllives = READSINT8(save_p); // lives
CHECKPOS
lives_p = &savebuffer.buf[savebuffer.pos];
pllives = P_ReadSINT8(&savebuffer); // lives
if (modifylives && pllives < startinglivesbalance[numgameovers])
{
pllives = startinglivesbalance[numgameovers];
WRITESINT8(lives_p, pllives);
*lives_p = startinglivesbalance[numgameovers];
}
(void)READINT32(save_p); // Score
CHECKPOS
(void)READINT32(save_p); // continues
(void)P_ReadINT32(&savebuffer); // Score
(void)P_ReadINT32(&savebuffer); // continues
// File end marker check
CHECKPOS
switch (READUINT8(save_p))
switch (P_ReadUINT8(&savebuffer))
{
case 0xb7:
{
UINT8 i, banksinuse;
CHECKPOS
banksinuse = READUINT8(save_p);
CHECKPOS
banksinuse = P_ReadUINT8(&savebuffer);
if (banksinuse > NUM_LUABANKS)
BADSAVE
for (i = 0; i < banksinuse; i++)
{
(void)READINT32(save_p);
CHECKPOS
(void)P_ReadINT32(&savebuffer);
}
if (READUINT8(save_p) != 0x1d)
if (P_ReadUINT8(&savebuffer) != 0x1d)
BADSAVE
}
case 0x1d:
......@@ -5003,7 +4982,7 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
}
// done
saved = FIL_WriteFile(backup, savebuffer, length);
saved = FIL_WriteFile(backup, savebuffer.buf, savebuffer.size);
}
cleanup:
......@@ -5011,11 +4990,9 @@ cleanup:
CONS_Printf(M_GetText("Game saved.\n"));
else if (!saved)
CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename));
Z_Free(savebuffer);
save_p = savebuffer = NULL;
Z_Free(savebuffer.buf);
}
#undef CHECKPOS
#undef BADSAVE
//
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -71,8 +71,8 @@ typedef enum {
#define P_ControlStyle(player) ((((player)->pflags & PF_ANALOGMODE) ? CS_LMAOGALOG : 0) | (((player)->pflags & PF_DIRECTIONCHAR) ? CS_STANDARD : 0))
extern consvar_t cv_autobrake, cv_autobrake2;
extern consvar_t cv_sideaxis, cv_turnaxis, cv_moveaxis, cv_lookaxis, cv_jumpaxis, cv_spinaxis, cv_shieldaxis, cv_fireaxis, cv_firenaxis, cv_deadzone, cv_digitaldeadzone;
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_shieldaxis2,cv_fireaxis2,cv_firenaxis2,cv_deadzone2,cv_digitaldeadzone2;
extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_jumpaxis,cv_spinaxis,cv_fireaxis,cv_firenaxis,cv_deadzone,cv_digitaldeadzone;
extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_jumpaxis2,cv_spinaxis2,cv_fireaxis2,cv_firenaxis2,cv_deadzone2,cv_digitaldeadzone2;
extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
// hi here's some new controls
......@@ -100,7 +100,6 @@ typedef enum
JA_JUMP = JA_DIGITAL,
JA_SPIN,
JA_SHIELD,
JA_FIRE,
JA_FIRENORMAL,
} joyaxis_e;
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -576,7 +576,9 @@ static const char *gamecontrolname[NUM_GAMECONTROLS] =
"weapon5",
"weapon6",
"weapon7",
"shield",
"weapon8",
"weapon9",
"weapon10",
"fire",
"firenormal",
"tossflag",
......@@ -691,7 +693,6 @@ void G_DefineDefaultControls(void)
gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_LCTRL;
gamecontroldefault[gcs_fps][GC_JUMP ][0] = KEY_SPACE;
gamecontroldefault[gcs_fps][GC_SPIN ][0] = KEY_LSHIFT;
gamecontroldefault[gcs_fps][GC_SHIELD ][0] = KEY_LALT;
gamecontroldefault[gcs_fps][GC_FIRE ][0] = KEY_RCTRL;
gamecontroldefault[gcs_fps][GC_FIRE ][1] = KEY_MOUSE1+0;
gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = KEY_RALT;
......@@ -712,7 +713,6 @@ void G_DefineDefaultControls(void)
gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END;
gamecontroldefault[gcs_platform][GC_JUMP ][0] = KEY_SPACE;
gamecontroldefault[gcs_platform][GC_SPIN ][0] = KEY_LSHIFT;
gamecontroldefault[gcs_platform][GC_SHIELD ][0] = KEY_LALT;
gamecontroldefault[gcs_platform][GC_FIRE ][0] = 's';
gamecontroldefault[gcs_platform][GC_FIRE ][1] = KEY_MOUSE1+0;
gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w';
......@@ -728,6 +728,9 @@ void G_DefineDefaultControls(void)
gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5';
gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6';
gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7';
gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8';
gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9';
gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0';
gamecontroldefault[i][GC_TOSSFLAG ][0] = '\'';
gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v';
gamecontroldefault[i][GC_CAMRESET ][0] = 'r';
......@@ -743,34 +746,34 @@ void G_DefineDefaultControls(void)
// Gamepad controls -- same for both schemes
gamecontroldefault[i][GC_JUMP ][1] = KEY_JOY1+0; // A
gamecontroldefault[i][GC_SPIN ][1] = KEY_JOY1+2; // X
gamecontroldefault[i][GC_SHIELD ][1] = KEY_JOY1+1; // B
gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+3; // Y
gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+4; // LB
gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB
gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B
gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y
gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick
gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+9; // Right Stick
gamecontroldefault[i][GC_SCORES ][1] = KEY_JOY1+6; // Back
gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+4; // LB
gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB
gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back
gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start
gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_HAT1+0; // D-Pad Up
gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+1; // D-Pad Down
gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_HAT1+2; // D-Pad Left
gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_HAT1+3; // D-Pad Right
gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_JOY1+9; // Right Stick
gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+0; // D-Pad Up
gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+1; // D-Pad Down
// Second player controls only have joypad defaults
gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A
gamecontrolbisdefault[i][GC_SPIN ][1] = KEY_2JOY1+2; // X
gamecontrolbisdefault[i][GC_SHIELD ][1] = KEY_2JOY1+1; // B
gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+3; // Y
gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+4; // LB
gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB
gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B
gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y
gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick
gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+9; // Right Stick
//gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2JOY1+6; // Back
gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+4; // LB
gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB
gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back
//gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start
gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2HAT1+0; // D-Pad Up
gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+1; // D-Pad Down
gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2HAT1+2; // D-Pad Left
gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2HAT1+3; // D-Pad Right
gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2JOY1+9; // Right Stick
gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+0; // D-Pad Up
//gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+1; // D-Pad Down
}
}
......
......@@ -74,7 +74,9 @@ typedef enum
GC_WEPSLOT5,
GC_WEPSLOT6,
GC_WEPSLOT7,
GC_SHIELD,
GC_WEPSLOT8,
GC_WEPSLOT9,
GC_WEPSLOT10,
GC_FIRE,
GC_FIRENORMAL,
GC_TOSSFLAG,
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Sonic Team Junior.
// Copyright (C) 2020-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -114,7 +114,7 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
polygonArray[polygonArraySize].numVerts = iNumPts;
polygonArray[polygonArraySize].polyFlags = PolyFlags;
polygonArray[polygonArraySize].texture = current_texture;
polygonArray[polygonArraySize].shader = (shader_target != -1) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].shader = (shader_target != SHADER_NONE) ? HWR_GetShaderFromTarget(shader_target) : shader_target;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
// default to polygonArraySize so we don't lose order on horizon lines
// (yes, it's supposed to be negative, since we're sorting in that direction)
......@@ -311,7 +311,6 @@ void HWR_RenderBatches(void)
int nextIndex = polygonIndexArray[polygonReadPos];
if (polygonArray[index].hash != polygonArray[nextIndex].hash)
{
changeState = true;
nextShader = polygonArray[nextIndex].shader;
nextTexture = polygonArray[nextIndex].texture;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
......@@ -320,14 +319,17 @@ void HWR_RenderBatches(void)
nextTexture = 0;
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
{
changeState = true;
changeShader = true;
}
if (currentTexture != nextTexture)
{
changeState = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changeState = true;
changePolyFlags = true;
}
if (cv_glshaders.value && gl_shadersavailable)
......@@ -339,6 +341,7 @@ void HWR_RenderBatches(void)
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
{
changeState = true;
changeSurfaceInfo = true;
}
}
......@@ -346,6 +349,7 @@ void HWR_RenderBatches(void)
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
{
changeState = true;
changeSurfaceInfo = true;
}
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2020-2023 by Sonic Team Junior.
// Copyright (C) 2020-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
......@@ -450,15 +450,10 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
texture = textures[texnum];
mipmap->flags = TF_WRAPXY;
mipmap->width = (UINT16)texture->width;
mipmap->height = (UINT16)texture->height;
mipmap->format = textureformat;
blockwidth = texture->width;
blockheight = texture->height;
blocksize = (blockwidth * blockheight);
block = MakeBlock(&grtex->mipmap);
blocksize = blockwidth * blockheight;
block = MakeBlock(mipmap);
// Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
......@@ -488,7 +483,7 @@ static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex, GLMipmap_t
realpatch = W_CachePatchNumPwad(wadnum, lumpnum, PU_PATCH);
}
HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch);
HWR_DrawTexturePatchInCache(mipmap, blockwidth, blockheight, texture, patch, realpatch);
if (free_patch)
Patch_Free(realpatch);
......@@ -680,25 +675,24 @@ void HWR_InitMapTextures(void)
gl_maptexturesloaded = false;
}
static void DeleteTextureMipmap(GLMipmap_t *grMipmap)
static void DeleteTextureMipmap(GLMipmap_t *grMipmap, boolean delete_mipmap)
{
HWD.pfnDeleteTexture(grMipmap);
// Chroma-keyed textures do not own their texture data, so do not free it
if (!(grMipmap->flags & TF_CHROMAKEYED))
if (delete_mipmap)
Z_Free(grMipmap->data);
}
static void FreeMapTexture(GLMapTexture_t *tex)
static void FreeMapTexture(GLMapTexture_t *tex, boolean delete_chromakeys)
{
if (tex->mipmap.nextcolormap)
{
DeleteTextureMipmap(tex->mipmap.nextcolormap);
DeleteTextureMipmap(tex->mipmap.nextcolormap, delete_chromakeys);
free(tex->mipmap.nextcolormap);
tex->mipmap.nextcolormap = NULL;
}
DeleteTextureMipmap(&tex->mipmap);
DeleteTextureMipmap(&tex->mipmap, true);
}
void HWR_FreeMapTextures(void)
......@@ -707,8 +701,8 @@ void HWR_FreeMapTextures(void)
for (i = 0; i < gl_numtextures; i++)
{
FreeMapTexture(&gl_textures[i]);
FreeMapTexture(&gl_flats[i]);
FreeMapTexture(&gl_textures[i], true);
FreeMapTexture(&gl_flats[i], false);
}
// now the heap don't have any 'user' pointing to our
......@@ -741,22 +735,7 @@ void HWR_LoadMapTextures(size_t pnumtextures)
// --------------------------------------------------------------------------
// Make sure texture is downloaded and set it as the source
// --------------------------------------------------------------------------
static void GetMapTexture(INT32 tex, GLMapTexture_t *grtex, GLMipmap_t *mipmap)
{
// Generate texture if missing from the cache
if (!mipmap->data && !mipmap->downloaded)
HWR_GenerateTexture(tex, grtex, mipmap);
// If hardware does not have the texture, then call pfnSetTexture to upload it
if (!mipmap->downloaded)
HWD.pfnSetTexture(mipmap);
HWR_SetCurrentTexture(mipmap);
// The system-memory data can be purged now.
Z_ChangeTag(mipmap->data, PU_HWRCACHE_UNLOCKED);
}
GLMapTexture_t *HWR_GetTexture(INT32 tex)
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed)
{
if (tex < 0 || tex >= (signed)gl_numtextures)
{
......@@ -769,7 +748,46 @@ GLMapTexture_t *HWR_GetTexture(INT32 tex)
GLMapTexture_t *grtex = &gl_textures[tex];
GetMapTexture(tex, grtex, &grtex->mipmap);
GLMipmap_t *grMipmap = &grtex->mipmap;
GLMipmap_t *originalMipmap = grMipmap;
if (!originalMipmap->downloaded)
{
originalMipmap->flags = TF_WRAPXY;
originalMipmap->width = (UINT16)textures[tex]->width;
originalMipmap->height = (UINT16)textures[tex]->height;
originalMipmap->format = textureformat;
}
// If chroma-keyed, create or use a different mipmap for the variant
if (chromakeyed && !textures[tex]->transparency)
{
// Allocate it if it wasn't already
if (!originalMipmap->nextcolormap)
{
GLMipmap_t *newMipmap = calloc(1, sizeof (*grMipmap));
if (newMipmap == NULL)
I_Error("%s: Out of memory", "HWR_GetTexture");
newMipmap->flags = originalMipmap->flags | TF_CHROMAKEYED;
newMipmap->width = originalMipmap->width;
newMipmap->height = originalMipmap->height;
newMipmap->format = originalMipmap->format;
originalMipmap->nextcolormap = newMipmap;
}
// Generate, upload and bind the variant texture instead of the original one
grMipmap = originalMipmap->nextcolormap;
}
if (!grMipmap->data)
HWR_GenerateTexture(tex, grtex, grMipmap);
if (!grMipmap->downloaded)
HWD.pfnSetTexture(grMipmap);
HWR_SetCurrentTexture(grMipmap);
Z_ChangeTag(grMipmap->data, PU_HWRCACHE_UNLOCKED);
return grtex;
}
......@@ -1240,20 +1258,29 @@ void HWR_SetMapPalette(void)
// Creates a hardware lighttable from the supplied lighttable.
// Returns the id of the hw lighttable, usable in FSurfaceInfo.
UINT32 HWR_CreateLightTable(UINT8 *lighttable)
UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable)
{
UINT32 i, id;
UINT32 i;
RGBA_t *palette = HWR_GetTexturePalette();
RGBA_t *hw_lighttable = Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_STATIC, NULL);
// To make the palette index -> RGBA mapping easier for the shader,
// the hardware lighttable is composed of RGBA colors instead of palette indices.
for (i = 0; i < 256 * 32; i++)
hw_lighttable[i] = palette[lighttable[i]];
id = HWD.pfnCreateLightTable(hw_lighttable);
Z_Free(hw_lighttable);
return id;
return HWD.pfnCreateLightTable(hw_lighttable);
}
// Updates a hardware lighttable of a given id from the supplied lighttable.
void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable)
{
UINT32 i;
RGBA_t *palette = HWR_GetTexturePalette();
for (i = 0; i < 256 * 32; i++)
hw_lighttable[i] = palette[lighttable[i]];
HWD.pfnUpdateLightTable(id, hw_lighttable);
}
// get hwr lighttable id for colormap, create it if it doesn't already exist
......@@ -1267,25 +1294,41 @@ UINT32 HWR_GetLightTableID(extracolormap_t *colormap)
default_colormap = true;
}
UINT8 *colormap_pointer;
if (default_colormap)
colormap_pointer = colormaps; // don't actually use the data from the "default colormap"
else
colormap_pointer = colormap->colormap;
// create hw lighttable if there isn't one
if (!colormap->gl_lighttable_id)
if (colormap->gl_lighttable.data == NULL)
{
UINT8 *colormap_pointer;
Z_Malloc(256 * 32 * sizeof(RGBA_t), PU_HWRLIGHTTABLEDATA, &colormap->gl_lighttable.data);
}
if (default_colormap)
colormap_pointer = colormaps; // don't actually use the data from the "default colormap"
else
colormap_pointer = colormap->colormap;
colormap->gl_lighttable_id = HWR_CreateLightTable(colormap_pointer);
// Generate the texture for this light table
if (!colormap->gl_lighttable.id)
{
colormap->gl_lighttable.id = HWR_CreateLightTable(colormap_pointer, colormap->gl_lighttable.data);
}
// Update the texture if it was directly changed by a script
else if (colormap->gl_lighttable.needs_update)
{
HWR_UpdateLightTable(colormap->gl_lighttable.id, colormap_pointer, colormap->gl_lighttable.data);
}
return colormap->gl_lighttable_id;
colormap->gl_lighttable.needs_update = false;
return colormap->gl_lighttable.id;
}
// Note: all hardware lighttable ids assigned before this
// call become invalid and must not be used.
void HWR_ClearLightTables(void)
{
Z_FreeTag(PU_HWRLIGHTTABLEDATA);
if (vid.glstate == VID_GL_LIBRARY_LOADED)
HWD.pfnClearLightTables();
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -256,8 +256,8 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
}
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
cx = -1 + (cx / (vid.width/2));
cy = 1 - (cy / (vid.height/2));
cx = -1.0f + (cx / (vid.width / 2.0f));
cy = 1.0f - (cy / (vid.height / 2.0f));
// fwidth and fheight are similar
fwidth /= vid.width / 2;
......@@ -598,43 +598,76 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// --------------------------------------------------------------------------
// Fills a box of pixels using a flat texture as a pattern
// Fixed to properly align like the other draw functions -luigi budd
// --------------------------------------------------------------------------
void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
{
FOutVector v[4];
const size_t len = W_LumpLength(flatlumpnum);
UINT16 flatflag = R_GetFlatSize(len) - 1;
double dflatsize = (double)(flatflag + 1);
UINT16 flatflag = R_GetFlatSize(len);
double dflatsize = (double)(flatflag);
// compilers are COOL!
float dup = (float)vid.dup;
float fx = (float)x * dup;
float fy = (float)y * dup;
float fw = (float)w * dup;
float fh = (float)h * dup;
/*
fx *= dup;
fy *= dup;
fw *= dup;
fh *= dup;
*/
if (fw <= 0 || fh <= 0)
return;
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f)
{
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2;
}
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f)
{
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2;
}
if (fx >= vid.width || fy >= vid.height)
return;
fx = -1.0f + (fx / (vid.width / 2.0f));
fy = 1.0f - (fy / (vid.height / 2.0f));
fw /= vid.width / 2;
fh /= vid.height / 2;
// 3--2
// | /|
// |/ |
// 0--1
// position vertices
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
v[0].x = v[3].x = (x - 160.0f)/160.0f;
v[2].x = v[1].x = ((x+w) - 160.0f)/160.0f;
v[0].y = v[1].y = -(y - 100.0f)/100.0f;
v[2].y = v[3].y = -((y+h) - 100.0f)/100.0f;
v[0].y = v[1].y = fy;
v[2].y = v[3].y = fy - fh;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = (float)((x & flatflag)/dflatsize);
v[2].s = v[1].s = (float)(v[0].s + w/dflatsize);
v[0].t = v[1].t = (float)((y & flatflag)/dflatsize);
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize);
// sides
v[0].s = v[3].s = (float)(flatflag/dflatsize) * 2;
v[2].s = v[1].s = (float)(v[0].s + w/dflatsize) * 2;
HWR_GetRawFlat(flatlumpnum);
// top/bottom
v[0].t = v[1].t = (float)(flatflag/dflatsize) * 2;
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize) * 2;
//Hurdler: Boris, the same comment as above... but maybe for pics
// it not a problem since they don't have any transparent pixel
// if I'm right !?
// BTW, I see we put 0 for PFs, and If I'm right, that
// means we take the previous PFs as default
// how can we be sure they are ok?
// needed to texture the poly
HWR_GetRawFlat(flatlumpnum);
HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent);
}
// --------------------------------------------------------------------------
// Fade down the screen so that the menu drawn on top of it looks brighter
// --------------------------------------------------------------------------
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -71,6 +71,7 @@ EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value);
EXPORT void HWRAPI(SetPaletteLookup)(UINT8 *lut);
EXPORT UINT32 HWRAPI(CreateLightTable)(RGBA_t *hw_lighttable);
EXPORT void HWRAPI(UpdateLightTable)(UINT32 id, RGBA_t *hw_lighttable);
EXPORT void HWRAPI(ClearLightTables)(void);
EXPORT void HWRAPI(SetScreenPalette)(RGBA_t *palette);
......@@ -125,6 +126,7 @@ struct hwdriver_s
SetPaletteLookup pfnSetPaletteLookup;
CreateLightTable pfnCreateLightTable;
UpdateLightTable pfnUpdateLightTable;
ClearLightTables pfnClearLightTables;
SetScreenPalette pfnSetScreenPalette;
};
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -120,7 +120,7 @@ void HWR_GetPatch(patch_t *patch);
void HWR_GetMappedPatch(patch_t *patch, const UINT8 *colormap);
void HWR_GetFadeMask(lumpnum_t fademasklumpnum);
GLMapTexture_t *HWR_GetTexture(INT32 tex);
GLMapTexture_t *HWR_GetTexture(INT32 tex, boolean chromakeyed);
void HWR_GetLevelFlat(levelflat_t *levelflat, boolean chromakeyed);
void HWR_GetRawFlat(lumpnum_t flatlumpnum);
......@@ -133,7 +133,8 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch);
void HWR_SetPalette(RGBA_t *palette);
void HWR_SetMapPalette(void);
UINT32 HWR_CreateLightTable(UINT8 *lighttable);
UINT32 HWR_CreateLightTable(UINT8 *lighttable, RGBA_t *hw_lighttable);
void HWR_UpdateLightTable(UINT32 id, UINT8 *lighttable, RGBA_t *hw_lighttable);
UINT32 HWR_GetLightTableID(extracolormap_t *colormap);
void HWR_ClearLightTables(void);
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -395,6 +395,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_XMS6
&lspr[NOLIGHT], // SPR_SNTT
&lspr[NOLIGHT], // SPR_SSTT
&lspr[NOLIGHT], // SPR_FHZI
&lspr[NOLIGHT], // SPR_ROSY
......@@ -428,6 +430,8 @@ light_t *t_lspr[NUMSPRITES] =
// Misc Scenery
&lspr[NOLIGHT], // SPR_STLG
&lspr[NOLIGHT], // SPR_DBAL
&lspr[NOLIGHT], // SPR_GINE
&lspr[NOLIGHT], // SPR_PPAL
// Powerup Indicators
&lspr[NOLIGHT], // SPR_ARMA
......@@ -614,6 +618,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_GWLG
&lspr[NOLIGHT], // SPR_GWLR
// LJ Knuckles
&lspr[NOLIGHT], // SPR_OLDK,
// Free slots
&lspr[NOLIGHT],
&lspr[NOLIGHT],
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -309,6 +309,43 @@ static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
return (FUINT)finallight;
}
static UINT8 HWR_SideLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light +
((side->lightabsolute) ? 0 : base_lightlevel)));
}
/* TODO: implement per-texture lighting
static UINT8 HWR_TopLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_top +
((side->lightabsolute_top) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
static UINT8 HWR_MidLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_mid +
((side->lightabsolute_mid) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
static UINT8 HWR_BottomLightLevel(side_t *side, INT16 base_lightlevel)
{
return max(0, min(255, side->light_bottom +
((side->lightabsolute_bottom) ? 0 : HWR_SideLightLevel(side, base_lightlevel))));
}
*/
static UINT8 HWR_FloorLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->floorlightlevel +
((sector->floorlightabsolute) ? 0 : base_lightlevel)));
}
static UINT8 HWR_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->ceilinglightlevel +
((sector->ceilinglightabsolute) ? 0 : base_lightlevel)));
}
// ==========================================================================
// FLOOR/CEILING GENERATION FROM SUBSECTORS
// ==========================================================================
......@@ -705,8 +742,9 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
fixed_t v2x = FloatToFixed(wallVerts[1].x);
fixed_t v2y = FloatToFixed(wallVerts[1].z);
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, sector->lightlevel);
const UINT8 alpha = Surf->PolyColor.s.alpha;
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
lightnum = HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
extracolormap_t *colormap = NULL;
if (!r_renderwalls)
......@@ -750,13 +788,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
{
if (pfloor && (pfloor->fofflags & FOF_FOG))
{
lightnum = pfloor->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, pfloor->master->frontsector->lightlevel);
colormap = pfloor->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
else
{
lightnum = *list[i].lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, *list[i].lightlevel);
colormap = *list[i].extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, v1x, v1y, v2x, v2y);
}
......@@ -916,6 +954,7 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf)
static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts)
{
sector_t *front, *back;
FOutVector wallVerts[4];
FSurfaceInfo Surf;
......@@ -925,6 +964,16 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
if (!HWR_BlendMidtextureSurface(&Surf))
return;
if (gl_linedef->frontsector->heightsec != -1)
front = &sectors[gl_linedef->frontsector->heightsec];
else
front = gl_linedef->frontsector;
if (gl_linedef->backsector->heightsec != -1)
back = &sectors[gl_linedef->backsector->heightsec];
else
back = gl_linedef->backsector;
fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid));
INT32 repeats;
......@@ -934,15 +983,15 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
{
fixed_t high, low;
if (gl_frontsector->ceilingheight > gl_backsector->ceilingheight)
high = gl_backsector->ceilingheight;
if (front->ceilingheight > back->ceilingheight)
high = back->ceilingheight;
else
high = gl_frontsector->ceilingheight;
high = front->ceilingheight;
if (gl_frontsector->floorheight > gl_backsector->floorheight)
low = gl_frontsector->floorheight;
if (front->floorheight > back->floorheight)
low = front->floorheight;
else
low = gl_backsector->floorheight;
low = back->floorheight;
repeats = (high - low) / texheight;
if ((high - low) % texheight)
......@@ -951,7 +1000,7 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
else
repeats = 1;
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture);
GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture, true);
float xscale = FixedToFloat(gl_sidedef->scalex_mid);
float yscale = FixedToFloat(gl_sidedef->scaley_mid);
......@@ -969,8 +1018,8 @@ static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliph
if (gl_curline->polyseg)
{
// Change this when polyobjects support slopes
popentop = popentopslope = gl_curline->backsector->ceilingheight;
popenbottom = popenbottomslope = gl_curline->backsector->floorheight;
popentop = popentopslope = back->ceilingheight;
popenbottom = popenbottomslope = back->floorheight;
}
else
{
......@@ -1167,7 +1216,7 @@ static void HWR_ProcessSeg(void)
float cliplow = (float)gl_curline->offset;
float cliphigh = cliplow + (gl_curline->flength * FRACUNIT);
FUINT lightnum = gl_frontsector->lightlevel;
FUINT lightnum = HWR_SideLightLevel(gl_sidedef, gl_frontsector->lightlevel);
extracolormap_t *colormap = gl_frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
......@@ -1210,7 +1259,7 @@ static void HWR_ProcessSeg(void)
// check TOP TEXTURE
if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture)
{
grTex = HWR_GetTexture(gl_toptexture);
grTex = HWR_GetTexture(gl_toptexture, false);
xscale = FixedToFloat(abs(gl_sidedef->scalex_top));
yscale = FixedToFloat(abs(gl_sidedef->scaley_top));
......@@ -1300,7 +1349,7 @@ static void HWR_ProcessSeg(void)
// check BOTTOM TEXTURE
if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture)
{
grTex = HWR_GetTexture(gl_bottomtexture);
grTex = HWR_GetTexture(gl_bottomtexture, false);
xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom));
yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom));
......@@ -1414,7 +1463,7 @@ static void HWR_ProcessSeg(void)
// Single sided line... Deal only with the middletexture (if one exists)
if (gl_midtexture && gl_linedef->special != SPECIAL_HORIZON_LINE) // (Ignore horizon line for OGL)
{
grTex = HWR_GetTexture(gl_midtexture);
grTex = HWR_GetTexture(gl_midtexture, false);
xscale = FixedToFloat(gl_sidedef->scalex_mid);
yscale = FixedToFloat(gl_sidedef->scaley_mid);
......@@ -1533,14 +1582,14 @@ static void HWR_ProcessSeg(void)
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
side_t *side = R_GetFFloorSide(gl_curline, rover);
side_t *side = R_GetFFloorSide(gl_curline->linedef, rover, gl_backsector);
boolean do_texture_skew;
boolean dont_peg_bottom;
if (rover->master->flags & ML_TFERLINE)
{
line_t *newline = R_GetFFloorLine(gl_curline, rover);
line_t *newline = R_GetFFloorLine(gl_curline->linedef, rover, gl_backsector);
do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
}
......@@ -1588,7 +1637,7 @@ static void HWR_ProcessSeg(void)
// -- Monster Iestyn 26/06/18
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
grTex = HWR_GetTexture(texnum);
grTex = HWR_GetTexture(texnum, true);
xscale = FixedToFloat(side->scalex_mid);
yscale = FixedToFloat(side->scaley_mid);
......@@ -1628,11 +1677,11 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel), rover->master->frontsector->extra_colormap);
if (gl_frontsector->numlights)
HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->fofflags, rover, blendmode);
......@@ -1643,7 +1692,7 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Masked;
if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend)
{
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent;
Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255));
......@@ -1689,14 +1738,14 @@ static void HWR_ProcessSeg(void)
if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
continue;
side_t *side = R_GetFFloorSide(gl_curline, rover);
side_t *side = R_GetFFloorSide(gl_curline->linedef, rover, gl_backsector);
boolean do_texture_skew;
boolean dont_peg_bottom;
if (rover->master->flags & ML_TFERLINE)
{
line_t *newline = R_GetFFloorLine(gl_curline, rover);
line_t *newline = R_GetFFloorLine(gl_curline->linedef, rover, gl_backsector);
do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
}
......@@ -1745,7 +1794,7 @@ static void HWR_ProcessSeg(void)
// -- Monster Iestyn 26/06/18
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
grTex = HWR_GetTexture(texnum);
grTex = HWR_GetTexture(texnum, true);
xscale = FixedToFloat(side->scalex_mid);
yscale = FixedToFloat(side->scaley_mid);
......@@ -1785,7 +1834,7 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Fog|PF_NoTexture;
lightnum = rover->master->frontsector->lightlevel;
lightnum = HWR_SideLightLevel(gl_sidedef, rover->master->frontsector->lightlevel);
colormap = rover->master->frontsector->extra_colormap;
lightnum = colormap ? lightnum : HWR_CalcWallLight(lightnum, vs.x, vs.y, ve.x, ve.y);
......@@ -1800,7 +1849,7 @@ static void HWR_ProcessSeg(void)
{
blendmode = PF_Masked;
if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend)
{
blendmode = rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent;
Surf.PolyColor.s.alpha = max(0, min(rover->alpha, 255));
......@@ -2447,14 +2496,14 @@ static void HWR_Subsector(size_t num)
continue;
if (sub->validcount == validcount)
continue;
// rendering heights for bottom and top planes
bottomCullHeight = P_GetFFloorBottomZAt(rover, viewx, viewy);
topCullHeight = P_GetFFloorTopZAt(rover, viewx, viewy);
if (gl_frontsector->cullheight)
{
if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(bottomCullHeight), FIXED_TO_FLOAT(topCullHeight)))
if (HWR_DoCulling(gl_frontsector->cullheight, viewsector->cullheight, gl_viewz, FIXED_TO_FLOAT(*rover->bottomheight), FIXED_TO_FLOAT(*rover->topheight)))
continue;
}
......@@ -2471,17 +2520,17 @@ static void HWR_Subsector(size_t num)
UINT8 alpha;
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
alpha = HWR_FogBlockAlpha(HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, false, rover->master->frontsector->extra_colormap);
}
else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) // SoM: Flags are more efficient
else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend) // SoM: Flags are more efficient
{
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
......@@ -2489,7 +2538,7 @@ static void HWR_Subsector(size_t num)
&extrasubsectors[num],
false,
*rover->bottomheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
......@@ -2498,8 +2547,9 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->bottompic], rover->fofflags & FOF_SPLAT);
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < bottomCullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude,
HWR_FloorLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
&levelflats[*rover->bottompic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
......@@ -2516,17 +2566,17 @@ static void HWR_Subsector(size_t num)
UINT8 alpha;
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap);
alpha = HWR_FogBlockAlpha(HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel), rover->master->frontsector->extra_colormap);
HWR_AddTransparentFloor(0,
&extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
alpha, rover->master->frontsector, PF_Fog|PF_NoTexture,
true, false, rover->master->frontsector->extra_colormap);
}
else if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend)
else if ((rover->fofflags & FOF_TRANSLUCENT && !((rover->fofflags & FOF_SPLAT) && rover->alpha >= 255)) || rover->blend)
{
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
......@@ -2534,7 +2584,7 @@ static void HWR_Subsector(size_t num)
&extrasubsectors[num],
true,
*rover->topheight,
*gl_frontsector->lightlist[light].lightlevel,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
max(0, min(rover->alpha, 255)), rover->master->frontsector,
HWR_RippleBlend(gl_frontsector, rover, false) | (rover->blend ? HWR_GetBlendModeFlag(rover->blend) : PF_Translucent),
false, rover->fofflags & FOF_SPLAT, *gl_frontsector->lightlist[light].extra_colormap);
......@@ -2543,8 +2593,9 @@ static void HWR_Subsector(size_t num)
{
HWR_GetLevelFlat(&levelflats[*rover->toppic], rover->fofflags & FOF_SPLAT);
light = R_GetPlaneLight(gl_frontsector, centerHeight, viewz < topCullHeight ? true : false);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, HWR_RippleBlend(gl_frontsector, rover, false)|PF_Occlude,
HWR_CeilingLightLevel(rover->master->frontsector, *gl_frontsector->lightlist[light].lightlevel),
&levelflats[*rover->toppic], rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap);
}
}
}
......@@ -2620,45 +2671,31 @@ fixed_t *hwbbox;
static void HWR_RenderBSPNode(INT32 bspnum)
{
node_t *bsp = &nodes[bspnum];
// Decide which side the view point is on
node_t *bsp;
INT32 side;
ps_numbspcalls.value.i++;
// Found a subsector?
if (bspnum & NF_SUBSECTOR)
while (!(bspnum & NF_SUBSECTOR)) // Found a subsector?
{
if (bspnum == -1)
{
//*(gl_drawsubsector_p++) = 0;
HWR_Subsector(0);
}
else
{
//*(gl_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR);
HWR_Subsector(bspnum&(~NF_SUBSECTOR));
}
return;
}
bsp = &nodes[bspnum];
// Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp);
// Decide which side the view point is on.
side = R_PointOnSide(viewx, viewy, bsp);
// BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp->bbox[side];
// Recursively divide front space.
HWR_RenderBSPNode(bsp->children[side]);
// BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp->bbox[side];
// Possibly divide back space.
// Recursively divide front space.
HWR_RenderBSPNode(bsp->children[side]);
if (!HWR_CheckBBox(bsp->bbox[side^1]))
return;
// Possibly divide back space.
if (HWR_CheckBBox(bsp->bbox[side^1]))
{
// BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp->bbox[side^1];
HWR_RenderBSPNode(bsp->children[side^1]);
bspnum = bsp->children[side^1];
}
HWR_Subsector(bspnum == -1 ? 0 : bspnum & ~NF_SUBSECTOR);
}
// ==========================================================================
......@@ -2880,7 +2917,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
}
HWR_Lighting(&sSurf, 0, colormap);
sSurf.PolyColor.s.alpha = alpha;
sSurf.PolyColor.s.alpha = FixedMul(thing->alpha, alpha);
if (HWR_UseShader())
{
......@@ -3055,10 +3092,15 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// co-ordinates
memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts));
fixed_t newalpha = spr->mobj->alpha;
// if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude)
// this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw.
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
{
newalpha = spr->mobj->tracer->alpha;
occlusion = 0;
}
else
occlusion = PF_Occlude;
......@@ -3095,6 +3137,8 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (HWR_UseShader())
{
shader = SHADER_SPRITE;
......@@ -3291,7 +3335,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
v[15].y = v[16].y = v[17].y = v[21].y = v[22].y = v[23].y = vis->gzt; // top
Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
HWR_ProcessPolygon(&Surf, v, 24, (cv_renderhitboxgldepth.value ? 0 : PF_NoDepthTest)|PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false);
}
......@@ -3543,11 +3587,15 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
FBITFIELD blend = 0;
FBITFIELD occlusion;
boolean use_linkdraw_hack = false;
fixed_t newalpha = spr->mobj->alpha;
// if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude)
// this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw.
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
{
occlusion = 0;
newalpha = spr->mobj->tracer->alpha;
}
else
occlusion = PF_Occlude;
......@@ -3584,6 +3632,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (spr->renderflags & RF_SHADOWEFFECTS)
{
INT32 alpha = Surf.PolyColor.s.alpha;
......@@ -3893,7 +3943,7 @@ void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boo
planeinfo[numplanes].isceiling = isceiling;
planeinfo[numplanes].fixedheight = fixedheight;
planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel;
planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent FOF planes always use light level
planeinfo[numplanes].levelflat = levelflat;
planeinfo[numplanes].xsub = xsub;
planeinfo[numplanes].alpha = alpha;
......@@ -3925,7 +3975,7 @@ void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polyse
polyplaneinfo[numpolyplanes].isceiling = isceiling;
polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? 255 : lightlevel;
polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; // TODO: 2.3: Make transparent polyobject planes always use light level
polyplaneinfo[numpolyplanes].levelflat = levelflat;
polyplaneinfo[numpolyplanes].polysector = polysector;
polyplaneinfo[numpolyplanes].alpha = alpha;
......@@ -4086,7 +4136,7 @@ static void HWR_CreateDrawNodes(void)
else if (sortnode[sortindex[i]].wall)
{
if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture))
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum);
HWR_GetTexture(sortnode[sortindex[i]].wall->texnum, true);
HWR_RenderWall(sortnode[sortindex[i]].wall->wallVerts, &sortnode[sortindex[i]].wall->Surf, sortnode[sortindex[i]].wall->blend, sortnode[sortindex[i]].wall->fogwall,
sortnode[sortindex[i]].wall->lightlevel, sortnode[sortindex[i]].wall->wallcolormap);
}
......@@ -5066,6 +5116,8 @@ static void HWR_DrawSkyBackground(player_t *player)
HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
HWR_GetTexture(texturetranslation[skytexture], false);
if (cv_glskydome.value)
{
FTransform dometransform;
......@@ -5081,8 +5133,6 @@ static void HWR_DrawSkyBackground(player_t *player)
HWR_SetTransformAiming(&dometransform, player, false);
dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
HWR_GetTexture(texturetranslation[skytexture]);
if (gl_sky.texture != texturetranslation[skytexture])
{
HWR_ClearSkyDome();
......@@ -5102,7 +5152,6 @@ static void HWR_DrawSkyBackground(player_t *player)
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
......@@ -5221,7 +5270,9 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
if (cv_glshearing.value == 1 || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox)))
{
fixed_t fixedaiming = AIMINGTODY(aimingangle);
trans->viewaiming = FIXED_TO_FLOAT(fixedaiming);
trans->viewaiming = FIXED_TO_FLOAT(fixedaiming) * ((float)vid.width / vid.height) / ((float)BASEVIDWIDTH / BASEVIDHEIGHT);
if (splitscreen)
trans->viewaiming *= 2.125; // splitscreen adjusts fov with 0.8, so compensate (but only halfway, since splitscreen means only half the screen is used)
trans->shearing = true;
gl_aimingangle = 0;
}
......@@ -5540,7 +5591,7 @@ void HWR_RenderPlayerView(INT32 viewnumber, player_t *player)
// Can't have palette rendering if shaders are disabled.
boolean HWR_ShouldUsePaletteRendering(void)
{
return (cv_glpaletterendering.value && HWR_UseShader());
return (pMasterPalette != NULL && cv_glpaletterendering.value && HWR_UseShader());
}
// enable or disable palette rendering state depending on settings and availability
......@@ -5610,7 +5661,6 @@ void HWR_LoadLevel(void)
// ==========================================================================
static CV_PossibleValue_t glshaders_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Ignore custom shaders"}, {0, NULL}};
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
......@@ -5639,7 +5689,7 @@ consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0
#endif
consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, glmodelinterpolation_cons_t, NULL);
consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "On", CV_SAVE, CV_OnOff, NULL);
consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glmodellighting_OnChange);
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
......@@ -5657,7 +5707,7 @@ consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL);
static CV_PossibleValue_t glpalettedepth_cons_t[] = {{16, "16 bits"}, {24, "24 bits"}, {0, NULL}};
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "Off", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange);
consvar_t cv_glpaletterendering = CVAR_INIT ("gr_paletterendering", "On", CV_SAVE|CV_CALL, CV_OnOff, CV_glpaletterendering_OnChange);
consvar_t cv_glpalettedepth = CVAR_INIT ("gr_palettedepth", "16 bits", CV_SAVE|CV_CALL, glpalettedepth_cons_t, CV_glpalettedepth_OnChange);
#define ONLY_IF_GL_LOADED if (vid.glstate != VID_GL_LIBRARY_LOADED) return;
......@@ -5729,6 +5779,7 @@ void HWR_AddCommands(void)
CV_RegisterVar(&cv_glskydome);
CV_RegisterVar(&cv_glspritebillboarding);
CV_RegisterVar(&cv_glfakecontrast);
CV_RegisterVar(&cv_glslopecontrast);
CV_RegisterVar(&cv_glshearing);
CV_RegisterVar(&cv_glshaders);
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -571,19 +571,15 @@ void HWR_LoadModels(void)
}
// Add sprite models.
// Must be 4 characters long exactly. Otherwise, it's not a sprite name.
if (len == 4)
for (i = 0; i < numsprites; i++)
{
for (i = 0; i < numsprites; i++)
if (stricmp(name, sprnames[i]) == 0)
{
if (stricmp(name, sprnames[i]) == 0)
{
md2_models[i].scale = scale;
md2_models[i].offset = offset;
md2_models[i].found = true;
strcpy(md2_models[i].filename, filename);
goto modelfound;
}
md2_models[i].scale = scale;
md2_models[i].offset = offset;
md2_models[i].found = true;
strcpy(md2_models[i].filename, filename);
goto modelfound;
}
}
......@@ -1066,15 +1062,11 @@ static boolean HWR_AllowModel(mobj_t *mobj)
static boolean HWR_CanInterpolateModel(mobj_t *mobj, model_t *model)
{
if (cv_glmodelinterpolation.value == 2) // Always interpolate
return true;
return model->interpolate[(mobj->frame & FF_FRAMEMASK)];
}
static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame)
{
if (cv_glmodelinterpolation.value == 2) // Always interpolate
return true;
return spr2frame->interpolate;
}
......@@ -1097,19 +1089,19 @@ static modelspr2frames_t *HWR_GetModelSprite2Frames(md2_t *md2, UINT16 spr2)
return &md2->model->superspr2frames[spr2];
}
if (md2->model->spr2frames)
if (md2->model->spr2frames[spr2].numframes)
return &md2->model->spr2frames[spr2];
return NULL;
}
static modelspr2frames_t *HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT16 spr2, player_t *player)
static UINT16 HWR_GetModelSprite2Num(md2_t *md2, skin_t *skin, UINT16 spr2, player_t *player)
{
UINT16 super = 0;
UINT8 i = 0;
if (!md2 || !md2->model || !skin)
return HWR_GetModelSprite2Frames(md2, 0);
return 0;
while (!HWR_GetModelSprite2Frames(md2, spr2)
&& spr2 != SPR2_STND
......@@ -1149,7 +1141,7 @@ static modelspr2frames_t *HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT16 s
if (i >= 32) // probably an infinite loop...
spr2 = 0;
return HWR_GetModelSprite2Frames(md2, spr2);
return spr2;
}
// Adjust texture coords of model to fit into a patch's max_s and max_t
......@@ -1158,6 +1150,9 @@ static void adjustTextureCoords(model_t *model, patch_t *patch)
int i;
GLPatch_t *gpatch = ((GLPatch_t *)patch->hardware);
if (!gpatch)
return;
for (i = 0; i < model->numMeshes; i++)
{
int j;
......@@ -1194,6 +1189,90 @@ static void adjustTextureCoords(model_t *model, patch_t *patch)
model->max_t = gpatch->max_t;
}
static INT32 GetAnimDuration(mobj_t *mobj) //part of p_mobj's setplayermobjstate logic, used to make sure that anim durations are actually correct when the speed gets adjusted on players
{
player_t *player = mobj->player;
INT32 tics = mobj->state->tics;
if (!(mobj->frame & FF_ANIMATE) && mobj->anim_duration) //set manually by something through lua
return mobj->anim_duration;
if (!player && mobj->type == MT_TAILSOVERLAY && mobj->tracer) //so tails overlays interpolate properly
player = mobj->tracer->player;
if (player)
{
if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE))
tics = 2;
else if (player->powers[pw_tailsfly] && (!(player->mo->eflags & MFE_UNDERWATER) || (mobj->type == MT_PLAYER))) //tailsoverlay does not get adjusted from these rules when underwater
{
if (player->fly1 > 0)
tics = 1;
else if (!(player->mo->eflags & MFE_UNDERWATER))
tics = 2;
else
tics = 4;
}
else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{
fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_FALL)
{
speed = FixedDiv(abs(mobj->momz), mobj->scale);
if (speed < 10<<FRACBITS)
tics = 4;
else if (speed < 20<<FRACBITS)
tics = 3;
else if (speed < 30<<FRACBITS)
tics = 2;
else
tics = 1;
}
else if (player->panim == PA_ABILITY2 && player->charability2 == CA2_SPINDASH)
{
fixed_t step = (player->maxdash - player->mindash)/4;
speed = (player->dashspeed - player->mindash);
if (speed > 3*step)
tics = 1;
else if (speed > step)
tics = 2;
else
tics = 3;
}
else
{
speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_ROLL || player->panim == PA_JUMP)
{
if (speed > 16<<FRACBITS)
tics = 1;
else
tics = 2;
}
else if (P_IsObjectOnGround(mobj) || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) // Only if on the ground or superflying.
{
if (player->panim == PA_WALK)
{
if (speed > 12<<FRACBITS)
tics = 2;
else if (speed > 6<<FRACBITS)
tics = 3;
else
tics = 4;
}
else if ((player->panim == PA_RUN) || (player->panim == PA_DASH))
{
if (speed > 52<<FRACBITS)
tics = 1;
else
tics = 2;
}
}
}
}
}
return tics;
}
//
// HWR_DrawModel
//
......@@ -1267,12 +1346,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
{
patch_t *gpatch, *blendgpatch;
GLPatch_t *hwrPatch = NULL, *hwrBlendPatch = NULL;
float durs = (float)spr->mobj->state->tics;
float durs = GetAnimDuration(spr->mobj);
float tics = (float)spr->mobj->tics;
const boolean papersprite = (R_ThingIsPaperSprite(spr->mobj) && !R_ThingIsFloorSprite(spr->mobj));
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(spr->mobj));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !R_ThingHorizontallyFlipped(spr->mobj));
spritedef_t *sprdef;
UINT16 spr2 = 0;
spriteframe_t *sprframe;
INT32 mod;
interpmobjstate_t interp;
......@@ -1287,8 +1367,13 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
// Apparently people don't like jump frames like that, so back it goes
//if (tics > durs)
//durs = tics;
if (tics > durs)
durs = tics;
// Make linkdraw objects use their tracer's alpha value
fixed_t newalpha = spr->mobj->alpha;
if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer)
newalpha = spr->mobj->tracer->alpha;
INT32 blendmode;
if (spr->mobj->frame & FF_BLENDMASK)
......@@ -1304,6 +1389,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode);
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
// don't forget to enable the depth test because we can't do this
// like before: model polygons are not sorted
......@@ -1442,13 +1529,17 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
frame = (spr->mobj->frame & FF_FRAMEMASK);
if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
spr2frames = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
{
spr2 = HWR_GetModelSprite2Num(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player);
spr2frames = HWR_GetModelSprite2Frames(md2, spr2);
}
if (spr2frames)
{
spritedef_t *defaultdef = P_GetSkinSpritedef(spr->mobj->skin, spr2);
mod = spr2frames->numframes;
#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod
if (mod > (INT32)sprdef->numframes)
mod = sprdef->numframes;
if (mod > (INT32)defaultdef->numframes)
mod = defaultdef->numframes;
#endif
if (!mod)
mod = 1;
......@@ -1596,7 +1687,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, md2->scale * xs, md2->scale * ys, flip, hflip, &Surf);
}
}
return true;
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
// Copyright (C) 2021-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -448,6 +448,101 @@ void HWR_LoadAllCustomShaders(void)
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
}
static const char version_directives[][14] = {
"#version 330\n",
"#version 150\n",
"#version 140\n",
"#version 130\n",
"#version 120\n",
"#version 110\n",
};
static boolean HWR_VersionDirectiveExists(const char* source)
{
return strncmp(source, "#version", 8) == 0;
}
static char* HWR_PrependVersionDirective(const char* source, UINT32 version_index)
{
const UINT32 version_len = sizeof(version_directives[version_index]) - 1;
const UINT32 source_len = strlen(source);
char* result = Z_Malloc(source_len + version_len + 1, PU_STATIC, NULL);
strcpy(result, version_directives[version_index]);
strcpy(result + version_len, source);
return result;
}
static void HWR_ReplaceVersionInplace(char* shader, UINT32 version_index)
{
shader[9] = version_directives[version_index][9];
shader[10] = version_directives[version_index][10];
shader[11] = version_directives[version_index][11];
}
static boolean HWR_CheckVersionDirectives(const char* vert, const char* frag)
{
return HWR_VersionDirectiveExists(vert) && HWR_VersionDirectiveExists(frag);
}
static void HWR_TryToCompileShaderWithImplicitVersion(INT32 shader_index, INT32 shaderxlat_id)
{
char* vert_shader = gl_shaders[shader_index].vertex;
char* frag_shader = gl_shaders[shader_index].fragment;
boolean vert_shader_version_exists = HWR_VersionDirectiveExists(vert_shader);
boolean frag_shader_version_exists = HWR_VersionDirectiveExists(frag_shader);
if(!vert_shader_version_exists) {
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: vertex shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
}
if(!frag_shader_version_exists) {
CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: fragment shader '%s' is missing a #version directive\n", HWR_GetShaderName(shaderxlat_id));
}
// try to compile as is
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled)
return;
// try each version directive
for(UINT32 i = 0; i < sizeof(version_directives) / sizeof(version_directives[0]); ++i) {
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Trying %s\n", version_directives[i]);
if(!vert_shader_version_exists) {
// first time reallocation would have to be made
if(i == 0) {
void* old = (void*)gl_shaders[shader_index].vertex;
vert_shader = gl_shaders[shader_index].vertex = HWR_PrependVersionDirective(vert_shader, i);
Z_Free(old);
} else {
HWR_ReplaceVersionInplace(vert_shader, i);
}
}
if(!frag_shader_version_exists) {
if(i == 0) {
void* old = (void*)gl_shaders[shader_index].fragment;
frag_shader = gl_shaders[shader_index].fragment = HWR_PrependVersionDirective(frag_shader, i);
Z_Free(old);
} else {
HWR_ReplaceVersionInplace(frag_shader, i);
}
}
HWR_CompileShader(shader_index);
if (gl_shaders[shader_index].compiled) {
CONS_Alert(CONS_NOTICE, "HWR_TryToCompileShaderWithImplicitVersion: Compiled with %s\n",
version_directives[i]);
CONS_Alert(CONS_WARNING, "Implicit GLSL version is used. Correct behavior is not guaranteed\n");
return;
}
}
}
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
{
UINT16 lump;
......@@ -610,7 +705,13 @@ skip_field:
gl_shaders[shader_index].fragment = Z_StrDup(gl_shadersources[i].fragment);
if (!gl_shaders[shader_index].vertex)
gl_shaders[shader_index].vertex = Z_StrDup(gl_shadersources[i].vertex);
HWR_CompileShader(shader_index);
if(!HWR_CheckVersionDirectives(gl_shaders[shader_index].vertex, gl_shaders[shader_index].fragment)) {
HWR_TryToCompileShaderWithImplicitVersion(shader_index, i);
} else {
HWR_CompileShader(shader_index);
}
if (!gl_shaders[shader_index].compiled)
CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: A compilation error occured for the %s shader in file %s. See the console messages above for more information.\n", shaderxlat[i].type, wadfiles[wadnum]->filename);
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2021 by Sonic Team Junior.
// Copyright (C) 2021-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......