📄 modes.c
字号:
#define INITGUID
#include <windows.h>
#include "shared.h"
#include "ddraw.h"
#include "d3d.h"
#include "dinput.h"
#include "main.h"
#include "input.h"
#include "registry.h"
#include "modes.h"
static LPDIRECTDRAW7 pDirectDraw = NULL;
static LPDIRECTDRAWSURFACE7 pFrontSurface = NULL;
static LPDIRECTDRAWSURFACE7 pBackSurface = NULL;
static LPDIRECT3D7 pDirect3D = NULL;
static LPDIRECT3DDEVICE7 p3DDevice = NULL;
static LPDIRECTDRAWSURFACE7 pSystemTexture = NULL;
static LPDIRECTDRAWSURFACE7 pVRAMTexture = NULL;
static LPDIRECTDRAWPALETTE pPalette = NULL;
static LPDIRECTDRAWCLIPPER pClipper = NULL;
static MODE Mode[MAX_MODES];
static int NoOfModes;
static int CurrentMode = -1;
static BOOL ModeIsFullScreen = FALSE;
static RECT ViewportRect;
static RECT ScreenRect;
static D3DTLVERTEX Vertex[4];
static D3DTLVERTEX ScanLine[2];
static BOOL UseGDISurface = FALSE;
static HMODULE hModule = NULL;
BOOL InitModes(void)
{
int i;
int Devices = 0;
HRESULT (WINAPI *pDirectDrawCreateEx)(GUID FAR *, LPVOID *, REFIID, IUnknown FAR *);
ModeIsFullScreen = FALSE;
hModule = LoadLibrary("ddraw.dll");
if (!hModule)
{
FreeLibrary(hModule);
hModule = NULL;
return FALSE;
}
pDirectDrawCreateEx = (void *)GetProcAddress(hModule, "DirectDrawCreateEx");
if (!pDirectDrawCreateEx) return FALSE;
if (pDirectDrawCreateEx(NULL, &pDirectDraw, &IID_IDirectDraw7, NULL) != DD_OK) return FALSE;
memset(Mode, 0, sizeof(MODE) * MAX_MODES);
NoOfModes = 0;
IDirectDraw7_EnumDisplayModes(pDirectDraw, DDEDM_REFRESHRATES, NULL, NULL, EnumModes);
if (IDirectDraw7_QueryInterface(pDirectDraw, &IID_IDirect3D7, &pDirect3D) != DD_OK)
{
TidyModes();
return FALSE;
}
memset(&Vertex, 0, sizeof(D3DTLVERTEX) * 4);
memset(&ScanLine, 0, sizeof(D3DTLVERTEX) * 2);
for (i = 0 ; i < 4 ; i++)
{
Vertex[i].rhw = 1;
Vertex[i].color = 0xFFFFFFFF;
}
return TRUE;
}
HRESULT WINAPI EnumModes(LPDDSURFACEDESC2 pDesc, LPVOID pContext)
{
if (pDesc->ddpfPixelFormat.dwRGBBitCount != 8 && pDesc->ddpfPixelFormat.dwRGBBitCount != 24)
{
Mode[NoOfModes].Width = pDesc->dwWidth;
Mode[NoOfModes].Height = pDesc->dwHeight;
Mode[NoOfModes].BitDepth = pDesc->ddpfPixelFormat.dwRGBBitCount;
NoOfModes++;
if (NoOfModes == MAX_MODES) return DDENUMRET_CANCEL;
}
return DDENUMRET_OK;
}
void TidyModes(void)
{
RestoreMode(GetSMShwnd());
if (pDirect3D)
{
IDirect3D7_Release(pDirect3D);
pDirect3D = NULL;
}
if (pDirectDraw)
{
IDirectDraw7_Release(pDirectDraw);
pDirectDraw = NULL;
}
if (hModule)
{
FreeLibrary(hModule);
hModule = NULL;
}
}
BOOL ChangeMode(int ModeIndex, BOOL FullScreen)
{
HWND hwnd = GetSMShwnd();
DDSURFACEDESC2 Surface;
DDSCAPS2 SurfaceCaps;
RestoreMode(hwnd);
memset(&Surface, 0, sizeof(DDSURFACEDESC2));
Surface.dwSize = sizeof(DDSURFACEDESC2);
if (FullScreen)
{
if (IDirectDraw7_SetCooperativeLevel(pDirectDraw, hwnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE) != DD_OK) return FALSE;
if (IDirectDraw7_SetDisplayMode(pDirectDraw, Mode[ModeIndex].Width, Mode[ModeIndex].Height, Mode[ModeIndex].BitDepth, 0, 0) != DD_OK)
{
RestoreMode(hwnd);
return FALSE;
}
Surface.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
Surface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
Surface.dwBackBufferCount = 1;
if (IDirectDraw7_CreateSurface(pDirectDraw, &Surface, &pFrontSurface, NULL) != DD_OK)
{
RestoreMode(hwnd);
return FALSE;
}
memset(&SurfaceCaps, 0, sizeof(DDSCAPS2));
SurfaceCaps.dwCaps = DDSCAPS_BACKBUFFER;
if (IDirectDrawSurface7_GetAttachedSurface(pFrontSurface, &SurfaceCaps, &pBackSurface) != DD_OK)
{
RestoreMode(hwnd);
return FALSE;
}
while (ShowCursor(FALSE) >= 0);
}
else
{
RECT Rect;
int Width;
int Height;
if (IDirectDraw7_SetCooperativeLevel(pDirectDraw, hwnd, DDSCL_NORMAL) != DD_OK) return FALSE;
Surface.dwFlags = DDSD_CAPS;
Surface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (IDirectDraw7_CreateSurface(pDirectDraw, &Surface, &pFrontSurface, NULL) != DD_OK)
{
return FALSE;
}
if (IDirectDraw7_CreateClipper(pDirectDraw, 0, &pClipper, NULL) != DD_OK)
{
RestoreMode(hwnd);
return FALSE;
}
IDirectDrawClipper_SetHWnd(pClipper, 0, hwnd);
IDirectDrawSurface7_SetClipper(pFrontSurface, pClipper);
GetConsoleScreenRect(&Rect);
Width = (Rect.right - Rect.left) * RegistryInfo.ScreenScale;
Height = (Rect.bottom - Rect.top) * RegistryInfo.ScreenScale;
Surface.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
Surface.dwWidth = Width;
Surface.dwHeight = Height;
Surface.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
if (IDirectDraw7_CreateSurface(pDirectDraw, &Surface, &pBackSurface, NULL) != DD_OK)
{
RestoreMode(hwnd);
return FALSE;
}
}
ModeIsFullScreen = FullScreen;
CurrentMode = ModeIndex;
RegistryInfo.FullScreenMode = CurrentMode;
if (!CreateTexture())
{
RestoreMode(hwnd);
return FALSE;
}
if (IDirect3D7_CreateDevice(pDirect3D, &IID_IDirect3DHALDevice, pBackSurface, &p3DDevice) != D3D_OK)
{
RestoreMode(hwnd);
return FALSE;
}
UpdateModeWindowCoords(hwnd);
SetModeSmoothing(RegistryInfo.ScreenSmoothing);
return TRUE;
}
void RestoreMode(HWND hwnd)
{
while (ShowCursor(TRUE) < 0);
DestroyTexture();
if (p3DDevice)
{
IDirect3DDevice7_Release(p3DDevice);
p3DDevice = NULL;
}
if (pBackSurface)
{
IDirectDrawSurface7_Release(pBackSurface);
pBackSurface = NULL;
}
if (pFrontSurface)
{
if (pClipper)
{
IDirectDrawSurface7_SetClipper(pFrontSurface, NULL);
IDirectDrawClipper_Release(pClipper);
pClipper = NULL;
}
IDirectDrawSurface7_Release(pFrontSurface);
pFrontSurface = NULL;
}
if (ModeIsFullScreen)
{
IDirectDraw7_RestoreDisplayMode(pDirectDraw);
IDirectDraw7_SetCooperativeLevel(pDirectDraw, GetSMShwnd(), DDSCL_NORMAL);
}
ModeIsFullScreen = FALSE;
}
void FlipScreens(void)
{
if (UseGDISurface && ModeIsFullScreen)
{
IDirectDrawSurface7_Blt(pFrontSurface, NULL, pBackSurface, NULL, DDBLT_WAIT, NULL);
return;
}
while (1)
{
HRESULT Result;
if (ModeIsFullScreen)
{
Result = IDirectDrawSurface7_Flip(pFrontSurface, NULL, 0);
}
else
{
Result = IDirectDrawSurface7_Blt(pFrontSurface, &ScreenRect, pBackSurface, &ViewportRect, DDBLTFAST_WAIT, NULL);
}
if (Result == DD_OK) break;
if (Result == DDERR_SURFACELOST)
{
Result = IDirectDrawSurface7_Restore(pFrontSurface);
if (Result != DD_OK) break;
}
if (Result != DDERR_WASSTILLDRAWING) break;
}
}
void UpdateModeWindowCoords(HWND hwnd)
{
RECT Rect;
float Top;
float Left;
float Right;
float Bottom;
GetConsoleScreenRect(&Rect);
if (ModeIsFullScreen)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -