mirror of
https://github.com/ZDoom/Raze.git
synced 2025-04-25 01:01:02 +00:00
- backend update from GZDoom.
The main bulk of this is the new start screen code. To make this work in Raze some more work on the startup procedure is needed. What this does provide is support for the DOS end-of-game text screens in Duke and SW on non-Windows systems.
This commit is contained in:
parent
47aa110441
commit
84173ee09b
95 changed files with 4001 additions and 3209 deletions
|
@ -414,7 +414,10 @@ if( MSVC AND NOT VPX_FOUND )
|
||||||
# Use prebuilt library
|
# Use prebuilt library
|
||||||
set( VPX_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/Windows/vpx" )
|
set( VPX_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/Windows/vpx" )
|
||||||
set( VPX_INCLUDE_DIR ${VPX_ROOT_PATH}/include )
|
set( VPX_INCLUDE_DIR ${VPX_ROOT_PATH}/include )
|
||||||
set( VPX_LIBRARIES libvpx libcompat-to-msvc )
|
set( VPX_LIBRARIES libvpx )
|
||||||
|
if ( NOT ARM64 )
|
||||||
|
set (VPX_LIBRARIES ${VPX_LIBRARIES} libcompat-to-msvc )
|
||||||
|
endif()
|
||||||
if( ARM64 )
|
if( ARM64 )
|
||||||
link_directories( ${VPX_ROOT_PATH}/lib/arm64 )
|
link_directories( ${VPX_ROOT_PATH}/lib/arm64 )
|
||||||
elseif( X64 )
|
elseif( X64 )
|
||||||
|
@ -460,10 +463,10 @@ set( PLAT_WIN32_SOURCES
|
||||||
common/platform/win32/i_rawps2.cpp
|
common/platform/win32/i_rawps2.cpp
|
||||||
common/platform/win32/i_xinput.cpp
|
common/platform/win32/i_xinput.cpp
|
||||||
common/platform/win32/i_main.cpp
|
common/platform/win32/i_main.cpp
|
||||||
|
common/platform/win32/i_mainwindow.cpp
|
||||||
common/platform/win32/i_system.cpp
|
common/platform/win32/i_system.cpp
|
||||||
common/platform/win32/i_specialpaths.cpp
|
common/platform/win32/i_specialpaths.cpp
|
||||||
common/platform/win32/st_start.cpp
|
common/platform/win32/st_start.cpp
|
||||||
common/platform/win32/st_start_util.cpp
|
|
||||||
common/platform/win32/gl_sysfb.cpp
|
common/platform/win32/gl_sysfb.cpp
|
||||||
common/platform/win32/base_sysfb.cpp
|
common/platform/win32/base_sysfb.cpp
|
||||||
common/platform/win32/win32basevideo.cpp
|
common/platform/win32/win32basevideo.cpp
|
||||||
|
@ -628,6 +631,7 @@ file( GLOB HEADER_FILES
|
||||||
common/platform/win32/*.h
|
common/platform/win32/*.h
|
||||||
common/models/*.h
|
common/models/*.h
|
||||||
common/textures/*.h
|
common/textures/*.h
|
||||||
|
common/startscreen/*.h
|
||||||
common/textures/hires/hqnx/*.h
|
common/textures/hires/hqnx/*.h
|
||||||
common/textures/hires/hqnx_asm/*.h
|
common/textures/hires/hqnx_asm/*.h
|
||||||
common/textures/hires/xbr/*.h
|
common/textures/hires/xbr/*.h
|
||||||
|
@ -1104,6 +1108,12 @@ set (PCH_SOURCES
|
||||||
common/2d/wipe.cpp
|
common/2d/wipe.cpp
|
||||||
common/thirdparty/gain_analysis.cpp
|
common/thirdparty/gain_analysis.cpp
|
||||||
common/thirdparty/sfmt/SFMT.cpp
|
common/thirdparty/sfmt/SFMT.cpp
|
||||||
|
common/startscreen/startscreen.cpp
|
||||||
|
common/startscreen/startscreen_heretic.cpp
|
||||||
|
common/startscreen/startscreen_hexen.cpp
|
||||||
|
common/startscreen/startscreen_strife.cpp
|
||||||
|
common/startscreen/startscreen_generic.cpp
|
||||||
|
common/startscreen/endoom.cpp
|
||||||
common/fonts/singlelumpfont.cpp
|
common/fonts/singlelumpfont.cpp
|
||||||
common/fonts/singlepicfont.cpp
|
common/fonts/singlepicfont.cpp
|
||||||
common/fonts/specialfont.cpp
|
common/fonts/specialfont.cpp
|
||||||
|
@ -1139,11 +1149,13 @@ set (PCH_SOURCES
|
||||||
common/textures/formats/pcxtexture.cpp
|
common/textures/formats/pcxtexture.cpp
|
||||||
common/textures/formats/pngtexture.cpp
|
common/textures/formats/pngtexture.cpp
|
||||||
common/textures/formats/rawpagetexture.cpp
|
common/textures/formats/rawpagetexture.cpp
|
||||||
|
common/textures/formats/startuptexture.cpp
|
||||||
common/textures/formats/emptytexture.cpp
|
common/textures/formats/emptytexture.cpp
|
||||||
common/textures/formats/shadertexture.cpp
|
common/textures/formats/shadertexture.cpp
|
||||||
common/textures/formats/tgatexture.cpp
|
common/textures/formats/tgatexture.cpp
|
||||||
common/textures/formats/stbtexture.cpp
|
common/textures/formats/stbtexture.cpp
|
||||||
common/textures/formats/anmtexture.cpp
|
common/textures/formats/anmtexture.cpp
|
||||||
|
common/textures/formats/startscreentexture.cpp
|
||||||
common/textures/hires/hqresize.cpp
|
common/textures/hires/hqresize.cpp
|
||||||
common/models/models_md3.cpp
|
common/models/models_md3.cpp
|
||||||
common/models/models_md2.cpp
|
common/models/models_md2.cpp
|
||||||
|
@ -1230,7 +1242,7 @@ set (PCH_SOURCES
|
||||||
common/menu/menudef.cpp
|
common/menu/menudef.cpp
|
||||||
common/menu/savegamemanager.cpp
|
common/menu/savegamemanager.cpp
|
||||||
common/statusbar/base_sbar.cpp
|
common/statusbar/base_sbar.cpp
|
||||||
|
|
||||||
common/rendering/v_framebuffer.cpp
|
common/rendering/v_framebuffer.cpp
|
||||||
common/rendering/v_video.cpp
|
common/rendering/v_video.cpp
|
||||||
common/rendering/r_thread.cpp
|
common/rendering/r_thread.cpp
|
||||||
|
@ -1409,6 +1421,7 @@ include_directories(
|
||||||
common/statusbar
|
common/statusbar
|
||||||
common/fonts
|
common/fonts
|
||||||
common/objects
|
common/objects
|
||||||
|
common/startscreen
|
||||||
common/rendering
|
common/rendering
|
||||||
common/rendering/hwrenderer
|
common/rendering/hwrenderer
|
||||||
common/rendering/hwrenderer/data
|
common/rendering/hwrenderer/data
|
||||||
|
|
|
@ -247,11 +247,13 @@ int GetUIScale(F2DDrawer* drawer, int altval);
|
||||||
int GetConScale(F2DDrawer* drawer, int altval);
|
int GetConScale(F2DDrawer* drawer, int altval);
|
||||||
|
|
||||||
EXTERN_CVAR(Int, uiscale);
|
EXTERN_CVAR(Int, uiscale);
|
||||||
EXTERN_CVAR(Int, con_scale);
|
|
||||||
|
|
||||||
inline int active_con_scale(F2DDrawer *drawer)
|
inline int active_con_scale(F2DDrawer *drawer)
|
||||||
{
|
{
|
||||||
return GetConScale(drawer, con_scale);
|
// this sets the threshold for upscaling the console font to 2560 x 1440.
|
||||||
|
int vscale = drawer->GetHeight() / 720;
|
||||||
|
int hscale = drawer->GetWidth() / 1280;
|
||||||
|
return max(1, min(vscale, hscale));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DrawText
|
#ifdef DrawText
|
||||||
|
|
|
@ -128,11 +128,6 @@ static GameAtExit *ExitCmdList;
|
||||||
static char *work = NULL;
|
static char *work = NULL;
|
||||||
static int worklen = 0;
|
static int worklen = 0;
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, con_scale, 0, CVAR_ARCHIVE)
|
|
||||||
{
|
|
||||||
if (self < 0) self = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE)
|
CUSTOM_CVAR(Float, con_alpha, 0.75f, CVAR_ARCHIVE)
|
||||||
{
|
{
|
||||||
if (self < 0.f) self = 0.f;
|
if (self < 0.f) self = 0.f;
|
||||||
|
|
|
@ -520,7 +520,6 @@ void FBaseCVar::EnableNoSet ()
|
||||||
|
|
||||||
void FBaseCVar::EnableCallbacks ()
|
void FBaseCVar::EnableCallbacks ()
|
||||||
{
|
{
|
||||||
m_inEnable = true;
|
|
||||||
m_UseCallback = true;
|
m_UseCallback = true;
|
||||||
FBaseCVar *cvar = CVars;
|
FBaseCVar *cvar = CVars;
|
||||||
|
|
||||||
|
@ -532,7 +531,6 @@ void FBaseCVar::EnableCallbacks ()
|
||||||
}
|
}
|
||||||
cvar = cvar->m_Next;
|
cvar = cvar->m_Next;
|
||||||
}
|
}
|
||||||
m_inEnable = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBaseCVar::DisableCallbacks ()
|
void FBaseCVar::DisableCallbacks ()
|
||||||
|
|
|
@ -210,9 +210,6 @@ protected:
|
||||||
uint32_t Flags;
|
uint32_t Flags;
|
||||||
bool inCallback = false;
|
bool inCallback = false;
|
||||||
|
|
||||||
public:
|
|
||||||
static inline bool m_inEnable = false;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FBaseCVar (const FBaseCVar &var) = delete;
|
FBaseCVar (const FBaseCVar &var) = delete;
|
||||||
FBaseCVar (const char *name, uint32_t flags);
|
FBaseCVar (const char *name, uint32_t flags);
|
||||||
|
|
|
@ -382,23 +382,17 @@ public:
|
||||||
const int ustride = img->stride[VPX_PLANE_U];
|
const int ustride = img->stride[VPX_PLANE_U];
|
||||||
const int vstride = img->stride[VPX_PLANE_V];
|
const int vstride = img->stride[VPX_PLANE_V];
|
||||||
|
|
||||||
for (unsigned int y = 0; y < height; y += 2)
|
for (unsigned int y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
unsigned int y1 = y + 1;
|
for (unsigned int x = 0; x < width; x++)
|
||||||
unsigned int wy = width * y;
|
|
||||||
unsigned int wy1 = width * y1;
|
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; x += 2)
|
|
||||||
{
|
{
|
||||||
uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)];
|
uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)];
|
||||||
uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)];
|
uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)];
|
||||||
|
|
||||||
SetPixel(&Pic[(wy + x) << 2], yplane[ystride * y + x], u, v);
|
SetPixel(&Pic[(x + y * width) << 2], yplane[ystride * y + x], u, v);
|
||||||
SetPixel(&Pic[(wy + x + 1) << 2], yplane[ystride * y + x + 1], u, v);
|
|
||||||
SetPixel(&Pic[(wy1 + x) << 2], yplane[ystride * y1 + x], u, v);
|
|
||||||
SetPixel(&Pic[(wy1 + x + 1) << 2], yplane[ystride * y1 + x + 1], u, v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ event_t events[MAXEVENTS];
|
||||||
|
|
||||||
CVAR(Float, m_sensitivity_x, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Float, m_sensitivity_x, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
CVAR(Float, m_sensitivity_y, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Float, m_sensitivity_y, 2, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -165,24 +164,11 @@ void D_PostEvent(event_t* ev)
|
||||||
|
|
||||||
void PostMouseMove(int xx, int yy)
|
void PostMouseMove(int xx, int yy)
|
||||||
{
|
{
|
||||||
static float lastx = 0, lasty = 0;
|
|
||||||
event_t ev{};
|
event_t ev{};
|
||||||
|
|
||||||
float x = float(xx) * m_sensitivity_x;
|
ev.x = float(xx) * m_sensitivity_x;
|
||||||
float y = -float(yy) * m_sensitivity_y;
|
ev.y = -float(yy) * m_sensitivity_y;
|
||||||
|
|
||||||
if (m_filter)
|
|
||||||
{
|
|
||||||
ev.x = (x + lastx) / 2;
|
|
||||||
ev.y = (y + lasty) / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ev.x = x;
|
|
||||||
ev.y = y;
|
|
||||||
}
|
|
||||||
lastx = x;
|
|
||||||
lasty = y;
|
|
||||||
if (ev.x || ev.y)
|
if (ev.x || ev.y)
|
||||||
{
|
{
|
||||||
ev.type = EV_Mouse;
|
ev.type = EV_Mouse;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "st_start.h"
|
||||||
|
|
||||||
// Some global engine variables taken out of the backend code.
|
// Some global engine variables taken out of the backend code.
|
||||||
|
FStartupScreen* StartWindow;
|
||||||
SystemCallbacks sysCallbacks;
|
SystemCallbacks sysCallbacks;
|
||||||
FString endoomName;
|
FString endoomName;
|
||||||
bool batchrun;
|
bool batchrun;
|
||||||
|
|
|
@ -292,9 +292,9 @@ void PacketGet (void)
|
||||||
if (err == WSAECONNRESET)
|
if (err == WSAECONNRESET)
|
||||||
{ // The remote node aborted unexpectedly, so pretend it sent an exit packet
|
{ // The remote node aborted unexpectedly, so pretend it sent an exit packet
|
||||||
|
|
||||||
if (StartScreen != NULL)
|
if (StartWindow != NULL)
|
||||||
{
|
{
|
||||||
StartScreen->NetMessage ("The connection from %s was dropped.\n",
|
I_NetMessage ("The connection from %s was dropped.\n",
|
||||||
GetPlayerName(node).GetChars());
|
GetPlayerName(node).GetChars());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -511,7 +511,7 @@ static void SendConAck (int num_connected, int num_needed)
|
||||||
{
|
{
|
||||||
PreSend (&packet, 4, &sendaddress[node]);
|
PreSend (&packet, 4, &sendaddress[node]);
|
||||||
}
|
}
|
||||||
StartScreen->NetProgress (doomcom.numnodes);
|
I_NetProgress (doomcom.numnodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Host_CheckForConnects (void *userdata)
|
bool Host_CheckForConnects (void *userdata)
|
||||||
|
@ -536,7 +536,7 @@ bool Host_CheckForConnects (void *userdata)
|
||||||
if (node == -1)
|
if (node == -1)
|
||||||
{
|
{
|
||||||
const uint8_t *s_addr_bytes = (const uint8_t *)&from->sin_addr;
|
const uint8_t *s_addr_bytes = (const uint8_t *)&from->sin_addr;
|
||||||
StartScreen->NetMessage ("Got extra connect from %d.%d.%d.%d:%d",
|
I_NetMessage ("Got extra connect from %d.%d.%d.%d:%d",
|
||||||
s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3],
|
s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3],
|
||||||
from->sin_port);
|
from->sin_port);
|
||||||
packet.Message = PRE_ALLFULL;
|
packet.Message = PRE_ALLFULL;
|
||||||
|
@ -549,7 +549,7 @@ bool Host_CheckForConnects (void *userdata)
|
||||||
{
|
{
|
||||||
node = doomcom.numnodes++;
|
node = doomcom.numnodes++;
|
||||||
sendaddress[node] = *from;
|
sendaddress[node] = *from;
|
||||||
StartScreen->NetMessage ("Got connect from node %d.", node);
|
I_NetMessage ("Got connect from node %d.", node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the new guest (and everyone else) know we got their message.
|
// Let the new guest (and everyone else) know we got their message.
|
||||||
|
@ -561,7 +561,7 @@ bool Host_CheckForConnects (void *userdata)
|
||||||
node = FindNode (from);
|
node = FindNode (from);
|
||||||
if (node >= 0)
|
if (node >= 0)
|
||||||
{
|
{
|
||||||
StartScreen->NetMessage ("Got disconnect from node %d.", node);
|
I_NetMessage ("Got disconnect from node %d.", node);
|
||||||
doomcom.numnodes--;
|
doomcom.numnodes--;
|
||||||
while (node < doomcom.numnodes)
|
while (node < doomcom.numnodes)
|
||||||
{
|
{
|
||||||
|
@ -708,10 +708,10 @@ bool HostGame (int i)
|
||||||
|
|
||||||
doomcom.numnodes = 1;
|
doomcom.numnodes = 1;
|
||||||
|
|
||||||
StartScreen->NetInit ("Waiting for players", numplayers);
|
I_NetInit ("Waiting for players", numplayers);
|
||||||
|
|
||||||
// Wait for numplayers-1 different connections
|
// Wait for numplayers-1 different connections
|
||||||
if (!StartScreen->NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers))
|
if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers))
|
||||||
{
|
{
|
||||||
SendAbort();
|
SendAbort();
|
||||||
return false;
|
return false;
|
||||||
|
@ -719,17 +719,17 @@ bool HostGame (int i)
|
||||||
|
|
||||||
// Now inform everyone of all machines involved in the game
|
// Now inform everyone of all machines involved in the game
|
||||||
memset (gotack, 0, sizeof(gotack));
|
memset (gotack, 0, sizeof(gotack));
|
||||||
StartScreen->NetMessage ("Sending all here.");
|
I_NetMessage ("Sending all here.");
|
||||||
StartScreen->NetInit ("Done waiting", 1);
|
I_NetInit ("Done waiting", 1);
|
||||||
|
|
||||||
if (!StartScreen->NetLoop (Host_SendAllHere, (void *)gotack))
|
if (!I_NetLoop (Host_SendAllHere, (void *)gotack))
|
||||||
{
|
{
|
||||||
SendAbort();
|
SendAbort();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go
|
// Now go
|
||||||
StartScreen->NetMessage ("Go");
|
I_NetMessage ("Go");
|
||||||
packet.Fake = PRE_FAKE;
|
packet.Fake = PRE_FAKE;
|
||||||
packet.Message = PRE_GO;
|
packet.Message = PRE_GO;
|
||||||
for (node = 1; node < doomcom.numnodes; node++)
|
for (node = 1; node < doomcom.numnodes; node++)
|
||||||
|
@ -742,7 +742,7 @@ bool HostGame (int i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartScreen->NetMessage ("Total players: %d", doomcom.numnodes);
|
I_NetMessage ("Total players: %d", doomcom.numnodes);
|
||||||
|
|
||||||
doomcom.id = DOOMCOM_ID;
|
doomcom.id = DOOMCOM_ID;
|
||||||
doomcom.numplayers = doomcom.numnodes;
|
doomcom.numplayers = doomcom.numnodes;
|
||||||
|
@ -776,9 +776,9 @@ bool Guest_ContactHost (void *userdata)
|
||||||
{
|
{
|
||||||
if (packet.Message == PRE_CONACK)
|
if (packet.Message == PRE_CONACK)
|
||||||
{
|
{
|
||||||
StartScreen->NetMessage ("Total players: %d", packet.NumNodes);
|
I_NetMessage ("Total players: %d", packet.NumNodes);
|
||||||
StartScreen->NetInit ("Waiting for other players", packet.NumNodes);
|
I_NetInit ("Waiting for other players", packet.NumNodes);
|
||||||
StartScreen->NetProgress (packet.NumPresent);
|
I_NetProgress (packet.NumPresent);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (packet.Message == PRE_DISCONNECT)
|
else if (packet.Message == PRE_DISCONNECT)
|
||||||
|
@ -795,7 +795,7 @@ bool Guest_ContactHost (void *userdata)
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the progress bar could not be marqueed, bump it.
|
// In case the progress bar could not be marqueed, bump it.
|
||||||
StartScreen->NetProgress (0);
|
I_NetProgress (0);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ bool Guest_WaitForOthers (void *userdata)
|
||||||
switch (packet.Message)
|
switch (packet.Message)
|
||||||
{
|
{
|
||||||
case PRE_CONACK:
|
case PRE_CONACK:
|
||||||
StartScreen->NetProgress (packet.NumPresent);
|
I_NetProgress (packet.NumPresent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRE_ALLHERE:
|
case PRE_ALLHERE:
|
||||||
|
@ -825,7 +825,7 @@ bool Guest_WaitForOthers (void *userdata)
|
||||||
doomcom.numnodes = packet.NumNodes + 2;
|
doomcom.numnodes = packet.NumNodes + 2;
|
||||||
sendplayer[0] = packet.ConsoleNum; // My player number
|
sendplayer[0] = packet.ConsoleNum; // My player number
|
||||||
doomcom.consoleplayer = packet.ConsoleNum;
|
doomcom.consoleplayer = packet.ConsoleNum;
|
||||||
StartScreen->NetMessage ("Console player number: %d", doomcom.consoleplayer);
|
I_NetMessage ("Console player number: %d", doomcom.consoleplayer);
|
||||||
for (node = 0; node < packet.NumNodes; node++)
|
for (node = 0; node < packet.NumNodes; node++)
|
||||||
{
|
{
|
||||||
sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address;
|
sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address;
|
||||||
|
@ -839,14 +839,14 @@ bool Guest_WaitForOthers (void *userdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StartScreen->NetMessage ("Received All Here, sending ACK.");
|
I_NetMessage ("Received All Here, sending ACK.");
|
||||||
packet.Fake = PRE_FAKE;
|
packet.Fake = PRE_FAKE;
|
||||||
packet.Message = PRE_ALLHEREACK;
|
packet.Message = PRE_ALLHEREACK;
|
||||||
PreSend (&packet, 2, &sendaddress[1]);
|
PreSend (&packet, 2, &sendaddress[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PRE_GO:
|
case PRE_GO:
|
||||||
StartScreen->NetMessage ("Received \"Go.\"");
|
I_NetMessage ("Received \"Go.\"");
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case PRE_DISCONNECT:
|
case PRE_DISCONNECT:
|
||||||
|
@ -878,22 +878,22 @@ bool JoinGame (int i)
|
||||||
|
|
||||||
|
|
||||||
// Let host know we are here
|
// Let host know we are here
|
||||||
StartScreen->NetInit ("Contacting host", 0);
|
I_NetInit ("Contacting host", 0);
|
||||||
|
|
||||||
if (!StartScreen->NetLoop (Guest_ContactHost, NULL))
|
if (!I_NetLoop (Guest_ContactHost, NULL))
|
||||||
{
|
{
|
||||||
SendAbort();
|
SendAbort();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for everyone else to connect
|
// Wait for everyone else to connect
|
||||||
if (!StartScreen->NetLoop (Guest_WaitForOthers, 0))
|
if (!I_NetLoop (Guest_WaitForOthers, 0))
|
||||||
{
|
{
|
||||||
SendAbort();
|
SendAbort();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartScreen->NetMessage ("Total players: %d", doomcom.numnodes);
|
I_NetMessage ("Total players: %d", doomcom.numnodes);
|
||||||
|
|
||||||
doomcom.id = DOOMCOM_ID;
|
doomcom.id = DOOMCOM_ID;
|
||||||
doomcom.numplayers = doomcom.numnodes;
|
doomcom.numplayers = doomcom.numnodes;
|
||||||
|
@ -1026,6 +1026,43 @@ void I_NetCmd (void)
|
||||||
I_Error ("Bad net cmd: %i\n",doomcom.command);
|
I_Error ("Bad net cmd: %i\n",doomcom.command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void I_NetMessage(const char* text, ...)
|
||||||
|
{
|
||||||
|
// todo: use better abstraction once everything is migrated to in-game start screens.
|
||||||
|
#if defined _WIN32 || defined __APPLE__
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, text);
|
||||||
|
VPrintf(PRINT_HIGH, text, ap);
|
||||||
|
Printf("\n");
|
||||||
|
va_end(ap);
|
||||||
|
#else
|
||||||
|
FString str;
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start(argptr, text);
|
||||||
|
str.VFormat(text, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
fprintf(stderr, "\r%-40s\n", str.GetChars());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: later these must be dispatched by the main menu, not the start screen.
|
||||||
|
void I_NetProgress(int val)
|
||||||
|
{
|
||||||
|
StartWindow->NetProgress(val);
|
||||||
|
}
|
||||||
|
void I_NetInit(const char* msg, int num)
|
||||||
|
{
|
||||||
|
StartWindow->NetInit(msg, num);
|
||||||
|
}
|
||||||
|
bool I_NetLoop(bool (*timer_callback)(void*), void* userdata)
|
||||||
|
{
|
||||||
|
return StartWindow->NetLoop(timer_callback, userdata);
|
||||||
|
}
|
||||||
|
void I_NetDone()
|
||||||
|
{
|
||||||
|
StartWindow->NetDone();
|
||||||
|
}
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
const char *neterror (void)
|
const char *neterror (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,11 @@
|
||||||
// Called by D_DoomMain.
|
// Called by D_DoomMain.
|
||||||
int I_InitNetwork (void);
|
int I_InitNetwork (void);
|
||||||
void I_NetCmd (void);
|
void I_NetCmd (void);
|
||||||
|
void I_NetMessage(const char*, ...);
|
||||||
|
void I_NetProgress(int val);
|
||||||
|
void I_NetInit(const char* msg, int num);
|
||||||
|
bool I_NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||||
|
void I_NetDone();
|
||||||
|
|
||||||
enum ENetConstants
|
enum ENetConstants
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,16 +135,19 @@ public:
|
||||||
|
|
||||||
FRemapTable* GetTranslation(int slot, int index)
|
FRemapTable* GetTranslation(int slot, int index)
|
||||||
{
|
{
|
||||||
|
if (TranslationTables.Size() <= (unsigned)slot) return nullptr;
|
||||||
return TranslationTables[slot].GetVal(index);
|
return TranslationTables[slot].GetVal(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearTranslationSlot(int slot)
|
void ClearTranslationSlot(int slot)
|
||||||
{
|
{
|
||||||
|
if (TranslationTables.Size() <= (unsigned)slot) return;
|
||||||
TranslationTables[slot].Clear();
|
TranslationTables[slot].Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NumTranslations(int slot) const
|
unsigned NumTranslations(int slot) const
|
||||||
{
|
{
|
||||||
|
if (TranslationTables.Size() <= (unsigned)slot) return 0;
|
||||||
return TranslationTables[slot].Size();
|
return TranslationTables[slot].Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
class FStartupScreen
|
class FStartupScreen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static FStartupScreen *CreateInstance(int max_progress);
|
static FStartupScreen *CreateInstance(int max_progress, bool showprogress);
|
||||||
|
|
||||||
FStartupScreen(int max_progress)
|
FStartupScreen(int max_progress)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,6 @@ public:
|
||||||
|
|
||||||
virtual void NetInit(const char *message, int num_players) {}
|
virtual void NetInit(const char *message, int num_players) {}
|
||||||
virtual void NetProgress(int count) {}
|
virtual void NetProgress(int count) {}
|
||||||
virtual void NetMessage(const char *format, ...) {} // cover for printf
|
|
||||||
virtual void NetDone() {}
|
virtual void NetDone() {}
|
||||||
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; }
|
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; }
|
||||||
virtual void AppendStatusLine(const char* status) {}
|
virtual void AppendStatusLine(const char* status) {}
|
||||||
|
@ -77,118 +76,12 @@ public:
|
||||||
void NetDone();
|
void NetDone();
|
||||||
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||||
protected:
|
protected:
|
||||||
long long NetMarqueeMode;
|
|
||||||
int NetMaxPos, NetCurPos;
|
int NetMaxPos, NetCurPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FGraphicalStartupScreen : public FBasicStartupScreen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FGraphicalStartupScreen(int max_progress);
|
|
||||||
~FGraphicalStartupScreen();
|
|
||||||
};
|
|
||||||
|
|
||||||
class FHereticStartupScreen : public FGraphicalStartupScreen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FHereticStartupScreen(int max_progress, long &hr);
|
|
||||||
|
|
||||||
void Progress();
|
|
||||||
void LoadingStatus(const char *message, int colors);
|
|
||||||
void AppendStatusLine(const char *status);
|
|
||||||
protected:
|
|
||||||
void SetWindowSize();
|
|
||||||
|
|
||||||
int ThermX, ThermY, ThermWidth, ThermHeight;
|
|
||||||
int HMsgY, SMsgX;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FHexenStartupScreen : public FGraphicalStartupScreen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FHexenStartupScreen(int max_progress, long &hr);
|
|
||||||
~FHexenStartupScreen();
|
|
||||||
|
|
||||||
void Progress();
|
|
||||||
void NetProgress(int count);
|
|
||||||
void NetDone();
|
|
||||||
void SetWindowSize();
|
|
||||||
|
|
||||||
// Hexen's notch graphics, converted to chunky pixels.
|
|
||||||
uint8_t * NotchBits;
|
|
||||||
uint8_t * NetNotchBits;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FStrifeStartupScreen : public FGraphicalStartupScreen
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FStrifeStartupScreen(int max_progress, long &hr);
|
|
||||||
~FStrifeStartupScreen();
|
|
||||||
|
|
||||||
void Progress();
|
|
||||||
protected:
|
|
||||||
void DrawStuff(int old_laser, int new_laser);
|
|
||||||
void SetWindowSize();
|
|
||||||
|
|
||||||
uint8_t *StartupPics[4+2+1];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
extern FStartupScreen *StartWindow;
|
||||||
extern FStartupScreen *StartScreen;
|
|
||||||
|
|
||||||
void DeleteStartupScreen();
|
|
||||||
extern void ST_Endoom();
|
|
||||||
|
|
||||||
// The entire set of functions here uses native Windows types. These are recreations of those types so that the code doesn't need to be changed more than necessary
|
|
||||||
|
|
||||||
struct BitmapInfoHeader
|
|
||||||
{
|
|
||||||
uint32_t biSize;
|
|
||||||
int32_t biWidth;
|
|
||||||
int32_t biHeight;
|
|
||||||
uint16_t biPlanes;
|
|
||||||
uint16_t biBitCount;
|
|
||||||
uint32_t biCompression;
|
|
||||||
uint32_t biSizeImage;
|
|
||||||
int32_t biXPelsPerMeter;
|
|
||||||
int32_t biYPelsPerMeter;
|
|
||||||
uint32_t biClrUsed;
|
|
||||||
uint32_t biClrImportant;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RgbQuad
|
|
||||||
{
|
|
||||||
uint8_t rgbBlue;
|
|
||||||
uint8_t rgbGreen;
|
|
||||||
uint8_t rgbRed;
|
|
||||||
uint8_t rgbReserved;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct BitmapInfo
|
|
||||||
{
|
|
||||||
BitmapInfoHeader bmiHeader;
|
|
||||||
RgbQuad bmiColors[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern BitmapInfo* StartupBitmap;
|
|
||||||
|
|
||||||
|
|
||||||
void ST_Util_PlanarToChunky4(uint8_t* dest, const uint8_t* src, int width, int height);
|
|
||||||
void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y, int bytewidth, int height);
|
|
||||||
void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int bytewidth, int height);
|
|
||||||
BitmapInfo* ST_Util_CreateBitmap(int width, int height, int color_bits);
|
|
||||||
uint8_t* ST_Util_BitsForBitmap(BitmapInfo* bitmap_info);
|
|
||||||
void ST_Util_FreeBitmap(BitmapInfo* bitmap_info);
|
|
||||||
void ST_Util_BitmapColorsFromPlaypal(BitmapInfo* bitmap_info);
|
|
||||||
uint8_t* ST_Util_LoadFont(const char* filename);
|
|
||||||
void ST_Util_FreeFont(uint8_t* font);
|
|
||||||
BitmapInfo* ST_Util_AllocTextBitmap(const uint8_t* font);
|
|
||||||
void ST_Util_DrawTextScreen(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font);
|
|
||||||
void ST_Util_DrawChar(BitmapInfo* screen, const uint8_t* font, int x, int y, uint8_t charnum, uint8_t attrib);
|
|
||||||
void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font, bool on);
|
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -200,10 +93,10 @@ void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen
|
||||||
|
|
||||||
inline void DeleteStartupScreen()
|
inline void DeleteStartupScreen()
|
||||||
{
|
{
|
||||||
if (StartScreen != nullptr)
|
if (StartWindow != nullptr)
|
||||||
{
|
{
|
||||||
delete StartScreen;
|
delete StartWindow;
|
||||||
StartScreen = nullptr;
|
StartWindow = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -222,7 +222,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NumLumps = info.NumEntries;
|
NumLumps = (uint32_t)info.NumEntries;
|
||||||
dirsize = info.DirectorySize;
|
dirsize = info.DirectorySize;
|
||||||
DirectoryOffset = info.DirectoryOffset;
|
DirectoryOffset = info.DirectoryOffset;
|
||||||
}
|
}
|
||||||
|
@ -521,7 +521,7 @@ int FZipLump::GetFileOffset()
|
||||||
{
|
{
|
||||||
if (Method != METHOD_STORED) return -1;
|
if (Method != METHOD_STORED) return -1;
|
||||||
if (NeedFileStart) SetLumpAddress();
|
if (NeedFileStart) SetLumpAddress();
|
||||||
return Position;
|
return (int)Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -47,8 +47,6 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
|
|
||||||
extern FILE* hashfile;
|
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
#define NULL_INDEX (0xffffffff)
|
#define NULL_INDEX (0xffffffff)
|
||||||
|
@ -208,7 +206,7 @@ void FileSystem::InitSingleFile(const char* filename, bool quiet)
|
||||||
InitMultipleFiles(filenames, true);
|
InitMultipleFiles(filenames, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystem::InitMultipleFiles (TArray<FString> &filenames, bool quiet, LumpFilterInfo* filter)
|
void FileSystem::InitMultipleFiles (TArray<FString> &filenames, bool quiet, LumpFilterInfo* filter, bool allowduplicates, FILE* hashfile)
|
||||||
{
|
{
|
||||||
int numfiles;
|
int numfiles;
|
||||||
|
|
||||||
|
@ -217,21 +215,24 @@ void FileSystem::InitMultipleFiles (TArray<FString> &filenames, bool quiet, Lump
|
||||||
numfiles = 0;
|
numfiles = 0;
|
||||||
|
|
||||||
// first, check for duplicates
|
// first, check for duplicates
|
||||||
if (!Args->CheckParm("-allowduplicates"))
|
if (allowduplicates)
|
||||||
{
|
{
|
||||||
for (unsigned i=0;i<filenames.Size(); i++)
|
for (unsigned i=0;i<filenames.Size(); i++)
|
||||||
{
|
{
|
||||||
for (unsigned j=i+1;j<filenames.Size(); j++)
|
for (unsigned j=i+1;j<filenames.Size(); j++)
|
||||||
{
|
{
|
||||||
if (strcmp(filenames[i], filenames[j]) == 0)
|
if (strcmp(filenames[i], filenames[j]) == 0)
|
||||||
|
{
|
||||||
filenames.Delete(j);
|
filenames.Delete(j);
|
||||||
|
j--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i=0;i<filenames.Size(); i++)
|
for(unsigned i=0;i<filenames.Size(); i++)
|
||||||
{
|
{
|
||||||
AddFile (filenames[i], nullptr, quiet, filter);
|
AddFile (filenames[i], nullptr, quiet, filter, hashfile);
|
||||||
|
|
||||||
if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/");
|
if (i == (unsigned)MaxIwadIndex) MoveLumpsInFolder("after_iwad/");
|
||||||
FStringf path("filter/%s", Files.Last()->GetHash().GetChars());
|
FStringf path("filter/%s", Files.Last()->GetHash().GetChars());
|
||||||
|
@ -307,7 +308,7 @@ int FileSystem::AddFromBuffer(const char* name, const char* type, char* data, in
|
||||||
// [RH] Removed reload hack
|
// [RH] Removed reload hack
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter)
|
void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, LumpFilterInfo* filter, FILE* hashfile)
|
||||||
{
|
{
|
||||||
int startlump;
|
int startlump;
|
||||||
bool isdir = false;
|
bool isdir = false;
|
||||||
|
@ -375,7 +376,7 @@ void FileSystem::AddFile (const char *filename, FileReader *filer, bool quiet, L
|
||||||
FString path;
|
FString path;
|
||||||
path.Format("%s:%s", filename, lump->getName());
|
path.Format("%s:%s", filename, lump->getName());
|
||||||
auto embedded = lump->NewReader();
|
auto embedded = lump->NewReader();
|
||||||
AddFile(path, &embedded, quiet, filter);
|
AddFile(path, &embedded, quiet, filter, hashfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,8 @@ public:
|
||||||
void SetMaxIwadNum(int x) { MaxIwadIndex = x; }
|
void SetMaxIwadNum(int x) { MaxIwadIndex = x; }
|
||||||
|
|
||||||
void InitSingleFile(const char *filename, bool quiet = false);
|
void InitSingleFile(const char *filename, bool quiet = false);
|
||||||
void InitMultipleFiles (TArray<FString> &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr);
|
void InitMultipleFiles (TArray<FString> &filenames, bool quiet = false, LumpFilterInfo* filter = nullptr, bool allowduplicates = false, FILE* hashfile = nullptr);
|
||||||
void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter);
|
void AddFile (const char *filename, FileReader *wadinfo, bool quiet, LumpFilterInfo* filter, FILE* hashfile);
|
||||||
int CheckIfResourceFileLoaded (const char *name) noexcept;
|
int CheckIfResourceFileLoaded (const char *name) noexcept;
|
||||||
void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {}
|
void AddAdditionalFile(const char* filename, FileReader* wadinfo = NULL) {}
|
||||||
|
|
||||||
|
|
|
@ -58,11 +58,12 @@ struct HexDataSource
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void ParseDefinition(int lumpnum)
|
void ParseDefinition(FResourceLump* font)
|
||||||
{
|
{
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
|
|
||||||
sc.OpenLumpNum(lumpnum);
|
auto data = font->Lock();
|
||||||
|
sc.OpenMem("newconsolefont.hex", (const char*)data, font->Size());
|
||||||
sc.SetCMode(true);
|
sc.SetCMode(true);
|
||||||
glyphdata.Push(0); // ensure that index 0 can be used as 'not present'.
|
glyphdata.Push(0); // ensure that index 0 can be used as 'not present'.
|
||||||
while (sc.GetString())
|
while (sc.GetString())
|
||||||
|
@ -96,6 +97,7 @@ struct HexDataSource
|
||||||
lumb = i * 255 / 17;
|
lumb = i * 255 / 17;
|
||||||
SmallPal[i] = PalEntry(255, lumb, lumb, lumb);
|
SmallPal[i] = PalEntry(255, lumb, lumb, lumb);
|
||||||
}
|
}
|
||||||
|
font->Unlock();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -400,7 +402,7 @@ public:
|
||||||
|
|
||||||
FFont *CreateHexLumpFont (const char *fontname, int lump)
|
FFont *CreateHexLumpFont (const char *fontname, int lump)
|
||||||
{
|
{
|
||||||
if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump);
|
assert(hexdata.FirstChar != INT_MAX);
|
||||||
return new FHexFont(fontname, lump);
|
return new FHexFont(fontname, lump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,6 +414,33 @@ FFont *CreateHexLumpFont (const char *fontname, int lump)
|
||||||
|
|
||||||
FFont *CreateHexLumpFont2(const char *fontname, int lump)
|
FFont *CreateHexLumpFont2(const char *fontname, int lump)
|
||||||
{
|
{
|
||||||
if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump);
|
assert(hexdata.FirstChar != INT_MAX);
|
||||||
return new FHexFont2(fontname, lump);
|
return new FHexFont2(fontname, lump);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
uint8_t* GetHexChar(int codepoint)
|
||||||
|
{
|
||||||
|
assert(hexdata.FirstChar != INT_MAX);
|
||||||
|
|
||||||
|
if (hexdata.glyphmap[codepoint] > 0)
|
||||||
|
{
|
||||||
|
auto offset = hexdata.glyphmap[codepoint];
|
||||||
|
return &hexdata.glyphdata[offset];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadHexFont(const char* filename)
|
||||||
|
{
|
||||||
|
auto resf = FResourceFile::OpenResourceFile(filename);
|
||||||
|
if (resf == nullptr) I_FatalError("Unable to open %s", filename);
|
||||||
|
auto hexfont = resf->FindLump("newconsolefont.hex");
|
||||||
|
if (hexfont == nullptr) I_FatalError("Unable to find newconsolefont.hex in %s", filename);
|
||||||
|
hexdata.ParseDefinition(hexfont);
|
||||||
|
}
|
||||||
|
|
|
@ -623,13 +623,16 @@ int FOBJModel::FindFrame(const char* name)
|
||||||
*
|
*
|
||||||
* @param renderer The model renderer
|
* @param renderer The model renderer
|
||||||
* @param skin The loaded skin for the surface
|
* @param skin The loaded skin for the surface
|
||||||
* @param frameno Unused
|
* @param frameno The first frame to interpolate between. Only prevents the model from rendering if it is < 0, since OBJ models are static.
|
||||||
* @param frameno2 Unused
|
* @param frameno2 The second frame to interpolate between.
|
||||||
* @param inter Unused
|
* @param inter The amount to interpolate the two frames.
|
||||||
* @param translation The translation for the skin
|
* @param translation The translation for the skin
|
||||||
*/
|
*/
|
||||||
void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation)
|
void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation)
|
||||||
{
|
{
|
||||||
|
// Prevent the model from rendering if the frame number is < 0
|
||||||
|
if (frameno < 0 || frameno2 < 0) return;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < surfaces.Size(); i++)
|
for (unsigned int i = 0; i < surfaces.Size(); i++)
|
||||||
{
|
{
|
||||||
OBJSurface *surf = &surfaces[i];
|
OBJSurface *surf = &surfaces[i];
|
||||||
|
|
|
@ -493,6 +493,11 @@ DEFINE_ACTION_FUNCTION(DObject, MSTime)
|
||||||
ACTION_RETURN_INT((uint32_t)I_msTime());
|
ACTION_RETURN_INT((uint32_t)I_msTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION_NATIVE(DObject, MSTimef, I_msTimeF)
|
||||||
|
{
|
||||||
|
ACTION_RETURN_FLOAT(I_msTimeF());
|
||||||
|
}
|
||||||
|
|
||||||
void *DObject::ScriptVar(FName field, PType *type)
|
void *DObject::ScriptVar(FName field, PType *type)
|
||||||
{
|
{
|
||||||
auto cls = GetClass();
|
auto cls = GetClass();
|
||||||
|
|
|
@ -277,7 +277,7 @@ void MarkArray(DObject **obj, size_t count)
|
||||||
|
|
||||||
static size_t CalcStepSize()
|
static size_t CalcStepSize()
|
||||||
{
|
{
|
||||||
int time_passed = CheckTime - LastCollectTime;
|
int time_passed = int(CheckTime - LastCollectTime);
|
||||||
auto alloc = min(LastCollectAlloc, Estimate);
|
auto alloc = min(LastCollectAlloc, Estimate);
|
||||||
size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0;
|
size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0;
|
||||||
return (StepMul > 0 && time_passed > 0)
|
return (StepMul > 0 && time_passed > 0)
|
||||||
|
@ -390,7 +390,7 @@ static size_t SingleStep()
|
||||||
case GCS_Finalize:
|
case GCS_Finalize:
|
||||||
State = GCS_Pause; // end collection
|
State = GCS_Pause; // end collection
|
||||||
LastCollectAlloc = AllocBytes;
|
LastCollectAlloc = AllocBytes;
|
||||||
LastCollectTime = CheckTime;
|
LastCollectTime = (int)CheckTime;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -183,6 +183,10 @@ public:
|
||||||
TObjPtr() = default;
|
TObjPtr() = default;
|
||||||
TObjPtr(const TObjPtr<T> &q) = default;
|
TObjPtr(const TObjPtr<T> &q) = default;
|
||||||
|
|
||||||
|
TObjPtr(T q) noexcept
|
||||||
|
: pp(q)
|
||||||
|
{
|
||||||
|
}
|
||||||
T operator=(T q)
|
T operator=(T q)
|
||||||
{
|
{
|
||||||
pp = q;
|
pp = q;
|
||||||
|
|
|
@ -42,22 +42,6 @@
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
|
|
||||||
|
|
||||||
FStartupScreen *StartScreen;
|
|
||||||
|
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (self < 0)
|
|
||||||
{
|
|
||||||
self = 0;
|
|
||||||
}
|
|
||||||
else if (self > 2)
|
|
||||||
{
|
|
||||||
self = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,18 +105,6 @@ void FBasicStartupScreen::NetProgress(const int count)
|
||||||
FConsoleWindow::GetInstance().NetProgress(count);
|
FConsoleWindow::GetInstance().NetProgress(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBasicStartupScreen::NetMessage(const char* const format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
FString message;
|
|
||||||
message.VFormat(format, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
Printf("%s\n", message.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBasicStartupScreen::NetDone()
|
void FBasicStartupScreen::NetDone()
|
||||||
{
|
{
|
||||||
FConsoleWindow::GetInstance().NetDone();
|
FConsoleWindow::GetInstance().NetDone();
|
||||||
|
@ -160,16 +132,7 @@ bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const user
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress)
|
FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress, bool showprogress)
|
||||||
{
|
{
|
||||||
return new FBasicStartupScreen(maxProgress, true);
|
return new FBasicStartupScreen(maxProgress, showprogress);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
void ST_Endoom()
|
|
||||||
{
|
|
||||||
throw CExitEvent(0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,8 @@ static const SDL_Keycode DIKToKeySym[256] =
|
||||||
SDLK_KP_8, SDLK_KP_9, SDLK_KP_MINUS, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_PLUS, SDLK_KP_1,
|
SDLK_KP_8, SDLK_KP_9, SDLK_KP_MINUS, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_PLUS, SDLK_KP_1,
|
||||||
SDLK_KP_2, SDLK_KP_3, SDLK_KP_0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11,
|
SDLK_KP_2, SDLK_KP_3, SDLK_KP_0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11,
|
||||||
SDLK_F12, 0, 0, 0, 0, 0, 0, 0,
|
SDLK_F12, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, 0,
|
0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, SDLK_F16,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
SDLK_F17, SDLK_F18, SDLK_F19, SDLK_F20, SDLK_F21, SDLK_F22, SDLK_F23, SDLK_F24,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
@ -109,8 +109,8 @@ static const SDL_Scancode DIKToKeyScan[256] =
|
||||||
SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_5, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_KP_1,
|
SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_5, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_KP_1,
|
||||||
SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F11,
|
SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F11,
|
||||||
SDL_SCANCODE_F12, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_F12, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
||||||
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_F16,
|
||||||
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_F17, SDL_SCANCODE_F18, SDL_SCANCODE_F19, SDL_SCANCODE_F20, SDL_SCANCODE_F21, SDL_SCANCODE_F22, SDL_SCANCODE_F23, SDL_SCANCODE_F24,
|
||||||
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
||||||
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
||||||
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
|
||||||
|
|
|
@ -79,7 +79,7 @@ double PerfToSec, PerfToMillisec;
|
||||||
CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
||||||
CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
||||||
|
|
||||||
extern FStartupScreen *StartScreen;
|
extern FStartupScreen *StartWindow;
|
||||||
|
|
||||||
void I_SetIWADInfo()
|
void I_SetIWADInfo()
|
||||||
{
|
{
|
||||||
|
@ -278,10 +278,10 @@ void I_PrintStr(const char *cp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StartScreen) CleanProgressBar();
|
if (StartWindow) CleanProgressBar();
|
||||||
fputs(printData.GetChars(),stdout);
|
fputs(printData.GetChars(),stdout);
|
||||||
if (terminal) fputs("\033[0m",stdout);
|
if (terminal) fputs("\033[0m",stdout);
|
||||||
if (StartScreen) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos);
|
if (StartWindow) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||||
|
|
|
@ -394,9 +394,7 @@ SDLVideo::SDLVideo ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail gracefully if we somehow reach here after linking against a SDL2 library older than 2.0.6.
|
// Fail gracefully if we somehow reach here after linking against a SDL2 library older than 2.0.6.
|
||||||
SDL_version sdlver;
|
if (!SDL_VERSION_ATLEAST(2, 0, 6))
|
||||||
SDL_GetVersion(&sdlver);
|
|
||||||
if (!(sdlver.patch >= 6))
|
|
||||||
{
|
{
|
||||||
I_FatalError("Only SDL 2.0.6 or later is supported.");
|
I_FatalError("Only SDL 2.0.6 or later is supported.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,6 @@ class FTTYStartupScreen : public FStartupScreen
|
||||||
void Progress();
|
void Progress();
|
||||||
void NetInit(const char *message, int num_players);
|
void NetInit(const char *message, int num_players);
|
||||||
void NetProgress(int count);
|
void NetProgress(int count);
|
||||||
void NetMessage(const char *format, ...); // cover for printf
|
|
||||||
void NetDone();
|
void NetDone();
|
||||||
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
|
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
|
||||||
protected:
|
protected:
|
||||||
|
@ -71,22 +70,6 @@ class FTTYStartupScreen : public FStartupScreen
|
||||||
extern void RedrawProgressBar(int CurPos, int MaxPos);
|
extern void RedrawProgressBar(int CurPos, int MaxPos);
|
||||||
extern void CleanProgressBar();
|
extern void CleanProgressBar();
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
||||||
|
|
||||||
FStartupScreen *StartScreen;
|
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (self < 0) self = 0;
|
|
||||||
else if (self > 2) self=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
|
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
|
||||||
|
@ -102,7 +85,7 @@ static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
|
FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool)
|
||||||
{
|
{
|
||||||
return new FTTYStartupScreen(max_progress);
|
return new FTTYStartupScreen(max_progress);
|
||||||
}
|
}
|
||||||
|
@ -214,27 +197,6 @@ void FTTYStartupScreen::NetDone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// FTTYStartupScreen :: NetMessage
|
|
||||||
//
|
|
||||||
// Call this between NetInit() and NetDone() instead of Printf() to
|
|
||||||
// display messages, because the progress meter is mixed in the same output
|
|
||||||
// stream as normal messages.
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void FTTYStartupScreen::NetMessage(const char *format, ...)
|
|
||||||
{
|
|
||||||
FString str;
|
|
||||||
va_list argptr;
|
|
||||||
|
|
||||||
va_start (argptr, format);
|
|
||||||
str.VFormat (format, argptr);
|
|
||||||
va_end (argptr);
|
|
||||||
fprintf (stderr, "\r%-40s\n", str.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// FTTYStartupScreen :: NetProgress
|
// FTTYStartupScreen :: NetProgress
|
||||||
|
@ -331,7 +293,3 @@ bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ST_Endoom()
|
|
||||||
{
|
|
||||||
throw CExitEvent(0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
#include "base_sysfb.h"
|
#include "base_sysfb.h"
|
||||||
#include "win32basevideo.h"
|
#include "win32basevideo.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||||
|
@ -85,7 +83,7 @@ EXTERN_CVAR(Int, vid_defheight)
|
||||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||||
scrwidth = (int)displaysettings.dmPelsWidth;
|
scrwidth = (int)displaysettings.dmPelsWidth;
|
||||||
scrheight = (int)displaysettings.dmPelsHeight;
|
scrheight = (int)displaysettings.dmPelsHeight;
|
||||||
GetWindowRect(Window, &rect);
|
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||||
cx = scrwidth / 2;
|
cx = scrwidth / 2;
|
||||||
cy = scrheight / 2;
|
cy = scrheight / 2;
|
||||||
if (in_w > 0) winw = in_w;
|
if (in_w > 0) winw = in_w;
|
||||||
|
@ -139,11 +137,11 @@ void SystemBaseFrameBuffer::SaveWindowedPos()
|
||||||
}
|
}
|
||||||
// Make sure we only save the window position if it's not fullscreen.
|
// Make sure we only save the window position if it's not fullscreen.
|
||||||
static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
|
static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
|
||||||
if ((GetWindowLong(Window, GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE)
|
if ((GetWindowLong(mainwindow.GetHandle(), GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE)
|
||||||
{
|
{
|
||||||
RECT wrect;
|
RECT wrect;
|
||||||
|
|
||||||
if (GetWindowRect(Window, &wrect))
|
if (GetWindowRect(mainwindow.GetHandle(), &wrect))
|
||||||
{
|
{
|
||||||
// If (win_x,win_y) specify to center the window, don't change them
|
// If (win_x,win_y) specify to center the window, don't change them
|
||||||
// if the window is still centered.
|
// if the window is still centered.
|
||||||
|
@ -171,7 +169,7 @@ void SystemBaseFrameBuffer::SaveWindowedPos()
|
||||||
win_h = wrect.bottom - wrect.top;
|
win_h = wrect.bottom - wrect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
win_maximized = IsZoomed(Window) == TRUE;
|
win_maximized = IsZoomed(mainwindow.GetHandle()) == TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,10 +202,10 @@ void SystemBaseFrameBuffer::RestoreWindowedPos()
|
||||||
}
|
}
|
||||||
KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight);
|
KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight);
|
||||||
}
|
}
|
||||||
SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
|
||||||
if (win_maximized && !Args->CheckParm("-0"))
|
if (win_maximized && !Args->CheckParm("-0"))
|
||||||
ShowWindow(Window, SW_MAXIMIZE);
|
ShowWindow(mainwindow.GetHandle(), SW_MAXIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -226,8 +224,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
||||||
{
|
{
|
||||||
LONG style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW;
|
LONG style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW;
|
||||||
LONG exStyle = WS_EX_WINDOWEDGE;
|
LONG exStyle = WS_EX_WINDOWEDGE;
|
||||||
SetWindowLong(Window, GWL_STYLE, style);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||||
|
|
||||||
int winx, winy, winw, winh, scrwidth, scrheight;
|
int winx, winy, winw, winh, scrwidth, scrheight;
|
||||||
|
|
||||||
|
@ -250,8 +248,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
||||||
|
|
||||||
if (!vid_fullscreen)
|
if (!vid_fullscreen)
|
||||||
{
|
{
|
||||||
ShowWindow(Window, SW_SHOWNORMAL);
|
ShowWindow(mainwindow.GetHandle(), SW_SHOWNORMAL);
|
||||||
SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
win_maximized = false;
|
win_maximized = false;
|
||||||
SetSize(GetClientWidth(), GetClientHeight());
|
SetSize(GetClientWidth(), GetClientHeight());
|
||||||
SaveWindowedPos();
|
SaveWindowedPos();
|
||||||
|
@ -302,9 +300,9 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowWindow(Window, SW_SHOW);
|
ShowWindow(mainwindow.GetHandle(), SW_SHOW);
|
||||||
|
|
||||||
GetWindowRect(Window, &r);
|
GetWindowRect(mainwindow.GetHandle(), &r);
|
||||||
style = WS_VISIBLE | WS_CLIPSIBLINGS;
|
style = WS_VISIBLE | WS_CLIPSIBLINGS;
|
||||||
exStyle = 0;
|
exStyle = 0;
|
||||||
|
|
||||||
|
@ -316,13 +314,13 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
||||||
exStyle |= WS_EX_WINDOWEDGE;
|
exStyle |= WS_EX_WINDOWEDGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowLong(Window, GWL_STYLE, style);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||||
|
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
MoveWindow(Window, monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE);
|
MoveWindow(mainwindow.GetHandle(), monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE);
|
||||||
|
|
||||||
// And now, seriously, it IS in the right place. Promise.
|
// And now, seriously, it IS in the right place. Promise.
|
||||||
}
|
}
|
||||||
|
@ -352,9 +350,9 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer(void *hMonitor, bool fullscreen) :
|
||||||
m_displayDeviceName = 0;
|
m_displayDeviceName = 0;
|
||||||
PositionWindow(fullscreen, true);
|
PositionWindow(fullscreen, true);
|
||||||
|
|
||||||
HDC hDC = GetDC(Window);
|
HDC hDC = GetDC(mainwindow.GetHandle());
|
||||||
|
|
||||||
ReleaseDC(Window, hDC);
|
ReleaseDC(mainwindow.GetHandle(), hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -367,10 +365,10 @@ SystemBaseFrameBuffer::~SystemBaseFrameBuffer()
|
||||||
{
|
{
|
||||||
if (!m_Fullscreen) SaveWindowedPos();
|
if (!m_Fullscreen) SaveWindowedPos();
|
||||||
|
|
||||||
ShowWindow (Window, SW_SHOW);
|
ShowWindow (mainwindow.GetHandle(), SW_SHOW);
|
||||||
SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
||||||
SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
|
||||||
static_cast<Win32BaseVideo *>(Video)->Shutdown();
|
static_cast<Win32BaseVideo *>(Video)->Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -407,13 +405,13 @@ void SystemBaseFrameBuffer::ToggleFullscreen(bool yes)
|
||||||
int SystemBaseFrameBuffer::GetClientWidth()
|
int SystemBaseFrameBuffer::GetClientWidth()
|
||||||
{
|
{
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
return rect.right - rect.left;
|
return rect.right - rect.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SystemBaseFrameBuffer::GetClientHeight()
|
int SystemBaseFrameBuffer::GetClientHeight()
|
||||||
{
|
{
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
return rect.bottom - rect.top;
|
return rect.bottom - rect.top;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include "win32glvideo.h"
|
#include "win32glvideo.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
extern "C" PROC zd_wglGetProcAddress(LPCSTR name);
|
extern "C" PROC zd_wglGetProcAddress(LPCSTR name);
|
||||||
|
|
||||||
|
@ -71,13 +70,13 @@ PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
|
||||||
|
|
||||||
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen)
|
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen)
|
||||||
{
|
{
|
||||||
if (!static_cast<Win32GLVideo*>(Video)->InitHardware(Window, 0))
|
if (!static_cast<Win32GLVideo*>(Video)->InitHardware(mainwindow.GetHandle(), 0))
|
||||||
{
|
{
|
||||||
I_FatalError("Unable to initialize OpenGL");
|
I_FatalError("Unable to initialize OpenGL");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC hDC = GetDC(Window);
|
HDC hDC = GetDC(mainwindow.GetHandle());
|
||||||
const char *wglext = nullptr;
|
const char *wglext = nullptr;
|
||||||
|
|
||||||
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT");
|
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT");
|
||||||
|
@ -102,7 +101,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst
|
||||||
SwapInterval = -1;
|
SwapInterval = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReleaseDC(Window, hDC);
|
ReleaseDC(mainwindow.GetHandle(), hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -52,11 +52,10 @@
|
||||||
#endif
|
#endif
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vid_preferbackend)
|
EXTERN_CVAR(Int, vid_preferbackend)
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
IVideo *Video;
|
IVideo *Video;
|
||||||
|
|
||||||
// do not include GL headers here, only declare the necessary functions.
|
// do not include GL headers here, only declare the necessary functions.
|
||||||
|
@ -117,12 +116,12 @@ void I_InitGraphics ()
|
||||||
|
|
||||||
// If the focus window is destroyed, it doesn't go back to the active window.
|
// If the focus window is destroyed, it doesn't go back to the active window.
|
||||||
// (e.g. because the net pane was up, and a button on it had focus)
|
// (e.g. because the net pane was up, and a button on it had focus)
|
||||||
if (GetFocus() == NULL && GetActiveWindow() == Window)
|
if (GetFocus() == NULL && GetActiveWindow() == mainwindow.GetHandle())
|
||||||
{
|
{
|
||||||
// Make sure it's in the foreground and focused. (It probably is
|
// Make sure it's in the foreground and focused. (It probably is
|
||||||
// already foregrounded but may not be focused.)
|
// already foregrounded but may not be focused.)
|
||||||
SetForegroundWindow(Window);
|
SetForegroundWindow(mainwindow.GetHandle());
|
||||||
SetFocus(Window);
|
SetFocus(mainwindow.GetHandle());
|
||||||
// Note that when I start a 2-player game on the same machine, the
|
// Note that when I start a 2-player game on the same machine, the
|
||||||
// window for the game that isn't focused, active, or foregrounded
|
// window for the game that isn't focused, active, or foregrounded
|
||||||
// still receives a WM_ACTIVATEAPP message telling it that it's the
|
// still receives a WM_ACTIVATEAPP message telling it that it's the
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
@ -212,9 +213,6 @@ struct MiniDumpThreadData
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
||||||
void I_FlushBufferedConsoleStuff();
|
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
static void AddFile (HANDLE file, const char *filename);
|
static void AddFile (HANDLE file, const char *filename);
|
||||||
|
@ -445,41 +443,6 @@ void Writef (HANDLE file, const char *format, ...)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb)
|
|
||||||
{
|
|
||||||
DWORD didwrite;
|
|
||||||
LONG p, pp;
|
|
||||||
|
|
||||||
// Replace gray foreground color with black.
|
|
||||||
static const char *badfg = "\\red223\\green223\\blue223;";
|
|
||||||
// 4321098 765432109 876543210
|
|
||||||
// 2 1 0
|
|
||||||
for (p = pp = 0; p < cb; ++p)
|
|
||||||
{
|
|
||||||
if (buffer[p] == badfg[pp])
|
|
||||||
{
|
|
||||||
++pp;
|
|
||||||
if (pp == 25)
|
|
||||||
{
|
|
||||||
buffer[p - 1] = buffer[p - 2] = buffer[p - 3] =
|
|
||||||
buffer[p - 9] = buffer[p -10] = buffer[p -11] =
|
|
||||||
buffer[p -18] = buffer[p -19] = buffer[p -20] = '0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WriteFile((HANDLE)cookie, buffer, cb, &didwrite, NULL))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*pcb = didwrite;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -489,15 +452,21 @@ static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
HANDLE WriteLogFile(HWND edit)
|
HANDLE WriteLogFile()
|
||||||
{
|
{
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
|
|
||||||
file = CreateTempFile();
|
file = CreateTempFile();
|
||||||
if (file != INVALID_HANDLE_VALUE)
|
if (file != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
EDITSTREAM streamer = { (DWORD_PTR)file, 0, WriteLogFileStreamer };
|
auto writeFile = [&](const void* data, uint32_t size, uint32_t& written) -> bool
|
||||||
SendMessage(edit, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
{
|
||||||
|
DWORD tmp = 0;
|
||||||
|
BOOL result = WriteFile(file, data, size, &tmp, nullptr);
|
||||||
|
written = tmp;
|
||||||
|
return result == TRUE;
|
||||||
|
};
|
||||||
|
mainwindow.GetLog(writeFile);
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +479,7 @@ HANDLE WriteLogFile(HWND edit)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog)
|
void CreateCrashLog (const char *custominfo, DWORD customsize)
|
||||||
{
|
{
|
||||||
// Do not collect information more than once.
|
// Do not collect information more than once.
|
||||||
if (NumFiles != 0)
|
if (NumFiles != 0)
|
||||||
|
@ -560,11 +529,7 @@ void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog)
|
||||||
AddFile (file, "local.txt");
|
AddFile (file, "local.txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (richlog != NULL)
|
AddFile (WriteLogFile(), "log.rtf");
|
||||||
{
|
|
||||||
I_FlushBufferedConsoleStuff();
|
|
||||||
AddFile (WriteLogFile(richlog), "log.rtf");
|
|
||||||
}
|
|
||||||
CloseHandle (DbgProcess);
|
CloseHandle (DbgProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } }
|
#define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } }
|
||||||
|
|
||||||
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
||||||
|
@ -266,7 +268,6 @@ protected:
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -372,7 +373,7 @@ bool FDInputJoystick::GetDevice()
|
||||||
Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars());
|
Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars());
|
Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars());
|
||||||
|
|
|
@ -50,18 +50,6 @@
|
||||||
#pragma warning(disable:4244)
|
#pragma warning(disable:4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compensate for w32api's lack
|
|
||||||
#ifndef WM_WTSSESSION_CHANGE
|
|
||||||
#define WM_WTSSESSION_CHANGE 0x02B1
|
|
||||||
#define WTS_CONSOLE_CONNECT 1
|
|
||||||
#define WTS_CONSOLE_DISCONNECT 2
|
|
||||||
#define WTS_SESSION_LOCK 7
|
|
||||||
#define WTS_SESSION_UNLOCK 8
|
|
||||||
#endif
|
|
||||||
#ifndef PBT_APMSUSPEND
|
|
||||||
// w32api does not #define the PBT_ macros in winuser.h like the PSDK does
|
|
||||||
#include <pbt.h>
|
|
||||||
#endif
|
|
||||||
#ifndef GET_RAWINPUT_CODE_WPARAM
|
#ifndef GET_RAWINPUT_CODE_WPARAM
|
||||||
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
|
#define GET_RAWINPUT_CODE_WPARAM(wParam) ((wParam) & 0xff)
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,6 +74,7 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "c_buttons.h"
|
#include "c_buttons.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// Compensate for w32api's lack
|
// Compensate for w32api's lack
|
||||||
#ifndef GET_XBUTTON_WPARAM
|
#ifndef GET_XBUTTON_WPARAM
|
||||||
|
@ -104,8 +93,6 @@ FJoystickCollection *JoyDevices[NUM_JOYDEVICES];
|
||||||
|
|
||||||
|
|
||||||
extern HINSTANCE g_hInst;
|
extern HINSTANCE g_hInst;
|
||||||
extern DWORD SessionID;
|
|
||||||
|
|
||||||
static HMODULE DInputDLL;
|
static HMODULE DInputDLL;
|
||||||
|
|
||||||
bool GUICapture;
|
bool GUICapture;
|
||||||
|
@ -116,7 +103,6 @@ extern bool ToggleFullscreen;
|
||||||
bool VidResizing;
|
bool VidResizing;
|
||||||
|
|
||||||
extern BOOL vidactive;
|
extern BOOL vidactive;
|
||||||
extern HWND Window, ConWindow;
|
|
||||||
|
|
||||||
EXTERN_CVAR (String, language)
|
EXTERN_CVAR (String, language)
|
||||||
EXTERN_CVAR (Bool, lookstrafe)
|
EXTERN_CVAR (Bool, lookstrafe)
|
||||||
|
@ -134,7 +120,6 @@ LPDIRECTINPUT g_pdi3;
|
||||||
|
|
||||||
extern bool AppActive;
|
extern bool AppActive;
|
||||||
|
|
||||||
int SessionState = 0;
|
|
||||||
int BlockMouseMove;
|
int BlockMouseMove;
|
||||||
|
|
||||||
static bool EventHandlerResultForNativeMouse;
|
static bool EventHandlerResultForNativeMouse;
|
||||||
|
@ -160,7 +145,7 @@ static void I_CheckGUICapture ()
|
||||||
|
|
||||||
void I_SetMouseCapture()
|
void I_SetMouseCapture()
|
||||||
{
|
{
|
||||||
SetCapture(Window);
|
SetCapture(mainwindow.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void I_ReleaseMouseCapture()
|
void I_ReleaseMouseCapture()
|
||||||
|
@ -444,7 +429,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
InvalidateRect (Window, NULL, FALSE);
|
InvalidateRect (hWnd, NULL, FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
|
@ -510,65 +495,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
S_SetSoundPaused (wParam);
|
S_SetSoundPaused (wParam);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_WTSSESSION_CHANGE:
|
|
||||||
case WM_POWERBROADCAST:
|
|
||||||
{
|
|
||||||
if (message == WM_WTSSESSION_CHANGE && lParam == (LPARAM)SessionID)
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
OutputDebugStringA ("SessionID matched\n");
|
|
||||||
#endif
|
|
||||||
// When using fast user switching, XP will lock a session before
|
|
||||||
// disconnecting it, and the session will be unlocked before reconnecting it.
|
|
||||||
// For our purposes, video output will only happen when the session is
|
|
||||||
// both unlocked and connected (that is, SessionState is 0).
|
|
||||||
switch (wParam)
|
|
||||||
{
|
|
||||||
case WTS_SESSION_LOCK:
|
|
||||||
SessionState |= 1;
|
|
||||||
break;
|
|
||||||
case WTS_SESSION_UNLOCK:
|
|
||||||
SessionState &= ~1;
|
|
||||||
break;
|
|
||||||
case WTS_CONSOLE_DISCONNECT:
|
|
||||||
SessionState |= 2;
|
|
||||||
break;
|
|
||||||
case WTS_CONSOLE_CONNECT:
|
|
||||||
SessionState &= ~2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (message == WM_POWERBROADCAST)
|
|
||||||
{
|
|
||||||
switch (wParam)
|
|
||||||
{
|
|
||||||
case PBT_APMSUSPEND:
|
|
||||||
SessionState |= 4;
|
|
||||||
break;
|
|
||||||
case PBT_APMRESUMESUSPEND:
|
|
||||||
SessionState &= ~4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GSnd != NULL)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
// Do we actually need this here?
|
|
||||||
if (!oldstate && SessionState)
|
|
||||||
{
|
|
||||||
GSnd->SuspendSound ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#ifdef _DEBUG
|
|
||||||
char foo[256];
|
|
||||||
mysnprintf (foo, countof(foo), "Session Change: %ld %d\n", (long)lParam, (int)wParam);
|
|
||||||
OutputDebugStringA (foo);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_ERASEBKGND:
|
case WM_ERASEBKGND:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -820,7 +746,7 @@ IJoystickConfig *I_UpdateDeviceList()
|
||||||
|
|
||||||
void I_PutInClipboard (const char *str)
|
void I_PutInClipboard (const char *str)
|
||||||
{
|
{
|
||||||
if (str == NULL || !OpenClipboard (Window))
|
if (str == NULL || !OpenClipboard (mainwindow.GetHandle()))
|
||||||
return;
|
return;
|
||||||
EmptyClipboard ();
|
EmptyClipboard ();
|
||||||
|
|
||||||
|
@ -842,7 +768,7 @@ FString I_GetFromClipboard (bool return_nothing)
|
||||||
HGLOBAL cliphandle;
|
HGLOBAL cliphandle;
|
||||||
wchar_t *clipstr;
|
wchar_t *clipstr;
|
||||||
|
|
||||||
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (Window))
|
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (mainwindow.GetHandle()))
|
||||||
return retstr;
|
return retstr;
|
||||||
|
|
||||||
cliphandle = GetClipboardData (CF_UNICODETEXT);
|
cliphandle = GetClipboardData (CF_UNICODETEXT);
|
||||||
|
|
|
@ -82,7 +82,6 @@ protected:
|
||||||
void ClearButtonState();
|
void ClearButtonState();
|
||||||
|
|
||||||
int WheelMove[2];
|
int WheelMove[2];
|
||||||
int LastX, LastY; // for m_filter
|
|
||||||
int ButtonState; // bit mask of current button states (1=down, 0=up)
|
int ButtonState; // bit mask of current button states (1=down, 0=up)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include "i_input.h"
|
#include "i_input.h"
|
||||||
#include "d_eventbase.h"
|
#include "d_eventbase.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
@ -87,7 +88,6 @@ protected:
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern LPDIRECTINPUT g_pdi3;
|
extern LPDIRECTINPUT g_pdi3;
|
||||||
extern bool GUICapture;
|
extern bool GUICapture;
|
||||||
|
@ -347,7 +347,7 @@ ufailit:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto ufailit;
|
goto ufailit;
|
||||||
|
@ -379,7 +379,7 @@ void FDInputKeyboard::ProcessInput()
|
||||||
DIDEVICEOBJECTDATA od;
|
DIDEVICEOBJECTDATA od;
|
||||||
DWORD dwElements;
|
DWORD dwElements;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
bool foreground = (GetForegroundWindow() == Window);
|
bool foreground = (GetForegroundWindow() == mainwindow.GetHandle());
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -448,7 +448,7 @@ bool FRawKeyboard::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_KEYBOARD;
|
rid.usUsage = HID_GDP_KEYBOARD;
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -48,9 +48,6 @@
|
||||||
#pragma warning(disable:4244)
|
#pragma warning(disable:4244)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#include <wtsapi32.h>
|
|
||||||
#define NOTIFY_FOR_THIS_SESSION 0
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <eh.h>
|
#include <eh.h>
|
||||||
#include <new.h>
|
#include <new.h>
|
||||||
|
@ -80,6 +77,8 @@
|
||||||
#include "startupinfo.h"
|
#include "startupinfo.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
// The main window's title.
|
// The main window's title.
|
||||||
|
@ -94,9 +93,8 @@
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
|
||||||
void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richedit);
|
void CreateCrashLog (const char *custominfo, DWORD customsize);
|
||||||
void DisplayCrashLog ();
|
void DisplayCrashLog ();
|
||||||
void I_FlushBufferedConsoleStuff();
|
|
||||||
void DestroyCustomCursor();
|
void DestroyCustomCursor();
|
||||||
int GameMain();
|
int GameMain();
|
||||||
|
|
||||||
|
@ -115,213 +113,13 @@ extern UINT TimerPeriod;
|
||||||
FArgs *Args;
|
FArgs *Args;
|
||||||
|
|
||||||
HINSTANCE g_hInst;
|
HINSTANCE g_hInst;
|
||||||
DWORD SessionID;
|
|
||||||
HANDLE MainThread;
|
HANDLE MainThread;
|
||||||
DWORD MainThreadID;
|
DWORD MainThreadID;
|
||||||
HANDLE StdOut;
|
HANDLE StdOut;
|
||||||
bool FancyStdOut, AttachedStdOut;
|
bool FancyStdOut, AttachedStdOut;
|
||||||
bool ConWindowHidden;
|
|
||||||
|
|
||||||
// The main window
|
|
||||||
HWND Window;
|
|
||||||
|
|
||||||
// The subwindows used for startup and error output
|
|
||||||
HWND ConWindow, GameTitleWindow;
|
|
||||||
HWND ErrorPane, ProgressBar, NetStartPane, StartupScreen, ErrorIcon;
|
|
||||||
|
|
||||||
HFONT GameTitleFont;
|
|
||||||
LONG GameTitleFontHeight;
|
|
||||||
LONG DefaultGUIFontHeight;
|
|
||||||
LONG ErrorIconChar;
|
|
||||||
|
|
||||||
FModule Kernel32Module{"Kernel32"};
|
|
||||||
FModule Shell32Module{"Shell32"};
|
|
||||||
FModule User32Module{"User32"};
|
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
||||||
|
|
||||||
static const WCHAR WinClassName[] = WGAMENAME "MainWindow";
|
|
||||||
static HMODULE hwtsapi32; // handle to wtsapi32.dll
|
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// UnCOM
|
|
||||||
//
|
|
||||||
// Called by atexit if CoInitialize() succeeded.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static void UnCOM (void)
|
|
||||||
{
|
|
||||||
CoUninitialize ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// UnWTS
|
|
||||||
//
|
|
||||||
// Called by atexit if RegisterSessionNotification() succeeded.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static void UnWTS (void)
|
|
||||||
{
|
|
||||||
if (hwtsapi32 != 0)
|
|
||||||
{
|
|
||||||
typedef BOOL (WINAPI *ursn)(HWND);
|
|
||||||
ursn unreg = (ursn)GetProcAddress (hwtsapi32, "WTSUnRegisterSessionNotification");
|
|
||||||
if (unreg != 0)
|
|
||||||
{
|
|
||||||
unreg (Window);
|
|
||||||
}
|
|
||||||
FreeLibrary (hwtsapi32);
|
|
||||||
hwtsapi32 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutErrorPane
|
|
||||||
//
|
|
||||||
// Lays out the error pane to the desired width, returning the required
|
|
||||||
// height.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static int LayoutErrorPane (HWND pane, int w)
|
|
||||||
{
|
|
||||||
HWND ctl, ctl_two;
|
|
||||||
RECT rectc, rectc_two;
|
|
||||||
|
|
||||||
// Right-align the Quit button.
|
|
||||||
ctl = GetDlgItem (pane, IDOK);
|
|
||||||
GetClientRect (ctl, &rectc); // Find out how big it is.
|
|
||||||
MoveWindow (ctl, w - rectc.right - 1, 1, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
// Second-right-align the Restart button
|
|
||||||
ctl_two = GetDlgItem (pane, IDC_BUTTON1);
|
|
||||||
GetClientRect (ctl_two, &rectc_two); // Find out how big it is.
|
|
||||||
MoveWindow (ctl_two, w - rectc.right - rectc_two.right - 2, 1, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
InvalidateRect (ctl, NULL, TRUE);
|
|
||||||
InvalidateRect (ctl_two, NULL, TRUE);
|
|
||||||
|
|
||||||
// Return the needed height for this layout
|
|
||||||
return rectc.bottom + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutNetStartPane
|
|
||||||
//
|
|
||||||
// Lays out the network startup pane to the specified width, returning
|
|
||||||
// its required height.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
int LayoutNetStartPane (HWND pane, int w)
|
|
||||||
{
|
|
||||||
HWND ctl;
|
|
||||||
RECT margin, rectc;
|
|
||||||
int staticheight, barheight;
|
|
||||||
|
|
||||||
// Determine margin sizes.
|
|
||||||
SetRect (&margin, 7, 7, 0, 0);
|
|
||||||
MapDialogRect (pane, &margin);
|
|
||||||
|
|
||||||
// Stick the message text in the upper left corner.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTMESSAGE);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
// Stick the count text in the upper right corner.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTCOUNT);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, w - rectc.right - margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
|
||||||
staticheight = rectc.bottom;
|
|
||||||
|
|
||||||
// Stretch the progress bar to fill the entire width.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTPROGRESS);
|
|
||||||
barheight = GetSystemMetrics (SM_CYVSCROLL);
|
|
||||||
MoveWindow (ctl, margin.left, margin.top*2 + staticheight, w - margin.left*2, barheight, TRUE);
|
|
||||||
|
|
||||||
// Center the abort button underneath the progress bar.
|
|
||||||
ctl = GetDlgItem (pane, IDCANCEL);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, (w - rectc.right) / 2, margin.top*3 + staticheight + barheight, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
return margin.top*4 + staticheight + barheight + rectc.bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutMainWindow
|
|
||||||
//
|
|
||||||
// Lays out the main window with the game title and log controls and
|
|
||||||
// possibly the error pane and progress bar.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void LayoutMainWindow (HWND hWnd, HWND pane)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
int errorpaneheight = 0;
|
|
||||||
int bannerheight = 0;
|
|
||||||
int progressheight = 0;
|
|
||||||
int netpaneheight = 0;
|
|
||||||
int leftside = 0;
|
|
||||||
int w, h;
|
|
||||||
|
|
||||||
GetClientRect (hWnd, &rect);
|
|
||||||
w = rect.right;
|
|
||||||
h = rect.bottom;
|
|
||||||
|
|
||||||
if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL)
|
|
||||||
{
|
|
||||||
bannerheight = GameTitleFontHeight + 5;
|
|
||||||
MoveWindow (GameTitleWindow, 0, 0, w, bannerheight, TRUE);
|
|
||||||
InvalidateRect (GameTitleWindow, NULL, FALSE);
|
|
||||||
}
|
|
||||||
if (ProgressBar != NULL)
|
|
||||||
{
|
|
||||||
// Base the height of the progress bar on the height of a scroll bar
|
|
||||||
// arrow, just as in the progress bar example.
|
|
||||||
progressheight = GetSystemMetrics (SM_CYVSCROLL);
|
|
||||||
MoveWindow (ProgressBar, 0, h - progressheight, w, progressheight, TRUE);
|
|
||||||
}
|
|
||||||
if (NetStartPane != NULL)
|
|
||||||
{
|
|
||||||
netpaneheight = LayoutNetStartPane (NetStartPane, w);
|
|
||||||
SetWindowPos (NetStartPane, HWND_TOP, 0, h - progressheight - netpaneheight, w, netpaneheight, SWP_SHOWWINDOW);
|
|
||||||
}
|
|
||||||
if (pane != NULL)
|
|
||||||
{
|
|
||||||
errorpaneheight = LayoutErrorPane (pane, w);
|
|
||||||
SetWindowPos (pane, HWND_TOP, 0, h - progressheight - netpaneheight - errorpaneheight, w, errorpaneheight, 0);
|
|
||||||
}
|
|
||||||
if (ErrorIcon != NULL)
|
|
||||||
{
|
|
||||||
leftside = GetSystemMetrics (SM_CXICON) + 6;
|
|
||||||
MoveWindow (ErrorIcon, 0, bannerheight, leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
|
||||||
}
|
|
||||||
// If there is a startup screen, it covers the log window
|
|
||||||
if (StartupScreen != NULL)
|
|
||||||
{
|
|
||||||
SetWindowPos (StartupScreen, HWND_TOP, leftside, bannerheight, w - leftside,
|
|
||||||
h - bannerheight - errorpaneheight - progressheight - netpaneheight, SWP_SHOWWINDOW);
|
|
||||||
InvalidateRect (StartupScreen, NULL, FALSE);
|
|
||||||
MoveWindow (ConWindow, 0, 0, 0, 0, TRUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The log window uses whatever space is left.
|
|
||||||
MoveWindow (ConWindow, leftside, bannerheight, w - leftside,
|
|
||||||
h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -332,436 +130,7 @@ void LayoutMainWindow (HWND hWnd, HWND pane)
|
||||||
void I_SetIWADInfo()
|
void I_SetIWADInfo()
|
||||||
{
|
{
|
||||||
// Make the startup banner show itself
|
// Make the startup banner show itself
|
||||||
LayoutMainWindow(Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LConProc
|
|
||||||
//
|
|
||||||
// The main window's WndProc during startup. During gameplay, the WndProc
|
|
||||||
// in i_input.cpp is used instead.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
HWND view;
|
|
||||||
HDC hdc;
|
|
||||||
HBRUSH hbr;
|
|
||||||
HGDIOBJ oldfont;
|
|
||||||
RECT rect;
|
|
||||||
SIZE size;
|
|
||||||
LOGFONT lf;
|
|
||||||
TEXTMETRIC tm;
|
|
||||||
HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
|
|
||||||
DRAWITEMSTRUCT *drawitem;
|
|
||||||
CHARFORMAT2W format;
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_CREATE:
|
|
||||||
// Create game title static control
|
|
||||||
memset (&lf, 0, sizeof(lf));
|
|
||||||
hdc = GetDC (hWnd);
|
|
||||||
lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
|
||||||
lf.lfCharSet = ANSI_CHARSET;
|
|
||||||
lf.lfWeight = FW_BOLD;
|
|
||||||
lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
|
|
||||||
wcscpy (lf.lfFaceName, L"Trebuchet MS");
|
|
||||||
GameTitleFont = CreateFontIndirect (&lf);
|
|
||||||
|
|
||||||
oldfont = SelectObject (hdc, GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
GetTextMetrics (hdc, &tm);
|
|
||||||
DefaultGUIFontHeight = tm.tmHeight;
|
|
||||||
if (GameTitleFont == NULL)
|
|
||||||
{
|
|
||||||
GameTitleFontHeight = DefaultGUIFontHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SelectObject (hdc, GameTitleFont);
|
|
||||||
GetTextMetrics (hdc, &tm);
|
|
||||||
GameTitleFontHeight = tm.tmHeight;
|
|
||||||
}
|
|
||||||
SelectObject (hdc, oldfont);
|
|
||||||
|
|
||||||
// Create log read-only edit control
|
|
||||||
view = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"RichEdit20W", nullptr,
|
|
||||||
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
|
||||||
ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
hWnd, NULL, inst, NULL);
|
|
||||||
HRESULT hr;
|
|
||||||
hr = GetLastError();
|
|
||||||
if (view == NULL)
|
|
||||||
{
|
|
||||||
ReleaseDC (hWnd, hdc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SendMessage (view, EM_SETREADONLY, TRUE, 0);
|
|
||||||
SendMessage (view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE);
|
|
||||||
SendMessage (view, EM_SETBKGNDCOLOR, 0, RGB(70,70,70));
|
|
||||||
// Setup default font for the log.
|
|
||||||
//SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE);
|
|
||||||
format.cbSize = sizeof(format);
|
|
||||||
format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET;
|
|
||||||
format.dwEffects = 0;
|
|
||||||
format.yHeight = 200;
|
|
||||||
format.crTextColor = RGB(223,223,223);
|
|
||||||
format.bCharSet = ANSI_CHARSET;
|
|
||||||
format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
|
|
||||||
wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p
|
|
||||||
SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format);
|
|
||||||
|
|
||||||
ConWindow = view;
|
|
||||||
ReleaseDC (hWnd, hdc);
|
|
||||||
|
|
||||||
view = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, nullptr, inst, nullptr);
|
|
||||||
if (view == nullptr)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SetWindowLong (view, GWL_ID, IDC_STATIC_TITLE);
|
|
||||||
GameTitleWindow = view;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_SIZE:
|
|
||||||
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
|
|
||||||
{
|
|
||||||
LayoutMainWindow (hWnd, ErrorPane);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_DRAWITEM:
|
|
||||||
// Draw title banner.
|
|
||||||
if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty())
|
|
||||||
{
|
|
||||||
const PalEntry *c;
|
|
||||||
|
|
||||||
// Draw the game title strip at the top of the window.
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
// Draw the background.
|
|
||||||
rect = drawitem->rcItem;
|
|
||||||
rect.bottom -= 1;
|
|
||||||
c = (const PalEntry *)&GameStartupInfo.BkColor;
|
|
||||||
hbr = CreateSolidBrush (RGB(c->r,c->g,c->b));
|
|
||||||
FillRect (drawitem->hDC, &drawitem->rcItem, hbr);
|
|
||||||
DeleteObject (hbr);
|
|
||||||
|
|
||||||
// Calculate width of the title string.
|
|
||||||
SetTextAlign (drawitem->hDC, TA_TOP);
|
|
||||||
oldfont = SelectObject (drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
auto widename = GameStartupInfo.Name.WideString();
|
|
||||||
GetTextExtentPoint32W (drawitem->hDC, widename.c_str(), (int)widename.length(), &size);
|
|
||||||
|
|
||||||
// Draw the title.
|
|
||||||
c = (const PalEntry *)&GameStartupInfo.FgColor;
|
|
||||||
SetTextColor (drawitem->hDC, RGB(c->r,c->g,c->b));
|
|
||||||
SetBkMode (drawitem->hDC, TRANSPARENT);
|
|
||||||
TextOutW (drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length());
|
|
||||||
SelectObject (drawitem->hDC, oldfont);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
// Draw startup screen
|
|
||||||
else if (wParam == IDC_STATIC_STARTUP)
|
|
||||||
{
|
|
||||||
if (StartupScreen != NULL)
|
|
||||||
{
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
rect = drawitem->rcItem;
|
|
||||||
// Windows expects DIBs to be bottom-up but ours is top-down,
|
|
||||||
// so flip it vertically while drawing it.
|
|
||||||
StretchDIBits (drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom,
|
|
||||||
0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight,
|
|
||||||
ST_Util_BitsForBitmap(StartupBitmap), reinterpret_cast<const BITMAPINFO*>(StartupBitmap), DIB_RGB_COLORS, SRCCOPY);
|
|
||||||
|
|
||||||
// If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt
|
|
||||||
// where the command prompt would have been in DOS.
|
|
||||||
if (GameTitleWindow == NULL)
|
|
||||||
{
|
|
||||||
auto quitmsg = WideString(GStrings("TXT_QUITENDOOM"));
|
|
||||||
|
|
||||||
SetTextColor (drawitem->hDC, RGB(240,240,240));
|
|
||||||
SetBkMode (drawitem->hDC, TRANSPARENT);
|
|
||||||
oldfont = SelectObject (drawitem->hDC, (HFONT)GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
TextOutW (drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, quitmsg.c_str(), (int)quitmsg.length());
|
|
||||||
SelectObject (drawitem->hDC, oldfont);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Draw stop icon.
|
|
||||||
else if (wParam == IDC_ICONPIC)
|
|
||||||
{
|
|
||||||
HICON icon;
|
|
||||||
POINTL char_pos;
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
// This background color should match the edit control's.
|
|
||||||
hbr = CreateSolidBrush (RGB(70,70,70));
|
|
||||||
FillRect (drawitem->hDC, &drawitem->rcItem, hbr);
|
|
||||||
DeleteObject (hbr);
|
|
||||||
|
|
||||||
// Draw the icon aligned with the first line of error text.
|
|
||||||
SendMessage (ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar);
|
|
||||||
icon = (HICON)LoadImage (0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
|
||||||
DrawIcon (drawitem->hDC, 6, char_pos.y, icon);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE)
|
|
||||||
{
|
|
||||||
// Be sure to redraw the error icon if the edit control changes.
|
|
||||||
InvalidateRect (ErrorIcon, NULL, TRUE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
PostQuitMessage (0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
|
||||||
if (GameTitleFont != NULL)
|
|
||||||
{
|
|
||||||
DeleteObject (GameTitleFont);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return DefWindowProc (hWnd, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ErrorPaneProc
|
|
||||||
//
|
|
||||||
// DialogProc for the error pane.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool restartrequest;
|
|
||||||
|
|
||||||
void CheckForRestart()
|
|
||||||
{
|
|
||||||
if (restartrequest)
|
|
||||||
{
|
|
||||||
HMODULE hModule = GetModuleHandleW(NULL);
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
GetModuleFileNameW(hModule, path, MAX_PATH);
|
|
||||||
ShellExecuteW(NULL, L"open", path, GetCommandLineW(), NULL, SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
restartrequest = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
INT_PTR CALLBACK ErrorPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
// Appear in the main window.
|
|
||||||
LayoutMainWindow (GetParent (hDlg), hDlg);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (HIWORD(wParam) == BN_CLICKED)
|
|
||||||
{
|
|
||||||
if (LOWORD(wParam) == IDC_BUTTON1) // we pressed the restart button, so run GZDoom again
|
|
||||||
{
|
|
||||||
restartrequest = true;
|
|
||||||
}
|
|
||||||
PostQuitMessage (0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// I_SetWndProc
|
|
||||||
//
|
|
||||||
// Sets the main WndProc, hides all the child windows, and starts up
|
|
||||||
// in-game input.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void I_SetWndProc()
|
|
||||||
{
|
|
||||||
if (GetWindowLongPtr (Window, GWLP_USERDATA) == 0)
|
|
||||||
{
|
|
||||||
SetWindowLongPtr (Window, GWLP_USERDATA, 1);
|
|
||||||
SetWindowLongPtr (Window, GWLP_WNDPROC, (WLONG_PTR)WndProc);
|
|
||||||
ShowWindow (ConWindow, SW_HIDE);
|
|
||||||
ShowWindow(ProgressBar, SW_HIDE);
|
|
||||||
ConWindowHidden = true;
|
|
||||||
ShowWindow (GameTitleWindow, SW_HIDE);
|
|
||||||
I_InitInput (Window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// RestoreConView
|
|
||||||
//
|
|
||||||
// Returns the main window to its startup state.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void RestoreConView()
|
|
||||||
{
|
|
||||||
HDC screenDC = GetDC(0);
|
|
||||||
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
|
||||||
ReleaseDC(0, screenDC);
|
|
||||||
int width = (512 * dpi + 96 / 2) / 96;
|
|
||||||
int height = (384 * dpi + 96 / 2) / 96;
|
|
||||||
|
|
||||||
// Make sure the window has a frame in case it was fullscreened.
|
|
||||||
SetWindowLongPtr (Window, GWL_STYLE, WS_VISIBLE|WS_OVERLAPPEDWINDOW);
|
|
||||||
if (GetWindowLong (Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
|
|
||||||
{
|
|
||||||
SetWindowPos (Window, HWND_BOTTOM, 0, 0, width, height,
|
|
||||||
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
|
|
||||||
SetWindowPos (Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetWindowPos (Window, NULL, 0, 0, width, height,
|
|
||||||
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowLongPtr (Window, GWLP_WNDPROC, (WLONG_PTR)LConProc);
|
|
||||||
ShowWindow (ConWindow, SW_SHOW);
|
|
||||||
ConWindowHidden = false;
|
|
||||||
ShowWindow (GameTitleWindow, SW_SHOW);
|
|
||||||
I_ShutdownInput (); // Make sure the mouse pointer is available.
|
|
||||||
// Make sure the progress bar isn't visible.
|
|
||||||
DeleteStartupScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ShowErrorPane
|
|
||||||
//
|
|
||||||
// Shows an error message, preferably in the main window, but it can
|
|
||||||
// use a normal message box too.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void ShowErrorPane(const char *text)
|
|
||||||
{
|
|
||||||
auto widetext = WideString(text);
|
|
||||||
if (Window == nullptr || ConWindow == nullptr)
|
|
||||||
{
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
MessageBoxW (Window, widetext.c_str(),
|
|
||||||
WGAMENAME " Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StartScreen != NULL) // Ensure that the network pane is hidden.
|
|
||||||
{
|
|
||||||
StartScreen->NetDone();
|
|
||||||
}
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
|
||||||
auto wcaption = caption.WideString();
|
|
||||||
SetWindowTextW (Window, wcaption.c_str());
|
|
||||||
ErrorIcon = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, g_hInst, NULL);
|
|
||||||
if (ErrorIcon != NULL)
|
|
||||||
{
|
|
||||||
SetWindowLong (ErrorIcon, GWL_ID, IDC_ICONPIC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ErrorPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL);
|
|
||||||
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
CHARRANGE end;
|
|
||||||
CHARFORMAT2 oldformat, newformat;
|
|
||||||
PARAFORMAT2 paraformat;
|
|
||||||
|
|
||||||
// Append the error message to the log.
|
|
||||||
end.cpMax = end.cpMin = GetWindowTextLength (ConWindow);
|
|
||||||
SendMessage (ConWindow, EM_EXSETSEL, 0, (LPARAM)&end);
|
|
||||||
|
|
||||||
// Remember current charformat.
|
|
||||||
oldformat.cbSize = sizeof(oldformat);
|
|
||||||
SendMessage (ConWindow, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
|
||||||
|
|
||||||
// Use bigger font and standout colors.
|
|
||||||
newformat.cbSize = sizeof(newformat);
|
|
||||||
newformat.dwMask = CFM_BOLD | CFM_COLOR | CFM_SIZE;
|
|
||||||
newformat.dwEffects = CFE_BOLD;
|
|
||||||
newformat.yHeight = oldformat.yHeight * 5 / 4;
|
|
||||||
newformat.crTextColor = RGB(255,170,170);
|
|
||||||
SendMessage (ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&newformat);
|
|
||||||
|
|
||||||
// Indent the rest of the text to make the error message stand out a little more.
|
|
||||||
paraformat.cbSize = sizeof(paraformat);
|
|
||||||
paraformat.dwMask = PFM_STARTINDENT | PFM_OFFSETINDENT | PFM_RIGHTINDENT;
|
|
||||||
paraformat.dxStartIndent = paraformat.dxOffset = paraformat.dxRightIndent = 120;
|
|
||||||
SendMessage (ConWindow, EM_SETPARAFORMAT, 0, (LPARAM)¶format);
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"\n");
|
|
||||||
|
|
||||||
// Find out where the error lines start for the error icon display control.
|
|
||||||
SendMessage (ConWindow, EM_EXGETSEL, 0, (LPARAM)&end);
|
|
||||||
ErrorIconChar = end.cpMax;
|
|
||||||
|
|
||||||
// Now start adding the actual error message.
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"Execution could not continue.\n\n");
|
|
||||||
|
|
||||||
// Restore old charformat but with light yellow text.
|
|
||||||
oldformat.crTextColor = RGB(255,255,170);
|
|
||||||
SendMessage (ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
|
||||||
|
|
||||||
// Add the error text.
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)widetext.c_str());
|
|
||||||
|
|
||||||
// Make sure the error text is not scrolled below the window.
|
|
||||||
SendMessage (ConWindow, EM_LINESCROLL, 0, SendMessage (ConWindow, EM_GETLINECOUNT, 0, 0));
|
|
||||||
// The above line scrolled everything off the screen, so pretend to move the scroll
|
|
||||||
// bar thumb, which clamps to not show any extra lines if it doesn't need to.
|
|
||||||
SendMessage (ConWindow, EM_SCROLL, SB_PAGEDOWN, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL bRet;
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
|
||||||
{
|
|
||||||
if (bRet == -1)
|
|
||||||
{
|
|
||||||
MessageBoxW (Window, widetext.c_str(), WGAMENAME " Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!IsDialogMessage (ErrorPane, &msg))
|
|
||||||
{
|
|
||||||
TranslateMessage (&msg);
|
|
||||||
DispatchMessage (&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeekThreadedErrorPane()
|
|
||||||
{
|
|
||||||
// Allow SendMessage from another thread to call its message handler so that it can display the crash dialog
|
|
||||||
MSG msg;
|
|
||||||
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void UnTbp()
|
|
||||||
{
|
|
||||||
timeEndPeriod(TimerPeriod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -788,16 +157,6 @@ int DoMain (HINSTANCE hInstance)
|
||||||
Args->AppendArg(FString(wargv[i]));
|
Args->AppendArg(FString(wargv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Win32 modules
|
|
||||||
Kernel32Module.Load({"kernel32.dll"});
|
|
||||||
Shell32Module.Load({"shell32.dll"});
|
|
||||||
User32Module.Load({"user32.dll"});
|
|
||||||
|
|
||||||
// Under XP, get our session ID so we can know when the user changes/locks sessions.
|
|
||||||
// Since we need to remain binary compatible with older versions of Windows, we
|
|
||||||
// need to extract the ProcessIdToSessionId function from kernel32.dll manually.
|
|
||||||
HMODULE kernel = GetModuleHandleA ("kernel32.dll");
|
|
||||||
|
|
||||||
if (Args->CheckParm("-stdout"))
|
if (Args->CheckParm("-stdout"))
|
||||||
{
|
{
|
||||||
// As a GUI application, we don't normally get a console when we start.
|
// As a GUI application, we don't normally get a console when we start.
|
||||||
|
@ -833,26 +192,17 @@ int DoMain (HINSTANCE hInstance)
|
||||||
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// These two functions do not exist in Windows XP.
|
// Deprecated stuff for legacy consoles. As of now this is still relevant, but this code can be removed once Windows 7 is no longer relevant.
|
||||||
BOOL (WINAPI* p_GetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
CONSOLE_FONT_INFOEX cfi;
|
||||||
BOOL (WINAPI* p_SetCurrentConsoleFontEx)(HANDLE hConsoleOutput, BOOL bMaximumWindow, PCONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
|
cfi.cbSize = sizeof(cfi);
|
||||||
|
if (GetCurrentConsoleFontEx(StdOut, false, &cfi))
|
||||||
p_SetCurrentConsoleFontEx = (decltype(p_SetCurrentConsoleFontEx))GetProcAddress(kernel, "SetCurrentConsoleFontEx");
|
|
||||||
p_GetCurrentConsoleFontEx = (decltype(p_GetCurrentConsoleFontEx))GetProcAddress(kernel, "GetCurrentConsoleFontEx");
|
|
||||||
if (p_SetCurrentConsoleFontEx && p_GetCurrentConsoleFontEx)
|
|
||||||
{
|
{
|
||||||
CONSOLE_FONT_INFOEX cfi;
|
if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive.
|
||||||
cfi.cbSize = sizeof(cfi);
|
|
||||||
|
|
||||||
if (p_GetCurrentConsoleFontEx(StdOut, false, &cfi))
|
|
||||||
{
|
{
|
||||||
if (*cfi.FaceName == 0) // If the face name is empty, the default (useless) raster font is actoive.
|
//cfi.dwFontSize = { 8, 14 };
|
||||||
{
|
wcscpy(cfi.FaceName, L"Lucida Console");
|
||||||
//cfi.dwFontSize = { 8, 14 };
|
cfi.FontFamily = FF_DONTCARE;
|
||||||
wcscpy(cfi.FaceName, L"Lucida Console");
|
SetCurrentConsoleFontEx(StdOut, false, &cfi);
|
||||||
cfi.FontFamily = FF_DONTCARE;
|
|
||||||
p_SetCurrentConsoleFontEx(StdOut, false, &cfi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FancyStdOut = true;
|
FancyStdOut = true;
|
||||||
|
@ -866,7 +216,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
TimerPeriod = tc.wPeriodMin;
|
TimerPeriod = tc.wPeriodMin;
|
||||||
|
|
||||||
timeBeginPeriod (TimerPeriod);
|
timeBeginPeriod (TimerPeriod);
|
||||||
atexit(UnTbp);
|
atexit([](){ timeEndPeriod(TimerPeriod); });
|
||||||
|
|
||||||
// Figure out what directory the program resides in.
|
// Figure out what directory the program resides in.
|
||||||
WCHAR progbuff[1024];
|
WCHAR progbuff[1024];
|
||||||
|
@ -904,82 +254,20 @@ int DoMain (HINSTANCE hInstance)
|
||||||
x = y = 0;
|
x = y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WNDCLASS WndClass;
|
|
||||||
WndClass.style = 0;
|
|
||||||
WndClass.lpfnWndProc = LConProc;
|
|
||||||
WndClass.cbClsExtra = 0;
|
|
||||||
WndClass.cbWndExtra = 0;
|
|
||||||
WndClass.hInstance = hInstance;
|
|
||||||
WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
|
||||||
WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
||||||
WndClass.hbrBackground = NULL;
|
|
||||||
WndClass.lpszMenuName = NULL;
|
|
||||||
WndClass.lpszClassName = WinClassName;
|
|
||||||
|
|
||||||
/* register this new class with Windows */
|
|
||||||
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create window */
|
/* create window */
|
||||||
FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
std::wstring wcaption = caption.WideString();
|
mainwindow.Create(caption, x, y, width, height);
|
||||||
Window = CreateWindowExW(
|
|
||||||
WS_EX_APPWINDOW,
|
|
||||||
WinClassName,
|
|
||||||
wcaption.c_str(),
|
|
||||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
|
||||||
x, y, width, height,
|
|
||||||
(HWND) NULL,
|
|
||||||
(HMENU) NULL,
|
|
||||||
hInstance,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!Window)
|
GetClientRect (mainwindow.GetHandle(), &cRect);
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kernel != NULL)
|
|
||||||
{
|
|
||||||
typedef BOOL (WINAPI *pts)(DWORD, DWORD *);
|
|
||||||
pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId");
|
|
||||||
if (pidsid != 0)
|
|
||||||
{
|
|
||||||
if (!pidsid (GetCurrentProcessId(), &SessionID))
|
|
||||||
{
|
|
||||||
SessionID = 0;
|
|
||||||
}
|
|
||||||
hwtsapi32 = LoadLibraryA ("wtsapi32.dll");
|
|
||||||
if (hwtsapi32 != 0)
|
|
||||||
{
|
|
||||||
FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification");
|
|
||||||
if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION))
|
|
||||||
{
|
|
||||||
FreeLibrary (hwtsapi32);
|
|
||||||
hwtsapi32 = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
atexit (UnWTS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GetClientRect (Window, &cRect);
|
|
||||||
|
|
||||||
WinWidth = cRect.right;
|
WinWidth = cRect.right;
|
||||||
WinHeight = cRect.bottom;
|
WinHeight = cRect.bottom;
|
||||||
|
|
||||||
CoInitialize (NULL);
|
CoInitialize (NULL);
|
||||||
atexit (UnCOM);
|
atexit ([](){ CoUninitialize(); }); // beware of calling convention.
|
||||||
|
|
||||||
int ret = GameMain ();
|
int ret = GameMain ();
|
||||||
CheckForRestart();
|
mainwindow.CheckForRestart();
|
||||||
|
|
||||||
DestroyCustomCursor();
|
DestroyCustomCursor();
|
||||||
if (ret == 1337) // special exit code for 'norun'.
|
if (ret == 1337) // special exit code for 'norun'.
|
||||||
|
@ -991,7 +279,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
ShowWindow(Window, SW_HIDE);
|
ShowWindow(mainwindow.GetHandle(), SW_HIDE);
|
||||||
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
||||||
FlushConsoleInputBuffer(stdinput);
|
FlushConsoleInputBuffer(stdinput);
|
||||||
SetConsoleMode(stdinput, 0);
|
SetConsoleMode(stdinput, 0);
|
||||||
|
@ -999,7 +287,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
}
|
}
|
||||||
else if (StdOut == NULL)
|
else if (StdOut == NULL)
|
||||||
{
|
{
|
||||||
ShowErrorPane(NULL);
|
mainwindow.ShowErrorPane(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1009,9 +297,8 @@ int DoMain (HINSTANCE hInstance)
|
||||||
void I_ShowFatalError(const char *msg)
|
void I_ShowFatalError(const char *msg)
|
||||||
{
|
{
|
||||||
I_ShutdownGraphics ();
|
I_ShutdownGraphics ();
|
||||||
RestoreConView ();
|
mainwindow.RestoreConView();
|
||||||
S_StopMusic(true);
|
S_StopMusic(true);
|
||||||
I_FlushBufferedConsoleStuff();
|
|
||||||
|
|
||||||
if (CVMAbortException::stacktrace.IsNotEmpty())
|
if (CVMAbortException::stacktrace.IsNotEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1020,7 +307,7 @@ void I_ShowFatalError(const char *msg)
|
||||||
|
|
||||||
if (!batchrun)
|
if (!batchrun)
|
||||||
{
|
{
|
||||||
ShowErrorPane(msg);
|
mainwindow.ShowErrorPane(msg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1087,7 +374,7 @@ void CALLBACK ExitFatally (ULONG_PTR dummy)
|
||||||
{
|
{
|
||||||
SetUnhandledExceptionFilter (ExitMessedUp);
|
SetUnhandledExceptionFilter (ExitMessedUp);
|
||||||
I_ShutdownGraphics ();
|
I_ShutdownGraphics ();
|
||||||
RestoreConView ();
|
mainwindow.RestoreConView ();
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +409,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info)
|
||||||
|
|
||||||
CrashPointers = *info;
|
CrashPointers = *info;
|
||||||
if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n");
|
if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n");
|
||||||
CreateCrashLog (custominfo, (DWORD)strlen(custominfo), ConWindow);
|
CreateCrashLog (custominfo, (DWORD)strlen(custominfo));
|
||||||
|
|
||||||
// If the main thread crashed, then make it clean up after itself.
|
// If the main thread crashed, then make it clean up after itself.
|
||||||
// Otherwise, put the crashing thread to sleep and signal the main thread to clean up.
|
// Otherwise, put the crashing thread to sleep and signal the main thread to clean up.
|
||||||
|
@ -1208,7 +495,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
||||||
*(int *)0 = 0;
|
*(int *)0 = 0;
|
||||||
}
|
}
|
||||||
__except(CrashPointers = *GetExceptionInformation(),
|
__except(CrashPointers = *GetExceptionInformation(),
|
||||||
CreateCrashLog ("TestCrash", 9, NULL), EXCEPTION_EXECUTE_HANDLER)
|
CreateCrashLog ("TestCrash", 9), EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
|
@ -1221,7 +508,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
||||||
infiniterecursion(1);
|
infiniterecursion(1);
|
||||||
}
|
}
|
||||||
__except(CrashPointers = *GetExceptionInformation(),
|
__except(CrashPointers = *GetExceptionInformation(),
|
||||||
CreateCrashLog ("TestStackCrash", 14, NULL), EXCEPTION_EXECUTE_HANDLER)
|
CreateCrashLog ("TestStackCrash", 14), EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
|
@ -1277,15 +564,5 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
||||||
// each platform has its own specific version of this function.
|
// each platform has its own specific version of this function.
|
||||||
void I_SetWindowTitle(const char* caption)
|
void I_SetWindowTitle(const char* caption)
|
||||||
{
|
{
|
||||||
std::wstring widecaption;
|
mainwindow.SetWindowTitle(caption);
|
||||||
if (!caption)
|
|
||||||
{
|
|
||||||
FStringf default_caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
|
||||||
widecaption = default_caption.WideString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
widecaption = WideString(caption);
|
|
||||||
}
|
|
||||||
SetWindowText(Window, widecaption.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
881
source/common/platform/win32/i_mainwindow.cpp
Normal file
881
source/common/platform/win32/i_mainwindow.cpp
Normal file
|
@ -0,0 +1,881 @@
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "palentry.h"
|
||||||
|
#include "st_start.h"
|
||||||
|
#include "i_input.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
#include "v_font.h"
|
||||||
|
#include "i_net.h"
|
||||||
|
#include <richedit.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
|
#ifdef _M_X64
|
||||||
|
#define X64 " 64-bit"
|
||||||
|
#else
|
||||||
|
#define X64 ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MainWindow mainwindow;
|
||||||
|
|
||||||
|
void MainWindow::Create(const FString& caption, int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
static const WCHAR WinClassName[] = L"MainWindow";
|
||||||
|
|
||||||
|
HINSTANCE hInstance = GetModuleHandle(0);
|
||||||
|
|
||||||
|
WNDCLASS WndClass;
|
||||||
|
WndClass.style = 0;
|
||||||
|
WndClass.lpfnWndProc = LConProc;
|
||||||
|
WndClass.cbClsExtra = 0;
|
||||||
|
WndClass.cbWndExtra = 0;
|
||||||
|
WndClass.hInstance = hInstance;
|
||||||
|
WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||||
|
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
WndClass.hbrBackground = NULL;
|
||||||
|
WndClass.lpszMenuName = NULL;
|
||||||
|
WndClass.lpszClassName = WinClassName;
|
||||||
|
|
||||||
|
/* register this new class with Windows */
|
||||||
|
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring wcaption = caption.WideString();
|
||||||
|
Window = CreateWindowExW(
|
||||||
|
WS_EX_APPWINDOW,
|
||||||
|
WinClassName,
|
||||||
|
wcaption.c_str(),
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
||||||
|
x, y, width, height,
|
||||||
|
(HWND)NULL,
|
||||||
|
(HMENU)NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!Window)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideGameTitleWindow()
|
||||||
|
{
|
||||||
|
if (GameTitleWindow != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(GameTitleWindow);
|
||||||
|
GameTitleWindow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MainWindow::GetGameTitleWindowHeight()
|
||||||
|
{
|
||||||
|
if (GameTitleWindow != 0)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(GameTitleWindow, &rect);
|
||||||
|
return rect.bottom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the main WndProc, hides all the child windows, and starts up in-game input.
|
||||||
|
void MainWindow::ShowGameView()
|
||||||
|
{
|
||||||
|
if (GetWindowLongPtr(Window, GWLP_USERDATA) == 0)
|
||||||
|
{
|
||||||
|
SetWindowLongPtr(Window, GWLP_USERDATA, 1);
|
||||||
|
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)WndProc);
|
||||||
|
ShowWindow(ConWindow, SW_HIDE);
|
||||||
|
ShowWindow(ProgressBar, SW_HIDE);
|
||||||
|
ConWindowHidden = true;
|
||||||
|
ShowWindow(GameTitleWindow, SW_HIDE);
|
||||||
|
I_InitInput(Window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the main window to its startup state.
|
||||||
|
void MainWindow::RestoreConView()
|
||||||
|
{
|
||||||
|
HDC screenDC = GetDC(0);
|
||||||
|
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
||||||
|
ReleaseDC(0, screenDC);
|
||||||
|
int width = (512 * dpi + 96 / 2) / 96;
|
||||||
|
int height = (384 * dpi + 96 / 2) / 96;
|
||||||
|
|
||||||
|
// Make sure the window has a frame in case it was fullscreened.
|
||||||
|
SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
|
||||||
|
if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
|
||||||
|
{
|
||||||
|
SetWindowPos(Window, HWND_BOTTOM, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
|
||||||
|
SetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetWindowPos(Window, NULL, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)LConProc);
|
||||||
|
ShowWindow(ConWindow, SW_SHOW);
|
||||||
|
ConWindowHidden = false;
|
||||||
|
ShowWindow(GameTitleWindow, SW_SHOW);
|
||||||
|
I_ShutdownInput(); // Make sure the mouse pointer is available.
|
||||||
|
// Make sure the progress bar isn't visible.
|
||||||
|
DeleteStartupScreen();
|
||||||
|
|
||||||
|
FlushBufferedConsoleStuff();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows an error message, preferably in the main window, but it can use a normal message box too.
|
||||||
|
void MainWindow::ShowErrorPane(const char* text)
|
||||||
|
{
|
||||||
|
auto widetext = WideString(text);
|
||||||
|
if (Window == nullptr || ConWindow == nullptr)
|
||||||
|
{
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
MessageBoxW(Window, widetext.c_str(),caption.WideString().c_str(), MB_OK | MB_ICONSTOP | MB_TASKMODAL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StartWindow != NULL) // Ensure that the network pane is hidden.
|
||||||
|
{
|
||||||
|
I_NetDone();
|
||||||
|
}
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
auto wcaption = caption.WideString();
|
||||||
|
SetWindowTextW(Window, wcaption.c_str());
|
||||||
|
ErrorIcon = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, GetModuleHandle(0), NULL);
|
||||||
|
if (ErrorIcon != NULL)
|
||||||
|
{
|
||||||
|
SetWindowLong(ErrorIcon, GWL_ID, IDC_ICONPIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL);
|
||||||
|
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
CHARRANGE end;
|
||||||
|
CHARFORMAT2 oldformat, newformat;
|
||||||
|
PARAFORMAT2 paraformat;
|
||||||
|
|
||||||
|
// Append the error message to the log.
|
||||||
|
end.cpMax = end.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&end);
|
||||||
|
|
||||||
|
// Remember current charformat.
|
||||||
|
oldformat.cbSize = sizeof(oldformat);
|
||||||
|
SendMessage(ConWindow, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
||||||
|
|
||||||
|
// Use bigger font and standout colors.
|
||||||
|
newformat.cbSize = sizeof(newformat);
|
||||||
|
newformat.dwMask = CFM_BOLD | CFM_COLOR | CFM_SIZE;
|
||||||
|
newformat.dwEffects = CFE_BOLD;
|
||||||
|
newformat.yHeight = oldformat.yHeight * 5 / 4;
|
||||||
|
newformat.crTextColor = RGB(255, 170, 170);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&newformat);
|
||||||
|
|
||||||
|
// Indent the rest of the text to make the error message stand out a little more.
|
||||||
|
paraformat.cbSize = sizeof(paraformat);
|
||||||
|
paraformat.dwMask = PFM_STARTINDENT | PFM_OFFSETINDENT | PFM_RIGHTINDENT;
|
||||||
|
paraformat.dxStartIndent = paraformat.dxOffset = paraformat.dxRightIndent = 120;
|
||||||
|
SendMessage(ConWindow, EM_SETPARAFORMAT, 0, (LPARAM)¶format);
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"\n");
|
||||||
|
|
||||||
|
// Find out where the error lines start for the error icon display control.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&end);
|
||||||
|
ErrorIconChar = end.cpMax;
|
||||||
|
|
||||||
|
// Now start adding the actual error message.
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"Execution could not continue.\n\n");
|
||||||
|
|
||||||
|
// Restore old charformat but with light yellow text.
|
||||||
|
oldformat.crTextColor = RGB(255, 255, 170);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
||||||
|
|
||||||
|
// Add the error text.
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)widetext.c_str());
|
||||||
|
|
||||||
|
// Make sure the error text is not scrolled below the window.
|
||||||
|
SendMessage(ConWindow, EM_LINESCROLL, 0, SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0));
|
||||||
|
// The above line scrolled everything off the screen, so pretend to move the scroll
|
||||||
|
// bar thumb, which clamps to not show any extra lines if it doesn't need to.
|
||||||
|
SendMessage(ConWindow, EM_SCROLL, SB_PAGEDOWN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL bRet;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
||||||
|
{
|
||||||
|
if (bRet == -1)
|
||||||
|
{
|
||||||
|
MessageBoxW(Window, widetext.c_str(), WGAMENAME " Fatal Error", MB_OK | MB_ICONSTOP | MB_TASKMODAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!IsDialogMessage(ErrorPane, &msg))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowProgressBar(int maxpos)
|
||||||
|
{
|
||||||
|
if (ProgressBar == 0)
|
||||||
|
ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 0, 0, 0, 0, Window, 0, GetModuleHandle(0), 0);
|
||||||
|
SendMessage(ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos));
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideProgressBar()
|
||||||
|
{
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(ProgressBar);
|
||||||
|
ProgressBar = 0;
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::SetProgressPos(int pos)
|
||||||
|
{
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
SendMessage(ProgressBar, PBM_SETPOS, pos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialogProc for the network startup pane. It just waits for somebody to click a button, and the only button available is the abort one.
|
||||||
|
static INT_PTR CALLBACK NetStartPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
|
||||||
|
{
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowNetStartPane(const char* message, int maxpos)
|
||||||
|
{
|
||||||
|
// Create the dialog child window
|
||||||
|
if (NetStartPane == NULL)
|
||||||
|
{
|
||||||
|
NetStartPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0);
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(ProgressBar);
|
||||||
|
ProgressBar = 0;
|
||||||
|
}
|
||||||
|
RECT winrect;
|
||||||
|
GetWindowRect(Window, &winrect);
|
||||||
|
SetWindowPos(Window, NULL, 0, 0,
|
||||||
|
winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane(NetStartPane, 0),
|
||||||
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
||||||
|
LayoutMainWindow(Window, NULL);
|
||||||
|
SetFocus(NetStartPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the message text
|
||||||
|
std::wstring wmessage = WideString(message);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str());
|
||||||
|
|
||||||
|
// Set the progress bar range
|
||||||
|
NetStartMaxPos = maxpos;
|
||||||
|
HWND ctl = GetDlgItem(NetStartPane, IDC_NETSTARTPROGRESS);
|
||||||
|
if (maxpos == 0)
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETMARQUEE, TRUE, 100);
|
||||||
|
SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) | PBS_MARQUEE);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETMARQUEE, FALSE, 0);
|
||||||
|
SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) & (~PBS_MARQUEE));
|
||||||
|
|
||||||
|
SendMessage(ctl, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos));
|
||||||
|
if (maxpos == 1)
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETPOS, 1, 0);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideNetStartPane()
|
||||||
|
{
|
||||||
|
if (NetStartPane != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(NetStartPane);
|
||||||
|
NetStartPane = 0;
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::SetNetStartProgress(int pos)
|
||||||
|
{
|
||||||
|
if (NetStartPane != 0 && NetStartMaxPos > 1)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
mysnprintf(buf, countof(buf), "%d/%d", pos, NetStartMaxPos);
|
||||||
|
SetDlgItemTextA(NetStartPane, IDC_NETSTARTCOUNT, buf);
|
||||||
|
SendDlgItemMessage(NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(pos, NetStartMaxPos), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::RunMessageLoop(bool (*timer_callback)(void*), void* userdata)
|
||||||
|
{
|
||||||
|
BOOL bRet;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
if (SetTimer(Window, 1337, 500, NULL) == 0)
|
||||||
|
{
|
||||||
|
I_FatalError("Could not set network synchronization timer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
||||||
|
{
|
||||||
|
if (bRet == -1)
|
||||||
|
{
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337)
|
||||||
|
{
|
||||||
|
if (timer_callback(userdata))
|
||||||
|
{
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IsDialogMessage(NetStartPane, &msg))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateLayout()
|
||||||
|
{
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the main window with the game title and log controls and possibly the error pane and progress bar.
|
||||||
|
void MainWindow::LayoutMainWindow(HWND hWnd, HWND pane)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
int errorpaneheight = 0;
|
||||||
|
int bannerheight = 0;
|
||||||
|
int progressheight = 0;
|
||||||
|
int netpaneheight = 0;
|
||||||
|
int leftside = 0;
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
GetClientRect(hWnd, &rect);
|
||||||
|
w = rect.right;
|
||||||
|
h = rect.bottom;
|
||||||
|
|
||||||
|
if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL)
|
||||||
|
{
|
||||||
|
bannerheight = GameTitleFontHeight + 5;
|
||||||
|
MoveWindow(GameTitleWindow, 0, 0, w, bannerheight, TRUE);
|
||||||
|
InvalidateRect(GameTitleWindow, NULL, FALSE);
|
||||||
|
}
|
||||||
|
if (ProgressBar != NULL)
|
||||||
|
{
|
||||||
|
// Base the height of the progress bar on the height of a scroll bar
|
||||||
|
// arrow, just as in the progress bar example.
|
||||||
|
progressheight = GetSystemMetrics(SM_CYVSCROLL);
|
||||||
|
MoveWindow(ProgressBar, 0, h - progressheight, w, progressheight, TRUE);
|
||||||
|
}
|
||||||
|
if (NetStartPane != NULL)
|
||||||
|
{
|
||||||
|
netpaneheight = LayoutNetStartPane(NetStartPane, w);
|
||||||
|
SetWindowPos(NetStartPane, HWND_TOP, 0, h - progressheight - netpaneheight, w, netpaneheight, SWP_SHOWWINDOW);
|
||||||
|
}
|
||||||
|
if (pane != NULL)
|
||||||
|
{
|
||||||
|
errorpaneheight = LayoutErrorPane(pane, w);
|
||||||
|
SetWindowPos(pane, HWND_TOP, 0, h - progressheight - netpaneheight - errorpaneheight, w, errorpaneheight, 0);
|
||||||
|
}
|
||||||
|
if (ErrorIcon != NULL)
|
||||||
|
{
|
||||||
|
leftside = GetSystemMetrics(SM_CXICON) + 6;
|
||||||
|
MoveWindow(ErrorIcon, 0, bannerheight, leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
||||||
|
}
|
||||||
|
// The log window uses whatever space is left.
|
||||||
|
MoveWindow(ConWindow, leftside, bannerheight, w - leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the error pane to the desired width, returning the required height.
|
||||||
|
int MainWindow::LayoutErrorPane(HWND pane, int w)
|
||||||
|
{
|
||||||
|
HWND ctl, ctl_two;
|
||||||
|
RECT rectc, rectc_two;
|
||||||
|
|
||||||
|
// Right-align the Quit button.
|
||||||
|
ctl = GetDlgItem(pane, IDOK);
|
||||||
|
GetClientRect(ctl, &rectc); // Find out how big it is.
|
||||||
|
MoveWindow(ctl, w - rectc.right - 1, 1, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
// Second-right-align the Restart button
|
||||||
|
ctl_two = GetDlgItem(pane, IDC_BUTTON1);
|
||||||
|
GetClientRect(ctl_two, &rectc_two); // Find out how big it is.
|
||||||
|
MoveWindow(ctl_two, w - rectc.right - rectc_two.right - 2, 1, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
InvalidateRect(ctl, NULL, TRUE);
|
||||||
|
InvalidateRect(ctl_two, NULL, TRUE);
|
||||||
|
|
||||||
|
// Return the needed height for this layout
|
||||||
|
return rectc.bottom + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the network startup pane to the specified width, returning its required height.
|
||||||
|
int MainWindow::LayoutNetStartPane(HWND pane, int w)
|
||||||
|
{
|
||||||
|
HWND ctl;
|
||||||
|
RECT margin, rectc;
|
||||||
|
int staticheight, barheight;
|
||||||
|
|
||||||
|
// Determine margin sizes.
|
||||||
|
SetRect(&margin, 7, 7, 0, 0);
|
||||||
|
MapDialogRect(pane, &margin);
|
||||||
|
|
||||||
|
// Stick the message text in the upper left corner.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTMESSAGE);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
// Stick the count text in the upper right corner.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTCOUNT);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, w - rectc.right - margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
||||||
|
staticheight = rectc.bottom;
|
||||||
|
|
||||||
|
// Stretch the progress bar to fill the entire width.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTPROGRESS);
|
||||||
|
barheight = GetSystemMetrics(SM_CYVSCROLL);
|
||||||
|
MoveWindow(ctl, margin.left, margin.top * 2 + staticheight, w - margin.left * 2, barheight, TRUE);
|
||||||
|
|
||||||
|
// Center the abort button underneath the progress bar.
|
||||||
|
ctl = GetDlgItem(pane, IDCANCEL);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, (w - rectc.right) / 2, margin.top * 3 + staticheight + barheight, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
return margin.top * 4 + staticheight + barheight + rectc.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::CheckForRestart()
|
||||||
|
{
|
||||||
|
if (restartrequest)
|
||||||
|
{
|
||||||
|
HMODULE hModule = GetModuleHandleW(NULL);
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
GetModuleFileNameW(hModule, path, MAX_PATH);
|
||||||
|
ShellExecuteW(NULL, L"open", path, GetCommandLineW(), NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
restartrequest = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main window's WndProc during startup. During gameplay, the WndProc in i_input.cpp is used instead.
|
||||||
|
LRESULT MainWindow::LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
return mainwindow.OnMessage(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
INT_PTR MainWindow::ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
// Appear in the main window.
|
||||||
|
mainwindow.LayoutMainWindow(GetParent(hDlg), hDlg);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (HIWORD(wParam) == BN_CLICKED)
|
||||||
|
{
|
||||||
|
if (LOWORD(wParam) == IDC_BUTTON1) // we pressed the restart button, so run GZDoom again
|
||||||
|
{
|
||||||
|
mainwindow.restartrequest = true;
|
||||||
|
}
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_CREATE: return OnCreate(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_SIZE: return OnSize(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_DRAWITEM: return OnDrawItem(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_COMMAND: return OnCommand(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_CLOSE: return OnClose(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_DESTROY: return OnDestroy(hWnd, msg, wParam, lParam);
|
||||||
|
default: return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HWND view;
|
||||||
|
HDC hdc;
|
||||||
|
HGDIOBJ oldfont;
|
||||||
|
LOGFONT lf;
|
||||||
|
TEXTMETRIC tm;
|
||||||
|
CHARFORMAT2W format;
|
||||||
|
|
||||||
|
HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
|
||||||
|
|
||||||
|
// Create game title static control
|
||||||
|
memset(&lf, 0, sizeof(lf));
|
||||||
|
hdc = GetDC(hWnd);
|
||||||
|
lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||||
|
lf.lfCharSet = ANSI_CHARSET;
|
||||||
|
lf.lfWeight = FW_BOLD;
|
||||||
|
lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
|
||||||
|
wcscpy(lf.lfFaceName, L"Trebuchet MS");
|
||||||
|
GameTitleFont = CreateFontIndirect(&lf);
|
||||||
|
|
||||||
|
oldfont = SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
||||||
|
GetTextMetrics(hdc, &tm);
|
||||||
|
DefaultGUIFontHeight = tm.tmHeight;
|
||||||
|
if (GameTitleFont == NULL)
|
||||||
|
{
|
||||||
|
GameTitleFontHeight = DefaultGUIFontHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectObject(hdc, GameTitleFont);
|
||||||
|
GetTextMetrics(hdc, &tm);
|
||||||
|
GameTitleFontHeight = tm.tmHeight;
|
||||||
|
}
|
||||||
|
SelectObject(hdc, oldfont);
|
||||||
|
|
||||||
|
// Create log read-only edit control
|
||||||
|
view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"RichEdit20W", nullptr,
|
||||||
|
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
||||||
|
ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
hWnd, NULL, inst, NULL);
|
||||||
|
HRESULT hr;
|
||||||
|
hr = GetLastError();
|
||||||
|
if (view == NULL)
|
||||||
|
{
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SendMessage(view, EM_SETREADONLY, TRUE, 0);
|
||||||
|
SendMessage(view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE);
|
||||||
|
SendMessage(view, EM_SETBKGNDCOLOR, 0, RGB(70, 70, 70));
|
||||||
|
// Setup default font for the log.
|
||||||
|
//SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE);
|
||||||
|
format.cbSize = sizeof(format);
|
||||||
|
format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET;
|
||||||
|
format.dwEffects = 0;
|
||||||
|
format.yHeight = 200;
|
||||||
|
format.crTextColor = RGB(223, 223, 223);
|
||||||
|
format.bCharSet = ANSI_CHARSET;
|
||||||
|
format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
|
||||||
|
wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p
|
||||||
|
SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format);
|
||||||
|
|
||||||
|
ConWindow = view;
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
|
||||||
|
view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, nullptr, inst, nullptr);
|
||||||
|
if (view == nullptr)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SetWindowLong(view, GWL_ID, IDC_STATIC_TITLE);
|
||||||
|
GameTitleWindow = view;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
|
||||||
|
{
|
||||||
|
LayoutMainWindow(hWnd, ErrorPane);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HGDIOBJ oldfont;
|
||||||
|
HBRUSH hbr;
|
||||||
|
DRAWITEMSTRUCT* drawitem;
|
||||||
|
RECT rect;
|
||||||
|
SIZE size;
|
||||||
|
|
||||||
|
// Draw title banner.
|
||||||
|
if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty())
|
||||||
|
{
|
||||||
|
const PalEntry* c;
|
||||||
|
|
||||||
|
// Draw the game title strip at the top of the window.
|
||||||
|
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
// Draw the background.
|
||||||
|
rect = drawitem->rcItem;
|
||||||
|
rect.bottom -= 1;
|
||||||
|
c = (const PalEntry*)&GameStartupInfo.BkColor;
|
||||||
|
hbr = CreateSolidBrush(RGB(c->r, c->g, c->b));
|
||||||
|
FillRect(drawitem->hDC, &drawitem->rcItem, hbr);
|
||||||
|
DeleteObject(hbr);
|
||||||
|
|
||||||
|
// Calculate width of the title string.
|
||||||
|
SetTextAlign(drawitem->hDC, TA_TOP);
|
||||||
|
oldfont = SelectObject(drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject(DEFAULT_GUI_FONT));
|
||||||
|
auto widename = GameStartupInfo.Name.WideString();
|
||||||
|
GetTextExtentPoint32W(drawitem->hDC, widename.c_str(), (int)widename.length(), &size);
|
||||||
|
|
||||||
|
// Draw the title.
|
||||||
|
c = (const PalEntry*)&GameStartupInfo.FgColor;
|
||||||
|
SetTextColor(drawitem->hDC, RGB(c->r, c->g, c->b));
|
||||||
|
SetBkMode(drawitem->hDC, TRANSPARENT);
|
||||||
|
TextOutW(drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length());
|
||||||
|
SelectObject(drawitem->hDC, oldfont);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
// Draw stop icon.
|
||||||
|
else if (wParam == IDC_ICONPIC)
|
||||||
|
{
|
||||||
|
HICON icon;
|
||||||
|
POINTL char_pos;
|
||||||
|
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
// This background color should match the edit control's.
|
||||||
|
hbr = CreateSolidBrush(RGB(70, 70, 70));
|
||||||
|
FillRect(drawitem->hDC, &drawitem->rcItem, hbr);
|
||||||
|
DeleteObject(hbr);
|
||||||
|
|
||||||
|
// Draw the icon aligned with the first line of error text.
|
||||||
|
SendMessage(ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar);
|
||||||
|
icon = (HICON)LoadImage(0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||||
|
DrawIcon(drawitem->hDC, 6, char_pos.y, icon);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE)
|
||||||
|
{
|
||||||
|
// Be sure to redraw the error icon if the edit control changes.
|
||||||
|
InvalidateRect(ErrorIcon, NULL, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (GameTitleFont != NULL)
|
||||||
|
{
|
||||||
|
DeleteObject(GameTitleFont);
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::PrintStr(const char* cp)
|
||||||
|
{
|
||||||
|
if (ConWindowHidden)
|
||||||
|
{
|
||||||
|
bufferedConsoleStuff.Push(cp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoPrintStr(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::FlushBufferedConsoleStuff()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++)
|
||||||
|
{
|
||||||
|
DoPrintStr(bufferedConsoleStuff[i]);
|
||||||
|
}
|
||||||
|
bufferedConsoleStuff.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::DoPrintStr(const char* cpt)
|
||||||
|
{
|
||||||
|
wchar_t wbuf[256];
|
||||||
|
int bpos = 0;
|
||||||
|
CHARRANGE selection = {};
|
||||||
|
CHARRANGE endselection = {};
|
||||||
|
LONG lines_before = 0, lines_after = 0;
|
||||||
|
|
||||||
|
// Store the current selection and set it to the end so we can append text.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&selection);
|
||||||
|
endselection.cpMax = endselection.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&endselection);
|
||||||
|
|
||||||
|
// GetWindowTextLength and EM_EXSETSEL can disagree on where the end of
|
||||||
|
// the text is. Find out what EM_EXSETSEL thought it was and use that later.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&endselection);
|
||||||
|
|
||||||
|
// Remember how many lines there were before we added text.
|
||||||
|
lines_before = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0);
|
||||||
|
|
||||||
|
const uint8_t* cptr = (const uint8_t*)cpt;
|
||||||
|
|
||||||
|
auto outputIt = [&]()
|
||||||
|
{
|
||||||
|
wbuf[bpos] = 0;
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)wbuf);
|
||||||
|
bpos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (int chr = GetCharFromString(cptr))
|
||||||
|
{
|
||||||
|
if ((chr == TEXTCOLOR_ESCAPE && bpos != 0) || bpos == 255)
|
||||||
|
{
|
||||||
|
outputIt();
|
||||||
|
}
|
||||||
|
if (chr != TEXTCOLOR_ESCAPE)
|
||||||
|
{
|
||||||
|
if (chr >= 0x1D && chr <= 0x1F)
|
||||||
|
{ // The bar characters, most commonly used to indicate map changes
|
||||||
|
chr = 0x2550; // Box Drawings Double Horizontal
|
||||||
|
}
|
||||||
|
wbuf[bpos++] = chr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW);
|
||||||
|
|
||||||
|
if (range != CR_UNDEFINED)
|
||||||
|
{
|
||||||
|
// Change the color of future text added to the control.
|
||||||
|
PalEntry color = V_LogColorFromColorRange(range);
|
||||||
|
|
||||||
|
// Change the color.
|
||||||
|
CHARFORMAT format;
|
||||||
|
format.cbSize = sizeof(format);
|
||||||
|
format.dwMask = CFM_COLOR;
|
||||||
|
format.dwEffects = 0;
|
||||||
|
format.crTextColor = RGB(color.r, color.g, color.b);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bpos != 0)
|
||||||
|
{
|
||||||
|
outputIt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the old selection was at the end of the text, keep it at the end and
|
||||||
|
// scroll. Don't scroll if the selection is anywhere else.
|
||||||
|
if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax)
|
||||||
|
{
|
||||||
|
selection.cpMax = selection.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
lines_after = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0);
|
||||||
|
if (lines_after > lines_before)
|
||||||
|
{
|
||||||
|
SendMessage(ConWindow, EM_LINESCROLL, 0, lines_after - lines_before);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Restore the previous selection.
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&selection);
|
||||||
|
// Give the edit control a chance to redraw itself.
|
||||||
|
I_GetEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG* pcb)
|
||||||
|
{
|
||||||
|
uint32_t didwrite;
|
||||||
|
LONG p, pp;
|
||||||
|
|
||||||
|
// Replace gray foreground color with black.
|
||||||
|
static const char* badfg = "\\red223\\green223\\blue223;";
|
||||||
|
// 4321098 765432109 876543210
|
||||||
|
// 2 1 0
|
||||||
|
for (p = pp = 0; p < cb; ++p)
|
||||||
|
{
|
||||||
|
if (buffer[p] == badfg[pp])
|
||||||
|
{
|
||||||
|
++pp;
|
||||||
|
if (pp == 25)
|
||||||
|
{
|
||||||
|
buffer[p - 1] = buffer[p - 2] = buffer[p - 3] =
|
||||||
|
buffer[p - 9] = buffer[p - 10] = buffer[p - 11] =
|
||||||
|
buffer[p - 18] = buffer[p - 19] = buffer[p - 20] = '0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& writeData = *reinterpret_cast<std::function<bool(const void* data, uint32_t size, uint32_t& written)>*>(cookie);
|
||||||
|
if (!writeData((const void*)buffer, cb, didwrite))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*pcb = didwrite;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeData)
|
||||||
|
{
|
||||||
|
FlushBufferedConsoleStuff();
|
||||||
|
|
||||||
|
EDITSTREAM streamer = { (DWORD_PTR)&writeData, 0, WriteLogFileStreamer };
|
||||||
|
SendMessage(ConWindow, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// each platform has its own specific version of this function.
|
||||||
|
void MainWindow::SetWindowTitle(const char* caption)
|
||||||
|
{
|
||||||
|
std::wstring widecaption;
|
||||||
|
if (!caption)
|
||||||
|
{
|
||||||
|
FStringf default_caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
widecaption = default_caption.WideString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widecaption = WideString(caption);
|
||||||
|
}
|
||||||
|
SetWindowText(Window, widecaption.c_str());
|
||||||
|
}
|
90
source/common/platform/win32/i_mainwindow.h
Normal file
90
source/common/platform/win32/i_mainwindow.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
// The WndProc used when the game view is active
|
||||||
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
class MainWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Create(const FString& title, int x, int y, int width, int height);
|
||||||
|
|
||||||
|
void ShowGameView();
|
||||||
|
void RestoreConView();
|
||||||
|
|
||||||
|
void ShowErrorPane(const char* text);
|
||||||
|
void CheckForRestart();
|
||||||
|
|
||||||
|
void HideGameTitleWindow();
|
||||||
|
int GetGameTitleWindowHeight();
|
||||||
|
|
||||||
|
void PrintStr(const char* cp);
|
||||||
|
void GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeFile);
|
||||||
|
|
||||||
|
void UpdateLayout();
|
||||||
|
|
||||||
|
void ShowProgressBar(int maxpos);
|
||||||
|
void HideProgressBar();
|
||||||
|
void SetProgressPos(int pos);
|
||||||
|
|
||||||
|
void ShowNetStartPane(const char* message, int maxpos);
|
||||||
|
void SetNetStartProgress(int pos);
|
||||||
|
bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata);
|
||||||
|
void HideNetStartPane();
|
||||||
|
|
||||||
|
void SetWindowTitle(const char* caption);
|
||||||
|
|
||||||
|
HWND GetHandle() { return Window; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LayoutMainWindow(HWND hWnd, HWND pane);
|
||||||
|
int LayoutErrorPane(HWND pane, int w);
|
||||||
|
int LayoutNetStartPane(HWND pane, int w);
|
||||||
|
|
||||||
|
void DoPrintStr(const char* cpt);
|
||||||
|
void FlushBufferedConsoleStuff();
|
||||||
|
|
||||||
|
LRESULT OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
static INT_PTR CALLBACK ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
HWND Window = 0;
|
||||||
|
|
||||||
|
HFONT GameTitleFont = 0;
|
||||||
|
LONG GameTitleFontHeight = 0;
|
||||||
|
LONG DefaultGUIFontHeight = 0;
|
||||||
|
LONG ErrorIconChar = 0;
|
||||||
|
|
||||||
|
bool restartrequest = false;
|
||||||
|
|
||||||
|
HWND GameTitleWindow = 0;
|
||||||
|
HWND ErrorPane = 0;
|
||||||
|
HWND ErrorIcon = 0;
|
||||||
|
|
||||||
|
bool ConWindowHidden = false;
|
||||||
|
HWND ConWindow = 0;
|
||||||
|
TArray<FString> bufferedConsoleStuff;
|
||||||
|
|
||||||
|
HWND ProgressBar = 0;
|
||||||
|
|
||||||
|
HWND NetStartPane = 0;
|
||||||
|
int NetStartMaxPos = 0;
|
||||||
|
|
||||||
|
HWND StartupScreen = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MainWindow mainwindow;
|
|
@ -46,6 +46,7 @@
|
||||||
#include "menustate.h"
|
#include "menustate.h"
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -138,7 +139,6 @@ static void CenterMouse(int x, int y, LONG *centx, LONG *centy);
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern LPDIRECTINPUT g_pdi3;
|
extern LPDIRECTINPUT g_pdi3;
|
||||||
extern bool GUICapture;
|
extern bool GUICapture;
|
||||||
|
@ -193,11 +193,11 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||||
static void SetCursorState(bool visible)
|
static void SetCursorState(bool visible)
|
||||||
{
|
{
|
||||||
CursorState = visible || !m_hidepointer;
|
CursorState = visible || !m_hidepointer;
|
||||||
if (GetForegroundWindow() == Window)
|
if (GetForegroundWindow() == mainwindow.GetHandle())
|
||||||
{
|
{
|
||||||
if (CursorState)
|
if (CursorState)
|
||||||
{
|
{
|
||||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(Window, GCLP_HCURSOR));
|
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -219,7 +219,7 @@ static void CenterMouse(int curx, int cury, LONG *centxp, LONG *centyp)
|
||||||
{
|
{
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
|
||||||
GetWindowRect(Window, &rect);
|
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
int centx = (rect.left + rect.right) >> 1;
|
int centx = (rect.left + rect.right) >> 1;
|
||||||
int centy = (rect.top + rect.bottom) >> 1;
|
int centy = (rect.top + rect.bottom) >> 1;
|
||||||
|
@ -258,7 +258,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((GetForegroundWindow() != Window) || preferNative || !use_mouse)
|
if ((GetForegroundWindow() != mainwindow.GetHandle()) || preferNative || !use_mouse)
|
||||||
{
|
{
|
||||||
want_native = true;
|
want_native = true;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,6 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
||||||
|
|
||||||
FMouse::FMouse()
|
FMouse::FMouse()
|
||||||
{
|
{
|
||||||
LastX = LastY = 0;
|
|
||||||
ButtonState = 0;
|
ButtonState = 0;
|
||||||
WheelMove[0] = 0;
|
WheelMove[0] = 0;
|
||||||
WheelMove[1] = 0;
|
WheelMove[1] = 0;
|
||||||
|
@ -490,7 +489,7 @@ bool FRawMouse::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_MOUSE;
|
rid.usUsage = HID_GDP_MOUSE;
|
||||||
rid.dwFlags = 0;
|
rid.dwFlags = 0;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -516,7 +515,7 @@ void FRawMouse::Grab()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_MOUSE;
|
rid.usUsage = HID_GDP_MOUSE;
|
||||||
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
|
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
GetCursorPos(&UngrabbedPointerPos);
|
GetCursorPos(&UngrabbedPointerPos);
|
||||||
|
@ -718,7 +717,7 @@ ufailit:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto ufailit;
|
goto ufailit;
|
||||||
|
@ -1066,11 +1065,11 @@ void FWin32Mouse::Grab()
|
||||||
|
|
||||||
GetCursorPos(&UngrabbedPointerPos);
|
GetCursorPos(&UngrabbedPointerPos);
|
||||||
ClipCursor(NULL); // helps with Win95?
|
ClipCursor(NULL); // helps with Win95?
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
// Reposition the rect so that it only covers the client area.
|
// Reposition the rect so that it only covers the client area.
|
||||||
ClientToScreen(Window, (LPPOINT)&rect.left);
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.left);
|
||||||
ClientToScreen(Window, (LPPOINT)&rect.right);
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.right);
|
||||||
|
|
||||||
ClipCursor(&rect);
|
ClipCursor(&rect);
|
||||||
SetCursorState(false);
|
SetCursorState(false);
|
||||||
|
|
|
@ -44,6 +44,8 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
#define DEFAULT_DEADZONE 0.25f
|
#define DEFAULT_DEADZONE 0.25f
|
||||||
|
@ -214,8 +216,6 @@ struct PS2Descriptor
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
|
@ -905,7 +905,7 @@ bool FRawPS2Manager::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_JOYSTICK;
|
rid.usUsage = HID_GDP_JOYSTICK;
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1273,7 +1273,7 @@ void FRawPS2Manager::DoRegister()
|
||||||
if (!Registered)
|
if (!Registered)
|
||||||
{
|
{
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
Registered = true;
|
Registered = true;
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -92,10 +93,6 @@
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
||||||
|
|
||||||
extern void LayoutMainWindow(HWND hWnd, HWND pane);
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
void DestroyCustomCursor();
|
void DestroyCustomCursor();
|
||||||
|
@ -116,13 +113,11 @@ EXTERN_CVAR (Bool, autoloadbrightmaps)
|
||||||
EXTERN_CVAR (Bool, autoloadwidescreen)
|
EXTERN_CVAR (Bool, autoloadwidescreen)
|
||||||
EXTERN_CVAR (Int, vid_preferbackend)
|
EXTERN_CVAR (Int, vid_preferbackend)
|
||||||
|
|
||||||
extern HWND Window, ConWindow, GameTitleWindow;
|
|
||||||
extern HANDLE StdOut;
|
extern HANDLE StdOut;
|
||||||
extern bool FancyStdOut;
|
extern bool FancyStdOut;
|
||||||
extern HINSTANCE g_hInst;
|
extern HINSTANCE g_hInst;
|
||||||
extern FILE *Logfile;
|
extern FILE *Logfile;
|
||||||
extern bool NativeMouse;
|
extern bool NativeMouse;
|
||||||
extern bool ConWindowHidden;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -281,42 +276,19 @@ void CalculateCPUSpeed()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
static void PrintToStdOut(const char *cpt, HANDLE StdOut)
|
||||||
{
|
{
|
||||||
if (edit == nullptr && StdOut == nullptr && !con_debugoutput)
|
if (StdOut == nullptr && !con_debugoutput)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wchar_t wbuf[256];
|
wchar_t wbuf[256];
|
||||||
int bpos = 0;
|
int bpos = 0;
|
||||||
CHARRANGE selection = {};
|
|
||||||
CHARRANGE endselection = {};
|
|
||||||
LONG lines_before = 0, lines_after;
|
|
||||||
CHARFORMAT format;
|
|
||||||
|
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// Store the current selection and set it to the end so we can append text.
|
|
||||||
SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&selection);
|
|
||||||
endselection.cpMax = endselection.cpMin = GetWindowTextLength(edit);
|
|
||||||
SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&endselection);
|
|
||||||
|
|
||||||
// GetWindowTextLength and EM_EXSETSEL can disagree on where the end of
|
|
||||||
// the text is. Find out what EM_EXSETSEL thought it was and use that later.
|
|
||||||
SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&endselection);
|
|
||||||
|
|
||||||
// Remember how many lines there were before we added text.
|
|
||||||
lines_before = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t *cptr = (const uint8_t*)cpt;
|
const uint8_t *cptr = (const uint8_t*)cpt;
|
||||||
|
|
||||||
auto outputIt = [&]()
|
auto outputIt = [&]()
|
||||||
{
|
{
|
||||||
wbuf[bpos] = 0;
|
wbuf[bpos] = 0;
|
||||||
if (edit != nullptr)
|
|
||||||
{
|
|
||||||
SendMessageW(edit, EM_REPLACESEL, FALSE, (LPARAM)wbuf);
|
|
||||||
}
|
|
||||||
if (con_debugoutput)
|
if (con_debugoutput)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(wbuf);
|
OutputDebugStringW(wbuf);
|
||||||
|
@ -385,17 +357,6 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
||||||
}
|
}
|
||||||
SetConsoleTextAttribute(StdOut, (WORD)attrib);
|
SetConsoleTextAttribute(StdOut, (WORD)attrib);
|
||||||
}
|
}
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// GDI uses BGR colors, but color is RGB, so swap the R and the B.
|
|
||||||
std::swap(color.r, color.b);
|
|
||||||
// Change the color.
|
|
||||||
format.cbSize = sizeof(format);
|
|
||||||
format.dwMask = CFM_COLOR;
|
|
||||||
format.dwEffects = 0;
|
|
||||||
format.crTextColor = color;
|
|
||||||
SendMessage(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,52 +365,16 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
||||||
outputIt();
|
outputIt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// If the old selection was at the end of the text, keep it at the end and
|
|
||||||
// scroll. Don't scroll if the selection is anywhere else.
|
|
||||||
if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax)
|
|
||||||
{
|
|
||||||
selection.cpMax = selection.cpMin = GetWindowTextLength (edit);
|
|
||||||
lines_after = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
|
|
||||||
if (lines_after > lines_before)
|
|
||||||
{
|
|
||||||
SendMessage(edit, EM_LINESCROLL, 0, lines_after - lines_before);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Restore the previous selection.
|
|
||||||
SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&selection);
|
|
||||||
// Give the edit control a chance to redraw itself.
|
|
||||||
I_GetEvent();
|
|
||||||
}
|
|
||||||
if (StdOut != NULL && FancyStdOut)
|
if (StdOut != NULL && FancyStdOut)
|
||||||
{ // Set text back to gray, in case it was changed.
|
{ // Set text back to gray, in case it was changed.
|
||||||
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TArray<FString> bufferedConsoleStuff;
|
|
||||||
|
|
||||||
void I_PrintStr(const char *cp)
|
void I_PrintStr(const char *cp)
|
||||||
{
|
{
|
||||||
if (ConWindowHidden)
|
mainwindow.PrintStr(cp);
|
||||||
{
|
PrintToStdOut(cp, StdOut);
|
||||||
bufferedConsoleStuff.Push(cp);
|
|
||||||
DoPrintStr(cp, NULL, StdOut);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoPrintStr(cp, ConWindow, StdOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I_FlushBufferedConsoleStuff()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++)
|
|
||||||
{
|
|
||||||
DoPrintStr(bufferedConsoleStuff[i], ConWindow, NULL);
|
|
||||||
}
|
|
||||||
bufferedConsoleStuff.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -635,7 +560,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||||
DefaultWad = defaultiwad;
|
DefaultWad = defaultiwad;
|
||||||
|
|
||||||
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
|
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
|
||||||
(HWND)Window, (DLGPROC)IWADBoxCallback);
|
(HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback);
|
||||||
}
|
}
|
||||||
return defaultiwad;
|
return defaultiwad;
|
||||||
}
|
}
|
||||||
|
@ -682,16 +607,16 @@ bool I_SetCursor(FGameTexture *cursorpic)
|
||||||
DestroyCustomCursor();
|
DestroyCustomCursor();
|
||||||
cursor = LoadCursor(NULL, IDC_ARROW);
|
cursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
}
|
}
|
||||||
SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)cursor);
|
SetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR, (LONG_PTR)cursor);
|
||||||
if (NativeMouse)
|
if (NativeMouse)
|
||||||
{
|
{
|
||||||
POINT pt;
|
POINT pt;
|
||||||
RECT client;
|
RECT client;
|
||||||
|
|
||||||
// If the mouse pointer is within the window's client rect, set it now.
|
// If the mouse pointer is within the window's client rect, set it now.
|
||||||
if (GetCursorPos(&pt) && GetClientRect(Window, &client) &&
|
if (GetCursorPos(&pt) && GetClientRect(mainwindow.GetHandle(), &client) &&
|
||||||
ClientToScreen(Window, (LPPOINT)&client.left) &&
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.left) &&
|
||||||
ClientToScreen(Window, (LPPOINT)&client.right))
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.right))
|
||||||
{
|
{
|
||||||
if (pt.x >= client.left && pt.x < client.right &&
|
if (pt.x >= client.left && pt.x < client.right &&
|
||||||
pt.y >= client.top && pt.y < client.bottom)
|
pt.y >= client.top && pt.y < client.bottom)
|
||||||
|
@ -912,7 +837,7 @@ bool I_WriteIniFailed()
|
||||||
);
|
);
|
||||||
errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf);
|
errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf);
|
||||||
LocalFree (lpMsgBuf);
|
LocalFree (lpMsgBuf);
|
||||||
return MessageBoxA(Window, errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY;
|
return MessageBoxA(mainwindow.GetHandle(), errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,6 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad);
|
||||||
// The ini could not be saved at exit
|
// The ini could not be saved at exit
|
||||||
bool I_WriteIniFailed ();
|
bool I_WriteIniFailed ();
|
||||||
|
|
||||||
// [RH] Used by the display code to set the normal window procedure
|
|
||||||
void I_SetWndProc();
|
|
||||||
|
|
||||||
// [RH] Checks the registry for Steam's install path, so we can scan its
|
// [RH] Checks the registry for Steam's install path, so we can scan its
|
||||||
// directories for IWADs if the user purchased any through Steam.
|
// directories for IWADs if the user purchased any through Steam.
|
||||||
TArray<FString> I_GetSteamPath();
|
TArray<FString> I_GetSteamPath();
|
||||||
|
|
|
@ -53,49 +53,15 @@
|
||||||
#include "startupinfo.h"
|
#include "startupinfo.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
#include "texturemanager.h"
|
#include "texturemanager.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
// MACROS ------------------------------------------------------------------
|
|
||||||
|
|
||||||
// How many ms elapse between blinking text flips. On a standard VGA
|
|
||||||
// adapter, the characters are on for 16 frames and then off for another 16.
|
|
||||||
// The number here therefore corresponds roughly to the blink rate on a
|
|
||||||
// 60 Hz display.
|
|
||||||
#define BLINK_PERIOD 267
|
|
||||||
#define TEXT_FONT_NAME "vga-rom-font.16"
|
|
||||||
|
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
void RestoreConView();
|
|
||||||
void LayoutMainWindow (HWND hWnd, HWND pane);
|
|
||||||
int LayoutNetStartPane (HWND pane, int w);
|
|
||||||
|
|
||||||
bool ST_Util_CreateStartupWindow ();
|
|
||||||
void ST_Util_SizeWindowForBitmap (int scale);
|
void ST_Util_SizeWindowForBitmap (int scale);
|
||||||
void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom);
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
||||||
|
|
||||||
static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HINSTANCE g_hInst;
|
extern HINSTANCE g_hInst;
|
||||||
extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTitleWindow;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
||||||
|
|
||||||
FStartupScreen *StartScreen;
|
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (self < 0) self = 0;
|
|
||||||
else if (self > 2) self=2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
@ -110,36 +76,9 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
|
FStartupScreen *FStartupScreen::CreateInstance(int max_progress, bool showprogress)
|
||||||
{
|
{
|
||||||
FStartupScreen *scr = NULL;
|
return new FBasicStartupScreen(max_progress, showprogress);
|
||||||
HRESULT hr = -1;
|
|
||||||
|
|
||||||
if (!Args->CheckParm("-nostartup"))
|
|
||||||
{
|
|
||||||
if (GameStartupInfo.Type == FStartupInfo::HexenStartup)
|
|
||||||
{
|
|
||||||
scr = new FHexenStartupScreen(max_progress, hr);
|
|
||||||
}
|
|
||||||
else if (GameStartupInfo.Type == FStartupInfo::HereticStartup)
|
|
||||||
{
|
|
||||||
scr = new FHereticStartupScreen(max_progress, hr);
|
|
||||||
}
|
|
||||||
else if (GameStartupInfo.Type == FStartupInfo::StrifeStartup)
|
|
||||||
{
|
|
||||||
scr = new FStrifeStartupScreen(max_progress, hr);
|
|
||||||
}
|
|
||||||
if (scr != NULL && FAILED(hr))
|
|
||||||
{
|
|
||||||
delete scr;
|
|
||||||
scr = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (scr == NULL)
|
|
||||||
{
|
|
||||||
scr = new FBasicStartupScreen(max_progress, true);
|
|
||||||
}
|
|
||||||
return scr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -155,12 +94,7 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
||||||
{
|
{
|
||||||
if (show_bar)
|
if (show_bar)
|
||||||
{
|
{
|
||||||
ProgressBar = CreateWindowEx(0, PROGRESS_CLASS,
|
mainwindow.ShowProgressBar(MaxPos);
|
||||||
NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
Window, 0, g_hInst, NULL);
|
|
||||||
SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos));
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
}
|
||||||
NetMaxPos = 0;
|
NetMaxPos = 0;
|
||||||
NetCurPos = 0;
|
NetCurPos = 0;
|
||||||
|
@ -177,13 +111,8 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
||||||
|
|
||||||
FBasicStartupScreen::~FBasicStartupScreen()
|
FBasicStartupScreen::~FBasicStartupScreen()
|
||||||
{
|
{
|
||||||
if (ProgressBar != NULL)
|
mainwindow.HideProgressBar();
|
||||||
{
|
KillTimer(mainwindow.GetHandle(), 1337);
|
||||||
DestroyWindow (ProgressBar);
|
|
||||||
ProgressBar = NULL;
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
|
||||||
KillTimer(Window, 1337);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -199,7 +128,7 @@ void FBasicStartupScreen::Progress()
|
||||||
if (CurPos < MaxPos)
|
if (CurPos < MaxPos)
|
||||||
{
|
{
|
||||||
CurPos++;
|
CurPos++;
|
||||||
SendMessage (ProgressBar, PBM_SETPOS, CurPos, 0);
|
mainwindow.SetProgressPos(CurPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,61 +147,8 @@ void FBasicStartupScreen::Progress()
|
||||||
void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
||||||
{
|
{
|
||||||
NetMaxPos = numplayers;
|
NetMaxPos = numplayers;
|
||||||
if (NetStartPane == NULL)
|
mainwindow.ShowNetStartPane(message, numplayers);
|
||||||
{
|
|
||||||
NetStartPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0);
|
|
||||||
// We don't need two progress bars.
|
|
||||||
if (ProgressBar != NULL)
|
|
||||||
{
|
|
||||||
DestroyWindow (ProgressBar);
|
|
||||||
ProgressBar = NULL;
|
|
||||||
}
|
|
||||||
RECT winrect;
|
|
||||||
GetWindowRect (Window, &winrect);
|
|
||||||
SetWindowPos (Window, NULL, 0, 0,
|
|
||||||
winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane (NetStartPane, 0),
|
|
||||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
SetFocus (NetStartPane);
|
|
||||||
}
|
|
||||||
if (NetStartPane != NULL)
|
|
||||||
{
|
|
||||||
HWND ctl;
|
|
||||||
|
|
||||||
std::wstring wmessage = WideString(message);
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str());
|
|
||||||
ctl = GetDlgItem (NetStartPane, IDC_NETSTARTPROGRESS);
|
|
||||||
|
|
||||||
if (numplayers == 0)
|
|
||||||
{
|
|
||||||
// PBM_SETMARQUEE is only available under XP and above, so this might fail.
|
|
||||||
NetMarqueeMode = SendMessage (ctl, PBM_SETMARQUEE, TRUE, 100);
|
|
||||||
if (NetMarqueeMode == FALSE)
|
|
||||||
{
|
|
||||||
SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,16));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we don't set the PBS_MARQUEE style, then the marquee will never show up.
|
|
||||||
SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) | PBS_MARQUEE);
|
|
||||||
}
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetMarqueeMode = FALSE;
|
|
||||||
SendMessage (ctl, PBM_SETMARQUEE, FALSE, 0);
|
|
||||||
// Make sure the marquee really is turned off.
|
|
||||||
SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) & (~PBS_MARQUEE));
|
|
||||||
|
|
||||||
SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,numplayers));
|
|
||||||
if (numplayers == 1)
|
|
||||||
{
|
|
||||||
SendMessage (ctl, PBM_SETPOS, 1, 0);
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NetMaxPos = numplayers;
|
NetMaxPos = numplayers;
|
||||||
NetCurPos = 0;
|
NetCurPos = 0;
|
||||||
NetProgress(1); // You always know about yourself
|
NetProgress(1); // You always know about yourself
|
||||||
|
@ -288,33 +164,7 @@ void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
||||||
|
|
||||||
void FBasicStartupScreen::NetDone()
|
void FBasicStartupScreen::NetDone()
|
||||||
{
|
{
|
||||||
if (NetStartPane != NULL)
|
mainwindow.HideNetStartPane();
|
||||||
{
|
|
||||||
DestroyWindow (NetStartPane);
|
|
||||||
NetStartPane = NULL;
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// FBasicStartupScreen :: NetMessage
|
|
||||||
//
|
|
||||||
// Call this between NetInit() and NetDone() instead of Printf() to
|
|
||||||
// display messages, in case the progress meter is mixed in the same output
|
|
||||||
// stream as normal messages.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FBasicStartupScreen::NetMessage(const char *format, ...)
|
|
||||||
{
|
|
||||||
FString str;
|
|
||||||
va_list argptr;
|
|
||||||
|
|
||||||
va_start (argptr, format);
|
|
||||||
str.VFormat (format, argptr);
|
|
||||||
va_end (argptr);
|
|
||||||
Printf ("%s\n", str.GetChars());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -326,7 +176,7 @@ void FBasicStartupScreen::NetMessage(const char *format, ...)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FBasicStartupScreen :: NetProgress(int count)
|
void FBasicStartupScreen::NetProgress(int count)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
|
@ -336,23 +186,8 @@ void FBasicStartupScreen :: NetProgress(int count)
|
||||||
{
|
{
|
||||||
NetCurPos = count;
|
NetCurPos = count;
|
||||||
}
|
}
|
||||||
if (NetStartPane == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (NetMaxPos == 0 && !NetMarqueeMode)
|
|
||||||
{
|
|
||||||
// PBM_SETMARQUEE didn't work, so just increment the progress bar endlessly.
|
|
||||||
SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, NetCurPos & 15, 0);
|
|
||||||
}
|
|
||||||
else if (NetMaxPos > 1)
|
|
||||||
{
|
|
||||||
char buf[16];
|
|
||||||
|
|
||||||
mysnprintf (buf, countof(buf), "%d/%d", NetCurPos, NetMaxPos);
|
mainwindow.SetNetStartProgress(count);
|
||||||
SetDlgItemTextA (NetStartPane, IDC_NETSTARTCOUNT, buf);
|
|
||||||
SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(NetCurPos, NetMaxPos), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -371,350 +206,5 @@ void FBasicStartupScreen :: NetProgress(int count)
|
||||||
|
|
||||||
bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
||||||
{
|
{
|
||||||
BOOL bRet;
|
return mainwindow.RunMessageLoop(timer_callback, userdata);
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
if (SetTimer (Window, 1337, 500, NULL) == 0)
|
|
||||||
{
|
|
||||||
I_FatalError ("Could not set network synchronization timer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
|
||||||
{
|
|
||||||
if (bRet == -1)
|
|
||||||
{
|
|
||||||
KillTimer (Window, 1337);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337)
|
|
||||||
{
|
|
||||||
if (timer_callback (userdata))
|
|
||||||
{
|
|
||||||
KillTimer (NetStartPane, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsDialogMessage (NetStartPane, &msg))
|
|
||||||
{
|
|
||||||
TranslateMessage (&msg);
|
|
||||||
DispatchMessage (&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KillTimer (Window, 1337);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// NetStartPaneProc
|
|
||||||
//
|
|
||||||
// DialogProc for the network startup pane. It just waits for somebody to
|
|
||||||
// click a button, and the only button available is the abort one.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
|
|
||||||
{
|
|
||||||
PostQuitMessage (0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// FGraphicalStartupScreen Constructor
|
|
||||||
//
|
|
||||||
// This doesn't really do anything. The subclass is responsible for
|
|
||||||
// creating the resources that will be freed by this class's destructor.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
|
||||||
: FBasicStartupScreen(max_progress, false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// FGraphicalStartupScreen Destructor
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
|
||||||
{
|
|
||||||
if (StartupScreen != NULL)
|
|
||||||
{
|
|
||||||
DestroyWindow (StartupScreen);
|
|
||||||
StartupScreen = NULL;
|
|
||||||
}
|
|
||||||
if (StartupBitmap != NULL)
|
|
||||||
{
|
|
||||||
ST_Util_FreeBitmap (StartupBitmap);
|
|
||||||
StartupBitmap = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FHexenStartupScreen::SetWindowSize()
|
|
||||||
{
|
|
||||||
ST_Util_SizeWindowForBitmap(1);
|
|
||||||
LayoutMainWindow(Window, NULL);
|
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FHereticStartupScreen::SetWindowSize()
|
|
||||||
{
|
|
||||||
ST_Util_SizeWindowForBitmap(1);
|
|
||||||
LayoutMainWindow(Window, NULL);
|
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FStrifeStartupScreen::SetWindowSize()
|
|
||||||
{
|
|
||||||
ST_Util_SizeWindowForBitmap(2);
|
|
||||||
LayoutMainWindow(Window, NULL);
|
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ST_Endoom
|
|
||||||
//
|
|
||||||
// Shows an ENDOOM text screen
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
int RunEndoom()
|
|
||||||
{
|
|
||||||
if (showendoom == 0 || endoomName.Len() == 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true);
|
|
||||||
|
|
||||||
uint8_t endoom_screen[4000];
|
|
||||||
uint8_t *font;
|
|
||||||
MSG mess;
|
|
||||||
BOOL bRet;
|
|
||||||
bool blinking = false, blinkstate = false;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2)
|
|
||||||
{
|
|
||||||
// showendoom==2 means to show only lumps from PWADs.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
font = ST_Util_LoadFont (TEXT_FONT_NAME);
|
|
||||||
if (font == NULL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ST_Util_CreateStartupWindow())
|
|
||||||
{
|
|
||||||
ST_Util_FreeFont (font);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
I_ShutdownGraphics ();
|
|
||||||
RestoreConView ();
|
|
||||||
S_StopMusic(true);
|
|
||||||
|
|
||||||
fileSystem.ReadFile (endoom_lump, endoom_screen);
|
|
||||||
|
|
||||||
// Draw the loading screen to a bitmap.
|
|
||||||
StartupBitmap = ST_Util_AllocTextBitmap (font);
|
|
||||||
ST_Util_DrawTextScreen (StartupBitmap, endoom_screen, font);
|
|
||||||
|
|
||||||
// Make the title banner go away.
|
|
||||||
if (GameTitleWindow != NULL)
|
|
||||||
{
|
|
||||||
DestroyWindow (GameTitleWindow);
|
|
||||||
GameTitleWindow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_Util_SizeWindowForBitmap (1);
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
InvalidateRect (StartupScreen, NULL, TRUE);
|
|
||||||
|
|
||||||
// Does this screen need blinking?
|
|
||||||
for (i = 0; i < 80*25; ++i)
|
|
||||||
{
|
|
||||||
if (endoom_screen[1+i*2] & 0x80)
|
|
||||||
{
|
|
||||||
blinking = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0)
|
|
||||||
{
|
|
||||||
blinking = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait until any key has been pressed or a quit message has been received
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
bRet = GetMessage (&mess, NULL, 0, 0);
|
|
||||||
if (bRet == 0 || bRet == -1 || // bRet == 0 means we received WM_QUIT
|
|
||||||
mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN)
|
|
||||||
{
|
|
||||||
if (blinking)
|
|
||||||
{
|
|
||||||
KillTimer (Window, 0x5A15A);
|
|
||||||
}
|
|
||||||
ST_Util_FreeBitmap (StartupBitmap);
|
|
||||||
ST_Util_FreeFont (font);
|
|
||||||
return int(bRet == 0 ? mess.wParam : 0);
|
|
||||||
}
|
|
||||||
else if (blinking && mess.message == WM_TIMER && mess.hwnd == Window && mess.wParam == 0x5A15A)
|
|
||||||
{
|
|
||||||
ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, font, blinkstate);
|
|
||||||
blinkstate = !blinkstate;
|
|
||||||
}
|
|
||||||
TranslateMessage (&mess);
|
|
||||||
DispatchMessage (&mess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ST_Endoom()
|
|
||||||
{
|
|
||||||
TexMan.DeleteAll();
|
|
||||||
int code = RunEndoom();
|
|
||||||
throw CExitEvent(code);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ST_Util_CreateStartupWindow
|
|
||||||
//
|
|
||||||
// Creates the static control that will draw the startup screen.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool ST_Util_CreateStartupWindow ()
|
|
||||||
{
|
|
||||||
StartupScreen = CreateWindowEx (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL,
|
|
||||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW,
|
|
||||||
0, 0, 0, 0, Window, NULL, g_hInst, NULL);
|
|
||||||
if (StartupScreen == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SetWindowLong (StartupScreen, GWL_ID, IDC_STATIC_STARTUP);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ST_Util_SizeWindowForBitmap
|
|
||||||
//
|
|
||||||
// Resizes the main window so that the startup bitmap will be drawn
|
|
||||||
// at the desired scale.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void ST_Util_SizeWindowForBitmap (int scale)
|
|
||||||
{
|
|
||||||
DEVMODE displaysettings;
|
|
||||||
int w, h, cx, cy, x, y;
|
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
if (GameTitleWindow != NULL)
|
|
||||||
{
|
|
||||||
GetClientRect (GameTitleWindow, &rect);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rect.bottom = 0;
|
|
||||||
}
|
|
||||||
RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale,
|
|
||||||
StartupBitmap->bmiHeader.biHeight * scale + rect.bottom };
|
|
||||||
AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW);
|
|
||||||
w = sizerect.right - sizerect.left;
|
|
||||||
h = sizerect.bottom - sizerect.top;
|
|
||||||
|
|
||||||
// Resize the window, but keep its center point the same, unless that
|
|
||||||
// puts it partially offscreen.
|
|
||||||
memset (&displaysettings, 0, sizeof(displaysettings));
|
|
||||||
displaysettings.dmSize = sizeof(displaysettings);
|
|
||||||
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
|
||||||
GetWindowRect (Window, &rect);
|
|
||||||
cx = (rect.left + rect.right) / 2;
|
|
||||||
cy = (rect.top + rect.bottom) / 2;
|
|
||||||
x = cx - w / 2;
|
|
||||||
y = cy - h / 2;
|
|
||||||
if (x + w > (int)displaysettings.dmPelsWidth)
|
|
||||||
{
|
|
||||||
x = displaysettings.dmPelsWidth - w;
|
|
||||||
}
|
|
||||||
if (x < 0)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
if (y + h > (int)displaysettings.dmPelsHeight)
|
|
||||||
{
|
|
||||||
y = displaysettings.dmPelsHeight - h;
|
|
||||||
}
|
|
||||||
if (y < 0)
|
|
||||||
{
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
MoveWindow (Window, x, y, w, h, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ST_Util_InvalidateRect
|
|
||||||
//
|
|
||||||
// Invalidates the portion of the window that the specified rect of the
|
|
||||||
// bitmap appears in.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
GetClientRect (hwnd, &rect);
|
|
||||||
rect.left = left * rect.right / bitmap_info->bmiHeader.biWidth - 1;
|
|
||||||
rect.top = top * rect.bottom / bitmap_info->bmiHeader.biHeight - 1;
|
|
||||||
rect.right = right * rect.right / bitmap_info->bmiHeader.biWidth + 1;
|
|
||||||
rect.bottom = bottom * rect.bottom / bitmap_info->bmiHeader.biHeight + 1;
|
|
||||||
InvalidateRect (hwnd, &rect, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom)
|
|
||||||
{
|
|
||||||
ST_Util_InvalidateRect(StartupScreen , bitmap_info, left, top, right, bottom);
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,6 +47,7 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "win32basevideo.h"
|
#include "win32basevideo.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
Win32BaseVideo::Win32BaseVideo()
|
Win32BaseVideo::Win32BaseVideo()
|
||||||
{
|
{
|
||||||
I_SetWndProc();
|
mainwindow.ShowGameView();
|
||||||
|
|
||||||
GetDisplayDeviceName();
|
GetDisplayDeviceName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#ifdef HAVE_SOFTPOLY
|
#ifdef HAVE_SOFTPOLY
|
||||||
|
|
||||||
|
@ -10,8 +11,6 @@ EXTERN_CVAR(Bool, vid_vsync)
|
||||||
|
|
||||||
bool ViewportLinearScale();
|
bool ViewportLinearScale();
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
#pragma comment(lib, "d3d9.lib")
|
#pragma comment(lib, "d3d9.lib")
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ void I_PolyPresentInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT rect = {};
|
RECT rect = {};
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
ClientWidth = rect.right;
|
ClientWidth = rect.right;
|
||||||
ClientHeight = rect.bottom;
|
ClientHeight = rect.bottom;
|
||||||
|
@ -52,10 +51,10 @@ void I_PolyPresentInit()
|
||||||
pp.BackBufferWidth = ClientWidth;
|
pp.BackBufferWidth = ClientWidth;
|
||||||
pp.BackBufferHeight = ClientHeight;
|
pp.BackBufferHeight = ClientHeight;
|
||||||
pp.BackBufferCount = 1;
|
pp.BackBufferCount = 1;
|
||||||
pp.hDeviceWindow = Window;
|
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||||
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||||
|
|
||||||
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device);
|
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mainwindow.GetHandle(), D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
I_FatalError("IDirect3D9.CreateDevice failed");
|
I_FatalError("IDirect3D9.CreateDevice failed");
|
||||||
|
@ -67,7 +66,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
|
|
||||||
RECT rect = {};
|
RECT rect = {};
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync)
|
if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync)
|
||||||
{
|
{
|
||||||
if (surface)
|
if (surface)
|
||||||
|
@ -86,7 +85,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
||||||
pp.BackBufferWidth = ClientWidth;
|
pp.BackBufferWidth = ClientWidth;
|
||||||
pp.BackBufferHeight = ClientHeight;
|
pp.BackBufferHeight = ClientHeight;
|
||||||
pp.BackBufferCount = 1;
|
pp.BackBufferCount = 1;
|
||||||
pp.hDeviceWindow = Window;
|
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||||
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||||
device->Reset(&pp);
|
device->Reset(&pp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
void I_GetVulkanDrawableSize(int *width, int *height)
|
void I_GetVulkanDrawableSize(int *width, int *height)
|
||||||
{
|
{
|
||||||
assert(Window);
|
assert(mainwindow.GetHandle());
|
||||||
|
|
||||||
RECT clientRect = { 0 };
|
RECT clientRect = { 0 };
|
||||||
GetClientRect(Window, &clientRect);
|
GetClientRect(mainwindow.GetHandle(), &clientRect);
|
||||||
|
|
||||||
if (width != nullptr)
|
if (width != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +65,7 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
|
||||||
windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
windowCreateInfo.pNext = nullptr;
|
windowCreateInfo.pNext = nullptr;
|
||||||
windowCreateInfo.flags = 0;
|
windowCreateInfo.flags = 0;
|
||||||
windowCreateInfo.hwnd = Window;
|
windowCreateInfo.hwnd = mainwindow.GetHandle();
|
||||||
windowCreateInfo.hinstance = GetModuleHandle(nullptr);
|
windowCreateInfo.hinstance = GetModuleHandle(nullptr);
|
||||||
|
|
||||||
const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface);
|
const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface);
|
||||||
|
|
|
@ -561,6 +561,11 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash,
|
||||||
GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D);
|
GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenGLFrameBuffer::CompileNextShader()
|
||||||
|
{
|
||||||
|
return GLRenderer->mShaderManager->CompileNextShader();
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// OpenGLFrameBuffer :: WipeStartScreen
|
// OpenGLFrameBuffer :: WipeStartScreen
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
explicit OpenGLFrameBuffer() {}
|
explicit OpenGLFrameBuffer() {}
|
||||||
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
|
OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ;
|
||||||
~OpenGLFrameBuffer();
|
~OpenGLFrameBuffer();
|
||||||
|
bool CompileNextShader() override;
|
||||||
void InitializeState() override;
|
void InitializeState() override;
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
|
|
|
@ -672,7 +672,7 @@ bool FShader::Bind()
|
||||||
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
|
FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType)
|
||||||
{
|
{
|
||||||
FString defines;
|
FString defines;
|
||||||
defines += shaderdefines;
|
if (shaderdefines) defines += shaderdefines;
|
||||||
// this can't be in the shader code due to ATI strangeness.
|
// this can't be in the shader code due to ATI strangeness.
|
||||||
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
||||||
if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n";
|
if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n";
|
||||||
|
@ -707,6 +707,20 @@ FShaderManager::FShaderManager()
|
||||||
mPassShaders.Push(new FShaderCollection((EPassType)passType));
|
mPassShaders.Push(new FShaderCollection((EPassType)passType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FShaderManager::CompileNextShader()
|
||||||
|
{
|
||||||
|
if (mPassShaders[mCompilePass]->CompileNextShader())
|
||||||
|
{
|
||||||
|
mCompilePass++;
|
||||||
|
if (mCompilePass >= MAX_PASS_TYPES)
|
||||||
|
{
|
||||||
|
mCompilePass = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FShaderManager::~FShaderManager()
|
FShaderManager::~FShaderManager()
|
||||||
{
|
{
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
@ -727,7 +741,7 @@ void FShaderManager::SetActiveShader(FShader *sh)
|
||||||
|
|
||||||
FShader *FShaderManager::BindEffect(int effect, EPassType passType)
|
FShader *FShaderManager::BindEffect(int effect, EPassType passType)
|
||||||
{
|
{
|
||||||
if (passType < mPassShaders.Size())
|
if (passType < mPassShaders.Size() && mCompilePass == -1)
|
||||||
return mPassShaders[passType]->BindEffect(effect);
|
return mPassShaders[passType]->BindEffect(effect);
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -735,7 +749,11 @@ FShader *FShaderManager::BindEffect(int effect, EPassType passType)
|
||||||
|
|
||||||
FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
||||||
{
|
{
|
||||||
if (r_skipmats && eff >= 3 && eff <= 4)
|
if (mCompilePass > -1)
|
||||||
|
{
|
||||||
|
return mPassShaders[0]->Get(0, false);
|
||||||
|
}
|
||||||
|
if ((r_skipmats && eff >= 3 && eff <= 4))
|
||||||
eff = 0;
|
eff = 0;
|
||||||
|
|
||||||
if (passType < mPassShaders.Size())
|
if (passType < mPassShaders.Size())
|
||||||
|
@ -752,7 +770,14 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT
|
||||||
|
|
||||||
FShaderCollection::FShaderCollection(EPassType passType)
|
FShaderCollection::FShaderCollection(EPassType passType)
|
||||||
{
|
{
|
||||||
CompileShaders(passType);
|
mPassType = passType;
|
||||||
|
mMaterialShaders.Clear();
|
||||||
|
mMaterialShadersNAT.Clear();
|
||||||
|
for (int i = 0; i < MAX_EFFECTS; i++)
|
||||||
|
{
|
||||||
|
mEffectShaders[i] = NULL;
|
||||||
|
}
|
||||||
|
CompileNextShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -772,35 +797,47 @@ FShaderCollection::~FShaderCollection()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FShaderCollection::CompileShaders(EPassType passType)
|
bool FShaderCollection::CompileNextShader()
|
||||||
{
|
{
|
||||||
mMaterialShaders.Clear();
|
int i = mCompileIndex;
|
||||||
mMaterialShadersNAT.Clear();
|
if (mCompileState == 0)
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
|
||||||
{
|
{
|
||||||
mEffectShaders[i] = NULL;
|
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, mPassType);
|
||||||
}
|
|
||||||
|
|
||||||
for(int i=0;defaultshaders[i].ShaderName != NULL;i++)
|
|
||||||
{
|
|
||||||
FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType);
|
|
||||||
mMaterialShaders.Push(shc);
|
mMaterialShaders.Push(shc);
|
||||||
if (i < SHADER_NoTexture)
|
mCompileIndex++;
|
||||||
|
if (defaultshaders[mCompileIndex].ShaderName == nullptr)
|
||||||
{
|
{
|
||||||
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType);
|
mCompileIndex = 0;
|
||||||
mMaterialShadersNAT.Push(shc1);
|
mCompileState++;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (mCompileState == 1)
|
||||||
for(unsigned i = 0; i < usershaders.Size(); i++)
|
{
|
||||||
|
FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, mPassType);
|
||||||
|
mMaterialShadersNAT.Push(shc1);
|
||||||
|
mCompileIndex++;
|
||||||
|
if (mCompileIndex >= SHADER_NoTexture)
|
||||||
|
{
|
||||||
|
mCompileIndex = 0;
|
||||||
|
mCompileState++;
|
||||||
|
if (usershaders.Size() == 0) mCompileState++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mCompileState == 2)
|
||||||
{
|
{
|
||||||
FString name = ExtractFileBase(usershaders[i].shader);
|
FString name = ExtractFileBase(usershaders[i].shader);
|
||||||
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
|
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
|
||||||
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType);
|
FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, mPassType);
|
||||||
mMaterialShaders.Push(shc);
|
mMaterialShaders.Push(shc);
|
||||||
|
mCompileIndex++;
|
||||||
|
if (mCompileIndex >= (int)usershaders.Size())
|
||||||
|
{
|
||||||
|
mCompileIndex = 0;
|
||||||
|
mCompileState++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (mCompileState == 3)
|
||||||
for(int i=0;i<MAX_EFFECTS;i++)
|
|
||||||
{
|
{
|
||||||
FShader *eff = new FShader(effectshaders[i].ShaderName);
|
FShader *eff = new FShader(effectshaders[i].ShaderName);
|
||||||
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
|
if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1,
|
||||||
|
@ -809,7 +846,13 @@ void FShaderCollection::CompileShaders(EPassType passType)
|
||||||
delete eff;
|
delete eff;
|
||||||
}
|
}
|
||||||
else mEffectShaders[i] = eff;
|
else mEffectShaders[i] = eff;
|
||||||
|
mCompileIndex++;
|
||||||
|
if (mCompileIndex >= MAX_EFFECTS)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -309,10 +309,12 @@ public:
|
||||||
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
|
FShader *Get(unsigned int eff, bool alphateston, EPassType passType);
|
||||||
|
|
||||||
void SetActiveShader(FShader *sh);
|
void SetActiveShader(FShader *sh);
|
||||||
|
bool CompileNextShader();
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FShader *mActiveShader = nullptr;
|
FShader *mActiveShader = nullptr;
|
||||||
TArray<FShaderCollection*> mPassShaders;
|
TArray<FShaderCollection*> mPassShaders;
|
||||||
|
int mCompilePass = 0;
|
||||||
|
|
||||||
friend class FShader;
|
friend class FShader;
|
||||||
};
|
};
|
||||||
|
@ -322,21 +324,23 @@ class FShaderCollection
|
||||||
TArray<FShader*> mMaterialShaders;
|
TArray<FShader*> mMaterialShaders;
|
||||||
TArray<FShader*> mMaterialShadersNAT;
|
TArray<FShader*> mMaterialShadersNAT;
|
||||||
FShader *mEffectShaders[MAX_EFFECTS];
|
FShader *mEffectShaders[MAX_EFFECTS];
|
||||||
|
int mCompileState = 0, mCompileIndex = 0;
|
||||||
|
EPassType mPassType;
|
||||||
|
|
||||||
void Clean();
|
void Clean();
|
||||||
void CompileShaders(EPassType passType);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FShaderCollection(EPassType passType);
|
FShaderCollection(EPassType passType);
|
||||||
~FShaderCollection();
|
~FShaderCollection();
|
||||||
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
|
FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType);
|
||||||
int Find(const char *mame);
|
int Find(const char *mame);
|
||||||
|
bool CompileNextShader();
|
||||||
FShader *BindEffect(int effect);
|
FShader *BindEffect(int effect);
|
||||||
|
|
||||||
FShader *Get(unsigned int eff, bool alphateston)
|
FShader *Get(unsigned int eff, bool alphateston)
|
||||||
{
|
{
|
||||||
// indices 0-2 match the warping modes, 3 no texture, the following are custom
|
// indices 0-2 match the warping modes, 3 no texture, the following are custom
|
||||||
if (!alphateston && eff <= 2)
|
if (!alphateston && eff < SHADER_NoTexture && mCompileState == -1)
|
||||||
{
|
{
|
||||||
return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
|
return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
|
|
||||||
void InitializeState() override;
|
void InitializeState() override;
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
int GetShaderCount() override { return 0; }
|
||||||
|
|
||||||
void FirstEye() override;
|
void FirstEye() override;
|
||||||
void NextEye(int eyecount) override;
|
void NextEye(int eyecount) override;
|
||||||
|
|
|
@ -733,7 +733,7 @@ bool FShader::Bind(ShaderFlavourData& flavour)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Since all shaders are REQUIRED, any error here needs to be fatal
|
//
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -744,21 +744,8 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP
|
||||||
// this can't be in the shader code due to ATI strangeness.
|
// this can't be in the shader code due to ATI strangeness.
|
||||||
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
if (!usediscard) defines += "#define NO_ALPHATEST\n";
|
||||||
|
|
||||||
FShader *shader = NULL;
|
FShader *shader = new FShader(ShaderName);
|
||||||
try
|
shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars());
|
||||||
{
|
|
||||||
shader = new FShader(ShaderName);
|
|
||||||
if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()))
|
|
||||||
{
|
|
||||||
I_FatalError("Unable to load shader %s\n", ShaderName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(CRecoverableError &err)
|
|
||||||
{
|
|
||||||
if (shader != NULL) delete shader;
|
|
||||||
shader = NULL;
|
|
||||||
I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage());
|
|
||||||
}
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,6 @@ ADD_STAT(lightstats)
|
||||||
static int printstats;
|
static int printstats;
|
||||||
static bool switchfps;
|
static bool switchfps;
|
||||||
static uint64_t waitstart;
|
static uint64_t waitstart;
|
||||||
extern uint64_t LastCount;
|
|
||||||
EXTERN_CVAR(Bool, vid_fps)
|
EXTERN_CVAR(Bool, vid_fps)
|
||||||
|
|
||||||
void CheckBench()
|
void CheckBench()
|
||||||
|
|
|
@ -34,7 +34,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "cmdlib.h"
|
||||||
#include "hw_shaderpatcher.h"
|
#include "hw_shaderpatcher.h"
|
||||||
|
#include "textures.h"
|
||||||
|
#include "hw_renderstate.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
|
||||||
|
|
||||||
static bool IsGlslWhitespace(char c)
|
static bool IsGlslWhitespace(char c)
|
||||||
|
@ -296,3 +300,12 @@ const FEffectShader effectshaders[] =
|
||||||
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
{ "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int DFrameBuffer::GetShaderCount()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; defaultshaders[i].ShaderName != nullptr; i++);
|
||||||
|
|
||||||
|
return MAX_PASS_TYPES * (countof(defaultshaders) - 1 + usershaders.Size() + MAX_EFFECTS + SHADER_NoTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,3 +28,4 @@ struct FEffectShader
|
||||||
|
|
||||||
extern const FDefaultShader defaultshaders[];
|
extern const FDefaultShader defaultshaders[];
|
||||||
extern const FEffectShader effectshaders[];
|
extern const FEffectShader effectshaders[];
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
|
|
||||||
PolyFrameBuffer(void *hMonitor, bool fullscreen);
|
PolyFrameBuffer(void *hMonitor, bool fullscreen);
|
||||||
~PolyFrameBuffer();
|
~PolyFrameBuffer();
|
||||||
|
int GetShaderCount() override { return 0; }
|
||||||
|
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
#include "polyrenderer/drawers/poly_triangle.h"
|
#include "polyrenderer/drawers/poly_triangle.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
void PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR(Int, r_debug_draw, 0, 0);
|
CVAR(Int, r_debug_draw, 0, 0);
|
||||||
|
|
||||||
|
@ -101,12 +97,7 @@ void DrawerThreads::WaitForWorkers()
|
||||||
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
|
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
|
||||||
if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
|
if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
I_FatalError("Drawer threads did not finish within 5 seconds!");
|
||||||
PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
// Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing
|
|
||||||
int *threadCrashed = nullptr;
|
|
||||||
*threadCrashed = 0xdeadbeef;
|
|
||||||
}
|
}
|
||||||
end_lock.unlock();
|
end_lock.unlock();
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,8 @@ public:
|
||||||
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
|
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
|
||||||
virtual bool IsVulkan() { return false; }
|
virtual bool IsVulkan() { return false; }
|
||||||
virtual bool IsPoly() { return false; }
|
virtual bool IsPoly() { return false; }
|
||||||
|
virtual int GetShaderCount();
|
||||||
|
virtual bool CompileNextShader() { return true; }
|
||||||
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
|
void SetAABBTree(hwrenderer::LevelAABBTree * tree)
|
||||||
{
|
{
|
||||||
mShadowMap.SetAABBTree(tree);
|
mShadowMap.SetAABBTree(tree);
|
||||||
|
@ -290,7 +292,6 @@ extern DFrameBuffer *screen;
|
||||||
|
|
||||||
#define SCREENWIDTH (screen->GetWidth ())
|
#define SCREENWIDTH (screen->GetWidth ())
|
||||||
#define SCREENHEIGHT (screen->GetHeight ())
|
#define SCREENHEIGHT (screen->GetHeight ())
|
||||||
#define SCREENPITCH (screen->GetPitch ())
|
|
||||||
|
|
||||||
EXTERN_CVAR (Float, vid_gamma)
|
EXTERN_CVAR (Float, vid_gamma)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
|
||||||
int samples = 1;
|
int samples = 1;
|
||||||
VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT;
|
VkSampleCountFlags bit = VK_SAMPLE_COUNT_1_BIT;
|
||||||
VkSampleCountFlags best = bit;
|
VkSampleCountFlags best = bit;
|
||||||
while (samples < requestedSamples)
|
while (samples <= requestedSamples)
|
||||||
{
|
{
|
||||||
if (deviceSampleCounts & bit)
|
if (deviceSampleCounts & bit)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,51 +28,93 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <ShaderLang.h>
|
#include <ShaderLang.h>
|
||||||
|
|
||||||
|
bool VkShaderManager::CompileNextShader()
|
||||||
|
{
|
||||||
|
const char *mainvp = "shaders/glsl/main.vp";
|
||||||
|
const char *mainfp = "shaders/glsl/main.fp";
|
||||||
|
int i = compileIndex;
|
||||||
|
|
||||||
|
if (compileState == 0)
|
||||||
|
{
|
||||||
|
// regular material shaders
|
||||||
|
|
||||||
|
VkShaderProgram prog;
|
||||||
|
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
|
||||||
|
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, compilePass == GBUFFER_PASS);
|
||||||
|
mMaterialShaders[compilePass].push_back(std::move(prog));
|
||||||
|
|
||||||
|
compileIndex++;
|
||||||
|
if (defaultshaders[compileIndex].ShaderName == nullptr)
|
||||||
|
{
|
||||||
|
compileIndex = 0;
|
||||||
|
compileState++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (compileState == 1)
|
||||||
|
{
|
||||||
|
// NAT material shaders
|
||||||
|
|
||||||
|
VkShaderProgram natprog;
|
||||||
|
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
|
||||||
|
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, compilePass == GBUFFER_PASS);
|
||||||
|
mMaterialShadersNAT[compilePass].push_back(std::move(natprog));
|
||||||
|
|
||||||
|
compileIndex++;
|
||||||
|
if (compileIndex == SHADER_NoTexture)
|
||||||
|
{
|
||||||
|
compileIndex = 0;
|
||||||
|
compileState++;
|
||||||
|
if (usershaders.Size() == 0) compileState++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (compileState == 2)
|
||||||
|
{
|
||||||
|
// user shaders
|
||||||
|
|
||||||
|
const FString& name = ExtractFileBase(usershaders[i].shader);
|
||||||
|
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
|
||||||
|
|
||||||
|
VkShaderProgram prog;
|
||||||
|
prog.vert = LoadVertShader(name, mainvp, defines);
|
||||||
|
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, compilePass == GBUFFER_PASS);
|
||||||
|
mMaterialShaders[compilePass].push_back(std::move(prog));
|
||||||
|
|
||||||
|
compileIndex++;
|
||||||
|
if (compileIndex >= (int)usershaders.Size())
|
||||||
|
{
|
||||||
|
compileIndex = 0;
|
||||||
|
compileState++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (compileState == 3)
|
||||||
|
{
|
||||||
|
// Effect shaders
|
||||||
|
|
||||||
|
VkShaderProgram prog;
|
||||||
|
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
|
||||||
|
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, compilePass == GBUFFER_PASS);
|
||||||
|
mEffectShaders[compilePass].push_back(std::move(prog));
|
||||||
|
|
||||||
|
compileIndex++;
|
||||||
|
if (compileIndex >= MAX_EFFECTS)
|
||||||
|
{
|
||||||
|
compileIndex = 0;
|
||||||
|
compilePass++;
|
||||||
|
if (compilePass == MAX_PASS_TYPES)
|
||||||
|
{
|
||||||
|
compileIndex = -1; // we're done.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
compileState = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
|
VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device)
|
||||||
{
|
{
|
||||||
ShInitialize();
|
ShInitialize();
|
||||||
|
CompileNextShader();
|
||||||
const char *mainvp = "shaders/glsl/main.vp";
|
|
||||||
const char *mainfp = "shaders/glsl/main.fp";
|
|
||||||
|
|
||||||
for (int j = 0; j < MAX_PASS_TYPES; j++)
|
|
||||||
{
|
|
||||||
bool gbufferpass = j;
|
|
||||||
for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++)
|
|
||||||
{
|
|
||||||
VkShaderProgram prog;
|
|
||||||
prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
|
|
||||||
prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass);
|
|
||||||
mMaterialShaders[j].push_back(std::move(prog));
|
|
||||||
|
|
||||||
if (i < SHADER_NoTexture)
|
|
||||||
{
|
|
||||||
VkShaderProgram natprog;
|
|
||||||
natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines);
|
|
||||||
natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass);
|
|
||||||
mMaterialShadersNAT[j].push_back(std::move(natprog));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < usershaders.Size(); i++)
|
|
||||||
{
|
|
||||||
FString name = ExtractFileBase(usershaders[i].shader);
|
|
||||||
FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines;
|
|
||||||
|
|
||||||
VkShaderProgram prog;
|
|
||||||
prog.vert = LoadVertShader(name, mainvp, defines);
|
|
||||||
prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass);
|
|
||||||
mMaterialShaders[j].push_back(std::move(prog));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_EFFECTS; i++)
|
|
||||||
{
|
|
||||||
VkShaderProgram prog;
|
|
||||||
prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines);
|
|
||||||
prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, gbufferpass);
|
|
||||||
mEffectShaders[j].push_back(std::move(prog));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkShaderManager::~VkShaderManager()
|
VkShaderManager::~VkShaderManager()
|
||||||
|
@ -82,7 +124,7 @@ VkShaderManager::~VkShaderManager()
|
||||||
|
|
||||||
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
|
VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
|
||||||
{
|
{
|
||||||
if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
|
if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag)
|
||||||
{
|
{
|
||||||
return &mEffectShaders[passType][effect];
|
return &mEffectShaders[passType][effect];
|
||||||
}
|
}
|
||||||
|
@ -91,8 +133,9 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType)
|
||||||
|
|
||||||
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType)
|
||||||
{
|
{
|
||||||
|
if (compileIndex != -1) return &mMaterialShaders[0][0];
|
||||||
// indices 0-2 match the warping modes, 3 no texture, the following are custom
|
// indices 0-2 match the warping modes, 3 no texture, the following are custom
|
||||||
if (!alphateston && eff <= 2)
|
if (!alphateston && eff < SHADER_NoTexture)
|
||||||
{
|
{
|
||||||
return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway
|
return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ public:
|
||||||
|
|
||||||
VkShaderProgram *GetEffect(int effect, EPassType passType);
|
VkShaderProgram *GetEffect(int effect, EPassType passType);
|
||||||
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
|
VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType);
|
||||||
|
bool CompileNextShader();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
|
std::unique_ptr<VulkanShader> LoadVertShader(FString shadername, const char *vert_lump, const char *defines);
|
||||||
|
@ -79,4 +80,6 @@ private:
|
||||||
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
|
std::vector<VkShaderProgram> mMaterialShaders[MAX_PASS_TYPES];
|
||||||
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
|
std::vector<VkShaderProgram> mMaterialShadersNAT[MAX_PASS_TYPES];
|
||||||
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
|
std::vector<VkShaderProgram> mEffectShaders[MAX_PASS_TYPES];
|
||||||
|
uint8_t compilePass = 0, compileState = 0;
|
||||||
|
int compileIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -277,16 +277,20 @@ void VulkanDevice::CreateInstance()
|
||||||
Extensions = GetExtensions();
|
Extensions = GetExtensions();
|
||||||
EnabledExtensions = GetPlatformExtensions();
|
EnabledExtensions = GetPlatformExtensions();
|
||||||
|
|
||||||
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
std::string debugLayer = "VK_LAYER_KHRONOS_validation";
|
||||||
bool wantDebugLayer = vk_debug;
|
bool wantDebugLayer = vk_debug;
|
||||||
bool debugLayerFound = false;
|
bool debugLayerFound = false;
|
||||||
for (const VkLayerProperties &layer : AvailableLayers)
|
if (wantDebugLayer)
|
||||||
{
|
{
|
||||||
if (layer.layerName == debugLayer && wantDebugLayer)
|
for (const VkLayerProperties& layer : AvailableLayers)
|
||||||
{
|
{
|
||||||
EnabledValidationLayers.push_back(debugLayer.c_str());
|
if (layer.layerName == debugLayer)
|
||||||
EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
{
|
||||||
debugLayerFound = true;
|
EnabledValidationLayers.push_back(layer.layerName);
|
||||||
|
EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
|
debugLayerFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,11 @@ void VulkanFrameBuffer::Update()
|
||||||
Super::Update();
|
Super::Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VulkanFrameBuffer::CompileNextShader()
|
||||||
|
{
|
||||||
|
return mShaderManager->CompileNextShader();
|
||||||
|
}
|
||||||
|
|
||||||
void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly)
|
void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly)
|
||||||
{
|
{
|
||||||
FrameTextureUpload.Buffers.clear();
|
FrameTextureUpload.Buffers.clear();
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
void InitializeState() override;
|
void InitializeState() override;
|
||||||
|
bool CompileNextShader() override;
|
||||||
void PrecacheMaterial(FMaterial *mat, int translation) override;
|
void PrecacheMaterial(FMaterial *mat, int translation) override;
|
||||||
void UpdatePalette() override;
|
void UpdatePalette() override;
|
||||||
const char* DeviceName() const override;
|
const char* DeviceName() const override;
|
||||||
|
|
|
@ -380,12 +380,13 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
||||||
auto base = Source();
|
auto base = Source();
|
||||||
int clampmode = state.mClampMode;
|
int clampmode = state.mClampMode;
|
||||||
int translation = state.mTranslation;
|
int translation = state.mTranslation;
|
||||||
|
auto translationp = IsLuminosityTranslation(translation)? translation : intptr_t(GPalette.GetTranslation(GetTranslationType(translation), GetTranslationIndex(translation)));
|
||||||
|
|
||||||
clampmode = base->GetClampMode(clampmode);
|
clampmode = base->GetClampMode(clampmode);
|
||||||
|
|
||||||
for (auto& set : mDescriptorSets)
|
for (auto& set : mDescriptorSets)
|
||||||
{
|
{
|
||||||
if (set.descriptor && set.clampmode == clampmode && set.flags == translation) return set.descriptor.get();
|
if (set.descriptor && set.clampmode == clampmode && set.remap == translationp) return set.descriptor.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int numLayers = NumLayers();
|
int numLayers = NumLayers();
|
||||||
|
@ -430,7 +431,7 @@ VulkanDescriptorSet* VkMaterial::GetDescriptorSet(const FMaterialState& state)
|
||||||
}
|
}
|
||||||
|
|
||||||
update.updateSets(fb->device);
|
update.updateSets(fb->device);
|
||||||
mDescriptorSets.emplace_back(clampmode, translation, std::move(descriptor));
|
mDescriptorSets.emplace_back(clampmode, translationp, std::move(descriptor));
|
||||||
return mDescriptorSets.back().descriptor.get();
|
return mDescriptorSets.back().descriptor.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,13 @@ class VkMaterial : public FMaterial
|
||||||
struct DescriptorEntry
|
struct DescriptorEntry
|
||||||
{
|
{
|
||||||
int clampmode;
|
int clampmode;
|
||||||
int flags;
|
intptr_t remap;
|
||||||
std::unique_ptr<VulkanDescriptorSet> descriptor;
|
std::unique_ptr<VulkanDescriptorSet> descriptor;
|
||||||
|
|
||||||
DescriptorEntry(int cm, int f, std::unique_ptr<VulkanDescriptorSet>&& d)
|
DescriptorEntry(int cm, intptr_t f, std::unique_ptr<VulkanDescriptorSet>&& d)
|
||||||
{
|
{
|
||||||
clampmode = cm;
|
clampmode = cm;
|
||||||
flags = f;
|
remap = f;
|
||||||
descriptor = std::move(d);
|
descriptor = std::move(d);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11158,7 +11158,7 @@ ExpEmit FxLocalArrayDeclaration::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
auto zero = build->GetConstantInt(0);
|
auto zero = build->GetConstantInt(0);
|
||||||
auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize);
|
auto elementSizeConst = build->GetConstantInt(static_cast<PArray *>(ValueType)->ElementSize);
|
||||||
int arrOffsetReg;
|
int arrOffsetReg = 0;
|
||||||
if (!isDynamicArray)
|
if (!isDynamicArray)
|
||||||
{
|
{
|
||||||
arrOffsetReg = build->Registers[REGT_POINTER].Get(1);
|
arrOffsetReg = build->Registers[REGT_POINTER].Get(1);
|
||||||
|
|
|
@ -421,6 +421,45 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
||||||
for (unsigned i = 0; i < Includes.Size(); i++)
|
for (unsigned i = 0; i < Includes.Size(); i++)
|
||||||
{
|
{
|
||||||
lumpnum = fileSystem.CheckNumForFullName(Includes[i], true);
|
lumpnum = fileSystem.CheckNumForFullName(Includes[i], true);
|
||||||
|
if (lumpnum == -1 && ( Includes[i].IndexOf("./") == 0 || Includes[i].IndexOf("../") == 0 ) ) // relative path resolving
|
||||||
|
{
|
||||||
|
FString fullPath = IncludeLocs[i].FileName.GetChars(); // get full path, format 'wad:filepath/filename'
|
||||||
|
|
||||||
|
long start = fullPath.IndexOf(":"); // find first ':'
|
||||||
|
|
||||||
|
long end = fullPath.LastIndexOf("/"); // find last '/'
|
||||||
|
|
||||||
|
if (start!=-1&&end!=-1)
|
||||||
|
{
|
||||||
|
FString resolvedPath = fullPath.Mid(start + 1, end - start - 1); // extract filepath from string
|
||||||
|
FString relativePath = Includes[i];
|
||||||
|
if ( relativePath.IndexOf("./") == 0 ) // strip initial marker
|
||||||
|
{
|
||||||
|
relativePath = relativePath.Mid(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pathOk = true;
|
||||||
|
|
||||||
|
while (relativePath.IndexOf("../") == 0) // go back one folder for each '..'
|
||||||
|
{
|
||||||
|
relativePath = relativePath.Mid(3);
|
||||||
|
long slash_index = resolvedPath.LastIndexOf("/");
|
||||||
|
if (slash_index != -1) {
|
||||||
|
resolvedPath = resolvedPath.Mid(0,slash_index);
|
||||||
|
} else {
|
||||||
|
pathOk = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( pathOk ) // if '..' parsing was successful
|
||||||
|
{
|
||||||
|
resolvedPath += "/" + relativePath; // add relative path
|
||||||
|
|
||||||
|
lumpnum = fileSystem.CheckNumForFullName(resolvedPath, true); // check for relative include
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (lumpnum == -1)
|
if (lumpnum == -1)
|
||||||
{
|
{
|
||||||
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
IncludeLocs[i].Message(MSG_ERROR, "Include script lump %s not found", Includes[i].GetChars());
|
||||||
|
|
199
source/common/startscreen/endoom.cpp
Normal file
199
source/common/startscreen/endoom.cpp
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
** endoom.cpp
|
||||||
|
** Handles the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** Copyright 2006-2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
// HEADER FILES ------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "m_argv.h"
|
||||||
|
#include "engineerrors.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "i_interface.h"
|
||||||
|
#include "texturemanager.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "i_time.h"
|
||||||
|
#include "g_input.h"
|
||||||
|
#include "d_eventbase.h"
|
||||||
|
|
||||||
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
// How many ms elapse between blinking text flips. On a standard VGA
|
||||||
|
// adapter, the characters are on for 16 frames and then off for another 16.
|
||||||
|
// The number here therefore corresponds roughly to the blink rate on a
|
||||||
|
// 60 Hz display.
|
||||||
|
#define BLINK_PERIOD 267
|
||||||
|
|
||||||
|
|
||||||
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, showendoom, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
{
|
||||||
|
if (self < 0) self = 0;
|
||||||
|
else if (self > 2) self=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
class FEndoomScreen : public FStartScreen
|
||||||
|
{
|
||||||
|
uint64_t lastUpdateTime;
|
||||||
|
bool blinkstate = false;
|
||||||
|
bool blinking = true;
|
||||||
|
uint8_t endoom_screen[4000];
|
||||||
|
|
||||||
|
public:
|
||||||
|
FEndoomScreen(int);
|
||||||
|
void Update();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHereticStartScreen Constructor
|
||||||
|
//
|
||||||
|
// Shows the Heretic startup screen. If the screen doesn't appear to be
|
||||||
|
// valid, it returns a failure code in hr.
|
||||||
|
//
|
||||||
|
// The loading screen is an 80x25 text screen with character data and
|
||||||
|
// attributes intermixed, which means it must be exactly 4000 bytes long.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FEndoomScreen::FEndoomScreen(int loading_lump)
|
||||||
|
: FStartScreen(0)
|
||||||
|
{
|
||||||
|
fileSystem.ReadFile(loading_lump, endoom_screen);
|
||||||
|
|
||||||
|
// Draw the loading screen to a bitmap.
|
||||||
|
StartupBitmap.Create(80 * 8, 26 * 16); // line 26 is for our own 'press any key to quit' message.
|
||||||
|
DrawTextScreen(StartupBitmap, endoom_screen);
|
||||||
|
ClearBlock(StartupBitmap, {0, 0, 0, 255}, 0, 25*16, 640, 16);
|
||||||
|
DrawString(StartupBitmap, 0, 25, GStrings("TXT_QUITENDOOM"), { 128, 128, 128 ,255}, { 0, 0, 0, 255});
|
||||||
|
lastUpdateTime = I_msTime();
|
||||||
|
|
||||||
|
// Does this screen need blinking?
|
||||||
|
for (int i = 0; i < 80*25; ++i)
|
||||||
|
{
|
||||||
|
if (endoom_screen[1+i*2] & 0x80)
|
||||||
|
{
|
||||||
|
blinking = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FEndoomScreen::Update()
|
||||||
|
{
|
||||||
|
if (blinking && I_msTime() > lastUpdateTime + BLINK_PERIOD)
|
||||||
|
{
|
||||||
|
lastUpdateTime = I_msTime();
|
||||||
|
UpdateTextBlink (StartupBitmap, endoom_screen, blinkstate);
|
||||||
|
blinkstate = !blinkstate;
|
||||||
|
StartupTexture->CleanHardwareData();
|
||||||
|
Render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Endoom
|
||||||
|
//
|
||||||
|
// Shows an ENDOOM text screen
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int RunEndoom()
|
||||||
|
{
|
||||||
|
if (showendoom == 0 || endoomName.Len() == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true);
|
||||||
|
|
||||||
|
if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2)
|
||||||
|
{
|
||||||
|
// showendoom==2 means to show only lumps from PWADs.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
S_StopMusic(true);
|
||||||
|
auto endoom = new FEndoomScreen(endoom_lump);
|
||||||
|
endoom->Render(true);
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
I_GetEvent();
|
||||||
|
endoom->Update();
|
||||||
|
while (eventtail != eventhead)
|
||||||
|
{
|
||||||
|
event_t *ev = &events[eventtail];
|
||||||
|
eventtail = (eventtail + 1) & (MAXEVENTS - 1);
|
||||||
|
|
||||||
|
if (ev->type == EV_KeyDown || ev->type == EV_KeyUp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ev->type == EV_GUI_Event && (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_LButtonDown || ev->subtype == EV_GUI_RButtonDown || ev->subtype == EV_GUI_MButtonDown))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ST_Endoom()
|
||||||
|
{
|
||||||
|
int code = RunEndoom();
|
||||||
|
throw CExitEvent(code);
|
||||||
|
}
|
716
source/common/startscreen/startscreen.cpp
Normal file
716
source/common/startscreen/startscreen.cpp
Normal file
|
@ -0,0 +1,716 @@
|
||||||
|
/*
|
||||||
|
** st_start.cpp
|
||||||
|
** Handles the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** Copyright 2006-2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "palutil.h"
|
||||||
|
#include "v_font.h"
|
||||||
|
#include "i_interface.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "m_argv.h"
|
||||||
|
#include "engineerrors.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "i_time.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "v_draw.h"
|
||||||
|
#include "g_input.h"
|
||||||
|
#include "texturemanager.h"
|
||||||
|
#include "gi.h"
|
||||||
|
|
||||||
|
// Text mode color values
|
||||||
|
enum{
|
||||||
|
LO = 85,
|
||||||
|
MD = 170,
|
||||||
|
HI = 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
const RgbQuad TextModePalette[16] =
|
||||||
|
{
|
||||||
|
{ 0, 0, 0, 255 }, // 0 black
|
||||||
|
{ MD, 0, 0, 255 }, // 1 blue
|
||||||
|
{ 0, MD, 0, 255 }, // 2 green
|
||||||
|
{ MD, MD, 0, 255 }, // 3 cyan
|
||||||
|
{ 0, 0, MD, 255 }, // 4 red
|
||||||
|
{ MD, 0, MD, 255 }, // 5 magenta
|
||||||
|
{ 0, LO, MD, 255 }, // 6 brown
|
||||||
|
{ MD, MD, MD, 255 }, // 7 light gray
|
||||||
|
|
||||||
|
{ LO, LO, LO, 255 }, // 8 dark gray
|
||||||
|
{ HI, LO, LO, 255 }, // 9 light blue
|
||||||
|
{ LO, HI, LO, 255 }, // A light green
|
||||||
|
{ HI, HI, LO, 255 }, // B light cyan
|
||||||
|
{ LO, LO, HI, 255 }, // C light red
|
||||||
|
{ HI, LO, HI, 255 }, // D light magenta
|
||||||
|
{ LO, HI, HI, 255 }, // E yellow
|
||||||
|
{ HI, HI, HI, 255 }, // F white
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t IBM437ToUnicode[] = {
|
||||||
|
0x0000, //#NULL
|
||||||
|
0x263a, //#START OF HEADING
|
||||||
|
0x263B, //#START OF TEXT
|
||||||
|
0x2665, //#END OF TEXT
|
||||||
|
0x2666, //#END OF TRANSMISSION
|
||||||
|
0x2663, //#ENQUIRY
|
||||||
|
0x2660, //#ACKNOWLEDGE
|
||||||
|
0x2022, //#BELL
|
||||||
|
0x25d8, //#BACKSPACE
|
||||||
|
0x25cb, //#HORIZONTAL TABULATION
|
||||||
|
0x25d9, //#LINE FEED
|
||||||
|
0x2642, //#VERTICAL TABULATION
|
||||||
|
0x2640, //#FORM FEED
|
||||||
|
0x266a, //#CARRIAGE RETURN
|
||||||
|
0x266b, //#SHIFT OUT
|
||||||
|
0x263c, //#SHIFT IN
|
||||||
|
0x25ba, //#DATA LINK ESCAPE
|
||||||
|
0x25c4, //#DEVICE CONTROL ONE
|
||||||
|
0x2195, //#DEVICE CONTROL TWO
|
||||||
|
0x203c, //#DEVICE CONTROL THREE
|
||||||
|
0x00b6, //#DEVICE CONTROL FOUR
|
||||||
|
0x00a7, //#NEGATIVE ACKNOWLEDGE
|
||||||
|
0x25ac, //#SYNCHRONOUS IDLE
|
||||||
|
0x21ab, //#END OF TRANSMISSION BLOCK
|
||||||
|
0x2191, //#CANCEL
|
||||||
|
0x2193, //#END OF MEDIUM
|
||||||
|
0x2192, //#SUBSTITUTE
|
||||||
|
0x2190, //#ESCAPE
|
||||||
|
0x221f, //#FILE SEPARATOR
|
||||||
|
0x2194, //#GROUP SEPARATOR
|
||||||
|
0x25b2, //#RECORD SEPARATOR
|
||||||
|
0x25bc, //#UNIT SEPARATOR
|
||||||
|
0x0020, //#SPACE
|
||||||
|
0x0021, //#EXCLAMATION MARK
|
||||||
|
0x0022, //#QUOTATION MARK
|
||||||
|
0x0023, //#NUMBER SIGN
|
||||||
|
0x0024, //#DOLLAR SIGN
|
||||||
|
0x0025, //#PERCENT SIGN
|
||||||
|
0x0026, //#AMPERSAND
|
||||||
|
0x0027, //#APOSTROPHE
|
||||||
|
0x0028, //#LEFT PARENTHESIS
|
||||||
|
0x0029, //#RIGHT PARENTHESIS
|
||||||
|
0x002a, //#ASTERISK
|
||||||
|
0x002b, //#PLUS SIGN
|
||||||
|
0x002c, //#COMMA
|
||||||
|
0x002d, //#HYPHEN-MINUS
|
||||||
|
0x002e, //#FULL STOP
|
||||||
|
0x002f, //#SOLIDUS
|
||||||
|
0x0030, //#DIGIT ZERO
|
||||||
|
0x0031, //#DIGIT ONE
|
||||||
|
0x0032, //#DIGIT TWO
|
||||||
|
0x0033, //#DIGIT THREE
|
||||||
|
0x0034, //#DIGIT FOUR
|
||||||
|
0x0035, //#DIGIT FIVE
|
||||||
|
0x0036, //#DIGIT SIX
|
||||||
|
0x0037, //#DIGIT SEVEN
|
||||||
|
0x0038, //#DIGIT EIGHT
|
||||||
|
0x0039, //#DIGIT NINE
|
||||||
|
0x003a, //#COLON
|
||||||
|
0x003b, //#SEMICOLON
|
||||||
|
0x003c, //#LESS-THAN SIGN
|
||||||
|
0x003d, //#EQUALS SIGN
|
||||||
|
0x003e, //#GREATER-THAN SIGN
|
||||||
|
0x003f, //#QUESTION MARK
|
||||||
|
0x0040, //#COMMERCIAL AT
|
||||||
|
0x0041, //#LATIN CAPITAL LETTER A
|
||||||
|
0x0042, //#LATIN CAPITAL LETTER B
|
||||||
|
0x0043, //#LATIN CAPITAL LETTER C
|
||||||
|
0x0044, //#LATIN CAPITAL LETTER D
|
||||||
|
0x0045, //#LATIN CAPITAL LETTER E
|
||||||
|
0x0046, //#LATIN CAPITAL LETTER F
|
||||||
|
0x0047, //#LATIN CAPITAL LETTER G
|
||||||
|
0x0048, //#LATIN CAPITAL LETTER H
|
||||||
|
0x0049, //#LATIN CAPITAL LETTER I
|
||||||
|
0x004a, //#LATIN CAPITAL LETTER J
|
||||||
|
0x004b, //#LATIN CAPITAL LETTER K
|
||||||
|
0x004c, //#LATIN CAPITAL LETTER L
|
||||||
|
0x004d, //#LATIN CAPITAL LETTER M
|
||||||
|
0x004e, //#LATIN CAPITAL LETTER N
|
||||||
|
0x004f, //#LATIN CAPITAL LETTER O
|
||||||
|
0x0050, //#LATIN CAPITAL LETTER P
|
||||||
|
0x0051, //#LATIN CAPITAL LETTER Q
|
||||||
|
0x0052, //#LATIN CAPITAL LETTER R
|
||||||
|
0x0053, //#LATIN CAPITAL LETTER S
|
||||||
|
0x0054, //#LATIN CAPITAL LETTER T
|
||||||
|
0x0055, //#LATIN CAPITAL LETTER U
|
||||||
|
0x0056, //#LATIN CAPITAL LETTER V
|
||||||
|
0x0057, //#LATIN CAPITAL LETTER W
|
||||||
|
0x0058, //#LATIN CAPITAL LETTER X
|
||||||
|
0x0059, //#LATIN CAPITAL LETTER Y
|
||||||
|
0x005a, //#LATIN CAPITAL LETTER Z
|
||||||
|
0x005b, //#LEFT SQUARE BRACKET
|
||||||
|
0x005c, //#REVERSE SOLIDUS
|
||||||
|
0x005d, //#RIGHT SQUARE BRACKET
|
||||||
|
0x005e, //#CIRCUMFLEX ACCENT
|
||||||
|
0x005f, //#LOW LINE
|
||||||
|
0x0060, //#GRAVE ACCENT
|
||||||
|
0x0061, //#LATIN SMALL LETTER A
|
||||||
|
0x0062, //#LATIN SMALL LETTER B
|
||||||
|
0x0063, //#LATIN SMALL LETTER C
|
||||||
|
0x0064, //#LATIN SMALL LETTER D
|
||||||
|
0x0065, //#LATIN SMALL LETTER E
|
||||||
|
0x0066, //#LATIN SMALL LETTER F
|
||||||
|
0x0067, //#LATIN SMALL LETTER G
|
||||||
|
0x0068, //#LATIN SMALL LETTER H
|
||||||
|
0x0069, //#LATIN SMALL LETTER I
|
||||||
|
0x006a, //#LATIN SMALL LETTER J
|
||||||
|
0x006b, //#LATIN SMALL LETTER K
|
||||||
|
0x006c, //#LATIN SMALL LETTER L
|
||||||
|
0x006d, //#LATIN SMALL LETTER M
|
||||||
|
0x006e, //#LATIN SMALL LETTER N
|
||||||
|
0x006f, //#LATIN SMALL LETTER O
|
||||||
|
0x0070, //#LATIN SMALL LETTER P
|
||||||
|
0x0071, //#LATIN SMALL LETTER Q
|
||||||
|
0x0072, //#LATIN SMALL LETTER R
|
||||||
|
0x0073, //#LATIN SMALL LETTER S
|
||||||
|
0x0074, //#LATIN SMALL LETTER T
|
||||||
|
0x0075, //#LATIN SMALL LETTER U
|
||||||
|
0x0076, //#LATIN SMALL LETTER V
|
||||||
|
0x0077, //#LATIN SMALL LETTER W
|
||||||
|
0x0078, //#LATIN SMALL LETTER X
|
||||||
|
0x0079, //#LATIN SMALL LETTER Y
|
||||||
|
0x007a, //#LATIN SMALL LETTER Z
|
||||||
|
0x007b, //#LEFT CURLY BRACKET
|
||||||
|
0x007c, //#VERTICAL LINE
|
||||||
|
0x007d, //#RIGHT CURLY BRACKET
|
||||||
|
0x007e, //#TILDE
|
||||||
|
0x2302, //#DELETE
|
||||||
|
0x00c7, //#LATIN CAPITAL LETTER C WITH CEDILLA
|
||||||
|
0x00fc, //#LATIN SMALL LETTER U WITH DIAERESIS
|
||||||
|
0x00e9, //#LATIN SMALL LETTER E WITH ACUTE
|
||||||
|
0x00e2, //#LATIN SMALL LETTER A WITH CIRCUMFLEX
|
||||||
|
0x00e4, //#LATIN SMALL LETTER A WITH DIAERESIS
|
||||||
|
0x00e0, //#LATIN SMALL LETTER A WITH GRAVE
|
||||||
|
0x00e5, //#LATIN SMALL LETTER A WITH RING ABOVE
|
||||||
|
0x00e7, //#LATIN SMALL LETTER C WITH CEDILLA
|
||||||
|
0x00ea, //#LATIN SMALL LETTER E WITH CIRCUMFLEX
|
||||||
|
0x00eb, //#LATIN SMALL LETTER E WITH DIAERESIS
|
||||||
|
0x00e8, //#LATIN SMALL LETTER E WITH GRAVE
|
||||||
|
0x00ef, //#LATIN SMALL LETTER I WITH DIAERESIS
|
||||||
|
0x00ee, //#LATIN SMALL LETTER I WITH CIRCUMFLEX
|
||||||
|
0x00ec, //#LATIN SMALL LETTER I WITH GRAVE
|
||||||
|
0x00c4, //#LATIN CAPITAL LETTER A WITH DIAERESIS
|
||||||
|
0x00c5, //#LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||||
|
0x00c9, //#LATIN CAPITAL LETTER E WITH ACUTE
|
||||||
|
0x00e6, //#LATIN SMALL LIGATURE AE
|
||||||
|
0x00c6, //#LATIN CAPITAL LIGATURE AE
|
||||||
|
0x00f4, //#LATIN SMALL LETTER O WITH CIRCUMFLEX
|
||||||
|
0x00f6, //#LATIN SMALL LETTER O WITH DIAERESIS
|
||||||
|
0x00f2, //#LATIN SMALL LETTER O WITH GRAVE
|
||||||
|
0x00fb, //#LATIN SMALL LETTER U WITH CIRCUMFLEX
|
||||||
|
0x00f9, //#LATIN SMALL LETTER U WITH GRAVE
|
||||||
|
0x00ff, //#LATIN SMALL LETTER Y WITH DIAERESIS
|
||||||
|
0x00d6, //#LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||||
|
0x00dc, //#LATIN CAPITAL LETTER U WITH DIAERESIS
|
||||||
|
0x00a2, //#CENT SIGN
|
||||||
|
0x00a3, //#POUND SIGN
|
||||||
|
0x00a5, //#YEN SIGN
|
||||||
|
0x20a7, //#PESETA SIGN
|
||||||
|
0x0192, //#LATIN SMALL LETTER F WITH HOOK
|
||||||
|
0x00e1, //#LATIN SMALL LETTER A WITH ACUTE
|
||||||
|
0x00ed, //#LATIN SMALL LETTER I WITH ACUTE
|
||||||
|
0x00f3, //#LATIN SMALL LETTER O WITH ACUTE
|
||||||
|
0x00fa, //#LATIN SMALL LETTER U WITH ACUTE
|
||||||
|
0x00f1, //#LATIN SMALL LETTER N WITH TILDE
|
||||||
|
0x00d1, //#LATIN CAPITAL LETTER N WITH TILDE
|
||||||
|
0x00aa, //#FEMININE ORDINAL INDICATOR
|
||||||
|
0x00ba, //#MASCULINE ORDINAL INDICATOR
|
||||||
|
0x00bf, //#INVERTED QUESTION MARK
|
||||||
|
0x2310, //#REVERSED NOT SIGN
|
||||||
|
0x00ac, //#NOT SIGN
|
||||||
|
0x00bd, //#VULGAR FRACTION ONE HALF
|
||||||
|
0x00bc, //#VULGAR FRACTION ONE QUARTER
|
||||||
|
0x00a1, //#INVERTED EXCLAMATION MARK
|
||||||
|
0x00ab, //#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||||
|
0x00bb, //#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
||||||
|
0x2591, //#LIGHT SHADE
|
||||||
|
0x2592, //#MEDIUM SHADE
|
||||||
|
0x2593, //#DARK SHADE
|
||||||
|
0x2502, //#BOX DRAWINGS LIGHT VERTICAL
|
||||||
|
0x2524, //#BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||||
|
0x2561, //#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
|
||||||
|
0x2562, //#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
|
||||||
|
0x2556, //#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
|
||||||
|
0x2555, //#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
|
||||||
|
0x2563, //#BOX DRAWINGS DOUBLE VERTICAL AND LEFT
|
||||||
|
0x2551, //#BOX DRAWINGS DOUBLE VERTICAL
|
||||||
|
0x2557, //#BOX DRAWINGS DOUBLE DOWN AND LEFT
|
||||||
|
0x255d, //#BOX DRAWINGS DOUBLE UP AND LEFT
|
||||||
|
0x255c, //#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
|
||||||
|
0x255b, //#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
|
||||||
|
0x2510, //#BOX DRAWINGS LIGHT DOWN AND LEFT
|
||||||
|
0x2514, //#BOX DRAWINGS LIGHT UP AND RIGHT
|
||||||
|
0x2534, //#BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||||
|
0x252c, //#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||||
|
0x251c, //#BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||||
|
0x2500, //#BOX DRAWINGS LIGHT HORIZONTAL
|
||||||
|
0x253c, //#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
|
||||||
|
0x255e, //#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
|
||||||
|
0x255f, //#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
|
||||||
|
0x255a, //#BOX DRAWINGS DOUBLE UP AND RIGHT
|
||||||
|
0x2554, //#BOX DRAWINGS DOUBLE DOWN AND RIGHT
|
||||||
|
0x2569, //#BOX DRAWINGS DOUBLE UP AND HORIZONTAL
|
||||||
|
0x2566, //#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
|
||||||
|
0x2560, //#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
|
||||||
|
0x2550, //#BOX DRAWINGS DOUBLE HORIZONTAL
|
||||||
|
0x256c, //#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
|
||||||
|
0x2567, //#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
|
||||||
|
0x2568, //#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
|
||||||
|
0x2564, //#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
|
||||||
|
0x2565, //#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
|
||||||
|
0x2559, //#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
|
||||||
|
0x2558, //#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
|
||||||
|
0x2552, //#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
|
||||||
|
0x2553, //#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
|
||||||
|
0x256b, //#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
|
||||||
|
0x256a, //#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
|
||||||
|
0x2518, //#BOX DRAWINGS LIGHT UP AND LEFT
|
||||||
|
0x250c, //#BOX DRAWINGS LIGHT DOWN AND RIGHT
|
||||||
|
0x2588, //#FULL BLOCK
|
||||||
|
0x2584, //#LOWER HALF BLOCK
|
||||||
|
0x258c, //#LEFT HALF BLOCK
|
||||||
|
0x2590, //#RIGHT HALF BLOCK
|
||||||
|
0x2580, //#UPPER HALF BLOCK
|
||||||
|
0x03b1, //#GREEK SMALL LETTER ALPHA
|
||||||
|
0x00df, //#LATIN SMALL LETTER SHARP S
|
||||||
|
0x0393, //#GREEK CAPITAL LETTER GAMMA
|
||||||
|
0x03c0, //#GREEK SMALL LETTER PI
|
||||||
|
0x03a3, //#GREEK CAPITAL LETTER SIGMA
|
||||||
|
0x03c3, //#GREEK SMALL LETTER SIGMA
|
||||||
|
0x00b5, //#MICRO SIGN
|
||||||
|
0x03c4, //#GREEK SMALL LETTER TAU
|
||||||
|
0x03a6, //#GREEK CAPITAL LETTER PHI
|
||||||
|
0x0398, //#GREEK CAPITAL LETTER THETA
|
||||||
|
0x03a9, //#GREEK CAPITAL LETTER OMEGA
|
||||||
|
0x03b4, //#GREEK SMALL LETTER DELTA
|
||||||
|
0x221e, //#INFINITY
|
||||||
|
0x03c6, //#GREEK SMALL LETTER PHI
|
||||||
|
0x03b5, //#GREEK SMALL LETTER EPSILON
|
||||||
|
0x2229, //#INTERSECTION
|
||||||
|
0x2261, //#IDENTICAL TO
|
||||||
|
0x00b1, //#PLUS-MINUS SIGN
|
||||||
|
0x2265, //#GREATER-THAN OR EQUAL TO
|
||||||
|
0x2264, //#LESS-THAN OR EQUAL TO
|
||||||
|
0x2320, //#TOP HALF INTEGRAL
|
||||||
|
0x2321, //#BOTTOM HALF INTEGRAL
|
||||||
|
0x00f7, //#DIVISION SIGN
|
||||||
|
0x2248, //#ALMOST EQUAL TO
|
||||||
|
0x00b0, //#DEGREE SIGN
|
||||||
|
0x2219, //#BULLET OPERATOR
|
||||||
|
0x00b7, //#MIDDLE DOT
|
||||||
|
0x221a, //#SQUARE ROOT
|
||||||
|
0x207f, //#SUPERSCRIPT LATIN SMALL LETTER N
|
||||||
|
0x00b2, //#SUPERSCRIPT TWO
|
||||||
|
0x25a0, //#BLACK SQUARE
|
||||||
|
0x00a0, //#NO-BREAK SPACE
|
||||||
|
};
|
||||||
|
|
||||||
|
FStartScreen* CreateHexenStartScreen(int max_progress);
|
||||||
|
FStartScreen* CreateHereticStartScreen(int max_progress);
|
||||||
|
FStartScreen* CreateStrifeStartScreen(int max_progress);
|
||||||
|
FStartScreen* CreateGenericStartScreen(int max_progress);
|
||||||
|
|
||||||
|
|
||||||
|
FStartScreen* GetGameStartScreen(int max_progress)
|
||||||
|
{
|
||||||
|
if (!Args->CheckParm("-nostartup"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (GameStartupInfo.Type == FStartupInfo::HexenStartup)
|
||||||
|
{
|
||||||
|
return CreateHexenStartScreen(max_progress);
|
||||||
|
}
|
||||||
|
else if (GameStartupInfo.Type == FStartupInfo::HereticStartup)
|
||||||
|
{
|
||||||
|
return CreateHereticStartScreen(max_progress);
|
||||||
|
}
|
||||||
|
else if (GameStartupInfo.Type == FStartupInfo::StrifeStartup)
|
||||||
|
{
|
||||||
|
return CreateStrifeStartScreen(max_progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(const CRecoverableError& err)
|
||||||
|
{
|
||||||
|
Printf("Error creating start screen: %s\n", err.what());
|
||||||
|
// fall through to the generic startup screen
|
||||||
|
}
|
||||||
|
//return CreateGenericStartScreen(max_progress);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Util_ClearBlock
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::ClearBlock(FBitmap& bitmap_info, RgbQuad fill, int x, int y, int bytewidth, int height)
|
||||||
|
{
|
||||||
|
int destpitch = bitmap_info.GetWidth();
|
||||||
|
auto dest = (RgbQuad*)(bitmap_info.GetPixels()) + x + y * destpitch;
|
||||||
|
|
||||||
|
while (height > 0)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < bytewidth; i++)
|
||||||
|
{
|
||||||
|
dest[i] = fill;
|
||||||
|
}
|
||||||
|
dest += destpitch;
|
||||||
|
height--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Util_DrawTextScreen
|
||||||
|
//
|
||||||
|
// Draws the text screen to the bitmap. The bitmap must be the proper size
|
||||||
|
// for the font.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::DrawTextScreen(FBitmap& bitmap_info, const uint8_t* text_screen)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (y = 0; y < 25; ++y)
|
||||||
|
{
|
||||||
|
for (x = 0; x < 80; ++x)
|
||||||
|
{
|
||||||
|
DrawChar(bitmap_info, x, y, IBM437ToUnicode[text_screen[0]], text_screen[1]);
|
||||||
|
text_screen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Util_DrawChar
|
||||||
|
//
|
||||||
|
// Draws a character on the bitmap. X and Y specify the character cell,
|
||||||
|
// and fg and bg are 4-bit colors.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
uint8_t* GetHexChar(int codepoint);
|
||||||
|
|
||||||
|
int FStartScreen::DrawChar(FBitmap& screen, double x, double y, unsigned charnum, RgbQuad fg, RgbQuad bg)
|
||||||
|
{
|
||||||
|
if (x < 0 || y < 0 || y >= screen.GetHeight() - 16) return 1;
|
||||||
|
static const uint8_t space[17] = { 16 };
|
||||||
|
const RgbQuad color_array[4] = { bg, fg };
|
||||||
|
const uint8_t* src = GetHexChar(charnum);
|
||||||
|
if (!src) src = space;
|
||||||
|
int size = (*src++) == 32? 2 : 1;
|
||||||
|
if (x > (screen.GetWidth() >> 3) - size) return size;
|
||||||
|
int pitch = screen.GetWidth();
|
||||||
|
RgbQuad* dest = (RgbQuad*)screen.GetPixels() + int(x * 8) + int(y * 16) * pitch;
|
||||||
|
|
||||||
|
for (y = 0; y <16; ++y)
|
||||||
|
{
|
||||||
|
uint8_t srcbyte = *src++;
|
||||||
|
|
||||||
|
dest[0] = color_array[(srcbyte >> 7) & 1];
|
||||||
|
dest[1] = color_array[(srcbyte >> 6) & 1];
|
||||||
|
dest[2] = color_array[(srcbyte >> 5) & 1];
|
||||||
|
dest[3] = color_array[(srcbyte >> 4) & 1];
|
||||||
|
dest[4] = color_array[(srcbyte >> 3) & 1];
|
||||||
|
dest[5] = color_array[(srcbyte >> 2) & 1];
|
||||||
|
dest[6] = color_array[(srcbyte >> 1) & 1];
|
||||||
|
dest[7] = color_array[(srcbyte) & 1];
|
||||||
|
if (size == 16)
|
||||||
|
{
|
||||||
|
srcbyte = *src++;
|
||||||
|
|
||||||
|
dest[8] = color_array[(srcbyte >> 7) & 1];
|
||||||
|
dest[9] = color_array[(srcbyte >> 6) & 1];
|
||||||
|
dest[10] = color_array[(srcbyte >> 5) & 1];
|
||||||
|
dest[11] = color_array[(srcbyte >> 4) & 1];
|
||||||
|
dest[12] = color_array[(srcbyte >> 3) & 1];
|
||||||
|
dest[13] = color_array[(srcbyte >> 2) & 1];
|
||||||
|
dest[14] = color_array[(srcbyte >> 1) & 1];
|
||||||
|
dest[15] = color_array[(srcbyte) & 1];
|
||||||
|
}
|
||||||
|
dest += pitch;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FStartScreen::DrawChar(FBitmap& screen, double x, double y, unsigned charnum, uint8_t attrib)
|
||||||
|
{
|
||||||
|
const uint8_t bg = (attrib & 0x70) >> 4;
|
||||||
|
const uint8_t fg = attrib & 0x0F;
|
||||||
|
auto bgc = TextModePalette[bg], fgc = TextModePalette[fg];
|
||||||
|
return DrawChar(screen, x, y, charnum, fgc, bgc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FStartScreen::DrawString(FBitmap& screen, double x, double y, const char* text, RgbQuad fg, RgbQuad bg)
|
||||||
|
{
|
||||||
|
double oldx = x;
|
||||||
|
auto str = (const uint8_t*)text;
|
||||||
|
while (auto chr = GetCharFromString(str))
|
||||||
|
{
|
||||||
|
x += DrawChar(screen, x, y, chr, fg, bg);
|
||||||
|
}
|
||||||
|
return int(x - oldx);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// SizeOfText
|
||||||
|
//
|
||||||
|
// returns width in pixels
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int FStartScreen::SizeOfText(const char* text)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
const uint8_t* utext = (uint8_t*)text;
|
||||||
|
while(auto code = GetCharFromString(utext))
|
||||||
|
{
|
||||||
|
const uint8_t* src = GetHexChar(code);
|
||||||
|
if (src && *src == 32) len += 2;
|
||||||
|
else len ++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Util_UpdateTextBlink
|
||||||
|
//
|
||||||
|
// Draws the parts of the text screen that blink to the bitmap. The bitmap
|
||||||
|
// must be the proper size for the font.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::UpdateTextBlink(FBitmap& bitmap_info, const uint8_t* text_screen, bool on)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (y = 0; y < 25; ++y)
|
||||||
|
{
|
||||||
|
for (x = 0; x < 80; ++x)
|
||||||
|
{
|
||||||
|
if (text_screen[1] & 0x80)
|
||||||
|
{
|
||||||
|
DrawChar(bitmap_info, x, y, on ? IBM437ToUnicode[text_screen[0]] : ' ', text_screen[1]);
|
||||||
|
}
|
||||||
|
text_screen += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ST_Sound
|
||||||
|
//
|
||||||
|
// plays a sound on the start screen
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::ST_Sound(const char* sndname)
|
||||||
|
{
|
||||||
|
if (sysCallbacks.PlayStartupSound)
|
||||||
|
sysCallbacks.PlayStartupSound(sndname);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CreateHeader
|
||||||
|
//
|
||||||
|
// creates a bitmap for the title header
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::CreateHeader()
|
||||||
|
{
|
||||||
|
HeaderBitmap.Create(StartupBitmap.GetWidth() * Scale, 2 * 16);
|
||||||
|
RgbQuad bcolor, fcolor;
|
||||||
|
bcolor.rgbRed = RPART(GameStartupInfo.BkColor);
|
||||||
|
bcolor.rgbGreen = GPART(GameStartupInfo.BkColor);
|
||||||
|
bcolor.rgbBlue = BPART(GameStartupInfo.BkColor);
|
||||||
|
bcolor.rgbReserved = 255;
|
||||||
|
fcolor.rgbRed = RPART(GameStartupInfo.FgColor);
|
||||||
|
fcolor.rgbGreen = GPART(GameStartupInfo.FgColor);
|
||||||
|
fcolor.rgbBlue = BPART(GameStartupInfo.FgColor);
|
||||||
|
fcolor.rgbReserved = 255;
|
||||||
|
ClearBlock(HeaderBitmap, bcolor, 0, 0, HeaderBitmap.GetWidth(), HeaderBitmap.GetHeight());
|
||||||
|
int textlen = SizeOfText(GameStartupInfo.Name);
|
||||||
|
DrawString(HeaderBitmap, (HeaderBitmap.GetWidth() >> 4) - (textlen >> 1), 0.5, GameStartupInfo.Name, fcolor, bcolor);
|
||||||
|
NetBitmap.Create(StartupBitmap.GetWidth() * Scale, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// DrawNetStatus
|
||||||
|
//
|
||||||
|
// Draws network status into the last line of the startup screen.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStartScreen::DrawNetStatus(int found, int total)
|
||||||
|
{
|
||||||
|
RgbQuad black = { 0, 0, 0, 255 };
|
||||||
|
RgbQuad gray = { 100, 100, 100, 255 };
|
||||||
|
ClearBlock(NetBitmap, black, 0, NetBitmap.GetHeight() - 16, NetBitmap.GetWidth(), 16);
|
||||||
|
DrawString(NetBitmap, 0, 0, NetMessageString, gray, black);
|
||||||
|
char of[10];
|
||||||
|
mysnprintf(of, 10, "%d/%d", found, total);
|
||||||
|
int siz = SizeOfText(of);
|
||||||
|
DrawString(NetBitmap, (NetBitmap.GetWidth() >> 3) - siz, 0, of, gray, black);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// NetInit
|
||||||
|
//
|
||||||
|
// sets network status message
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FStartScreen::NetInit(const char* message, int numplayers)
|
||||||
|
{
|
||||||
|
NetMaxPos = numplayers;
|
||||||
|
NetCurPos = 0;
|
||||||
|
NetMessageString.Format("%s %s", message, GStrings("TXT_NET_PRESSESC"));
|
||||||
|
NetProgress(1); // You always know about yourself
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Progress
|
||||||
|
//
|
||||||
|
// advances the progress bar
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FStartScreen::DoProgress(int advance)
|
||||||
|
{
|
||||||
|
CurPos = min(CurPos + advance, MaxPos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FStartScreen::DoNetProgress(int count)
|
||||||
|
{
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
NetCurPos++;
|
||||||
|
}
|
||||||
|
else if (count > 0)
|
||||||
|
{
|
||||||
|
NetCurPos = count;
|
||||||
|
}
|
||||||
|
NetTexture->CleanHardwareData();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FStartScreen::Progress(int advance)
|
||||||
|
{
|
||||||
|
bool done = DoProgress(advance);
|
||||||
|
Render();
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FStartScreen::NetProgress(int count)
|
||||||
|
{
|
||||||
|
DoNetProgress(count);
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FStartScreen::Render(bool force)
|
||||||
|
{
|
||||||
|
auto nowtime = I_msTime();
|
||||||
|
// Do not refresh too often. This function gets called a lot more frequently than the screen can update.
|
||||||
|
if (nowtime - screen->FrameTime > 30 || force)
|
||||||
|
{
|
||||||
|
screen->FrameTime = nowtime;
|
||||||
|
screen->BeginFrame();
|
||||||
|
twod->ClearClipRect();
|
||||||
|
I_GetEvent();
|
||||||
|
ValidateTexture();
|
||||||
|
float displaywidth;
|
||||||
|
float displayheight;
|
||||||
|
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||||
|
|
||||||
|
// At this point the shader for untextured rendering has not been loaded yet, so we got to clear the screen by rendering a texture with black color.
|
||||||
|
DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, StartupTexture->GetDisplayWidth(), DTA_VirtualHeightF, StartupTexture->GetDisplayHeight(), DTA_KeepRatio, true, DTA_Color, PalEntry(255,0,0,0), TAG_END);
|
||||||
|
|
||||||
|
if (HeaderTexture)
|
||||||
|
{
|
||||||
|
displaywidth = HeaderTexture->GetDisplayWidth();
|
||||||
|
displayheight = HeaderTexture->GetDisplayHeight() + StartupTexture->GetDisplayHeight();
|
||||||
|
DrawTexture(twod, HeaderTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
|
||||||
|
DrawTexture(twod, StartupTexture, 0, 32, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
|
||||||
|
if (NetMaxPos >= 0) DrawTexture(twod, NetTexture, 0, displayheight - 16, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
displaywidth = StartupTexture->GetDisplayWidth();
|
||||||
|
displayheight = StartupTexture->GetDisplayHeight();
|
||||||
|
DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
twod->End();
|
||||||
|
screen->Update();
|
||||||
|
twod->OnFrameDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FImageSource* CreateStartScreenTexture(FBitmap& srcdata);
|
||||||
|
|
||||||
|
void FStartScreen::ValidateTexture()
|
||||||
|
{
|
||||||
|
if (StartupTexture == nullptr)
|
||||||
|
{
|
||||||
|
auto imgsource = CreateStartScreenTexture(StartupBitmap);
|
||||||
|
StartupTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override);
|
||||||
|
StartupTexture->SetScale(1.f / Scale, 1.f / Scale);
|
||||||
|
}
|
||||||
|
if (HeaderTexture == nullptr && HeaderBitmap.GetWidth() > 0)
|
||||||
|
{
|
||||||
|
auto imgsource = CreateStartScreenTexture(HeaderBitmap);
|
||||||
|
HeaderTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override);
|
||||||
|
}
|
||||||
|
if (NetTexture == nullptr && NetBitmap.GetWidth() > 0)
|
||||||
|
{
|
||||||
|
auto imgsource = CreateStartScreenTexture(NetBitmap);
|
||||||
|
NetTexture = MakeGameTexture(new FImageTexture(imgsource), nullptr, ETextureType::Override);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
104
source/common/startscreen/startscreen.h
Normal file
104
source/common/startscreen/startscreen.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
** st_start.h
|
||||||
|
** Interface for the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
#pragma once
|
||||||
|
** The startup screen interface is based on a mix of Heretic and Hexen.
|
||||||
|
** Actual implementation is system-specific.
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <functional>
|
||||||
|
#include "bitmap.h"
|
||||||
|
|
||||||
|
class FGameTexture;
|
||||||
|
|
||||||
|
struct RgbQuad
|
||||||
|
{
|
||||||
|
uint8_t rgbBlue;
|
||||||
|
uint8_t rgbGreen;
|
||||||
|
uint8_t rgbRed;
|
||||||
|
uint8_t rgbReserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern const RgbQuad TextModePalette[16];
|
||||||
|
|
||||||
|
class FStartScreen
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
int CurPos = 0;
|
||||||
|
int MaxPos;
|
||||||
|
int Scale = 1;
|
||||||
|
int NetMaxPos = -1;
|
||||||
|
int NetCurPos = 0;
|
||||||
|
FBitmap StartupBitmap;
|
||||||
|
FBitmap HeaderBitmap;
|
||||||
|
FBitmap NetBitmap;
|
||||||
|
FString NetMessageString;
|
||||||
|
FGameTexture* StartupTexture = nullptr;
|
||||||
|
FGameTexture* HeaderTexture = nullptr;
|
||||||
|
FGameTexture* NetTexture = nullptr;
|
||||||
|
public:
|
||||||
|
FStartScreen(int maxp) { MaxPos = maxp; }
|
||||||
|
virtual ~FStartScreen() = default;
|
||||||
|
void Render(bool force = false);
|
||||||
|
bool Progress(int);
|
||||||
|
void NetProgress(int count);
|
||||||
|
virtual void LoadingStatus(const char *message, int colors) {}
|
||||||
|
virtual void AppendStatusLine(const char *status) {}
|
||||||
|
virtual bool NetInit(const char* message, int numplayers);
|
||||||
|
virtual void NetDone() {}
|
||||||
|
virtual void NetTick() {}
|
||||||
|
FBitmap& GetBitmap() { return StartupBitmap; }
|
||||||
|
int GetScale() const { return Scale; }
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ClearBlock(FBitmap& bitmap_info, RgbQuad fill, int x, int y, int bytewidth, int height);
|
||||||
|
FBitmap AllocTextBitmap();
|
||||||
|
void DrawTextScreen(FBitmap& bitmap_info, const uint8_t* text_screen);
|
||||||
|
int DrawChar(FBitmap& screen, double x, double y, unsigned charnum, uint8_t attrib);
|
||||||
|
int DrawChar(FBitmap& screen, double x, double y, unsigned charnum, RgbQuad fg, RgbQuad bg);
|
||||||
|
int DrawString(FBitmap& screen, double x, double y, const char* text, RgbQuad fg, RgbQuad bg);
|
||||||
|
void UpdateTextBlink(FBitmap& bitmap_info, const uint8_t* text_screen, bool on);
|
||||||
|
void ST_Sound(const char* sndname);
|
||||||
|
int SizeOfText(const char* text);
|
||||||
|
void CreateHeader();
|
||||||
|
void DrawNetStatus(int found, int total);
|
||||||
|
void ValidateTexture();
|
||||||
|
virtual bool DoProgress(int);
|
||||||
|
virtual void DoNetProgress(int count);
|
||||||
|
};
|
||||||
|
|
||||||
|
FStartScreen* GetGameStartScreen(int max_progress);
|
||||||
|
|
||||||
|
extern void ST_Endoom();
|
127
source/common/startscreen/startscreen_generic.cpp
Normal file
127
source/common/startscreen/startscreen_generic.cpp
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
** st_start.cpp
|
||||||
|
** Generic startup screen
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "texturemanager.h"
|
||||||
|
|
||||||
|
// Hexen startup screen
|
||||||
|
#define ST_PROGRESS_X 64 // Start of notches x screen pos.
|
||||||
|
#define ST_PROGRESS_Y 441 // Start of notches y screen pos.
|
||||||
|
|
||||||
|
|
||||||
|
class FGenericStartScreen : public FStartScreen
|
||||||
|
{
|
||||||
|
FBitmap Background;
|
||||||
|
int NotchPos = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FGenericStartScreen(int max_progress);
|
||||||
|
|
||||||
|
bool DoProgress(int) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FGenericStartScreen Constructor
|
||||||
|
//
|
||||||
|
// Shows the Hexen startup screen. If the screen doesn't appear to be
|
||||||
|
// valid, it sets hr for a failure.
|
||||||
|
//
|
||||||
|
// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a
|
||||||
|
// 16 entry (48 byte) VGA palette.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FGenericStartScreen::FGenericStartScreen(int max_progress)
|
||||||
|
: FStartScreen(max_progress)
|
||||||
|
{
|
||||||
|
// at this point we do not have a working texture manager yet, so we have to do the lookup via the file system
|
||||||
|
int startup_lump = fileSystem.CheckNumForName("GZDOOM", ns_graphics);
|
||||||
|
|
||||||
|
StartupBitmap.Create(640, 480);
|
||||||
|
ClearBlock(StartupBitmap, { 0, 0, 0, 255 }, 0, 0, 640, 480);
|
||||||
|
// This also needs to work if the lump turns out to be unusable.
|
||||||
|
if (startup_lump != -1)
|
||||||
|
{
|
||||||
|
auto iBackground = FImageSource::GetImage(startup_lump, false);
|
||||||
|
if (iBackground)
|
||||||
|
{
|
||||||
|
Background = iBackground->GetCachedBitmap(nullptr, FImageSource::normal);
|
||||||
|
if (Background.GetWidth() < 640 || Background.GetHeight() < 480)
|
||||||
|
StartupBitmap.Blit(320 - Background.GetWidth()/2, 220 - Background.GetHeight() /2, Background);
|
||||||
|
else
|
||||||
|
StartupBitmap.Blit(0, 0, Background, 640, 480);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CreateHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FGenericStartScreen :: Progress
|
||||||
|
//
|
||||||
|
// Bumps the progress meter one notch.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FGenericStartScreen::DoProgress(int advance)
|
||||||
|
{
|
||||||
|
int notch_pos;
|
||||||
|
|
||||||
|
if (CurPos < MaxPos)
|
||||||
|
{
|
||||||
|
RgbQuad bcolor = { 128, 0, 0, 255 }; // todo: make configurable
|
||||||
|
int numnotches = 512;
|
||||||
|
notch_pos = ((CurPos + 1) * 512) / MaxPos;
|
||||||
|
if (notch_pos != NotchPos)
|
||||||
|
{ // Time to draw another notch.
|
||||||
|
ClearBlock(StartupBitmap, bcolor, ST_PROGRESS_X, ST_PROGRESS_Y, notch_pos, 16);
|
||||||
|
NotchPos = notch_pos;
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FStartScreen::DoProgress(advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FStartScreen* CreateGenericStartScreen(int max_progress)
|
||||||
|
{
|
||||||
|
return new FGenericStartScreen(max_progress);
|
||||||
|
}
|
181
source/common/startscreen/startscreen_heretic.cpp
Normal file
181
source/common/startscreen/startscreen_heretic.cpp
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
** st_start.cpp
|
||||||
|
** Handles the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** Copyright 2006-2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "texturemanager.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Heretic startup screen
|
||||||
|
#define HERETIC_MINOR_VERSION '3' // Since we're based on Heretic 1.3
|
||||||
|
#define THERM_X 14
|
||||||
|
#define THERM_Y 14
|
||||||
|
#define THERM_LEN 51
|
||||||
|
#define THERM_COLOR 0xA // light green
|
||||||
|
|
||||||
|
|
||||||
|
class FHereticStartScreen : public FStartScreen
|
||||||
|
{
|
||||||
|
int NotchPos;
|
||||||
|
int ThermX, ThermY, ThermWidth, ThermHeight;
|
||||||
|
int HMsgY, SMsgX;
|
||||||
|
public:
|
||||||
|
FHereticStartScreen(int max_progress);
|
||||||
|
|
||||||
|
bool DoProgress(int) override;
|
||||||
|
void LoadingStatus(const char *message, int colors) override;
|
||||||
|
void AppendStatusLine(const char *status) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHereticStartScreen Constructor
|
||||||
|
//
|
||||||
|
// Shows the Heretic startup screen. If the screen doesn't appear to be
|
||||||
|
// valid, it returns a failure code in hr.
|
||||||
|
//
|
||||||
|
// The loading screen is an 80x25 text screen with character data and
|
||||||
|
// attributes intermixed, which means it must be exactly 4000 bytes long.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FHereticStartScreen::FHereticStartScreen(int max_progress)
|
||||||
|
: FStartScreen(max_progress)
|
||||||
|
{
|
||||||
|
int loading_lump = fileSystem.CheckNumForName("LOADING");
|
||||||
|
uint8_t loading_screen[4000];
|
||||||
|
|
||||||
|
if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000)
|
||||||
|
{
|
||||||
|
I_Error("'LOADING' not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSystem.ReadFile(loading_lump, loading_screen);
|
||||||
|
|
||||||
|
// Slap the Heretic minor version on the loading screen. Heretic
|
||||||
|
// did this inside the executable rather than coming with modified
|
||||||
|
// LOADING screens, so we need to do the same.
|
||||||
|
loading_screen[2 * 160 + 49 * 2] = HERETIC_MINOR_VERSION;
|
||||||
|
|
||||||
|
// Draw the loading screen to a bitmap.
|
||||||
|
StartupBitmap.Create(80 * 8, 25 * 16);
|
||||||
|
DrawTextScreen(StartupBitmap, loading_screen);
|
||||||
|
|
||||||
|
ThermX = THERM_X * 8;
|
||||||
|
ThermY = THERM_Y * 16;
|
||||||
|
ThermWidth = THERM_LEN * 8 - 4;
|
||||||
|
ThermHeight = 16;
|
||||||
|
HMsgY = 7;
|
||||||
|
SMsgX = 1;
|
||||||
|
NotchPos = 0;
|
||||||
|
CreateHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHereticStartScreen::Progress
|
||||||
|
//
|
||||||
|
// Bumps the progress meter one notch.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FHereticStartScreen::DoProgress(int advance)
|
||||||
|
{
|
||||||
|
if (CurPos < MaxPos)
|
||||||
|
{
|
||||||
|
int notch_pos = ((CurPos + 1) * ThermWidth) / MaxPos;
|
||||||
|
if (notch_pos != NotchPos && !(notch_pos & 3))
|
||||||
|
{ // Time to draw another notch.
|
||||||
|
int left = NotchPos + ThermX;
|
||||||
|
int top = ThermY;
|
||||||
|
int right = notch_pos + ThermX;
|
||||||
|
int bottom = top + ThermHeight;
|
||||||
|
ClearBlock(StartupBitmap, TextModePalette[THERM_COLOR], left, top, right - left, bottom - top);
|
||||||
|
NotchPos = notch_pos;
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FStartScreen::DoProgress(advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHereticStartScreen :: LoadingStatus
|
||||||
|
//
|
||||||
|
// Prints text in the center box of the startup screen.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FHereticStartScreen::LoadingStatus(const char* message, int colors)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 0; message[x] != '\0'; ++x)
|
||||||
|
{
|
||||||
|
DrawChar(StartupBitmap, 17 + x, HMsgY, message[x], colors);
|
||||||
|
}
|
||||||
|
HMsgY++;
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHereticStartScreen :: AppendStatusLine
|
||||||
|
//
|
||||||
|
// Appends text to Heretic's status line.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FHereticStartScreen::AppendStatusLine(const char* status)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
for (x = 0; status[x] != '\0'; ++x)
|
||||||
|
{
|
||||||
|
DrawChar(StartupBitmap, SMsgX + x, 24, status[x], 0x1f);
|
||||||
|
}
|
||||||
|
SMsgX += x;
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FStartScreen* CreateHereticStartScreen(int max_progress)
|
||||||
|
{
|
||||||
|
return new FHereticStartScreen(max_progress);
|
||||||
|
}
|
212
source/common/startscreen/startscreen_hexen.cpp
Normal file
212
source/common/startscreen/startscreen_hexen.cpp
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
** st_start.cpp
|
||||||
|
** Handles the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** Copyright 2006-2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "texturemanager.h"
|
||||||
|
|
||||||
|
// Hexen startup screen
|
||||||
|
#define ST_PROGRESS_X 64 // Start of notches x screen pos.
|
||||||
|
#define ST_PROGRESS_Y 441 // Start of notches y screen pos.
|
||||||
|
|
||||||
|
#define ST_NETPROGRESS_X 288
|
||||||
|
#define ST_NETPROGRESS_Y 32
|
||||||
|
|
||||||
|
class FHexenStartScreen : public FStartScreen
|
||||||
|
{
|
||||||
|
// Hexen's notch graphics, converted to chunky pixels.
|
||||||
|
FBitmap Background;
|
||||||
|
FBitmap NotchBits;
|
||||||
|
FBitmap NetNotchBits;
|
||||||
|
int NotchPos = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FHexenStartScreen(int max_progress);
|
||||||
|
|
||||||
|
bool DoProgress(int) override;
|
||||||
|
void DoNetProgress(int count) override;
|
||||||
|
void NetDone() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHexenStartScreen Constructor
|
||||||
|
//
|
||||||
|
// Shows the Hexen startup screen. If the screen doesn't appear to be
|
||||||
|
// valid, it sets hr for a failure.
|
||||||
|
//
|
||||||
|
// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a
|
||||||
|
// 16 entry (48 byte) VGA palette.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FHexenStartScreen::FHexenStartScreen(int max_progress)
|
||||||
|
: FStartScreen(max_progress)
|
||||||
|
{
|
||||||
|
// at this point we do not have a working texture manager yet, so we have to do the lookup via the file system
|
||||||
|
int startup_lump = fileSystem.CheckNumForName("STARTUP", ns_graphics);
|
||||||
|
int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH", ns_graphics);
|
||||||
|
int notch_lump = fileSystem.CheckNumForName("NOTCH", ns_graphics);
|
||||||
|
|
||||||
|
// For backwards compatibility we also need to look in the default namespace, because these were previously not handled as graphics.
|
||||||
|
if (startup_lump == -1) startup_lump = fileSystem.CheckNumForName("STARTUP");
|
||||||
|
if (netnotch_lump == -1)netnotch_lump = fileSystem.CheckNumForName("NETNOTCH");
|
||||||
|
if (notch_lump == -1)notch_lump = fileSystem.CheckNumForName("NOTCH");
|
||||||
|
|
||||||
|
|
||||||
|
if (startup_lump < 0 || netnotch_lump < 0 || notch_lump < 0)
|
||||||
|
{
|
||||||
|
I_Error("Start screen assets missing");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iBackground = FImageSource::GetImage(startup_lump, false);
|
||||||
|
auto iNetNotchBits = FImageSource::GetImage(netnotch_lump, false);
|
||||||
|
auto iNotchBits = FImageSource::GetImage(notch_lump, false);
|
||||||
|
if (!iBackground || !iNetNotchBits || !iNotchBits || iBackground->GetWidth() != 640 || iBackground->GetHeight() != 480)
|
||||||
|
{
|
||||||
|
I_Error("Start screen assets missing");
|
||||||
|
}
|
||||||
|
NetNotchBits = iNetNotchBits->GetCachedBitmap(nullptr, FImageSource::normal);
|
||||||
|
NotchBits = iNotchBits->GetCachedBitmap(nullptr, FImageSource::normal);
|
||||||
|
Background = iBackground->GetCachedBitmap(nullptr, FImageSource::normal);
|
||||||
|
|
||||||
|
StartupBitmap.Create(640, 480);
|
||||||
|
StartupBitmap.Blit(0, 0, Background, 640, 480);
|
||||||
|
|
||||||
|
// Fill in the bitmap data. Convert to chunky, because I can't figure out
|
||||||
|
// if Windows actually supports planar images or not, despite the presence
|
||||||
|
// of biPlanes in the BITMAPINFOHEADER.
|
||||||
|
|
||||||
|
|
||||||
|
if (!batchrun)
|
||||||
|
{
|
||||||
|
if (GameStartupInfo.Song.IsNotEmpty())
|
||||||
|
{
|
||||||
|
S_ChangeMusic(GameStartupInfo.Song.GetChars(), true, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_ChangeMusic("orb", true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CreateHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHexenStartScreen :: Progress
|
||||||
|
//
|
||||||
|
// Bumps the progress meter one notch.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FHexenStartScreen::DoProgress(int advance)
|
||||||
|
{
|
||||||
|
int notch_pos, x, y;
|
||||||
|
|
||||||
|
if (CurPos < MaxPos)
|
||||||
|
{
|
||||||
|
int numnotches = (16 * 32) / NotchBits.GetWidth();
|
||||||
|
notch_pos = ((CurPos + 1) * numnotches) / MaxPos;
|
||||||
|
if (notch_pos != NotchPos)
|
||||||
|
{ // Time to draw another notch.
|
||||||
|
for (; NotchPos < notch_pos; NotchPos++)
|
||||||
|
{
|
||||||
|
x = ST_PROGRESS_X + NotchBits.GetWidth() * NotchPos;
|
||||||
|
y = ST_PROGRESS_Y;
|
||||||
|
StartupBitmap.Blit(x, y, NotchBits);
|
||||||
|
}
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
ST_Sound("StartupTick");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FStartScreen::DoProgress(advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHexenStartScreen :: NetProgress
|
||||||
|
//
|
||||||
|
// Draws the red net noches in addition to the normal progress bar.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FHexenStartScreen::DoNetProgress(int count)
|
||||||
|
{
|
||||||
|
int oldpos = NetCurPos;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
FStartScreen::NetProgress(count);
|
||||||
|
|
||||||
|
if (NetMaxPos != 0 && NetCurPos > oldpos)
|
||||||
|
{
|
||||||
|
int numnotches = (4 * 8) / NetNotchBits.GetWidth();
|
||||||
|
int notch_pos = (NetCurPos * numnotches) / NetMaxPos;
|
||||||
|
|
||||||
|
for (; oldpos < NetCurPos && oldpos < numnotches; ++oldpos)
|
||||||
|
{
|
||||||
|
x = ST_NETPROGRESS_X + NetNotchBits.GetWidth() * oldpos;
|
||||||
|
y = ST_NETPROGRESS_Y;
|
||||||
|
StartupBitmap.Blit(x, y, NetNotchBits);
|
||||||
|
}
|
||||||
|
ST_Sound("misc/netnotch");
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FHexenStartScreen :: NetDone
|
||||||
|
//
|
||||||
|
// Aside from the standard processing, also plays a sound.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FHexenStartScreen::NetDone()
|
||||||
|
{
|
||||||
|
ST_Sound("PickupWeapon");
|
||||||
|
FStartScreen::NetDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FStartScreen* CreateHexenStartScreen(int max_progress)
|
||||||
|
{
|
||||||
|
return new FHexenStartScreen(max_progress);
|
||||||
|
}
|
202
source/common/startscreen/startscreen_strife.cpp
Normal file
202
source/common/startscreen/startscreen_strife.cpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
** st_start.cpp
|
||||||
|
** Handles the startup screen.
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2006-2007 Randy Heit
|
||||||
|
** Copyright 2006-2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "startscreen.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "textures.h"
|
||||||
|
#include "palettecontainer.h"
|
||||||
|
|
||||||
|
// Strife startup screen
|
||||||
|
#define PEASANT_INDEX 0
|
||||||
|
#define LASER_INDEX 4
|
||||||
|
#define BOT_INDEX 6
|
||||||
|
|
||||||
|
#define ST_LASERSPACE_X 60
|
||||||
|
#define ST_LASERSPACE_Y 156
|
||||||
|
#define ST_LASERSPACE_WIDTH 200
|
||||||
|
#define ST_LASER_WIDTH 16
|
||||||
|
#define ST_LASER_HEIGHT 16
|
||||||
|
|
||||||
|
#define ST_BOT_X 14
|
||||||
|
#define ST_BOT_Y 138
|
||||||
|
#define ST_BOT_WIDTH 48
|
||||||
|
#define ST_BOT_HEIGHT 48
|
||||||
|
|
||||||
|
#define ST_PEASANT_X 262
|
||||||
|
#define ST_PEASANT_Y 136
|
||||||
|
#define ST_PEASANT_WIDTH 32
|
||||||
|
#define ST_PEASANT_HEIGHT 64
|
||||||
|
|
||||||
|
static const char* StrifeStartupPicNames[] =
|
||||||
|
{
|
||||||
|
"STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1",
|
||||||
|
"STRTLZ1", "STRTLZ2",
|
||||||
|
"STRTBOT",
|
||||||
|
"STARTUP0"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FStrifeStartScreen : public FStartScreen
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FStrifeStartScreen(int max_progress);
|
||||||
|
|
||||||
|
bool DoProgress(int) override;
|
||||||
|
protected:
|
||||||
|
void DrawStuff(int old_laser, int new_laser);
|
||||||
|
|
||||||
|
FBitmap StartupPics[4+2+1+1];
|
||||||
|
int NotchPos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FStrifeStartScreen Constructor
|
||||||
|
//
|
||||||
|
// Shows the Strife startup screen. If the screen doesn't appear to be
|
||||||
|
// valid, it returns a failure code in hr.
|
||||||
|
//
|
||||||
|
// The startup background is a raw 320x200 image, however Strife only
|
||||||
|
// actually uses 95 rows from it, starting at row 57. The rest of the image
|
||||||
|
// is discarded. (What a shame.)
|
||||||
|
//
|
||||||
|
// The peasants are raw 32x64 images. The laser dots are raw 16x16 images.
|
||||||
|
// The bot is a raw 48x48 image. All use the standard PLAYPAL.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FStrifeStartScreen::FStrifeStartScreen(int max_progress)
|
||||||
|
: FStartScreen(max_progress)
|
||||||
|
{
|
||||||
|
// at this point we do not have a working texture manager yet, so we have to do the lookup via the file system
|
||||||
|
|
||||||
|
int startup_lump = fileSystem.CheckNumForName("STARTUP0");
|
||||||
|
|
||||||
|
if (startup_lump < 0)
|
||||||
|
{
|
||||||
|
I_Error("bad startscreen assets");
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupBitmap.Create(320, 200);
|
||||||
|
|
||||||
|
// Load the animated overlays.
|
||||||
|
for (size_t i = 0; i < countof(StrifeStartupPicNames); ++i)
|
||||||
|
{
|
||||||
|
int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i], ns_graphics);
|
||||||
|
if (lumpnum < 0) lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]);
|
||||||
|
|
||||||
|
if (lumpnum >= 0)
|
||||||
|
{
|
||||||
|
auto lumpr1 = FImageSource::GetImage(lumpnum, false);
|
||||||
|
if (lumpr1) StartupPics[i] = lumpr1->GetCachedBitmap(nullptr, FImageSource::normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StartupPics[7].GetWidth() != 320 || StartupPics[7].GetHeight() != 200)
|
||||||
|
{
|
||||||
|
I_Error("bad startscreen assets");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the startup image appear.
|
||||||
|
DrawStuff(0, 0);
|
||||||
|
Scale = 2;
|
||||||
|
CreateHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FStrifeStartScreen :: Progress
|
||||||
|
//
|
||||||
|
// Bumps the progress meter one notch.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FStrifeStartScreen::DoProgress(int advance)
|
||||||
|
{
|
||||||
|
int notch_pos;
|
||||||
|
|
||||||
|
if (CurPos < MaxPos)
|
||||||
|
{
|
||||||
|
notch_pos = ((CurPos + 1) * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos;
|
||||||
|
if (notch_pos != NotchPos && !(notch_pos & 1))
|
||||||
|
{ // Time to update.
|
||||||
|
DrawStuff(NotchPos, notch_pos);
|
||||||
|
NotchPos = notch_pos;
|
||||||
|
StartupTexture->CleanHardwareData(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FStartScreen::DoProgress(advance);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// FStrifeStartScreen :: DrawStuff
|
||||||
|
//
|
||||||
|
// Draws all the moving parts of Strife's startup screen. If you're
|
||||||
|
// running off a slow drive, it can look kind of good. Otherwise, it
|
||||||
|
// borders on crazy insane fast.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void FStrifeStartScreen::DrawStuff(int old_laser, int new_laser)
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
|
||||||
|
// Clear old laser
|
||||||
|
StartupBitmap.Blit(0, 0, StartupPics[7]);
|
||||||
|
|
||||||
|
// Draw new laser
|
||||||
|
auto& lp = StartupPics[LASER_INDEX + (new_laser & 1)];
|
||||||
|
StartupBitmap.Blit(ST_LASERSPACE_X + new_laser, ST_LASERSPACE_Y, lp);
|
||||||
|
|
||||||
|
// The bot jumps up and down like crazy.
|
||||||
|
y = max(0, (new_laser >> 1) % 5 - 2);
|
||||||
|
|
||||||
|
StartupBitmap.Blit(ST_BOT_X, ST_BOT_Y + y, StartupPics[BOT_INDEX]);
|
||||||
|
|
||||||
|
// The peasant desperately runs in place, trying to get away from the laser.
|
||||||
|
// Yet, despite all his limb flailing, he never manages to get anywhere.
|
||||||
|
auto& pp = StartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)];
|
||||||
|
StartupBitmap.Blit(ST_PEASANT_X, ST_PEASANT_Y, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FStartScreen* CreateStrifeStartScreen(int max_progress)
|
||||||
|
{
|
||||||
|
return new FStrifeStartScreen(max_progress);
|
||||||
|
}
|
|
@ -59,9 +59,9 @@ CVAR(Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE);
|
||||||
CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE);
|
CVAR(Int, crosshairhealth, 2, CVAR_ARCHIVE);
|
||||||
CVARD(Float, crosshairscale, 0.5, CVAR_ARCHIVE, "changes the size of the crosshair");
|
CVARD(Float, crosshairscale, 0.5, CVAR_ARCHIVE, "changes the size of the crosshair");
|
||||||
CVAR(Bool, crosshairgrow, false, CVAR_ARCHIVE);
|
CVAR(Bool, crosshairgrow, false, CVAR_ARCHIVE);
|
||||||
EXTERN_CVAR(Bool, vid_fps)
|
|
||||||
|
|
||||||
EXTERN_CVAR(Float, hud_scalefactor)
|
EXTERN_CVAR(Float, hud_scalefactor)
|
||||||
|
EXTERN_CVAR(Bool, hud_aspectscale)
|
||||||
|
|
||||||
void ST_LoadCrosshair(int num, bool alwaysload)
|
void ST_LoadCrosshair(int num, bool alwaysload)
|
||||||
{
|
{
|
||||||
|
@ -353,10 +353,12 @@ void DStatusBarCore::SetScale()
|
||||||
int vert = VerticalResolution;
|
int vert = VerticalResolution;
|
||||||
double refaspect = horz / double(vert);
|
double refaspect = horz / double(vert);
|
||||||
double screenaspect = w / double(h);
|
double screenaspect = w / double(h);
|
||||||
|
double aspectscale = 1.0;
|
||||||
|
|
||||||
if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400))
|
if ((horz == 320 && vert == 200) || (horz == 640 && vert == 400))
|
||||||
{
|
{
|
||||||
refaspect = 1.333;
|
refaspect = 1.333;
|
||||||
|
if (!hud_aspectscale) aspectscale = 1 / 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (screenaspect < refaspect)
|
if (screenaspect < refaspect)
|
||||||
|
@ -370,14 +372,14 @@ void DStatusBarCore::SetScale()
|
||||||
refw = h * refaspect;
|
refw = h * refaspect;
|
||||||
}
|
}
|
||||||
refw *= hud_scalefactor;
|
refw *= hud_scalefactor;
|
||||||
refh *= hud_scalefactor;
|
refh *= hud_scalefactor * aspectscale;
|
||||||
|
|
||||||
int sby = VerticalResolution - RelTop;
|
int sby = vert - int(RelTop * hud_scalefactor * aspectscale);
|
||||||
// Use full pixels for destination size.
|
// Use full pixels for destination size.
|
||||||
|
|
||||||
ST_X = xs_CRoundToInt((w - refw) / 2);
|
ST_X = xs_CRoundToInt((w - refw) / 2);
|
||||||
ST_Y = xs_CRoundToInt(h - refh);
|
ST_Y = xs_CRoundToInt(h - refh);
|
||||||
SBarTop = Scale(sby, h, VerticalResolution);
|
SBarTop = Scale(sby, h, vert);
|
||||||
SBarScale.X = refw / horz;
|
SBarScale.X = refw / horz;
|
||||||
SBarScale.Y = refh / vert;
|
SBarScale.Y = refh / vert;
|
||||||
}
|
}
|
||||||
|
@ -565,9 +567,6 @@ void DStatusBarCore::DrawGraphic(FGameTexture* tex, double x, double y, int flag
|
||||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
|
||||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
|
||||||
|
|
||||||
DVector2 Scale = GetHUDScale();
|
DVector2 Scale = GetHUDScale();
|
||||||
|
|
||||||
x *= Scale.X;
|
x *= Scale.X;
|
||||||
|
@ -659,9 +658,6 @@ void DStatusBarCore::DrawRotated(FGameTexture* tex, double x, double y, int flag
|
||||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
|
||||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
|
||||||
|
|
||||||
x *= Scale.X;
|
x *= Scale.X;
|
||||||
y *= Scale.Y;
|
y *= Scale.Y;
|
||||||
scaleX *= Scale.X;
|
scaleX *= Scale.X;
|
||||||
|
@ -739,9 +735,6 @@ void DStatusBarCore::DrawString(FFont* font, const FString& cstring, double x, d
|
||||||
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
case DI_SCREEN_VCENTER: orgy = twod->GetHeight() / 2; break;
|
||||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
|
||||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -904,9 +897,6 @@ void DStatusBarCore::TransformRect(double& x, double& y, double& w, double& h, i
|
||||||
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
case DI_SCREEN_BOTTOM: orgy = twod->GetHeight(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// move stuff in the top right corner a bit down if the fps counter is on.
|
|
||||||
if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10;
|
|
||||||
|
|
||||||
DVector2 Scale = GetHUDScale();
|
DVector2 Scale = GetHUDScale();
|
||||||
|
|
||||||
x *= Scale.X;
|
x *= Scale.X;
|
||||||
|
|
|
@ -209,13 +209,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step,
|
||||||
iCopyColors<cIA, cBGRA, op>, \
|
iCopyColors<cIA, cBGRA, op>, \
|
||||||
iCopyColors<cCMYK, cBGRA, op>, \
|
iCopyColors<cCMYK, cBGRA, op>, \
|
||||||
iCopyColors<cYCbCr, cBGRA, op>, \
|
iCopyColors<cYCbCr, cBGRA, op>, \
|
||||||
|
iCopyColors<cYCCK, cBGRA, op>, \
|
||||||
iCopyColors<cBGR, cBGRA, op>, \
|
iCopyColors<cBGR, cBGRA, op>, \
|
||||||
iCopyColors<cBGRA, cBGRA, op>, \
|
iCopyColors<cBGRA, cBGRA, op>, \
|
||||||
iCopyColors<cI16, cBGRA, op>, \
|
iCopyColors<cI16, cBGRA, op>, \
|
||||||
iCopyColors<cRGB555, cBGRA, op>, \
|
iCopyColors<cRGB555, cBGRA, op>, \
|
||||||
iCopyColors<cPalEntry, cBGRA, op> \
|
iCopyColors<cPalEntry, cBGRA, op> \
|
||||||
}
|
}
|
||||||
static const CopyFunc copyfuncs[][11]={
|
static const CopyFunc copyfuncs[][12]={
|
||||||
COPY_FUNCS(bCopy),
|
COPY_FUNCS(bCopy),
|
||||||
COPY_FUNCS(bBlend),
|
COPY_FUNCS(bBlend),
|
||||||
COPY_FUNCS(bAdd),
|
COPY_FUNCS(bAdd),
|
||||||
|
@ -402,7 +403,6 @@ void FBitmap::CopyPixelDataRGB(int originx, int originy, const uint8_t *patch, i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class TDest, class TBlend>
|
template<class TDest, class TBlend>
|
||||||
void iCopyPaletted(uint8_t *buffer, const uint8_t * patch, int srcwidth, int srcheight, int Pitch,
|
void iCopyPaletted(uint8_t *buffer, const uint8_t * patch, int srcwidth, int srcheight, int Pitch,
|
||||||
int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf)
|
int step_x, int step_y, int rotate, const PalEntry * palette, FCopyInfo *inf)
|
||||||
|
|
|
@ -65,6 +65,7 @@ enum ColorType
|
||||||
CF_IA,
|
CF_IA,
|
||||||
CF_CMYK,
|
CF_CMYK,
|
||||||
CF_YCbCr,
|
CF_YCbCr,
|
||||||
|
CF_YCCK,
|
||||||
CF_BGR,
|
CF_BGR,
|
||||||
CF_BGRA,
|
CF_BGRA,
|
||||||
CF_I16,
|
CF_I16,
|
||||||
|
@ -326,6 +327,15 @@ struct cYCbCr
|
||||||
static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
|
static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct cYCCK
|
||||||
|
{
|
||||||
|
static __forceinline unsigned char R(const unsigned char* p) { auto myR = cYCbCr::R(p); return p[3] - ((myR * p[3]) >> 8); }
|
||||||
|
static __forceinline unsigned char G(const unsigned char* p) { auto myG = cYCbCr::G(p); return p[3] - ((myG * p[3]) >> 8); }
|
||||||
|
static __forceinline unsigned char B(const unsigned char* p) { auto myB = cYCbCr::B(p); return p[3] - ((myB * p[3]) >> 8); }
|
||||||
|
static __forceinline unsigned char A(const unsigned char* p, uint8_t x, uint8_t y, uint8_t z) { return 255; }
|
||||||
|
static __forceinline int Gray(const unsigned char* p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; }
|
||||||
|
};
|
||||||
|
|
||||||
struct cBGR
|
struct cBGR
|
||||||
{
|
{
|
||||||
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }
|
static __forceinline unsigned char R(const unsigned char * p) { return p[2]; }
|
||||||
|
|
|
@ -282,6 +282,7 @@ TArray<uint8_t> FJPEGTexture::CreatePalettedPixels(int conversion)
|
||||||
jpeg_read_header(&cinfo, TRUE);
|
jpeg_read_header(&cinfo, TRUE);
|
||||||
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
|
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
|
||||||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
|
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
|
||||||
|
(cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) ||
|
||||||
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
|
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
|
||||||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
|
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
|
||||||
{
|
{
|
||||||
|
@ -350,6 +351,24 @@ TArray<uint8_t> FJPEGTexture::CreatePalettedPixels(int conversion)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JCS_YCCK:
|
||||||
|
// Probably useless but since I had the formula available...
|
||||||
|
for (int x = Width; x > 0; --x)
|
||||||
|
{
|
||||||
|
double Y = in[0], Cb = in[1], Cr = in[2];
|
||||||
|
int K = in[3];
|
||||||
|
int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255);
|
||||||
|
int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255);
|
||||||
|
int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255);
|
||||||
|
r = r - ((r * K) >> 8);
|
||||||
|
g = g - ((g * K) >> 8);
|
||||||
|
b = b - ((b * K) >> 8);
|
||||||
|
*out = ImageHelpers::RGBToPalette(doalpha, r, g, b);
|
||||||
|
out += Height;
|
||||||
|
in += 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// The other colorspaces were considered above and discarded,
|
// The other colorspaces were considered above and discarded,
|
||||||
// but GCC will complain without a default for them here.
|
// but GCC will complain without a default for them here.
|
||||||
|
@ -402,6 +421,7 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion)
|
||||||
|
|
||||||
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
|
if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) ||
|
||||||
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
|
(cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) ||
|
||||||
|
(cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) ||
|
||||||
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
|
(cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) ||
|
||||||
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
|
(cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1)))
|
||||||
{
|
{
|
||||||
|
@ -439,6 +459,11 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion)
|
||||||
4, cinfo.output_width * cinfo.output_components, 0, CF_CMYK);
|
4, cinfo.output_width * cinfo.output_components, 0, CF_CMYK);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JCS_YCCK:
|
||||||
|
bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height,
|
||||||
|
4, cinfo.output_width * cinfo.output_components, 0, CF_YCCK);
|
||||||
|
break;
|
||||||
|
|
||||||
case JCS_YCbCr:
|
case JCS_YCbCr:
|
||||||
bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height,
|
bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height,
|
||||||
4, cinfo.output_width * cinfo.output_components, 0, CF_YCbCr);
|
4, cinfo.output_width * cinfo.output_components, 0, CF_YCbCr);
|
||||||
|
|
|
@ -62,9 +62,9 @@ public:
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static bool CheckIfRaw(FileReader & data)
|
bool CheckIfRaw(FileReader & data, int desiredsize)
|
||||||
{
|
{
|
||||||
if (data.GetLength() != 64000) return false;
|
if (data.GetLength() != desiredsize) return false;
|
||||||
|
|
||||||
// This is probably a raw page graphic, but do some checking to be sure
|
// This is probably a raw page graphic, but do some checking to be sure
|
||||||
patch_t *foo;
|
patch_t *foo;
|
||||||
|
@ -136,7 +136,7 @@ static bool CheckIfRaw(FileReader & data)
|
||||||
|
|
||||||
FImageSource *RawPageImage_TryCreate(FileReader & file, int lumpnum)
|
FImageSource *RawPageImage_TryCreate(FileReader & file, int lumpnum)
|
||||||
{
|
{
|
||||||
if (!CheckIfRaw(file)) return nullptr;
|
if (!CheckIfRaw(file, 64000)) return nullptr;
|
||||||
return new FRawPageTexture(lumpnum);
|
return new FRawPageTexture(lumpnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
82
source/common/textures/formats/startscreentexture.cpp
Normal file
82
source/common/textures/formats/startscreentexture.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
** startscreentexture.cpp
|
||||||
|
** Texture class to create a texture from the start screen's imagé
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2004-2006 Randy Heit
|
||||||
|
** Copyright 2019 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "files.h"
|
||||||
|
#include "gi.h"
|
||||||
|
#include "bitmap.h"
|
||||||
|
#include "textures.h"
|
||||||
|
#include "imagehelpers.h"
|
||||||
|
#include "image.h"
|
||||||
|
#include "startscreen.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FStartScreenTexture : public FImageSource
|
||||||
|
{
|
||||||
|
FBitmap& info; // This must remain constant for the lifetime of this texture
|
||||||
|
|
||||||
|
public:
|
||||||
|
FStartScreenTexture(FBitmap& srcdata)
|
||||||
|
: FImageSource(-1), info(srcdata)
|
||||||
|
{
|
||||||
|
Width = srcdata.GetWidth();
|
||||||
|
Height = srcdata.GetHeight();
|
||||||
|
bUseGamePalette = false;
|
||||||
|
}
|
||||||
|
int CopyPixels(FBitmap* bmp, int conversion)
|
||||||
|
{
|
||||||
|
bmp->Blit(0, 0, info);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FImageSource *CreateStartScreenTexture(FBitmap& srcdata)
|
||||||
|
{
|
||||||
|
return new FStartScreenTexture(srcdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
381
source/common/textures/formats/startuptexture.cpp
Normal file
381
source/common/textures/formats/startuptexture.cpp
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
** startuptexture.cpp
|
||||||
|
** Texture class for Hexen's startup screen
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
** Copyright 2022 Christoph Oelckers
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "files.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "bitmap.h"
|
||||||
|
#include "imagehelpers.h"
|
||||||
|
#include "image.h"
|
||||||
|
|
||||||
|
#define ST_NOTCH_WIDTH 16
|
||||||
|
#define ST_NOTCH_HEIGHT 23
|
||||||
|
|
||||||
|
#define ST_NETNOTCH_WIDTH 4
|
||||||
|
#define ST_NETNOTCH_HEIGHT 16
|
||||||
|
|
||||||
|
struct StrifeStartupInfo
|
||||||
|
{
|
||||||
|
char name[9];
|
||||||
|
uint8_t width, height;
|
||||||
|
};
|
||||||
|
|
||||||
|
static StrifeStartupInfo StrifeRawPics[] =
|
||||||
|
{
|
||||||
|
{ "STRTPA1", 32, 64},
|
||||||
|
{ "STRTPB1", 32, 64},
|
||||||
|
{ "STRTPC1", 32, 64},
|
||||||
|
{ "STRTPD1", 32, 64},
|
||||||
|
{ "STRTLZ1", 16, 16},
|
||||||
|
{ "STRTLZ2", 16, 16},
|
||||||
|
{ "STRTBOT", 48, 48}
|
||||||
|
};
|
||||||
|
|
||||||
|
// there is only one palette for all these images.
|
||||||
|
static uint8_t startuppalette8[16];
|
||||||
|
static uint32_t startuppalette32[16];
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FStartupTexture : public FImageSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FStartupTexture (int lumpnum);
|
||||||
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||||
|
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FNotchTexture : public FImageSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FNotchTexture (int lumpnum, int width, int height);
|
||||||
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||||
|
int CopyPixels(FBitmap *bmp, int conversion) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FStrifeStartupTexture : public FImageSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FStrifeStartupTexture (int lumpnum, int w, int h);
|
||||||
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FStrifeStartupBackground : public FImageSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FStrifeStartupBackground (int lumpnum);
|
||||||
|
TArray<uint8_t> CreatePalettedPixels(int conversion) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Use the same function as raw textures to eliminate Doom patches
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool CheckIfRaw(FileReader & data, int desiredsize);
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// loads all raw images for Hexen's and Strife's startup screens
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FImageSource *StartupPageImage_TryCreate(FileReader & file, int lumpnum)
|
||||||
|
{
|
||||||
|
if (fileSystem.CheckFileName(lumpnum, "STARTUP"))
|
||||||
|
{
|
||||||
|
if (!CheckIfRaw(file, 153648)) return nullptr;
|
||||||
|
return new FStartupTexture(lumpnum);
|
||||||
|
}
|
||||||
|
if (fileSystem.CheckFileName(lumpnum, "NOTCH"))
|
||||||
|
{
|
||||||
|
if (!CheckIfRaw(file, ST_NOTCH_WIDTH * ST_NOTCH_HEIGHT / 2)) return nullptr;
|
||||||
|
return new FNotchTexture(lumpnum, ST_NOTCH_WIDTH, ST_NOTCH_HEIGHT);
|
||||||
|
}
|
||||||
|
if (fileSystem.CheckFileName(lumpnum, "NETNOTCH"))
|
||||||
|
{
|
||||||
|
if (!CheckIfRaw(file, ST_NETNOTCH_WIDTH * ST_NETNOTCH_HEIGHT / 2)) return nullptr;
|
||||||
|
return new FNotchTexture(lumpnum, ST_NETNOTCH_WIDTH, ST_NETNOTCH_HEIGHT);
|
||||||
|
}
|
||||||
|
if (fileSystem.CheckFileName(lumpnum, "STARTUP0"))
|
||||||
|
{
|
||||||
|
if (!CheckIfRaw(file, 64000)) return nullptr;
|
||||||
|
return new FStrifeStartupBackground(lumpnum);
|
||||||
|
}
|
||||||
|
for(auto& sst : StrifeRawPics)
|
||||||
|
{
|
||||||
|
if (fileSystem.CheckFileName(lumpnum, sst.name))
|
||||||
|
{
|
||||||
|
if (!CheckIfRaw(file, sst.width * sst.height)) return nullptr;
|
||||||
|
return new FStrifeStartupTexture(lumpnum, sst.width, sst.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FStartupTexture::FStartupTexture (int lumpnum)
|
||||||
|
: FImageSource(lumpnum)
|
||||||
|
{
|
||||||
|
Width = 640;
|
||||||
|
Height = 480;
|
||||||
|
bUseGamePalette = false;
|
||||||
|
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
|
||||||
|
// Initialize the bitmap palette.
|
||||||
|
// the palette is static so that the notches can share it.
|
||||||
|
// Note that if the STARTUP image gets replaced, the notches will be all black unless they get replaced as well!
|
||||||
|
for (int i = 0; i < 16; ++i)
|
||||||
|
{
|
||||||
|
PalEntry pe;
|
||||||
|
pe.r = source[i * 3 + 0];
|
||||||
|
pe.g = source[i * 3 + 1];
|
||||||
|
pe.b = source[i * 3 + 2];
|
||||||
|
pe.a = 63;
|
||||||
|
// Convert from 6-bit per component to 8-bit per component.
|
||||||
|
pe.d= (pe.d << 2) | ((pe.d >> 4) & 0x03030303);
|
||||||
|
startuppalette8[i] = ColorMatcher.Pick(pe);
|
||||||
|
startuppalette32[i] = pe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// PlanarToChunky
|
||||||
|
//
|
||||||
|
// Convert a 4-bpp planar image to chunky pixels.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void PlanarToChunky(T* dest, const uint8_t* src, const T* remap, int width, int height)
|
||||||
|
{
|
||||||
|
int y, x;
|
||||||
|
const uint8_t* src1, * src2, * src3, * src4;
|
||||||
|
size_t plane_size = width / 8 * height;
|
||||||
|
|
||||||
|
src1 = src;
|
||||||
|
src2 = src1 + plane_size;
|
||||||
|
src3 = src2 + plane_size;
|
||||||
|
src4 = src3 + plane_size;
|
||||||
|
|
||||||
|
for (y = height; y > 0; --y)
|
||||||
|
{
|
||||||
|
for (x = width; x > 0; x -= 8)
|
||||||
|
{
|
||||||
|
dest[0] = remap[((*src4 & 0x80) | ((*src3 & 0x80) >> 1) | ((*src2 & 0x80) >> 2) | ((*src1 & 0x80) >> 3)) >> 4];
|
||||||
|
dest[1] = remap[((*src4 & 0x40) >> 3) | ((*src3 & 0x40) >> 4) | ((*src2 & 0x40) >> 5) | ((*src1 & 0x40) >> 6)];
|
||||||
|
dest[2] = remap[(((*src4 & 0x20) << 2) | ((*src3 & 0x20) << 1) | ((*src2 & 0x20)) | ((*src1 & 0x20) >> 1)) >> 4];
|
||||||
|
dest[3] = remap[((*src4 & 0x10) >> 1) | ((*src3 & 0x10) >> 2) | ((*src2 & 0x10) >> 3) | ((*src1 & 0x10) >> 4)];
|
||||||
|
dest[4] = remap[(((*src4 & 0x08) << 4) | ((*src3 & 0x08) << 3) | ((*src2 & 0x08) << 2) | ((*src1 & 0x08) << 1)) >> 4];
|
||||||
|
dest[5] = remap[((*src4 & 0x04) << 1) | ((*src3 & 0x04)) | ((*src2 & 0x04) >> 1) | ((*src1 & 0x04) >> 2)];
|
||||||
|
dest[6] = remap[(((*src4 & 0x02) << 6) | ((*src3 & 0x02) << 5) | ((*src2 & 0x02) << 4) | ((*src1 & 0x02) << 3)) >> 4];
|
||||||
|
dest[7] = remap[((*src4 & 0x01) << 3) | ((*src3 & 0x01) << 2) | ((*src2 & 0x01) << 1) | ((*src1 & 0x01))];
|
||||||
|
dest += 8;
|
||||||
|
src1 += 1;
|
||||||
|
src2 += 1;
|
||||||
|
src3 += 1;
|
||||||
|
src4 += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
TArray<uint8_t> FStartupTexture::CreatePalettedPixels(int conversion)
|
||||||
|
{
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
||||||
|
|
||||||
|
|
||||||
|
TArray<uint8_t> Work(Width*Height, true);
|
||||||
|
TArray<uint8_t> Pixels(Width*Height, true);
|
||||||
|
PlanarToChunky(Work.Data(), source + 48, startuppalette8, Width, Height);
|
||||||
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap);
|
||||||
|
return Pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int FStartupTexture::CopyPixels(FBitmap *bmp, int conversion)
|
||||||
|
{
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
PlanarToChunky((uint32_t*)bmp->GetPixels(), source + 48, startuppalette32, Width, Height);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FNotchTexture::FNotchTexture (int lumpnum, int width, int height)
|
||||||
|
: FImageSource(lumpnum)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
bUseGamePalette = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
TArray<uint8_t> FNotchTexture::CreatePalettedPixels(int conversion)
|
||||||
|
{
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
||||||
|
|
||||||
|
TArray<uint8_t> Work(Width*Height, true);
|
||||||
|
TArray<uint8_t> Pixels(Width*Height, true);
|
||||||
|
for(int i=0; i * Width * Height / 2; i++)
|
||||||
|
{
|
||||||
|
Work[i * 2] = startuppalette8[source[i] >> 4];
|
||||||
|
Work[i * 2 + 1] = startuppalette8[source[i] & 15];
|
||||||
|
}
|
||||||
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), Work.Data(), Width, Height, Width, remap);
|
||||||
|
return Pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
int FNotchTexture::CopyPixels(FBitmap *bmp, int conversion)
|
||||||
|
{
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
|
||||||
|
auto Work = (uint32_t*)bmp->GetPixels();
|
||||||
|
for(int i = 0; i < Width * Height / 2; i++)
|
||||||
|
{
|
||||||
|
Work[i * 2] = startuppalette32[source[i] >> 4];
|
||||||
|
Work[i * 2 + 1] = startuppalette32[source[i] & 15];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FStrifeStartupTexture::FStrifeStartupTexture (int lumpnum, int w, int h)
|
||||||
|
: FImageSource(lumpnum)
|
||||||
|
{
|
||||||
|
Width = w;
|
||||||
|
Height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
TArray<uint8_t> FStrifeStartupTexture::CreatePalettedPixels(int conversion)
|
||||||
|
{
|
||||||
|
FileData lump = fileSystem.ReadFile (SourceLump);
|
||||||
|
const uint8_t *source = (const uint8_t *)lump.GetMem();
|
||||||
|
TArray<uint8_t> Pixels(Width*Height, true);
|
||||||
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
||||||
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source, Width, Height, Width, remap);
|
||||||
|
return Pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FStrifeStartupBackground::FStrifeStartupBackground (int lumpnum)
|
||||||
|
: FImageSource(lumpnum)
|
||||||
|
{
|
||||||
|
Width = 320;
|
||||||
|
Height = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// this image is very messy but let's prepare it just like Strife does
|
||||||
|
// so that the screen can be replaced with a whole image.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
TArray<uint8_t> FStrifeStartupBackground::CreatePalettedPixels(int conversion)
|
||||||
|
{
|
||||||
|
TArray<uint8_t> source(64000, true);
|
||||||
|
memset(source.Data(), 0xF0, 64000);
|
||||||
|
auto lumpr = fileSystem.OpenFileReader(SourceLump);
|
||||||
|
lumpr.Seek(57 * 320, FileReader::SeekSet);
|
||||||
|
lumpr.Read(source.Data() + 41 * 320, 95 * 320);
|
||||||
|
|
||||||
|
TArray<uint8_t> Pixels(Width*Height, true);
|
||||||
|
const uint8_t *remap = ImageHelpers::GetRemap(conversion == luminance);
|
||||||
|
ImageHelpers::FlipNonSquareBlockRemap(Pixels.Data(), source.Data(), Width, Height, Width, remap);
|
||||||
|
return Pixels;
|
||||||
|
}
|
|
@ -311,7 +311,7 @@ void FGameTexture::SetupSpriteData()
|
||||||
|
|
||||||
if (i == 1 && ShouldExpandSprite())
|
if (i == 1 && ShouldExpandSprite())
|
||||||
{
|
{
|
||||||
spi.mTrimResult = Base->TrimBorders(spi.trim); // get the trim size before adding the empty frame
|
spi.mTrimResult = Base->TrimBorders(spi.trim) && !GetNoTrimming(); // get the trim size before adding the empty frame
|
||||||
spi.spriteWidth += 2;
|
spi.spriteWidth += 2;
|
||||||
spi.spriteHeight += 2;
|
spi.spriteHeight += 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -335,6 +335,7 @@ FImageSource *FlatImage_TryCreate(FileReader &, int lumpnum);
|
||||||
FImageSource *PatchImage_TryCreate(FileReader &, int lumpnum);
|
FImageSource *PatchImage_TryCreate(FileReader &, int lumpnum);
|
||||||
FImageSource *EmptyImage_TryCreate(FileReader &, int lumpnum);
|
FImageSource *EmptyImage_TryCreate(FileReader &, int lumpnum);
|
||||||
FImageSource *AutomapImage_TryCreate(FileReader &, int lumpnum);
|
FImageSource *AutomapImage_TryCreate(FileReader &, int lumpnum);
|
||||||
|
FImageSource *StartupPageImage_TryCreate(FileReader &, int lumpnum);
|
||||||
|
|
||||||
|
|
||||||
// Examines the lump contents to decide what type of texture to create,
|
// Examines the lump contents to decide what type of texture to create,
|
||||||
|
@ -350,6 +351,7 @@ FImageSource * FImageSource::GetImage(int lumpnum, bool isflat)
|
||||||
{ StbImage_TryCreate, false },
|
{ StbImage_TryCreate, false },
|
||||||
{ TGAImage_TryCreate, false },
|
{ TGAImage_TryCreate, false },
|
||||||
{ AnmImage_TryCreate, false },
|
{ AnmImage_TryCreate, false },
|
||||||
|
{ StartupPageImage_TryCreate, false },
|
||||||
{ RawPageImage_TryCreate, false },
|
{ RawPageImage_TryCreate, false },
|
||||||
{ FlatImage_TryCreate, true }, // flat detection is not reliable, so only consider this for real flats.
|
{ FlatImage_TryCreate, true }, // flat detection is not reliable, so only consider this for real flats.
|
||||||
{ PatchImage_TryCreate, false },
|
{ PatchImage_TryCreate, false },
|
||||||
|
|
|
@ -1186,19 +1186,19 @@ FGameTexture *CreateShaderTexture(bool, bool);
|
||||||
void InitBuildTiles();
|
void InitBuildTiles();
|
||||||
FImageSource* CreateEmptyTexture();
|
FImageSource* CreateEmptyTexture();
|
||||||
|
|
||||||
void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&))
|
void FTextureManager::Init()
|
||||||
{
|
{
|
||||||
progressFunc = progressFunc_;
|
|
||||||
DeleteAll();
|
DeleteAll();
|
||||||
//if (BuildTileFiles.Size() == 0) CountBuildTiles ();
|
|
||||||
|
|
||||||
|
// Add all the static content
|
||||||
auto nulltex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Null);
|
auto nulltex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Null);
|
||||||
AddGameTexture(nulltex);
|
AddGameTexture(nulltex);
|
||||||
|
|
||||||
// This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture.
|
// This is for binding to unused texture units, because accessing an unbound texture unit is undefined. It's a one pixel empty texture.
|
||||||
auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Override);
|
auto emptytex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), nullptr, ETextureType::Override);
|
||||||
emptytex->SetSize(1, 1);
|
emptytex->SetSize(1, 1);
|
||||||
AddGameTexture(emptytex);
|
AddGameTexture(emptytex);
|
||||||
|
|
||||||
// some special textures used in the game.
|
// some special textures used in the game.
|
||||||
AddGameTexture(CreateShaderTexture(false, false));
|
AddGameTexture(CreateShaderTexture(false, false));
|
||||||
AddGameTexture(CreateShaderTexture(false, true));
|
AddGameTexture(CreateShaderTexture(false, true));
|
||||||
|
@ -1211,6 +1211,12 @@ void FTextureManager::Init(void (*progressFunc_)(), void (*checkForHacks)(BuildI
|
||||||
mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override);
|
mt = MakeGameTexture(new AnimTexture(), "AnimTextureFrame2", ETextureType::Override);
|
||||||
mt->SetUpscaleFlag(false, true);
|
mt->SetUpscaleFlag(false, true);
|
||||||
AddGameTexture(mt);
|
AddGameTexture(mt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FTextureManager::AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&))
|
||||||
|
{
|
||||||
|
progressFunc = progressFunc_;
|
||||||
|
//if (BuildTileFiles.Size() == 0) CountBuildTiles ();
|
||||||
|
|
||||||
int wadcnt = fileSystem.GetNumWads();
|
int wadcnt = fileSystem.GetNumWads();
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,8 @@ public:
|
||||||
|
|
||||||
void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build);
|
void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build);
|
||||||
void AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build);
|
void AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build);
|
||||||
void Init(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo &));
|
void Init();
|
||||||
|
void AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&));
|
||||||
void DeleteAll();
|
void DeleteAll();
|
||||||
|
|
||||||
void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free);
|
void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free);
|
||||||
|
|
|
@ -238,6 +238,8 @@
|
||||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
# elif defined(_MSC_VER) && defined(_M_ARM)
|
# elif defined(_MSC_VER) && defined(_M_ARM)
|
||||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
|
# elif defined(_MSC_VER) && defined(_M_ARM64)
|
||||||
|
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||||
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||||
# define RAPIDJSON_ENDIAN
|
# define RAPIDJSON_ENDIAN
|
||||||
# else
|
# else
|
||||||
|
|
|
@ -408,6 +408,7 @@ public:
|
||||||
{
|
{
|
||||||
new(&Array[start + i]) T(std::move(item[i]));
|
new(&Array[start + i]) T(std::move(item[i]));
|
||||||
}
|
}
|
||||||
|
item.Clear();
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1463,7 +1463,7 @@ bool DoArbitrate (void *userdata)
|
||||||
|
|
||||||
data->playersdetected[0] |= 1 << netbuffer[1];
|
data->playersdetected[0] |= 1 << netbuffer[1];
|
||||||
|
|
||||||
StartScreen->NetMessage ("Found %s (node %d, player %d)", GetPlayerName(netbuffer[1]).GetChars(),
|
I_NetMessage ("Found %s (node %d, player %d)", GetPlayerName(netbuffer[1]).GetChars(),
|
||||||
node, netbuffer[1]+1);
|
node, netbuffer[1]+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1610,8 +1610,8 @@ bool D_ArbitrateNetStart (void)
|
||||||
data.gotsetup[0] = 0x80;
|
data.gotsetup[0] = 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartScreen->NetInit ("Exchanging game information", 1);
|
I_NetInit ("Exchanging game information", 1);
|
||||||
if (!StartScreen->NetLoop (DoArbitrate, &data))
|
if (!I_NetLoop (DoArbitrate, &data))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1629,7 +1629,7 @@ bool D_ArbitrateNetStart (void)
|
||||||
fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]);
|
fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StartScreen->NetDone();
|
I_NetDone();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "razefont.h"
|
#include "razefont.h"
|
||||||
#include "coreactor.h"
|
#include "coreactor.h"
|
||||||
#include "wipe.h"
|
#include "wipe.h"
|
||||||
|
#include "findfile.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
void LoadHexFont(const char* filename);
|
||||||
|
|
||||||
CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
@ -918,9 +922,11 @@ void GetGames()
|
||||||
|
|
||||||
static void InitTextures()
|
static void InitTextures()
|
||||||
{
|
{
|
||||||
|
|
||||||
TexMan.usefullnames = true;
|
TexMan.usefullnames = true;
|
||||||
TexMan.Init([]() {}, [](BuildInfo&) {});
|
TexMan.Init();
|
||||||
StartScreen->Progress();
|
TexMan.AddTextures([]() {}, [](BuildInfo&) {});
|
||||||
|
StartWindow->Progress();
|
||||||
mdinit();
|
mdinit();
|
||||||
|
|
||||||
TileFiles.Init();
|
TileFiles.Init();
|
||||||
|
@ -951,6 +957,13 @@ int RunGame()
|
||||||
{
|
{
|
||||||
GameStartupInfo.FgColor = 0xffffff;
|
GameStartupInfo.FgColor = 0xffffff;
|
||||||
|
|
||||||
|
auto wad = BaseFileSearch(ENGINERES_FILE, NULL, true, GameConfig);
|
||||||
|
if (wad == NULL)
|
||||||
|
{
|
||||||
|
I_FatalError("Cannot find " ENGINERES_FILE);
|
||||||
|
}
|
||||||
|
LoadHexFont(wad); // load hex font early so we have it during startup.
|
||||||
|
|
||||||
// Set up the console before anything else so that it can receive text.
|
// Set up the console before anything else so that it can receive text.
|
||||||
C_InitConsole(1024, 768, true);
|
C_InitConsole(1024, 768, true);
|
||||||
|
|
||||||
|
@ -1026,8 +1039,8 @@ int RunGame()
|
||||||
|
|
||||||
V_InitScreenSize();
|
V_InitScreenSize();
|
||||||
V_InitScreen();
|
V_InitScreen();
|
||||||
StartScreen = FStartupScreen::CreateInstance(8);
|
StartWindow = FStartupScreen::CreateInstance(8, true);
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
|
|
||||||
TArray<FString> addArt;
|
TArray<FString> addArt;
|
||||||
for (auto& grp : usedgroups)
|
for (auto& grp : usedgroups)
|
||||||
|
@ -1062,18 +1075,18 @@ int RunGame()
|
||||||
GPalette.Init(MAXPALOOKUPS + 2, palindexmap); // one slot for each translation, plus a separate one for the base palettes and the internal one
|
GPalette.Init(MAXPALOOKUPS + 2, palindexmap); // one slot for each translation, plus a separate one for the base palettes and the internal one
|
||||||
gi->loadPalette();
|
gi->loadPalette();
|
||||||
BuildFogTable();
|
BuildFogTable();
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
InitTextures();
|
InitTextures();
|
||||||
|
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
I_InitSound();
|
I_InitSound();
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
Mus_InitMusic();
|
Mus_InitMusic();
|
||||||
S_ParseSndInfo();
|
S_ParseSndInfo();
|
||||||
S_ParseReverbDef();
|
S_ParseReverbDef();
|
||||||
InitStatistics();
|
InitStatistics();
|
||||||
LoadScripts();
|
LoadScripts();
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
SetDefaultStrings();
|
SetDefaultStrings();
|
||||||
Job_Init();
|
Job_Init();
|
||||||
Local_Job_Init();
|
Local_Job_Init();
|
||||||
|
@ -1082,12 +1095,12 @@ int RunGame()
|
||||||
|
|
||||||
SetupGameButtons();
|
SetupGameButtons();
|
||||||
gameinfo.mBackButton = "engine/graphics/m_back.png";
|
gameinfo.mBackButton = "engine/graphics/m_back.png";
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
|
|
||||||
engineInit();
|
engineInit();
|
||||||
GC::AddMarkerFunc(MarkMap);
|
GC::AddMarkerFunc(MarkMap);
|
||||||
gi->app_init();
|
gi->app_init();
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
G_ParseMapInfo();
|
G_ParseMapInfo();
|
||||||
ParseGLDefs();
|
ParseGLDefs();
|
||||||
ReplaceMusics(true);
|
ReplaceMusics(true);
|
||||||
|
@ -1095,7 +1108,7 @@ int RunGame()
|
||||||
SetDefaultMenuColors();
|
SetDefaultMenuColors();
|
||||||
M_Init();
|
M_Init();
|
||||||
BuildGameMenus();
|
BuildGameMenus();
|
||||||
StartScreen->Progress();
|
StartWindow->Progress();
|
||||||
if (!(paletteloaded & PALETTE_MAIN))
|
if (!(paletteloaded & PALETTE_MAIN))
|
||||||
I_FatalError("No palette found.");
|
I_FatalError("No palette found.");
|
||||||
|
|
||||||
|
@ -1104,6 +1117,10 @@ int RunGame()
|
||||||
DeleteStartupScreen();
|
DeleteStartupScreen();
|
||||||
|
|
||||||
V_Init2();
|
V_Init2();
|
||||||
|
while (!screen->CompileNextShader())
|
||||||
|
{
|
||||||
|
// here we can do some visual updates later
|
||||||
|
}
|
||||||
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
twod->Begin(screen->GetWidth(), screen->GetHeight());
|
||||||
twod->End();
|
twod->End();
|
||||||
UpdateJoystickMenu(NULL);
|
UpdateJoystickMenu(NULL);
|
||||||
|
|
|
@ -139,6 +139,12 @@ CUSTOM_CVARD(Float, hud_scalefactor, 1, CVAR_ARCHIVE, "changes the hud scale")
|
||||||
else setViewport(hud_size);
|
else setViewport(hud_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, hud_aspectscale, false, CVAR_ARCHIVE)
|
||||||
|
{
|
||||||
|
setViewport(hud_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Note: The shift detection here should be part of the key event data, but that requires a lot more work. Ideally use a ShiftBinds mapping. For control through bound keys this should be fine, bunt not for use from the console.
|
// Note: The shift detection here should be part of the key event data, but that requires a lot more work. Ideally use a ShiftBinds mapping. For control through bound keys this should be fine, bunt not for use from the console.
|
||||||
CCMD(sizeup)
|
CCMD(sizeup)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
|
||||||
#include "dukeactor.h"
|
#include "dukeactor.h"
|
||||||
#include "interpolate.h"
|
#include "interpolate.h"
|
||||||
#include "razefont.h"
|
#include "razefont.h"
|
||||||
|
#include "startscreen.h"
|
||||||
|
|
||||||
BEGIN_DUKE_NS
|
BEGIN_DUKE_NS
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
||||||
#include "st_start.h"
|
#include "st_start.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
#include "psky.h"
|
#include "psky.h"
|
||||||
|
#include "startscreen.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,33 @@ enum EPrintLevel
|
||||||
PRINT_NOLOG = 2048, // Flag - do not print to log file
|
PRINT_NOLOG = 2048, // Flag - do not print to log file
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
// These are here to document the intrinsic methods and fields available on
|
||||||
|
// the built-in ZScript types
|
||||||
|
struct Vector2
|
||||||
|
{
|
||||||
|
Vector2(x, y);
|
||||||
|
double x, y;
|
||||||
|
native double Length();
|
||||||
|
native Vector2 Unit();
|
||||||
|
// The dot product of two vectors can be calculated like this:
|
||||||
|
// double d = a dot b;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Vector3
|
||||||
|
{
|
||||||
|
Vector3(x, y, z);
|
||||||
|
double x, y, z;
|
||||||
|
Vector2 xy; // Convenient access to the X and Y coordinates of a 3D vector
|
||||||
|
native double Length();
|
||||||
|
native Vector3 Unit();
|
||||||
|
// The dot product of two vectors can be calculated like this:
|
||||||
|
// double d = a dot b;
|
||||||
|
// The cross product of two vectors can be calculated like this:
|
||||||
|
// Vector3 d = a cross b;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this.
|
struct _ native // These are the global variables, the struct is only here to avoid extending the parser for this.
|
||||||
{
|
{
|
||||||
native readonly Array<class> AllClasses;
|
native readonly Array<class> AllClasses;
|
||||||
|
@ -216,7 +243,7 @@ struct MusPlayingInfo native
|
||||||
native int baseorder;
|
native int baseorder;
|
||||||
native bool loop;
|
native bool loop;
|
||||||
native voidptr handle;
|
native voidptr handle;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TexMan
|
struct TexMan
|
||||||
|
@ -252,7 +279,7 @@ struct TexMan
|
||||||
ForceLookup = 128,
|
ForceLookup = 128,
|
||||||
NoAlias = 256
|
NoAlias = 256
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ETexReplaceFlags
|
enum ETexReplaceFlags
|
||||||
{
|
{
|
||||||
NOT_BOTTOM = 1,
|
NOT_BOTTOM = 1,
|
||||||
|
@ -274,6 +301,47 @@ struct TexMan
|
||||||
native static bool UseGamePalette(TextureID tex);
|
native static bool UseGamePalette(TextureID tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Intrinsic TextureID methods
|
||||||
|
// This isn't really a class, and can be used as an integer
|
||||||
|
struct TextureID
|
||||||
|
{
|
||||||
|
native bool IsValid();
|
||||||
|
native bool IsNull();
|
||||||
|
native bool Exists();
|
||||||
|
native void SetInvalid();
|
||||||
|
native void SetNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 32-bit RGBA color - each component is one byte, or 8-bit
|
||||||
|
// This isn't really a class, and can be used as an integer
|
||||||
|
struct Color
|
||||||
|
{
|
||||||
|
// Constructor - alpha channel is optional
|
||||||
|
Color(int alpha, int red, int green, int blue);
|
||||||
|
Color(int red, int green, int blue); // Alpha is 0 if omitted
|
||||||
|
int r; // Red
|
||||||
|
int g; // Green
|
||||||
|
int b; // Blue
|
||||||
|
int a; // Alpha
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name - a string with an integer ID
|
||||||
|
struct Name
|
||||||
|
{
|
||||||
|
Name(Name name);
|
||||||
|
Name(String name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sound ID - can be created by casting from a string (name from SNDINFO) or an
|
||||||
|
// integer (sound ID as integer).
|
||||||
|
struct Sound
|
||||||
|
{
|
||||||
|
Sound(String soundName);
|
||||||
|
Sound(int id);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
enum EScaleMode
|
enum EScaleMode
|
||||||
{
|
{
|
||||||
FSMode_None = 0,
|
FSMode_None = 0,
|
||||||
|
@ -475,7 +543,7 @@ struct Font native
|
||||||
CR_TEAL,
|
CR_TEAL,
|
||||||
NUM_TEXT_COLORS
|
NUM_TEXT_COLORS
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEXTCOLOR_BRICK = "\034A";
|
const TEXTCOLOR_BRICK = "\034A";
|
||||||
const TEXTCOLOR_TAN = "\034B";
|
const TEXTCOLOR_TAN = "\034B";
|
||||||
const TEXTCOLOR_GRAY = "\034C";
|
const TEXTCOLOR_GRAY = "\034C";
|
||||||
|
@ -509,7 +577,8 @@ struct Font native
|
||||||
|
|
||||||
const TEXTCOLOR_CHAT = "\034*";
|
const TEXTCOLOR_CHAT = "\034*";
|
||||||
const TEXTCOLOR_TEAMCHAT = "\034!";
|
const TEXTCOLOR_TEAMCHAT = "\034!";
|
||||||
|
// native Font(const String name); // String/name to font casts
|
||||||
|
// native Font(const Name name);
|
||||||
|
|
||||||
native int GetCharWidth(int code);
|
native int GetCharWidth(int code);
|
||||||
native int StringWidth(String code);
|
native int StringWidth(String code);
|
||||||
|
@ -591,14 +660,64 @@ class Object native
|
||||||
private native static void BuiltinRandomSeed(voidptr rng, int seed);
|
private native static void BuiltinRandomSeed(voidptr rng, int seed);
|
||||||
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
|
private native static Class<Object> BuiltinNameToClass(Name nm, Class<Object> filter);
|
||||||
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
|
private native static Object BuiltinClassCast(Object inptr, Class<Object> test);
|
||||||
|
|
||||||
native static uint MSTime();
|
deprecated("4.8", "Use MSTimeF instead") native static uint MSTime();
|
||||||
|
native static double MSTimeF();
|
||||||
native vararg static void ThrowAbortException(String fmt, ...);
|
native vararg static void ThrowAbortException(String fmt, ...);
|
||||||
|
|
||||||
native virtualscope void Destroy();
|
native virtualscope void Destroy();
|
||||||
|
|
||||||
// This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown.
|
// This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown.
|
||||||
virtual virtualscope void OnDestroy() {}
|
virtual virtualscope void OnDestroy() {}
|
||||||
|
//
|
||||||
|
// Object intrinsics
|
||||||
|
// Every ZScript "class" inherits from Object, and so inherits these methods as well
|
||||||
|
// clearscope bool IsAbstract(); // Query whether or not the class of this object is abstract
|
||||||
|
// clearscope Object GetParentClass(); // Get the parent class of this object
|
||||||
|
// clearscope Name GetClassName(); // Get the name of this object's class
|
||||||
|
// clearscope Class<Object> GetClass(); // Get the object's class
|
||||||
|
// clearscope Object new(class<Object> type); // Create a new object with this class. This is only valid for thinkers and plain objects, except menus. For actors, use Actor.Spawn();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Intrinsic random number generation functions. Note that the square
|
||||||
|
// bracket syntax for specifying an RNG ID is only available for these
|
||||||
|
// functions.
|
||||||
|
// clearscope void SetRandomSeed[Name rngId = 'None'](int seed); // Set the seed for the given RNG.
|
||||||
|
// clearscope int Random[Name rngId = 'None'](int min, int max); // Use the given RNG to generate a random integer number in the range (min, max) inclusive.
|
||||||
|
// clearscope int Random2[Name rngId = 'None'](int mask); // Use the given RNG to generate a random integer number, and do a "union" (bitwise AND, AKA &) operation with the bits in the mask integer.
|
||||||
|
// clearscope double FRandom[Name rngId = 'None'](double min, double max); // Use the given RNG to generate a random real number in the range (min, max) inclusive.
|
||||||
|
// clearscope int RandomPick[Name rngId = 'None'](int choices...); // Use the given RNG to generate a random integer from the given choices.
|
||||||
|
// clearscope double FRandomPick[Name rngId = 'None'](double choices...); // Use the given RNG to generate a random real number from the given choices.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Intrinsic math functions - the argument and return types for these
|
||||||
|
// functions depend on the arguments given. Other than that, they work the
|
||||||
|
// same way similarly-named functions in other programming languages work.
|
||||||
|
// Note that trigonometric functions work with degrees instead of radians
|
||||||
|
// clearscope T abs(T x);
|
||||||
|
// clearscope T atan2(T y, T x); // NOTE: Returns a value in degrees instead of radians
|
||||||
|
// clearscope T vectorangle(T x, T y); // Same as Atan2 with the arguments in a different order
|
||||||
|
// clearscope T min(T x...);
|
||||||
|
// clearscope T max(T x...);
|
||||||
|
// clearscope T clamp(T x, T min, T max);
|
||||||
|
//
|
||||||
|
// These math functions only work with doubles - they are defined in FxFlops
|
||||||
|
// clearscope double exp(double x);
|
||||||
|
// clearscope double log(double x);
|
||||||
|
// clearscope double log10(double x);
|
||||||
|
// clearscope double sqrt(double x);
|
||||||
|
// clearscope double ceil(double x);
|
||||||
|
// clearscope double floor(double x);
|
||||||
|
// clearscope double acos(double x);
|
||||||
|
// clearscope double asin(double x);
|
||||||
|
// clearscope double atan(double x);
|
||||||
|
// clearscope double cos(double x);
|
||||||
|
// clearscope double sin(double x);
|
||||||
|
// clearscope double tan(double x);
|
||||||
|
// clearscope double cosh(double x);
|
||||||
|
// clearscope double sinh(double x);
|
||||||
|
// clearscope double tanh(double x);
|
||||||
|
// clearscope double round(double x);
|
||||||
}
|
}
|
||||||
|
|
||||||
class BrokenLines : Object native version("2.4")
|
class BrokenLines : Object native version("2.4")
|
||||||
|
@ -665,11 +784,15 @@ enum EmptyTokenType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Although String is a builtin type, this is a convenient way to attach methods to it.
|
// Although String is a builtin type, this is a convenient way to attach methods to it.
|
||||||
|
// All of these methods are available on strings
|
||||||
struct StringStruct native
|
struct StringStruct native
|
||||||
{
|
{
|
||||||
native static vararg String Format(String fmt, ...);
|
native static vararg String Format(String fmt, ...);
|
||||||
native vararg void AppendFormat(String fmt, ...);
|
native vararg void AppendFormat(String fmt, ...);
|
||||||
|
// native int Length(); // Intrinsic
|
||||||
|
// native bool operator==(String other); // Equality comparison
|
||||||
|
// native bool operator~==(String other); // Case-insensitive equality comparison
|
||||||
|
// native String operator..(String other); // Concatenate with another String
|
||||||
native void Replace(String pattern, String replacement);
|
native void Replace(String pattern, String replacement);
|
||||||
native String Left(int len) const;
|
native String Left(int len) const;
|
||||||
native String Mid(int pos = 0, int len = 2147483647) const;
|
native String Mid(int pos = 0, int len = 2147483647) const;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
struct DynArray_I8 native
|
struct DynArray_I8 native
|
||||||
{
|
{
|
||||||
native readonly uint Size;
|
native readonly uint Size;
|
||||||
|
|
||||||
native void Copy(DynArray_I8 other);
|
native void Copy(DynArray_I8 other);
|
||||||
native void Move(DynArray_I8 other);
|
native void Move(DynArray_I8 other);
|
||||||
native void Append (DynArray_I8 other);
|
native void Append (DynArray_I8 other);
|
||||||
|
@ -65,7 +65,7 @@ struct DynArray_I32 native
|
||||||
struct DynArray_F32 native
|
struct DynArray_F32 native
|
||||||
{
|
{
|
||||||
native readonly uint Size;
|
native readonly uint Size;
|
||||||
|
|
||||||
native void Copy(DynArray_F32 other);
|
native void Copy(DynArray_F32 other);
|
||||||
native void Move(DynArray_F32 other);
|
native void Move(DynArray_F32 other);
|
||||||
native void Append (DynArray_F32 other);
|
native void Append (DynArray_F32 other);
|
||||||
|
@ -85,7 +85,7 @@ struct DynArray_F32 native
|
||||||
struct DynArray_F64 native
|
struct DynArray_F64 native
|
||||||
{
|
{
|
||||||
native readonly uint Size;
|
native readonly uint Size;
|
||||||
|
|
||||||
native void Copy(DynArray_F64 other);
|
native void Copy(DynArray_F64 other);
|
||||||
native void Move(DynArray_F64 other);
|
native void Move(DynArray_F64 other);
|
||||||
native void Append (DynArray_F64 other);
|
native void Append (DynArray_F64 other);
|
||||||
|
@ -105,7 +105,7 @@ struct DynArray_F64 native
|
||||||
struct DynArray_Ptr native
|
struct DynArray_Ptr native
|
||||||
{
|
{
|
||||||
native readonly uint Size;
|
native readonly uint Size;
|
||||||
|
|
||||||
native void Copy(DynArray_Ptr other);
|
native void Copy(DynArray_Ptr other);
|
||||||
native void Move(DynArray_Ptr other);
|
native void Move(DynArray_Ptr other);
|
||||||
native void Append (DynArray_Ptr other);
|
native void Append (DynArray_Ptr other);
|
||||||
|
@ -125,7 +125,7 @@ struct DynArray_Ptr native
|
||||||
struct DynArray_Obj native
|
struct DynArray_Obj native
|
||||||
{
|
{
|
||||||
native readonly uint Size;
|
native readonly uint Size;
|
||||||
|
|
||||||
native void Copy(DynArray_Obj other);
|
native void Copy(DynArray_Obj other);
|
||||||
native void Move(DynArray_Obj other);
|
native void Move(DynArray_Obj other);
|
||||||
native void Append (DynArray_Obj other);
|
native void Append (DynArray_Obj other);
|
||||||
|
|
|
@ -193,7 +193,7 @@ class OptionMenu : Menu
|
||||||
mDesc.mScrollPos += 2;
|
mDesc.mScrollPos += 2;
|
||||||
VisBottom += 2;
|
VisBottom += 2;
|
||||||
}
|
}
|
||||||
else
|
else if (VisBottom < mDesc.mItems.Size()-1)
|
||||||
{
|
{
|
||||||
mDesc.mScrollPos++;
|
mDesc.mScrollPos++;
|
||||||
VisBottom++;
|
VisBottom++;
|
||||||
|
@ -201,6 +201,30 @@ class OptionMenu : Menu
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (ev.type == UIEvent.Type_Char)
|
||||||
|
{
|
||||||
|
int key = String.CharLower(ev.keyChar);
|
||||||
|
int itemsNumber = mDesc.mItems.Size();
|
||||||
|
int direction = ev.IsAlt ? -1 : 1;
|
||||||
|
for (int i = 0; i < itemsNumber; ++i)
|
||||||
|
{
|
||||||
|
int index = (mDesc.mSelectedItem + direction * (i + 1) + itemsNumber) % itemsNumber;
|
||||||
|
if (!mDesc.mItems[index].Selectable()) continue;
|
||||||
|
String label = StringTable.Localize(mDesc.mItems[index].mLabel);
|
||||||
|
int firstLabelCharacter = String.CharLower(label.GetNextCodePoint(0));
|
||||||
|
if (firstLabelCharacter == key)
|
||||||
|
{
|
||||||
|
mDesc.mSelectedItem = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mDesc.mSelectedItem <= mDesc.mScrollTop + mDesc.mScrollPos
|
||||||
|
|| mDesc.mSelectedItem > VisBottom)
|
||||||
|
{
|
||||||
|
int pagesize = VisBottom - mDesc.mScrollPos - mDesc.mScrollTop;
|
||||||
|
mDesc.mScrollPos = clamp(mDesc.mSelectedItem - mDesc.mScrollTop - 1, 0, mDesc.mItems.size() - pagesize - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
return Super.OnUIEvent(ev);
|
return Super.OnUIEvent(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue