- Added the -norun parameter to quit the game just before video

initialization. To be used to check for errors in scripts without actually
  running the game.
- Added the -stdout parameter to the Windows version to send all output to
  a console, like the Linux version has done all along.


SVN r1486 (trunk)
This commit is contained in:
Randy Heit 2009-03-18 05:02:32 +00:00
parent 314216343d
commit c2aab5dd46
5 changed files with 185 additions and 40 deletions

View file

@ -1,4 +1,11 @@
March 16, 2009 March 17, 2009
- Added the -norun parameter to quit the game just before video
initialization. To be used to check for errors in scripts without actually
running the game.
- Added the -stdout parameter to the Windows version to send all output to
a console, like the Linux version has done all along.
March 16, 2009
- Added support for loading ZGL2 nodes. (Only useful with UDMF and maps with - Added support for loading ZGL2 nodes. (Only useful with UDMF and maps with
more than 65534 lines.) more than 65534 lines.)

View file

@ -2637,6 +2637,12 @@ void D_DoomMain (void)
delete StartScreen; delete StartScreen;
StartScreen = NULL; StartScreen = NULL;
if (Args->CheckParm("-norun"))
{
throw CNoRunExit();
}
V_Init2(); V_Init2();
files = Args->GatherFiles ("-playdemo", ".lmp", false); files = Args->GatherFiles ("-playdemo", ".lmp", false);

View file

@ -68,6 +68,10 @@ private:
char m_Message[MAX_ERRORTEXT]; char m_Message[MAX_ERRORTEXT];
}; };
class CNoRunExit : public CDoomError
{
};
class CRecoverableError : public CDoomError class CRecoverableError : public CDoomError
{ {
public: public:

View file

@ -125,6 +125,8 @@ HINSTANCE g_hInst;
DWORD SessionID; DWORD SessionID;
HANDLE MainThread; HANDLE MainThread;
DWORD MainThreadID; DWORD MainThreadID;
HANDLE StdOut;
bool FancyStdOut, AttachedStdOut;
// The main window // The main window
HWND Window; HWND Window;
@ -806,6 +808,49 @@ void DoMain (HINSTANCE hInstance)
// need to extract the ProcessIdToSessionId function from kernel32.dll manually. // need to extract the ProcessIdToSessionId function from kernel32.dll manually.
HMODULE kernel = GetModuleHandle ("kernel32.dll"); HMODULE kernel = GetModuleHandle ("kernel32.dll");
if (Args->CheckParm("-stdout"))
{
// As a GUI application, we don't normally get a console when we start.
// If we were run from the shell and are on XP+, we can attach to its
// console. Otherwise, we can create a new one. If we already have a
// stdout handle, then we have been redirected and should just use that
// handle instead of creating a console window.
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (StdOut != NULL)
{
// It seems that running from a shell always creates a std output
// for us, even if it doesn't go anywhere. (Running from Explorer
// does not.) If we can get file information for this handle, it's
// a file or pipe, so use it. Otherwise, pretend it wasn't there
// and find a console to use instead.
BY_HANDLE_FILE_INFORMATION info;
if (!GetFileInformationByHandle(StdOut, &info))
{
StdOut = NULL;
}
}
if (StdOut == NULL)
{
// AttachConsole was introduced with Windows XP. (OTOH, since we
// have to share the console with the shell, I'm not sure if it's
// a good idea to actually attach to it.)
typedef BOOL (WINAPI *ac)(DWORD);
ac attach_console = kernel != NULL ? (ac)GetProcAddress(kernel, "AttachConsole") : NULL;
if (attach_console != NULL && attach_console(ATTACH_PARENT_PROCESS))
{
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD foo; WriteFile(StdOut, "\n", 1, &foo, NULL);
AttachedStdOut = true;
}
if (StdOut == NULL && AllocConsole())
{
StdOut = GetStdHandle(STD_OUTPUT_HANDLE);
}
FancyStdOut = true;
}
}
// Set the timer to be as accurate as possible // Set the timer to be as accurate as possible
if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR) if (timeGetDevCaps (&tc, sizeof(tc)) != TIMERR_NOERROR)
TimerPeriod = 1; // Assume minimum resolution of 1 ms TimerPeriod = 1; // Assume minimum resolution of 1 ms
@ -906,7 +951,7 @@ void DoMain (HINSTANCE hInstance)
if (!Window) if (!Window)
I_FatalError ("Could not open window"); I_FatalError ("Could not open window");
if (kernel != 0) if (kernel != NULL)
{ {
typedef BOOL (WINAPI *pts)(DWORD, DWORD *); typedef BOOL (WINAPI *pts)(DWORD, DWORD *);
pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId"); pts pidsid = (pts)GetProcAddress (kernel, "ProcessIdToSessionId");
@ -946,6 +991,36 @@ void DoMain (HINSTANCE hInstance)
I_DetectOS (); I_DetectOS ();
D_DoomMain (); D_DoomMain ();
} }
catch (class CNoRunExit &)
{
I_ShutdownGraphics();
if (FancyStdOut && !AttachedStdOut)
{ // Outputting to a new console window: Wait for a keypress before quitting.
DWORD bytes;
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
ShowWindow (Window, SW_HIDE);
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
FlushConsoleInputBuffer(stdinput);
SetConsoleMode(stdinput, 0);
ReadConsole(stdinput, &bytes, 1, &bytes, NULL);
}
else if (StdOut == NULL)
{
BOOL bRet;
MSG msg;
RestoreConView();
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (bRet == -1)
{
exit(0);
}
}
}
exit(0);
}
catch (class CDoomError &error) catch (class CDoomError &error)
{ {
I_ShutdownGraphics (); I_ShutdownGraphics ();

View file

@ -66,7 +66,7 @@
#include "v_font.h" #include "v_font.h"
#include "g_level.h" #include "g_level.h"
#include "doomstat.h" #include "doomstat.h"
#include "v_palette.h"
#include "stats.h" #include "stats.h"
EXTERN_CVAR (String, language) EXTERN_CVAR (String, language)
@ -74,6 +74,8 @@ EXTERN_CVAR (String, language)
extern void CheckCPUID(CPUInfo *cpu); extern void CheckCPUID(CPUInfo *cpu);
extern HWND Window, ConWindow, GameTitleWindow; extern HWND Window, ConWindow, GameTitleWindow;
extern HANDLE StdOut;
extern bool FancyStdOut;
extern HINSTANCE g_hInst; extern HINSTANCE g_hInst;
double PerfToSec, PerfToMillisec; double PerfToSec, PerfToMillisec;
@ -554,10 +556,9 @@ void I_SetIWADInfo (const IWADInfo *info)
void I_PrintStr (const char *cp) void I_PrintStr (const char *cp)
{ {
if (ConWindow == NULL) if (ConWindow == NULL && StdOut == NULL)
return; return;
static bool newLine = true;
HWND edit = ConWindow; HWND edit = ConWindow;
char buf[256]; char buf[256];
int bpos = 0; int bpos = 0;
@ -566,17 +567,20 @@ void I_PrintStr (const char *cp)
LONG lines_before, lines_after; LONG lines_before, lines_after;
CHARFORMAT format; CHARFORMAT format;
// Store the current selection and set it to the end so we can append text. if (edit != NULL)
SendMessage (edit, EM_EXGETSEL, 0, (LPARAM)&selection); {
endselection.cpMax = endselection.cpMin = GetWindowTextLength (edit); // Store the current selection and set it to the end so we can append text.
SendMessage (edit, EM_EXSETSEL, 0, (LPARAM)&endselection); 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 // 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. // the text is. Find out what EM_EXSETSEL thought it was and use that later.
SendMessage (edit, EM_EXGETSEL, 0, (LPARAM)&endselection); SendMessage (edit, EM_EXGETSEL, 0, (LPARAM)&endselection);
// Remember how many lines there were before we added text. // Remember how many lines there were before we added text.
lines_before = SendMessage (edit, EM_GETLINECOUNT, 0, 0); lines_before = SendMessage (edit, EM_GETLINECOUNT, 0, 0);
}
while (*cp != 0) while (*cp != 0)
{ {
@ -584,8 +588,15 @@ void I_PrintStr (const char *cp)
if ((*cp == 28 && bpos != 0) || bpos == 255) if ((*cp == 28 && bpos != 0) || bpos == 255)
{ {
buf[bpos] = 0; buf[bpos] = 0;
SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf); if (edit != NULL)
newLine = buf[bpos-1] == '\n'; {
SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf);
}
if (StdOut != NULL)
{
DWORD bytes_written;
WriteFile(StdOut, buf, bpos, &bytes_written, NULL);
}
bpos = 0; bpos = 0;
} }
if (*cp != 28) if (*cp != 28)
@ -602,39 +613,81 @@ void I_PrintStr (const char *cp)
{ {
// Change the color of future text added to the control. // Change the color of future text added to the control.
PalEntry color = V_LogColorFromColorRange (range); PalEntry color = V_LogColorFromColorRange (range);
// GDI uses BGR colors, but color is RGB, so swap the R and the B. if (StdOut != NULL && FancyStdOut)
swap (color.r, color.b); {
// Change the color. // Unfortunately, we are pretty limited here: There are only
format.cbSize = sizeof(format); // eight basic colors, and each comes in a dark and a bright
format.dwMask = CFM_COLOR; // variety.
format.dwEffects = 0; float h, s, v, r, g, b;
format.crTextColor = color; WORD attrib = 0;
SendMessage (edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
RGBtoHSV(color.r / 255.0, color.g / 255.0, color.b / 255.0, &h, &s, &v);
if (s != 0)
{ // color
HSVtoRGB(&r, &g, &b, h, 1, 1);
if (r == 1) attrib = FOREGROUND_RED;
if (g == 1) attrib |= FOREGROUND_GREEN;
if (b == 1) attrib |= FOREGROUND_BLUE;
if (v > 0.6) attrib |= FOREGROUND_INTENSITY;
}
else
{ // gray
if (v < 0.33) attrib = FOREGROUND_INTENSITY;
else if (v < 0.90) attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
else attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
}
SetConsoleTextAttribute(StdOut, attrib);
}
if (edit != NULL)
{
// GDI uses BGR colors, but color is RGB, so swap the R and the B.
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);
}
} }
} }
} }
if (bpos != 0) if (bpos != 0)
{ {
buf[bpos] = 0; buf[bpos] = 0;
SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf); if (edit != NULL)
newLine = buf[bpos-1] == '\n';
}
// 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 = SendMessage (edit, EM_GETLINECOUNT, 0, 0);
if (lines_after > lines_before)
{ {
SendMessage (edit, EM_LINESCROLL, 0, lines_after - lines_before); SendMessage (edit, EM_REPLACESEL, FALSE, (LPARAM)buf);
}
if (StdOut != NULL)
{
DWORD bytes_written;
WriteFile(StdOut, buf, bpos, &bytes_written, NULL);
} }
} }
// Restore the previous selection.
SendMessage (edit, EM_EXSETSEL, 0, (LPARAM)&selection); if (edit != NULL)
// Give the edit control a chance to redraw itself. {
I_GetEvent (); // 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 = 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)
{ // Set text back to gray, in case it was changed.
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
} }
EXTERN_CVAR (Bool, queryiwad); EXTERN_CVAR (Bool, queryiwad);