48 changed files with 14768 additions and 0 deletions
@ -0,0 +1,14 @@
|
||||
--- |
||||
IndentWidth: 4 |
||||
TabWidth: 4 |
||||
--- |
||||
Language: Cpp |
||||
UseTab: ForIndentation |
||||
AlignTrailingComments: false |
||||
BreakBeforeBraces: Linux |
||||
ColumnLimit: 120 |
||||
IncludeBlocks: Preserve |
||||
AlignEscapedNewlines: DontAlign |
||||
AlignOperands: true |
||||
AllowShortFunctionsOnASingleLine: Inline |
||||
Standard: Cpp11 |
||||
@ -0,0 +1,248 @@
|
||||
LINK_IMPORT(imp_CloseHandle, CloseHandle) |
||||
LINK_IMPORT(imp_CopyFileA, CopyFileA) |
||||
LINK_IMPORT(imp_CreateEventA, CreateEventA) |
||||
LINK_IMPORT(imp_CreateFileA, CreateFileA) |
||||
LINK_IMPORT(imp_CreateFileMappingA, CreateFileMappingA) |
||||
LINK_IMPORT(imp_CreateProcessA, CreateProcessA) |
||||
LINK_IMPORT(imp_DeleteCriticalSection, DeleteCriticalSection) |
||||
LINK_IMPORT(imp_DeleteFileA, DeleteFileA) |
||||
LINK_IMPORT(imp_DestroyWindow, DestroyWindow) |
||||
LINK_IMPORT(imp_DispatchMessageA, DispatchMessageA) |
||||
LINK_IMPORT(imp_EnterCriticalSection, EnterCriticalSection) |
||||
LINK_IMPORT(imp_ExitProcess, ExitProcess) |
||||
LINK_IMPORT(imp_FindClose, FindClose) |
||||
LINK_IMPORT(imp_FindFirstFileA, FindFirstFileA) |
||||
LINK_IMPORT(imp_FindWindowA, FindWindowA) |
||||
LINK_IMPORT(imp_GetComputerNameA, GetComputerNameA) |
||||
LINK_IMPORT(imp_GetCurrentProcessId, GetCurrentProcessId) |
||||
LINK_IMPORT(imp_GetCurrentThread, GetCurrentThread) |
||||
LINK_IMPORT(imp_GetCurrentThreadId, GetCurrentThreadId) |
||||
LINK_IMPORT(imp_GetDC, GetDC) |
||||
LINK_IMPORT(imp_GetDeviceCaps, GetDeviceCaps) |
||||
LINK_IMPORT(imp_GetDiskFreeSpaceA, GetDiskFreeSpaceA) |
||||
LINK_IMPORT(imp_GetFileAttributesA, GetFileAttributesA) |
||||
LINK_IMPORT(imp_GetFileSize, GetFileSize) |
||||
LINK_IMPORT(imp_GetForegroundWindow, GetForegroundWindow) |
||||
LINK_IMPORT(imp_GetLastActivePopup, GetLastActivePopup) |
||||
LINK_IMPORT(imp_GetLastError, GetLastError) |
||||
LINK_IMPORT(imp_GetModuleFileNameA, GetModuleFileNameA) |
||||
LINK_IMPORT(imp_GetPrivateProfileStringA, GetPrivateProfileStringA) |
||||
LINK_IMPORT(imp_GetSystemInfo, GetSystemInfo) |
||||
LINK_IMPORT(imp_GetSystemPaletteEntries, GetSystemPaletteEntries) |
||||
LINK_IMPORT(imp_GetTickCount, GetTickCount) |
||||
LINK_IMPORT(imp_GetTopWindow, GetTopWindow) |
||||
LINK_IMPORT(imp_GetWindow, GetWindow) |
||||
LINK_IMPORT(imp_GetWindowThreadProcessId, GetWindowThreadProcessId) |
||||
LINK_IMPORT(imp_GetWindowsDirectoryA, GetWindowsDirectoryA) |
||||
LINK_IMPORT(imp_InitializeCriticalSection, InitializeCriticalSection) |
||||
LINK_IMPORT(imp_LeaveCriticalSection, LeaveCriticalSection) |
||||
LINK_IMPORT(imp_MapViewOfFile, MapViewOfFile) |
||||
LINK_IMPORT(imp_OpenFile, OpenFile) |
||||
LINK_IMPORT(imp_PeekMessageA, PeekMessageA) |
||||
LINK_IMPORT(imp_PostMessageA, PostMessageA) |
||||
LINK_IMPORT(imp_ReadFile, ReadFile) |
||||
LINK_IMPORT(imp_ReleaseCapture, ReleaseCapture) |
||||
LINK_IMPORT(imp_ReleaseDC, ReleaseDC) |
||||
LINK_IMPORT(imp_SDrawGetFrameWindow, SDrawGetFrameWindow) |
||||
LINK_IMPORT(imp_SDrawRealizePalette, SDrawRealizePalette) |
||||
LINK_IMPORT(imp_SDrawUpdatePalette, SDrawUpdatePalette) |
||||
LINK_IMPORT(imp_SErrGetErrorStr, SErrGetErrorStr) |
||||
LINK_IMPORT(imp_SErrGetLastError, SErrGetLastError) |
||||
LINK_IMPORT(imp_SErrSetLastError, SErrSetLastError) |
||||
LINK_IMPORT(imp_SFileCloseArchive, SFileCloseArchive) |
||||
LINK_IMPORT(imp_SFileCloseFile, SFileCloseFile) |
||||
LINK_IMPORT(imp_SFileDdaBeginEx, SFileDdaBeginEx) |
||||
LINK_IMPORT(imp_SFileDdaDestroy, SFileDdaDestroy) |
||||
LINK_IMPORT(imp_SFileDdaEnd, SFileDdaEnd) |
||||
LINK_IMPORT(imp_SFileDdaGetPos, SFileDdaGetPos) |
||||
LINK_IMPORT(imp_SFileDdaInitialize, SFileDdaInitialize) |
||||
LINK_IMPORT(imp_SFileDdaSetVolume, SFileDdaSetVolume) |
||||
LINK_IMPORT(imp_SFileGetFileArchive, SFileGetFileArchive) |
||||
LINK_IMPORT(imp_SFileGetFileSize, SFileGetFileSize) |
||||
LINK_IMPORT(imp_SFileOpenArchive, SFileOpenArchive) |
||||
LINK_IMPORT(imp_SFileOpenFile, SFileOpenFile) |
||||
LINK_IMPORT(imp_SFileOpenFileEx, SFileOpenFileEx) |
||||
LINK_IMPORT(imp_SFileReadFile, SFileReadFile) |
||||
LINK_IMPORT(imp_SFileSetFilePointer, SFileSetFilePointer) |
||||
LINK_IMPORT(imp_SMemAlloc, SMemAlloc) |
||||
LINK_IMPORT(imp_SMemFree, SMemFree) |
||||
LINK_IMPORT(imp_SNetCreateGame, SNetCreateGame) |
||||
LINK_IMPORT(imp_SNetDestroy, SNetDestroy) |
||||
LINK_IMPORT(imp_SNetDropPlayer, SNetDropPlayer) |
||||
LINK_IMPORT(imp_SNetGetGameInfo, SNetGetGameInfo) |
||||
LINK_IMPORT(imp_SNetGetOwnerTurnsWaiting, SNetGetOwnerTurnsWaiting) |
||||
LINK_IMPORT(imp_SNetGetProviderCaps, SNetGetProviderCaps) |
||||
LINK_IMPORT(imp_SNetGetTurnsInTransit, SNetGetTurnsInTransit) |
||||
LINK_IMPORT(imp_SNetInitializeProvider, SNetInitializeProvider) |
||||
LINK_IMPORT(imp_SNetLeaveGame, SNetLeaveGame) |
||||
LINK_IMPORT(imp_SNetPerformUpgrade, SNetPerformUpgrade) |
||||
LINK_IMPORT(imp_SNetReceiveMessage, SNetReceiveMessage) |
||||
LINK_IMPORT(imp_SNetReceiveTurns, SNetReceiveTurns) |
||||
LINK_IMPORT(imp_SNetRegisterEventHandler, SNetRegisterEventHandler) |
||||
LINK_IMPORT(imp_SNetSendMessage, SNetSendMessage) |
||||
LINK_IMPORT(imp_SNetSendServerChatCommand, SNetSendServerChatCommand) |
||||
LINK_IMPORT(imp_SNetSendTurn, SNetSendTurn) |
||||
LINK_IMPORT(imp_SNetSetBasePlayer, SNetSetBasePlayer) |
||||
LINK_IMPORT(imp_SNetUnregisterEventHandler, SNetUnregisterEventHandler) |
||||
LINK_IMPORT(imp_SRegLoadData, SRegLoadData) |
||||
LINK_IMPORT(imp_SRegLoadString, SRegLoadString) |
||||
LINK_IMPORT(imp_SRegLoadValue, SRegLoadValue) |
||||
LINK_IMPORT(imp_SRegSaveData, SRegSaveData) |
||||
LINK_IMPORT(imp_SRegSaveString, SRegSaveString) |
||||
LINK_IMPORT(imp_SRegSaveValue, SRegSaveValue) |
||||
LINK_IMPORT(imp_SStrCopy, SStrCopy) |
||||
LINK_IMPORT(imp_SetCapture, SetCapture) |
||||
LINK_IMPORT(imp_SetCursorPos, SetCursorPos) |
||||
LINK_IMPORT(imp_SetEndOfFile, SetEndOfFile) |
||||
LINK_IMPORT(imp_SetFileAttributesA, SetFileAttributesA) |
||||
LINK_IMPORT(imp_SetFilePointer, SetFilePointer) |
||||
LINK_IMPORT(imp_SetFocus, SetFocus) |
||||
LINK_IMPORT(imp_SetForegroundWindow, SetForegroundWindow) |
||||
LINK_IMPORT(imp_SetLastError, SetLastError) |
||||
LINK_IMPORT(imp_SetThreadPriority, SetThreadPriority) |
||||
LINK_IMPORT(imp_ShowCursor, ShowCursor) |
||||
LINK_IMPORT(imp_Sleep, Sleep) |
||||
LINK_IMPORT(imp_TranslateMessage, TranslateMessage) |
||||
LINK_IMPORT(imp_UiAppActivate, UiAppActivate) |
||||
LINK_IMPORT(imp_UiArtCallback, UiArtCallback) |
||||
LINK_IMPORT(imp_UiAuthCallback, UiAuthCallback) |
||||
LINK_IMPORT(imp_UiCategoryCallback, UiCategoryCallback) |
||||
LINK_IMPORT(imp_UiCopyProtError, UiCopyProtError) |
||||
LINK_IMPORT(imp_UiCreateGameCallback, UiCreateGameCallback) |
||||
LINK_IMPORT(imp_UiCreatePlayerDescription, UiCreatePlayerDescription) |
||||
LINK_IMPORT(imp_UiCreditsDialog, UiCreditsDialog) |
||||
LINK_IMPORT(imp_UiDestroy, UiDestroy) |
||||
LINK_IMPORT(imp_UiDrawDescCallback, UiDrawDescCallback) |
||||
LINK_IMPORT(imp_UiGetDataCallback, UiGetDataCallback) |
||||
LINK_IMPORT(imp_UiInitialize, UiInitialize) |
||||
LINK_IMPORT(imp_UiMainMenuDialog, UiMainMenuDialog) |
||||
LINK_IMPORT(imp_UiMessageBoxCallback, UiMessageBoxCallback) |
||||
LINK_IMPORT(imp_UiProfileCallback, UiProfileCallback) |
||||
LINK_IMPORT(imp_UiProfileDraw, UiProfileDraw) |
||||
LINK_IMPORT(imp_UiProfileGetString, UiProfileGetString) |
||||
LINK_IMPORT(imp_UiProgressDialog, UiProgressDialog) |
||||
LINK_IMPORT(imp_UiSelHeroMultDialog, UiSelHeroMultDialog) |
||||
LINK_IMPORT(imp_UiSelHeroSingDialog, UiSelHeroSingDialog) |
||||
LINK_IMPORT(imp_UiSelectGame, UiSelectGame) |
||||
LINK_IMPORT(imp_UiSelectProvider, UiSelectProvider) |
||||
LINK_IMPORT(imp_UiSetupPlayerInfo, UiSetupPlayerInfo) |
||||
LINK_IMPORT(imp_UiSoundCallback, UiSoundCallback) |
||||
LINK_IMPORT(imp_UiTitleDialog, UiTitleDialog) |
||||
LINK_IMPORT(imp_UiValidPlayerName, UiValidPlayerName) |
||||
LINK_IMPORT(imp_UnmapViewOfFile, UnmapViewOfFile) |
||||
LINK_IMPORT(imp_WaitForInputIdle, WaitForInputIdle) |
||||
LINK_IMPORT(imp_WaitForSingleObject, WaitForSingleObject) |
||||
LINK_IMPORT(imp_WriteFile, WriteFile) |
||||
LINK_IMPORT(imp_wsprintfA, wsprintfA) |
||||
MISSING_IMPORT(imp_CompareStringA, CompareStringA) |
||||
MISSING_IMPORT(imp_CompareStringW, CompareStringW) |
||||
MISSING_IMPORT(imp_CreateThread, CreateThread) |
||||
MISSING_IMPORT(imp_CreateWindowExA, CreateWindowExA) |
||||
MISSING_IMPORT(imp_DefWindowProcA, DefWindowProcA) |
||||
MISSING_IMPORT(imp_DialogBoxParamA, DialogBoxParamA) |
||||
MISSING_IMPORT(imp_EndDialog, EndDialog) |
||||
MISSING_IMPORT(imp_ExitThread, ExitThread) |
||||
MISSING_IMPORT(imp_FileTimeToLocalFileTime, FileTimeToLocalFileTime) |
||||
MISSING_IMPORT(imp_FileTimeToSystemTime, FileTimeToSystemTime) |
||||
MISSING_IMPORT(imp_FindNextFileA, FindNextFileA) |
||||
MISSING_IMPORT(imp_FlushFileBuffers, FlushFileBuffers) |
||||
MISSING_IMPORT(imp_FormatMessageA, FormatMessageA) |
||||
MISSING_IMPORT(imp_FreeEnvironmentStringsA, FreeEnvironmentStringsA) |
||||
MISSING_IMPORT(imp_FreeEnvironmentStringsW, FreeEnvironmentStringsW) |
||||
MISSING_IMPORT(imp_GdiSetBatchLimit, GdiSetBatchLimit) |
||||
MISSING_IMPORT(imp_GetACP, GetACP) |
||||
MISSING_IMPORT(imp_GetCPInfo, GetCPInfo) |
||||
MISSING_IMPORT(imp_GetClassNameA, GetClassNameA) |
||||
MISSING_IMPORT(imp_GetCommandLineA, GetCommandLineA) |
||||
MISSING_IMPORT(imp_GetCurrentDirectoryA, GetCurrentDirectoryA) |
||||
MISSING_IMPORT(imp_GetCurrentProcess, GetCurrentProcess) |
||||
MISSING_IMPORT(imp_GetDesktopWindow, GetDesktopWindow) |
||||
MISSING_IMPORT(imp_GetDriveTypeA, GetDriveTypeA) |
||||
MISSING_IMPORT(imp_GetEnvironmentStrings, GetEnvironmentStrings) |
||||
MISSING_IMPORT(imp_GetEnvironmentStringsW, GetEnvironmentStringsW) |
||||
MISSING_IMPORT(imp_GetFileType, GetFileType) |
||||
MISSING_IMPORT(imp_GetFileVersionInfoA, GetFileVersionInfoA) |
||||
MISSING_IMPORT(imp_GetFileVersionInfoSizeA, GetFileVersionInfoSizeA) |
||||
MISSING_IMPORT(imp_GetLocalTime, GetLocalTime) |
||||
MISSING_IMPORT(imp_GetLocaleInfoA, GetLocaleInfoA) |
||||
MISSING_IMPORT(imp_GetLocaleInfoW, GetLocaleInfoW) |
||||
MISSING_IMPORT(imp_GetLogicalDriveStringsA, GetLogicalDriveStringsA) |
||||
MISSING_IMPORT(imp_GetModuleHandleA, GetModuleHandleA) |
||||
MISSING_IMPORT(imp_GetOEMCP, GetOEMCP) |
||||
MISSING_IMPORT(imp_GetProcAddress, GetProcAddress) |
||||
MISSING_IMPORT(imp_GetStartupInfoA, GetStartupInfoA) |
||||
MISSING_IMPORT(imp_GetStdHandle, GetStdHandle) |
||||
MISSING_IMPORT(imp_GetStockObject, GetStockObject) |
||||
MISSING_IMPORT(imp_GetStringTypeA, GetStringTypeA) |
||||
MISSING_IMPORT(imp_GetStringTypeW, GetStringTypeW) |
||||
MISSING_IMPORT(imp_GetSystemMetrics, GetSystemMetrics) |
||||
MISSING_IMPORT(imp_GetSystemTime, GetSystemTime) |
||||
MISSING_IMPORT(imp_GetTimeZoneInformation, GetTimeZoneInformation) |
||||
MISSING_IMPORT(imp_GetUserNameA, GetUserNameA) |
||||
MISSING_IMPORT(imp_GetVersion, GetVersion) |
||||
MISSING_IMPORT(imp_GetVersionExA, GetVersionExA) |
||||
MISSING_IMPORT(imp_GetWindowLongA, GetWindowLongA) |
||||
MISSING_IMPORT(imp_GetWindowRect, GetWindowRect) |
||||
MISSING_IMPORT(imp_HeapAlloc, HeapAlloc) |
||||
MISSING_IMPORT(imp_HeapCreate, HeapCreate) |
||||
MISSING_IMPORT(imp_HeapDestroy, HeapDestroy) |
||||
MISSING_IMPORT(imp_HeapFree, HeapFree) |
||||
MISSING_IMPORT(imp_HeapReAlloc, HeapReAlloc) |
||||
MISSING_IMPORT(imp_HeapSize, HeapSize) |
||||
MISSING_IMPORT(imp_InterlockedDecrement, InterlockedDecrement) |
||||
MISSING_IMPORT(imp_InterlockedIncrement, InterlockedIncrement) |
||||
MISSING_IMPORT(imp_InvalidateRect, InvalidateRect) |
||||
MISSING_IMPORT(imp_IsBadReadPtr, IsBadReadPtr) |
||||
MISSING_IMPORT(imp_IsBadWritePtr, IsBadWritePtr) |
||||
MISSING_IMPORT(imp_LCMapStringA, LCMapStringA) |
||||
MISSING_IMPORT(imp_LCMapStringW, LCMapStringW) |
||||
MISSING_IMPORT(imp_LoadCursorA, LoadCursorA) |
||||
MISSING_IMPORT(imp_LoadIconA, LoadIconA) |
||||
MISSING_IMPORT(imp_LoadImageA, LoadImageA) |
||||
MISSING_IMPORT(imp_LoadLibraryA, LoadLibraryA) |
||||
MISSING_IMPORT(imp_MessageBoxA, MessageBoxA) |
||||
MISSING_IMPORT(imp_MultiByteToWideChar, MultiByteToWideChar) |
||||
MISSING_IMPORT(imp_PostQuitMessage, PostQuitMessage) |
||||
MISSING_IMPORT(imp_RaiseException, RaiseException) |
||||
MISSING_IMPORT(imp_RegCloseKey, RegCloseKey) |
||||
MISSING_IMPORT(imp_RegOpenKeyExA, RegOpenKeyExA) |
||||
MISSING_IMPORT(imp_RegQueryValueExA, RegQueryValueExA) |
||||
MISSING_IMPORT(imp_RegSetValueExA, RegSetValueExA) |
||||
MISSING_IMPORT(imp_RegisterClassExA, RegisterClassExA) |
||||
MISSING_IMPORT(imp_ResetEvent, ResetEvent) |
||||
MISSING_IMPORT(imp_RtlUnwind, RtlUnwind) |
||||
MISSING_IMPORT(imp_SDrawDestroy, SDrawDestroy) |
||||
MISSING_IMPORT(imp_SDrawManualInitialize, SDrawManualInitialize) |
||||
MISSING_IMPORT(imp_SDrawMessageBox, SDrawMessageBox) |
||||
MISSING_IMPORT(imp_SFileSetBasePath, SFileSetBasePath) |
||||
MISSING_IMPORT(imp_SHGetPathFromIDListA, SHGetPathFromIDListA) |
||||
MISSING_IMPORT(imp_SHGetSpecialFolderLocation, SHGetSpecialFolderLocation) |
||||
MISSING_IMPORT(imp_SVidDestroy, SVidDestroy) |
||||
MISSING_IMPORT(imp_SVidInitialize, SVidInitialize) |
||||
MISSING_IMPORT(imp_SVidPlayBegin, SVidPlayBegin) |
||||
MISSING_IMPORT(imp_SVidPlayContinue, SVidPlayContinue) |
||||
MISSING_IMPORT(imp_SVidPlayEnd, SVidPlayEnd) |
||||
MISSING_IMPORT(imp_SetDlgItemTextA, SetDlgItemTextA) |
||||
MISSING_IMPORT(imp_SetEnvironmentVariableA, SetEnvironmentVariableA) |
||||
MISSING_IMPORT(imp_SetEvent, SetEvent) |
||||
MISSING_IMPORT(imp_SetHandleCount, SetHandleCount) |
||||
MISSING_IMPORT(imp_SetStdHandle, SetStdHandle) |
||||
MISSING_IMPORT(imp_SetUnhandledExceptionFilter, SetUnhandledExceptionFilter) |
||||
MISSING_IMPORT(imp_SetWindowLongA, SetWindowLongA) |
||||
MISSING_IMPORT(imp_SetWindowPos, SetWindowPos) |
||||
MISSING_IMPORT(imp_ShellExecuteA, ShellExecuteA) |
||||
MISSING_IMPORT(imp_ShowWindow, ShowWindow) |
||||
MISSING_IMPORT(imp_StormDestroy, StormDestroy) |
||||
MISSING_IMPORT(imp_TerminateProcess, TerminateProcess) |
||||
MISSING_IMPORT(imp_TlsAlloc, TlsAlloc) |
||||
MISSING_IMPORT(imp_TlsGetValue, TlsGetValue) |
||||
MISSING_IMPORT(imp_TlsSetValue, TlsSetValue) |
||||
MISSING_IMPORT(imp_UnhandledExceptionFilter, UnhandledExceptionFilter) |
||||
MISSING_IMPORT(imp_UpdateWindow, UpdateWindow) |
||||
MISSING_IMPORT(imp_VerQueryValueA, VerQueryValueA) |
||||
MISSING_IMPORT(imp_VirtualAlloc, VirtualAlloc) |
||||
MISSING_IMPORT(imp_VirtualFree, VirtualFree) |
||||
MISSING_IMPORT(imp_VirtualQuery, VirtualQuery) |
||||
MISSING_IMPORT(imp_WideCharToMultiByte, WideCharToMultiByte) |
||||
MISSING_IMPORT(imp_lstrcpynA, lstrcpynA) |
||||
MISSING_IMPORT(imp_wvsprintfA, wvsprintfA) |
||||
@ -0,0 +1,47 @@
|
||||
LINK_STUB(d_CaptureScreen, CaptureScreen) |
||||
LINK_STUB(d_DDErrMsg, DDErrMsg) |
||||
LINK_STUB(d_DirErrorDlg, DirErrorDlg) |
||||
LINK_STUB(d_DiskFreeDlg, DiskFreeDlg) |
||||
LINK_STUB(d_DrawDlg, DrawDlg) |
||||
LINK_STUB(d_ErrDlg, ErrDlg) |
||||
LINK_STUB(d_ErrOkDlg, ErrOkDlg) |
||||
LINK_STUB(d_FileErrDlg, FileErrDlg) |
||||
LINK_STUB(d_InsertCDDlg, InsertCDDlg) |
||||
LINK_STUB(d_MainWndProc, MainWndProc) |
||||
LINK_STUB(d_ReadOnlyTest, ReadOnlyTest) |
||||
LINK_STUB(d_RestrictedTest, RestrictedTest) |
||||
LINK_STUB(d_SetWindowProc, SetWindowProc) |
||||
LINK_STUB(d_TermMsg, TermMsg) |
||||
LINK_STUB(d_TraceLastError, TraceLastError) |
||||
LINK_STUB(d_dthread_cleanup, dthread_cleanup) |
||||
LINK_STUB(d_dthread_remove_player, dthread_remove_player) |
||||
LINK_STUB(d_dthread_send_delta, dthread_send_delta) |
||||
LINK_STUB(d_dthread_start, dthread_start) |
||||
LINK_STUB(d_dx_init, dx_init) |
||||
LINK_STUB(d_dx_reinit, dx_reinit) |
||||
LINK_STUB(d_exception_get_filter, exception_get_filter) |
||||
LINK_STUB(d_init_archives, init_archives) |
||||
LINK_STUB(d_init_create_window, init_create_window) |
||||
LINK_STUB(d_init_get_file_info, init_get_file_info) |
||||
LINK_STUB(d_lock_buf_priv, lock_buf_priv) |
||||
LINK_STUB(d_music_start, music_start) |
||||
LINK_STUB(d_music_stop, music_stop) |
||||
LINK_STUB(d_nthread_cleanup, nthread_cleanup) |
||||
LINK_STUB(d_nthread_has_500ms_passed, nthread_has_500ms_passed) |
||||
LINK_STUB(d_nthread_ignore_mutex, nthread_ignore_mutex) |
||||
LINK_STUB(d_nthread_recv_turns, nthread_recv_turns) |
||||
LINK_STUB(d_nthread_send_and_recv_turn, nthread_send_and_recv_turn) |
||||
LINK_STUB(d_nthread_set_turn_upper_bit, nthread_set_turn_upper_bit) |
||||
LINK_STUB(d_nthread_start, nthread_start) |
||||
LINK_STUB(d_nthread_terminate_game, nthread_terminate_game) |
||||
LINK_STUB(d_play_movie, play_movie) |
||||
LINK_STUB(d_snd_init, snd_init) |
||||
LINK_STUB(d_snd_play_snd, snd_play_snd) |
||||
LINK_STUB(d_snd_playing, snd_playing) |
||||
LINK_STUB(d_snd_stop_snd, snd_stop_snd) |
||||
LINK_STUB(d_snd_update, snd_update) |
||||
LINK_STUB(d_sound_file_cleanup, sound_file_cleanup) |
||||
LINK_STUB(d_sound_file_load, sound_file_load) |
||||
LINK_STUB(d_sound_get_or_set_music_volume, sound_get_or_set_music_volume) |
||||
LINK_STUB(d_sound_get_or_set_sound_volume, sound_get_or_set_sound_volume) |
||||
LINK_STUB(d_unlock_buf_priv, unlock_buf_priv) |
||||
@ -0,0 +1,55 @@
|
||||
#include <assert.h> |
||||
#include <string.h> |
||||
#include <sys/mman.h> |
||||
|
||||
#include "Stub/stubs.h" |
||||
#include "absolute.h" |
||||
#include "hook.h" |
||||
|
||||
static void missing_import() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
static void link_imports() |
||||
{ |
||||
#define LINK_IMPORT(imp_name, name) imp_name = (void *)name; |
||||
#define MISSING_IMPORT(imp_name, name) imp_name = (void *)missing_import; |
||||
|
||||
#include "absolute-imports.h" |
||||
} |
||||
|
||||
static void link_stubs() |
||||
{ |
||||
#define LINK_STUB(orig, dest) hook((void *)orig, (void *)dest); |
||||
#include "absolute-stubs.h" |
||||
|
||||
LINK_STUB(d_srand, srand_miniwin); |
||||
LINK_STUB(d_rand, rand_miniwin); |
||||
LINK_STUB(d_time, time); |
||||
|
||||
LINK_STUB(d_sprintf, sprintf); // Calls into kernel
|
||||
|
||||
// These functions potentially access uninitialized memory
|
||||
LINK_STUB(d_strcat, strcat); |
||||
LINK_STUB(d_strcpy, strcpy); |
||||
LINK_STUB(d_strlen, strlen); |
||||
|
||||
// strchr() is overloaded in glibc C++ mode, pick right function....
|
||||
char *(*strchr_overload)(char *, int) = strchr; |
||||
LINK_STUB(d_strchr, strchr_overload); |
||||
} |
||||
|
||||
static void protect_rdata(int prot) |
||||
{ |
||||
mprotect(&__start_rdata, &__end_rdata - &__start_rdata, prot); |
||||
} |
||||
|
||||
void init_absolute() |
||||
{ |
||||
protect_rdata(PROT_READ | PROT_WRITE); |
||||
link_imports(); |
||||
protect_rdata(PROT_READ); |
||||
|
||||
link_stubs(); |
||||
} |
||||
@ -0,0 +1,6 @@
|
||||
#pragma once |
||||
|
||||
#include "../types.h" |
||||
#include "absolute-decls.h" |
||||
|
||||
void init_absolute(); |
||||
@ -0,0 +1,230 @@
|
||||
/* Script for -z combreloc -z separate-code: combine and sort reloc sections with separate code segment */ |
||||
/* Copyright (C) 2014-2018 Free Software Foundation, Inc. |
||||
Copying and distribution of this script, with or without modification, |
||||
are permitted in any medium without royalty provided the copyright |
||||
notice and this notice are preserved. */ |
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386", |
||||
"elf32-i386") |
||||
OUTPUT_ARCH(i386) |
||||
ENTRY(_start) |
||||
SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu32"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/i386-linux-gnu/lib32"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib32"); SEARCH_DIR("=/usr/i386-linux-gnu/lib"); |
||||
SECTIONS |
||||
{ |
||||
INCLUDE "sections.ld" |
||||
|
||||
/* Note: Start address of regular sections was adjusted for |
||||
there to be enough contiguous virtual address space for eg. Valgrind. */ |
||||
|
||||
/* Read-only sections, merged into text segment: */ |
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0A00000)); |
||||
. = SEGMENT_START("text-segment", 0x0A00000) + SIZEOF_HEADERS; |
||||
|
||||
.interp : { *(.interp) } |
||||
.note.gnu.build-id : { *(.note.gnu.build-id) } |
||||
.hash : { *(.hash) } |
||||
.gnu.hash : { *(.gnu.hash) } |
||||
.dynsym : { *(.dynsym) } |
||||
.dynstr : { *(.dynstr) } |
||||
.gnu.version : { *(.gnu.version) } |
||||
.gnu.version_d : { *(.gnu.version_d) } |
||||
.gnu.version_r : { *(.gnu.version_r) } |
||||
.rel.dyn : |
||||
{ |
||||
*(.rel.init) |
||||
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) |
||||
*(.rel.fini) |
||||
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) |
||||
*(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) |
||||
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) |
||||
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) |
||||
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) |
||||
*(.rel.ctors) |
||||
*(.rel.dtors) |
||||
*(.rel.got) |
||||
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) |
||||
*(.rel.ifunc) |
||||
} |
||||
.rel.plt : |
||||
{ |
||||
*(.rel.plt) |
||||
PROVIDE_HIDDEN (__rel_iplt_start = .); |
||||
*(.rel.iplt) |
||||
PROVIDE_HIDDEN (__rel_iplt_end = .); |
||||
} |
||||
. = ALIGN(CONSTANT (MAXPAGESIZE)); |
||||
.init : |
||||
{ |
||||
KEEP (*(SORT_NONE(.init))) |
||||
} |
||||
.plt : { *(.plt) *(.iplt) } |
||||
.plt.got : { *(.plt.got) } |
||||
.plt.sec : { *(.plt.sec) } |
||||
.text : |
||||
{ |
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*) |
||||
*(.text.exit .text.exit.*) |
||||
*(.text.startup .text.startup.*) |
||||
*(.text.hot .text.hot.*) |
||||
*(.text .stub .text.* .gnu.linkonce.t.*) |
||||
/* .gnu.warning sections are handled specially by elf32.em. */ |
||||
*(.gnu.warning) |
||||
} |
||||
.fini : |
||||
{ |
||||
KEEP (*(SORT_NONE(.fini))) |
||||
} |
||||
PROVIDE (__etext = .); |
||||
PROVIDE (_etext = .); |
||||
PROVIDE (etext = .); |
||||
. = ALIGN(CONSTANT (MAXPAGESIZE)); |
||||
/* Adjust the address for the rodata segment. We want to adjust up to |
||||
the same address within the page on the next page up. */ |
||||
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1))); |
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } |
||||
.rodata1 : { *(.rodata1) } |
||||
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } |
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } |
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table |
||||
.gcc_except_table.*) } |
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } |
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */ |
||||
.exception_ranges : ONLY_IF_RO { *(.exception_ranges |
||||
.exception_ranges*) } |
||||
/* Adjust the address for the data segment. We want to adjust up to |
||||
the same address within the page on the next page up. */ |
||||
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); |
||||
/* Exception handling */ |
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } |
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) } |
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } |
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } |
||||
/* Thread Local Storage sections */ |
||||
.tdata : |
||||
{ |
||||
PROVIDE_HIDDEN (__tdata_start = .); |
||||
*(.tdata .tdata.* .gnu.linkonce.td.*) |
||||
} |
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } |
||||
.preinit_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__preinit_array_start = .); |
||||
KEEP (*(.preinit_array)) |
||||
PROVIDE_HIDDEN (__preinit_array_end = .); |
||||
} |
||||
.init_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__init_array_start = .); |
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) |
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) |
||||
PROVIDE_HIDDEN (__init_array_end = .); |
||||
} |
||||
.fini_array : |
||||
{ |
||||
PROVIDE_HIDDEN (__fini_array_start = .); |
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) |
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) |
||||
PROVIDE_HIDDEN (__fini_array_end = .); |
||||
} |
||||
.ctors : |
||||
{ |
||||
/* gcc uses crtbegin.o to find the start of |
||||
the constructors, so we make sure it is |
||||
first. Because this is a wildcard, it |
||||
doesn't matter if the user does not |
||||
actually link against crtbegin.o; the |
||||
linker won't look for a file to match a |
||||
wildcard. The wildcard also means that it |
||||
doesn't matter which directory crtbegin.o |
||||
is in. */ |
||||
KEEP (*crtbegin.o(.ctors)) |
||||
KEEP (*crtbegin?.o(.ctors)) |
||||
/* We don't want to include the .ctor section from |
||||
the crtend.o file until after the sorted ctors. |
||||
The .ctor section from the crtend file contains the |
||||
end of ctors marker and it must be last */ |
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) |
||||
KEEP (*(SORT(.ctors.*))) |
||||
KEEP (*(.ctors)) |
||||
} |
||||
.dtors : |
||||
{ |
||||
KEEP (*crtbegin.o(.dtors)) |
||||
KEEP (*crtbegin?.o(.dtors)) |
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) |
||||
KEEP (*(SORT(.dtors.*))) |
||||
KEEP (*(.dtors)) |
||||
} |
||||
.jcr : { KEEP (*(.jcr)) } |
||||
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } |
||||
.dynamic : { *(.dynamic) } |
||||
.got : { *(.got) *(.igot) } |
||||
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 12 ? 12 : 0, .); |
||||
.got.plt : { *(.got.plt) *(.igot.plt) } |
||||
.data : |
||||
{ |
||||
*(.data .data.* .gnu.linkonce.d.*) |
||||
SORT(CONSTRUCTORS) |
||||
} |
||||
.data1 : { *(.data1) } |
||||
_edata = .; PROVIDE (edata = .); |
||||
. = .; |
||||
__bss_start = .; |
||||
.bss : |
||||
{ |
||||
*(.dynbss) |
||||
*(.bss .bss.* .gnu.linkonce.b.*) |
||||
*(COMMON) |
||||
/* Align here to ensure that the .bss section occupies space up to |
||||
_end. Align after .bss to ensure correct alignment even if the |
||||
.bss section disappears because there are no input sections. |
||||
FIXME: Why do we need it? When there is no .bss section, we don't |
||||
pad the .data section. */ |
||||
. = ALIGN(. != 0 ? 32 / 8 : 1); |
||||
} |
||||
. = ALIGN(32 / 8); |
||||
. = SEGMENT_START("ldata-segment", .); |
||||
. = ALIGN(32 / 8); |
||||
_end = .; PROVIDE (end = .); |
||||
. = DATA_SEGMENT_END (.); |
||||
/* Stabs debugging sections. */ |
||||
.stab 0 : { *(.stab) } |
||||
.stabstr 0 : { *(.stabstr) } |
||||
.stab.excl 0 : { *(.stab.excl) } |
||||
.stab.exclstr 0 : { *(.stab.exclstr) } |
||||
.stab.index 0 : { *(.stab.index) } |
||||
.stab.indexstr 0 : { *(.stab.indexstr) } |
||||
.comment 0 : { *(.comment) } |
||||
/* DWARF debug sections. |
||||
Symbols in the DWARF debugging sections are relative to the beginning |
||||
of the section so we begin them at 0. */ |
||||
/* DWARF 1 */ |
||||
.debug 0 : { *(.debug) } |
||||
.line 0 : { *(.line) } |
||||
/* GNU DWARF 1 extensions */ |
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) } |
||||
.debug_sfnames 0 : { *(.debug_sfnames) } |
||||
/* DWARF 1.1 and DWARF 2 */ |
||||
.debug_aranges 0 : { *(.debug_aranges) } |
||||
.debug_pubnames 0 : { *(.debug_pubnames) } |
||||
/* DWARF 2 */ |
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } |
||||
.debug_abbrev 0 : { *(.debug_abbrev) } |
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } |
||||
.debug_frame 0 : { *(.debug_frame) } |
||||
.debug_str 0 : { *(.debug_str) } |
||||
.debug_loc 0 : { *(.debug_loc) } |
||||
.debug_macinfo 0 : { *(.debug_macinfo) } |
||||
/* SGI/MIPS DWARF 2 extensions */ |
||||
.debug_weaknames 0 : { *(.debug_weaknames) } |
||||
.debug_funcnames 0 : { *(.debug_funcnames) } |
||||
.debug_typenames 0 : { *(.debug_typenames) } |
||||
.debug_varnames 0 : { *(.debug_varnames) } |
||||
/* DWARF 3 */ |
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) } |
||||
.debug_ranges 0 : { *(.debug_ranges) } |
||||
/* DWARF Extension. */ |
||||
.debug_macro 0 : { *(.debug_macro) } |
||||
.debug_addr 0 : { *(.debug_addr) } |
||||
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } |
||||
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } |
||||
} |
||||
@ -0,0 +1,32 @@
|
||||
#include <assert.h> |
||||
#include <sys/mman.h> |
||||
|
||||
#include "hook.h" |
||||
|
||||
#pragma pack(push, 1) |
||||
struct hook_jmp_rel32 { |
||||
uint8_t op; |
||||
int32_t offset; |
||||
}; |
||||
#pragma pack(pop) |
||||
|
||||
static void hook_assemble_jump(void *at, void *to) |
||||
{ |
||||
hook_jmp_rel32 *jmp = (hook_jmp_rel32 *)at; |
||||
|
||||
jmp->op = 0xE9; |
||||
jmp->offset = (intptr_t)to - ((intptr_t)at + sizeof(*jmp)); |
||||
} |
||||
|
||||
static int hook_unprotect(void *address, size_t size) |
||||
{ |
||||
// Align to bottom of page
|
||||
address = (void *)((uintptr_t)address & ~(4096 - 1)); |
||||
return mprotect(address, size, PROT_READ | PROT_WRITE | PROT_EXEC); |
||||
} |
||||
|
||||
void hook(void *at, void *to) |
||||
{ |
||||
assert(hook_unprotect(at, sizeof(hook_jmp_rel32)) == 0); |
||||
hook_assemble_jump(at, to); |
||||
} |
||||
@ -0,0 +1,6 @@
|
||||
#pragma once |
||||
|
||||
#include <stddef.h> |
||||
#include <stdint.h> |
||||
|
||||
void hook(void *at, void *to); |
||||
@ -0,0 +1,4 @@
|
||||
. = 0x00401000; .d.text : { *(.d.text) } |
||||
. = 0x00479000; .d.rdata : { *(.d.rdata) } |
||||
. = 0x00483000; .d.data : { *(.d.data) } |
||||
. = 0x004B7930; .d.bss : { *(.d.bss) } |
||||
@ -0,0 +1,22 @@
|
||||
message(STATUS "Using 32-bit toolchain") |
||||
|
||||
set(CMAKE_CXX_FLAGS -m32 CACHE STRING "") |
||||
|
||||
# Affects pkg-config |
||||
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS TRUE) |
||||
# Used by pkg-config on Debian |
||||
set(CMAKE_LIBRARY_ARCHITECTURE i386-linux-gnu) |
||||
# Silly hack required to get the pkg-config path code to activate |
||||
list(APPEND CMAKE_PREFIX_PATH /usr) |
||||
|
||||
# Find where 32-bit CMake modules are stored |
||||
find_path(DIR NAMES cmake PATHS /usr/lib32 /usr/lib/i386-linux-gnu NO_DEFAULT_PATH) |
||||
|
||||
if(DIR) |
||||
message(STATUS "Using 32-bit libraries from ${DIR}") |
||||
# Read CMake modules from 32-bit packages |
||||
set(CMAKE_FIND_ROOT_PATH ${DIR}) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) |
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) |
||||
endif() |
||||
@ -0,0 +1,16 @@
|
||||
include(FindPkgConfig) |
||||
|
||||
pkg_check_modules(SDL2 sdl2) |
||||
|
||||
if(NOT SDL2_LIBRARIES) |
||||
find_package(SDL2 REQUIRED) |
||||
|
||||
# WORKAROUND: Arch Linux SDL2 cmake config not setting this variable |
||||
if(NOT SDL2_LIBRARIES) |
||||
# Note: you will probably need to install multilib/lib32-dbus on Arch |
||||
set(SDL2_LIBRARIES SDL2::SDL2) |
||||
endif() |
||||
endif() |
||||
|
||||
# WORKAROUND: Issue with Ubuntu 16.04 having whitespace (CMP0004) |
||||
string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES) |
||||
@ -0,0 +1,36 @@
|
||||
set(ORIGINAL_EXE "${CMAKE_SOURCE_DIR}/Diablo.exe") |
||||
|
||||
if(EXISTS "${ORIGINAL_EXE}") |
||||
message(STATUS "Using EXE at ${ORIGINAL_EXE}") |
||||
|
||||
file(MD5 ${ORIGINAL_EXE} MD5SUM) |
||||
if(NOT MD5SUM STREQUAL "da62d5cd8bd71a0b66e6d4ef7a111233") |
||||
message(FATAL_ERROR "MD5 of EXE is not correct (${MD5SUM})") |
||||
endif() |
||||
|
||||
find_program(ASM NAMES nasm yasm) |
||||
|
||||
set(HARNESS_OBJECT "${CMAKE_BINARY_DIR}/harness.o") |
||||
set(HARNESS_ASM "${CMAKE_SOURCE_DIR}/Absolute/harness.asm") |
||||
|
||||
add_library(harness OBJECT ${HARNESS_OBJECT}) |
||||
target_compile_options(harness PUBLIC -no-pie) |
||||
target_compile_definitions(harness INTERFACE -DNO_GLOBALS) |
||||
# For some reason, HARNESS_OBJECT needs to be added here even though it's in the sources above |
||||
target_link_libraries(harness INTERFACE |
||||
${HARNESS_OBJECT} |
||||
-L${CMAKE_SOURCE_DIR}/Absolute -Tdefault.ld |
||||
) |
||||
|
||||
add_custom_command( |
||||
COMMENT Assembling |
||||
OUTPUT ${HARNESS_OBJECT} |
||||
MAIN_DEPENDENCY ${HARNESS_ASM} |
||||
COMMAND ${ASM} |
||||
-f elf -DEXE=\\"${ORIGINAL_EXE}\\" |
||||
-o ${HARNESS_OBJECT} |
||||
${HARNESS_ASM} |
||||
) |
||||
else() |
||||
message(STATUS "Original .exe not found at ${ORIGINAL_EXE}") |
||||
endif() |
||||
@ -0,0 +1,3 @@
|
||||
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) |
||||
message(WARNING [[In-source build detected, please eg. create a new directory and use `cmake ..`]]) |
||||
endif() |
||||
@ -0,0 +1,18 @@
|
||||
include(CheckCXXCompilerFlag) |
||||
include(CMakePushCheckState) |
||||
|
||||
set(SANITIZE_OPTIONS -fsanitize=null -fsanitize=return) |
||||
# TODO: use "-fsanitize=object-size" |
||||
# "-fsanitize=bounds" not enabled because the code often generates temporary pointers out-of-bounds of arrays |
||||
|
||||
# Note: The compiler must always support recovery because the decompiled code is not ASAN-clean |
||||
set(SANITIZE_ADDRESS_FLAGS -fsanitize=address -fsanitize-recover=address) |
||||
|
||||
cmake_push_check_state() |
||||
set(CMAKE_REQUIRED_LIBRARIES ${SANITIZE_ADDRESS_FLAGS}) |
||||
check_cxx_compiler_flag("${SANITIZE_ADDRESS_FLAGS}" HAS_SANITIZE_ADDRESS) |
||||
cmake_pop_check_state() |
||||
|
||||
if(HAS_SANITIZE_ADDRESS) |
||||
list(APPEND SANITIZE_OPTIONS ${SANITIZE_ADDRESS_FLAGS}) |
||||
endif() |
||||
@ -0,0 +1,220 @@
|
||||
cmake_minimum_required(VERSION 3.5) |
||||
|
||||
# Turn on modern `try_compile()` policies. |
||||
if(POLICY CMP0066) |
||||
cmake_policy(SET CMP0066 NEW) |
||||
endif() |
||||
if(POLICY CMP0067) |
||||
cmake_policy(SET CMP0067 NEW) |
||||
endif() |
||||
|
||||
include(CMake/out_of_tree.cmake) |
||||
|
||||
# This *must* be included before calling `project()`, due to setting early compiler flags. |
||||
include(CMake/32bit.cmake) |
||||
|
||||
set(CMAKE_CXX_STANDARD 11) |
||||
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) |
||||
|
||||
project(devil-miniwin |
||||
VERSION 0.0.1 |
||||
LANGUAGES C CXX |
||||
) |
||||
|
||||
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 4) |
||||
message(WARNING "sizeof(void*) == ${CMAKE_SIZEOF_VOID_P}.") |
||||
message(FATAL_ERROR [[This project can only be compiled in 32-bit mode.]]) |
||||
endif() |
||||
|
||||
# Note: In Debug mode, GCC generates spurious memory references that upset Valgrind, |
||||
# these options fix that. |
||||
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-omit-frame-pointer") |
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") |
||||
# Clang/LLVM optimizations break everything |
||||
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Og") |
||||
endif() |
||||
|
||||
set(SOURCES |
||||
Source/automap.cpp |
||||
Source/codec.cpp |
||||
Source/control.cpp |
||||
Source/cursor.cpp |
||||
Source/dead.cpp |
||||
Source/debug.cpp |
||||
Source/diablo.cpp |
||||
Source/doom.cpp |
||||
Source/drlg_l1.cpp |
||||
Source/drlg_l2.cpp |
||||
Source/drlg_l3.cpp |
||||
Source/drlg_l4.cpp |
||||
Source/effects.cpp |
||||
Source/encrypt.cpp |
||||
Source/engine.cpp |
||||
Source/error.cpp |
||||
Source/gamemenu.cpp |
||||
Source/gendung.cpp |
||||
Source/gmenu.cpp |
||||
Source/help.cpp |
||||
Source/interfac.cpp |
||||
Source/inv.cpp |
||||
Source/items.cpp |
||||
Source/lighting.cpp |
||||
Source/loadsave.cpp |
||||
Source/mainmenu.cpp |
||||
Source/minitext.cpp |
||||
Source/missiles.cpp |
||||
Source/monster.cpp |
||||
Source/mpqapi.cpp |
||||
Source/msgcmd.cpp |
||||
Source/msg.cpp |
||||
Source/multi.cpp |
||||
Source/objects.cpp |
||||
Source/pack.cpp |
||||
Source/palette.cpp |
||||
Source/path.cpp |
||||
Source/pfile.cpp |
||||
Source/player.cpp |
||||
Source/plrmsg.cpp |
||||
Source/portal.cpp |
||||
Source/quests.cpp |
||||
Source/render.cpp |
||||
Source/scrollrt.cpp |
||||
Source/setmaps.cpp |
||||
Source/sha.cpp |
||||
Source/spells.cpp |
||||
Source/stores.cpp |
||||
Source/sync.cpp |
||||
Source/textdat.cpp |
||||
Source/themes.cpp |
||||
Source/tmsg.cpp |
||||
Source/town.cpp |
||||
Source/towners.cpp |
||||
Source/track.cpp |
||||
Source/trigs.cpp |
||||
Source/wave.cpp |
||||
|
||||
3rdParty/PKWare/explode.cpp |
||||
3rdParty/PKWare/implode.cpp |
||||
) |
||||
|
||||
# Stubbed out sources, for reference |
||||
set(ORIGINAL_SOURCES |
||||
Source/capture.cpp |
||||
Source/appfat.cpp |
||||
Source/dthread.cpp |
||||
Source/dx.cpp |
||||
Source/fault.cpp |
||||
Source/init.cpp |
||||
Source/logging.cpp |
||||
Source/movie.cpp |
||||
Source/nthread.cpp |
||||
Source/restrict.cpp |
||||
Source/sound.cpp |
||||
) |
||||
|
||||
set(STUB_SOURCES |
||||
Stub/miniwin.cpp |
||||
Stub/miniwin_rand.cpp |
||||
Stub/appfat.cpp |
||||
Stub/capture.cpp |
||||
Stub/dthread.cpp |
||||
Stub/dx.cpp |
||||
Stub/fault.cpp |
||||
Stub/init.cpp |
||||
Stub/movie.cpp |
||||
Stub/nthread.cpp |
||||
Stub/restrict.cpp |
||||
Stub/sound.cpp |
||||
Stub/storm.cpp |
||||
Stub/diabloui.cpp |
||||
Stub/miniwin_io.cpp |
||||
Stub/miniwin_msg_sdl.cpp |
||||
Stub/storm_net.cpp |
||||
Stub/validate.cpp |
||||
|
||||
3rdParty/StormLib/src/FileStream.cpp |
||||
3rdParty/StormLib/src/SBaseCommon.cpp |
||||
3rdParty/StormLib/src/SBaseFileTable.cpp |
||||
3rdParty/StormLib/src/SBaseSubTypes.cpp |
||||
3rdParty/StormLib/src/SCompression.cpp |
||||
3rdParty/StormLib/src/SFileExtractFile.cpp |
||||
3rdParty/StormLib/src/SFileFindFile.cpp |
||||
3rdParty/StormLib/src/SFileGetFileInfo.cpp |
||||
3rdParty/StormLib/src/SFileOpenArchive.cpp |
||||
3rdParty/StormLib/src/SFileOpenFileEx.cpp |
||||
3rdParty/StormLib/src/SFileReadFile.cpp |
||||
) |
||||
|
||||
include(CMake/SDL2_fixed.cmake) |
||||
include(CMake/sanitize.cmake) |
||||
include(CMake/absolute.cmake) |
||||
|
||||
include_directories(${SDL2_INCLUDE_DIRS}) |
||||
|
||||
include_directories(. Stub) |
||||
|
||||
# FUTURE: use add_compile_definitions() |
||||
add_definitions( |
||||
-D_DEBUG |
||||
-DMINIWIN |
||||
# Skip fades and other fluff |
||||
-DFASTER |
||||
) |
||||
|
||||
# Ignore serious warnings due to "quality" of decompiled code |
||||
add_compile_options(-fpermissive -Wno-write-strings -Wno-multichar) |
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") |
||||
# Style issues |
||||
add_compile_options(-Wno-parentheses -Wno-logical-op-parentheses -Wno-bitwise-op-parentheses) |
||||
# Silence warnings about __int64 alignment hack not always being applicable |
||||
add_compile_options(-Wno-ignored-attributes) |
||||
# Fix: error: cast from pointer to smaller type 'unsigned char' loses information |
||||
add_compile_options(-fms-extensions) |
||||
endif() |
||||
|
||||
# Vanilla build |
||||
add_executable(devilution |
||||
${SOURCES} |
||||
${STUB_SOURCES} |
||||
Stub/main.cpp |
||||
) |
||||
|
||||
target_link_libraries(devilution PUBLIC |
||||
m |
||||
${SDL2_LIBRARIES} |
||||
) |
||||
|
||||
# Build with harness enabled (conflicts with sanitizers) |
||||
if(TARGET harness) |
||||
add_executable(devil-harness |
||||
${SOURCES} |
||||
${STUB_SOURCES} |
||||
Stub/main_harness.cpp |
||||
Absolute/absolute.cpp |
||||
Absolute/hook.cpp |
||||
) |
||||
|
||||
target_link_libraries(devil-harness PUBLIC |
||||
m |
||||
harness |
||||
${SDL2_LIBRARIES} |
||||
) |
||||
endif() |
||||
|
||||
# Build with sanitizers enabled |
||||
add_executable(devil-sanitize |
||||
${SOURCES} |
||||
${STUB_SOURCES} |
||||
Stub/main_test.cpp |
||||
) |
||||
|
||||
target_compile_options(devil-sanitize PRIVATE |
||||
${SANITIZE_OPTIONS} |
||||
) |
||||
|
||||
target_link_libraries(devil-sanitize PUBLIC |
||||
m |
||||
${SDL2_LIBRARIES} |
||||
${SANITIZE_OPTIONS} |
||||
) |
||||
@ -0,0 +1,14 @@
|
||||
--- |
||||
IndentWidth: 4 |
||||
TabWidth: 4 |
||||
--- |
||||
Language: Cpp |
||||
UseTab: ForIndentation |
||||
AlignTrailingComments: false |
||||
BreakBeforeBraces: Linux |
||||
ColumnLimit: 120 |
||||
IncludeBlocks: Preserve |
||||
AlignEscapedNewlines: DontAlign |
||||
AlignOperands: true |
||||
AllowShortFunctionsOnASingleLine: Inline |
||||
Standard: Cpp11 |
||||
@ -0,0 +1,66 @@
|
||||
#include <stdarg.h> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
char empty_string = 0; |
||||
|
||||
void TermMsg(char *pszFmt, ...) |
||||
{ |
||||
char buf[256]; |
||||
|
||||
va_list args; |
||||
va_start(args, pszFmt); |
||||
|
||||
vsnprintf(buf, sizeof(buf), pszFmt, args); |
||||
|
||||
eprintf("%s: %s\n", __FUNCTION__, buf); |
||||
abort(); |
||||
} |
||||
|
||||
void __fastcall ErrDlg(int template_id, int error_code, char *log_file_path, int log_line_nr) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall ErrOkDlg(int template_id, int error_code, char *log_file_path, int log_line_nr) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall DirErrorDlg(char *error) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
bool __cdecl InsertCDDlg() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall FileErrDlg(char *error) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall DDErrMsg(int error_code, int log_line_nr, char *log_file_path) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall DiskFreeDlg(char *error) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void DrawDlg(char *pszFmt, ...) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
char *__cdecl TraceLastError() |
||||
{ |
||||
DUMMY(); |
||||
|
||||
return NULL; |
||||
} |
||||
@ -0,0 +1,7 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
void __cdecl CaptureScreen() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
@ -0,0 +1,182 @@
|
||||
#include <vector> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
void __cdecl UiDestroy() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
BOOL __stdcall UiTitleDialog(int a1) |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
void __cdecl UiInitialize() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
static std::vector<_uiheroinfo> hero_infos; |
||||
|
||||
static BOOL __stdcall ui_add_hero_info(_uiheroinfo *info) |
||||
{ |
||||
hero_infos.emplace_back(*info); |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL __stdcall UiSelHeroSingDialog(BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinfo *)), |
||||
BOOL(__stdcall *fncreate)(_uiheroinfo *), BOOL(__stdcall *fnremove)(_uiheroinfo *), |
||||
BOOL(__stdcall *fnstats)(int, _uidefaultstats *), int *dlgresult, char *name, |
||||
int *difficulty) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
hero_infos.clear(); |
||||
fninfo(&ui_add_hero_info); |
||||
|
||||
// If a hero is available, load it, otherwise create a new one
|
||||
if (!hero_infos.empty()) { |
||||
const char *hero_name = hero_infos[0].name; |
||||
DUMMY_PRINT("use hero: %s", hero_name); |
||||
strcpy(name, hero_name); |
||||
|
||||
*dlgresult = 2; |
||||
} else { |
||||
const char *test_name = "tester"; |
||||
DUMMY_PRINT("create hero: %s", test_name); |
||||
|
||||
strcpy(name, test_name); |
||||
|
||||
_uiheroinfo hero_info = {0}; |
||||
strcpy(hero_info.name, test_name); |
||||
hero_info.heroclass = PC_SORCERER; |
||||
|
||||
fncreate(&hero_info); |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL __stdcall UiMainMenuDialog(char *name, int *pdwResult, void(__stdcall *fnSound)(char *file), int a4) |
||||
{ |
||||
DUMMY(); |
||||
// Pretend we selected Single Player from the main menu
|
||||
*pdwResult = MAINMENU_SINGLE_PLAYER; |
||||
return TRUE; |
||||
} |
||||
|
||||
int __cdecl UiProfileGetString() |
||||
{ |
||||
DUMMY(); |
||||
return 0; |
||||
} |
||||
|
||||
void __stdcall UiSetupPlayerInfo(char *infostr, _uiheroinfo *pInfo, int type) |
||||
{ |
||||
DUMMY_PRINT("chr: %s", infostr); |
||||
} |
||||
|
||||
BOOL __stdcall UiCopyProtError(int *pdwResult) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __stdcall UiAppActivate(BOOL bActive) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __fastcall UiValidPlayerName(char *name) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __stdcall UiProgressDialog(HWND window, char *msg, int a3, void *fnfunc, int a5) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiSelHeroMultDialog(BOOL(__stdcall *fninfo)(BOOL(__stdcall *fninfofunc)(_uiheroinfo *)), |
||||
BOOL(__stdcall *fncreate)(_uiheroinfo *), BOOL(__stdcall *fnremove)(_uiheroinfo *), |
||||
BOOL(__stdcall *fnstats)(int, _uidefaultstats *), int *dlgresult, int *a6, |
||||
char *name) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiCreditsDialog(int a1) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __cdecl UiProfileCallback() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __cdecl UiProfileDraw() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiCategoryCallback(int a1, int a2, int a3, int a4, int a5, _DWORD *a6, _DWORD *a7) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiGetDataCallback(int game_type, int data_code, void *a3, int a4, int a5) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiAuthCallback(int a1, char *a2, char *a3, char a4, char *a5, LPSTR lpBuffer, int cchBufferMax) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiSoundCallback(int a1, int type, int a3) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __stdcall UiMessageBoxCallback(HWND hWnd, char *lpText, LPCSTR lpCaption, UINT uType) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiDrawDescCallback(int arg0, COLORREF color, LPCSTR lpString, char *a4, int a5, UINT align, time_t a7, |
||||
HDC *a8) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiCreateGameCallback(int a1, int a2, int a3, int a4, int a5, int a6) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL __stdcall UiArtCallback(int game_type, unsigned int art_code, PALETTEENTRY *pPalette, void *pBuffer, |
||||
DWORD dwBuffersize, DWORD *pdwWidth, DWORD *pdwHeight, DWORD *pdwBpp) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __stdcall UiSelectGame(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, |
||||
_SNETVERSIONDATA *file_info, int *a6) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __stdcall UiSelectProvider(int a1, _SNETPROGRAMDATA *client_info, _SNETPLAYERDATA *user_info, _SNETUIDATA *ui_info, |
||||
_SNETVERSIONDATA *file_info, int *type) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __stdcall UiCreatePlayerDescription(_uiheroinfo *info, int mode, char *desc) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
@ -0,0 +1,22 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
void __cdecl dthread_start() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __cdecl dthread_cleanup() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __fastcall dthread_send_delta(int pnum, char cmd, void *pbSrc, int dwLen) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __fastcall dthread_remove_player(int pnum) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
@ -0,0 +1,375 @@
|
||||
#include "dx_stub.h" |
||||
#include "miniwin_sdl.h" |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#ifndef NO_GLOBALS |
||||
Screen *gpBuffer; |
||||
|
||||
IDirectDraw *lpDDInterface; |
||||
IDirectDrawSurface *lpDDSPrimary; |
||||
IDirectDrawSurface *lpDDSBackBuf; |
||||
IDirectDrawPalette *lpDDPalette; |
||||
|
||||
char gbBackBuf; // unread
|
||||
char gbEmulate; // unread
|
||||
#endif |
||||
|
||||
SDL_Window *sdl_window; |
||||
SDL_Renderer *sdl_renderer; |
||||
SDL_Texture *sdl_render_texture; |
||||
|
||||
/** 32-bit in-memory backbuffer surface */ |
||||
SDL_Surface *sdl_surface; |
||||
|
||||
/** 8-bit surface wrapper around #gpBuffer */ |
||||
SDL_Surface *sdl_pal_surface; |
||||
/** Currently active palette */ |
||||
SDL_Palette *sdl_palette; |
||||
|
||||
/**
|
||||
* Is #sdl_pal_surface dirty? |
||||
* |
||||
* This is required so the front buffer would not be updated twice per game loop in unlock_buf_priv() |
||||
* which causes the cursor to flicker. |
||||
*/ |
||||
bool surface_dirty; |
||||
|
||||
//
|
||||
// DirectDraw COM interface stub implementations
|
||||
//
|
||||
|
||||
#define METHOD virtual __stdcall |
||||
|
||||
class StubSurface : public IDirectDrawSurface |
||||
{ |
||||
METHOD HRESULT QueryInterface(REFIID refiid, LPVOID *lpvoid) { UNIMPLEMENTED(); }; |
||||
METHOD ULONG AddRef() { UNIMPLEMENTED(); }; |
||||
METHOD ULONG Release() { UNIMPLEMENTED(); }; |
||||
|
||||
METHOD HRESULT AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT AddOverlayDirtyRect(LPRECT lpRect) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT Blt(LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, |
||||
LPDDBLTFX lpDDBltFx) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT BltBatch(LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
|
||||
METHOD HRESULT BltFast(DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(lpDDSrcSurface == lpDDSBackBuf); |
||||
|
||||
int w = lpSrcRect->right - lpSrcRect->left + 1; |
||||
int h = lpSrcRect->bottom - lpSrcRect->top + 1; |
||||
|
||||
SDL_Rect src_rect = {lpSrcRect->left, lpSrcRect->top, w, h}; |
||||
SDL_Rect dst_rect = {(int)dwX, (int)dwY, w, h}; |
||||
|
||||
// Convert from 8-bit to 32-bit
|
||||
SDL_CHECK(SDL_BlitSurface(sdl_pal_surface, &src_rect, sdl_surface, &dst_rect)); |
||||
|
||||
surface_dirty = true; |
||||
return S_OK; |
||||
} |
||||
|
||||
METHOD HRESULT DeleteAttachedSurface(DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSAttachedSurface) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT EnumAttachedSurfaces(LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT EnumOverlayZOrders(DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetAttachedSurface(LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT GetBltStatus(DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetCaps(LPDDSCAPS lpDDSCaps) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetColorKey(DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) { UNIMPLEMENTED(); } |
||||
|
||||
METHOD HRESULT GetDC(HDC *lphDC) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return S_OK; |
||||
} |
||||
|
||||
METHOD HRESULT GetFlipStatus(DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetOverlayPosition(LPLONG lplX, LPLONG lplY) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT Initialize(LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc) { UNIMPLEMENTED(); } |
||||
|
||||
METHOD HRESULT IsLost() |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return S_OK; |
||||
} |
||||
|
||||
METHOD HRESULT Lock(LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
METHOD HRESULT ReleaseDC(HDC hDC) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return S_OK; |
||||
} |
||||
|
||||
METHOD HRESULT Restore() { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetColorKey(DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetOverlayPosition(LONG lX, LONG lY) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetPalette(LPDIRECTDRAWPALETTE lpDDPalette) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT Unlock(LPVOID lpSurfaceData) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT UpdateOverlay(LPRECT lpSrcRect, LPDIRECTDRAWSURFACE lpDDDestSurface, LPRECT lpDestRect, |
||||
DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT UpdateOverlayDisplay(DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT UpdateOverlayZOrder(DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSReference) { UNIMPLEMENTED(); } |
||||
}; |
||||
|
||||
class StubPalette : public IDirectDrawPalette |
||||
{ |
||||
METHOD HRESULT QueryInterface(REFIID refiid, LPVOID *lpvoid) { UNIMPLEMENTED(); }; |
||||
METHOD ULONG AddRef() { UNIMPLEMENTED(); }; |
||||
METHOD ULONG Release() { UNIMPLEMENTED(); }; |
||||
|
||||
METHOD HRESULT GetCaps(LPDWORD lpdwCaps) { UNIMPLEMENTED(); }; |
||||
METHOD HRESULT GetEntries(DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
}; |
||||
METHOD HRESULT Initialize(LPDIRECTDRAW lpDD, DWORD dwFlags, LPPALETTEENTRY lpDDColorTable) { UNIMPLEMENTED(); }; |
||||
METHOD HRESULT SetEntries(DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
}; |
||||
}; |
||||
|
||||
class StubDraw : public IDirectDraw |
||||
{ |
||||
METHOD HRESULT QueryInterface(REFIID refiid, LPVOID *lpvoid) { UNIMPLEMENTED(); }; |
||||
METHOD ULONG AddRef() { UNIMPLEMENTED(); }; |
||||
METHOD ULONG Release() { UNIMPLEMENTED(); }; |
||||
|
||||
METHOD HRESULT Compact() { UNIMPLEMENTED(); } |
||||
METHOD HRESULT CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, |
||||
IUnknown *pUnkOuter) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, |
||||
IUnknown *pUnkOuter) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, |
||||
LPDDENUMMODESCALLBACK lpEnumModesCallback) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT EnumSurfaces(DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, |
||||
LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
METHOD HRESULT FlipToGDISurface() { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetFourCCCodes(LPDWORD lpNumCodes, LPDWORD lpCodes) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetMonitorFrequency(LPDWORD lpdwFrequency) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetScanLine(LPDWORD lpdwScanLine) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT GetVerticalBlankStatus(BOOL *lpbIsInVB) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT Initialize(GUID *lpGUID) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT RestoreDisplayMode() { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetCooperativeLevel(HWND hWnd, DWORD dwFlags) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) { UNIMPLEMENTED(); } |
||||
METHOD HRESULT WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent) |
||||
{ |
||||
DUMMY(); |
||||
return S_OK; |
||||
} |
||||
}; |
||||
|
||||
static StubDraw stub_draw; |
||||
static StubSurface stub_surface; |
||||
static StubPalette stub_palette; |
||||
|
||||
//
|
||||
// Main functions
|
||||
//
|
||||
|
||||
void sdl_init_video() |
||||
{ |
||||
SDL_CHECK(SDL_Init(SDL_INIT_VIDEO)); |
||||
|
||||
sdl_window = |
||||
SDL_CreateWindow("devil-test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); |
||||
assert(sdl_window); |
||||
|
||||
// Hack since ShowCursor is called before dx_init()
|
||||
SDL_ShowCursor(SDL_DISABLE); |
||||
|
||||
sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_PRESENTVSYNC); |
||||
assert(sdl_renderer); |
||||
|
||||
// FUTURE: Use SDL_CreateRGBSurfaceWithFormat with SDL_PIXELFORMAT_RGBA8888
|
||||
sdl_surface = SDL_CreateRGBSurface(0, 640, 480, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); |
||||
assert(sdl_surface); |
||||
|
||||
sdl_render_texture = |
||||
SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 640, 480); |
||||
assert(sdl_render_texture); |
||||
|
||||
sdl_palette = SDL_AllocPalette(256); |
||||
assert(sdl_palette); |
||||
} |
||||
|
||||
void __fastcall dx_init(HWND hWnd) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
sdl_init_video(); |
||||
|
||||
gbActive = TRUE; |
||||
|
||||
lpDDInterface = &stub_draw; |
||||
lpDDSPrimary = &stub_surface; |
||||
lpDDSBackBuf = &stub_surface; |
||||
lpDDPalette = &stub_palette; |
||||
} |
||||
|
||||
/** Copy the palette surface to the main backbuffer */ |
||||
void sdl_update_entire_surface() |
||||
{ |
||||
assert(sdl_surface && sdl_pal_surface); |
||||
|
||||
SDL_Rect src_rect = {64, 160, 640, 480}; |
||||
SDL_CHECK(SDL_BlitSurface(sdl_pal_surface, &src_rect, sdl_surface, NULL)); |
||||
} |
||||
|
||||
void sdl_present_surface() |
||||
{ |
||||
assert(!SDL_MUSTLOCK(sdl_surface)); |
||||
SDL_CHECK(SDL_UpdateTexture(sdl_render_texture, NULL, sdl_surface->pixels, sdl_surface->pitch)); |
||||
|
||||
SDL_CHECK(SDL_RenderCopy(sdl_renderer, sdl_render_texture, NULL, NULL)); |
||||
SDL_RenderPresent(sdl_renderer); |
||||
|
||||
surface_dirty = false; |
||||
} |
||||
|
||||
void __cdecl lock_buf_priv() |
||||
{ |
||||
const int pitch = 640 + 64 + 64; |
||||
|
||||
if (!gpBuffer) { |
||||
gpBuffer = (Screen *)malloc(sizeof(Screen)); |
||||
gpBufEnd += (unsigned int)gpBuffer; |
||||
|
||||
sdl_pal_surface = SDL_CreateRGBSurfaceFrom(gpBuffer, pitch, 160 + 480 + 16, 8, pitch, 0, 0, 0, 0); |
||||
assert(sdl_pal_surface); |
||||
|
||||
SDL_CHECK(SDL_SetSurfacePalette(sdl_pal_surface, sdl_palette)); |
||||
} |
||||
} |
||||
|
||||
void __cdecl unlock_buf_priv() |
||||
{ |
||||
gpBufEnd -= (unsigned int)gpBufEnd; |
||||
|
||||
if (!surface_dirty) { |
||||
return; |
||||
} |
||||
|
||||
sdl_present_surface(); |
||||
} |
||||
|
||||
void __cdecl dx_reinit() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
//
|
||||
// Storm functions
|
||||
//
|
||||
|
||||
BOOL STORMAPI SDrawUpdatePalette(unsigned int firstentry, unsigned int numentries, PALETTEENTRY *pPalEntries, int a4) |
||||
{ |
||||
DUMMY_PRINT("first: %d num: %d", firstentry, numentries); |
||||
|
||||
assert(firstentry == 0); |
||||
assert(numentries == 256); |
||||
|
||||
SDL_Color colors[256]; |
||||
for (int i = firstentry; i < numentries; i++) { |
||||
SDL_Color *c = &colors[i]; |
||||
PALETTEENTRY *p = &pPalEntries[i]; |
||||
c->r = p->peRed; |
||||
c->g = p->peGreen; |
||||
c->b = p->peBlue; |
||||
c->a = SDL_ALPHA_OPAQUE; |
||||
} |
||||
|
||||
assert(sdl_palette); |
||||
SDL_CHECK(SDL_SetPaletteColors(sdl_palette, colors, firstentry, numentries)); |
||||
|
||||
if (sdl_pal_surface) { |
||||
sdl_update_entire_surface(); |
||||
sdl_present_surface(); |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
//
|
||||
// Windows API functions
|
||||
//
|
||||
|
||||
WINBOOL WINAPI SetCursorPos(int X, int Y) |
||||
{ |
||||
DUMMY(); |
||||
assert(sdl_window); |
||||
SDL_WarpMouseInWindow(sdl_window, X, Y); |
||||
return TRUE; |
||||
} |
||||
|
||||
int WINAPI ShowCursor(WINBOOL bShow) |
||||
{ |
||||
DUMMY_PRINT("%d", bShow); |
||||
if (sdl_window) { |
||||
SDL_ShowCursor(bShow ? SDL_ENABLE : SDL_DISABLE); |
||||
} |
||||
return bShow; |
||||
} |
||||
|
||||
WINBOOL WINAPI TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(sdl_window); |
||||
SDL_SetWindowTitle(sdl_window, lpString); |
||||
|
||||
return TRUE; |
||||
} |
||||
@ -0,0 +1,10 @@
|
||||
#pragma once |
||||
|
||||
#include <SDL2/SDL.h> |
||||
|
||||
extern SDL_Window *sdl_window; |
||||
extern SDL_Renderer *sdl_renderer; |
||||
extern SDL_Texture *sdl_render_texture; |
||||
extern SDL_Surface *sdl_surface; |
||||
|
||||
void sdl_present_surface(); |
||||
@ -0,0 +1,10 @@
|
||||
#include "../types.h" |
||||
|
||||
#include "stubs.h" |
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER __cdecl exception_get_filter() |
||||
{ |
||||
DUMMY(); |
||||
|
||||
return NULL; |
||||
} |
||||
@ -0,0 +1,96 @@
|
||||
#include <dirent.h> |
||||
#include <string> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#ifndef NO_GLOBALS |
||||
void *diabdat_mpq; |
||||
void *patch_rt_mpq; |
||||
|
||||
_SNETVERSIONDATA fileinfo; |
||||
WNDPROC CurrentProc; |
||||
int gbActive; |
||||
#endif |
||||
|
||||
char gszVersionNumber[260]; |
||||
char gszProductName[260]; |
||||
|
||||
/**
|
||||
* Case insensitive search for a file name in a directory. |
||||
* @return Empty string when not found. |
||||
*/ |
||||
static std::string find_file_in_directory(const char *dirpath, const char *file) |
||||
{ |
||||
DIR *dir = opendir(dirpath); |
||||
if (!dir) { |
||||
return ""; |
||||
} |
||||
|
||||
struct dirent *entry; |
||||
std::string result; |
||||
while ((entry = readdir(dir)) != NULL) { |
||||
if (strcasecmp(entry->d_name, file) == 0) { |
||||
result = std::string(dirpath) + "/" + entry->d_name; |
||||
break; |
||||
} |
||||
} |
||||
closedir(dir); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
static std::string find_file_in_std_directories(const char *file) |
||||
{ |
||||
for (auto dir : {".", "..", "../.."}) { |
||||
auto path = find_file_in_directory(dir, file); |
||||
if (!path.empty()) { |
||||
return path; |
||||
} |
||||
} |
||||
|
||||
TermMsg("Required file %s not found", file); |
||||
} |
||||
|
||||
void __fastcall init_create_window(int nCmdShow) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
init_get_file_info(); |
||||
|
||||
// pfile_init_save_directory();
|
||||
|
||||
dx_init(NULL); |
||||
snd_init(NULL); |
||||
|
||||
init_archives(); |
||||
} |
||||
|
||||
LRESULT __stdcall MainWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WNDPROC __fastcall SetWindowProc(WNDPROC NewProc) |
||||
{ |
||||
WNDPROC OldProc = CurrentProc; |
||||
CurrentProc = NewProc; |
||||
return OldProc; |
||||
} |
||||
|
||||
void __cdecl init_archives() |
||||
{ |
||||
DUMMY(); |
||||
|
||||
SFileOpenArchive(find_file_in_std_directories("diabdat.mpq").c_str(), 1000, 0, &diabdat_mpq); |
||||
assert(diabdat_mpq); |
||||
|
||||
SFileOpenArchive(find_file_in_std_directories("patch_rt.mpq").c_str(), 1000, 0, &patch_rt_mpq); |
||||
assert(patch_rt_mpq); |
||||
} |
||||
|
||||
void __cdecl init_get_file_info() |
||||
{ |
||||
strcpy(gszVersionNumber, "0.1"); |
||||
strcpy(gszProductName, "devil-test"); |
||||
} |
||||
@ -0,0 +1,22 @@
|
||||
#include <string> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
static std::string build_cmdline(int argc, char **argv) |
||||
{ |
||||
std::string str; |
||||
for (int i = 1; i < argc; i++) { |
||||
if (i != 1) { |
||||
str += ' '; |
||||
} |
||||
str += argv[i]; |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
auto cmdline = build_cmdline(argc, argv); |
||||
return WinMain(NULL, NULL, cmdline.c_str(), 0); |
||||
} |
||||
@ -0,0 +1,12 @@
|
||||
#include "../types.h" |
||||
#include "Absolute/absolute.h" |
||||
#include "stubs.h" |
||||
|
||||
#include <stddef.h> |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
init_absolute(); |
||||
|
||||
d_WinMain(NULL, NULL, "", 0); |
||||
} |
||||
@ -0,0 +1,72 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#include <stddef.h> |
||||
|
||||
extern "C" const char *__asan_default_options() |
||||
{ |
||||
return "halt_on_error=0:print_legend=0"; |
||||
} |
||||
|
||||
static void init() |
||||
{ |
||||
init_archives(); |
||||
|
||||
encrypt_init_lookup_table(); |
||||
diablo_init_screen(); |
||||
|
||||
InitLightTable(); |
||||
|
||||
gdwNormalMsgSize = 512; |
||||
} |
||||
|
||||
static void test_levelgen() |
||||
{ |
||||
init(); |
||||
|
||||
SetRndSeed(123); |
||||
|
||||
currlevel = 2; |
||||
leveltype = DTYPE_CATACOMBS; |
||||
|
||||
// DRLG_Init_Globals();
|
||||
// LoadLvlGFX();
|
||||
// CreateLevel(0);
|
||||
|
||||
// LoadGameLevel(TRUE, 0);
|
||||
} |
||||
|
||||
static void test_newgame() |
||||
{ |
||||
init(); |
||||
|
||||
start_game(WM_DIABNEWGAME); |
||||
} |
||||
|
||||
int main(int argc, char **argv) |
||||
{ |
||||
//#define O(f) fprintf(stderr, "offsetof(%s) = %d\n", #f, offsetof(PlayerStruct, f))
|
||||
//
|
||||
// O(_pRSplType);
|
||||
// O(_pSBkSplType);
|
||||
// O(_pSplLvl);
|
||||
// O(_pMemSpells64);
|
||||
// O(_pAblSpells64);
|
||||
// O(_pSpellFlags);
|
||||
// O(_pClass);
|
||||
// O(_pVar8);
|
||||
// O(_pIBonusDamMod);
|
||||
// O(_pISpells64);
|
||||
// O(_pBData);
|
||||
//
|
||||
// printf("s %d\n", sizeof(UINT64));
|
||||
|
||||
// test_levelgen();
|
||||
// test_newgame();
|
||||
|
||||
WinMain(NULL, NULL, argc > 1 ? argv[1] : (char*)"", 0); |
||||
|
||||
eprintf("Done!\n"); |
||||
|
||||
return 0; |
||||
} |
||||
@ -0,0 +1,294 @@
|
||||
#include <fcntl.h> |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "miniwin.h" |
||||
#include "stubs.h" |
||||
|
||||
DWORD last_error; |
||||
|
||||
DWORD WINAPI GetLastError(VOID) |
||||
{ |
||||
return last_error; |
||||
} |
||||
|
||||
VOID WINAPI SetLastError(DWORD dwErrCode) |
||||
{ |
||||
last_error = dwErrCode; |
||||
} |
||||
|
||||
char __cdecl *_strlwr(char *str) |
||||
{ |
||||
for (char *p = str; *p; ++p) { |
||||
*p = tolower(*p); |
||||
} |
||||
return str; |
||||
} |
||||
|
||||
int WINAPIV wsprintfA(LPSTR dest, LPCSTR format, ...) |
||||
{ |
||||
va_list args; |
||||
va_start(args, format); |
||||
return vsprintf(dest, format, args); |
||||
} |
||||
|
||||
int __cdecl _strcmpi(const char *_Str1, const char *_Str2) |
||||
{ |
||||
return strcasecmp(_Str1, _Str2); |
||||
} |
||||
|
||||
char *__cdecl _itoa(int _Value, char *_Dest, int _Radix) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI GetTickCount(VOID) |
||||
{ |
||||
struct timespec now; |
||||
if (clock_gettime(CLOCK_MONOTONIC, &now)) |
||||
return 0; |
||||
return now.tv_sec * 1000.0 + now.tv_nsec / 1000000.0; |
||||
} |
||||
|
||||
VOID WINAPI Sleep(DWORD dwMilliseconds) |
||||
{ |
||||
usleep(dwMilliseconds * 1000); |
||||
} |
||||
|
||||
HANDLE WINAPI FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI FindClose(HANDLE hFindFile) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
UINT WINAPI GetWindowsDirectoryA(LPSTR lpBuffer, UINT uSize) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, |
||||
LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize) |
||||
{ |
||||
DUMMY(); |
||||
assert(nSize >= 16); |
||||
const char *name = ".\\diablo.exe"; |
||||
strncpy(lpFilename, name, nSize); |
||||
return strlen(name); |
||||
} |
||||
|
||||
WINBOOL WINAPI GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI DeleteFileA(LPCSTR lpFileName) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, WINBOOL bFailIfExists) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
VOID WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
VOID WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
} |
||||
|
||||
VOID WINAPI LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
} |
||||
|
||||
VOID WINAPI DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HANDLE WINAPI CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, WINBOOL bManualReset, WINBOOL bInitialState, |
||||
LPCSTR lpName) |
||||
{ |
||||
DUMMY_PRINT("%s", nullstr(lpName)); |
||||
return NULL; |
||||
} |
||||
|
||||
HWND WINAPI SetCapture(HWND hWnd) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return hWnd; |
||||
} |
||||
|
||||
WINBOOL WINAPI ReleaseCapture(VOID) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return TRUE; |
||||
} |
||||
|
||||
WINBOOL WINAPI DestroyWindow(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI GetLastActivePopup(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI GetTopWindow(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI SetForegroundWindow(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI SetFocus(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName) |
||||
{ |
||||
DUMMY_PRINT("class: %s window: %s", nullstr(lpClassName), nullstr(lpWindowName)); |
||||
return NULL; |
||||
} |
||||
|
||||
HANDLE WINAPI GetCurrentThread(VOID) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return NULL; |
||||
} |
||||
|
||||
DWORD WINAPI GetCurrentThreadId(VOID) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return TRUE; |
||||
} |
||||
|
||||
VOID WINAPI GetSystemInfo(LPSYSTEM_INFO lpSystemInfo) |
||||
{ |
||||
DUMMY(); |
||||
memset(lpSystemInfo, 0, sizeof(*lpSystemInfo)); |
||||
lpSystemInfo->dwPageSize = 4096; |
||||
} |
||||
|
||||
HDC WINAPI GetDC(HWND hWnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int WINAPI ReleaseDC(HWND hWnd, HDC hDC) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int WINAPI GetDeviceCaps(HDC hdc, int index) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
UINT WINAPI GetSystemPaletteEntries(HDC hdc, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
uintptr_t __cdecl _beginthreadex(void *_Security, unsigned _StackSize, unsigned(__stdcall *_StartAddress)(void *), |
||||
void *_ArgList, unsigned _InitFlag, unsigned *_ThrdAddr) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, |
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, WINBOOL bInheritHandles, DWORD dwCreationFlags, |
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, |
||||
LPPROCESS_INFORMATION lpProcessInformation) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
VOID WINAPI ExitProcess(UINT uExitCode) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI GetCurrentProcessId(VOID) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HANDLE WINAPI CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, |
||||
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) |
||||
{ |
||||
DUMMY(); |
||||
assert(hFile == (HANDLE)-1); |
||||
return NULL; |
||||
} |
||||
|
||||
LPVOID WINAPI MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, |
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI UnmapViewOfFile(LPCVOID lpBaseAddress) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI GetForegroundWindow(VOID) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
HWND WINAPI GetWindow(HWND hWnd, UINT uCmd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD WINAPI GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, |
||||
DWORD nSize, LPCSTR lpFileName) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
@ -0,0 +1,557 @@
|
||||
#pragma once |
||||
|
||||
#ifdef NO_GLOBALS |
||||
#define STATIC extern |
||||
#else |
||||
#define STATIC static |
||||
#endif |
||||
|
||||
#include <ctype.h> |
||||
#include <math.h> |
||||
#include <stdarg.h> |
||||
#include <stdint.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <time.h> |
||||
// For _rotr()
|
||||
#include <x86intrin.h> |
||||
|
||||
// Constants
|
||||
#define CONST const |
||||
#define TRUE true |
||||
#define FALSE false |
||||
|
||||
#define NO_ERROR 0 |
||||
|
||||
// Calling conventions
|
||||
#define __cdecl __attribute__((cdecl)) |
||||
#define __fastcall __attribute__((fastcall)) |
||||
#define __stdcall __attribute__((stdcall)) |
||||
#define CALLBACK __stdcall |
||||
#define WINAPI __stdcall |
||||
#define WINAPIV __cdecl |
||||
|
||||
#define ALIGNED(n) __attribute__((aligned(n))) |
||||
|
||||
// Basic types
|
||||
#define __int8 char |
||||
#define __int16 short |
||||
#define __int32 int |
||||
#define __int64 long long ALIGNED(8) |
||||
|
||||
#define VOID void |
||||
|
||||
typedef char CHAR; |
||||
typedef uint16_t SHORT; |
||||
typedef int32_t LONG; |
||||
|
||||
typedef LONG *PLONG; |
||||
typedef unsigned long ULONG; |
||||
typedef ULONG *PULONG; |
||||
typedef unsigned short USHORT; |
||||
typedef USHORT *PUSHORT; |
||||
typedef unsigned char UCHAR; |
||||
typedef UCHAR *PUCHAR; |
||||
typedef char *PSZ; |
||||
|
||||
typedef unsigned long DWORD; |
||||
typedef int BOOL, WINBOOL; |
||||
typedef unsigned char BYTE; |
||||
typedef unsigned short WORD; |
||||
typedef float FLOAT; |
||||
typedef FLOAT *PFLOAT; |
||||
typedef BOOL *LPBOOL; |
||||
typedef BYTE *LPBYTE; |
||||
typedef int *LPINT; |
||||
typedef WORD *LPWORD; |
||||
typedef long *LPLONG; |
||||
typedef DWORD *LPDWORD; |
||||
typedef void *LPVOID; |
||||
typedef CONST void *LPCVOID; |
||||
|
||||
typedef int INT; |
||||
typedef unsigned int UINT; |
||||
typedef unsigned int *PUINT; |
||||
|
||||
// GCC qword alignment is 4, MSVC is 8, work around by introducing a more aligned type
|
||||
typedef long long INT64 ALIGNED(8); |
||||
typedef unsigned long long UINT64 ALIGNED(8); |
||||
|
||||
typedef int INT_PTR, *PINT_PTR; |
||||
typedef unsigned int UINT_PTR, *PUINT_PTR; |
||||
|
||||
typedef int32_t LONG_PTR, *PLONG_PTR; |
||||
typedef uint32_t ULONG_PTR, *PULONG_PTR; |
||||
typedef ULONG_PTR SIZE_T; |
||||
|
||||
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; |
||||
|
||||
typedef CHAR *LPSTR; |
||||
typedef CONST CHAR *LPCSTR; |
||||
|
||||
typedef UINT_PTR WPARAM; |
||||
typedef LONG_PTR LPARAM; |
||||
typedef LONG_PTR LRESULT; |
||||
|
||||
//
|
||||
// Handles
|
||||
//
|
||||
typedef void *HANDLE; |
||||
#define INVALID_HANDLE ((HANDLE)-1) |
||||
|
||||
typedef HANDLE HWND, HGDIOBJ, HMODULE, HDC, HRGN, HINSTANCE, HPALETTE, HFILE, HCURSOR; |
||||
|
||||
typedef LONG LCID; |
||||
|
||||
typedef DWORD COLORREF; |
||||
|
||||
typedef LONG HRESULT; |
||||
|
||||
typedef LRESULT(CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM); |
||||
|
||||
//
|
||||
// Intrinsics
|
||||
//
|
||||
#define LOBYTE(w) ((BYTE)(((DWORD_PTR)(w)) & 0xff)) |
||||
#define HIBYTE(w) ((BYTE)((((DWORD_PTR)(w)) >> 8) & 0xff)) |
||||
#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) |
||||
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff)) |
||||
|
||||
#define InterlockedIncrement(x) __sync_add_and_fetch(x, 1) |
||||
|
||||
typedef struct waveformat_tag { |
||||
WORD wFormatTag; |
||||
WORD nChannels; |
||||
DWORD nSamplesPerSec; |
||||
DWORD nAvgBytesPerSec; |
||||
WORD nBlockAlign; |
||||
} WAVEFORMAT, *PWAVEFORMAT, *LPWAVEFORMAT; |
||||
|
||||
typedef struct pcmwaveformat_tag { |
||||
WAVEFORMAT wf; |
||||
WORD wBitsPerSample; |
||||
} PCMWAVEFORMAT, *PPCMWAVEFORMAT, *LPPCMWAVEFORMAT; |
||||
|
||||
typedef struct tWAVEFORMATEX { |
||||
WORD wFormatTag; |
||||
WORD nChannels; |
||||
DWORD nSamplesPerSec; |
||||
DWORD nAvgBytesPerSec; |
||||
WORD nBlockAlign; |
||||
WORD wBitsPerSample; |
||||
WORD cbSize; |
||||
} WAVEFORMATEX, *LPWAVEFORMATEX, *LPCWAVEFORMATEX; |
||||
|
||||
typedef struct _FILETIME { |
||||
DWORD dwLowDateTime; |
||||
DWORD dwHighDateTime; |
||||
} FILETIME, *LPFILETIME; |
||||
|
||||
typedef struct tagRECT { |
||||
LONG left; |
||||
LONG top; |
||||
LONG right; |
||||
LONG bottom; |
||||
} RECT; |
||||
|
||||
typedef RECT *LPRECT; |
||||
|
||||
typedef struct tagPOINT { |
||||
LONG x; |
||||
LONG y; |
||||
} POINT; |
||||
|
||||
typedef struct tagSIZE { |
||||
LONG cx; |
||||
LONG cy; |
||||
} SIZE; |
||||
|
||||
typedef struct tagVS_FIXEDFILEINFO { |
||||
DWORD dwSignature; |
||||
DWORD dwStrucVersion; |
||||
DWORD dwFileVersionMS; |
||||
DWORD dwFileVersionLS; |
||||
DWORD dwProductVersionMS; |
||||
DWORD dwProductVersionLS; |
||||
DWORD dwFileFlagsMask; |
||||
DWORD dwFileFlags; |
||||
DWORD dwFileOS; |
||||
DWORD dwFileType; |
||||
DWORD dwFileSubtype; |
||||
DWORD dwFileDateMS; |
||||
DWORD dwFileDateLS; |
||||
} VS_FIXEDFILEINFO; |
||||
|
||||
typedef struct tagMSG { |
||||
HWND hwnd; |
||||
UINT message; |
||||
WPARAM wParam; |
||||
LPARAM lParam; |
||||
DWORD time; |
||||
POINT pt; |
||||
} MSG, *LPMSG; |
||||
|
||||
//
|
||||
// COM
|
||||
//
|
||||
#define DECLARE_INTERFACE_(name, base) struct name : public base |
||||
#define THIS_ |
||||
#define THIS |
||||
#define PURE = 0 |
||||
|
||||
#define STDMETHOD(name) STDMETHOD_(HRESULT, name) |
||||
#define STDMETHOD_(type, name) virtual WINAPI type name |
||||
|
||||
typedef void *REFIID; |
||||
|
||||
struct IUnknown { |
||||
// clang-format off
|
||||
STDMETHOD(QueryInterface)(THIS_ REFIID, LPVOID *) PURE; |
||||
STDMETHOD_(ULONG, AddRef)(THIS) PURE; |
||||
STDMETHOD_(ULONG, Release)(THIS) PURE; |
||||
// clang-format on
|
||||
}; |
||||
|
||||
#define MAKE_HRESULT(sev, fac, code) ((HRESULT)(((uint32_t)(sev) << 31) | ((uint32_t)(fac) << 16) | ((uint32_t)(code)))) |
||||
#define E_FAIL ((HRESULT)0x80004005L) |
||||
#define S_OK ((HRESULT)0) |
||||
|
||||
//
|
||||
// Everything else
|
||||
//
|
||||
typedef struct tagPALETTEENTRY { |
||||
BYTE peRed; |
||||
BYTE peGreen; |
||||
BYTE peBlue; |
||||
BYTE peFlags; |
||||
} PALETTEENTRY, *PPALETTEENTRY, *LPPALETTEENTRY; |
||||
|
||||
typedef void *LPTOP_LEVEL_EXCEPTION_FILTER, *PEXCEPTION_POINTERS; |
||||
|
||||
typedef struct _SYSTEM_INFO { |
||||
union { |
||||
DWORD dwOemId; |
||||
struct { |
||||
WORD wProcessorArchitecture; |
||||
WORD wReserved; |
||||
}; |
||||
}; |
||||
DWORD dwPageSize; |
||||
LPVOID lpMinimumApplicationAddress; |
||||
LPVOID lpMaximumApplicationAddress; |
||||
DWORD_PTR dwActiveProcessorMask; |
||||
DWORD dwNumberOfProcessors; |
||||
DWORD dwProcessorType; |
||||
DWORD dwAllocationGranularity; |
||||
WORD wProcessorLevel; |
||||
WORD wProcessorRevision; |
||||
} SYSTEM_INFO, *LPSYSTEM_INFO; |
||||
|
||||
typedef void *LPSECURITY_ATTRIBUTES; |
||||
|
||||
#define ERROR_ALREADY_EXISTS 183 |
||||
|
||||
typedef struct _LIST_ENTRY { |
||||
struct _LIST_ENTRY *Flink; |
||||
struct _LIST_ENTRY *Blink; |
||||
} LIST_ENTRY, *PLIST_ENTRY; |
||||
|
||||
typedef struct _RTL_CRITICAL_SECTION_DEBUG { |
||||
WORD Type; |
||||
WORD CreatorBackTraceIndex; |
||||
struct _RTL_CRITICAL_SECTION *CriticalSection; |
||||
LIST_ENTRY ProcessLocksList; |
||||
DWORD EntryCount; |
||||
DWORD ContentionCount; |
||||
DWORD Flags; |
||||
WORD CreatorBackTraceIndexHigh; |
||||
WORD SpareWORD; |
||||
} RTL_CRITICAL_SECTION_DEBUG, *PRTL_CRITICAL_SECTION_DEBUG; |
||||
|
||||
typedef struct { |
||||
PRTL_CRITICAL_SECTION_DEBUG DebugInfo; |
||||
LONG LockCount; |
||||
LONG RecursionCount; |
||||
HANDLE OwningThread; |
||||
HANDLE LockSemaphore; |
||||
ULONG_PTR SpinCount; |
||||
} CRITICAL_SECTION, *LPCRITICAL_SECTION; |
||||
|
||||
VOID WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); |
||||
VOID WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); |
||||
VOID WINAPI LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); |
||||
VOID WINAPI DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); |
||||
|
||||
DWORD WINAPI WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); |
||||
|
||||
DWORD WINAPI GetTickCount(VOID); |
||||
|
||||
DWORD WINAPI GetLastError(VOID); |
||||
VOID WINAPI SetLastError(DWORD dwErrCode); |
||||
|
||||
WINBOOL WINAPI CloseHandle(HANDLE hObject); |
||||
|
||||
HANDLE WINAPI CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, WINBOOL bManualReset, WINBOOL bInitialState, |
||||
LPCSTR lpName); |
||||
#define CreateEvent CreateEventA |
||||
|
||||
WINBOOL WINAPI SetCursorPos(int X, int Y); |
||||
int WINAPI ShowCursor(WINBOOL bShow); |
||||
HWND WINAPI SetCapture(HWND hWnd); |
||||
WINBOOL WINAPI ReleaseCapture(VOID); |
||||
|
||||
SHORT WINAPI GetAsyncKeyState(int vKey); |
||||
|
||||
#define PM_NOREMOVE 0x0000 |
||||
#define PM_REMOVE 0x0001 |
||||
|
||||
#define WM_QUIT 0x0012 |
||||
|
||||
WINBOOL WINAPI PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg); |
||||
#define PeekMessage PeekMessageA |
||||
WINBOOL WINAPI TranslateMessage(CONST MSG *lpMsg); |
||||
LRESULT WINAPI DispatchMessageA(CONST MSG *lpMsg); |
||||
#define DispatchMessage DispatchMessageA |
||||
WINBOOL WINAPI PostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); |
||||
#define PostMessage PostMessageA |
||||
|
||||
WINBOOL WINAPI DestroyWindow(HWND hWnd); |
||||
HWND WINAPI GetLastActivePopup(HWND hWnd); |
||||
HWND WINAPI GetTopWindow(HWND hWnd); |
||||
WINBOOL WINAPI SetForegroundWindow(HWND hWnd); |
||||
HWND WINAPI SetFocus(HWND hWnd); |
||||
HWND WINAPI FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName); |
||||
#define FindWindow FindWindowA |
||||
|
||||
#define THREAD_BASE_PRIORITY_MAX 2 |
||||
#define THREAD_PRIORITY_NORMAL 0 |
||||
#define THREAD_PRIORITY_HIGHEST THREAD_BASE_PRIORITY_MAX |
||||
#define THREAD_PRIORITY_ABOVE_NORMAL (THREAD_PRIORITY_HIGHEST - 1) |
||||
|
||||
HANDLE WINAPI GetCurrentThread(VOID); |
||||
DWORD WINAPI GetCurrentThreadId(VOID); |
||||
WINBOOL WINAPI SetThreadPriority(HANDLE hThread, int nPriority); |
||||
VOID WINAPI Sleep(DWORD dwMilliseconds); |
||||
|
||||
VOID WINAPI GetSystemInfo(LPSYSTEM_INFO lpSystemInfo); |
||||
|
||||
HDC WINAPI GetDC(HWND hWnd); |
||||
int WINAPI ReleaseDC(HWND hWnd, HDC hDC); |
||||
WINBOOL WINAPI TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c); |
||||
#define TextOut TextOutA |
||||
|
||||
#define NUMRESERVED 106 |
||||
int WINAPI GetDeviceCaps(HDC hdc, int index); |
||||
UINT WINAPI GetSystemPaletteEntries(HDC hdc, UINT iStart, UINT cEntries, LPPALETTEENTRY pPalEntries); |
||||
|
||||
uintptr_t __cdecl _beginthreadex(void *_Security, unsigned _StackSize, unsigned(__stdcall *_StartAddress)(void *), |
||||
void *_ArgList, unsigned _InitFlag, unsigned *_ThrdAddr); |
||||
int WINAPIV wsprintfA(LPSTR, LPCSTR, ...); |
||||
#define wsprintf wsprintfA |
||||
int __cdecl _strcmpi(const char *_Str1, const char *_Str2); |
||||
char *__cdecl _itoa(int _Value, char *_Dest, int _Radix); |
||||
|
||||
char *__cdecl _strlwr(char *str); |
||||
|
||||
//
|
||||
// File I/O
|
||||
//
|
||||
#define FILE_BEGIN 0 |
||||
#define FILE_CURRENT 1 |
||||
#define FILE_FLAG_WRITE_THROUGH 0x80000000 |
||||
#define CREATE_ALWAYS 2 |
||||
#define GENERIC_READ 0x80000000L |
||||
#define GENERIC_WRITE 0x40000000L |
||||
#define OPEN_EXISTING 3 |
||||
#define ERROR_FILE_NOT_FOUND 2 |
||||
#define FILE_ATTRIBUTE_HIDDEN 0x00000002 |
||||
#define FILE_ATTRIBUTE_SYSTEM 0x00000004 |
||||
|
||||
struct _WIN32_FIND_DATAA { |
||||
FILETIME ftCreationTime; |
||||
FILETIME ftLastWriteTime; |
||||
}; |
||||
|
||||
typedef struct _WIN32_FIND_DATAA *LPWIN32_FIND_DATAA; |
||||
|
||||
typedef void *LPOVERLAPPED; |
||||
|
||||
#define OFS_MAXPATHNAME 128 |
||||
|
||||
typedef struct _OFSTRUCT { |
||||
BYTE cBytes; |
||||
BYTE fFixedDisk; |
||||
WORD nErrCode; |
||||
WORD Reserved1; |
||||
WORD Reserved2; |
||||
CHAR szPathName[OFS_MAXPATHNAME]; |
||||
} OFSTRUCT, *LPOFSTRUCT, *POFSTRUCT; |
||||
|
||||
#define SEC_COMMIT 0x8000000 |
||||
#define PAGE_READWRITE 0x04 |
||||
|
||||
#define FILE_MAP_ALL_ACCESS SECTION_ALL_ACCESS |
||||
#define SECTION_QUERY 0x0001 |
||||
#define SECTION_MAP_WRITE 0x0002 |
||||
#define SECTION_MAP_READ 0x0004 |
||||
#define SECTION_MAP_EXECUTE 0x0008 |
||||
#define SECTION_EXTEND_SIZE 0x0010 |
||||
#define SECTION_MAP_EXECUTE_EXPLICIT 0x0020 |
||||
#define STANDARD_RIGHTS_REQUIRED 0x000F0000 |
||||
|
||||
#define SECTION_ALL_ACCESS \ |
||||
(STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | \
|
||||
SECTION_EXTEND_SIZE) |
||||
|
||||
#define CREATE_NEW_PROCESS_GROUP 0x200 |
||||
|
||||
typedef struct _PROCESS_INFORMATION { |
||||
HANDLE hProcess; |
||||
HANDLE hThread; |
||||
DWORD dwProcessId; |
||||
DWORD dwThreadId; |
||||
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; |
||||
|
||||
typedef void *LPSTARTUPINFOA; |
||||
WINBOOL WINAPI CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, |
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, WINBOOL bInheritHandles, DWORD dwCreationFlags, |
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, |
||||
LPPROCESS_INFORMATION lpProcessInformation); |
||||
#define CreateProcess CreateProcessA |
||||
VOID WINAPI ExitProcess(UINT uExitCode); |
||||
DWORD WINAPI GetCurrentProcessId(VOID); |
||||
|
||||
HANDLE WINAPI CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, |
||||
DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName); |
||||
#define CreateFileMapping CreateFileMappingA |
||||
LPVOID WINAPI MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, |
||||
DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap); |
||||
WINBOOL WINAPI UnmapViewOfFile(LPCVOID lpBaseAddress); |
||||
|
||||
DWORD WINAPI WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds); |
||||
HWND WINAPI GetForegroundWindow(VOID); |
||||
HWND WINAPI GetWindow(HWND hWnd, UINT uCmd); |
||||
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId); |
||||
|
||||
DWORD WINAPI GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault, LPSTR lpReturnedString, |
||||
DWORD nSize, LPCSTR lpFileName); |
||||
#define GetPrivateProfileString GetPrivateProfileStringA |
||||
|
||||
WINBOOL WINAPI WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, |
||||
LPOVERLAPPED lpOverlapped); |
||||
DWORD WINAPI SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); |
||||
WINBOOL WINAPI SetEndOfFile(HANDLE hFile); |
||||
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName); |
||||
#define GetFileAttributes GetFileAttributesA |
||||
WINBOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes); |
||||
#define SetFileAttributes SetFileAttributesA |
||||
HANDLE WINAPI FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData); |
||||
#define FindFirstFile FindFirstFileA |
||||
WINBOOL WINAPI FindClose(HANDLE hFindFile); |
||||
HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, |
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, |
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); |
||||
#define CreateFile CreateFileA |
||||
WINBOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, |
||||
LPOVERLAPPED lpOverlapped); |
||||
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); |
||||
UINT WINAPI GetWindowsDirectoryA(LPSTR lpBuffer, UINT uSize); |
||||
#define GetWindowsDirectory GetWindowsDirectoryA |
||||
WINBOOL WINAPI GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector, |
||||
LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters); |
||||
#define GetDiskFreeSpace GetDiskFreeSpaceA |
||||
DWORD WINAPI GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize); |
||||
#define GetModuleFileName GetModuleFileNameA |
||||
WINBOOL WINAPI GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize); |
||||
#define GetComputerName GetComputerNameA |
||||
WINBOOL WINAPI DeleteFileA(LPCSTR lpFileName); |
||||
#define DeleteFile DeleteFileA |
||||
WINBOOL WINAPI CopyFileA(LPCSTR lpExistingFileName, LPCSTR lpNewFileName, WINBOOL bFailIfExists); |
||||
#define CopyFile CopyFileA |
||||
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle); |
||||
|
||||
//
|
||||
// Events
|
||||
//
|
||||
#define WM_MOUSEFIRST 0x0200 |
||||
#define WM_MOUSEMOVE 0x0200 |
||||
#define WM_LBUTTONDOWN 0x0201 |
||||
#define WM_LBUTTONUP 0x0202 |
||||
#define WM_RBUTTONDOWN 0x0204 |
||||
#define WM_RBUTTONUP 0x0205 |
||||
|
||||
#define WM_KEYFIRST 0x0100 |
||||
#define WM_KEYDOWN 0x0100 |
||||
#define WM_KEYUP 0x0101 |
||||
#define WM_SYSKEYDOWN 0x0104 |
||||
|
||||
#define WM_SYSCOMMAND 0x0112 |
||||
|
||||
#define WM_CHAR 0x0102 |
||||
#define WM_CAPTURECHANGED 0x0215 |
||||
|
||||
#define SC_CLOSE 0xF060 |
||||
|
||||
#define VK_RETURN 0x0D |
||||
#define VK_BACK 0x08 |
||||
#define VK_SHIFT 0x10 |
||||
#define VK_ESCAPE 0x1B |
||||
#define VK_SPACE 0x20 |
||||
#define VK_LEFT 0x25 |
||||
#define VK_UP 0x26 |
||||
#define VK_RIGHT 0x27 |
||||
#define VK_DOWN 0x28 |
||||
|
||||
#define VK_F1 0x70 |
||||
#define VK_F2 0x71 |
||||
#define VK_F3 0x72 |
||||
#define VK_F4 0x73 |
||||
#define VK_F5 0x74 |
||||
#define VK_F6 0x75 |
||||
#define VK_F7 0x76 |
||||
#define VK_F8 0x77 |
||||
#define VK_F9 0x78 |
||||
#define VK_F10 0x79 |
||||
#define VK_F11 0x7A |
||||
#define VK_F12 0x7B |
||||
|
||||
#define VK_TAB 0x09 |
||||
#define VK_PAUSE 0x13 |
||||
#define VK_PRIOR 0x21 |
||||
#define VK_NEXT 0x22 |
||||
#define VK_SNAPSHOT 0x2C |
||||
|
||||
#define VK_OEM_1 0xBA |
||||
#define VK_OEM_PLUS 0xBB |
||||
#define VK_OEM_COMMA 0xBC |
||||
#define VK_OEM_MINUS 0xBD |
||||
#define VK_OEM_PERIOD 0xBE |
||||
#define VK_OEM_2 0xBF |
||||
#define VK_OEM_3 0xC0 |
||||
#define VK_OEM_4 0xDB |
||||
#define VK_OEM_5 0xDC |
||||
#define VK_OEM_6 0xDD |
||||
#define VK_OEM_7 0xDE |
||||
//#define VK_OEM_8 0xDF
|
||||
//#define VK_OEM_102 0xE2
|
||||
|
||||
//
|
||||
// Total fakes
|
||||
//
|
||||
typedef struct { |
||||
} SOCKADDR, GUID; |
||||
|
||||
typedef struct { |
||||
DWORD cb; |
||||
} STARTUPINFOA; |
||||
|
||||
//
|
||||
// MSCVRT emulation
|
||||
//
|
||||
|
||||
int rand_miniwin(void); |
||||
void srand_miniwin(unsigned int seed); |
||||
|
||||
#include "miniwin_ddraw.h" |
||||
#include "miniwin_dsound.h" |
||||
@ -0,0 +1,196 @@
|
||||
#pragma once |
||||
|
||||
#include "miniwin.h" |
||||
|
||||
typedef struct _DDCOLORKEY { |
||||
DWORD dwColorSpaceLowValue; |
||||
DWORD dwColorSpaceHighValue; |
||||
} DDCOLORKEY; |
||||
|
||||
typedef DDCOLORKEY *LPDDCOLORKEY; |
||||
|
||||
typedef struct _DDSCAPS { |
||||
DWORD dwCaps; |
||||
} DDSCAPS, *LPDDSCAPS; |
||||
|
||||
typedef struct _DDPIXELFORMAT { |
||||
DWORD dwSize; |
||||
DWORD dwFlags; |
||||
DWORD dwFourCC; |
||||
union { |
||||
DWORD dwRGBBitCount; |
||||
DWORD dwYUVBitCount; |
||||
DWORD dwZBufferBitDepth; |
||||
DWORD dwAlphaBitDepth; |
||||
}; |
||||
union { |
||||
DWORD dwRBitMask; |
||||
DWORD dwYBitMask; |
||||
}; |
||||
union { |
||||
DWORD dwGBitMask; |
||||
DWORD dwUBitMask; |
||||
}; |
||||
union { |
||||
DWORD dwBBitMask; |
||||
DWORD dwVBitMask; |
||||
}; |
||||
union { |
||||
DWORD dwRGBAlphaBitMask; |
||||
DWORD dwYUVAlphaBitMask; |
||||
DWORD dwRGBZBitMask; |
||||
DWORD dwYUVZBitMask; |
||||
}; |
||||
} DDPIXELFORMAT, *LPDDPIXELFORMAT; |
||||
|
||||
typedef struct _DDSURFACEDESC { |
||||
DWORD dwSize; |
||||
DWORD dwFlags; |
||||
DWORD dwHeight; |
||||
DWORD dwWidth; |
||||
union { |
||||
LONG lPitch; |
||||
DWORD dwLinearSize; |
||||
}; |
||||
DWORD dwBackBufferCount; |
||||
union { |
||||
DWORD dwMipMapCount; |
||||
DWORD dwZBufferBitDepth; |
||||
DWORD dwRefreshRate; |
||||
}; |
||||
DWORD dwAlphaBitDepth; |
||||
DWORD dwReserved; |
||||
LPVOID lpSurface; |
||||
DDCOLORKEY ddckCKDestOverlay; |
||||
DDCOLORKEY ddckCKDestBlt; |
||||
DDCOLORKEY ddckCKSrcOverlay; |
||||
DDCOLORKEY ddckCKSrcBlt; |
||||
DDPIXELFORMAT ddpfPixelFormat; |
||||
DDSCAPS ddsCaps; |
||||
} DDSURFACEDESC, *LPDDSURFACEDESC; |
||||
|
||||
#define _FACDD 0x876 |
||||
#define MAKE_DDHRESULT(code) MAKE_HRESULT(1, _FACDD, code) |
||||
|
||||
#define DDERR_SURFACELOST MAKE_DDHRESULT(450) |
||||
#define DDERR_WASSTILLDRAWING MAKE_DDHRESULT(540) |
||||
#define DDERR_SURFACEBUSY MAKE_DDHRESULT(430) |
||||
|
||||
typedef struct IDirectDrawPalette *LPDIRECTDRAWPALETTE; |
||||
typedef struct IDirectDrawSurface *LPDIRECTDRAWSURFACE; |
||||
typedef struct IDirectDraw *LPDIRECTDRAW; |
||||
|
||||
// No methods are actually used
|
||||
DECLARE_INTERFACE_(IDirectDrawPalette, IUnknown) |
||||
{ |
||||
// clang-format off
|
||||
STDMETHOD(GetCaps)(THIS_ LPDWORD lpdwCaps) PURE; |
||||
STDMETHOD(GetEntries)(THIS_ DWORD dwFlags, DWORD dwBase, DWORD dwNumEntries, LPPALETTEENTRY lpEntries) PURE; |
||||
STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, DWORD dwFlags, LPPALETTEENTRY lpDDColorTable) PURE; |
||||
STDMETHOD(SetEntries)(THIS_ DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries) PURE; |
||||
// clang-format on
|
||||
}; |
||||
|
||||
/*
|
||||
Actually used methods: |
||||
|
||||
DECLARE_INTERFACE_(IDirectDrawSurface, IUnknown) { |
||||
STDMETHOD(GetDC)(THIS_ HDC *); |
||||
STDMETHOD(IsLost)(THIS); |
||||
STDMETHOD(Lock)(THIS_ LPRECT, LPDDSURFACEDESC, DWORD, HANDLE); |
||||
STDMETHOD(ReleaseDC)(THIS_ HDC); |
||||
STDMETHOD(Restore)(THIS); |
||||
STDMETHOD(Unlock)(THIS_ LPVOID); |
||||
STDMETHOD(BltFast)(THIS_ DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD); |
||||
STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE); |
||||
}; |
||||
*/ |
||||
|
||||
typedef void *LPDDBLTBATCH, *LPDDBLTFX, *LPDIRECTDRAWCLIPPER, *LPDDENUMSURFACESCALLBACK, *LPDDOVERLAYFX; |
||||
DECLARE_INTERFACE_(IDirectDrawSurface, IUnknown) |
||||
{ |
||||
// clang-format off
|
||||
STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSAttachedSurface) PURE; |
||||
STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT lpRect) PURE; |
||||
STDMETHOD(Blt)(THIS_ LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx) PURE; |
||||
STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH lpDDBltBatch, DWORD dwCount, DWORD dwFlags) PURE; |
||||
STDMETHOD(BltFast)(THIS_ DWORD dwX, DWORD dwY, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwTrans) PURE; |
||||
STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSAttachedSurface) PURE; |
||||
STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; |
||||
STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD dwFlags, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpfnCallback) PURE; |
||||
STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride, DWORD dwFlags) PURE; |
||||
STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS lpDDSCaps, LPDIRECTDRAWSURFACE *lplpDDAttachedSurface) PURE; |
||||
STDMETHOD(GetBltStatus)(THIS_ DWORD dwFlags) PURE; |
||||
STDMETHOD(GetCaps)(THIS_ LPDDSCAPS lpDDSCaps) PURE; |
||||
STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER *lplpDDClipper) PURE; |
||||
STDMETHOD(GetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; |
||||
STDMETHOD(GetDC)(THIS_ HDC *lphDC) PURE; |
||||
STDMETHOD(GetFlipStatus)(THIS_ DWORD dwFlags) PURE; |
||||
STDMETHOD(GetOverlayPosition)(THIS_ LPLONG lplX, LPLONG lplY) PURE; |
||||
STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE *lplpDDPalette) PURE; |
||||
STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT lpDDPixelFormat) PURE; |
||||
STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; |
||||
STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW lpDD, LPDDSURFACEDESC lpDDSurfaceDesc) PURE; |
||||
STDMETHOD(IsLost)(THIS) PURE; |
||||
STDMETHOD(Lock)(THIS_ LPRECT lpDestRect, LPDDSURFACEDESC lpDDSurfaceDesc, DWORD dwFlags, HANDLE hEvent) PURE; |
||||
STDMETHOD(ReleaseDC)(THIS_ HDC hDC) PURE; |
||||
STDMETHOD(Restore)(THIS) PURE; |
||||
STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER lpDDClipper) PURE; |
||||
STDMETHOD(SetColorKey)(THIS_ DWORD dwFlags, LPDDCOLORKEY lpDDColorKey) PURE; |
||||
STDMETHOD(SetOverlayPosition)(THIS_ LONG lX, LONG lY) PURE; |
||||
STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE lpDDPalette) PURE; |
||||
STDMETHOD(Unlock)(THIS_ LPVOID lpSurfaceData) PURE; |
||||
STDMETHOD(UpdateOverlay)(THIS_ LPRECT lpSrcRect, LPDIRECTDRAWSURFACE lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags, LPDDOVERLAYFX lpDDOverlayFx) PURE; |
||||
STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD dwFlags) PURE; |
||||
STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD dwFlags, LPDIRECTDRAWSURFACE lpDDSReference) PURE; |
||||
// clang-format off
|
||||
}; |
||||
|
||||
#define DDBLTFAST_WAIT 0x00000010 |
||||
|
||||
#define DDLOCK_WRITEONLY 0x00000020L |
||||
#define DDLOCK_WAIT 0x00000001L |
||||
|
||||
#define DDPCAPS_ALLOW256 0x00000040l |
||||
#define DDPCAPS_8BIT 0x00000004l |
||||
|
||||
#define PC_RESERVED 0x01 |
||||
#define PC_NOCOLLAPSE 0x04 |
||||
|
||||
#define DDWAITVB_BLOCKBEGIN 0x00000001l |
||||
|
||||
/*
|
||||
Actually used methods: |
||||
|
||||
DECLARE_INTERFACE_(IDirectDraw, IUnknown) { |
||||
STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *); |
||||
STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE); |
||||
}; |
||||
*/ |
||||
|
||||
typedef void *LPDDENUMMODESCALLBACK, *LPDDCAPS; |
||||
DECLARE_INTERFACE_(IDirectDraw,IUnknown) |
||||
{ |
||||
// clang-format off
|
||||
STDMETHOD(Compact)(THIS) PURE; |
||||
STDMETHOD(CreateClipper)(THIS_ DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, IUnknown *pUnkOuter) PURE; |
||||
STDMETHOD(CreatePalette)(THIS_ DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE *lplpDDPalette, IUnknown *pUnkOuter) PURE; |
||||
STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE *lplpDDSurface, IUnknown *pUnkOuter) PURE; |
||||
STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE *lplpDupDDSurface) PURE; |
||||
STDMETHOD(EnumDisplayModes)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback) PURE; |
||||
STDMETHOD(EnumSurfaces)(THIS_ DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback) PURE; |
||||
STDMETHOD(FlipToGDISurface)(THIS) PURE; |
||||
STDMETHOD(GetCaps)(THIS_ LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps) PURE; |
||||
STDMETHOD(GetDisplayMode)(THIS_ LPDDSURFACEDESC lpDDSurfaceDesc) PURE; |
||||
STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD lpNumCodes, LPDWORD lpCodes) PURE; |
||||
STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE *lplpGDIDDSurface) PURE; |
||||
STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; |
||||
STDMETHOD(GetScanLine)(THIS_ LPDWORD lpdwScanLine) PURE; |
||||
STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL *lpbIsInVB) PURE; |
||||
STDMETHOD(Initialize)(THIS_ GUID *lpGUID) PURE; |
||||
STDMETHOD(RestoreDisplayMode)(THIS) PURE; |
||||
STDMETHOD(SetCooperativeLevel)(THIS_ HWND hWnd, DWORD dwFlags) PURE; |
||||
STDMETHOD(SetDisplayMode)(THIS_ DWORD dwWidth, DWORD dwHeight, DWORD dwBPP) PURE; |
||||
STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD dwFlags, HANDLE hEvent) PURE; |
||||
// clang-format on
|
||||
}; |
||||
@ -0,0 +1,46 @@
|
||||
#pragma once |
||||
|
||||
#include "miniwin.h" |
||||
|
||||
typedef void *LPDSBCAPS, *LPDIRECTSOUND, *LPCDSBUFFERDESC; |
||||
|
||||
DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown) |
||||
{ |
||||
// clang-format off
|
||||
STDMETHOD(GetCaps)(THIS_ LPDSBCAPS pDSBufferCaps); |
||||
STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor); |
||||
STDMETHOD(GetFormat)(THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten); |
||||
STDMETHOD(GetVolume)(THIS_ LPLONG plVolume); |
||||
STDMETHOD(GetPan)(THIS_ LPLONG plPan); |
||||
STDMETHOD(GetFrequency)(THIS_ LPDWORD pdwFrequency); |
||||
STDMETHOD(GetStatus)(THIS_ LPDWORD pdwStatus); |
||||
STDMETHOD(Initialize)(THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc); |
||||
STDMETHOD(Lock)(THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, |
||||
LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags); |
||||
STDMETHOD(Play)(THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags); |
||||
STDMETHOD(SetCurrentPosition)(THIS_ DWORD dwNewPosition); |
||||
STDMETHOD(SetFormat)(THIS_ LPCWAVEFORMATEX pcfxFormat); |
||||
STDMETHOD(SetVolume)(THIS_ LONG lVolume); |
||||
STDMETHOD(SetPan)(THIS_ LONG lPan); |
||||
STDMETHOD(SetFrequency)(THIS_ DWORD dwFrequency); |
||||
STDMETHOD(Stop)(THIS); |
||||
STDMETHOD(Unlock)(THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2); |
||||
STDMETHOD(Restore)(THIS); |
||||
// clang-format on
|
||||
}; |
||||
|
||||
typedef void *LPDIRECTSOUNDBUFFER, *LPDSCAPS, *LPUNKNOWN, *LPCGUID; |
||||
|
||||
DECLARE_INTERFACE_(IDirectSound, IUnknown) |
||||
{ |
||||
// clang-format off
|
||||
STDMETHOD(CreateSoundBuffer)(THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter); |
||||
STDMETHOD(GetCaps)(THIS_ LPDSCAPS pDSCaps); |
||||
STDMETHOD(DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate); |
||||
STDMETHOD(SetCooperativeLevel)(THIS_ HWND hwnd, DWORD dwLevel); |
||||
STDMETHOD(Compact)(THIS); |
||||
STDMETHOD(GetSpeakerConfig)(THIS_ LPDWORD pdwSpeakerConfig); |
||||
STDMETHOD(SetSpeakerConfig)(THIS_ DWORD dwSpeakerConfig); |
||||
STDMETHOD(Initialize)(THIS_ LPCGUID pcGuidDevice); |
||||
// clang-format on
|
||||
}; |
||||
@ -0,0 +1,141 @@
|
||||
#include <fcntl.h> |
||||
#include <sys/stat.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "miniwin.h" |
||||
#include "stubs.h" |
||||
|
||||
void TranslateFileName(char *dst, int dstLen, const char *src) |
||||
{ |
||||
for (int i = 0; i < dstLen; i++) { |
||||
char c = *src++; |
||||
dst[i] = c == '\\' ? '/' : c; |
||||
if (!c) { |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
HANDLE WINAPI CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, |
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, |
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) |
||||
{ |
||||
char name[260]; |
||||
TranslateFileName(name, sizeof(name), lpFileName); |
||||
|
||||
DUMMY_PRINT("file: %s (%s)", lpFileName, name); |
||||
|
||||
assert(dwDesiredAccess == GENERIC_READ | GENERIC_WRITE); |
||||
|
||||
int flags = O_RDWR; |
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
||||
if (dwCreationDisposition == OPEN_EXISTING) { |
||||
// Nothing
|
||||
} else if (dwCreationDisposition == CREATE_ALWAYS) { |
||||
flags |= O_CREAT | O_TRUNC; |
||||
} else { |
||||
UNIMPLEMENTED(); |
||||
} |
||||
int fd = open(name, flags, mode); |
||||
|
||||
return (HANDLE)fd; |
||||
} |
||||
|
||||
WINBOOL WINAPI ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, |
||||
LPOVERLAPPED lpOverlapped) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(!lpOverlapped); |
||||
int len = read((int)hFile, lpBuffer, nNumberOfBytesToRead); |
||||
assert(len != -1); |
||||
*lpNumberOfBytesRead = len; |
||||
return TRUE; |
||||
} |
||||
|
||||
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(!lpFileSizeHigh); |
||||
struct stat s; |
||||
int ret = fstat((int)hFile, &s); |
||||
assert(ret == 0); |
||||
return s.st_size; |
||||
} |
||||
|
||||
WINBOOL WINAPI WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, |
||||
LPOVERLAPPED lpOverlapped) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(!lpOverlapped); |
||||
ssize_t len = write((int)hFile, lpBuffer, nNumberOfBytesToWrite); |
||||
if (len == -1) { |
||||
*lpNumberOfBytesWritten = 0; |
||||
return FALSE; |
||||
} |
||||
*lpNumberOfBytesWritten = (DWORD)len; |
||||
return TRUE; |
||||
} |
||||
|
||||
DWORD WINAPI SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
assert(!lpDistanceToMoveHigh); |
||||
int whence; |
||||
if (dwMoveMethod == FILE_BEGIN) { |
||||
whence = SEEK_SET; |
||||
} else if (dwMoveMethod == FILE_CURRENT) { |
||||
whence = SEEK_CUR; |
||||
} else { |
||||
UNIMPLEMENTED(); |
||||
} |
||||
off_t ret = lseek((int)hFile, lDistanceToMove, whence); |
||||
return (DWORD)ret; |
||||
} |
||||
|
||||
WINBOOL WINAPI SetEndOfFile(HANDLE hFile) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
off_t cur = lseek((int)hFile, 0, SEEK_CUR); |
||||
assert(cur != -1); |
||||
int res = ftruncate((int)hFile, cur); |
||||
assert(res == 0); |
||||
return TRUE; |
||||
} |
||||
|
||||
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName) |
||||
{ |
||||
char name[260]; |
||||
TranslateFileName(name, sizeof(name), lpFileName); |
||||
|
||||
DUMMY_PRINT("file: %s (%s)", lpFileName, name); |
||||
|
||||
struct stat s; |
||||
int res = stat(name, &s); |
||||
|
||||
if (res == -1) { |
||||
SetLastError(ERROR_FILE_NOT_FOUND); |
||||
return (DWORD)-1; |
||||
} |
||||
|
||||
return 0x80; |
||||
} |
||||
|
||||
WINBOOL WINAPI SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes) |
||||
{ |
||||
DUMMY_PRINT("file: %s", lpFileName); |
||||
return TRUE; |
||||
} |
||||
|
||||
WINBOOL WINAPI CloseHandle(HANDLE hObject) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
int ret = close((int)hObject); |
||||
assert(ret == 0); |
||||
return TRUE; |
||||
} |
||||
@ -0,0 +1,277 @@
|
||||
/** @file
|
||||
* * |
||||
* Windows message handling and keyboard event conversion for SDL. |
||||
*/ |
||||
#include <deque> |
||||
|
||||
#include "miniwin_sdl.h" |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
static std::deque<MSG> message_queue; |
||||
|
||||
static int translate_sdl_key(SDL_Keysym key) |
||||
{ |
||||
int sym = key.sym; |
||||
switch (sym) { |
||||
case SDLK_ESCAPE: |
||||
return VK_ESCAPE; |
||||
case SDLK_RETURN: |
||||
return VK_RETURN; |
||||
case SDLK_TAB: |
||||
return VK_TAB; |
||||
case SDLK_BACKSPACE: |
||||
return VK_BACK; |
||||
|
||||
case SDLK_DOWN: |
||||
return VK_DOWN; |
||||
case SDLK_LEFT: |
||||
return VK_LEFT; |
||||
case SDLK_RIGHT: |
||||
return VK_RIGHT; |
||||
case SDLK_UP: |
||||
return VK_UP; |
||||
|
||||
case SDLK_PAGEUP: |
||||
return VK_PRIOR; |
||||
case SDLK_PAGEDOWN: |
||||
return VK_NEXT; |
||||
|
||||
case SDLK_PAUSE: |
||||
return VK_PAUSE; |
||||
|
||||
case SDLK_SEMICOLON: |
||||
return VK_OEM_1; |
||||
case SDLK_QUESTION: |
||||
return VK_OEM_2; |
||||
case SDLK_BACKQUOTE: |
||||
return VK_OEM_3; |
||||
case SDLK_LEFTBRACKET: |
||||
return VK_OEM_4; |
||||
case SDLK_BACKSLASH: |
||||
return VK_OEM_5; |
||||
case SDLK_RIGHTBRACKET: |
||||
return VK_OEM_6; |
||||
case SDLK_QUOTE: |
||||
return VK_OEM_7; |
||||
case SDLK_MINUS: |
||||
return VK_OEM_MINUS; |
||||
case SDLK_PLUS: |
||||
return VK_OEM_PLUS; |
||||
case SDLK_PERIOD: |
||||
return VK_OEM_PERIOD; |
||||
case SDLK_COMMA: |
||||
return VK_OEM_COMMA; |
||||
|
||||
case SDLK_LSHIFT: |
||||
case SDLK_RSHIFT: |
||||
// Not handled yet
|
||||
return -1; |
||||
|
||||
default: |
||||
if (sym >= SDLK_a && sym <= SDLK_z) { |
||||
return 'A' + (sym - SDLK_a); |
||||
} else if (sym >= SDLK_0 && sym <= SDLK_9) { |
||||
return '0' + (sym - SDLK_0); |
||||
} else if (sym >= SDLK_F1 && sym <= SDLK_F12) { |
||||
return VK_F1 + (sym - SDLK_F1); |
||||
} |
||||
|
||||
DUMMY_PRINT("unknown key: name=%s sym=0x%X scan=%d mod=0x%X", SDL_GetKeyName(sym), sym, key.scancode, key.mod); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
WINBOOL WINAPI PeekMessageA(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) |
||||
{ |
||||
// DUMMY_PRINT("hwnd: %d", hWnd);
|
||||
assert(wMsgFilterMin == 0 && wMsgFilterMax == 0); |
||||
if (wRemoveMsg == PM_NOREMOVE) { |
||||
// XXX: This does not actually fill out lpMsg properly
|
||||
lpMsg->hwnd = (HWND)-1; |
||||
lpMsg->message = 0; |
||||
|
||||
return !message_queue.empty() || SDL_PollEvent(NULL); |
||||
} else if (wRemoveMsg == PM_REMOVE) { |
||||
if (!message_queue.empty()) { |
||||
*lpMsg = message_queue.front(); |
||||
message_queue.pop_front(); |
||||
return TRUE; |
||||
} |
||||
|
||||
SDL_Event e; |
||||
int pending = SDL_PollEvent(&e); |
||||
if (!pending) { |
||||
return FALSE; |
||||
} |
||||
|
||||
lpMsg->hwnd = hWnd; |
||||
lpMsg->lParam = 0; |
||||
lpMsg->wParam = 0; |
||||
|
||||
switch (e.type) { |
||||
case SDL_QUIT: { |
||||
lpMsg->message = WM_QUIT; |
||||
break; |
||||
} |
||||
|
||||
case SDL_KEYDOWN: |
||||
case SDL_KEYUP: { |
||||
int key = translate_sdl_key(e.key.keysym); |
||||
if (key == -1) { |
||||
return FALSE; |
||||
} |
||||
|
||||
lpMsg->message = e.type == SDL_KEYDOWN ? WM_KEYFIRST : WM_KEYUP; |
||||
lpMsg->wParam = (DWORD)key; |
||||
// Hack: Encode modifier in lParam for TranslateMessage later
|
||||
lpMsg->lParam = e.key.keysym.mod << 16; |
||||
break; |
||||
} |
||||
|
||||
case SDL_MOUSEMOTION: { |
||||
lpMsg->message = WM_MOUSEMOVE; |
||||
lpMsg->lParam = (e.motion.y << 16) | (e.motion.x & 0xFFFF); |
||||
break; |
||||
} |
||||
|
||||
case SDL_MOUSEBUTTONDOWN: |
||||
case SDL_MOUSEBUTTONUP: { |
||||
int button = e.button.button; |
||||
if (button != SDL_BUTTON_LEFT && button != SDL_BUTTON_RIGHT) { |
||||
return FALSE; |
||||
} |
||||
bool left = button == SDL_BUTTON_LEFT; |
||||
lpMsg->message = e.type == SDL_MOUSEBUTTONDOWN ? (left ? WM_LBUTTONDOWN : WM_RBUTTONDOWN) |
||||
: (left ? WM_LBUTTONUP : WM_RBUTTONUP); |
||||
lpMsg->lParam = (e.button.y << 16) | (e.button.x & 0xFFFF); |
||||
break; |
||||
} |
||||
|
||||
case SDL_TEXTINPUT: |
||||
case SDL_WINDOWEVENT: { |
||||
return FALSE; |
||||
} |
||||
|
||||
default: { |
||||
DUMMY_PRINT("unknown SDL message 0x%X", e.type); |
||||
return FALSE; |
||||
} |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
WINBOOL WINAPI TranslateMessage(CONST MSG *lpMsg) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
assert(lpMsg->hwnd == 0); |
||||
|
||||
if (lpMsg->message == WM_KEYDOWN) { |
||||
int key = lpMsg->wParam; |
||||
unsigned mod = (DWORD)lpMsg->lParam >> 16; |
||||
|
||||
bool shift = (mod & KMOD_SHIFT) != 0; |
||||
bool upper = shift != (mod & KMOD_CAPS); |
||||
|
||||
bool is_alpha = (key >= 'A' && key <= 'Z'); |
||||
bool is_numeric = (key >= '0' && key <= '9'); |
||||
bool is_control = key == VK_SPACE || key == VK_BACK || key == VK_ESCAPE || key == VK_TAB || key == VK_RETURN; |
||||
bool is_oem = (key >= VK_OEM_1 && key <= VK_OEM_7); |
||||
|
||||
if (is_control || is_alpha || is_numeric || is_oem) { |
||||
if (!upper && is_alpha) { |
||||
key = tolower(key); |
||||
} else if (shift && is_numeric) { |
||||
key = key == '0' ? ')' : key - 0x10; |
||||
} else if (is_oem) { |
||||
// XXX: This probably only supports US keyboard layout
|
||||
switch (key) { |
||||
case VK_OEM_1: |
||||
key = shift ? ':' : ';'; |
||||
break; |
||||
case VK_OEM_2: |
||||
key = shift ? '?' : '/'; |
||||
break; |
||||
case VK_OEM_3: |
||||
key = shift ? '~' : '`'; |
||||
break; |
||||
case VK_OEM_4: |
||||
key = shift ? '{' : '['; |
||||
break; |
||||
case VK_OEM_5: |
||||
key = shift ? '|' : '\\'; |
||||
break; |
||||
case VK_OEM_6: |
||||
key = shift ? '}' : ']'; |
||||
break; |
||||
case VK_OEM_7: |
||||
key = shift ? '"' : '\''; |
||||
break; |
||||
|
||||
case VK_OEM_MINUS: |
||||
key = shift ? '_' : '-'; |
||||
break; |
||||
case VK_OEM_PLUS: |
||||
key = shift ? '+' : '='; |
||||
break; |
||||
case VK_OEM_PERIOD: |
||||
key = shift ? '>' : '.'; |
||||
break; |
||||
case VK_OEM_COMMA: |
||||
key = shift ? '<' : ','; |
||||
break; |
||||
|
||||
default: |
||||
UNIMPLEMENTED(); |
||||
} |
||||
} |
||||
|
||||
if (key >= 32) { |
||||
DUMMY_PRINT("char: %c", key); |
||||
} |
||||
|
||||
// XXX: This does not add extended info to lParam
|
||||
PostMessageA(lpMsg->hwnd, WM_CHAR, key, 0); |
||||
} |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
SHORT WINAPI GetAsyncKeyState(int vKey) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
// TODO: Not handled yet.
|
||||
return 0; |
||||
} |
||||
|
||||
LRESULT WINAPI DispatchMessageA(CONST MSG *lpMsg) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
assert(lpMsg->hwnd == 0); |
||||
assert(CurrentProc); |
||||
// assert(CurrentProc == GM_Game);
|
||||
|
||||
return CurrentProc(lpMsg->hwnd, lpMsg->message, lpMsg->wParam, lpMsg->lParam); |
||||
} |
||||
|
||||
WINBOOL WINAPI PostMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
assert(hWnd == 0); |
||||
|
||||
MSG msg; |
||||
msg.hwnd = hWnd; |
||||
msg.message = Msg; |
||||
msg.wParam = wParam; |
||||
msg.lParam = lParam; |
||||
|
||||
message_queue.push_back(msg); |
||||
|
||||
return TRUE; |
||||
} |
||||
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
* |
||||
* An implementation of the MSVCRT random number generator for codec_encode(). |
||||
*/ |
||||
#include "miniwin.h" |
||||
|
||||
#include "stubs.h" |
||||
|
||||
unsigned int rand_state = 1; |
||||
|
||||
int rand_miniwin(void) |
||||
{ |
||||
rand_state = rand_state * 214013 + 2531011; |
||||
return (rand_state >> 16) & 0x7FFF; |
||||
} |
||||
|
||||
void srand_miniwin(unsigned int seed) |
||||
{ |
||||
rand_state = seed; |
||||
} |
||||
@ -0,0 +1,11 @@
|
||||
#pragma once |
||||
|
||||
/** @file
|
||||
* Utilities for SDL. |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include <SDL2/SDL.h> |
||||
|
||||
#define SDL_CHECK(e) assert(e == 0) |
||||
@ -0,0 +1,11 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#ifndef NO_GLOBALS |
||||
BOOL loop_movie; |
||||
#endif |
||||
|
||||
void __fastcall play_movie(char *pszMovie, BOOL user_can_close) |
||||
{ |
||||
DUMMY_PRINT("%s", pszMovie); |
||||
} |
||||
@ -0,0 +1,81 @@
|
||||
#include <algorithm> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#ifndef NO_GLOBALS |
||||
int gdwNormalMsgSize; |
||||
int gdwLargestMsgSize; |
||||
int gdwMsgLenTbl[4]; |
||||
int glpMsgTbl[4]; |
||||
int gdwTurnsInTransit; |
||||
char byte_679704; |
||||
#endif |
||||
|
||||
void __fastcall nthread_start(bool set_turn_upper_bit) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
byte_679704 = 1; |
||||
gdwTurnsInTransit = 1; |
||||
gdwLargestMsgSize = 496; |
||||
gdwNormalMsgSize = 496; |
||||
} |
||||
|
||||
void __cdecl nthread_cleanup() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __fastcall nthread_terminate_game(char *pszFcn) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall nthread_ignore_mutex(bool bStart) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
bool __cdecl nthread_has_500ms_passed() |
||||
{ |
||||
DUMMY_ONCE(); |
||||
return TRUE; |
||||
} |
||||
|
||||
DWORD last_frame_time = 0; |
||||
const int MSEC_PER_FRAME = 1000 / 35; |
||||
|
||||
static void frame_rate_limiter() |
||||
{ |
||||
if (last_frame_time) { |
||||
int elapsed = GetTickCount() - last_frame_time; |
||||
int remaining = MSEC_PER_FRAME - elapsed; |
||||
if (remaining > 0) { |
||||
Sleep(std::max(remaining, MSEC_PER_FRAME)); |
||||
} |
||||
} |
||||
last_frame_time = GetTickCount(); |
||||
} |
||||
|
||||
int __fastcall nthread_send_and_recv_turn(int cur_turn, int turn_delta) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
// DUMMY_PRINT("cur_turn: %d turn_delta: %d", cur_turn, turn_delta);
|
||||
|
||||
frame_rate_limiter(); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
void __cdecl nthread_set_turn_upper_bit() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __fastcall nthread_recv_turns(int *pfSendAsync) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
*pfSendAsync = 0; |
||||
return TRUE; |
||||
} |
||||
@ -0,0 +1,14 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
bool __cdecl RestrictedTest() |
||||
{ |
||||
DUMMY(); |
||||
return FALSE; |
||||
} |
||||
|
||||
bool __cdecl ReadOnlyTest() |
||||
{ |
||||
DUMMY(); |
||||
return FALSE; |
||||
} |
||||
@ -0,0 +1,66 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
#ifndef NO_GLOBALS |
||||
char gbSndInited; |
||||
char gbDupSounds; |
||||
UCHAR gbMusicOn; |
||||
UCHAR gbSoundOn; |
||||
#endif |
||||
|
||||
void __fastcall snd_init(HWND hWnd) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __fastcall music_start(int nTrack) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
void __cdecl music_stop() |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
bool __fastcall snd_playing(TSnd *pSnd) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall snd_play_snd(TSnd *pSnd, int lVolume, int lPan) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall snd_stop_snd(TSnd *pSnd) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
TSnd *__fastcall sound_file_load(char *path) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void __fastcall sound_file_cleanup(TSnd *sound_file) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int __fastcall sound_get_or_set_sound_volume(int volume) |
||||
{ |
||||
DUMMY_PRINT("volume: %d", volume); |
||||
return volume; |
||||
} |
||||
|
||||
int __fastcall sound_get_or_set_music_volume(int volume) |
||||
{ |
||||
DUMMY_PRINT("volume: %d", volume); |
||||
return volume; |
||||
} |
||||
|
||||
void __fastcall snd_update(bool bStopAll) |
||||
{ |
||||
DUMMY_PRINT("stopall: %d", bStopAll); |
||||
} |
||||
@ -0,0 +1,367 @@
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
DWORD nLastError = 0; |
||||
|
||||
BOOL STORMAPI SNetCreateGame(const char *pszGameName, const char *pszGamePassword, const char *pszGameStatString, |
||||
DWORD dwGameType, char *GameTemplateData, int GameTemplateSize, int playerCount, |
||||
char *creatorName, char *a11, int *playerID) |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL STORMAPI SNetDestroy() |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL STORMAPI SNetDropPlayer(int playerid, DWORD flags) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetGetGameInfo(int type, void *dst, size_t length, size_t *byteswritten) |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL STORMAPI SNetGetTurnsInTransit(int *turns) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetLeaveGame(int type) |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL STORMAPI SNetPerformUpgrade(DWORD *upgradestatus) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetReceiveTurns(int a1, int arraysize, char **arraydata, unsigned int *arraydatabytes, |
||||
DWORD *arrayplayerstatus) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetSendTurn(char *data, size_t databytes) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetSetGameMode(DWORD modeFlags, bool makePublic) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SNetSendServerChatCommand(const char *command) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
// BOOL STORMAPI SFileCloseArchive(HANDLE hArchive)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
// BOOL STORMAPI SFileCloseFile(HANDLE hFile)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
BOOL STORMAPI SFileDdaBeginEx(HANDLE directsound, DWORD flags, DWORD mask, unsigned __int32 lDistanceToMove, |
||||
signed __int32 volume, signed int a6, int a7) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileDdaDestroy() |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileDdaEnd(HANDLE directsound) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileDdaGetPos(HANDLE directsound, int a2, int a3) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileDdaInitialize(HANDLE directsound) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileDdaSetVolume(HANDLE directsound, signed int bigvolume, signed int volume) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SFileGetFileArchive(HANDLE hFile, HANDLE archive) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
// LONG STORMAPI SFileGetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
// BOOL STORMAPI SFileOpenArchive(const char *szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE
|
||||
// *phMpq)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
BOOL STORMAPI SFileOpenFile(const char *filename, HANDLE *phFile) |
||||
{ |
||||
BOOL result; |
||||
eprintf("%s: %s\n", __FUNCTION__, filename); |
||||
|
||||
result = SFileOpenFileEx((HANDLE)patch_rt_mpq, filename, 0, phFile); |
||||
if (!result) { |
||||
result = SFileOpenFileEx((HANDLE)diabdat_mpq, filename, 0, phFile); |
||||
} |
||||
|
||||
if (!result || !*phFile) { |
||||
eprintf("%s: Not found: %s\n", __FUNCTION__, filename); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
// BOOL STORMAPI SFileOpenFileEx(HANDLE hMpq, const char *szFileName, DWORD dwSearchScope, HANDLE
|
||||
// *phFile)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
// BOOL STORMAPI SFileReadFile(HANDLE hFile, void *buffer, DWORD nNumberOfBytesToRead, DWORD *read,
|
||||
// LONG lpDistanceToMoveHigh)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
// int __stdcall SFileSetFilePointer(HANDLE, int, HANDLE, int)
|
||||
// {
|
||||
// UNIMPLEMENTED();
|
||||
// }
|
||||
|
||||
HWND STORMAPI SDrawGetFrameWindow(HWND *sdraw_framewindow) |
||||
{ |
||||
DUMMY(); |
||||
return NULL; |
||||
} |
||||
|
||||
// BOOL STORMAPI SDrawManualInitialize(HWND hWnd, LPDIRECTDRAW ddInterface, LPDIRECTDRAWSURFACE
|
||||
// primarySurface, LPDIRECTDRAWSURFACE surface2, LPDIRECTDRAWSURFACE surface3, LPDIRECTDRAWSURFACE
|
||||
// backSurface, LPDIRECTDRAWPALETTE ddPalette, HPALETTE hPalette)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
|
||||
void *STORMAPI SMemAlloc(size_t amount, char *logfilename, int logline, char defaultValue) |
||||
{ |
||||
// fprintf(stderr, "%s: %d (%s:%d)\n", __FUNCTION__, amount, logfilename, logline);
|
||||
assert(amount != -1); |
||||
return malloc(amount); |
||||
} |
||||
|
||||
BOOL STORMAPI SMemFree(void *location, char *logfilename, int logline, char defaultValue) |
||||
{ |
||||
// fprintf(stderr, "%s: (%s:%d)\n", __FUNCTION__, logfilename, logline);
|
||||
assert(location); |
||||
free(location); |
||||
return TRUE; |
||||
} |
||||
|
||||
void *STORMAPI SMemReAlloc(void *location, size_t amount, char *logfilename, int logline, char defaultValue) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SRegLoadData(const char *keyname, const char *valuename, int size, LPBYTE lpData, BYTE flags, |
||||
LPDWORD lpcbData) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SRegLoadString(const char *keyname, const char *valuename, BYTE flags, char *buffer, size_t buffersize) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SRegLoadValue(const char *keyname, const char *valuename, BYTE flags, int *value) |
||||
{ |
||||
DUMMY_PRINT("key: %s value: %s", keyname, valuename); |
||||
return FALSE; |
||||
} |
||||
|
||||
BOOL STORMAPI SRegSaveData(const char *keyname, const char *valuename, int size, BYTE *lpData, DWORD cbData) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SRegSaveString(const char *keyname, const char *valuename, BYTE flags, char *string) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SRegSaveValue(const char *keyname, const char *valuename, BYTE flags, DWORD result) |
||||
{ |
||||
DUMMY_PRINT("key: %s value: %s", keyname, valuename); |
||||
return TRUE; |
||||
} |
||||
|
||||
// BOOL STORMAPI SVidDestroy()
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// BOOL STORMAPI SVidInitialize(HANDLE video)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// BOOL STORMAPI SVidPlayBegin(char *filename, int arg4, int a3, int a4, int a5, int a6, HANDLE
|
||||
// *video)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// BOOL STORMAPI SVidPlayEnd(HANDLE video)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
|
||||
BOOL STORMAPI SErrDisplayError(DWORD dwErrMsg, const char *logfilename, int logline, const char *message, |
||||
BOOL allowOption, int exitCode) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
BOOL STORMAPI SErrGetErrorStr(DWORD dwErrCode, char *buffer, size_t bufferchars) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
DWORD STORMAPI SErrGetLastError() |
||||
{ |
||||
return nLastError; |
||||
} |
||||
|
||||
void STORMAPI SErrSetLastError(DWORD dwErrCode) |
||||
{ |
||||
nLastError = dwErrCode; |
||||
} |
||||
|
||||
void STORMAPI SMemCopy(void *dest, const void *source, size_t size) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void STORMAPI SMemFill(void *location, size_t length, char fillWith) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void STORMAPI SMemZero(void *location, DWORD length) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int STORMAPI SMemCmp(void *location1, void *location2, DWORD size) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int STORMAPI SStrCopy(char *dest, const char *src, int max_length) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int STORMAPI SStrCmp(const char *string1, const char *string2, size_t size) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
int STORMAPI SStrCmpI(const char *string1, const char *string2, size_t size) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
// void __stdcall SDrawMessageBox(char *, char *, int)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// void __cdecl SDrawDestroy(void)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// bool __cdecl StormDestroy(void)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
//
|
||||
// bool __stdcall SFileSetBasePath(char *)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
|
||||
void __cdecl SDrawRealizePalette(void) |
||||
{ |
||||
DUMMY(); |
||||
} |
||||
|
||||
// bool __cdecl SVidPlayContinue(void)
|
||||
//{
|
||||
// UNIMPLEMENTED();
|
||||
//}
|
||||
|
||||
bool __stdcall SNetGetOwnerTurnsWaiting(int *) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
void *__stdcall SNetUnregisterEventHandler(int, void(__stdcall *)(struct _SNETEVENT *)) |
||||
{ |
||||
DUMMY(); |
||||
return (void *)-1; |
||||
} |
||||
|
||||
void *__stdcall SNetRegisterEventHandler(int, void(__stdcall *)(struct _SNETEVENT *)) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
|
||||
bool __stdcall SNetSetBasePlayer(int) |
||||
{ |
||||
DUMMY(); |
||||
return TRUE; |
||||
} |
||||
|
||||
int __stdcall SNetInitializeProvider(unsigned long a1, struct _SNETPROGRAMDATA *client_info, |
||||
struct _SNETPLAYERDATA *user_info, struct _SNETUIDATA *ui_info, |
||||
struct _SNETVERSIONDATA *fileinfo) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
ui_info->selectnamecallback(0, 0, 0, 0, 0, NULL, 0, NULL, 0, NULL); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
int __stdcall SNetGetProviderCaps(struct _SNETCAPS *) |
||||
{ |
||||
UNIMPLEMENTED(); |
||||
} |
||||
@ -0,0 +1,49 @@
|
||||
/** @file
|
||||
* |
||||
* A minimal implementation of the Storm network stack necessary for local play. |
||||
*/ |
||||
#include <deque> |
||||
#include <string> |
||||
|
||||
#include "../types.h" |
||||
#include "stubs.h" |
||||
|
||||
struct StubMessage { |
||||
int playerid; |
||||
std::string data; |
||||
}; |
||||
|
||||
/** A queue of messages waiting to be processed. */ |
||||
static std::deque<StubMessage> snet_messages; |
||||
/**
|
||||
* Last message returned from SNetReceiveMessage(). |
||||
* Must always be kept alive because the caller will read the data afterwards. |
||||
*/ |
||||
static StubMessage snet_current_message; |
||||
|
||||
BOOL STORMAPI SNetReceiveMessage(int *senderplayerid, char **data, int *databytes) |
||||
{ |
||||
DUMMY_ONCE(); |
||||
|
||||
if (snet_messages.empty()) { |
||||
SErrSetLastError(STORM_ERROR_NO_MESSAGES_WAITING); |
||||
return FALSE; |
||||
} |
||||
|
||||
snet_current_message = std::move(snet_messages.front()); |
||||
snet_messages.pop_front(); |
||||
|
||||
*senderplayerid = snet_current_message.playerid; |
||||
*data = const_cast<char *>(snet_current_message.data.data()); |
||||
*databytes = snet_current_message.data.size(); |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL STORMAPI SNetSendMessage(int playerID, void *data, size_t databytes) |
||||
{ |
||||
DUMMY(); |
||||
|
||||
snet_messages.push_back(StubMessage{playerID, std::string((char *)data, databytes)}); |
||||
return TRUE; |
||||
} |
||||
@ -0,0 +1,34 @@
|
||||
#pragma once |
||||
|
||||
/** @file
|
||||
* Utility functions for stubs. |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
#include <stdio.h> |
||||
|
||||
#define eprintf(...) fprintf(stderr, __VA_ARGS__) |
||||
|
||||
#define UNIMPLEMENTED() \ |
||||
{ \
|
||||
eprintf("UNIMPLEMENTED: %s @ %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
|
||||
abort(); \
|
||||
} |
||||
|
||||
#define DUMMY() eprintf("DUMMY: %s @ %s:%d\n", __FUNCTION__, __FILE__, __LINE__) |
||||
|
||||
#define DUMMY_ONCE() \ |
||||
{ \
|
||||
static bool dummy_shown = false; \
|
||||
if (!dummy_shown) { \
|
||||
DUMMY(); \
|
||||
dummy_shown = true; \
|
||||
} \
|
||||
} |
||||
|
||||
#define DUMMY_PRINT(fmt, ...) eprintf("DUMMY: %s : " fmt "\n", __FUNCTION__, __VA_ARGS__) |
||||
|
||||
static inline const char *nullstr(const char *a) |
||||
{ |
||||
return a ? a : "(null)"; |
||||
} |
||||
@ -0,0 +1,6 @@
|
||||
/** @file
|
||||
* Perform some basic compile-time validation to make sure things line up. |
||||
*/ |
||||
#include "../types.h" |
||||
|
||||
static_assert(sizeof(plr) == 0x15360u, "sizeof(PlayerStruct) is wrong"); |
||||
@ -0,0 +1,9 @@
|
||||
FROM base/archlinux |
||||
|
||||
RUN echo -e "[multilib]\nInclude = /etc/pacman.d/mirrorlist" >> /etc/pacman.conf |
||||
RUN pacman -Sy |
||||
RUN pacman --noconfirm -Sy \ |
||||
make gcc cmake pkg-config nasm lib32-gcc-libs lib32-sdl2 |
||||
|
||||
WORKDIR /build |
||||
VOLUME /src |
||||
@ -0,0 +1,10 @@
|
||||
#!/bin/bash |
||||
|
||||
# |
||||
# Build script to run inside a Docker container |
||||
# |
||||
|
||||
set -e |
||||
|
||||
cmake /src |
||||
make -j$(nproc) |
||||
Loading…
Reference in new issue