1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-23 08:52:25 +01:00
cnc-ddraw/src/mouse.c

343 lines
9.2 KiB
C
Raw Normal View History

/*
* Copyright (c) 2010 Toni Spets <toni.spets@iki.fi>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* This is a special mouse coordinate fix for games that use GetCursorPos and expect to be in fullscreen */
#include <windows.h>
#include <stdio.h>
#include "main.h"
#include "surface.h"
#define MAX_HOOKS 16
BOOL mouse_active = FALSE;
int yAdjust = 0;
struct hook { char name[32]; void *func; };
struct hack
{
char name[32];
struct hook hooks[MAX_HOOKS];
};
BOOL WINAPI fake_GetCursorPos(LPPOINT lpPoint)
{
2018-03-23 03:21:16 +01:00
POINT pt, realpt;
2018-03-11 21:23:22 +01:00
if (!GetCursorPos(&pt))
return FALSE;
2018-03-23 03:21:16 +01:00
realpt.x = pt.x;
realpt.y = pt.y;
2018-03-11 21:23:22 +01:00
if(ddraw->locked && (!ddraw->windowed || ScreenToClient(ddraw->hWnd, &pt)))
2011-09-11 19:09:15 +03:00
{
//fallback solution for possible ClipCursor failure
int diffx = 0, diffy = 0;
if (pt.x < 0)
{
diffx = abs(pt.x);
pt.x = 0;
}
if (pt.y < 0)
{
diffy = abs(pt.y);
pt.y = 0;
}
if (diffx || diffy)
SetCursorPos(realpt.x + diffx, realpt.y + diffy);
2018-03-11 21:23:22 +01:00
if(ddraw->adjmouse)
{
ddraw->cursor.x = pt.x * ((float)ddraw->width / ddraw->render.viewport.width);
ddraw->cursor.y = pt.y * ((float)ddraw->height / ddraw->render.viewport.height);
2018-03-11 21:23:22 +01:00
}
else
2018-03-09 18:20:09 +01:00
{
ddraw->cursor.x = pt.x;
ddraw->cursor.y = pt.y;
}
//fallback solution for possible ClipCursor failure
diffx = 0;
diffy = 0;
if (ddraw->cursor.x > ddraw->width)
{
diffx = ddraw->cursor.x - ddraw->width;
ddraw->cursor.x = ddraw->width;
}
if (ddraw->cursor.y > ddraw->height)
{
diffy = ddraw->cursor.y - ddraw->height;
ddraw->cursor.y = ddraw->height;
}
if (diffx || diffy)
SetCursorPos(realpt.x - diffx, realpt.y - diffy);
2018-03-23 23:10:49 +01:00
if (ddraw->vhack && (ddraw->iscnc1 || ddraw->isredalert) && ddraw->incutscene)
2018-03-23 03:21:16 +01:00
{
diffx = 0;
diffy = 0;
2018-03-23 03:21:16 +01:00
if (ddraw->cursor.x > CUTSCENE_WIDTH)
{
diffx = ddraw->cursor.x - CUTSCENE_WIDTH;
ddraw->cursor.x = CUTSCENE_WIDTH;
}
if (ddraw->cursor.y > CUTSCENE_HEIGHT)
{
diffy = ddraw->cursor.y - CUTSCENE_HEIGHT;
ddraw->cursor.y = CUTSCENE_HEIGHT;
}
if (diffx || diffy)
SetCursorPos(realpt.x - diffx, realpt.y - diffy);
}
2018-03-11 21:23:22 +01:00
}
2018-03-11 21:23:22 +01:00
if (lpPoint)
{
2018-03-19 01:11:54 +01:00
if (ddraw->fakecursorpos)
{
2018-03-19 01:11:54 +01:00
lpPoint->x = (int)ddraw->cursor.x;
lpPoint->y = (int)ddraw->cursor.y;
}
2018-03-19 01:11:54 +01:00
else if (ddraw->locked || ddraw->devmode)
{
2018-03-23 03:21:16 +01:00
lpPoint->x = realpt.x;
lpPoint->y = realpt.y;
2018-03-19 01:11:54 +01:00
}
else
return FALSE;
2011-09-11 19:09:15 +03:00
}
2018-03-14 13:15:34 +01:00
return TRUE;
}
BOOL WINAPI fake_ClipCursor(const RECT *lpRect)
{
2010-11-26 21:44:31 +02:00
if(lpRect)
{
/* hack for 640x480 mode */
if (lpRect->bottom == 400 && ddraw->height == 480)
yAdjust = 40;
2010-11-26 21:44:31 +02:00
}
return TRUE;
}
int WINAPI fake_ShowCursor(BOOL bShow)
{
return TRUE;
}
HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
{
return NULL;
}
struct hack hacks[] =
{
{
"user32.dll",
{
{ "GetCursorPos", fake_GetCursorPos },
{ "ClipCursor", fake_ClipCursor },
{ "ShowCursor", fake_ShowCursor },
{ "SetCursor", fake_SetCursor } ,
{ "", NULL }
}
},
{
"",
{
{ "", NULL }
}
}
};
void hack_iat(struct hack *hck)
{
int i;
char buf[32];
struct hook *hk;
DWORD dwWritten;
IMAGE_DOS_HEADER dos_hdr;
IMAGE_NT_HEADERS nt_hdr;
IMAGE_IMPORT_DESCRIPTOR *dir;
IMAGE_THUNK_DATA thunk;
PDWORD ptmp;
HMODULE base = GetModuleHandle(NULL);
HANDLE hProcess = GetCurrentProcess();
ReadProcessMemory(hProcess, (void *)base, &dos_hdr, sizeof(IMAGE_DOS_HEADER), &dwWritten);
2018-05-06 10:52:06 +02:00
ReadProcessMemory(hProcess, (void *)((char *)base + dos_hdr.e_lfanew), &nt_hdr, sizeof(IMAGE_NT_HEADERS), &dwWritten);
dir = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nt_hdr.OptionalHeader.DataDirectory[1].Size));
2018-05-06 10:52:06 +02:00
ReadProcessMemory(hProcess, (void *)((char *)base + nt_hdr.OptionalHeader.DataDirectory[1].VirtualAddress), dir, nt_hdr.OptionalHeader.DataDirectory[1].Size, &dwWritten);
2018-05-06 10:52:06 +02:00
while (dir->Name > 0)
{
memset(buf, 0, 32);
2018-05-06 10:52:06 +02:00
ReadProcessMemory(hProcess, (void *)((char *)base + dir->Name), buf, 32, &dwWritten);
if (_stricmp(buf, hck->name) == 0)
{
ptmp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DWORD) * 64);
2018-05-06 10:52:06 +02:00
ReadProcessMemory(hProcess, (void *)((char *)base + dir->Characteristics), ptmp, sizeof(DWORD) * 64, &dwWritten);
i = 0;
while (*ptmp)
{
memset(buf, 0, 32);
2018-05-06 10:52:06 +02:00
ReadProcessMemory(hProcess, (void *)((char *)base + (*ptmp) + 2), buf, 32, &dwWritten);
hk = &hck->hooks[0];
2018-05-06 10:52:06 +02:00
while (hk->func)
{
2018-05-06 10:52:06 +02:00
if (_stricmp(hk->name, buf) == 0)
{
thunk.u1.Function = (DWORD)hk->func;
thunk.u1.Ordinal = (DWORD)hk->func;
thunk.u1.AddressOfData = (DWORD)hk->func;
2018-05-06 10:52:06 +02:00
VirtualProtectEx(hProcess, (void *)((char *)base + dir->FirstThunk + (sizeof(IMAGE_THUNK_DATA) * i)), sizeof(IMAGE_THUNK_DATA), PAGE_EXECUTE_READWRITE, &dwWritten);
WriteProcessMemory(hProcess, (void *)((char *)base + dir->FirstThunk + (sizeof(IMAGE_THUNK_DATA) * i)), &thunk, sizeof(IMAGE_THUNK_DATA), &dwWritten);
mouse_active = TRUE;
}
hk++;
}
ptmp++;
i++;
}
}
dir++;
}
CloseHandle(hProcess);
}
void mouse_lock()
{
RECT rc;
if (ddraw->devmode)
{
while(ShowCursor(FALSE) > 0);
return;
}
if (mouse_active && !ddraw->locked)
{
// Get the window client area.
GetClientRect(ddraw->hWnd, &rc);
if(ddraw->adjmouse)
{
rc.right = ddraw->render.viewport.width;
rc.bottom = ddraw->render.viewport.height;
}
else
2018-03-11 21:23:22 +01:00
{
rc.right = ddraw->width;
rc.bottom = ddraw->height;
2018-03-11 21:23:22 +01:00
}
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(ddraw->hWnd, &pt);
ClientToScreen(ddraw->hWnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
rc.bottom -= (yAdjust * 2) * ((float)ddraw->render.viewport.height / ddraw->height);
2018-03-11 21:23:22 +01:00
if(ddraw->adjmouse)
{
SetCursorPos(
rc.left + (ddraw->cursor.x * ((float)ddraw->render.viewport.width / ddraw->width)),
rc.top + ((ddraw->cursor.y - yAdjust) * ((float)ddraw->render.viewport.height / ddraw->height)));
2018-03-11 21:23:22 +01:00
}
else
{
SetCursorPos(rc.left + ddraw->cursor.x, rc.top + ddraw->cursor.y - yAdjust);
}
SetCapture(ddraw->hWnd);
ClipCursor(&rc);
while(ShowCursor(FALSE) > 0);
ddraw->locked = TRUE;
}
}
void mouse_unlock()
{
RECT rc;
if (ddraw->devmode)
{
while(ShowCursor(TRUE) < 0);
return;
}
if(!mouse_active)
{
return;
}
if(ddraw->locked)
{
ddraw->locked = FALSE;
// Get the window client area.
GetClientRect(ddraw->hWnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(ddraw->hWnd, &pt);
ClientToScreen(ddraw->hWnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
2010-11-08 19:23:39 +02:00
while(ShowCursor(TRUE) < 0);
SetCursor(LoadCursor(NULL, IDC_ARROW));
ClipCursor(NULL);
ReleaseCapture();
SetCursorPos(
rc.left + ddraw->render.viewport.x +
(ddraw->cursor.x * ((float)ddraw->render.viewport.width / ddraw->width)),
rc.top + ddraw->render.viewport.y +
((ddraw->cursor.y + yAdjust) * ((float)ddraw->render.viewport.height / ddraw->height)));
}
}
void mouse_init()
{
hack_iat(&hacks[0]);
mouse_active = TRUE;
}