1999-02-21 00:00:00 +00:00
|
|
|
//**************************************************************************
|
|
|
|
//**
|
|
|
|
//** i_video.cpp: Low level DOOM graphics routines.
|
|
|
|
//** This version uses PTC. (Prometheus True Color)
|
|
|
|
//** NEW (1.17a): Support for DirectDraw is back!
|
|
|
|
//**
|
|
|
|
//** There are two reasons why I switched from DirectDraw to PTC:
|
|
|
|
//** 1. PTC makes windowed modes easy without any special work.
|
|
|
|
//** 2. PTC makes it easy to support *all* hi- and true-color modes.
|
|
|
|
//**
|
|
|
|
//**************************************************************************
|
|
|
|
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
|
|
#ifndef INITGUID
|
|
|
|
#define INITGUID
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <objbase.h>
|
|
|
|
#include <initguid.h>
|
|
|
|
#include <ddraw.h>
|
|
|
|
#include <mmsystem.h>
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
#include "ptc.h"
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
#define __BYTEBOOL__
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "c_dispch.h"
|
|
|
|
#include "c_consol.h"
|
|
|
|
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "i_input.h"
|
|
|
|
#include "i_video.h"
|
|
|
|
#include "v_video.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "d_main.h"
|
|
|
|
#include "m_alloc.h"
|
|
|
|
#include "c_consol.h"
|
|
|
|
#include "c_cvars.h"
|
|
|
|
#include "c_dispch.h"
|
|
|
|
#include "st_stuff.h"
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "z_zone.h"
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
|
|
|
|
#define true TRUE
|
|
|
|
#define false FALSE
|
|
|
|
|
|
|
|
// TYPES -------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct screenchain {
|
|
|
|
screen_t *scr;
|
|
|
|
struct screenchain *next;
|
|
|
|
} *chain;
|
|
|
|
|
|
|
|
typedef struct modelist_s {
|
|
|
|
modelist_s *next;
|
|
|
|
int width, height, bpp;
|
|
|
|
int id;
|
|
|
|
} modelist_t;
|
|
|
|
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
|
|
|
|
void I_StartModeIterator (int id);
|
|
|
|
BOOLI_NextMode (int *width, int *height);
|
|
|
|
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
|
|
|
|
struct player_s;
|
|
|
|
static void Cmd_Vid_DescribeModes (struct player_s*,int,char**);
|
|
|
|
static void Cmd_Vid_DescribeCurrentMode (struct player_s*,int,char**);
|
|
|
|
|
|
|
|
static void AddMode (int x, int y, int bpp, int id, modelist_t **lastmode);
|
|
|
|
static void FreeModes (void);
|
|
|
|
static void MakeModesList (void);
|
|
|
|
static char *GetFormatName (const int id);
|
|
|
|
static void ReinitPTC (char *iface);
|
|
|
|
static void refreshDisplay (void);
|
|
|
|
static void stretchChanged (cvar_t *var);
|
|
|
|
static void fullChanged (cvar_t *var);
|
|
|
|
|
|
|
|
static HRESULT WINAPI EnumDDModesCB (LPDDSURFACEDESC desc, void *modes);
|
|
|
|
static void InitDDraw (void);
|
|
|
|
static void NewDDMode (int width, int height);
|
|
|
|
|
|
|
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
extern HWND Window;
|
|
|
|
extern BOOL vidactive; // Checked to avoid annoying flashes on console
|
1999-02-21 00:00:00 +00:00
|
|
|
// during startup if developer is true
|
1998-07-14 00:00:00 +00:00
|
|
|
extern BOOL setmodeneeded;
|
1998-12-22 00:00:00 +00:00
|
|
|
extern int NewWidth, NewHeight, NewID;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
cvar_t *I_ShowFPS;
|
|
|
|
cvar_t *ticker;
|
1998-07-14 00:00:00 +00:00
|
|
|
cvar_t *win_stretchx;
|
|
|
|
cvar_t *win_stretchy;
|
|
|
|
cvar_t *fullscreen;
|
|
|
|
BOOL Fullscreen;
|
1999-02-21 00:00:00 +00:00
|
|
|
static modelist_t *IteratorMode;
|
|
|
|
static int IteratorID;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
char *IdStrings[22] = {
|
|
|
|
"ARGB8888",
|
|
|
|
"ABGR8888",
|
|
|
|
"BGRA8888",
|
|
|
|
"RGBA8888",
|
|
|
|
"RGB888",
|
|
|
|
"BGR888",
|
|
|
|
"RGB565",
|
|
|
|
"BGR565",
|
|
|
|
"ARGB1555",
|
|
|
|
"ABGR1555",
|
|
|
|
"INDEX8",
|
|
|
|
"FAKEMODE1A",
|
|
|
|
"FAKEMODE1B",
|
|
|
|
"FAKEMODE1C",
|
|
|
|
"FAKEMODE2A",
|
|
|
|
"FAKEMODE2B",
|
|
|
|
"FAKEMODE2C",
|
|
|
|
"FAKEMODE3A",
|
|
|
|
"FAKEMODE3B",
|
|
|
|
"FAKEMODE3C",
|
|
|
|
"GREY8",
|
|
|
|
"RGB332"
|
|
|
|
};
|
|
|
|
|
|
|
|
byte IdTobpp[22] = {
|
|
|
|
32, 32, 32, 32, 24, 24, 16, 16, 15, 15, 8,
|
|
|
|
18, 18, 18, 14, 14, 14, 12, 12, 12, 8, 8
|
|
|
|
};
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
int DisplayID;
|
|
|
|
int DisplayBPP; // Number of bits-per-pixel of output device
|
|
|
|
int DisplayWidth, DisplayHeight; // Display size
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
static modelist_t *Modes = NULL;
|
1999-02-21 00:00:00 +00:00
|
|
|
static char WindowedIFace[8];
|
|
|
|
static char FullscreenIFace[8];
|
|
|
|
static int nummodes = 0;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static struct CmdDispatcher VidCommands[] = {
|
|
|
|
{ "vid_currentmode", Cmd_Vid_DescribeCurrentMode },
|
|
|
|
{ "vid_listmodes", Cmd_Vid_DescribeModes },
|
|
|
|
{ NULL, }
|
|
|
|
};
|
1999-02-17 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
} // extern "C"
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static PTC ptc; // the PTC interface object
|
|
|
|
static Palette *DisPal; // the display palette
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static IDirectDraw *DDObj;
|
|
|
|
static LPDIRECTDRAWPALETTE DDPalette;
|
|
|
|
static LPDIRECTDRAWSURFACE DDPrimary;
|
|
|
|
static LPDIRECTDRAWSURFACE DDBack;
|
|
|
|
static int NeedPalChange;
|
|
|
|
static BOOL CalledCoInitialize;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static union {
|
|
|
|
PALETTEENTRY pe[256];
|
|
|
|
uint ui[256];
|
|
|
|
} PalEntries;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
extern "C" {
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// AddMode
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static void AddMode (int x, int y, int bpp, int id, modelist_t **lastmode)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
modelist_t *newmode = (modelist_t *)Z_Malloc (sizeof (modelist_t), PU_STATIC, 0);
|
|
|
|
|
|
|
|
nummodes++;
|
|
|
|
newmode->next = NULL;
|
|
|
|
newmode->width = x;
|
|
|
|
newmode->height = y;
|
|
|
|
newmode->bpp = bpp;
|
|
|
|
newmode->id = id;
|
|
|
|
|
|
|
|
(*lastmode)->next = newmode;
|
|
|
|
*lastmode = newmode;
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FreeModes
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void FreeModes (void)
|
|
|
|
{
|
|
|
|
modelist_t *mode = Modes, *tempmode;
|
|
|
|
|
|
|
|
while (mode)
|
|
|
|
{
|
|
|
|
tempmode = mode;
|
|
|
|
mode = mode->next;
|
|
|
|
Z_Free (tempmode);
|
|
|
|
}
|
|
|
|
Modes = NULL;
|
|
|
|
nummodes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// MakeModesList
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
static void MakeModesList (void)
|
|
|
|
{
|
|
|
|
modelist_t *lastmode = (modelist_t *)&Modes;
|
|
|
|
BOOL have320x200x8 = false, have320x240x8 = false;
|
|
|
|
|
|
|
|
// get ptc modelist
|
|
|
|
List<MODE> list;
|
|
|
|
ptc.GetModeList(list);
|
|
|
|
|
|
|
|
// modelist iterator
|
|
|
|
List<MODE>::Iterator iterator = list.first();
|
|
|
|
MODE *ptcmode = iterator.current();
|
|
|
|
|
|
|
|
while (ptcmode) {
|
|
|
|
if (ptcmode->output == WINDOWED) {
|
|
|
|
if (!WindowedIFace[0])
|
|
|
|
strncpy (WindowedIFace, ptcmode->i, 8);
|
|
|
|
} else {
|
|
|
|
if (!FullscreenIFace[0])
|
|
|
|
strncpy (FullscreenIFace, ptcmode->i, 8);
|
|
|
|
|
|
|
|
// Filter out modes taller than 1024 pixels since the
|
|
|
|
// assembly routines will choke on them. (Besides, they
|
|
|
|
// are really slow so why use them?)
|
1998-12-22 00:00:00 +00:00
|
|
|
if (ptcmode->y <= 1024 && ptcmode->format.id == INDEX8) {
|
1998-07-14 00:00:00 +00:00
|
|
|
nummodes++;
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
AddMode (ptcmode->x, ptcmode->y, ptcmode->format.bits,
|
|
|
|
ptcmode->format.id, &lastmode);
|
1998-07-14 00:00:00 +00:00
|
|
|
if (ptcmode->x == 320 && ptcmode->format.bits == 8) {
|
|
|
|
if (ptcmode->y == 200)
|
|
|
|
have320x200x8 = true;
|
|
|
|
else if (ptcmode->y == 240)
|
|
|
|
have320x240x8 = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ptcmode = iterator.next ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OSPlatform == os_Win95) {
|
|
|
|
// Windows 95 will let us use Mode X (assuming my PTC patch has been
|
|
|
|
// applied). If we didn't find any linear modes in the loop above,
|
|
|
|
// add the Mode X modes here.
|
|
|
|
|
|
|
|
if (!have320x200x8)
|
1999-02-21 00:00:00 +00:00
|
|
|
AddMode (320, 200, 8, INDEX8, &lastmode);
|
1998-07-14 00:00:00 +00:00
|
|
|
if (!have320x240x8)
|
1999-02-21 00:00:00 +00:00
|
|
|
AddMode (320, 240, 8, INDEX8, &lastmode);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// GetFormatName
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
static char *GetFormatName (const int id)
|
|
|
|
{
|
1998-12-22 00:00:00 +00:00
|
|
|
return IdStrings[id-1000];
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_ShutdownGraphics
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
void STACK_ARGS I_ShutdownGraphics (void)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
FreeModes ();
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
while (chain) {
|
|
|
|
I_FreeScreen (chain->scr);
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
if (DDPalette)
|
|
|
|
{
|
|
|
|
DDPalette->Release();
|
|
|
|
DDPalette = NULL;
|
|
|
|
}
|
|
|
|
if (DDPrimary)
|
|
|
|
{
|
|
|
|
DDPrimary->Release();
|
|
|
|
DDPrimary = NULL;
|
|
|
|
}
|
|
|
|
DDObj->Release();
|
|
|
|
DDObj = NULL;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1999-02-21 00:00:00 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (DisPal)
|
|
|
|
{
|
|
|
|
delete DisPal;
|
|
|
|
DisPal = NULL;
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
ptc.Close ();
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (CalledCoInitialize)
|
|
|
|
{
|
|
|
|
CoUninitialize ();
|
|
|
|
CalledCoInitialize = false;
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
//
|
|
|
|
// [RH] I_BeginUpdate
|
|
|
|
//
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_BeginUpdate (void)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
V_LockScreen (&screen);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
1998-12-22 00:00:00 +00:00
|
|
|
//
|
|
|
|
// I_FinishUpdateNoBlit
|
|
|
|
//
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
void I_FinishUpdateNoBlit (void)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
V_UnlockScreen (&screen);
|
1998-12-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
//
|
|
|
|
// I_FinishUpdate
|
|
|
|
//
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_FinishUpdate (void)
|
|
|
|
{
|
1999-02-17 00:00:00 +00:00
|
|
|
static int lasttic, lastms = 0, lastsec = 0;
|
|
|
|
static int framecount = 0, lastcount = 0;
|
1998-07-14 00:00:00 +00:00
|
|
|
int tics, ms;
|
|
|
|
int i;
|
1999-02-17 00:00:00 +00:00
|
|
|
int howlong;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
ms = timeGetTime ();
|
1999-02-17 00:00:00 +00:00
|
|
|
if ((howlong = ms - lastms) && I_ShowFPS->value) {
|
1998-07-14 00:00:00 +00:00
|
|
|
char fpsbuff[40];
|
|
|
|
int chars;
|
|
|
|
|
|
|
|
sprintf (fpsbuff, "%d ms (%d fps)",
|
1999-02-17 00:00:00 +00:00
|
|
|
howlong,
|
|
|
|
lastcount);
|
1998-07-14 00:00:00 +00:00
|
|
|
chars = strlen (fpsbuff);
|
1999-02-21 00:00:00 +00:00
|
|
|
V_Clear (0, screen.height - 8, chars * 8, screen.height, &screen, 0);
|
|
|
|
V_PrintStr (0, screen.height - 8, (byte *)&fpsbuff[0], chars);
|
1999-02-17 00:00:00 +00:00
|
|
|
if (lastsec != ms / 1000) {
|
|
|
|
lastcount = framecount;
|
|
|
|
framecount = 0;
|
|
|
|
lastsec = ms / 1000;
|
|
|
|
}
|
|
|
|
framecount++;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
lastms = ms;
|
|
|
|
|
|
|
|
// draws little dots on the bottom of the screen
|
1998-12-22 00:00:00 +00:00
|
|
|
if (ticker->value) {
|
1998-07-14 00:00:00 +00:00
|
|
|
i = I_GetTime();
|
|
|
|
tics = i - lasttic;
|
|
|
|
lasttic = i;
|
|
|
|
if (tics > 20) tics = 20;
|
|
|
|
|
|
|
|
for (i=0 ; i<tics*2 ; i+=2)
|
1999-02-21 00:00:00 +00:00
|
|
|
screen.buffer[(screen.height-1)*screen.pitch + i] = 0xff;
|
1998-07-14 00:00:00 +00:00
|
|
|
for ( ; i<20*2 ; i+=2)
|
1999-02-21 00:00:00 +00:00
|
|
|
screen.buffer[(screen.height-1)*screen.pitch + i] = 0x0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
// Using DirectDrawSurface's Blt method is horrendously slow.
|
|
|
|
// Using it to copy an 800x600 framebuffer to the back buffer is
|
|
|
|
// slower than using the following routine for a 960x720 surface.
|
|
|
|
|
|
|
|
HRESULT dderr;
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
|
|
|
|
memset (&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(DDSURFACEDESC);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dderr = DDBack->Lock (NULL, &ddsd, DDLOCK_WRITEONLY |
|
|
|
|
DDLOCK_SURFACEMEMORYPTR, NULL);
|
|
|
|
} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));
|
|
|
|
|
|
|
|
if (dderr == DDERR_SURFACELOST) {
|
|
|
|
dderr = DDPrimary->Restore ();
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dderr = DDBack->Lock (NULL, &ddsd, DDLOCK_WRITEONLY |
|
|
|
|
DDLOCK_SURFACEMEMORYPTR, NULL);
|
|
|
|
} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dderr == DD_OK) {
|
|
|
|
byte *to = (byte *)ddsd.lpSurface;
|
|
|
|
byte *from = screen.buffer;
|
|
|
|
int y;
|
|
|
|
|
|
|
|
if (ddsd.lPitch == screen.width && screen.width == screen.pitch) {
|
|
|
|
memcpy (to, from, screen.width * screen.height);
|
|
|
|
} else {
|
|
|
|
for (y = 0; y < screen.height; y++) {
|
|
|
|
memcpy (to, from, screen.width);
|
|
|
|
to += ddsd.lPitch;
|
|
|
|
from += screen.pitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dderr = DDBack->Unlock (ddsd.lpSurface);
|
|
|
|
} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));
|
|
|
|
}
|
|
|
|
|
|
|
|
V_UnlockScreen (&screen);
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
dderr = DDPrimary->Flip (NULL, DDFLIP_WAIT);
|
|
|
|
if (dderr == DDERR_SURFACELOST)
|
|
|
|
{
|
|
|
|
dderr = DDPrimary->Restore ();
|
|
|
|
if (dderr != DD_OK)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (dderr != DDERR_WASSTILLDRAWING)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedPalChange > 0)
|
|
|
|
{
|
|
|
|
NeedPalChange--;
|
|
|
|
DDPalette->SetEntries (0, 0, 256, PalEntries.pe);
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1999-02-21 00:00:00 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
V_UnlockScreen (&screen);
|
|
|
|
((Surface *)(screen.impdata))->Update ();
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (DisPal && NeedPalChange > 0)
|
|
|
|
{
|
|
|
|
uint *palentries;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (palentries = (uint *)DisPal->Lock ())
|
|
|
|
{
|
|
|
|
NeedPalChange--;
|
|
|
|
memcpy (palentries, PalEntries.ui, 256*sizeof(uint));
|
|
|
|
DisPal->Unlock ();
|
|
|
|
|
|
|
|
if (screen.is8bit)
|
|
|
|
((Surface *)(screen.impdata))->SetPalette (*DisPal);
|
|
|
|
|
|
|
|
// Only set the display palette if it is indexed color
|
|
|
|
FORMAT format = ptc.GetFormat ();
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (format.type == INDEXED && format.model != GREYSCALE)
|
|
|
|
ptc.SetPalette (*DisPal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
//
|
|
|
|
// I_ReadScreen
|
|
|
|
//
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_ReadScreen (byte *scr)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
int y;
|
1998-07-14 00:00:00 +00:00
|
|
|
byte *source;
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
V_LockScreen (&screen);
|
|
|
|
source = screen.buffer;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
for (y = 0; y < screen.height; y++)
|
|
|
|
{
|
|
|
|
memcpy (scr, source, screen.width);
|
|
|
|
scr += screen.width;
|
|
|
|
source += screen.pitch;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
V_UnlockScreen (&screen);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
//
|
|
|
|
// I_SetPalette
|
|
|
|
//
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_SetPalette (unsigned int *pal)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (!pal)
|
1998-07-14 00:00:00 +00:00
|
|
|
return;
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (DDPalette)
|
|
|
|
{
|
|
|
|
int i;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
{
|
|
|
|
PalEntries.pe[i].peRed = RPART(pal[i]);
|
|
|
|
PalEntries.pe[i].peGreen = GPART(pal[i]);
|
|
|
|
PalEntries.pe[i].peBlue = BPART(pal[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (PalEntries.ui, pal, 256*sizeof(uint));
|
|
|
|
}
|
|
|
|
NeedPalChange++;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ReinitPTC
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
static void ReinitPTC (char *iface)
|
|
|
|
{
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!ptc.Init (iface, (WINDOW)Window))
|
1998-07-14 00:00:00 +00:00
|
|
|
I_FatalError ("Could not reinitialize PTC");
|
1998-12-22 00:00:00 +00:00
|
|
|
#ifdef _DEBUG
|
1998-07-14 00:00:00 +00:00
|
|
|
// We don't want our priority class bumped up!
|
|
|
|
SetPriorityClass (GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
1998-12-22 00:00:00 +00:00
|
|
|
#endif
|
|
|
|
if (developer->value && vidactive)
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "PTC reinitialized to use %s\n\n", iface);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_SetMode
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
void I_SetMode (int width, int height, int id)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
DisplayWidth = width;
|
|
|
|
DisplayHeight = height;
|
1998-12-22 00:00:00 +00:00
|
|
|
DisplayID = id;
|
|
|
|
|
|
|
|
ShowWindow (Window, SW_SHOW);
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
NewDDMode (width, height);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1999-02-21 00:00:00 +00:00
|
|
|
else
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (Fullscreen)
|
|
|
|
{
|
|
|
|
if (!fullscreen->value)
|
|
|
|
{
|
|
|
|
Fullscreen = FALSE;
|
|
|
|
// Get out of fullscreen mode
|
|
|
|
ptc.Close ();
|
|
|
|
//ReinitPTC (WindowedIFace);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fullscreen->value)
|
|
|
|
{
|
|
|
|
Fullscreen = TRUE;
|
|
|
|
ReinitPTC (FullscreenIFace);
|
|
|
|
I_ResumeMouse (); // Make sure mouse pointer is grabbed.
|
|
|
|
}
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (Fullscreen)
|
|
|
|
{
|
|
|
|
ptc.SetMode (width, height, id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
width *= win_stretchx->value;
|
|
|
|
height *= win_stretchy->value;
|
|
|
|
|
|
|
|
height += GetSystemMetrics (SM_CYFIXEDFRAME) * 2 +
|
|
|
|
GetSystemMetrics (SM_CYCAPTION);
|
|
|
|
width += GetSystemMetrics (SM_CXFIXEDFRAME) * 2;
|
|
|
|
|
|
|
|
SetWindowPos (Window, NULL, 0, 0, width, height, SWP_DRAWFRAME|
|
|
|
|
SWP_NOACTIVATE|
|
|
|
|
SWP_NOCOPYBITS|
|
|
|
|
SWP_NOMOVE|
|
|
|
|
SWP_NOZORDER);
|
|
|
|
|
|
|
|
// Let PTC know about the new window size
|
|
|
|
ReinitPTC (WindowedIFace);
|
|
|
|
|
|
|
|
// If the menu is active, make sure the mouse is released.
|
|
|
|
if (menuactive || gamestate == GS_FULLCONSOLE)
|
|
|
|
I_PauseMouse ();
|
|
|
|
|
|
|
|
MODE mode = ptc.GetMode();
|
|
|
|
|
|
|
|
DisplayBPP = mode.format.bits;
|
|
|
|
if (developer->value && vidactive)
|
|
|
|
Printf (PRINT_HIGH, "Mode set: %dx%d (%s)\n", mode.x, mode.y,
|
|
|
|
IdStrings[DisplayID-1000]);
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// cheapo hack to make sure current display BPP is stored in screen
|
|
|
|
screen.Bpp = IdTobpp[DisplayID-1000] >> 3;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// refreshDisplay
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void refreshDisplay (void)
|
|
|
|
{
|
1998-07-14 00:00:00 +00:00
|
|
|
NewWidth = DisplayWidth;
|
|
|
|
NewHeight = DisplayHeight;
|
1998-12-22 00:00:00 +00:00
|
|
|
NewID = DisplayID;
|
1998-07-14 00:00:00 +00:00
|
|
|
setmodeneeded = true;
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// stretchChanged
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
static void stretchChanged (cvar_t *var)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (!Fullscreen && !DDObj)
|
1998-07-14 00:00:00 +00:00
|
|
|
refreshDisplay ();
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// fullChanged
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
static void fullChanged (cvar_t *var)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (!DDObj && Fullscreen != var->value)
|
1998-07-14 00:00:00 +00:00
|
|
|
refreshDisplay ();
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_InitGraphics
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
void I_InitGraphics (void)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
char num[8], *iface;
|
|
|
|
modelist_t *mode = (modelist_t *)&Modes;
|
1999-02-21 00:00:00 +00:00
|
|
|
cvar_t *vid_noptc;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
I_DetectOS ();
|
|
|
|
|
|
|
|
I_ShowFPS = cvar ("vid_fps", "0", 0);
|
1998-12-22 00:00:00 +00:00
|
|
|
num[0] = '0' + !!M_CheckParm ("-devparm");
|
|
|
|
num[1] = 0;
|
|
|
|
ticker = cvar ("ticker", num, 0);
|
1998-07-14 00:00:00 +00:00
|
|
|
win_stretchx = cvar ("win_stretchx", "1.0", CVAR_ARCHIVE|CVAR_CALLBACK);
|
|
|
|
win_stretchy = cvar ("win_stretchy", "1.0", CVAR_ARCHIVE|CVAR_CALLBACK);
|
|
|
|
fullscreen = cvar ("fullscreen", "1", CVAR_ARCHIVE|CVAR_CALLBACK);
|
1999-02-21 00:00:00 +00:00
|
|
|
vid_noptc = cvar ("vid_noptc", "0", CVAR_ARCHIVE);
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
Fullscreen = (BOOL)fullscreen->value;
|
|
|
|
|
|
|
|
win_stretchx->u.callback =
|
|
|
|
win_stretchy->u.callback = stretchChanged;
|
|
|
|
fullscreen->u.callback = fullChanged;
|
|
|
|
|
|
|
|
C_RegisterCommands (VidCommands);
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (vid_noptc->value || M_CheckParm ("-noptc"))
|
|
|
|
{
|
|
|
|
Printf_Bold ("Bypassing PTC\n");
|
|
|
|
InitDDraw ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MakeModesList ();
|
|
|
|
sprintf (num, "%d", nummodes);
|
|
|
|
cvar ("vid_nummodes", num, CVAR_NOSET);
|
|
|
|
|
|
|
|
if (Fullscreen)
|
|
|
|
iface = FullscreenIFace;
|
|
|
|
else
|
|
|
|
iface = WindowedIFace;
|
|
|
|
|
|
|
|
if (!ptc.Init (iface, Window))
|
|
|
|
{
|
|
|
|
Printf_Bold ("Failed to initialize PTC. You won't be\n");
|
|
|
|
Printf_Bold ("able to play in a window. (Terrible, huh?)\n");
|
|
|
|
InitDDraw ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
|
|
// We don't want our priority class bumped up!
|
|
|
|
SetPriorityClass (GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
|
|
|
#endif
|
|
|
|
if (!(DisPal = new Palette))
|
|
|
|
{
|
|
|
|
FreeModes ();
|
|
|
|
I_FatalError ("Could not create palette");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
atexit (I_ShutdownGraphics);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// InitDDraw
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void InitDDraw (void)
|
|
|
|
{
|
|
|
|
modelist_t *lastmode = (modelist_t *)&Modes;
|
|
|
|
HRESULT dderr;
|
|
|
|
char num[8];
|
|
|
|
|
|
|
|
CoInitialize (NULL);
|
|
|
|
CalledCoInitialize = true;
|
|
|
|
|
|
|
|
dderr = CoCreateInstance (CLSID_DirectDraw, 0, CLSCTX_INPROC_SERVER,
|
|
|
|
IID_IDirectDraw, (void **)&DDObj);
|
|
|
|
|
|
|
|
if (FAILED(dderr))
|
|
|
|
I_FatalError ("Could not create DirectDraw object: %x", dderr);
|
|
|
|
|
|
|
|
dderr = DDObj->Initialize (0);
|
|
|
|
if (FAILED(dderr))
|
|
|
|
{
|
|
|
|
DDObj->Release ();
|
|
|
|
I_FatalError ("Could not initialize DirectDraw object");
|
|
|
|
}
|
|
|
|
|
|
|
|
dderr = DDObj->SetCooperativeLevel (Window, DDSCL_EXCLUSIVE |
|
|
|
|
DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX);
|
|
|
|
if (FAILED(dderr))
|
|
|
|
{
|
|
|
|
DDObj->Release ();
|
|
|
|
I_FatalError ("Could not set cooperative level: %x", dderr);
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeModes ();
|
|
|
|
dderr = DDObj->EnumDisplayModes (0, NULL, &lastmode, EnumDDModesCB);
|
|
|
|
if (FAILED(dderr))
|
|
|
|
{
|
|
|
|
DDObj->Release ();
|
|
|
|
I_FatalError ("Could not enumerate display modes: %x", dderr);
|
|
|
|
}
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
sprintf (num, "%d", nummodes);
|
1999-02-21 00:00:00 +00:00
|
|
|
cvar_forceset ("vid_nummodes", num);
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// EnumDDModesCallback
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static HRESULT WINAPI EnumDDModesCB (LPDDSURFACEDESC desc, void *modes)
|
|
|
|
{
|
|
|
|
if (desc->ddpfPixelFormat.dwRGBBitCount == 8 &&
|
|
|
|
desc->dwHeight <= 1024)
|
|
|
|
{
|
|
|
|
nummodes++;
|
|
|
|
AddMode (desc->dwWidth, desc->dwHeight, 8, INDEX8, (modelist_t **)modes);
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
return DDENUMRET_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// NewDDMode
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
static void NewDDMode (int width, int height)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
DDSCAPS ddscaps;
|
|
|
|
HRESULT err;
|
|
|
|
|
|
|
|
err = DDObj->SetDisplayMode (width, height, 8);
|
|
|
|
if (err != DD_OK)
|
|
|
|
I_FatalError ("Could not set display mode: %x", err);
|
|
|
|
|
|
|
|
if (DDPrimary) DDPrimary->Release(), DDPrimary = NULL;
|
|
|
|
if (DDPalette) DDPalette->Release(), DDPalette = NULL;
|
|
|
|
|
|
|
|
memset (&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
|
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
|
|
|
|
DDSCAPS_FLIP |
|
|
|
|
DDSCAPS_COMPLEX |
|
|
|
|
DDSCAPS_VIDEOMEMORY;
|
|
|
|
ddsd.dwBackBufferCount = 2;
|
|
|
|
|
|
|
|
// try to get a triple buffered video memory surface.
|
|
|
|
err = DDObj->CreateSurface (&ddsd, &DDPrimary, NULL);
|
|
|
|
|
|
|
|
if (err != DD_OK)
|
|
|
|
{
|
|
|
|
// try to get a double buffered video memory surface.
|
|
|
|
ddsd.dwBackBufferCount = 1;
|
|
|
|
err = DDObj->CreateSurface (&ddsd, &DDPrimary, NULL);
|
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (err != DD_OK)
|
|
|
|
{
|
|
|
|
// settle for a main memory surface.
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
|
|
err = DDObj->CreateSurface (&ddsd, &DDPrimary, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
Printf_Bold ("%s-buffering\n", ddsd.dwBackBufferCount == 2 ? "triple" : "double");
|
|
|
|
|
|
|
|
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
|
|
|
err = DDPrimary->GetAttachedSurface (&ddscaps, &DDBack);
|
|
|
|
if (err != DD_OK)
|
|
|
|
I_FatalError ("Could not get back buffer: %x", err);
|
|
|
|
|
|
|
|
err = DDObj->CreatePalette (DDPCAPS_8BIT|DDPCAPS_ALLOW256, PalEntries.pe,
|
|
|
|
&DDPalette, NULL);
|
|
|
|
if (err != DD_OK)
|
|
|
|
I_FatalError ("Could not create palette: %x", err);
|
|
|
|
DDPrimary->SetPalette (DDPalette);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_CheckResolution
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
BOOL I_CheckResolution (int width, int height, int id)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
modelist_t *mode = Modes;
|
|
|
|
|
|
|
|
while (mode) {
|
1998-12-22 00:00:00 +00:00
|
|
|
if (mode->width == width && mode->height == height && mode->id == id)
|
1998-07-14 00:00:00 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
mode = mode->next;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_StartModeIteratior
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
void I_StartModeIterator (int id)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
IteratorMode = Modes;
|
1998-12-22 00:00:00 +00:00
|
|
|
IteratorID = id;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_NextMode
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
BOOL I_NextMode (int *width, int *height)
|
|
|
|
{
|
|
|
|
if (IteratorMode) {
|
1998-12-22 00:00:00 +00:00
|
|
|
while (IteratorMode && IteratorMode->id != IteratorID)
|
1998-07-14 00:00:00 +00:00
|
|
|
IteratorMode = IteratorMode->next;
|
|
|
|
|
|
|
|
if (IteratorMode) {
|
|
|
|
*width = IteratorMode->width;
|
|
|
|
*height = IteratorMode->height;
|
|
|
|
IteratorMode = IteratorMode->next;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Cmd_Vid_DescribeModes
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void Cmd_Vid_DescribeModes (struct player_s *p, int c, char **v)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
|
|
|
modelist_t *mode = Modes;
|
|
|
|
|
|
|
|
while (mode)
|
|
|
|
{
|
|
|
|
// print accumulated mode info
|
1999-02-17 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "%4dx%-4d %2dbit %10s\n",
|
1998-07-14 00:00:00 +00:00
|
|
|
mode->width,
|
|
|
|
mode->height,
|
|
|
|
mode->bpp,
|
1998-12-22 00:00:00 +00:00
|
|
|
IdStrings[mode->id-1000]);
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
// go to next mode
|
|
|
|
mode = mode->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Cmd_Vid_DescribeCurrentMode
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1999-02-17 00:00:00 +00:00
|
|
|
void Cmd_Vid_DescribeCurrentMode (struct player_s *p, int c, char **v)
|
1998-07-14 00:00:00 +00:00
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
Printf (PRINT_HIGH, "%dx%d (%s)\n", screen.width, screen.height,
|
|
|
|
IdStrings[DisplayID-1000]);
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_AllocateScreen
|
|
|
|
//
|
|
|
|
//==========================================================================
|
1998-07-14 00:00:00 +00:00
|
|
|
|
|
|
|
BOOL I_AllocateScreen (screen_t *scrn, int width, int height, int Bpp)
|
|
|
|
{
|
|
|
|
if (scrn->impdata)
|
|
|
|
I_FreeScreen (scrn);
|
|
|
|
|
|
|
|
scrn->width = width;
|
|
|
|
scrn->height = height;
|
|
|
|
scrn->is8bit = (Bpp == 8) ? true : false;
|
|
|
|
scrn->lockcount = 0;
|
1998-12-22 00:00:00 +00:00
|
|
|
scrn->Bpp = IdTobpp[DisplayID-1000] >> 3;
|
1998-07-14 00:00:00 +00:00
|
|
|
scrn->palette = NULL;
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
HRESULT dderr;
|
|
|
|
LPDIRECTDRAWSURFACE surface;
|
|
|
|
|
|
|
|
if (!scrn->is8bit)
|
|
|
|
I_FatalError ("Only 8-bit screens are supported");
|
|
|
|
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
|
|
ddsd.dwWidth = width;
|
|
|
|
ddsd.dwHeight = height;
|
|
|
|
|
|
|
|
dderr = DDObj->CreateSurface (&ddsd, &surface, NULL);
|
|
|
|
if (SUCCEEDED(dderr))
|
|
|
|
{
|
|
|
|
screenchain *tracer = (screenchain *)Malloc (sizeof(*tracer));
|
|
|
|
|
|
|
|
scrn->impdata = surface;
|
|
|
|
tracer->scr = scrn;
|
|
|
|
tracer->next = chain;
|
|
|
|
chain = tracer;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
else
|
1999-02-21 00:00:00 +00:00
|
|
|
{
|
|
|
|
Surface *surface;
|
|
|
|
|
|
|
|
if (scrn == &screen)
|
|
|
|
surface = new Surface (ptc, width, height, (Bpp == 8) ? INDEX8 : ARGB8888);
|
|
|
|
else
|
|
|
|
surface = new Surface (width, height, (Bpp == 8) ? INDEX8 : ARGB8888);
|
|
|
|
|
|
|
|
if (surface)
|
|
|
|
{
|
|
|
|
screenchain *tracer = (screenchain *)Malloc (sizeof(*tracer));
|
|
|
|
|
|
|
|
scrn->impdata = surface;
|
|
|
|
tracer->scr = scrn;
|
|
|
|
tracer->next = chain;
|
|
|
|
chain = tracer;
|
|
|
|
|
|
|
|
if (developer->value && vidactive)
|
|
|
|
{
|
|
|
|
Printf_Bold ("Allocated new surface. (%dx%dx%d)\n",
|
|
|
|
surface->GetWidth (),
|
|
|
|
surface->GetHeight (),
|
|
|
|
surface->GetBitsPerPixel ());
|
|
|
|
Printf (PRINT_HIGH, "Orientation: %d\n", surface->GetOrientation ());
|
|
|
|
Printf (PRINT_HIGH, "Layout: %d\n", surface->GetLayout ());
|
|
|
|
Printf (PRINT_HIGH, "Advance: %d\n", surface->GetAdvance ());
|
|
|
|
Printf (PRINT_HIGH, "Pitch: %d\n", surface->GetPitch ());
|
|
|
|
Printf (PRINT_HIGH, "Format: %s\n\n", GetFormatName ((surface->GetFormat ()).id));
|
|
|
|
}
|
|
|
|
return true;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
1999-02-21 00:00:00 +00:00
|
|
|
return false;
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_FreeScreen
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_FreeScreen (screen_t *scrn)
|
|
|
|
{
|
|
|
|
struct screenchain *thisone, *prev;
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (scrn->impdata)
|
|
|
|
{
|
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
// Make sure the surface is unlocked
|
|
|
|
if (scrn->lockcount)
|
|
|
|
((LPDIRECTDRAWSURFACE)(scrn->impdata))->Unlock (NULL);
|
|
|
|
|
|
|
|
((LPDIRECTDRAWSURFACE)(scrn->impdata))->Release ();
|
|
|
|
scrn->impdata = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Make sure the surface is unlocked
|
|
|
|
if (scrn->lockcount)
|
|
|
|
((Surface *)(scrn->impdata))->Unlock ();
|
|
|
|
|
|
|
|
delete (Surface *)(scrn->impdata);
|
|
|
|
scrn->impdata = NULL;
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
V_DetachPalette (scrn);
|
|
|
|
|
|
|
|
thisone = chain;
|
|
|
|
prev = NULL;
|
|
|
|
while (thisone) {
|
|
|
|
if (thisone->scr == scrn) {
|
|
|
|
if (prev) {
|
|
|
|
prev->next = thisone->next;
|
|
|
|
} else {
|
|
|
|
chain = thisone->next;
|
|
|
|
}
|
|
|
|
free (thisone);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
prev = thisone;
|
|
|
|
thisone = thisone->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_LockScreen
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_LockScreen (screen_t *scrn)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (scrn->impdata)
|
|
|
|
{
|
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC ddsd;
|
|
|
|
HRESULT dderr;
|
|
|
|
|
|
|
|
memset (&ddsd, 0, sizeof(ddsd));
|
|
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
|
|
do
|
|
|
|
{
|
|
|
|
dderr = ((LPDIRECTDRAWSURFACE)(scrn->impdata))->Lock (NULL,
|
|
|
|
&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
|
|
|
|
} while (dderr == DDERR_SURFACEBUSY || dderr == DDERR_WASSTILLDRAWING);
|
|
|
|
|
|
|
|
// the surface is always in system memory, so it should never be lost
|
|
|
|
if (FAILED(dderr))
|
|
|
|
I_FatalError ("Could not lock surface: %x", dderr);
|
|
|
|
|
|
|
|
scrn->buffer = (byte *)ddsd.lpSurface;
|
|
|
|
scrn->pitch = ddsd.lPitch;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scrn->buffer = (byte *)((Surface *)(scrn->impdata))->Lock ();
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
if (scrn->buffer == NULL)
|
|
|
|
I_FatalError ("Could not lock surface");
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
scrn->pitch = ((Surface *)(scrn->impdata))->GetPitch ();
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
} else {
|
|
|
|
scrn->lockcount--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_UnlockScreen
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_UnlockScreen (screen_t *scrn)
|
|
|
|
{
|
1999-02-21 00:00:00 +00:00
|
|
|
if (scrn->impdata)
|
|
|
|
{
|
|
|
|
if (DDObj)
|
|
|
|
{
|
|
|
|
((LPDIRECTDRAWSURFACE)(scrn->impdata))->Unlock (scrn->buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
((Surface *)(scrn->impdata))->Unlock ();
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
scrn->buffer = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// I_Blit
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
1998-07-14 00:00:00 +00:00
|
|
|
void I_Blit (screen_t *src, int srcx, int srcy, int srcwidth, int srcheight,
|
|
|
|
screen_t *dest, int destx, int desty, int destwidth, int destheight)
|
|
|
|
{
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!src->impdata || !dest->impdata)
|
|
|
|
return;
|
1998-07-14 00:00:00 +00:00
|
|
|
/*
|
|
|
|
Funny problem with calling BitBlt() here. The more I do, the slower it gets.
|
|
|
|
It also doesn't give me quite the right dimensions. (?) For now, I just do
|
|
|
|
the conversion and copying myself.
|
1998-12-22 00:00:00 +00:00
|
|
|
*/
|
|
|
|
#if 0
|
|
|
|
RECTANGLE srcrect (srcx, srcy, srcx + srcwidth, srcy + srcheight);
|
|
|
|
RECTANGLE destrect (destx, desty, destx + destwidth, desty + destheight);
|
|
|
|
|
|
|
|
((Surface *)(src->impdata))->BitBlt (*(Surface *)(dest->impdata),
|
|
|
|
srcrect, destrect);
|
|
|
|
#else
|
|
|
|
fixed_t fracxstep, fracystep;
|
|
|
|
fixed_t fracx, fracy;
|
|
|
|
int x, y;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!src->lockcount)
|
|
|
|
I_LockScreen (src);
|
|
|
|
if (!dest->lockcount)
|
|
|
|
I_LockScreen (dest);
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
fracy = srcy << FRACBITS;
|
|
|
|
fracystep = (srcheight << FRACBITS) / destheight;
|
|
|
|
fracxstep = (srcwidth << FRACBITS) / destwidth;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (src->is8bit == dest->is8bit) {
|
|
|
|
// INDEX8 -> INDEX8 or ARGB8888 -> ARGB8888
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
byte *destline, *srcline;
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (!dest->is8bit) {
|
|
|
|
destwidth <<= 2;
|
|
|
|
srcwidth <<= 2;
|
|
|
|
srcx <<= 2;
|
|
|
|
destx <<= 2;
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
if (fracxstep == FRACUNIT) {
|
|
|
|
for (y = desty; y < desty + destheight; y++, fracy += fracystep) {
|
|
|
|
memcpy (dest->buffer + y * dest->pitch + destx,
|
|
|
|
src->buffer + (fracy >> FRACBITS) * src->pitch + srcx,
|
|
|
|
destwidth);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (y = desty; y < desty + destheight; y++, fracy += fracystep) {
|
|
|
|
srcline = src->buffer + (fracy >> FRACBITS) * src->pitch + srcx;
|
|
|
|
destline = dest->buffer + y * dest->pitch + destx;
|
|
|
|
for (x = fracx = 0; x < destwidth; x++, fracx += fracxstep) {
|
|
|
|
destline[x] = srcline[fracx >> FRACBITS];
|
|
|
|
}
|
|
|
|
}
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
} else if (!src->is8bit && dest->is8bit) {
|
|
|
|
// ARGB8888 -> INDEX8
|
|
|
|
I_FatalError ("Can't I_Blit() an ARGB8888 source to\nan INDEX8 destination");
|
|
|
|
} else {
|
|
|
|
// INDEX8 -> ARGB8888 (Palette set in V_Palette)
|
|
|
|
uint *destline;
|
|
|
|
byte *srcline;
|
|
|
|
|
|
|
|
if (fracxstep == FRACUNIT) {
|
|
|
|
// No X-scaling
|
|
|
|
for (y = desty; y < desty + destheight; y++, fracy += fracystep) {
|
|
|
|
srcline = src->buffer + (fracy >> FRACBITS) * src->pitch + srcx;
|
|
|
|
destline = (uint *)(dest->buffer + y * dest->pitch) + destx;
|
|
|
|
for (x = 0; x < destwidth; x++) {
|
|
|
|
destline[x] = V_Palette[srcline[x]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// With X-scaling
|
|
|
|
for (y = desty; y < desty + destheight; y++, fracy += fracystep) {
|
|
|
|
srcline = src->buffer + (fracy >> FRACBITS) * src->pitch + srcx;
|
|
|
|
destline = (uint *)(dest->buffer + y * dest->pitch) + destx;
|
|
|
|
for (x = fracx = 0; x < destwidth; x++, fracx += fracxstep) {
|
|
|
|
destline[x] = V_Palette[srcline[fracx >> FRACBITS]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!src->lockcount)
|
|
|
|
I_UnlockScreen (src);
|
|
|
|
if (!dest->lockcount)
|
|
|
|
I_UnlockScreen (dest);
|
|
|
|
#endif
|
1998-07-14 00:00:00 +00:00
|
|
|
}
|
1998-12-22 00:00:00 +00:00
|
|
|
|
1999-02-21 00:00:00 +00:00
|
|
|
// NON-PTC DIRECTDRAW STUFF FOLLOWS ----------------------------------------
|
|
|
|
|
|
|
|
|
1998-12-22 00:00:00 +00:00
|
|
|
} // extern "C"
|