mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-12 07:50:53 +02:00
368 lines
10 KiB
C++
368 lines
10 KiB
C++
//******************************************************************
|
|
// dx.cpp
|
|
//******************************************************************
|
|
|
|
|
|
#include "diablo.h"
|
|
#pragma hdrstop
|
|
#include "storm/h/storm.h"
|
|
#include "palette.h"
|
|
#include "engine.h"
|
|
#include "resource.h"
|
|
#include "gendung.h"
|
|
|
|
|
|
//******************************************************************
|
|
// extern
|
|
//******************************************************************
|
|
void myDebugBreak();
|
|
void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine);
|
|
|
|
|
|
//******************************************************************
|
|
// public
|
|
//******************************************************************
|
|
BYTE * gpBuffer;
|
|
LPDIRECTDRAW lpDD; // DirectDraw object
|
|
LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary surface
|
|
LPDIRECTDRAWSURFACE lpDDSBackBuf; // optional back buffer
|
|
LPDIRECTDRAWPALETTE lpDDPal; // DirectDraw palette
|
|
BYTE gbForceBackBuf = FALSE;
|
|
BYTE gbUseDDEmulation = FALSE;
|
|
|
|
|
|
//******************************************************************
|
|
// private
|
|
//******************************************************************
|
|
static DWORD sgdwLockCount;
|
|
static CCritSect sgDrawCrit;
|
|
static BYTE * sgpBackBuf;
|
|
static HINSTANCE sghDDlib = NULL;
|
|
|
|
#ifndef NDEBUG
|
|
static DWORD sgdwLockTbl[256];
|
|
#endif
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
static void init_backbuf() {
|
|
app_assert(! gpBuffer);
|
|
app_assert(! sgdwLockCount);
|
|
app_assert(! sgpBackBuf);
|
|
|
|
// can we lock the primary surface?
|
|
DDSCAPS caps;
|
|
DDSURFACEDESC ddsd;
|
|
app_assert(lpDDSPrimary);
|
|
HRESULT ddrval = lpDDSPrimary->GetCaps(&caps);
|
|
ddraw_assert(ddrval);
|
|
app_assert(caps.dwCaps & DDSCAPS_PRIMARYSURFACE);
|
|
|
|
// is this a lockable surface?
|
|
extern BYTE gbForceBackBuf;
|
|
if (! gbForceBackBuf) {
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddrval = lpDDSPrimary->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_WRITEONLY,NULL);
|
|
if (ddrval == DD_OK) {
|
|
ddrval = lpDDSPrimary->Unlock(NULL);
|
|
// pjw.patch1.start.1/13/97
|
|
// commented out -- in NT it is possible to
|
|
// lose a video surface while it is locked
|
|
// ddraw_assert(ddrval);
|
|
// pjw.patch1.end.1/13/97
|
|
|
|
// surface is lockable, just create an offscreen memory buffer
|
|
sgpBackBuf = DiabloAllocPtrSig(BUFFERSIZE,'OFFS');
|
|
return;
|
|
}
|
|
// non-lockable surface?
|
|
if (ddrval != DDERR_CANTLOCKSURFACE)
|
|
ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
}
|
|
|
|
// create a secondary surface and lock it permanently
|
|
ZeroMemory(&ddsd,sizeof(ddsd));
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
ddsd.dwHeight = BUFFERY;
|
|
ddsd.dwWidth = BUFFERX;
|
|
ddsd.lPitch = BUFFERX;
|
|
ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
|
|
ddrval = lpDDSPrimary->GetPixelFormat(&ddsd.ddpfPixelFormat);
|
|
if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
ddrval = lpDD->CreateSurface(&ddsd,&lpDDSBackBuf,NULL);
|
|
if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
static void init_primary() {
|
|
DDSURFACEDESC ddsd;
|
|
ZeroMemory(&ddsd, sizeof(ddsd));
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
ddsd.dwFlags = DDSD_CAPS;
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL);
|
|
if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
static HRESULT InDirectDrawCreate(
|
|
GUID * lpGUID,
|
|
LPDIRECTDRAW * lplpDD,
|
|
IUnknown * pUnkOuter
|
|
) {
|
|
// bind to DirectDrawCreate
|
|
typedef HRESULT (WINAPI * DDCREATETYPE)(GUID *,LPDIRECTDRAW *,IUnknown *);
|
|
DDCREATETYPE ddcreatefunc = (DDCREATETYPE)SDirectDrawCreate;
|
|
if (! ddcreatefunc) ErrorDlg(IDD_DDRAW_DLL_ERR,GetLastError(),__FILE__,__LINE__);
|
|
|
|
// call DirectDrawCreate
|
|
return ddcreatefunc(lpGUID,lplpDD,pUnkOuter);
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
void init_directx(HWND hWnd) {
|
|
HRESULT ddrval;
|
|
app_assert(! gpBuffer);
|
|
app_assert(! sgdwLockCount);
|
|
app_assert(! sgpBackBuf);
|
|
|
|
SetFocus(hWnd);
|
|
ShowWindow(hWnd,SW_SHOWNORMAL);
|
|
|
|
extern BYTE gbUseDDEmulation;
|
|
GUID * lpGUID = NULL;
|
|
if (gbUseDDEmulation) lpGUID = (GUID *) DDCREATE_EMULATIONONLY;
|
|
ddrval = InDirectDrawCreate(lpGUID,&lpDD,NULL);
|
|
if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
|
|
#if !ALLOW_WINDOWED_MODE
|
|
fullscreen = TRUE;
|
|
#endif
|
|
|
|
#if ALLOW_WINDOWED_MODE
|
|
if (!fullscreen) {
|
|
ddrval = lpDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL | DDSCL_ALLOWREBOOT);
|
|
if (ddrval == DDERR_EXCLUSIVEMODEALREADYSET) myDebugBreak();
|
|
else if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
|
|
// turn off "topmost" flag so that we don't stick above debugger
|
|
SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
|
|
}
|
|
else {
|
|
#endif
|
|
// Get exclusive mode
|
|
ddrval = lpDD->SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
|
|
if (ddrval == DDERR_EXCLUSIVEMODEALREADYSET) myDebugBreak();
|
|
else if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
|
|
// Set the video mode to 640x480x8
|
|
ddrval = lpDD->SetDisplayMode( 640, 480, 8);
|
|
// pjw.patch1.start.1/13/97
|
|
// some notebook computers can't switch resolutions -- but
|
|
// we should be able to switch the color depth to 256 ???
|
|
if (ddrval != DD_OK) {
|
|
int nWdt = GetSystemMetrics(SM_CXSCREEN);
|
|
int nHgt = GetSystemMetrics(SM_CYSCREEN);
|
|
ddrval = lpDD->SetDisplayMode(nWdt, nHgt, 8);
|
|
}
|
|
// pjw.patch1.end.1/13/97
|
|
if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__);
|
|
|
|
#if ALLOW_WINDOWED_MODE
|
|
}
|
|
#endif
|
|
|
|
init_primary();
|
|
|
|
CreatePalette();
|
|
|
|
// Do not allow gdi batching
|
|
GdiSetBatchLimit(1);
|
|
|
|
// Get the full offscreen buffer including edges
|
|
init_backbuf();
|
|
|
|
// inform STORM library of our DirectDraw objects
|
|
BOOL bSuccess = SDrawManualInitialize(
|
|
hWnd, // window
|
|
lpDD, // direct draw
|
|
lpDDSPrimary, // primary
|
|
NULL, // secondary
|
|
NULL, // system
|
|
lpDDSBackBuf, // temporary
|
|
lpDDPal, // palette
|
|
NULL // gdi palette
|
|
);
|
|
app_assert(bSuccess);
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
static void lock_buf_priv() {
|
|
// don't allow any other threads access to the draw
|
|
// buffer while we have it locked
|
|
sgDrawCrit.Enter();
|
|
|
|
if (sgpBackBuf) {
|
|
gpBuffer = sgpBackBuf;
|
|
}
|
|
else if (! lpDDSBackBuf) {
|
|
// if the back buffer was destroyed by another thread
|
|
// it is because it is fataling...give it a chance to
|
|
// shut down the system before performing our own fatal
|
|
Sleep(20000);
|
|
app_fatal("lock_buf_priv");
|
|
}
|
|
else if (! sgdwLockCount) {
|
|
DDSURFACEDESC ddsd;
|
|
ddsd.dwSize = sizeof(ddsd);
|
|
HRESULT ddrval = lpDDSBackBuf->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL);
|
|
ddraw_assert(ddrval);
|
|
gpBuffer = (BYTE *) ddsd.lpSurface;
|
|
app_assert(gpBuffer);
|
|
glClipY += (long) gpBuffer;
|
|
}
|
|
|
|
// increment lock count
|
|
sgdwLockCount++;
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
void lock_buf(BYTE bFcn) {
|
|
// for debugging -- make sure no lock count over/underflow
|
|
#ifndef NDEBUG
|
|
sgdwLockTbl[bFcn]++;
|
|
#endif
|
|
|
|
lock_buf_priv();
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
static void unlock_buf_priv() {
|
|
if (! sgdwLockCount) app_fatal("draw main unlock error");
|
|
if (! gpBuffer) app_fatal("draw consistency error");
|
|
if (! sgpBackBuf) app_assert(lpDDSBackBuf);
|
|
|
|
// decrement lock count
|
|
sgdwLockCount--;
|
|
|
|
if (! sgdwLockCount) {
|
|
glClipY -= (long) gpBuffer;
|
|
gpBuffer = NULL;
|
|
if (! sgpBackBuf) {
|
|
HRESULT ddrval = lpDDSBackBuf->Unlock(NULL);
|
|
ddraw_assert(ddrval);
|
|
}
|
|
}
|
|
|
|
sgDrawCrit.Leave();
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
void unlock_buf(BYTE bFcn) {
|
|
// for debugging -- make sure no lock count over/underflow
|
|
#ifndef NDEBUG
|
|
if (! sgdwLockTbl[bFcn]) app_fatal("Draw lock underflow: 0x%x",bFcn);
|
|
sgdwLockTbl[bFcn]--;
|
|
#endif
|
|
|
|
unlock_buf_priv();
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
// THIS FUNCTION MAY BE CALLED FROM ANY THREAD IN THE PROGRAM
|
|
// ALL OTHER PUBLIC FUNCTIONS IN THIS MODULE MAY ONLY BE CALLED
|
|
// FROM THE MAIN APPLICATION THREAD!
|
|
//******************************************************************
|
|
void free_directx() {
|
|
if (ghMainWnd) ShowWindow(ghMainWnd,SW_HIDE);
|
|
|
|
// tell SDraw that we're about to kill off direct draw
|
|
// so it doesn't try to re-use freed objects
|
|
SDrawDestroy();
|
|
|
|
sgDrawCrit.Enter();
|
|
if (sgpBackBuf) {
|
|
app_assert(! lpDDSBackBuf);
|
|
DiabloFreePtr(sgpBackBuf);
|
|
}
|
|
else if (lpDDSBackBuf) {
|
|
lpDDSBackBuf->Release();
|
|
lpDDSBackBuf = NULL;
|
|
}
|
|
sgdwLockCount = 0;
|
|
gpBuffer = NULL;
|
|
sgDrawCrit.Leave();
|
|
|
|
if (lpDDSPrimary) {
|
|
lpDDSPrimary->Release();
|
|
lpDDSPrimary = NULL;
|
|
}
|
|
if (lpDDPal) {
|
|
lpDDPal->Release();
|
|
lpDDPal = NULL;
|
|
}
|
|
if (lpDD) {
|
|
lpDD->Release();
|
|
lpDD = NULL;
|
|
}
|
|
|
|
// cannot free library now, still may be in use
|
|
// by directX window procedure...
|
|
/*
|
|
if (sghDDlib) {
|
|
FreeLibrary(sghDDlib);
|
|
sghDDlib = NULL;
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
void ddraw_switch_modes() {
|
|
sgDrawCrit.Enter();
|
|
app_assert(ghMainWnd);
|
|
|
|
void savecrsr_reset();
|
|
savecrsr_reset();
|
|
|
|
// remove any locks this thread has on buffer
|
|
DWORD dwSaveCount = sgdwLockCount;
|
|
while (sgdwLockCount) unlock_buf_priv();
|
|
|
|
free_directx();
|
|
force_redraw = FULLDRAW;
|
|
init_directx(ghMainWnd);
|
|
|
|
// restore locks
|
|
while (dwSaveCount--) lock_buf_priv();
|
|
|
|
sgDrawCrit.Leave();
|
|
}
|
|
|
|
|
|
//******************************************************************
|
|
//******************************************************************
|
|
void ddraw_reinit() {
|
|
ddraw_switch_modes();
|
|
}
|