: assigned or transferred by contract.
Authors : os, m
Created : 2007-08-23 10:08:25
- Updated : 2018-10-04 16:40:44
+ Updated : 2018-10-19 16:01:23
Comment : Reference for RetroPlatformIPC.h (RP Player interprocess communication include file)
*****************************************************************************/
RawInput RI_MOUSE_BUTTON_* flags or 0
+Message:
+ RP_IPC_TO_HOST_MOUSEMOVE
+Description:
+ the guest sends this message to forward mouse move events;
+ mouse events forwarding is off by default and is enabled
+ by the RP_IPC_TO_GUEST_SENDMOUSEEVENTS message;
+ the screen coordinate range is the same used for screen overlays
+ (e.g. lLeft and lTop fields of the RPSCREENOVERLAY structure)
+Data sent:
+ LPARAM = screen coordinates combined with the MAKELONG macro (i.e. MAKELONG(x,y))
+Response:
+ none
+
+
+Message:
+ RP_IPC_TO_HOST_MOUSEBUTTON
+Description:
+ the guest sends this message to forward mouse button events;
+ mouse events forwarding is off by default and is enabled
+ by the RP_IPC_TO_GUEST_SENDMOUSEEVENTS message;
+ the screen coordinate range is the same used for screen overlays
+ (e.g. lLeft and lTop fields of the RPSCREENOVERLAY structure)
+Data sent:
+ WPARAM = mouse buttons state
+ (bit 0 = left button state, bit 1 = right button state, ...)
+ LPARAM = screen coordinates combined with the MAKELONG macro (i.e. MAKELONG(x,y))
+Response:
+ none
+
+
Messages:
RP_IPC_TO_HOST_PRIVATE_REGISTER
RP_IPC_TO_HOST_PRIVATE_SHAREDEVENT
RP_IPC_TO_HOST_PRIVATE_GUESTEVENT
RP_IPC_TO_HOST_PRIVATE_KEYPROMPT
RP_IPC_TO_HOST_PRIVATE_CLOSEKBDWIN
+ RP_IPC_TO_HOST_PRIVATE_MENUEVENT
Description:
these are private messages, sent by code in RPGuest.dll
Message:
RP_IPC_TO_GUEST_SCREENOVERLAY
Description:
- This message sets or clears a screen overlay (an image that the guest
+ This message creates a screen overlay (an image that the guest
renders on top of the emulated system screen).
Multiple screen overlays can be set and simultaneously displayed
on the screen (see the dwIndex field of the RPSCREENOVERLAY structure).
- When the lWidth and lHeight fields of the RPSCREENOVERLAY structure
- are set to a non-zero value, an overlay is defined or updated;
- if the two fields are set to 0, the overlay specified
- by the dwIndex field is removed from screen
+ NOTE: guests that support screen overlays must set the
+ RP_FEATURE_SCREENOVERLAY flag in the startup RP_IPC_TO_HOST_FEATURES message.
Data sent:
pData = a RPSCREENOVERLAY structure containing overlay information and image data
Response:
LRESULT = 1, if the guest successfully executed the command, or 0 otherwise
+Message:
+ RP_IPC_TO_GUEST_MOVESCREENOVERLAY
+Description:
+ This message moves a previously defined screen overlay to a specified position.
+Data sent:
+ WPARAM = screen overlay index
+ LPARAM = screen coordinates combined with the MAKELONG macro (i.e. MAKELONG(x,y))
+Response:
+ LRESULT = 1, if the guest successfully executed the command, or 0 otherwise
+
+
+Message:
+ RP_IPC_TO_GUEST_DELETESCREENOVERLAY
+Description:
+ This message deletes a previously defined screen overlay.
+Data sent:
+ WPARAM = screen overlay index
+Response:
+ LRESULT = 1, if the guest successfully executed the command, or 0 otherwise
+
+
+Message:
+ RP_IPC_TO_GUEST_SENDMOUSEEVENTS
+Description:
+ The host sends this message to ask the guest to enable/disable
+ mouse events forwarding; this is typically done when the emulation is paused
+ and the host wnats to handle mouse navigation of screen overlays;
+ see RP_IPC_TO_HOST_MOUSEMOVE and RP_IPC_TO_HOST_MOUSEBUTTON
+ for additional information.
+Data sent:
+ WPARAM = set to 1 to enable mouse events forwarding, or 0 to disable it
+Response:
+ LRESULT = 1 if the guest acknowledged the command or 0 otherwise
+
+
Messages:
RP_IPC_TO_GUEST_PRIVATE_STARTUP
RP_IPC_TO_GUEST_PRIVATE_TYPECLIP
RP_IPC_TO_GUEST_PRIVATE_INPUTDEVICES
RP_IPC_TO_GUEST_PRIVATE_NOKEYPROMPT
RP_IPC_TO_GUEST_PRIVATE_KEYBOARDWINDOW
+ RP_IPC_TO_GUEST_PRIVATE_MENUMODE
Description:
these are private messages, received by code in RPGuest.dll;
they never reach the message function in guest code
: Software Foundation.
Authors : os, m
Created : 2007-08-27 13:55:49
- Updated : 2018-10-04 16:26:12
+ Updated : 2018-10-19 15:58:12
Comment : RetroPlatform Player interprocess communication include file
*****************************************************************************/
#define RP_IPC_TO_HOST_PRIVATE_KEYREMINDER (WM_APP + 35) // introduced in RetroPlatform API 7.2
#define RP_IPC_TO_HOST_RAWINPUT_EVENT (WM_APP + 36) // introduced in RetroPlatform API 7.3
#define RP_IPC_TO_HOST_PRIVATE_CLOSEKBDWIN (WM_APP + 37) // introduced in RetroPlatform API 7.4
+#define RP_IPC_TO_HOST_MOUSEMOVE (WM_APP + 38) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_HOST_MOUSEBUTTON (WM_APP + 39) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_HOST_PRIVATE_MENUEVENT (WM_APP + 40) // introduced in RetroPlatform API 7.5
// ****************************************************************************
// Host-to-Guest Messages
#define RP_IPC_TO_GUEST_PRIVATE_KEYREMINDER (WM_APP + 229) // introduced in RetroPlatform API 7.2
#define RP_IPC_TO_GUEST_PRIVATE_KEYBOARDWINDOW (WM_APP + 230) // introduced in RetroPlatform API 7.4
#define RP_IPC_TO_GUEST_SCREENOVERLAY (WM_APP + 231) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_GUEST_MOVESCREENOVERLAY (WM_APP + 232) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_GUEST_DELETESCREENOVERLAY (WM_APP + 233) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_GUEST_SENDMOUSEEVENTS (WM_APP + 234) // introduced in RetroPlatform API 7.5
+#define RP_IPC_TO_GUEST_PRIVATE_MENUMODE (WM_APP + 235) // introduced in RetroPlatform API 7.5
// ****************************************************************************
// Message Data Structures and Defines
#define RP_FEATURE_MEMORY_ADVANCED 0x04000000 // Memory I/O advanced features: Watch, Find, Alert, Freeze, Lock, Unlock, Off (must set both flags if full set is supported!)
#define RP_FEATURE_SCREENCAPTURE 0x08000000 // new screen capture functionality is available (see RP_IPC_TO_GUEST_SCREENCAPTURE message)
#define RP_FEATURE_RAWINPUT_EVENT 0x10000000 // RawInput mouse buttons events are forwarded via RP_IPC_TO_HOST_RAWINPUT_EVENT messages
+#define RP_FEATURE_SCREENOVERLAY 0x20000000 // supports screen overlays
typedef struct RPScreenMode
{
// RPSCREENOVERLAY dwFormat
#define RPSOPF_32BIT_BGRA 0 // 4 bytes per pixel (blue, green, red, alpha)
+
+// RP_IPC_TO_HOST_PRIVATE_MENUEVENT wParam
+#define RP_MENU_EVENT_RIGHT 1
+#define RP_MENU_EVENT_LEFT 2
+#define RP_MENU_EVENT_DOWN 3
+#define RP_MENU_EVENT_UP 4
+#define RP_MENU_EVENT_SELECT 5
+#define RP_MENU_EVENT_BACK 6
+
+
// Legacy Compatibility
#ifndef RP_NO_LEGACY
// Changed in 7.0
D3DXHANDLE framecounterHandle;
};
+struct d3d9overlay
+{
+ int x, y;
+ LPDIRECT3DTEXTURE9 tex;
+};
+
#define MAX_SHADERS (2 * MAX_FILTERSHADERS + 2)
#define SHADER_POST 0
float mask2texture_wwx, mask2texture_hhx, mask2texture_minusx, mask2texture_minusy;
float mask2texture_multx, mask2texture_multy, mask2texture_offsetw;
LPDIRECT3DTEXTURE9 cursorsurfaced3d;
+ struct d3d9overlay extoverlays[EXTOVERLAYS];
IDirect3DVertexBuffer9 *vertexBuffer;
ID3DXSprite *sprite;
HWND d3dhwnd;
d3d->cursorsurfaced3d->Release ();
d3d->cursorsurfaced3d = NULL;
}
+ for (int i = 0; i < EXTOVERLAYS; i++) {
+ struct d3d9overlay *o = &d3d->extoverlays[i];
+ if (o->tex) {
+ o->tex->Release();
+ o->tex = NULL;
+ }
+ }
for (int i = 0; i < MAX_SHADERS; i++) {
if (d3d->shaders[i].pEffect) {
d3d->shaders[i].pEffect->Release ();
v.z = 0;
d3d->sprite->Draw(d3d->ledtexture, NULL, NULL, &v, 0xffffffff);
}
+ for (int i = 0; i < EXTOVERLAYS; i++) {
+ struct d3d9overlay *o = &d3d->extoverlays[i];
+ if (o->tex) {
+ v.x = o->x;
+ v.y = o->y;
+ v.z = 0;
+ d3d->sprite->Draw(o->tex, NULL, NULL, &v, 0xffffffff);
+ }
+ }
d3d->sprite->End();
}
#endif
if (!isd3d (d3d))
return;
- D3D_render2 (d3d, true);
- D3D_showframe2 (d3d, true);
- D3D_render2 (d3d, true);
- D3D_showframe2 (d3d, true);
- createscanlines (d3d, 0);
+ createscanlines(d3d, 0);
+ for (int i = 0; i < 2; i++) {
+ D3D_render2(d3d, true);
+ D3D_showframe2(d3d, true);
+ }
}
void D3D_getpixelformat (int depth, int *rb, int *gb, int *bb, int *rs, int *gs, int *bs, int *ab, int *as, int *a)
return false;
}
+static bool xD3D_extoverlay(struct extoverlay *ext)
+{
+ struct d3dstruct *d3d = &d3ddata[0];
+ D3DLOCKED_RECT locked;
+ HRESULT hr;
+
+ if (ext->idx >= EXTOVERLAYS)
+ return false;
+
+ write_log(_T("extoverlay %d: x=%d y=%d %d*%d\n"), ext->idx, ext->xpos, ext->ypos, ext->width, ext->height);
+
+ struct d3d9overlay *s = &d3d->extoverlays[ext->idx];
+
+ if (!s->tex && (ext->width <= 0 || ext->height <= 0))
+ return false;
+
+ if (!ext->data && s->tex && (ext->width == 0 || ext->height == 0)) {
+ s->x = ext->xpos;
+ s->y = ext->ypos;
+ return true;
+ }
+
+ if (s->tex) {
+ s->tex->Release();
+ s->tex = NULL;
+ }
+
+ if (ext->width <= 0 || ext->height <= 0)
+ return true;
+
+ s->tex = createtext(d3d, ext->width, ext->height, D3DFMT_A8R8G8B8);
+
+ if (!s->tex)
+ return false;
+
+ s->x = ext->xpos;
+ s->y = ext->ypos;
+
+ hr = s->tex->LockRect(0, &locked, NULL, 0);
+ if (FAILED(hr)) {
+ write_log(_T("extoverlay LockRect failed %08x\n"), hr);
+ s->tex->Release();
+ s->tex = NULL;
+ return false;
+ }
+ for (int y = 0; y < ext->height; y++) {
+ memcpy((uae_u8*)locked.pBits + y * locked.Pitch, ext->data + y * ext->width * 4, ext->width * 4);
+ }
+ s->tex->UnlockRect(0);
+
+ return true;
+}
+
void d3d9_select(void)
{
D3D_free = xD3D_free;
D3D_debug = xD3D_debug;
D3D_led = xD3D_led;
D3D_getscanline = xD3D_getscanline;
+ D3D_extoverlay = xD3D_extoverlay;
}
#endif
return;
createscanlines(d3d, 0);
- if (xD3D11_renderframe(monid, true, true)) {
- xD3D11_showframe(monid);
+ for (int i = 0; i < 2; i++) {
+ if (xD3D11_renderframe(monid, true, true)) {
+ xD3D11_showframe(monid);
+ }
}
clearcnt = 0;
}
if (ext->idx >= EXTOVERLAYS)
return false;
- write_log(_T("extoverlay %d: x=%d y=%d %d*%d\n"), ext->idx, ext->xpos, ext->ypos, ext->width, ext->height);
+ write_log(_T("extoverlay %d: x=%d y=%d %d*%d data=%p\n"), ext->idx, ext->xpos, ext->ypos, ext->width, ext->height, ext->data);
struct d3d11sprite *s = &d3d->extoverlays[ext->idx];
+ if (!s->enabled && (ext->width <= 0 || ext->height <= 0))
+ return false;
+
+ if (!ext->data && s->enabled && (ext->width == 0 || ext->height == 0)) {
+ s->x = ext->xpos;
+ s->y = ext->ypos;
+ return true;
+ }
+
freesprite(s);
- if (!allocsprite(d3d, &d3d->extoverlays[ext->idx], ext->width, ext->height, true))
+
+ if (ext->width <= 0 || ext->height <= 0)
+ return true;
+
+ if (!allocsprite(d3d, s, ext->width, ext->height, true))
return false;
s->enabled = true;
static int screenmode_request;
static HWND guestwindow;
static int hwndset_delay;
+static int sendmouseevents;
+static int mouseevent_x, mouseevent_y, mouseevent_buttons;
static int cando (void)
{
case RP_IPC_TO_HOST_HOSTVERSION: return _T("RP_IPC_TO_HOST_HOSTVERSION");
case RP_IPC_TO_HOST_INPUTDEVICE: return _T("RP_IPC_TO_HOST_INPUTDEVICE");
case RP_IPC_TO_HOST_KEYBOARDLAYOUT: return _T("RP_IPC_TO_HOST_KEYBOARDLAYOUT");
+ case RP_IPC_TO_HOST_MOUSEMOVE: return _T("RP_IPC_TO_HOST_MOUSEMOVE");
+ case RP_IPC_TO_HOST_MOUSEBUTTON: return _T("RP_IPC_TO_HOST_MOUSEBUTTON");
case RP_IPC_TO_GUEST_CLOSE: return _T("RP_IPC_TO_GUEST_CLOSE");
case RP_IPC_TO_GUEST_SCREENMODE: return _T("RP_IPC_TO_GUEST_SCREENMODE");
case RP_IPC_TO_GUEST_SHOWOPTIONS: return _T("RP_IPC_TO_GUEST_SHOWOPTIONS");
case RP_IPC_TO_GUEST_DEVICEACTIVITY: return _T("RP_IPC_TO_GUEST_DEVICEACTIVITY");
case RP_IPC_TO_GUEST_SCREENOVERLAY: return _T("RP_IPC_TO_GUEST_SCREENOVERLAY");
+ case RP_IPC_TO_GUEST_DELETESCREENOVERLAY: return _T("RP_IPC_TO_GUEST_DELETESCREENOVERLAY");
+ case RP_IPC_TO_GUEST_MOVESCREENOVERLAY: return _T("RP_IPC_TO_GUEST_MOVESCREENOVERLAY");
+ case RP_IPC_TO_GUEST_SENDMOUSEEVENTS: return _T("RP_IPC_TO_GUEST_SENDMOUSEEVENTS");
default: return _T("UNKNOWN");
}
}
xfree(s);
}
+static int movescreenoverlay(WPARAM wParam, LPARAM lParam)
+{
+ struct extoverlay eo = { 0 };
+ if (!D3D_extoverlay)
+ return 0;
+ eo.idx = wParam;
+ eo.xpos = LOWORD(lParam);
+ eo.ypos = HIWORD(lParam);
+ int ret = D3D_extoverlay(&eo);
+ if (pause_emulation) {
+ D3D_refresh(0);
+ }
+ return ret;
+}
+
+static int deletescreenoverlay(WPARAM wParam)
+{
+ struct extoverlay eo = { 0 };
+ if (!D3D_extoverlay)
+ return 0;
+ eo.idx = wParam;
+ eo.width = -1;
+ eo.height = -1;
+ int ret = D3D_extoverlay(&eo);
+ if (pause_emulation) {
+ D3D_refresh(0);
+ }
+ return ret;
+}
+
static int screenoverlay(LPCVOID pData)
{
struct RPScreenOverlay *rpo = (struct RPScreenOverlay*)pData;
eo.width = rpo->lWidth;
eo.height = rpo->lHeight;
eo.data = rpo->btData;
- return D3D_extoverlay(&eo) ? 1 : 0;
+ int ret = D3D_extoverlay(&eo);
+ if (pause_emulation) {
+ D3D_refresh(0);
+ }
+ return ret;
}
static LRESULT CALLBACK RPHostMsgFunction2 (UINT uMessage, WPARAM wParam, LPARAM lParam,
return deviceactivity(wParam, lParam);
case RP_IPC_TO_GUEST_SCREENOVERLAY:
return screenoverlay(pData);
+ case RP_IPC_TO_GUEST_DELETESCREENOVERLAY:
+ return deletescreenoverlay(wParam);
+ case RP_IPC_TO_GUEST_MOVESCREENOVERLAY:
+ return movescreenoverlay(wParam, lParam);
+ case RP_IPC_TO_GUEST_SENDMOUSEEVENTS:
+ sendmouseevents = wParam;
+ if (sendmouseevents) {
+ LRESULT lr = NULL;
+ LPARAM lp = MAKELONG(mouseevent_x, mouseevent_y);
+ RPSendMessage(RP_IPC_TO_HOST_MOUSEMOVE, 0, lp, NULL, 0, &guestinfo, &lr);
+ }
+ return 1;
}
return FALSE;
}
feat = RP_FEATURE_POWERLED | RP_FEATURE_SCREEN1X | RP_FEATURE_FULLSCREEN;
feat |= RP_FEATURE_PAUSE | RP_FEATURE_TURBO_CPU | RP_FEATURE_TURBO_FLOPPY | RP_FEATURE_VOLUME | RP_FEATURE_SCREENCAPTURE;
- feat |= RP_FEATURE_STATE | RP_FEATURE_DEVICEREADWRITE;
+ feat |= RP_FEATURE_STATE | RP_FEATURE_DEVICEREADWRITE | RP_FEATURE_SCREENOVERLAY;
if (WIN32GFX_IsPicassoScreen(mon)) {
if (currprefs.gfx_api)
feat |= RP_FEATURE_SCREEN2X | RP_FEATURE_SCREEN3X | RP_FEATURE_SCREEN4X;
write_log (_T("rp_fixup_options(escapekey=%d,escapeholdtime=%d,screenmode=%d,inputmode=%d)\n"),
rp_rpescapekey, rp_rpescapeholdtime, rp_screenmode, rp_inputmode);
+ sendmouseevents = 0;
+ mouseevent_x = mouseevent_y = 0;
+ mouseevent_buttons = 0;
max_horiz_dbl = currprefs.gfx_max_horizontal;
max_vert_dbl = currprefs.gfx_max_vertical;
maxjports = (rp_version * 256 + rp_revision) >= 2 * 256 + 3 ? MAX_JPORTS : 2;
return usButtonFlags;
}
+bool rp_mouseevent(int x, int y, int buttons, int buttonmask)
+{
+ if (!sendmouseevents) {
+ if (x > -30000 && y > -30000) {
+ mouseevent_x = x;
+ mouseevent_y = y;
+ }
+ return false;
+ }
+ LRESULT lr;
+ if (x > -30000 && y > -30000 && (x != mouseevent_x || y != mouseevent_y)) {
+ LPARAM lParam = MAKELONG(x, y);
+ RPSendMessage(RP_IPC_TO_HOST_MOUSEMOVE, 0, lParam, NULL, 0, &guestinfo, &lr);
+ mouseevent_x = x;
+ mouseevent_y = y;
+ }
+ if (buttons >= 0 && (buttons & buttonmask) != (mouseevent_buttons & buttonmask)) {
+ LPARAM lParam = MAKELONG(mouseevent_x, mouseevent_y);
+ mouseevent_buttons &= ~buttonmask;
+ mouseevent_buttons |= buttons & buttonmask;
+ RPSendMessage(RP_IPC_TO_HOST_MOUSEBUTTON, mouseevent_buttons, lParam, NULL, 0, &guestinfo, &lr);
+ }
+ return true;
+}
+
int rp_isactive (void)
{
return initialized;
extern void rp_screenmode_changed (void);
extern void rp_keymap(TrapContext*, uaecptr, uae_u32);
extern USHORT rp_rawbuttons(LPARAM lParam, USHORT usButtonFlags);
+extern bool rp_mouseevent(int x, int y, int buttons, int buttonmask);
extern TCHAR *rp_param;
extern int rp_rpescapekey;
return 0;
case WM_LBUTTONUP:
+ rp_mouseevent(-32768, -32768, 0, 1);
if (dinput_winmouse() >= 0 && isfocus()) {
if (log_winmouse)
write_log(_T("WM_LBUTTONUP\n"));
return 0;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
+ rp_mouseevent(-32768, -32768, 1, 1);
if (!mouseactive && !gui_active && (!mousehack_alive() || currprefs.input_tablet != TABLET_MOUSEHACK || (currprefs.input_tablet == TABLET_MOUSEHACK && !(currprefs.input_mouse_untrap & MOUSEUNTRAP_MAGIC)) || isfullscreen() > 0)) {
// borderless = do not capture with single-click
if (ignorelbutton) {
}
return 0;
case WM_RBUTTONUP:
+ rp_mouseevent(-32768, -32768, 0, 2);
if (dinput_winmouse() >= 0 && isfocus()) {
if (log_winmouse)
write_log(_T("WM_RBUTTONUP\n"));
return 0;
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
+ rp_mouseevent(-32768, -32768, 2, 2);
if (dinput_winmouse() >= 0 && isfocus() > 0) {
if (log_winmouse)
write_log(_T("WM_RBUTTONDOWN\n"));
}
return 0;
case WM_MBUTTONUP:
+ rp_mouseevent(-32768, -32768, 0, 4);
if (!(currprefs.input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON)) {
if (log_winmouse)
write_log(_T("WM_MBUTTONUP\n"));
return 0;
case WM_MBUTTONDOWN:
case WM_MBUTTONDBLCLK:
+ rp_mouseevent(-32768, -32768, 4, 4);
if (currprefs.input_mouse_untrap & MOUSEUNTRAP_MIDDLEBUTTON) {
activationtoggle(mon->monitor_id, true);
} else {
if (log_winmouse)
write_log (_T("WM_MOUSEMOVE MON=%d NUM=%d ACT=%d FOCUS=%d CLIP=%d CAP=%d FS=%d %dx%d %dx%d\n"),
mon->monitor_id, wm, mouseactive, focus, mon_cursorclipped, recapture, isfullscreen (), mx, my, mon->mouseposx, mon->mouseposy);
+
+ if (rp_mouseevent(mx, my, -1, -1))
+ return 0;
+
mx -= mon->mouseposx;
my -= mon->mouseposy;