Start macOS/Linux fake-api

This commit is contained in:
Inori 2019-08-22 13:56:18 -04:00 committed by Inori
parent 141e06c7a0
commit 606975b505
4 changed files with 325 additions and 48 deletions

View file

@ -108,12 +108,12 @@ Being simple as it is, it remains mostly as the lazy option/last resort to add C
To alleviate possible porting of heavily Win32API reliant scripts, certain functionality that you won't find in the RGSS spec has been added. Currently this amounts to the following:
# Input
### Input
* The `Input.press?` family of functions accepts three additional button constants: `::MOUSELEFT`, `::MOUSEMIDDLE` and `::MOUSERIGHT` for the respective mouse buttons.
* The `Input` module has two additional functions, `#mouse_x` and `#mouse_y` to query the mouse pointer position relative to the game screen.
# Graphics
### Graphics
* The `Graphics` module has two additional properties: `fullscreen` represents the current fullscreen mode (`true` = fullscreen, `false` = windowed), `show_cursor` hides the system cursor inside the game window when `false`.
* The `Graphics` module has one additional function: `Graphics.screenshot(path)` will save a screenshot to `path` in BMP format.

View file

@ -59,8 +59,12 @@ MiniFFI_GetFunctionHandle(void *libhandle, const char *func)
CAPTURE(RegisterHotKey);
CAPTURE(GetKeyboardState);
#ifndef __WIN32__
// Functions needed on Linux and macOS go here
// Functions only needed on Linux and macOS go here
CAPTURE(RtlMoveMemory);
CAPTURE(LoadLibrary);
CAPTURE(FreeLibrary);
#endif
if (!libhandle) return 0;
#endif
return SDL_LoadFunction(libhandle, func);
}
@ -74,14 +78,11 @@ RB_METHOD(MiniFFI_initialize)
rb_scan_args(argc, argv, "22", &libname, &func, &imports, &exports);
SafeStringValue(libname);
SafeStringValue(func);
void *hlib = SDL_LoadObject(RSTRING_PTR(libname));
if (!hlib)
rb_raise(rb_eRuntimeError, SDL_GetError());
DATA_PTR(self) = hlib;
void *hfunc = MiniFFI_GetFunctionHandle(hlib, RSTRING_PTR(func));
#ifdef __WIN32__
if (!hfunc)
if (hlib && !hfunc)
{
VALUE func_a = rb_str_new3(func);
func_a = rb_str_cat(func_a, "A", 1);

View file

@ -1,9 +1,12 @@
#ifdef __WIN32__
#include <SDL.h>
#include <SDL_syswm.h>
#include <cmath>
#ifdef __WIN32__
#include <windows.h>
#include <SDL_syswm.h>
#else
#include <map>
#include "eventthread.h"
#endif
#include "sharedstate.h"
#include "input.h"
@ -39,34 +42,208 @@
// functionality into MKXP and don't use MiniFFI/Win32API at all.
// A lot of functions here will probably be bound directly to Ruby
// eventually (so that you can just call Graphics.save_screenshot
// or something instead of having to make a messy Win32API call
// eventually (so that you can just call Graphics.screenshot or
// something instead of having to make a messy Win32API call
// that *now* has to run entirely different function to even work)
// No macOS/Linux support yet.
// macOS/Linux support WIP.
// ===============================================================
// This map is for converting Windows virtual keycodes to SDL's
// scancodes. Only needs to exist on macOS and Linux to allow
// getAsyncKeyState to work.
// ===============================================================
#ifndef __WIN32__
#define m(vk,sc) { vk, SDL_SCANCODE_##sc }
#define n(vk) m(vk,-1)
std::map<int, int> vKeyToScancode{
// 0x01 LEFT MOUSE
// 0x02 RIGHT MOUSE
m(0x03, CANCEL),
// 0x04 MIDDLE MOUSE
// 0x05 XBUTTON 1
// 0x06 XBUTTON 2
// 0x07 undef
m(0x08, BACKSPACE),
m(0x09, TAB),
// 0x0a reserved
// 0x0b reserved
m(0x0c, CLEAR),
m(0x0d, RETURN),
// 0x0e undefined
// 0x0f undefined
// 0x10 SHIFT (both)
// 0x11 CONTROL (both)
// 0x12 ALT (both)
m(0x13, PAUSE),
m(0x14, CAPSLOCK),
// 0x15 KANA, HANGUL
// 0x16 undefined
// 0x17 JUNJA
// 0x18 FINAL
// 0x19 HANJA, KANJI
// 0x1a undefined
m(0x1b, ESCAPE),
// 0x1c CONVERT
// 0x1d NONCONVERT
// 0x1e ACCEPT
// 0x1f MODECHANGE
m(0x20, SPACE),
m(0x21, PAGEUP),
m(0x22, PAGEDOWN),
m(0x23, END),
m(0x24, HOME),
m(0x25, LEFT),
m(0x26, UP),
m(0x27, RIGHT),
m(0x28, DOWN),
m(0x29, SELECT),
// 0x2A print
m(0x2b, EXECUTE),
m(0x2c, PRINTSCREEN),
m(0x2d, INSERT),
m(0x2e, DELETE),
m(0x2f, HELP),
m(0x30, 0), m(0x31, 1),
m(0x32, 2), m(0x33, 3),
m(0x34, 4), m(0x35, 5),
m(0x36, 6), m(0x37, 7),
m(0x38, 8), m(0x39, 9),
// 0x3a-0x40 undefined
m(0x41, A), m(0x42, B),
m(0x43, C), m(0x44, D),
m(0x45, E), m(0x46, F),
m(0x47, G), m(0x48, H),
m(0x49, I), m(0x4a, J),
m(0x4b, K), m(0x4c, L),
m(0x4d, M), m(0x4e, N),
m(0x4f, O), m(0x50, P),
m(0x51, Q), m(0x52, R),
m(0x53, S), m(0x54, T),
m(0x55, U), m(0x56, V),
m(0x57, W), m(0x58, X),
m(0x59, Y), m(0x5a, Z),
m(0x5b, LGUI), m(0x5c, RGUI),
m(0x5d, APPLICATION),
// 0x5e reserved
m(0x5f, SLEEP),
m(0x60, KP_0), m(0x61, KP_1),
m(0x62, KP_2), m(0x63, KP_3),
m(0x64, KP_4), m(0x65, KP_5),
m(0x66, KP_6), m(0x67, KP_7),
m(0x68, KP_8), m(0x69, KP_9),
m(0x6a, KP_MULTIPLY),
m(0x6b, KP_PLUS),
m(0x6c, RETURN), // SEPARATOR
m(0x6d, KP_MINUS),
m(0x6e, KP_DECIMAL),
m(0x6f, KP_DIVIDE),
m(0x70, F1), m(0x71, F2),
m(0x72, F3), m(0x73, F4),
m(0x74, F5), m(0x75, F6),
m(0x76, F7), m(0x77, F8),
m(0x78, F9), m(0x79, F10),
m(0x7a, F11), m(0x7b, F12),
m(0x7c, F13), m(0x7d, F14),
m(0x7e, F15), m(0x7f, F16),
m(0x80, F17), m(0x81, F18),
m(0x82, F19), m(0x83, F20),
m(0x84, F21), m(0x85, F22),
m(0x86, F23), m(0x87, F24),
// 0x88-0x8f unassigned
m(0x90, NUMLOCKCLEAR),
m(0x91, SCROLLLOCK),
// 0x92-0x96 oem specific
// 0x97-0x9f unassigned
m(0xa0, LSHIFT),
m(0xa1, RSHIFT),
m(0xa2, LCTRL),
m(0xa3, RCTRL),
m(0xa4, LALT),
m(0xa5, RALT),
m(0xa6, AC_BACK),
m(0xa7, AC_FORWARD),
m(0xa8, AC_REFRESH),
m(0xa9, AC_STOP),
m(0xaa, AC_SEARCH),
// 0xab BROWSER_FAVORITES
m(0xac, AC_HOME),
m(0xad, AUDIOMUTE),
m(0xae, VOLUMEDOWN),
m(0xaf, VOLUMEUP),
m(0xb0, AUDIONEXT),
m(0xb1, AUDIOPREV),
m(0xb2, AUDIOSTOP),
m(0xb3, AUDIOPLAY),
m(0xb4, MAIL),
m(0xb5, MEDIASELECT),
// 0xb6 LAUNCH_APP1
// 0xb7 LAUNCH_APP2
// 0xb8-0xb9 reserved
// Everything below here is OEM
// and can vary by country
m(0xba, SEMICOLON),
m(0xbb, EQUALS),
m(0xbc, COMMA),
m(0xbd, MINUS),
m(0xbe, PERIOD),
m(0xbf, SLASH),
m(0xc0, GRAVE),
// 0xc1-0xd7 reserved
// 0xd8-0xda unassigned
m(0xdb, LEFTBRACKET),
m(0xdc, BACKSLASH),
m(0xdd, RIGHTBRACKET),
m(0xde, APOSTROPHE),
// 0xdf OEM_8
// 0xe0 reserved
// 0xe1 oem-specific
// 0xe2 OEM_102
// 0xe3-0xe4 oem-specific
// 0xe5 PROCESSKEY
// 0xe6 oem-specific
// 0xe7 PACKET
// 0xe8 unassigned
// 0xe9-0xf5 oem_specific
// 0xf6 ATTN
m(0xf7, CRSEL),
m(0xf8, EXSEL),
// 0xf9 EREOF
m(0xfa, AUDIOPLAY), // PLAY, guessing
// 0xfb ZOOM
// 0xfc NONAME
// 0xfd PA1
m(0xfe, CLEAR)
};
#undef m
#endif
DWORD __stdcall
PREFABI DWORD
MKXP_GetCurrentThreadId(void)
NOP_VAL(DUMMY_VAL)
DWORD __stdcall
PREFABI DWORD
MKXP_GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId)
NOP_VAL(DUMMY_VAL)
HWND __stdcall
PREFABI HWND
MKXP_FindWindowEx(HWND hWnd,
HWND hWndChildAfter,
LPCSTR lpszClass,
LPCSTR lpszWindow
)
#ifdef __WIN32__
{
SDL_SysWMinfo wm;
SDL_GetWindowWMInfo(shState->sdlWindow(), &wm);
return wm.info.win.window;
}
#else
NOP_VAL(DUMMY_VAL)
#endif
DWORD __stdcall
PREFABI DWORD
MKXP_GetForegroundWindow(void)
{
if (SDL_GetWindowFlags(shState->sdlWindow()) & SDL_WINDOW_INPUT_FOCUS)
@ -76,7 +253,7 @@ MKXP_GetForegroundWindow(void)
return 0;
}
BOOL __stdcall
PREFABI BOOL
MKXP_GetClientRect(HWND hWnd, LPRECT lpRect)
{
SDL_GetWindowSize(shState->sdlWindow(),
@ -89,14 +266,14 @@ MKXP_GetClientRect(HWND hWnd, LPRECT lpRect)
// You would think that you could just call GetCursorPos
// and ScreenToClient with the window handle and lppoint
// and be fine, but nope
BOOL __stdcall
PREFABI BOOL
MKXP_GetCursorPos(LPPOINT lpPoint)
{
SDL_GetGlobalMouseState((int*)&lpPoint->x, (int*)&lpPoint->y);
return true;
}
BOOL __stdcall
PREFABI BOOL
MKXP_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
{
lpPoint->x = shState->input().mouseX();
@ -104,7 +281,7 @@ MKXP_ScreenToClient(HWND hWnd, LPPOINT lpPoint)
return true;
}
BOOL __stdcall
PREFABI BOOL
MKXP_SetWindowPos(HWND hWnd,
HWND hWndInsertAfter,
int X,
@ -117,12 +294,16 @@ MKXP_SetWindowPos(HWND hWnd,
// SetWindowPos, but it still needs to be called
// because Win32API.restoreScreen is picky about its
// metrics
#ifdef __WIN32__
SetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
#else
SDL_SetWindowSize(shState->sdlWindow(), cx, cy);
#endif
SDL_SetWindowPosition(shState->sdlWindow(), X, Y);
return true;
}
BOOL __stdcall
PREFABI BOOL
MKXP_SetWindowTextA(HWND hWnd, LPCSTR lpString)
{
SDL_SetWindowTitle(shState->sdlWindow(), (const char*)lpString);
@ -130,7 +311,7 @@ MKXP_SetWindowTextA(HWND hWnd, LPCSTR lpString)
}
BOOL __stdcall
PREFABI BOOL
MKXP_GetWindowRect(HWND hWnd, LPRECT lpRect)
{
int cur_x, cur_y, cur_w, cur_h;
@ -143,17 +324,19 @@ MKXP_GetWindowRect(HWND hWnd, LPRECT lpRect)
return true;
}
BOOL __stdcall
PREFABI BOOL
MKXP_RegisterHotKey(HWND hWnd,
int id,
UINT fsModifiers,
UINT vk)
NOP_VAL(true)
// Shift key from GetKeyboardState doesn't work for whatever reason
BOOL __stdcall
// Shift key with GetKeyboardState doesn't work for whatever reason,
// so Windows needs this too
PREFABI BOOL
MKXP_GetKeyboardState(PBYTE lpKeyState)
{
#ifdef __WIN32__
bool rc = GetKeyboardState(lpKeyState);
if (rc)
{
@ -163,5 +346,69 @@ MKXP_GetKeyboardState(PBYTE lpKeyState)
lpKeyState[VK_SHIFT] = (lpKeyState[VK_LSHIFT] || lpKeyState[VK_RSHIFT]) ? 0x80 : 0;
}
return rc;
}
#else
for (int i = 254; i > 0; i--)
{
if (i == 0x10) // Either Shift key
{
lpKeyState[i] = (lpKeyState[0xa0] || lpKeyState[0xa1]) ? 0x80 : 0;
}
else if (i == 0x11) // Either Ctrl key
{
lpKeyState[i] = (lpKeyState[0xa2] || lpKeyState[0xa3]) ? 0x80 : 0;
}
else if (i == 0x12) // Either Alt key
{
lpKeyState[i] = (lpKeyState[0xa4] || lpKeyState[0xa5]) ? 0x80 : 0;
}
else
{
try
{
lpKeyState[i] = shState->eThread().keyStates[vKeyToScancode[i]] << 7;
}
catch(...)
{
lpKeyState[i] = 0;
}
}
}
return true;
#endif
}
// =========================================
// macOS / Linux only stuff starts here
// =========================================
#ifndef __WIN32__
PREFABI VOID
MKXP_RtlMoveMemory(VOID *Destination, VOID *Source, SIZE_T Length)
{
// I have no idea if this is a good idea or not
// or why it's even necessary in the first place,
// getting rid of this is priority #1
memcpy(Destination, Source, Length);
}
// I don't know who's more crazy, them for writing this stuff
// or me for being willing to put it here.
// Probably me.
PREFABI HMODULE
MKXP_LoadLibrary(LPCSTR lpLibFileName)
{
return SDL_LoadObject(lpLibFileName);
}
PREFABI BOOL
MKXP_FreeLibrary(HMODULE hLibModule)
{
SDL_UnloadObject(hLibModule);
return true;
}
#endif

View file

@ -1,23 +1,40 @@
#pragma once
#ifdef __WIN32__
#include <windows.h>
#else
#include <map>
#endif
#define ABI(x) __attribute__((x))
#if defined(__WIN32__)
#define PREFABI ABI(stdcall)
#else
#define PREFABI
#endif
/*
#ifndef __WIN32__
typedef unsigned long HWND;
typedef unsigned int DWORD;
typedef unsigned int* LPDWORD;
typedef char* LPCSTR;
typedef unsigned int HWND, DWORD, UINT, *LPDWORD;
typedef char *LPCSTR, *PBYTE;
typedef int LONG;
typedef bool BOOL;
typedef unsigned int UINT;
typedef struct {
LONG x;
LONG y;
} POINT;
typedef POINT* LPPOINT;
} POINT, *LPPOINT;
typedef struct {
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT, *PRECT, *NPRECT, *LPRECT;
typedef void VOID, *LPVOID, *HANDLE, *HMODULE;
typedef size_t SIZE_T;
extern std::map<int, int> vKeyToScancode;
#endif
*/
#define DUMMY_VAL 571
#define NOP \
@ -29,32 +46,32 @@ return; \
return x; \
}
DWORD __stdcall
PREFABI DWORD
MKXP_GetCurrentThreadId(void);
DWORD __stdcall
PREFABI DWORD
MKXP_GetWindowThreadProcessId(HWND hWnd, LPDWORD lpdwProcessId);
HWND __stdcall
PREFABI HWND
MKXP_FindWindowEx(HWND hWnd,
HWND hWndChildAfter,
LPCSTR lpszClass,
LPCSTR lpszWindow
);
DWORD __stdcall
PREFABI DWORD
MKXP_GetForegroundWindow(void);
BOOL __stdcall
PREFABI BOOL
MKXP_GetClientRect(HWND hWnd, LPRECT lpRect);
BOOL __stdcall
PREFABI BOOL
MKXP_GetCursorPos(LPPOINT lpPoint);
BOOL __stdcall
PREFABI BOOL
MKXP_ScreenToClient(HWND hWnd, LPPOINT lpPoint);
BOOL __stdcall
PREFABI BOOL
MKXP_SetWindowPos(HWND hWnd,
HWND hWndInsertAfter,
int X,
@ -63,18 +80,30 @@ MKXP_SetWindowPos(HWND hWnd,
int cy,
UINT uFlags);
BOOL __stdcall
PREFABI BOOL
MKXP_SetWindowTextA(HWND hWnd, LPCSTR lpString);
BOOL __stdcall
PREFABI BOOL
MKXP_GetWindowRect(HWND hWnd, LPRECT lpRect);
BOOL __stdcall
PREFABI BOOL
MKXP_RegisterHotKey(HWND hWnd,
int id,
UINT fsModifiers,
UINT vk);
BOOL __stdcall
PREFABI BOOL
MKXP_GetKeyboardState(PBYTE lpKeyState);
#ifndef __WIN32__
PREFABI VOID
MKXP_RtlMoveMemory(VOID *Destination, VOID *Source, SIZE_T Length);
PREFABI HMODULE
MKXP_LoadLibrary(LPCSTR lpLibFileName);
PREFABI BOOL
MKXP_FreeLibrary(HMODULE hLibModule);
#endif