diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2f3035276..dbbe22ec2 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,8 @@ +January 5, 2007 +- Added simulation of Heretic's startup screen. +- Changed copyright notice for i_main.cpp, since none of it is really id's + code. + January 5, 2007 (Changes by Graf Zahl) - Added customizable border textures. They will be defined with the MAPINFO keyword 'bordertexture' and are settable per map. diff --git a/src/d_main.cpp b/src/d_main.cpp index 6ba9a2f8d..537c6d8ad 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2109,7 +2109,7 @@ void D_DoomMain (void) FActorInfo::StaticGameSet (); ST_Progress (); - Printf ("R_Init: Init %s refresh subsystem\n", GameNames[gameinfo.gametype]); + Printf ("R_Init: Init %s refresh subsystem.\n", GameNames[gameinfo.gametype]); R_Init (); Printf ("DecalLibrary: Load decals.\n"); diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 86ebb0f6e..e0f437811 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -1,24 +1,38 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id: i_main.c,v 1.8 1998/05/15 00:34:03 killough Exp $ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// -// DESCRIPTION: -// Main program, simply calls D_DoomMain high level loop. -// -//----------------------------------------------------------------------------- +/* +** i_main.cpp +** System-specific startup code. Eventually calls D_DoomMain. +** +**--------------------------------------------------------------------------- +** Copyright 1998-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. +**--------------------------------------------------------------------------- +** +*/ + +// HEADER FILES ------------------------------------------------------------ #include #include @@ -37,13 +51,36 @@ #include "version.h" #include "w_wad.h" +// MACROS ------------------------------------------------------------------ + +// The maximum number of functions that can be registered with atterm. +#define MAX_TERMS 32 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*)); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +// The command line arguments. DArgs Args; -#define MAX_TERMS 32 -void (*TermFuncs[MAX_TERMS]) (); -const char *TermNames[MAX_TERMS]; +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static void (*TermFuncs[MAX_TERMS]) (); +static const char *TermNames[MAX_TERMS]; static int NumTerms; +// CODE -------------------------------------------------------------------- + void addterm (void (*func) (), const char *name) { // Make sure this function wasn't already registered. @@ -85,7 +122,6 @@ static void STACK_ARGS NewFailure () I_FatalError ("Failed to allocate memory from system heap"); } -extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*)); static int DoomSpecificInfo (char *buffer, char *end) { const char *arg; diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 4b52f24cb..80138ca6a 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1715,8 +1715,8 @@ FWadLump FWadCollection::OpenLumpNum (int lump) } else if (l->flags & LUMPF_EXTERNAL) { - static char zero = '\0'; - FILE *f; + static char zero = '\0'; + FILE *f; if (wad != NULL) // The WadRecord in this case is just a means to store a path { @@ -1798,9 +1798,9 @@ FWadLump *FWadCollection::ReopenLumpNum (int lump) return new FWadLump(buffer, l->size, true); //... but restore the file pointer afterward! } else if (l->flags & LUMPF_EXTERNAL) - { + { static char zero = '\0'; - FILE *f; + FILE *f; if (wad != NULL) // The WadRecord in this case is just a means to store a path { diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 9737c9a8f..22f9a8d30 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -1,26 +1,38 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id:$ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// $Log:$ -// -// DESCRIPTION: -// Main program, simply calls D_DoomMain high level loop. -// -//----------------------------------------------------------------------------- +/* +** i_main.cpp +** System-specific startup code. Eventually calls D_DoomMain. +** +**--------------------------------------------------------------------------- +** Copyright 1998-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. +**--------------------------------------------------------------------------- +** +*/ +// HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0501 @@ -67,24 +79,39 @@ #include +// MACROS ------------------------------------------------------------------ + +// The main window's title. #define WINDOW_TITLE GAMESIG " " DOTVERSIONSTR " (" __DATE__ ")" + +// The maximum number of functions that can be registered with atterm. +#define MAX_TERMS 32 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); - void CreateCrashLog (char *custominfo, DWORD customsize); -extern void DisplayCrashLog (); +void DisplayCrashLog (); +extern BYTE *ST_Util_BitsForBitmap (BITMAPINFO *bitmap_info); + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + extern EXCEPTION_POINTERS CrashPointers; +extern BITMAPINFO *StartupBitmap; +extern UINT TimerPeriod; +extern HCURSOR TheArrowCursor, TheInvisibleCursor; -// Will this work with something besides VC++? -// Answer: yes it will. -// Which brings up the question, what won't it work with? -// -//extern int __argc; -//extern char **__argv; +// PUBLIC DATA DEFINITIONS ------------------------------------------------- +// The command line arguments. DArgs Args; -const char WinClassName[] = "ZDoomMainWindow"; - HINSTANCE g_hInst; DWORD SessionID; HANDLE MainThread; @@ -100,30 +127,23 @@ HWND ErrorPane, ProgressBar, NetStartPane, StartupScreen; HFONT GameTitleFont; LONG GameTitleFontHeight; -extern struct -{ - BITMAPINFOHEADER Header; - RGBQUAD Colors[16]; -} StartupBitmapInfo; -extern BYTE *StartupBitmapBits; +// PRIVATE DATA DEFINITIONS ------------------------------------------------ -HMODULE hwtsapi32; // handle to wtsapi32.dll - -extern UINT TimerPeriod; -extern HCURSOR TheArrowCursor, TheInvisibleCursor; - -#define MAX_TERMS 32 -void (*TermFuncs[MAX_TERMS])(void); +static const char WinClassName[] = "ZDoomMainWindow"; +static HMODULE hwtsapi32; // handle to wtsapi32.dll +static void (*TermFuncs[MAX_TERMS])(void); static int NumTerms; -//=========================================================================== +// CODE -------------------------------------------------------------------- + +//========================================================================== // // atterm // // Our own atexit because atexit can be problematic under Linux, though I // forget the circumstances that cause trouble. // -//=========================================================================== +//========================================================================== void atterm (void (*func)(void)) { @@ -143,13 +163,13 @@ void atterm (void (*func)(void)) TermFuncs[NumTerms++] = func; } -//=========================================================================== +//========================================================================== // // popterm // // Removes the most recently register atterm function. // -//=========================================================================== +//========================================================================== void popterm () { @@ -157,11 +177,11 @@ void popterm () NumTerms--; } -//=========================================================================== +//========================================================================== // // call_terms // -//=========================================================================== +//========================================================================== static void STACK_ARGS call_terms (void) { @@ -179,26 +199,26 @@ static int STACK_ARGS NewFailure (size_t size) } #endif -//=========================================================================== +//========================================================================== // // UnCOM // // Called by atterm if CoInitialize() succeeded. // -//=========================================================================== +//========================================================================== static void UnCOM (void) { CoUninitialize (); } -//=========================================================================== +//========================================================================== // // UnWTS // // Called by atterm if RegisterSessionNotification() succeeded. // -//=========================================================================== +//========================================================================== static void UnWTS (void) { @@ -215,14 +235,14 @@ static void UnWTS (void) } } -//=========================================================================== +//========================================================================== // // LayoutErrorPane // // Lays out the error pane to the desired width, returning the required // height. // -//=========================================================================== +//========================================================================== static int LayoutErrorPane (HWND pane, int w) { @@ -282,14 +302,14 @@ static int LayoutErrorPane (HWND pane, int w) return margin.top*3 + textheight + rectc.bottom; } -//=========================================================================== +//========================================================================== // // LayoutNetStartPane // // Lays out the network startup pane to the specified width, returning // its required height. // -//=========================================================================== +//========================================================================== int LayoutNetStartPane (HWND pane, int w) { @@ -325,14 +345,14 @@ int LayoutNetStartPane (HWND pane, int w) 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) { @@ -389,14 +409,14 @@ void LayoutMainWindow (HWND hWnd, HWND pane) } } -//=========================================================================== +//========================================================================== // // 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) { @@ -506,8 +526,8 @@ LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) // 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, StartupBitmapInfo.Header.biWidth, StartupBitmapInfo.Header.biHeight, - StartupBitmapBits, (BITMAPINFO *)&StartupBitmapInfo, DIB_RGB_COLORS, SRCCOPY); + 0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight, + ST_Util_BitsForBitmap(StartupBitmap), StartupBitmap, DIB_RGB_COLORS, SRCCOPY); } } return FALSE; @@ -529,13 +549,13 @@ LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) return DefWindowProc (hWnd, msg, wParam, lParam); } -//=========================================================================== +//========================================================================== // // ErrorPaneProc // // DialogProc for the error pane. // -//=========================================================================== +//========================================================================== INT_PTR CALLBACK ErrorPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -574,14 +594,14 @@ INT_PTR CALLBACK ErrorPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara return FALSE; } -//=========================================================================== +//========================================================================== // // I_SetWndProc // // Sets the main WndProc, hides all the child windows, and starts up // in-game input. // -//=========================================================================== +//========================================================================== void I_SetWndProc() { @@ -595,13 +615,13 @@ void I_SetWndProc() } } -//=========================================================================== +//========================================================================== // // RestoreConView // // Returns the main window to its startup state. // -//=========================================================================== +//========================================================================== void RestoreConView() { @@ -623,17 +643,20 @@ void RestoreConView() ShowWindow (ConWindow, SW_SHOW); ShowWindow (GameTitleWindow, SW_SHOW); // Make sure the progress bar isn't visible. - ST_Done(); + if (ST_Done != NULL) + { + ST_Done(); + } } -//=========================================================================== +//========================================================================== // // ShowErrorPane // // Shows an error message, preferably in the main window, but it can // use a normal message box too. // -//=========================================================================== +//========================================================================== void ShowErrorPane(const char *text) { @@ -671,11 +694,11 @@ void ShowErrorPane(const char *text) } } -//=========================================================================== +//========================================================================== // // DoMain // -//=========================================================================== +//========================================================================== void DoMain (HINSTANCE hInstance) { @@ -871,13 +894,13 @@ void DoMain (HINSTANCE hInstance) } } -//=========================================================================== +//========================================================================== // // DoomSpecificInfo // // Called by the crash logger to get application-specific information. // -//=========================================================================== +//========================================================================== void DoomSpecificInfo (char *buffer) { @@ -947,36 +970,36 @@ extern FILE *Logfile; // To make this work with MinGW, you will need to use inline assembly // because GCC offers no native support for Windows' SEH. -//=========================================================================== +//========================================================================== // // SleepForever // -//=========================================================================== +//========================================================================== void SleepForever () { Sleep (INFINITE); } -//=========================================================================== +//========================================================================== // // ExitMessedUp // // An exception occurred while exiting, so don't do any standard processing. // Just die. // -//=========================================================================== +//========================================================================== LONG WINAPI ExitMessedUp (LPEXCEPTION_POINTERS foo) { ExitProcess (1000); } -//=========================================================================== +//========================================================================== // // ExitFatally // -//=========================================================================== +//========================================================================== void CALLBACK ExitFatally (ULONG_PTR dummy) { @@ -987,11 +1010,11 @@ void CALLBACK ExitFatally (ULONG_PTR dummy) exit (-1); } -//=========================================================================== +//========================================================================== // // CatchAllExceptions // -//=========================================================================== +//========================================================================== LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) { @@ -1027,13 +1050,13 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) return EXCEPTION_CONTINUE_EXECUTION; } -//=========================================================================== +//========================================================================== // // infiniterecursion // // Debugging routine for testing the crash logger. // -//=========================================================================== +//========================================================================== #ifdef _DEBUG static void infiniterecursion(int foo) @@ -1045,11 +1068,11 @@ static void infiniterecursion(int foo) } #endif -//=========================================================================== +//========================================================================== // // WinMain // -//=========================================================================== +//========================================================================== int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int nCmdShow) { @@ -1113,14 +1136,14 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n return 0; } -//=========================================================================== +//========================================================================== // // CCMD crashout // // Debugging routine for testing the crash logger. // Useless in a debug build, because that doesn't enable the crash logger. // -//=========================================================================== +//========================================================================== #ifndef _DEBUG #include "c_dispatch.h" diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 17e65293d..376940126 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -50,14 +50,15 @@ #include "gi.h" #include "w_wad.h" #include "s_sound.h" +#include "m_alloc.h" // MACROS ------------------------------------------------------------------ -#define ST_MAX_NOTCHES 32 -#define ST_NOTCH_WIDTH 16 -#define ST_NOTCH_HEIGHT 23 -#define ST_PROGRESS_X 64 // Start of notches x screen pos. -#define ST_PROGRESS_Y 441 // Start of notches y screen pos. +#define ST_MAX_NOTCHES 32 +#define ST_NOTCH_WIDTH 16 +#define ST_NOTCH_HEIGHT 23 +#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 @@ -65,12 +66,37 @@ #define ST_NETNOTCH_HEIGHT 16 #define ST_MAX_NETNOTCHES 8 +#define TEXT_FONT_HEIGHT 14 +#define TEXT_FONT_NAME "vga-rom-font.14" + +#define THERM_X 14 +#define THERM_Y 14 +#define THERM_LEN 51 +#define THERM_COLOR 0xAA // light green + +// Text mode color values +#define LO 85 +#define MD 170 +#define HI 255 + // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -extern void ST_Util_PlanarToChunky4 (BYTE *dest, const BYTE *src, int width, int height); -extern void ST_Util_DrawBlock (BYTE *dest, const BYTE *src, int bytewidth, int height, int destpitch); +bool ST_Util_CreateStartupWindow (); +void ST_Util_SizeWindowForBitmap (); +BITMAPINFO *ST_Util_CreateBitmap (int width, int height, int color_bits); +BYTE *ST_Util_BitsForBitmap (BITMAPINFO *bitmap_info); +void ST_Util_FreeBitmap (BITMAPINFO *bitmap_info); +void ST_Util_PlanarToChunky4 (BYTE *dest, const BYTE *src, int width, int height); +void ST_Util_DrawBlock (BYTE *dest, const BYTE *src, int bytewidth, int height, int destpitch); +void ST_Util_ClearBlock (BYTE *dest, BYTE fill, int bytewidth, int height, int destpitch); +void ST_Util_InvalidateRect (HWND hwnd, BITMAPINFO *bitmap_info, int left, int top, int right, int bottom); +BYTE *ST_Util_LoadFont (const char *filename, int height); +void ST_Util_FreeFont (BYTE *font); +BITMAPINFO *ST_Util_AllocTextBitmap (const BYTE *font); +void ST_Util_DrawTextScreen (BITMAPINFO *bitmap_info, const BYTE *text_screen, const BYTE *font); +void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE charnum, BYTE attrib); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -91,10 +117,13 @@ static void ST_Hexen_Init (); static void ST_Hexen_Done (); static void ST_Hexen_Progress (); +static void ST_Heretic_Init (); +static void ST_Heretic_Progress (); + // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern HINSTANCE g_hInst; -extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen; +extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTitleWindow; extern void LayoutMainWindow (HWND hWnd, HWND pane); // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -107,19 +136,35 @@ void (*ST_NetMessage)(const char *format, ...); void (*ST_NetDone)(); bool (*ST_NetLoop)(bool (*timer_callback)(void *), void *userdata); -struct -{ - BITMAPINFOHEADER Header; - RGBQUAD Colors[16]; -} StartupBitmapInfo; -BYTE *StartupBitmapBits; +BITMAPINFO *StartupBitmap; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int MaxPos, CurPos, NotchPos; static int NetMaxPos, NetCurPos; static LRESULT NetMarqueeMode; -static RGBQUAD StartupPalette[16]; +static int ThermX, ThermY, ThermWidth, ThermHeight; + +static const RGBQUAD TextModePalette[16] = +{ + { 0, 0, 0, 0 }, // 0 black + { MD, 0, 0, 0 }, // 1 blue + { 0, MD, 0, 0 }, // 2 green + { MD, MD, 0, 0 }, // 3 cyan + { 0, 0, MD, 0 }, // 4 red + { MD, 0, MD, 0 }, // 5 magenta + { 0, MD, MD, 0 }, // 6 brown + { MD, MD, MD, 0 }, // 7 light gray + + { LO, LO, LO, 0 }, // 8 dark gray + { HI, LO, LO, 0 }, // 9 light blue + { LO, HI, LO, 0 }, // A light green + { HI, HI, LO, 0 }, // B light cyan + { LO, LO, HI, 0 }, // C light red + { HI, LO, HI, 0 }, // D light magenta + { LO, HI, HI, 0 }, // E yellow + { HI, HI, HI, 0 }, // F white +}; // Hexen's notch graphics, converted to chunky pixels. @@ -191,6 +236,10 @@ void ST_Init(int maxProgress) { ST_Hexen_Init (); } + else if (gameinfo.gametype == GAME_Heretic) + { + ST_Heretic_Init (); + } else { ST_Basic_Init (); @@ -494,20 +543,12 @@ static void ST_Hexen_Init () { int startup_lump = Wads.CheckNumForName ("STARTUP"); - if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 153648) + if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 153648 || !ST_Util_CreateStartupWindow()) { ST_Basic_Init (); return; } - StartupScreen = CreateWindowEx (WS_EX_NOPARENTNOTIFY, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, g_hInst, NULL); - if (StartupScreen == NULL) - { - ST_Basic_Init (); - return; - } - SetWindowLong (StartupScreen, GWL_ID, IDC_STATIC_STARTUP); - BYTE startup_screen[153648]; union { @@ -519,20 +560,9 @@ static void ST_Hexen_Init () color.rgbReserved = 0; - // Initialize the bitmap info header. - StartupBitmapInfo.Header.biSize = sizeof(BITMAPINFOHEADER); - StartupBitmapInfo.Header.biWidth = 640; - StartupBitmapInfo.Header.biHeight = 480; - StartupBitmapInfo.Header.biPlanes = 1; - StartupBitmapInfo.Header.biBitCount = 4; - StartupBitmapInfo.Header.biCompression = 0; - StartupBitmapInfo.Header.biSizeImage = 153600; - StartupBitmapInfo.Header.biXPelsPerMeter = 0; - StartupBitmapInfo.Header.biYPelsPerMeter = 0; - StartupBitmapInfo.Header.biClrUsed = 16; - StartupBitmapInfo.Header.biClrImportant = 16; + StartupBitmap = ST_Util_CreateBitmap (640, 480, 4); - // Initialize the bitmap header. + // Initialize the bitmap palette. for (int i = 0; i < 16; ++i) { color.rgbRed = startup_screen[i*3+0]; @@ -540,15 +570,15 @@ static void ST_Hexen_Init () color.rgbBlue = startup_screen[i*3+2]; // Convert from 6-bit per component to 8-bit per component. quad = (quad << 2) | ((quad >> 4) & 0x03030303); - StartupBitmapInfo.Colors[i] = color; + StartupBitmap->bmiColors[i] = color; } // 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. - StartupBitmapBits = new BYTE[640*480/2]; - ST_Util_PlanarToChunky4 (StartupBitmapBits, startup_screen + 48, 640, 480); + ST_Util_PlanarToChunky4 (ST_Util_BitsForBitmap(StartupBitmap), startup_screen + 48, 640, 480); + ST_Util_SizeWindowForBitmap (); LayoutMainWindow (Window, NULL); InvalidateRect (StartupScreen, NULL, TRUE); @@ -581,6 +611,11 @@ static void ST_Hexen_Done() DestroyWindow (StartupScreen); StartupScreen = NULL; } + if (StartupBitmap != NULL) + { + ST_Util_FreeBitmap (StartupBitmap); + StartupBitmap = NULL; + } } //========================================================================== @@ -594,7 +629,6 @@ static void ST_Hexen_Done() static void ST_Hexen_Progress() { int notch_pos, x, y; - RECT rect; if (CurPos < MaxPos) { @@ -606,13 +640,9 @@ static void ST_Hexen_Progress() { x = ST_PROGRESS_X + ST_NOTCH_WIDTH * NotchPos; y = ST_PROGRESS_Y; - ST_Util_DrawBlock (StartupBitmapBits + x / 2 + y * 320, NotchBits, ST_NOTCH_WIDTH / 2, ST_NOTCH_HEIGHT, 320); - GetClientRect (StartupScreen, &rect); - rect.left = x * rect.right / 640 - 1; - rect.top = y * rect.bottom / 480 - 1; - rect.right = (x + ST_NOTCH_WIDTH) * rect.right / 640 + 1; - rect.bottom = (y + ST_NOTCH_HEIGHT) * rect.bottom / 480 + 1; - InvalidateRect (StartupScreen, &rect, FALSE); + ST_Util_DrawBlock (ST_Util_BitsForBitmap(StartupBitmap) + x / 2 + y * 320, + NotchBits, ST_NOTCH_WIDTH / 2, ST_NOTCH_HEIGHT, 320); + ST_Util_InvalidateRect (StartupScreen, StartupBitmap, x, y, x + ST_NOTCH_WIDTH, y + ST_NOTCH_HEIGHT); } S_Sound (CHAN_BODY, "StartupTick", 1, ATTN_NONE); } @@ -620,6 +650,161 @@ static void ST_Hexen_Progress() I_GetEvent (); } +//========================================================================== +// +// ST_Heretic_Init +// +// Shows the Hexen startup screen. If the screen doesn't appear to be +// valid, it falls back to ST_Basic_Init. +// +// The loading screen is an 80x25 text screen with character data and +// attributes intermixed, which means it must be exactly 4000 bytes long. +// +//========================================================================== + +static void ST_Heretic_Init () +{ + int loading_lump = Wads.CheckNumForName ("LOADING"); + BYTE loading_screen[4000]; + BYTE *font; + + if (loading_lump < 0 || Wads.LumpLength (loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) + { + ST_Basic_Init (); + return; + } + + font = ST_Util_LoadFont (TEXT_FONT_NAME, TEXT_FONT_HEIGHT); + if (font == NULL) + { + DestroyWindow (StartupScreen); + ST_Basic_Init (); + return; + } + + Wads.ReadLump (loading_lump, loading_screen); + StartupBitmap = ST_Util_AllocTextBitmap (font); + ST_Util_DrawTextScreen (StartupBitmap, loading_screen, font); + ST_Util_FreeFont (font); + + ST_Util_SizeWindowForBitmap (); + LayoutMainWindow (Window, NULL); + InvalidateRect (StartupScreen, NULL, TRUE); + + ThermX = THERM_X * 4; + ThermY = THERM_Y * TEXT_FONT_HEIGHT; + ThermWidth = THERM_LEN * 4; + ThermHeight = TEXT_FONT_HEIGHT; + + ST_Done = ST_Hexen_Done; + ST_Progress = ST_Heretic_Progress; + ST_NetInit = ST_Basic_NetInit; + ST_NetProgress = ST_Basic_NetProgress; + ST_NetMessage = ST_Basic_NetMessage; + ST_NetDone = ST_Basic_NetDone; + ST_NetLoop = ST_Basic_NetLoop; +} + +//========================================================================== +// +// ST_Heretic_Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +static void ST_Heretic_Progress() +{ + int notch_pos; + + if (CurPos < MaxPos) + { + CurPos++; + notch_pos = (CurPos * ThermWidth) / MaxPos; + if (notch_pos != NotchPos && (!(notch_pos & 7) || CurPos == MaxPos)) + { // Time to draw another notch. + int left = NotchPos + ThermX; + int top = ThermY; + int right = notch_pos + ThermX; + int bottom = top + ThermHeight; + ST_Util_ClearBlock (ST_Util_BitsForBitmap(StartupBitmap) + left + top * 320, THERM_COLOR, right - left, bottom - top, 320); + ST_Util_InvalidateRect (StartupScreen, StartupBitmap, left*2, top, right*2, bottom); + NotchPos = notch_pos; + Sleep (20); + } + } + I_GetEvent (); +} + +//========================================================================== +// +// ST_Util_CreateStartupWindow +// +// Creates the static control that will draw the startup screen. +// +//========================================================================== + +bool ST_Util_CreateStartupWindow () +{ + StartupScreen = CreateWindowEx (WS_EX_NOPARENTNOTIFY, "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 draw 1:1. +// +//========================================================================== + +void ST_Util_SizeWindowForBitmap () +{ + DEVMODE displaysettings; + int w, h, cx, cy, x, y; + RECT rect; + + GetClientRect (GameTitleWindow, &rect); + w = StartupBitmap->bmiHeader.biWidth + GetSystemMetrics (SM_CXSIZEFRAME)*2; + h = StartupBitmap->bmiHeader.biHeight + rect.bottom + + GetSystemMetrics (SM_CYSIZEFRAME) * 2 + GetSystemMetrics (SM_CYCAPTION); + + // 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_PlanarToChunky4 @@ -692,3 +877,212 @@ void ST_Util_DrawBlock (BYTE *dest, const BYTE *src, int bytewidth, int height, } } } + +//========================================================================== +// +// ST_Util_ClearBlock +// +//========================================================================== + +void ST_Util_ClearBlock (BYTE *dest, BYTE fill, int bytewidth, int height, int destpitch) +{ + while (height > 0) + { + memset (dest, fill, bytewidth); + dest += destpitch; + height--; + } +} + +//========================================================================== +// +// ST_Util_CreateBitmap +// +// Creates a BITMAPINFOHEADER, RGBQUAD, and pixel data arranged +// consecutively in memory (in other words, a normal Windows BMP file). +// The BITMAPINFOHEADER will be filled in, and the caller must fill +// in the color and pixel data. +// +// You must pass 4 or 8 for color_bits. +// +//========================================================================== + +BITMAPINFO *ST_Util_CreateBitmap (int width, int height, int color_bits) +{ + DWORD size_image = (width * height) >> int(color_bits == 4); + BITMAPINFO *bitmap_info = (BITMAPINFO *)M_Malloc (sizeof(BITMAPINFOHEADER) + + (sizeof(RGBQUAD) << color_bits) + size_image); + + // Initialize the header. + bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmap_info->bmiHeader.biWidth = width; + bitmap_info->bmiHeader.biHeight = height; + bitmap_info->bmiHeader.biPlanes = 1; + bitmap_info->bmiHeader.biBitCount = color_bits; + bitmap_info->bmiHeader.biCompression = 0; + bitmap_info->bmiHeader.biSizeImage = size_image; + bitmap_info->bmiHeader.biXPelsPerMeter = 0; + bitmap_info->bmiHeader.biYPelsPerMeter = 0; + bitmap_info->bmiHeader.biClrUsed = 1 << color_bits; + bitmap_info->bmiHeader.biClrImportant = 0; + + return bitmap_info; +} + +//========================================================================== +// +// ST_Util_BitsForBitmap +// +// Given a bitmap created by ST_Util_CreateBitmap, returns the start +// address for the pixel data for the bitmap. +// +//========================================================================== + +BYTE *ST_Util_BitsForBitmap (BITMAPINFO *bitmap_info) +{ + return (BYTE *)bitmap_info + sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) << bitmap_info->bmiHeader.biBitCount); +} + +//========================================================================== +// +// ST_Util_FreeBitmap +// +// Frees all the data for a bitmap created by ST_Util_CreateBitmap. +// +//========================================================================== + +void ST_Util_FreeBitmap (BITMAPINFO *bitmap_info) +{ + free (bitmap_info); +} + +//========================================================================== +// +// 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); +} + +//========================================================================== +// +// ST_Util_LoadFont +// +// Loads a monochrome fixed-width font. Every character is one byte +// (eight pixels) wide. +// +//========================================================================== + +BYTE *ST_Util_LoadFont (const char *filename, int height) +{ + int lumpnum, lumplen; + BYTE *font; + + lumpnum = Wads.CheckNumForFullName (filename); + if (lumpnum < 0) + { // font not found + return NULL; + } + lumplen = Wads.LumpLength (lumpnum); + if (lumplen != height << 8) + { // font is a bad size + return NULL; + } + font = new BYTE[lumplen + 1]; + font[0] = height; // Store font height in the first byte. + Wads.ReadLump (lumpnum, font + 1); + return font; +} + +void ST_Util_FreeFont (BYTE *font) +{ + delete[] font; +} + +//========================================================================== +// +// ST_Util_AllocTextBitmap +// +// Returns a bitmap properly sized to hold an 80x25 display of characters +// using the specified font. +// +//========================================================================== + +BITMAPINFO *ST_Util_AllocTextBitmap (const BYTE *font) +{ + BITMAPINFO *bitmap = ST_Util_CreateBitmap (80 * 8, 25 * font[0], 4); + memcpy (bitmap->bmiColors, TextModePalette, sizeof(TextModePalette)); + return bitmap; +} + +//========================================================================== +// +// ST_Util_DrawTextScreen +// +// Draws the text screen to the bitmap. The bitmap must be the proper size +// for the font. +// +//========================================================================== + +void ST_Util_DrawTextScreen (BITMAPINFO *bitmap_info, const BYTE *text_screen, const BYTE *font) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + ST_Util_DrawChar (bitmap_info, font, x, y, 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. +// +//========================================================================== + +void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE charnum, BYTE attrib) +{ + const BYTE bg_left = attrib & 0xF0; + const BYTE fg = attrib & 0x0F; + const BYTE fg_left = fg << 4; + const BYTE bg = bg_left >> 4; + const BYTE color_array[4] = { bg_left | bg, attrib, fg_left | bg, fg_left | fg }; + const BYTE *src = font + 1 + charnum * font[0]; + int pitch = screen->bmiHeader.biWidth >> 1; + BYTE *dest = ST_Util_BitsForBitmap(screen) + x*4 + y * font[0] * pitch; + + for (y = font[0]; y > 0; --y) + { + BYTE srcbyte = *src++; + + // Pixels 0 and 1 + dest[0] = color_array[(srcbyte >> 6) & 3]; + // Pixels 2 and 3 + dest[1] = color_array[(srcbyte >> 4) & 3]; + // Pixels 4 and 5 + dest[2] = color_array[(srcbyte >> 2) & 3]; + // Pixels 6 and 7 + dest[3] = color_array[(srcbyte) & 3]; + dest += pitch; + } +} diff --git a/wadsrc/vga-rom.f14 b/wadsrc/vga-rom.f14 new file mode 100644 index 000000000..2c6d8bb12 Binary files /dev/null and b/wadsrc/vga-rom.f14 differ diff --git a/wadsrc/zdoom.lst b/wadsrc/zdoom.lst index ba0b7dbc3..45d8c5a3e 100644 --- a/wadsrc/zdoom.lst +++ b/wadsrc/zdoom.lst @@ -2,6 +2,8 @@ @zdoom.pk3 +vga-rom-font.14 vga-rom.f14 + graphics/invgemr2.lmp invgemr2.lmp graphics/invgemr1.lmp invgemr1.lmp graphics/invgeml2.lmp invgeml2.lmp