mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-11 23:40:51 +02:00
Initial commit.
This commit is contained in:
@@ -0,0 +1,367 @@
|
||||
//******************************************************************
|
||||
// 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();
|
||||
}
|
||||
Reference in New Issue
Block a user