|
|
|
|
#include "devilution.h"
|
|
|
|
|
#include "miniwin/ddraw.h"
|
|
|
|
|
#include "stubs.h"
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
#include "DiabloUI/diabloui.h"
|
|
|
|
|
#include "DiabloUI/dialogs.h"
|
|
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#define strcasecmp _stricmp
|
|
|
|
|
#define strncasecmp _strnicmp
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace dvl {
|
|
|
|
|
|
|
|
|
|
DWORD last_error;
|
|
|
|
|
|
|
|
|
|
DWORD GetLastError()
|
|
|
|
|
{
|
|
|
|
|
return last_error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetLastError(DWORD dwErrCode)
|
|
|
|
|
{
|
|
|
|
|
last_error = dwErrCode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *_strlwr(char *str)
|
|
|
|
|
{
|
|
|
|
|
for (char *p = str; *p; ++p) {
|
|
|
|
|
*p = tolower(*p);
|
|
|
|
|
}
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wsprintfA(LPSTR dest, LPCSTR format, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
return vsprintf(dest, format, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int wvsprintfA(LPSTR dest, LPCSTR format, va_list arglist)
|
|
|
|
|
{
|
|
|
|
|
return vsnprintf(dest, 256, format, arglist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _strcmpi(const char *_Str1, const char *_Str2)
|
|
|
|
|
{
|
|
|
|
|
return strcasecmp(_Str1, _Str2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _strnicmp(const char *_Str1, const char *_Str2, size_t n)
|
|
|
|
|
{
|
|
|
|
|
return strncasecmp(_Str1, _Str2, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *_itoa(int _Value, char *_Dest, int _Radix)
|
|
|
|
|
{
|
|
|
|
|
switch (_Radix) {
|
|
|
|
|
case 8:
|
|
|
|
|
sprintf(_Dest, "%o", _Value);
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
sprintf(_Dest, "%d", _Value);
|
|
|
|
|
break;
|
|
|
|
|
case 16:
|
|
|
|
|
sprintf(_Dest, "%x", _Value);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _Dest;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD GetTickCount()
|
|
|
|
|
{
|
|
|
|
|
return SDL_GetTicks();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Sleep(DWORD dwMilliseconds)
|
|
|
|
|
{
|
|
|
|
|
SDL_Delay(dwMilliseconds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
return (HANDLE)-1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WINBOOL FindClose(HANDLE hFindFile)
|
|
|
|
|
{
|
|
|
|
|
UNIMPLEMENTED();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WINBOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
strncpy(lpBuffer, "localhost", *nSize);
|
|
|
|
|
*nSize = strlen(lpBuffer);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT GetDriveTypeA(LPCSTR lpRootPathName)
|
|
|
|
|
{
|
|
|
|
|
return DVL_DRIVE_CDROM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WINBOOL DeleteFileA(LPCSTR lpFileName)
|
|
|
|
|
{
|
|
|
|
|
char name[DVL_MAX_PATH];
|
|
|
|
|
TranslateFileName(name, sizeof(name), lpFileName);
|
|
|
|
|
|
|
|
|
|
FILE *f = fopen(name, "r+");
|
|
|
|
|
if (f) {
|
|
|
|
|
fclose(f);
|
|
|
|
|
remove(name);
|
|
|
|
|
f = NULL;
|
|
|
|
|
eprintf("Removed file: %s\n", name);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf("Failed to remove file: %s\n", name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HWND SetCapture(HWND hWnd)
|
|
|
|
|
{
|
|
|
|
|
DUMMY_ONCE();
|
|
|
|
|
return hWnd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WINBOOL ReleaseCapture()
|
|
|
|
|
{
|
|
|
|
|
DUMMY_ONCE();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FakeWMDestroy()
|
|
|
|
|
{
|
|
|
|
|
MainWndProc(NULL, DVL_WM_DESTROY, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HWND CreateWindowExA(
|
|
|
|
|
DWORD dwExStyle,
|
|
|
|
|
LPCSTR lpClassName,
|
|
|
|
|
LPCSTR lpWindowName,
|
|
|
|
|
DWORD dwStyle,
|
|
|
|
|
int X,
|
|
|
|
|
int Y,
|
|
|
|
|
int nWidth,
|
|
|
|
|
int nHeight,
|
|
|
|
|
HWND hWndParent,
|
|
|
|
|
HMENU hMenu,
|
|
|
|
|
HINSTANCE hInstance,
|
|
|
|
|
LPVOID lpParam)
|
|
|
|
|
{
|
|
|
|
|
if (SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) <= -1) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SDL1
|
|
|
|
|
SDL_EnableUNICODE(1);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
atexit(SDL_Quit);
|
|
|
|
|
|
|
|
|
|
int upscale = 1;
|
|
|
|
|
DvlIntSetting("upscale", &upscale);
|
|
|
|
|
DvlIntSetting("fullscreen", (int *)&fullscreen);
|
|
|
|
|
|
|
|
|
|
int grabInput = 1;
|
|
|
|
|
DvlIntSetting("grab input", &grabInput);
|
|
|
|
|
|
|
|
|
|
#ifdef USE_SDL1
|
|
|
|
|
int flags = SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_HWPALETTE;
|
|
|
|
|
if (fullscreen) {
|
|
|
|
|
SDL_Log("fullscreen not yet supported with SDL1");
|
|
|
|
|
}
|
|
|
|
|
// flags |= fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
|
|
|
|
|
SDL_WM_SetCaption(lpWindowName, WINDOW_ICON_NAME);
|
|
|
|
|
SDL_SetVideoMode(nWidth, nHeight, /*bpp=*/0, flags);
|
|
|
|
|
window = SDL_GetVideoSurface();
|
|
|
|
|
if (grabInput)
|
|
|
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
|
|
|
#else
|
|
|
|
|
int flags = 0;
|
|
|
|
|
if (upscale) {
|
|
|
|
|
flags |= fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_RESIZABLE;
|
|
|
|
|
|
|
|
|
|
char scaleQuality[2] = "2";
|
|
|
|
|
DvlStringSetting("scaling quality", scaleQuality, 2);
|
|
|
|
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scaleQuality);
|
|
|
|
|
} else if (fullscreen) {
|
|
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (grabInput) {
|
|
|
|
|
flags |= SDL_WINDOW_INPUT_GRABBED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window = SDL_CreateWindow(lpWindowName, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, nWidth, nHeight, flags);
|
|
|
|
|
#endif
|
|
|
|
|
if (window == NULL) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
atexit(FakeWMDestroy);
|
|
|
|
|
|
|
|
|
|
if (upscale) {
|
|
|
|
|
#ifdef USE_SDL1
|
|
|
|
|
SDL_Log("upscaling not supported with USE_SDL1");
|
|
|
|
|
#else
|
|
|
|
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
|
|
|
|
|
if (renderer == NULL) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, nWidth, nHeight);
|
|
|
|
|
if (texture == NULL) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (SDL_RenderSetLogicalSize(renderer, nWidth, nHeight) <= -1) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return window;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL InvalidateRect(HWND hWnd, const RECT *lpRect, BOOL bErase)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Appears to be used to clear the FB on init
|
|
|
|
|
*/
|
|
|
|
|
BOOL UpdateWindow(HWND hWnd)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL ShowWindow(HWND hWnd, int nCmdShow)
|
|
|
|
|
{
|
|
|
|
|
if (nCmdShow == DVL_SW_HIDE) {
|
|
|
|
|
SDL_HideWindow(window);
|
|
|
|
|
} else if (nCmdShow == DVL_SW_SHOWNORMAL) {
|
|
|
|
|
SDL_ShowWindow(window);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Because we don't change resolution it dosen't make sens to use SDL_GetCurrentDisplayMode
|
|
|
|
|
*/
|
|
|
|
|
int GetSystemMetrics(int nIndex)
|
|
|
|
|
{
|
|
|
|
|
switch (nIndex) {
|
|
|
|
|
case DVL_SM_CXSCREEN:
|
|
|
|
|
return SCREEN_WIDTH;
|
|
|
|
|
case DVL_SM_CYSCREEN:
|
|
|
|
|
return SCREEN_HEIGHT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int GetDeviceCaps(HDC hdc, int index)
|
|
|
|
|
{
|
|
|
|
|
SDL_DisplayMode current;
|
|
|
|
|
|
|
|
|
|
if (SDL_GetCurrentDisplayMode(0, ¤t) <= -1) {
|
|
|
|
|
SDL_Log(SDL_GetError());
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (index == DVL_HORZRES) {
|
|
|
|
|
return current.w;
|
|
|
|
|
}
|
|
|
|
|
if (index == DVL_VERTRES) {
|
|
|
|
|
return current.h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GetWindowRect(HWND hDlg, tagRECT *Rect)
|
|
|
|
|
{
|
|
|
|
|
int x, y, w, h;
|
|
|
|
|
SDL_GetWindowPosition(window, &x, &y);
|
|
|
|
|
SDL_GetWindowSize(window, &w, &h);
|
|
|
|
|
|
|
|
|
|
Rect->right = x;
|
|
|
|
|
Rect->top = y;
|
|
|
|
|
Rect->left = w + x;
|
|
|
|
|
Rect->bottom = h + y;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT GetSystemPaletteEntries(HDC hdc, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GetVersionExA(LPOSVERSIONINFOA lpVersionInformation)
|
|
|
|
|
{
|
|
|
|
|
lpVersionInformation->dwMajorVersion = 5;
|
|
|
|
|
lpVersionInformation->dwMinorVersion = 0;
|
|
|
|
|
lpVersionInformation->dwPlatformId = DVL_VER_PLATFORM_WIN32_NT;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void lstrcpynA(LPSTR lpString1, LPCSTR lpString2, int iMaxLength)
|
|
|
|
|
{
|
|
|
|
|
strncpy(lpString1, lpString2, iMaxLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int MessageBoxA(HWND hWnd, const char *Text, const char *Title, UINT Flags)
|
|
|
|
|
{
|
|
|
|
|
UiOkDialog(Title, Text, /*error=*/!!(Flags & (DVL_MB_ICONHAND | DVL_MB_ICONEXCLAMATION)), nullptr, 0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PostQuitMessage(int nExitCode)
|
|
|
|
|
{
|
|
|
|
|
DUMMY();
|
|
|
|
|
PostMessageA(NULL, DVL_WM_QUERYENDSESSION, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LRESULT DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
|
|
|
|
{
|
|
|
|
|
DUMMY_ONCE();
|
|
|
|
|
if (Msg == DVL_WM_QUERYENDSESSION)
|
|
|
|
|
exit(0);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|