- Added simulation of Heretic's startup screen.

SVN r438 (trunk)
This commit is contained in:
Randy Heit 2007-01-06 04:08:24 +00:00
parent ec2e63c6d3
commit dbe2593500
8 changed files with 630 additions and 170 deletions

View File

@ -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.

View File

@ -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");

View File

@ -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 <SDL.h>
#include <unistd.h>
@ -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;

View File

@ -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
{

View File

@ -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 <assert.h>
// 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"

View File

@ -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;
}
}

BIN
wadsrc/vga-rom.f14 Normal file

Binary file not shown.

View File

@ -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