mirror of
https://github.com/ZDoom/Raze.git
synced 2025-03-22 00:41:05 +00:00
backend update from GZDoom.
This commit is contained in:
parent
b0e8aae59f
commit
3590de2f2a
44 changed files with 645 additions and 168 deletions
|
@ -43,6 +43,8 @@
|
|||
#include "s_soundinternal.h"
|
||||
#include "i_time.h"
|
||||
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
|
||||
class FBurnTexture : public FTexture
|
||||
{
|
||||
TArray<uint32_t> WorkBuffer;
|
||||
|
@ -163,6 +165,8 @@ protected:
|
|||
public:
|
||||
virtual ~Wiper();
|
||||
virtual bool Run(int ticks) = 0;
|
||||
virtual bool RunInterpolated(double ticks) { return true; };
|
||||
virtual bool Interpolatable() { return false; }
|
||||
virtual void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen)
|
||||
{
|
||||
startScreen = startscreen;
|
||||
|
@ -177,9 +181,11 @@ class Wiper_Crossfade : public Wiper
|
|||
{
|
||||
public:
|
||||
bool Run(int ticks) override;
|
||||
bool RunInterpolated(double ticks) override;
|
||||
bool Interpolatable() override { return true; }
|
||||
|
||||
private:
|
||||
int Clock = 0;
|
||||
float Clock = 0;
|
||||
};
|
||||
|
||||
class Wiper_Melt : public Wiper
|
||||
|
@ -187,10 +193,12 @@ class Wiper_Melt : public Wiper
|
|||
public:
|
||||
Wiper_Melt();
|
||||
bool Run(int ticks) override;
|
||||
bool RunInterpolated(double ticks) override;
|
||||
bool Interpolatable() override { return true; }
|
||||
|
||||
private:
|
||||
enum { WIDTH = 320, HEIGHT = 200 };
|
||||
int y[WIDTH];
|
||||
double y[WIDTH];
|
||||
};
|
||||
|
||||
class Wiper_Burn : public Wiper
|
||||
|
@ -268,7 +276,23 @@ bool Wiper_Crossfade::Run(int ticks)
|
|||
Clock += ticks;
|
||||
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
|
||||
return Clock >= 32;
|
||||
return Clock >= 32.;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Crossfade :: Run
|
||||
//
|
||||
// Fades the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Crossfade::RunInterpolated(double ticks)
|
||||
{
|
||||
Clock += ticks;
|
||||
DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE);
|
||||
return Clock >= 32.;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -282,7 +306,7 @@ Wiper_Melt::Wiper_Melt()
|
|||
y[0] = -(M_Random() & 15);
|
||||
for (int i = 1; i < WIDTH; ++i)
|
||||
{
|
||||
y[i] = clamp(y[i-1] + (M_Random() % 3) - 1, -15, 0);
|
||||
y[i] = clamp(y[i-1] + (double)(M_Random() % 3) - 1., -15., 0.);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,25 +331,25 @@ bool Wiper_Melt::Run(int ticks)
|
|||
{
|
||||
if (y[i] < HEIGHT)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
y[i]++;
|
||||
else if (y[i] < 16)
|
||||
y[i] += y[i] + 1;
|
||||
if (y[i] < 0.)
|
||||
y[i] = y[i] + 1.;
|
||||
else if (y[i] < 16.)
|
||||
y[i] += y[i] + 1.;
|
||||
else
|
||||
y[i] = min<int>(y[i] + 8, HEIGHT);
|
||||
y[i] = min<double>(y[i] + 8., HEIGHT);
|
||||
done = false;
|
||||
}
|
||||
if (ticks == 0)
|
||||
{
|
||||
struct {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
double y;
|
||||
} dpt;
|
||||
struct {
|
||||
int32_t left;
|
||||
int32_t top;
|
||||
double top;
|
||||
int32_t right;
|
||||
int32_t bottom;
|
||||
double bottom;
|
||||
} rect;
|
||||
|
||||
// Only draw for the final tick.
|
||||
|
@ -333,7 +357,7 @@ bool Wiper_Melt::Run(int ticks)
|
|||
int w = startScreen->GetTexelWidth();
|
||||
int h = startScreen->GetTexelHeight();
|
||||
dpt.x = i * w / WIDTH;
|
||||
dpt.y = max(0, y[i] * h / HEIGHT);
|
||||
dpt.y = max(0., y[i] * (double)h / (double)HEIGHT);
|
||||
rect.left = dpt.x;
|
||||
rect.top = 0;
|
||||
rect.right = (i + 1) * w / WIDTH;
|
||||
|
@ -348,6 +372,77 @@ bool Wiper_Melt::Run(int ticks)
|
|||
return done;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Wiper_Melt :: RunInterpolated
|
||||
//
|
||||
// Melts the old screen into the new one over 32 ticks (interpolated).
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool Wiper_Melt::RunInterpolated(double ticks)
|
||||
{
|
||||
bool done = false;
|
||||
DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE);
|
||||
|
||||
// Copy the old screen in vertical strips on top of the new one.
|
||||
while (ticks > 0.)
|
||||
{
|
||||
done = true;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (y[i] < (double)HEIGHT)
|
||||
{
|
||||
if (ticks > 0. && ticks < 1.)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
y[i] += ticks;
|
||||
else if (y[i] < 16)
|
||||
y[i] += (y[i] + 1) * ticks;
|
||||
else
|
||||
y[i] = min<double>(y[i] + (8 * ticks), (double)HEIGHT);
|
||||
}
|
||||
else if (y[i] < 0.)
|
||||
y[i] = y[i] + 1.;
|
||||
else if (y[i] < 16.)
|
||||
y[i] += y[i] + 1.;
|
||||
else
|
||||
y[i] = min<double>(y[i] + 8., HEIGHT);
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
ticks -= 1.;
|
||||
}
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
struct {
|
||||
int32_t x;
|
||||
double y;
|
||||
} dpt;
|
||||
struct {
|
||||
int32_t left;
|
||||
double top;
|
||||
int32_t right;
|
||||
double bottom;
|
||||
} rect;
|
||||
|
||||
// Only draw for the final tick.
|
||||
int w = startScreen->GetTexelWidth();
|
||||
double h = startScreen->GetTexelHeight();
|
||||
dpt.x = i * w / WIDTH;
|
||||
dpt.y = max(0., y[i] * (double)h / (double)HEIGHT);
|
||||
rect.left = dpt.x;
|
||||
rect.top = 0;
|
||||
rect.right = (i + 1) * w / WIDTH;
|
||||
rect.bottom = h - dpt.y;
|
||||
if (rect.bottom > rect.top)
|
||||
{
|
||||
DrawTexture(twod, startScreen, 0, dpt.y, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, DTA_Masked, false, TAG_DONE);
|
||||
}
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLFrameBuffer :: Wiper_Burn Constructor
|
||||
|
@ -423,6 +518,7 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops
|
|||
{
|
||||
// wipe update
|
||||
uint64_t wipestart, nowtime, diff;
|
||||
double diff_frac;
|
||||
bool done;
|
||||
|
||||
GSnd->SetSfxPaused(true, 1);
|
||||
|
@ -438,20 +534,34 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops
|
|||
|
||||
do
|
||||
{
|
||||
do
|
||||
if (wiper->Interpolatable() && !cl_capfps)
|
||||
{
|
||||
I_WaitVBL(2);
|
||||
nowtime = I_msTime();
|
||||
diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow.
|
||||
} while (diff < 1);
|
||||
wipestart = nowtime;
|
||||
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||
done = wiper->Run(1);
|
||||
if (overlaydrawer) overlaydrawer();
|
||||
twod->End();
|
||||
screen->Update();
|
||||
twod->OnFrameDone();
|
||||
|
||||
diff_frac = (nowtime - wipestart) * 40. / 1000.; // Using 35 here feels too slow.
|
||||
wipestart = nowtime;
|
||||
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||
done = wiper->RunInterpolated(diff_frac);
|
||||
if (overlaydrawer) overlaydrawer();
|
||||
twod->End();
|
||||
screen->Update();
|
||||
twod->OnFrameDone();
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
I_WaitVBL(2);
|
||||
nowtime = I_msTime();
|
||||
diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow.
|
||||
} while (diff < 1);
|
||||
wipestart = nowtime;
|
||||
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||
done = wiper->Run(1);
|
||||
if (overlaydrawer) overlaydrawer();
|
||||
twod->End();
|
||||
screen->Update();
|
||||
twod->OnFrameDone();
|
||||
}
|
||||
} while (!done);
|
||||
delete wiper;
|
||||
I_FreezeTime(false);
|
||||
|
|
|
@ -61,7 +61,7 @@ enum
|
|||
{
|
||||
DEFAULT_PITCH = 128,
|
||||
};
|
||||
static FRandom pr_soundpitch ("SoundPitch");
|
||||
static FCRandom pr_soundpitch ("SoundPitch");
|
||||
SoundEngine* soundEngine;
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -193,7 +193,7 @@ int FCommandLine::argc ()
|
|||
return _argc;
|
||||
}
|
||||
|
||||
char *FCommandLine::operator[] (int i)
|
||||
const char *FCommandLine::operator[] (int i)
|
||||
{
|
||||
if (_argv == NULL)
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
FCommandLine (const char *commandline, bool no_escapes = false);
|
||||
~FCommandLine ();
|
||||
int argc ();
|
||||
char *operator[] (int i);
|
||||
const char *operator[] (int i);
|
||||
const char *args () { return cmd; }
|
||||
void Shift();
|
||||
|
||||
|
|
|
@ -240,6 +240,16 @@ void* FBaseCVar::GetExtraDataPointer()
|
|||
return m_ExtraDataPointer;
|
||||
}
|
||||
|
||||
void FBaseCVar::SetExtraDataPointer2(void *pointer)
|
||||
{
|
||||
m_ExtraDataPointer2 = pointer;
|
||||
}
|
||||
|
||||
void* FBaseCVar::GetExtraDataPointer2()
|
||||
{
|
||||
return m_ExtraDataPointer2;
|
||||
}
|
||||
|
||||
const char *FBaseCVar::GetHumanString(int precision) const
|
||||
{
|
||||
return GetGenericRep(CVAR_String).String;
|
||||
|
|
|
@ -222,8 +222,10 @@ public:
|
|||
void ClearCallback();
|
||||
|
||||
void SetExtraDataPointer(void *pointer);
|
||||
void SetExtraDataPointer2(void *pointer);
|
||||
|
||||
void* GetExtraDataPointer();
|
||||
void* GetExtraDataPointer2();
|
||||
|
||||
int pnum = -1;
|
||||
FName userinfoName;
|
||||
|
@ -259,7 +261,8 @@ private:
|
|||
static inline bool m_UseCallback = false;
|
||||
static inline bool m_DoNoSet = false;
|
||||
|
||||
void *m_ExtraDataPointer;
|
||||
void *m_ExtraDataPointer = nullptr;
|
||||
void *m_ExtraDataPointer2 = nullptr;
|
||||
|
||||
// These need to go away!
|
||||
friend FString C_GetMassCVarString (uint32_t filter, bool compact);
|
||||
|
@ -275,6 +278,8 @@ private:
|
|||
friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter);
|
||||
friend void C_DeinitConsole();
|
||||
friend void C_ListCVarsWithoutDescription();
|
||||
|
||||
friend class GLDefsParser;
|
||||
};
|
||||
|
||||
// Returns a string with all cvars whose flags match filter. In compact mode,
|
||||
|
|
|
@ -132,7 +132,8 @@ enum
|
|||
PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt
|
||||
PRE_ALLFULL, // Sent from host to an unwanted guest
|
||||
PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt
|
||||
PRE_GO // Sent from host to guest to continue game startup
|
||||
PRE_GO, // Sent from host to guest to continue game startup
|
||||
PRE_IN_PROGRESS, // Sent from host to guest if the game has already started
|
||||
};
|
||||
|
||||
// Set PreGamePacket.fake to this so that the game rejects any pregame packets
|
||||
|
@ -269,6 +270,8 @@ void PacketSend (void)
|
|||
// I_Error ("SendPacket error: %s",strerror(errno));
|
||||
}
|
||||
|
||||
void PreSend(const void* buffer, int bufferlen, const sockaddr_in* to);
|
||||
void SendConAck(int num_connected, int num_needed);
|
||||
|
||||
//
|
||||
// PacketGet
|
||||
|
@ -303,7 +306,7 @@ void PacketGet (void)
|
|||
GetPlayerName(node).GetChars());
|
||||
}
|
||||
|
||||
doomcom.data[0] = 0x80; // NCMD_EXIT
|
||||
doomcom.data[0] = NCMD_EXIT;
|
||||
c = 1;
|
||||
}
|
||||
else if (err != WSAEWOULDBLOCK)
|
||||
|
@ -341,10 +344,11 @@ void PacketGet (void)
|
|||
}
|
||||
else if (c > 0)
|
||||
{ //The packet is not from any in-game node, so we might as well discard it.
|
||||
// Don't show the message for disconnect notifications.
|
||||
if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT)
|
||||
if (TransmitBuffer[0] == PRE_FAKE)
|
||||
{
|
||||
DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
|
||||
// If it's someone waiting in the lobby, let them know the game already started
|
||||
uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS };
|
||||
PreSend(msg, 2, &fromaddress);
|
||||
}
|
||||
doomcom.remotenode = -1;
|
||||
return;
|
||||
|
@ -369,7 +373,22 @@ sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort)
|
|||
int err = WSAGetLastError();
|
||||
if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET))
|
||||
return NULL; // no packet
|
||||
I_Error ("PreGet: %s", neterror ());
|
||||
|
||||
if (doomcom.consoleplayer == 0)
|
||||
{
|
||||
int node = FindNode(&fromaddress);
|
||||
I_NetMessage("Got unexpected disconnect.");
|
||||
doomcom.numnodes--;
|
||||
for (; node < doomcom.numnodes; ++node)
|
||||
sendaddress[node] = sendaddress[node + 1];
|
||||
|
||||
// Let remaining guests know that somebody left.
|
||||
SendConAck(doomcom.numnodes, doomcom.numplayers);
|
||||
}
|
||||
else
|
||||
{
|
||||
I_NetError("The host disbanded the game unexpectedly");
|
||||
}
|
||||
}
|
||||
return &fromaddress;
|
||||
}
|
||||
|
@ -499,7 +518,7 @@ void SendAbort (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void SendConAck (int num_connected, int num_needed)
|
||||
void SendConAck (int num_connected, int num_needed)
|
||||
{
|
||||
PreGamePacket packet;
|
||||
|
||||
|
@ -708,7 +727,7 @@ bool HostGame (int i)
|
|||
|
||||
doomcom.numnodes = 1;
|
||||
|
||||
I_NetInit ("Waiting for players", numplayers);
|
||||
I_NetInit ("Hosting game", numplayers);
|
||||
|
||||
// Wait for numplayers-1 different connections
|
||||
if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers))
|
||||
|
@ -783,13 +802,15 @@ bool Guest_ContactHost (void *userdata)
|
|||
}
|
||||
else if (packet.Message == PRE_DISCONNECT)
|
||||
{
|
||||
doomcom.numnodes = 0;
|
||||
I_FatalError ("The host cancelled the game.");
|
||||
I_NetError("The host cancelled the game.");
|
||||
}
|
||||
else if (packet.Message == PRE_ALLFULL)
|
||||
{
|
||||
doomcom.numnodes = 0;
|
||||
I_FatalError ("The game is full.");
|
||||
I_NetError("The game is full.");
|
||||
}
|
||||
else if (packet.Message == PRE_IN_PROGRESS)
|
||||
{
|
||||
I_NetError("The game was already started.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -850,7 +871,7 @@ bool Guest_WaitForOthers (void *userdata)
|
|||
return true;
|
||||
|
||||
case PRE_DISCONNECT:
|
||||
I_FatalError ("The host cancelled the game.");
|
||||
I_NetError("The host cancelled the game.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -875,6 +896,7 @@ bool JoinGame (int i)
|
|||
BuildAddress (&sendaddress[1], Args->GetArg(i+1));
|
||||
sendplayer[1] = 0;
|
||||
doomcom.numnodes = 2;
|
||||
doomcom.consoleplayer = -1;
|
||||
|
||||
|
||||
// Let host know we are here
|
||||
|
@ -1046,6 +1068,13 @@ void I_NetMessage(const char* text, ...)
|
|||
#endif
|
||||
}
|
||||
|
||||
void I_NetError(const char* error)
|
||||
{
|
||||
doomcom.numnodes = 0;
|
||||
StartWindow->NetClose();
|
||||
I_FatalError("%s", error);
|
||||
}
|
||||
|
||||
// todo: later these must be dispatched by the main menu, not the start screen.
|
||||
void I_NetProgress(int val)
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
int I_InitNetwork (void);
|
||||
void I_NetCmd (void);
|
||||
void I_NetMessage(const char*, ...);
|
||||
void I_NetError(const char* error);
|
||||
void I_NetProgress(int val);
|
||||
void I_NetInit(const char* msg, int num);
|
||||
bool I_NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||
|
|
|
@ -83,7 +83,7 @@ FRandom pr_exrandom("EX_Random");
|
|||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
FRandom M_Random;
|
||||
FCRandom M_Random;
|
||||
|
||||
// Global seed. This is modified predictably to initialize every RNG.
|
||||
uint32_t rngseed;
|
||||
|
@ -126,8 +126,8 @@ CCMD(rngseed)
|
|||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
FRandom *FRandom::RNGList;
|
||||
static TDeletingArray<FRandom *> NewRNGs;
|
||||
FRandom *FRandom::RNGList, *FRandom::CRNGList;
|
||||
static TDeletingArray<FRandom *> NewRNGs, NewCRNGs;
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
||||
|
@ -139,14 +139,22 @@ static TDeletingArray<FRandom *> NewRNGs;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FRandom::FRandom ()
|
||||
: NameCRC (0)
|
||||
FRandom::FRandom (bool client)
|
||||
: NameCRC (0), bClient(client)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
Name = NULL;
|
||||
#endif
|
||||
Next = RNGList;
|
||||
RNGList = this;
|
||||
if (bClient)
|
||||
{
|
||||
Next = CRNGList;
|
||||
CRNGList = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Next = RNGList;
|
||||
RNGList = this;
|
||||
}
|
||||
Init(0);
|
||||
}
|
||||
|
||||
|
@ -158,7 +166,7 @@ FRandom::FRandom ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FRandom::FRandom (const char *name)
|
||||
FRandom::FRandom (const char *name, bool client) : bClient(client)
|
||||
{
|
||||
NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name));
|
||||
#ifndef NDEBUG
|
||||
|
@ -170,7 +178,7 @@ FRandom::FRandom (const char *name)
|
|||
#endif
|
||||
|
||||
// Insert the RNG in the list, sorted by CRC
|
||||
FRandom **prev = &RNGList, *probe = RNGList;
|
||||
FRandom **prev = (bClient ? &CRNGList : &RNGList), * probe = (bClient ? CRNGList : RNGList);
|
||||
|
||||
while (probe != NULL && probe->NameCRC < NameCRC)
|
||||
{
|
||||
|
@ -205,8 +213,8 @@ FRandom::~FRandom ()
|
|||
|
||||
FRandom *last = NULL;
|
||||
|
||||
prev = &RNGList;
|
||||
rng = RNGList;
|
||||
prev = bClient ? &CRNGList : &RNGList;
|
||||
rng = bClient ? CRNGList : RNGList;
|
||||
|
||||
while (rng != NULL && rng != this)
|
||||
{
|
||||
|
@ -237,6 +245,11 @@ void FRandom::StaticClearRandom ()
|
|||
{
|
||||
rng->Init(rngseed);
|
||||
}
|
||||
|
||||
for (FRandom* rng = FRandom::CRNGList; rng != NULL; rng = rng->Next)
|
||||
{
|
||||
rng->Init(rngseed);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -345,15 +358,15 @@ void FRandom::StaticReadRNGState(FSerializer &arc)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FRandom *FRandom::StaticFindRNG (const char *name)
|
||||
FRandom *FRandom::StaticFindRNG (const char *name, bool client)
|
||||
{
|
||||
uint32_t NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name));
|
||||
|
||||
// Use the default RNG if this one happens to have a CRC of 0.
|
||||
if (NameCRC == 0) return &pr_exrandom;
|
||||
if (NameCRC == 0) return client ? &M_Random : &pr_exrandom;
|
||||
|
||||
// Find the RNG in the list, sorted by CRC
|
||||
FRandom **prev = &RNGList, *probe = RNGList;
|
||||
FRandom **prev = (client ? &CRNGList : &RNGList), *probe = (client ? CRNGList : RNGList);
|
||||
|
||||
while (probe != NULL && probe->NameCRC < NameCRC)
|
||||
{
|
||||
|
@ -364,14 +377,32 @@ FRandom *FRandom::StaticFindRNG (const char *name)
|
|||
if (probe == NULL || probe->NameCRC != NameCRC)
|
||||
{
|
||||
// A matching RNG doesn't exist yet so create it.
|
||||
probe = new FRandom(name);
|
||||
probe = new FRandom(name, client);
|
||||
|
||||
// Store the new RNG for destruction when ZDoom quits.
|
||||
NewRNGs.Push(probe);
|
||||
if (client)
|
||||
NewCRNGs.Push(probe);
|
||||
else
|
||||
NewRNGs.Push(probe);
|
||||
}
|
||||
return probe;
|
||||
}
|
||||
|
||||
void FRandom::SaveRNGState(TArray<FRandom>& backups)
|
||||
{
|
||||
for (auto cur = RNGList; cur != nullptr; cur = cur->Next)
|
||||
backups.Push(*cur);
|
||||
}
|
||||
|
||||
void FRandom::RestoreRNGState(TArray<FRandom>& backups)
|
||||
{
|
||||
unsigned int i = 0u;
|
||||
for (auto cur = RNGList; cur != nullptr; cur = cur->Next)
|
||||
*cur = backups[i++];
|
||||
|
||||
backups.Clear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FRandom :: StaticPrintSeeds
|
||||
|
|
|
@ -44,9 +44,9 @@ class FSerializer;
|
|||
class FRandom : public SFMTObj
|
||||
{
|
||||
public:
|
||||
FRandom ();
|
||||
FRandom (const char *name);
|
||||
~FRandom ();
|
||||
FRandom() : FRandom(false) {}
|
||||
FRandom(const char* name) : FRandom(name, false) {}
|
||||
~FRandom();
|
||||
|
||||
int Seed() const
|
||||
{
|
||||
|
@ -170,20 +170,34 @@ public:
|
|||
static void StaticClearRandom ();
|
||||
static void StaticReadRNGState (FSerializer &arc);
|
||||
static void StaticWriteRNGState (FSerializer &file);
|
||||
static FRandom *StaticFindRNG(const char *name);
|
||||
static FRandom *StaticFindRNG(const char *name, bool client);
|
||||
static void SaveRNGState(TArray<FRandom>& backups);
|
||||
static void RestoreRNGState(TArray<FRandom>& backups);
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void StaticPrintSeeds ();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
FRandom(bool client);
|
||||
FRandom(const char* name, bool client);
|
||||
|
||||
private:
|
||||
#ifndef NDEBUG
|
||||
const char *Name;
|
||||
#endif
|
||||
FRandom *Next;
|
||||
uint32_t NameCRC;
|
||||
bool bClient;
|
||||
|
||||
static FRandom *RNGList;
|
||||
static FRandom *RNGList, *CRNGList;
|
||||
};
|
||||
|
||||
class FCRandom : public FRandom
|
||||
{
|
||||
public:
|
||||
FCRandom() : FRandom(true) {}
|
||||
FCRandom(const char* name) : FRandom(name, true) {}
|
||||
};
|
||||
|
||||
extern uint32_t rngseed; // The starting seed (not part of state)
|
||||
|
@ -193,6 +207,6 @@ extern bool use_staticrng;
|
|||
|
||||
|
||||
// M_Random can be used for numbers that do not affect gameplay
|
||||
extern FRandom M_Random;
|
||||
extern FCRandom M_Random;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,12 @@ xx(Random2)
|
|||
xx(RandomPick)
|
||||
xx(FRandomPick)
|
||||
xx(SetRandomSeed)
|
||||
xx(CRandom)
|
||||
xx(CFRandom)
|
||||
xx(CRandom2)
|
||||
xx(CRandomPick)
|
||||
xx(CFRandomPick)
|
||||
xx(CSetRandomSeed)
|
||||
xx(BuiltinRandomSeed)
|
||||
xx(BuiltinNew)
|
||||
xx(GetClass)
|
||||
|
@ -190,9 +196,15 @@ xx(TranslationID)
|
|||
xx(Overlay)
|
||||
xx(IsValid)
|
||||
xx(IsNull)
|
||||
xx(IsEmpty)
|
||||
xx(IsFixed)
|
||||
xx(IsKeep)
|
||||
xx(Exists)
|
||||
xx(SetInvalid)
|
||||
xx(SetNull)
|
||||
xx(SetEmpty)
|
||||
xx(SetFixed)
|
||||
xx(SetKeep)
|
||||
xx(Key)
|
||||
xx(Index)
|
||||
xx(Find)
|
||||
|
|
|
@ -252,7 +252,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &
|
|||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnim &ao, ModelAnim *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def);
|
||||
FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
||||
FSerializer &Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
||||
|
||||
void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public:
|
|||
virtual void NetInit(const char *message, int num_players) {}
|
||||
virtual void NetProgress(int count) {}
|
||||
virtual void NetDone() {}
|
||||
virtual void NetClose() {}
|
||||
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; }
|
||||
virtual void AppendStatusLine(const char* status) {}
|
||||
virtual void LoadingStatus(const char* message, int colors) {}
|
||||
|
@ -74,6 +75,7 @@ public:
|
|||
void NetProgress(int count);
|
||||
void NetMessage(const char* format, ...); // cover for printf
|
||||
void NetDone();
|
||||
void NetClose();
|
||||
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||
protected:
|
||||
int NetMaxPos, NetCurPos;
|
||||
|
|
|
@ -42,8 +42,8 @@ public:
|
|||
void SetMaxIwadNum(int x) { MaxIwadIndex = x; }
|
||||
|
||||
bool InitSingleFile(const char *filename, FileSystemMessageFunc Printf = nullptr);
|
||||
bool InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr);
|
||||
void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile);
|
||||
bool InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter = nullptr, FileSystemMessageFunc Printf = nullptr, bool allowduplicates = false);
|
||||
void AddFile (const char *filename, FileReader *wadinfo, LumpFilterInfo* filter, FileSystemMessageFunc Printf);
|
||||
int CheckIfResourceFileLoaded (const char *name) noexcept;
|
||||
void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ bool FileSystem::InitSingleFile(const char* filename, FileSystemMessageFunc Prin
|
|||
return InitMultipleFiles(filenames, nullptr, Printf);
|
||||
}
|
||||
|
||||
bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates, FILE* hashfile)
|
||||
bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFilterInfo* filter, FileSystemMessageFunc Printf, bool allowduplicates)
|
||||
{
|
||||
int numfiles;
|
||||
|
||||
|
@ -269,7 +269,7 @@ bool FileSystem::InitMultipleFiles (std::vector<std::string>& filenames, LumpFil
|
|||
|
||||
for(size_t i=0;i<filenames.size(); i++)
|
||||
{
|
||||
AddFile(filenames[i].c_str(), nullptr, filter, Printf, hashfile);
|
||||
AddFile(filenames[i].c_str(), nullptr, filter, Printf);
|
||||
|
||||
if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/");
|
||||
std::string path = "filter/%s";
|
||||
|
@ -327,7 +327,7 @@ int FileSystem::AddFromBuffer(const char* name, char* data, int size, int id, in
|
|||
// [RH] Removed reload hack
|
||||
//==========================================================================
|
||||
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf, FILE* hashfile)
|
||||
void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInfo* filter, FileSystemMessageFunc Printf)
|
||||
{
|
||||
int startlump;
|
||||
bool isdir = false;
|
||||
|
@ -396,49 +396,10 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, LumpFilterInf
|
|||
path += ':';
|
||||
path += resfile->getName(i);
|
||||
auto embedded = resfile->GetEntryReader(i, READER_CACHED);
|
||||
AddFile(path.c_str(), &embedded, filter, Printf, hashfile);
|
||||
AddFile(path.c_str(), &embedded, filter, Printf);
|
||||
}
|
||||
}
|
||||
|
||||
if (hashfile)
|
||||
{
|
||||
uint8_t cksum[16];
|
||||
char cksumout[33];
|
||||
memset(cksumout, 0, sizeof(cksumout));
|
||||
|
||||
if (filereader.isOpen())
|
||||
{
|
||||
filereader.Seek(0, FileReader::SeekSet);
|
||||
md5Hash(filereader, cksum);
|
||||
|
||||
for (size_t j = 0; j < sizeof(cksum); ++j)
|
||||
{
|
||||
snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]);
|
||||
}
|
||||
|
||||
fprintf(hashfile, "file: %s, hash: %s, size: %td\n", filename, cksumout, filereader.GetLength());
|
||||
}
|
||||
|
||||
else
|
||||
fprintf(hashfile, "file: %s, Directory structure\n", filename);
|
||||
|
||||
for (int i = 0; i < resfile->EntryCount(); i++)
|
||||
{
|
||||
int flags = resfile->GetEntryFlags(i);
|
||||
if (!(flags & RESFF_EMBEDDED))
|
||||
{
|
||||
auto reader = resfile->GetEntryReader(i, READER_SHARED, 0);
|
||||
md5Hash(filereader, cksum);
|
||||
|
||||
for (size_t j = 0; j < sizeof(cksum); ++j)
|
||||
{
|
||||
snprintf(cksumout + (j * 2), 3, "%02X", cksum[j]);
|
||||
}
|
||||
|
||||
fprintf(hashfile, "file: %s, lump: %s, hash: %s, size: %zu\n", filename, resfile->getName(i), cksumout, (uint64_t)resfile->Length(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
|
||||
CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
FString SavegameFolder;
|
||||
CVAR(Int, save_sort_order, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -136,7 +137,19 @@ int FSavegameManagerBase::InsertSaveNode(FSaveGameNode *node)
|
|||
//if (SaveGames[0] == &NewSaveNode) i++; // To not insert above the "new savegame" dummy entry.
|
||||
for (; i < SaveGames.Size(); i++)
|
||||
{
|
||||
if (SaveGames[i]->bOldVersion || node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0)
|
||||
bool sortcmp = false;
|
||||
switch(save_sort_order)
|
||||
{
|
||||
case 1:
|
||||
sortcmp = node->CreationTime.CompareNoCase(SaveGames[i]->CreationTime) > 0;
|
||||
break;
|
||||
default:
|
||||
case 0:
|
||||
sortcmp = node->SaveTitle.CompareNoCase(SaveGames[i]->SaveTitle) <= 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SaveGames[i]->bOldVersion || sortcmp)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -170,12 +183,18 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit
|
|||
#endif
|
||||
{
|
||||
node->SaveTitle = title;
|
||||
node->CreationTime = myasctime();
|
||||
node->bOldVersion = false;
|
||||
node->bMissingWads = false;
|
||||
|
||||
// refresh my game's position on the list (needed if time/name changed)
|
||||
SaveGames.Delete(i);
|
||||
int index = InsertSaveNode(node);
|
||||
|
||||
if (okForQuicksave)
|
||||
{
|
||||
if (quickSaveSlot == nullptr || quickSaveSlot == (FSaveGameNode*)1 || forceQuicksave) quickSaveSlot = node;
|
||||
LastAccessed = LastSaved = i;
|
||||
LastAccessed = LastSaved = index;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -183,6 +202,7 @@ void FSavegameManagerBase::NotifyNewSave(const FString &file, const FString &tit
|
|||
|
||||
auto node = new FSaveGameNode;
|
||||
node->SaveTitle = title;
|
||||
node->CreationTime = myasctime();
|
||||
node->Filename = file;
|
||||
node->bOldVersion = false;
|
||||
node->bMissingWads = false;
|
||||
|
|
|
@ -11,6 +11,7 @@ struct FSaveGameNode
|
|||
{
|
||||
FString SaveTitle;
|
||||
FString Filename;
|
||||
FString CreationTime;
|
||||
bool bOldVersion = false;
|
||||
bool bMissingWads = false;
|
||||
bool bNoDelete = false;
|
||||
|
|
|
@ -66,6 +66,7 @@ public:
|
|||
void NetInit(const char* message, int playerCount);
|
||||
void NetProgress(int count);
|
||||
void NetDone();
|
||||
void NetClose();
|
||||
|
||||
private:
|
||||
NSWindow* m_window;
|
||||
|
|
|
@ -531,3 +531,8 @@ void FConsoleWindow::NetDone()
|
|||
m_netAbortButton = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void FConsoleWindow::NetClose()
|
||||
{
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
|
|
@ -110,6 +110,11 @@ void FBasicStartupScreen::NetDone()
|
|||
FConsoleWindow::GetInstance().NetDone();
|
||||
}
|
||||
|
||||
void FBasicStartupScreen::NetClose()
|
||||
{
|
||||
FConsoleWindow::GetInstance().NetClose();
|
||||
}
|
||||
|
||||
bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData)
|
||||
{
|
||||
while (true)
|
||||
|
|
|
@ -54,17 +54,6 @@ bool I_WriteIniFailed (const char* filename);
|
|||
class FGameTexture;
|
||||
bool I_SetCursor(FGameTexture *);
|
||||
|
||||
static inline char *strlwr(char *str)
|
||||
{
|
||||
char *ptr = str;
|
||||
while(*ptr)
|
||||
{
|
||||
*ptr = tolower(*ptr);
|
||||
++ptr;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
inline int I_GetNumaNodeCount() { return 1; }
|
||||
inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max<int>(std::thread::hardware_concurrency(), 1); }
|
||||
inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { }
|
||||
|
|
|
@ -308,7 +308,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int&
|
|||
#ifdef __APPLE__
|
||||
return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad);
|
||||
#else
|
||||
return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, extraArgs);
|
||||
return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ class FTTYStartupScreen : public FStartupScreen
|
|||
void NetInit(const char *message, int num_players);
|
||||
void NetProgress(int count);
|
||||
void NetDone();
|
||||
void NetClose();
|
||||
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
|
||||
protected:
|
||||
bool DidNetInit;
|
||||
|
@ -237,6 +238,11 @@ void FTTYStartupScreen::NetProgress(int count)
|
|||
}
|
||||
}
|
||||
|
||||
void FTTYStartupScreen::NetClose()
|
||||
{
|
||||
// TODO: Implement this
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FTTYStartupScreen :: NetLoop
|
||||
|
|
|
@ -134,6 +134,39 @@ void I_SetIWADInfo()
|
|||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// isConsoleApp()
|
||||
//
|
||||
// runtime detection to detect if this is a console subsystem app.
|
||||
//
|
||||
// the reason for doing this is because it is possible to edit a binary directly and change its subsystem
|
||||
// type via hexedit so in order to gain flexibility it makes no sense to just compile out the unused code.
|
||||
//
|
||||
// we may plan to publish tools to allow users to do this manually on their own.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool isConsoleApp()
|
||||
{
|
||||
static bool alreadychecked = false;
|
||||
static bool returnvalue;
|
||||
|
||||
if (!alreadychecked)
|
||||
{
|
||||
DWORD pids[2];
|
||||
DWORD num_pids = GetConsoleProcessList(pids, 2);
|
||||
bool win32con_is_exclusive = (num_pids <= 1);
|
||||
|
||||
returnvalue = ((GetConsoleWindow() != NULL && !win32con_is_exclusive) || (GetStdHandle(STD_OUTPUT_HANDLE) != NULL));
|
||||
alreadychecked = true;
|
||||
}
|
||||
|
||||
//printf("isConsoleApp is %i\n", returnvalue);
|
||||
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DoMain
|
||||
|
@ -158,7 +191,22 @@ int DoMain (HINSTANCE hInstance)
|
|||
Args->AppendArg(FString(wargv[i]));
|
||||
}
|
||||
|
||||
if (Args->CheckParm("-stdout") || Args->CheckParm("-norun"))
|
||||
if (isConsoleApp())
|
||||
{
|
||||
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
SetConsoleCP(CP_UTF8);
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
|
||||
DWORD mode;
|
||||
|
||||
if (GetConsoleMode(StdOut, &mode))
|
||||
{
|
||||
if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING))
|
||||
FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting.
|
||||
}
|
||||
}
|
||||
else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun"))
|
||||
{
|
||||
// As a GUI application, we don't normally get a console when we start.
|
||||
// If we were run from the shell and are on XP+, we can attach to its
|
||||
|
@ -475,6 +523,11 @@ CUSTOM_CVAR(Bool, disablecrashlog, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int wmain()
|
||||
{
|
||||
return wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), SW_SHOW);
|
||||
}
|
||||
|
||||
int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int nCmdShow)
|
||||
{
|
||||
g_hInst = hInstance;
|
||||
|
|
|
@ -128,6 +128,11 @@ void MainWindow::HideNetStartPane()
|
|||
NetStartWindow::HideNetStartPane();
|
||||
}
|
||||
|
||||
void MainWindow::CloseNetStartPane()
|
||||
{
|
||||
NetStartWindow::NetClose();
|
||||
}
|
||||
|
||||
void MainWindow::SetNetStartProgress(int pos)
|
||||
{
|
||||
NetStartWindow::SetNetStartProgress(pos);
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
void SetNetStartProgress(int pos);
|
||||
bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata);
|
||||
void HideNetStartPane();
|
||||
void CloseNetStartPane();
|
||||
|
||||
void SetWindowTitle(const char* caption);
|
||||
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
void DestroyCustomCursor();
|
||||
bool isConsoleApp();
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
|
@ -306,6 +307,7 @@ static void PrintToStdOut(const char *cpt, HANDLE StdOut)
|
|||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD bytes_written;
|
||||
WriteFile(StdOut, printData.GetChars(), (DWORD)printData.Len(), &bytes_written, NULL);
|
||||
if (terminal)
|
||||
|
@ -370,7 +372,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int&
|
|||
}
|
||||
if (showwin || (vkey != 0 && GetAsyncKeyState(vkey)))
|
||||
{
|
||||
return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, extraArgs);
|
||||
return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs);
|
||||
}
|
||||
return defaultiwad;
|
||||
}
|
||||
|
|
|
@ -201,3 +201,8 @@ bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata
|
|||
{
|
||||
return mainwindow.RunMessageLoop(timer_callback, userdata);
|
||||
}
|
||||
|
||||
void FBasicStartupScreen::NetClose()
|
||||
{
|
||||
mainwindow.CloseNetStartPane();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
//===========================================================================
|
||||
|
||||
CVAR(Bool, gl_aalines, false, CVAR_ARCHIVE)
|
||||
CVAR(Bool, hw_2dmip, true, CVAR_ARCHIVE)
|
||||
|
||||
void Draw2D(F2DDrawer* drawer, FRenderState& state)
|
||||
{
|
||||
|
@ -71,6 +72,8 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int
|
|||
state.EnableMultisampling(false);
|
||||
state.EnableLineSmooth(gl_aalines);
|
||||
|
||||
bool cache_hw_2dmip = hw_2dmip; // cache cvar lookup so it's not done in a loop
|
||||
|
||||
auto &vertices = drawer->mVertices;
|
||||
auto &indices = drawer->mIndices;
|
||||
auto &commands = drawer->mData;
|
||||
|
@ -180,7 +183,7 @@ void Draw2D(F2DDrawer* drawer, FRenderState& state, int x, int y, int width, int
|
|||
auto flags = cmd.mTexture->GetUseType() >= ETextureType::Special? UF_None : cmd.mTexture->GetUseType() == ETextureType::FontChar? UF_Font : UF_Texture;
|
||||
|
||||
auto scaleflags = cmd.mFlags & F2DDrawer::DTF_Indexed ? CTF_Indexed : 0;
|
||||
state.SetMaterial(cmd.mTexture, flags, scaleflags, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : CLAMP_XY_NOMIP, cmd.mTranslationId, -1);
|
||||
state.SetMaterial(cmd.mTexture, flags, scaleflags, cmd.mFlags & F2DDrawer::DTF_Wrap ? CLAMP_NONE : (cache_hw_2dmip ? CLAMP_XY : CLAMP_XY_NOMIP), cmd.mTranslationId, -1);
|
||||
state.EnableTexture(true);
|
||||
|
||||
// Canvas textures are stored upside down
|
||||
|
|
|
@ -947,6 +947,7 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d
|
|||
case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break;
|
||||
case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break;
|
||||
case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break;
|
||||
case PostProcessUniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -1085,6 +1086,13 @@ void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate)
|
|||
fValues[2] = (float)pair->Value.Values[2];
|
||||
memcpy(dst, fValues, sizeof(float) * 3);
|
||||
break;
|
||||
case PostProcessUniformType::Vec4:
|
||||
fValues[0] = (float)pair->Value.Values[0];
|
||||
fValues[1] = (float)pair->Value.Values[1];
|
||||
fValues[2] = (float)pair->Value.Values[2];
|
||||
fValues[3] = (float)pair->Value.Values[3];
|
||||
memcpy(dst, fValues, sizeof(float) * 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -116,6 +116,31 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PPShader, SetUniform4f)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_STRING(shaderName);
|
||||
PARAM_STRING(uniformName);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
PARAM_FLOAT(z);
|
||||
PARAM_FLOAT(w);
|
||||
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = z;
|
||||
vec4[3] = w;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
|
|
@ -9,7 +9,8 @@ enum class PostProcessUniformType
|
|||
Int,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3
|
||||
Vec3,
|
||||
Vec4
|
||||
};
|
||||
|
||||
struct PostProcessUniformValue
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*---------------------------------------------------------------------------
|
||||
**
|
||||
** Copyright(C) 2017 Magnus Norddahl
|
||||
** Copyright(C) 2017-2020 Rachael Alexanderson
|
||||
** Copyright(C) 2017-2024 Rachael Alexanderson
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
|
@ -98,6 +98,33 @@ namespace
|
|||
{
|
||||
return (uint32_t)((float)inheight * v_MinimumToFill(inwidth, inheight));
|
||||
}
|
||||
|
||||
float v_MinimumToFill2(uint32_t inwidth, uint32_t inheight)
|
||||
{
|
||||
// sx = screen x dimension, sy = same for y
|
||||
float sx = (float)inwidth * 1.2f, sy = (float)inheight;
|
||||
static float lastsx = 0., lastsy = 0., result = 0.;
|
||||
if (lastsx != sx || lastsy != sy)
|
||||
{
|
||||
if (sx <= 0. || sy <= 0.)
|
||||
return 1.; // prevent x/0 error
|
||||
// set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible
|
||||
float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2f / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy;
|
||||
result = (ssx < ssy) ? ssy : ssx;
|
||||
lastsx = sx;
|
||||
lastsy = sy;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
inline uint32_t v_mfillX2(uint32_t inwidth, uint32_t inheight)
|
||||
{
|
||||
return (uint32_t)((float)inwidth * v_MinimumToFill2(inwidth, inheight) * 1.2);
|
||||
}
|
||||
inline uint32_t v_mfillY2(uint32_t inwidth, uint32_t inheight)
|
||||
{
|
||||
return (uint32_t)((float)inheight * v_MinimumToFill2(inwidth, inheight));
|
||||
}
|
||||
|
||||
inline void refresh_minimums()
|
||||
{
|
||||
// specialUI is tracking a state where high-res console fonts are actually required, and
|
||||
|
@ -128,16 +155,17 @@ namespace
|
|||
|
||||
// the odd formatting of this struct definition is meant to resemble a table header. set your tab stops to 4 when editing this file.
|
||||
struct v_ScaleTable
|
||||
{ bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; };
|
||||
{ bool isValid; uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height); uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height); float pixelAspect; bool isCustom; };
|
||||
v_ScaleTable vScaleTable[] =
|
||||
{
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, 1.0f, false }, // 0 - Native
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, 1.0f, false }, // 6 - Minimum Scale to Fill Entire Screen
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, 1.2f, false }, // 2 - 640x400 (formerly 320x200)
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, 1.2f, false }, // 3 - 960x600 (formerly 640x400)
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 7 - 320x200
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, 1.0f, false }, // 0 - Native
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, 1.0f, false }, // 1 - Minimum Scale to Fill Entire Screen
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, 1.2f, false }, // 2 - 640x400 (formerly 320x200)
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, 1.2f, false }, // 3 - 960x600 (formerly 640x400)
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200
|
||||
{ true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2f; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2)
|
||||
};
|
||||
bool isOutOfBounds(int x)
|
||||
{
|
||||
|
@ -248,7 +276,7 @@ CCMD (vid_scaletoheight)
|
|||
}
|
||||
}
|
||||
|
||||
inline bool atob(char* I)
|
||||
inline bool atob(const char* I)
|
||||
{
|
||||
if (stricmp (I, "true") == 0 || stricmp (I, "1") == 0)
|
||||
return true;
|
||||
|
|
|
@ -1842,6 +1842,12 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
|||
{
|
||||
goto basereturn;
|
||||
}
|
||||
else if (ctx.Version >= MakeVersion(4, 15, 0) && basex->ValueType == TypeNullPtr && (ValueType == TypeSpriteID || ValueType == TypeTextureID || ValueType == TypeTranslationID))
|
||||
{
|
||||
delete basex;
|
||||
basex = new FxConstant(0, ScriptPosition);
|
||||
goto basereturn;
|
||||
}
|
||||
else if (IsFloat())
|
||||
{
|
||||
FxExpression *x = new FxFloatCast(basex);
|
||||
|
@ -8268,8 +8274,12 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction
|
|||
FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &&args, const FScriptPosition &pos)
|
||||
: FxExpression(EFX_FunctionCall, pos)
|
||||
{
|
||||
const bool isClient = methodname == NAME_CRandom || methodname == NAME_CFRandom
|
||||
|| methodname == NAME_CRandomPick || methodname == NAME_CFRandomPick
|
||||
|| methodname == NAME_CRandom2 || methodname == NAME_CSetRandomSeed;
|
||||
|
||||
MethodName = methodname;
|
||||
RNG = &pr_exrandom;
|
||||
RNG = isClient ? &M_Random : &pr_exrandom;
|
||||
ArgList = std::move(args);
|
||||
if (rngname != NAME_None)
|
||||
{
|
||||
|
@ -8281,7 +8291,16 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &&
|
|||
case NAME_FRandomPick:
|
||||
case NAME_Random2:
|
||||
case NAME_SetRandomSeed:
|
||||
RNG = FRandom::StaticFindRNG(rngname.GetChars());
|
||||
RNG = FRandom::StaticFindRNG(rngname.GetChars(), false);
|
||||
break;
|
||||
|
||||
case NAME_CRandom:
|
||||
case NAME_CFRandom:
|
||||
case NAME_CRandomPick:
|
||||
case NAME_CFRandomPick:
|
||||
case NAME_CRandom2:
|
||||
case NAME_CSetRandomSeed:
|
||||
RNG = FRandom::StaticFindRNG(rngname.GetChars(), true);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -8498,6 +8517,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
case NAME_State:
|
||||
case NAME_SpriteID:
|
||||
case NAME_TextureID:
|
||||
case NAME_TranslationID:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition))
|
||||
{
|
||||
PType *type =
|
||||
|
@ -8547,13 +8567,22 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
break;
|
||||
|
||||
case NAME_CSetRandomSeed:
|
||||
if (CheckArgSize(NAME_CRandom, ArgList, 1, 1, ScriptPosition))
|
||||
{
|
||||
func = new FxRandomSeed(RNG, ArgList[0], ScriptPosition, ctx.FromDecorate);
|
||||
ArgList[0] = nullptr;
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Random:
|
||||
case NAME_CRandom:
|
||||
// allow calling Random without arguments to default to (0, 255)
|
||||
if (ArgList.Size() == 0)
|
||||
{
|
||||
func = new FxRandom(RNG, new FxConstant(0, ScriptPosition), new FxConstant(255, ScriptPosition), ScriptPosition, ctx.FromDecorate);
|
||||
}
|
||||
else if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition))
|
||||
else if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition))
|
||||
{
|
||||
func = new FxRandom(RNG, ArgList[0], ArgList[1], ScriptPosition, ctx.FromDecorate);
|
||||
ArgList[0] = ArgList[1] = nullptr;
|
||||
|
@ -8561,7 +8590,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
break;
|
||||
|
||||
case NAME_FRandom:
|
||||
if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition))
|
||||
case NAME_CFRandom:
|
||||
if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition))
|
||||
{
|
||||
func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition);
|
||||
ArgList[0] = ArgList[1] = nullptr;
|
||||
|
@ -8570,14 +8600,17 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx)
|
|||
|
||||
case NAME_RandomPick:
|
||||
case NAME_FRandomPick:
|
||||
case NAME_CRandomPick:
|
||||
case NAME_CFRandomPick:
|
||||
if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition))
|
||||
{
|
||||
func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate);
|
||||
func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick || MethodName == NAME_CFRandomPick, ScriptPosition, ctx.FromDecorate);
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Random2:
|
||||
if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition))
|
||||
case NAME_CRandom2:
|
||||
if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition))
|
||||
{
|
||||
func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate);
|
||||
if (ArgList.Size() > 0) ArgList[0] = nullptr;
|
||||
|
@ -8850,7 +8883,24 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
return Self;
|
||||
}
|
||||
}
|
||||
else if (Self->ValueType == TypeTextureID)
|
||||
else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSound && MethodName == NAME_IsValid)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Self->ValueType = TypeSInt32; // treat as integer
|
||||
FxExpression *x = new FxCompareRel('>', Self, new FxConstant(0, ScriptPosition));
|
||||
Self = nullptr;
|
||||
SAFE_RESOLVE(x, ctx);
|
||||
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
else if (Self->ValueType == TypeTextureID || (ctx.Version >= MakeVersion(4, 15, 0) && (Self->ValueType == TypeTranslationID)))
|
||||
{
|
||||
if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull)
|
||||
{
|
||||
|
@ -8893,6 +8943,67 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
}
|
||||
|
||||
else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSpriteID)
|
||||
{
|
||||
if (MethodName == NAME_IsValid || MethodName == NAME_IsEmpty || MethodName == NAME_IsFixed || MethodName == NAME_IsKeep
|
||||
|| MethodName == NAME_Exists
|
||||
|| MethodName == NAME_SetInvalid || MethodName == NAME_SetEmpty || MethodName == NAME_SetFixed || MethodName == NAME_SetKeep)
|
||||
{
|
||||
if (ArgList.Size() > 0)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "Too many parameters in call to %s", MethodName.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
// No need to create a dedicated node here, all builtins map directly to trivial operations.
|
||||
Self->ValueType = TypeSInt32; // all builtins treat the texture index as integer.
|
||||
FxExpression *x = nullptr;
|
||||
switch (MethodName.GetIndex())
|
||||
{
|
||||
case NAME_IsValid:
|
||||
x = new FxCompareRel(TK_Geq, Self, new FxConstant(0, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_IsEmpty: // TNT1
|
||||
x = new FxCompareEq(TK_Eq, Self, new FxConstant(0, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_IsFixed: // "----"
|
||||
x = new FxCompareEq(TK_Eq, Self, new FxConstant(1, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_IsKeep: // "####"
|
||||
x = new FxCompareEq(TK_Eq, Self, new FxConstant(2, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_Exists:
|
||||
x = new FxCompareRel(TK_Geq, Self, new FxConstant(3, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_SetInvalid:
|
||||
x = new FxAssign(Self, new FxConstant(-1, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_SetEmpty: // TNT1
|
||||
x = new FxAssign(Self, new FxConstant(0, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_SetFixed: // "----"
|
||||
x = new FxAssign(Self, new FxConstant(1, ScriptPosition));
|
||||
break;
|
||||
|
||||
case NAME_SetKeep: // "####"
|
||||
x = new FxAssign(Self, new FxConstant(2, ScriptPosition));
|
||||
break;
|
||||
}
|
||||
Self = nullptr;
|
||||
SAFE_RESOLVE(x, ctx);
|
||||
if (MethodName == NAME_SetInvalid || MethodName == NAME_SetEmpty || MethodName == NAME_SetFixed || MethodName == NAME_SetKeep) x->ValueType = TypeVoid; // override the default type of the assignment operator.
|
||||
delete this;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
else if (Self->IsVector())
|
||||
{
|
||||
// handle builtins: Vectors got 5.
|
||||
|
@ -8967,7 +9078,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (PFunction **Override; ctx.Version >= MakeVersion(4, 11, 0) && (Override = static_cast<PDynArray*>(Self->ValueType)->FnOverrides.CheckKey(MethodName)))
|
||||
if (PFunction **Override; (Override = static_cast<PDynArray*>(Self->ValueType)->FnOverrides.CheckKey(MethodName)))
|
||||
{
|
||||
afd_override = *Override;
|
||||
}
|
||||
|
@ -12640,6 +12751,15 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx)
|
|||
if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto)
|
||||
{
|
||||
auto sfunc = static_cast<VMScriptFunction *>(ctx.Function->Variants[0].Implementation);
|
||||
|
||||
const unsigned MAX_STACK_ALLOC = 512 * 1024; // Windows stack is 1 MB, but we cannot go up there without problems
|
||||
if (uint64_t(ValueType->Size) + uint64_t(sfunc->ExtraSpace) > MAX_STACK_ALLOC)
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "%s exceeds max. allowed size of 512kb for local variables at variable %s", sfunc->Name.GetChars(), Name.GetChars());
|
||||
delete this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StackOffset = sfunc->AllocExtraStack(ValueType);
|
||||
|
||||
if (Init != nullptr)
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "filesystem.h"
|
||||
|
||||
CVAR(Bool, strictdecorate, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE)
|
||||
CVAR(Bool, warningstoerrors, false, CVAR_GLOBALCONFIG | CVAR_ARCHIVE)
|
||||
|
||||
EXTERN_CVAR(Bool, vm_jit)
|
||||
EXTERN_CVAR(Bool, vm_jit_aot)
|
||||
|
@ -879,10 +880,18 @@ void FFunctionBuildList::Build()
|
|||
{
|
||||
if (!item.Code->CheckReturn())
|
||||
{
|
||||
auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition);
|
||||
newcmpd->Add(item.Code);
|
||||
newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition));
|
||||
item.Code = newcmpd->Resolve(ctx);
|
||||
if (ctx.ReturnProto == nullptr || !ctx.ReturnProto->ReturnTypes.Size())
|
||||
{
|
||||
auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition);
|
||||
newcmpd->Add(item.Code);
|
||||
newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition));
|
||||
item.Code = newcmpd->Resolve(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Code->ScriptPosition.Message(MSG_ERROR, "Missing return statement in %s", item.PrintableName.GetChars());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
item.Proto = ctx.ReturnProto;
|
||||
|
|
|
@ -2286,6 +2286,11 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize,
|
|||
Error(arraysize, "Array size must be positive");
|
||||
return TypeError;
|
||||
}
|
||||
if (uint64_t(size) * baseType->Size > 0x7fffffff)
|
||||
{
|
||||
Error(arraysize, "Array size overflow. Total size must be less than 2GB");
|
||||
return TypeError;
|
||||
}
|
||||
baseType = NewArray(baseType, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -1706,7 +1706,7 @@ DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptError)
|
|||
{
|
||||
PARAM_SELF_PROLOGUE(DScriptScanner);
|
||||
|
||||
FString s = FStringFormat(VM_ARGS_NAMES);
|
||||
FString s = FStringFormat(VM_ARGS_NAMES, 1);
|
||||
self->wrapped.ScriptError("%s", s.GetChars());
|
||||
return 0;
|
||||
}
|
||||
|
@ -1715,7 +1715,7 @@ DEFINE_ACTION_FUNCTION(DScriptScanner, ScriptMessage)
|
|||
{
|
||||
PARAM_SELF_PROLOGUE(DScriptScanner);
|
||||
|
||||
FString s = FStringFormat(VM_ARGS_NAMES);
|
||||
FString s = FStringFormat(VM_ARGS_NAMES, 1);
|
||||
self->wrapped.ScriptMessage("%s", s.GetChars());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ enum EGameTexFlags
|
|||
GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font.
|
||||
GTexf_NoTrim = 1024, // Don't perform trimming on this texture.
|
||||
GTexf_Seen = 2048, // Set to true when the texture is being used for rendering. Must be cleared manually if the check is needed.
|
||||
GTexf_NoMipmap = 4096, // Disable mipmapping for this texture
|
||||
};
|
||||
|
||||
struct FMaterialLayers
|
||||
|
@ -265,6 +266,9 @@ public:
|
|||
void SetGlowing(PalEntry color) { flags = (flags & ~GTexf_AutoGlowing) | GTexf_Glowing; GlowColor = color; }
|
||||
void SetDisableBrightmap() { flags |= GTexf_BrightmapChecked; Brightmap = nullptr; }
|
||||
|
||||
bool isNoMipmap() const { return !!(flags & GTexf_NoMipmap); }
|
||||
void SetNoMipmap(bool set) { if (set) flags |= GTexf_NoMipmap; else flags &= ~GTexf_NoMipmap; }
|
||||
|
||||
bool isUserContent() const;
|
||||
int CheckRealHeight() { return xs_RoundToInt(Base->CheckRealHeight() / ScaleY); }
|
||||
void SetSize(int x, int y)
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// The maximum size of an IDAT chunk ZDoom will write. This is also the
|
||||
// size of the compression buffer it allocates on the stack.
|
||||
// size of the compression buffer it allocates on the heap.
|
||||
#define PNG_WRITE_SIZE 32768
|
||||
|
||||
// Set this to 1 to use a simple heuristic to select the filter to apply
|
||||
|
@ -926,8 +926,7 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
temprow[i] = &temprow_storage[temprow_size * i];
|
||||
}
|
||||
|
||||
TArray<Byte> array(PNG_WRITE_SIZE, true);
|
||||
auto buffer = array.data();
|
||||
TArray<Byte> buffer(PNG_WRITE_SIZE, true);
|
||||
z_stream stream;
|
||||
int err;
|
||||
int y;
|
||||
|
@ -944,8 +943,8 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
}
|
||||
|
||||
y = height;
|
||||
stream.next_out = buffer;
|
||||
stream.avail_out = sizeof(buffer);
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
|
||||
temprow[0][0] = 0;
|
||||
#if USE_FILTER_HEURISTIC
|
||||
|
@ -1007,12 +1006,12 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
}
|
||||
while (stream.avail_out == 0)
|
||||
{
|
||||
if (!WriteIDAT (file, buffer, sizeof(buffer)))
|
||||
if (!WriteIDAT (file, buffer.data(), buffer.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
stream.next_out = buffer;
|
||||
stream.avail_out = sizeof(buffer);
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
if (stream.avail_in != 0)
|
||||
{
|
||||
err = deflate (&stream, (y == 0) ? Z_FINISH : 0);
|
||||
|
@ -1033,12 +1032,12 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
}
|
||||
if (stream.avail_out == 0)
|
||||
{
|
||||
if (!WriteIDAT (file, buffer, sizeof(buffer)))
|
||||
if (!WriteIDAT (file, buffer.data(), buffer.size()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
stream.next_out = buffer;
|
||||
stream.avail_out = sizeof(buffer);
|
||||
stream.next_out = buffer.data();
|
||||
stream.avail_out = buffer.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1048,7 +1047,7 @@ bool M_SaveBitmap(const uint8_t *from, ESSType color_type, int width, int height
|
|||
{
|
||||
return false;
|
||||
}
|
||||
return WriteIDAT (file, buffer, sizeof(buffer)-stream.avail_out);
|
||||
return WriteIDAT (file, buffer.data(), buffer.size() - stream.avail_out);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -924,7 +924,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
~TDeletingArray<T, TT> ()
|
||||
~TDeletingArray()
|
||||
{
|
||||
for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i)
|
||||
{
|
||||
|
|
|
@ -64,6 +64,12 @@ bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newu
|
|||
return Instance->exitreason;
|
||||
}
|
||||
|
||||
void NetStartWindow::NetClose()
|
||||
{
|
||||
if (Instance != nullptr)
|
||||
Instance->OnClose();
|
||||
}
|
||||
|
||||
NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window)
|
||||
{
|
||||
SetWindowBackground(Colorf::fromRgba8(51, 51, 51));
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
static void HideNetStartPane();
|
||||
static void SetNetStartProgress(int pos);
|
||||
static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata);
|
||||
static void NetClose();
|
||||
|
||||
private:
|
||||
NetStartWindow();
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#include <zwidget/window/window.h>
|
||||
#include <zwidget/widgets/tabwidget/tabwidget.h>
|
||||
|
||||
int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs)
|
||||
int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString* extraArgs)
|
||||
{
|
||||
Size screenSize = GetScreenSize();
|
||||
double windowWidth = 615.0;
|
||||
double windowHeight = 700.0;
|
||||
|
||||
auto launcher = std::make_unique<LauncherWindow>(wads, numwads, defaultiwad, autoloadflags, extraArgs);
|
||||
auto launcher = std::make_unique<LauncherWindow>(wads, numwads, defaultiwad, autoloadflags, *extraArgs);
|
||||
launcher->SetFrameGeometry((screenSize.width - windowWidth) * 0.5, (screenSize.height - windowHeight) * 0.5, windowWidth, windowHeight);
|
||||
launcher->Show();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ struct WadStuff;
|
|||
class LauncherWindow : public Widget
|
||||
{
|
||||
public:
|
||||
static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs);
|
||||
static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString* extraArgs);
|
||||
|
||||
LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString& extraArgs);
|
||||
void UpdateLanguage();
|
||||
|
|
Loading…
Reference in a new issue