#include "harness/hooks.h"
#include "harness/os.h"
#include "harness/win95_polyfill.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_WIN32) || defined(_WIN64)
#include <direct.h>
#include <windows.h>
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getcwd-wgetcwd?view=msvc-170
#define getcwd _getcwd
#define chdir _chdir
#else
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
#endif
// All functions have a "_" suffix to avoid collisions with <windows.h>-defined types
uint32_t GetFileAttributesA_(char* lpFileName) {
FILE
* f
= fopen(lpFileName
, "r");
if (f == NULL) {
return INVALID_FILE_ATTRIBUTES;
}
return FILE_ATTRIBUTE_NORMAL;
}
int SetFileAttributesA_(char* lpFileName, uint32_t dwFileAttributes) {
// no-op for now
return 0;
}
void* CreateFileA_(char* lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode, void* lpSecurityAttributes, uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes, void* hTemplateFile) {
assert(dwDesiredAccess
== GENERIC_READ
);
assert(lpSecurityAttributes
== NULL
);
assert(dwCreationDisposition
== OPEN_EXISTING
);
FILE
* f
= fopen(lpFileName
, "r");
if (!f) {
return INVALID_HANDLE_VALUE;
}
return f;
}
uint32_t GetFileSize_(void* hFile, uint32_t* lpFileSizeHigh) {
assert(lpFileSizeHigh
== NULL
);
long current_offset
= ftell(hFile
);
fseek(hFile
, 0, SEEK_END
);
long size
= ftell(hFile
);
fseek(hFile
, current_offset
, SEEK_SET
);
return size;
}
int CloseHandle_(void* hObject) {
return 0;
}
void GlobalMemoryStatus_(MEMORYSTATUS_* lpBuffer) {
lpBuffer->dwTotalPhys = 64000000;
lpBuffer->dwAvailPhys = 64000000; // pretend we have a whole 64mb of ram!
lpBuffer->dwAvailPageFile = 0;
lpBuffer->dwTotalVirtual = 0;
lpBuffer->dwAvailVirtual = 0;
lpBuffer->dwMemoryLoad = 0;
lpBuffer->dwTotalPageFile = 0;
}
int GetCursorPos_(POINT_* lpPoint) {
int x, y;
gHarness_platform.GetMousePosition(&x, &y);
lpPoint->x = x;
lpPoint->y = y;
return 0;
}
int ScreenToClient_(void* hWnd, POINT_* lpPoint) {
// no-op, we assume the point is already relative to client
return 0;
}
uint32_t timeGetTime_(void) {
return gHarness_platform.GetTicks();
}
uint32_t GetCurrentDirectoryA_(uint32_t nBufferLength, char* lpBuffer) {
char* ret = getcwd(lpBuffer, nBufferLength);
if (ret == NULL) {
return 0;
}
}
int SetCurrentDirectoryA_(char* lpPathName) {
int ret = chdir(lpPathName);
// chdir returning zero means success, SetCurrentDirectory returning non-zero means success
if (ret == 0) {
return 1;
} else {
return 0;
}
}
HANDLE_ FindFirstFileA_(char* lpFileName, WIN32_FIND_DATAA_* lpFindFileData) {
#if defined(_WIN32) || defined(_WIN64)
WIN32_FIND_DATAA fd; // Pierre-Marie Baty -- explicitly use WIN32_FIND_DATAA instead of WIN32_FIND_DATA
void* hFile = FindFirstFileA(lpFileName, &fd); // Pierre-Marie Baty -- explicitly use FindFirstFileA() instead of FindFirstFile()
if (hFile != INVALID_HANDLE_VALUE) {
strcpy(lpFindFileData
->cFileName
, fd.
cFileName);
}
return hFile;
#else
DIR* dir;
dir = opendir(lpFileName);
if (dir == NULL) {
return INVALID_HANDLE_VALUE;
}
if (FindNextFileA_(dir, lpFindFileData)) {
return dir;
} else {
closedir(dir);
return INVALID_HANDLE_VALUE;
}
#endif
}
int FindNextFileA_(HANDLE_ hFindFile, WIN32_FIND_DATAA_* lpFindFileData) {
#if defined(_WIN32) || defined(_WIN64)
WIN32_FIND_DATAA fd; // Pierre-Marie Baty -- explicitly use WIN32_FIND_DATAA instead of WIN32_FIND_DATA
int result = FindNextFileA(hFindFile, &fd); // Pierre-Marie Baty -- explicitly use FindNextFileA() instead of FindNextFile()
if (result) {
strcpy(lpFindFileData
->cFileName
, fd.
cFileName);
}
return result;
#else
struct dirent* entry;
if (hFindFile == NULL) {
return 0;
}
while ((entry = readdir(hFindFile)) != NULL) {
if (entry->d_type == DT_REG) {
strcpy(lpFindFileData
->cFileName
, entry
->d_name
);
return 1;
}
}
return 0;
#endif
}
int FindClose_(HANDLE_ hFindFile) {
#if defined(_WIN32) || defined(_WIN64)
return FindClose(hFindFile);
#else
return closedir(hFindFile);
#endif
}
void* CreateWindowExA_(uint32_t dwExStyle, char* lpClassName, char* lpWindowName, uint32_t dwStyle, int X, int Y, int nWidth, int nHeight, void* hWndParent, void* hMenu, void* hInstance, void* lpParam) {
return gHarness_platform.CreateWindowAndRenderer(lpWindowName, X, Y, nWidth, nHeight);
}
int SetWindowPos_(void* hWnd, void* hWndInsertAfter, int X, int Y, int cx, int cy, unsigned int uFlags) {
return gHarness_platform.SetWindowPos(hWnd, X, Y, cx, cy);
}
int ShowCursor_(int bShow) {
gHarness_platform.ShowCursor(bShow);
return 0;
}
int SendMessageA_(void* hWnd, unsigned int Msg, unsigned int wParam, long lParam) {
return 0;
}
int MessageBoxA_(void* hWnd, char* lpText, char* lpCaption, unsigned int uType) {
// only ever used for errors
assert(uType
== MB_ICONERROR
);
return gHarness_platform.ShowErrorMessage(hWnd, lpText, lpCaption);
}
int DestroyWindow_(void* hWnd) {
gHarness_platform.DestroyWindow(hWnd);
return 0;
}
void ExitProcess_(unsigned int uExitCode) {
}
void TranslateMessage_(MSG_* lpMsg) {
// no-op
}
void DispatchMessageA_(MSG_* lpMsg) {
// no-op
}
int PeekMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax, unsigned int wRemoveMsg) {
return gHarness_platform.ProcessWindowMessages(lpMsg);
}
int GetMessageA_(MSG_* lpMsg, void* hWnd, unsigned int wMsgFilterMin, unsigned int wMsgFilterMax) {
return gHarness_platform.ProcessWindowMessages(lpMsg);
}
void Sleep_(uint32_t dwMilliseconds) {
gHarness_platform.Sleep(dwMilliseconds);
}
void DirectDraw_CreateSurface(int width, int height) {
// no-op
}
void DirectInputDevice_GetDeviceState(unsigned int count, uint8_t* buffer) {
gHarness_platform.GetKeyboardState(count, buffer);
}
void DirectDrawDevice_SetPaletteEntries(PALETTEENTRY_* palette, int pFirst_colour, int pCount) {
gHarness_platform.Renderer_SetPalette(palette);
}
void _splitpath_(char* path, char* drive, char* dir, char* fname, char* ext) {
char* result = OS_Basename(path);
}
int _CrtDbgReport_(int reportType, const char* filename, int linenumber, const char* moduleName, const char* format, ...) {
printf("_CrtDbgReport: (TODO)\n");
return 1;
}