浏览代码

* updated ptc and ptcgraph to the latest trunk (future 0.99.15 release) from sourceforge

git-svn-id: trunk@36507 -
nickysn 8 年之前
父节点
当前提交
f2587b6061
共有 49 个文件被更改,包括 7424 次插入1699 次删除
  1. 4 1
      .gitattributes
  2. 226 8
      packages/graph/src/ptcgraph/ptcgraph.pp
  3. 88 0
      packages/ptc/docs/CHANGES.txt
  4. 7 4
      packages/ptc/docs/INSTALL.txt
  5. 1 1
      packages/ptc/docs/README.txt
  6. 135 3
      packages/ptc/examples/keyboard3.pp
  7. 0 1
      packages/ptc/fpmake.pp
  8. 4 1
      packages/ptc/src/core/baseconsoled.inc
  9. 10 1
      packages/ptc/src/core/baseconsolei.inc
  10. 8 1
      packages/ptc/src/core/consolei.inc
  11. 1 1
      packages/ptc/src/core/errori.inc
  12. 7 2
      packages/ptc/src/core/keyeventd.inc
  13. 32 6
      packages/ptc/src/core/mouseeventd.inc
  14. 0 1299
      packages/ptc/src/dos/base/go32fix.pp
  15. 1 1
      packages/ptc/src/dos/timeunit/timeunit.pp
  16. 5 2
      packages/ptc/src/ptc.pp
  17. 240 0
      packages/ptc/src/ptclaz.lpi
  18. 6 0
      packages/ptc/src/ptclaz.lpr
  19. 6 0
      packages/ptc/src/ptcpas.cfg
  20. 13 4
      packages/ptc/src/win32/base/win32hook.inc
  21. 90 43
      packages/ptc/src/win32/base/win32kbd.inc
  22. 1 6
      packages/ptc/src/win32/base/win32kbdd.inc
  23. 2 1
      packages/ptc/src/win32/base/win32moused.inc
  24. 85 13
      packages/ptc/src/win32/base/win32mousei.inc
  25. 160 52
      packages/ptc/src/win32/base/win32window.inc
  26. 3 1
      packages/ptc/src/win32/base/win32windowd.inc
  27. 1 1
      packages/ptc/src/win32/directx/p_ddraw.pp
  28. 4829 0
      packages/ptc/src/win32/directx/p_dinput.pp
  29. 2 1
      packages/ptc/src/win32/directx/win32directxconsoled.inc
  30. 8 2
      packages/ptc/src/win32/directx/win32directxconsolei.inc
  31. 3 3
      packages/ptc/src/win32/directx/win32directxdisplay.inc
  32. 12 12
      packages/ptc/src/win32/directx/win32directxhook.inc
  33. 5 3
      packages/ptc/src/win32/gdi/win32gdiconsoled.inc
  34. 9 3
      packages/ptc/src/win32/gdi/win32gdiconsolei.inc
  35. 2 2
      packages/ptc/src/win32/gdi/win32openglwindowd.inc
  36. 2 2
      packages/ptc/src/win32/gdi/win32openglwindowi.inc
  37. 4 1
      packages/ptc/src/x11/x11consoled.inc
  38. 51 2
      packages/ptc/src/x11/x11consolei.inc
  39. 2 1
      packages/ptc/src/x11/x11dga1displayd.inc
  40. 7 1
      packages/ptc/src/x11/x11dga1displayi.inc
  41. 2 1
      packages/ptc/src/x11/x11dga2displayd.inc
  42. 7 1
      packages/ptc/src/x11/x11dga2displayi.inc
  43. 11 1
      packages/ptc/src/x11/x11displayd.inc
  44. 56 6
      packages/ptc/src/x11/x11displayi.inc
  45. 1 0
      packages/ptc/src/x11/x11extensions.inc
  46. 734 197
      packages/ptc/src/x11/x11unikey.inc
  47. 11 1
      packages/ptc/src/x11/x11windowdisplayd.inc
  48. 408 6
      packages/ptc/src/x11/x11windowdisplayi.inc
  49. 122 0
      packages/ptc/tests/event.pp

+ 4 - 1
.gitattributes

@@ -6923,7 +6923,6 @@ packages/ptc/src/core/surfaced.inc svneol=native#text/plain
 packages/ptc/src/core/surfacei.inc svneol=native#text/plain
 packages/ptc/src/core/timerd.inc svneol=native#text/plain
 packages/ptc/src/core/timeri.inc svneol=native#text/plain
-packages/ptc/src/dos/base/go32fix.pp svneol=native#text/plain
 packages/ptc/src/dos/base/kbd.inc svneol=native#text/plain
 packages/ptc/src/dos/base/kbdd.inc svneol=native#text/plain
 packages/ptc/src/dos/base/mouse33h.pp svneol=native#text/plain
@@ -6944,6 +6943,8 @@ packages/ptc/src/dos/vga/vga.pp svneol=native#text/plain
 packages/ptc/src/dos/vga/vgaconsoled.inc svneol=native#text/plain
 packages/ptc/src/dos/vga/vgaconsolei.inc svneol=native#text/plain
 packages/ptc/src/ptc.pp svneol=native#text/plain
+packages/ptc/src/ptclaz.lpi svneol=native#text/plain
+packages/ptc/src/ptclaz.lpr svneol=native#text/plain
 packages/ptc/src/ptcpas.cfg svneol=native#text/plain
 packages/ptc/src/ptcwrapper/ptceventqueue.pp svneol=native#text/plain
 packages/ptc/src/ptcwrapper/ptcwrapper.pp svneol=native#text/plain
@@ -6969,6 +6970,7 @@ packages/ptc/src/win32/base/win32window.inc svneol=native#text/plain
 packages/ptc/src/win32/base/win32windowd.inc svneol=native#text/plain
 packages/ptc/src/win32/base/windows.ico -text
 packages/ptc/src/win32/directx/p_ddraw.pp svneol=native#text/plain
+packages/ptc/src/win32/directx/p_dinput.pp svneol=native#text/plain
 packages/ptc/src/win32/directx/win32directxcheck.inc svneol=native#text/plain
 packages/ptc/src/win32/directx/win32directxconsoled.inc svneol=native#text/plain
 packages/ptc/src/win32/directx/win32directxconsolei.inc svneol=native#text/plain
@@ -7028,6 +7030,7 @@ packages/ptc/src/x11/x11windowdisplayd.inc svneol=native#text/plain
 packages/ptc/src/x11/x11windowdisplayi.inc svneol=native#text/plain
 packages/ptc/tests/convtest.pp svneol=native#text/plain
 packages/ptc/tests/endian.inc svneol=native#text/plain
+packages/ptc/tests/event.pp svneol=native#text/plain
 packages/ptc/tests/view.pp svneol=native#text/plain
 packages/pthreads/Makefile svneol=native#text/plain
 packages/pthreads/Makefile.fpc svneol=native#text/plain

+ 226 - 8
packages/graph/src/ptcgraph/ptcgraph.pp

@@ -120,6 +120,7 @@ const
   FullscreenGraph: Boolean = False;
 
 var
+  WindowTitle: AnsiString;
   PTCWrapperObject: TPTCWrapperThread;
 
 {******************************************************************************}
@@ -128,6 +129,8 @@ var
 
 const
   InternalDriverName = 'PTCPas';
+  FirstNonStandardModeNumber = $200;
+  NonStandardModeNumberMaxLimit = $7FFF;
 
 var
   Has320x200: Boolean;
@@ -617,7 +620,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 16 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat8, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -642,7 +645,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 256 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat8, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -657,7 +660,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 4 colours, palette ' + strf(CGAPalette));
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat8, 1);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, 1);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -672,7 +675,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 2 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat8, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -687,7 +690,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 2 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat8, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat8, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -702,7 +705,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 32768 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat15, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat15, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -715,7 +718,7 @@ begin
   LogLn('Initializing mode ' + strf(XResolution) + ', ' + strf(YResolution) + ' 65536 colours');
 {$ENDIF logging}
   { open the console }
-  ptc_InternalOpen(ParamStr(0), XResolution, YResolution, PTCFormat16, Pages);
+  ptc_InternalOpen(WindowTitle, XResolution, YResolution, PTCFormat16, Pages);
   PTCWidth := XResolution;
   PTCHeight := YResolution;
   CurrentActivePage := 0;
@@ -869,6 +872,26 @@ begin
   ptc_InitMode64k(1280, 1024, 2);
 end;
 
+procedure ptc_InitNonStandard16;
+begin
+  ptc_InitMode16(MaxX + 1, MaxY + 1, 2);
+end;
+
+procedure ptc_InitNonStandard256;
+begin
+  ptc_InitMode256(MaxX + 1, MaxY + 1, 2);
+end;
+
+procedure ptc_InitNonStandard32k;
+begin
+  ptc_InitMode32k(MaxX + 1, MaxY + 1, 2);
+end;
+
+procedure ptc_InitNonStandard64k;
+begin
+  ptc_InitMode64k(MaxX + 1, MaxY + 1, 2);
+end;
+
 procedure ptc_SetVisualPage(page: word);
 begin
   if page > HardwarePages then
@@ -1409,8 +1432,64 @@ end;
       ContainsAtLeast := False;
     end;
 
+    function IsNonStandardResolution(AWidth, AHeight: Integer): Boolean;
+    begin
+      IsNonStandardResolution :=
+            not ((AWidth =  320) and (AHeight =  200))
+        and not ((AWidth =  640) and (AHeight =  200))
+        and not ((AWidth =  640) and (AHeight =  350))
+        and not ((AWidth =  640) and (AHeight =  400))
+        and not ((AWidth =  640) and (AHeight =  480))
+        and not ((AWidth =  720) and (AHeight =  348))
+        and not ((AWidth =  800) and (AHeight =  600))
+        and not ((AWidth = 1024) and (AHeight =  768))
+        and not ((AWidth = 1280) and (AHeight = 1024));
+    end;
+
+    function CompareModes(AMode1, AMode2: IPTCMode): Boolean;
+    begin
+      if AMode1.Width <> AMode2.Width then
+        CompareModes := AMode1.Width < AMode2.Width
+      else if AMode1.Height <> AMode2.Height then
+        CompareModes := AMode1.Height < AMode2.Height
+      else if AMode1.Format.Bits <> AMode2.Format.Bits then
+        CompareModes := AMode1.Format.Bits < AMode2.Format.Bits
+      else
+        CompareModes := PtrUInt(AMode1) < PtrUInt(AMode2);
+    end;
+
+    procedure SortModes(l,r: longint);
+      var
+         i,j: longint;
+         x,y: IPTCMode;
+      begin
+         i:=l;
+         j:=r;
+         x:=PTCModeList[(l+r) div 2];
+         repeat
+           while CompareModes(PTCModeList[i], x) do
+            inc(i);
+           while CompareModes(x, PTCModeList[j]) do
+            dec(j);
+           if not(i>j) then
+             begin
+                y:=PTCModeList[i];
+                PTCModeList[i]:=PTCModeList[j];
+                PTCModeList[j]:=y;
+                inc(i);
+                j:=j-1;
+             end;
+         until i>j;
+         if l<j then
+           SortModes(l,j);
+         if i<r then
+           SortModes(i,r);
+      end;
+
    var
     graphmode:Tmodeinfo;
+    I: Integer;
+    NextNonStandardModeNumber: SmallInt;
    begin
      QueryAdapterInfo := ModeList;
      { If the mode listing already exists... }
@@ -1419,7 +1498,8 @@ end;
      if assigned(ModeList) then
        exit;
 
-     PTCModeList := PTCWrapperObject.Modes;
+     PTCModeList := Copy(PTCWrapperObject.Modes);
+     SortModes(Low(PTCModeList), High(PTCModeList));
 
      Has320x200 := ContainsExactResolution(320, 200);
      Has320x240 := ContainsExactResolution(320, 240);
@@ -2567,9 +2647,147 @@ end;
        end;
        AddMode(graphmode);
      end;
+
+     { finally, add all the non-standard (i.e. not VESA or classic PC) modes }
+     NextNonStandardModeNumber := FirstNonStandardModeNumber;
+     for I := Low(PTCModeList) to High(PTCModeList) do
+       with PTCModeList[I] do
+         if IsNonStandardResolution(Width, Height) and
+            ((I = Low(PTCModeList)) or ((Width <> PTCModeList[I-1].Width) or (Height <> PTCModeList[I-1].Height))) then
+         begin
+           InitMode(graphmode);
+           with graphmode do
+           begin
+             ModeNumber := NextNonStandardModeNumber;
+             DriverNumber := VESA;
+             HardwarePages := 1;
+             WriteStr(ModeName, Width, ' x ', Height, ' VESA');
+             MaxColor := 16;
+             DirectColor := FALSE;
+             PaletteSize := MaxColor;
+             MaxX := Width - 1;
+             MaxY := Height - 1;
+             InitMode       := @ptc_InitNonStandard16;
+             DirectPutPixel := @ptc_DirectPixelProc_8bpp;
+             PutPixel       := @ptc_PutPixelProc_8bpp;
+             GetPixel       := @ptc_GetPixelProc_8bpp;
+             SetRGBPalette  := @ptc_SetRGBPaletteProc;
+             GetRGBPalette  := @ptc_GetRGBPaletteProc;
+
+             HLine          := @ptc_HLineProc_8bpp;
+             VLine          := @ptc_VLineProc_8bpp;
+
+             SetVisualPage  := @ptc_SetVisualPage;
+             SetActivePage  := @ptc_SetActivePage;
+
+             XAspect := 10000;
+             YAspect := 10000;
+           end;
+           AddMode(graphmode);
+           Inc(NextNonStandardModeNumber);
+           if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then
+             break;
+
+           InitMode(graphmode);
+           with graphmode do
+           begin
+             ModeNumber := NextNonStandardModeNumber;
+             DriverNumber := VESA;
+             HardwarePages := 1;
+             WriteStr(ModeName, Width, ' x ', Height, ' VESA');
+             MaxColor := 256;
+             DirectColor := FALSE;
+             PaletteSize := MaxColor;
+             MaxX := Width - 1;
+             MaxY := Height - 1;
+             InitMode       := @ptc_InitNonStandard256;
+             DirectPutPixel := @ptc_DirectPixelProc_8bpp;
+             PutPixel       := @ptc_PutPixelProc_8bpp;
+             GetPixel       := @ptc_GetPixelProc_8bpp;
+             SetRGBPalette  := @ptc_SetRGBPaletteProc;
+             GetRGBPalette  := @ptc_GetRGBPaletteProc;
+             //SetAllPalette  := @ptc_SetRGBAllPaletteProc;
+
+             HLine          := @ptc_HLineProc_8bpp;
+             VLine          := @ptc_VLineProc_8bpp;
+
+             SetVisualPage  := @ptc_SetVisualPage;
+             SetActivePage  := @ptc_SetActivePage;
+
+             XAspect := 10000;
+             YAspect := 10000;
+           end;
+           AddMode(graphmode);
+           Inc(NextNonStandardModeNumber);
+           if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then
+             break;
+
+           InitMode(graphmode);
+           with graphmode do
+           begin
+             ModeNumber := NextNonStandardModeNumber;
+             DriverNumber := VESA;
+             HardwarePages := 1;
+             WriteStr(ModeName, Width, ' x ', Height, ' VESA');
+             MaxColor := 32768;
+             DirectColor := TRUE;
+             PaletteSize := MaxColor;
+             MaxX := Width - 1;
+             MaxY := Height - 1;
+             InitMode       := @ptc_InitNonStandard32k;
+             DirectPutPixel := @ptc_DirectPixelProc_16bpp;
+             PutPixel       := @ptc_PutPixelProc_16bpp;
+             GetPixel       := @ptc_GetPixelProc_16bpp;
+             SetRGBPalette  := @ptc_SetRGBPaletteProc;
+             GetRGBPalette  := @ptc_GetRGBPaletteProc;
+             HLine          := @ptc_HLineProc_16bpp;
+             VLine          := @ptc_VLineProc_16bpp;
+             SetVisualPage  := @ptc_SetVisualPage;
+             SetActivePage  := @ptc_SetActivePage;
+
+             XAspect := 10000;
+             YAspect := 10000;
+           end;
+           AddMode(graphmode);
+           Inc(NextNonStandardModeNumber);
+           if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then
+             break;
+
+           InitMode(graphmode);
+           with graphmode do
+           begin
+             ModeNumber := NextNonStandardModeNumber;
+             DriverNumber := VESA;
+             HardwarePages := 1;
+             WriteStr(ModeName, Width, ' x ', Height, ' VESA');
+             MaxColor := 65536;
+             DirectColor := TRUE;
+             PaletteSize := MaxColor;
+             MaxX := Width - 1;
+             MaxY := Height - 1;
+             InitMode       := @ptc_InitNonStandard64k;
+             DirectPutPixel := @ptc_DirectPixelProc_16bpp;
+             PutPixel       := @ptc_PutPixelProc_16bpp;
+             GetPixel       := @ptc_GetPixelProc_16bpp;
+             SetRGBPalette  := @ptc_SetRGBPaletteProc;
+             GetRGBPalette  := @ptc_GetRGBPaletteProc;
+             HLine          := @ptc_HLineProc_16bpp;
+             VLine          := @ptc_VLineProc_16bpp;
+             SetVisualPage  := @ptc_SetVisualPage;
+             SetActivePage  := @ptc_SetActivePage;
+
+             XAspect := 10000;
+             YAspect := 10000;
+           end;
+           AddMode(graphmode);
+           Inc(NextNonStandardModeNumber);
+           if NextNonStandardModeNumber > NonStandardModeNumberMaxLimit then
+             break;
+         end;
   end;
 
 initialization
+  WindowTitle := ParamStr(0);
   PTCFormat8 := TPTCFormatFactory.CreateNew(8);
   PTCFormat15 := TPTCFormatFactory.CreateNew(16, $7C00, $03E0, $001F);
   PTCFormat16 := TPTCFormatFactory.CreateNew(16, $F800, $07E0, $001F);

+ 88 - 0
packages/ptc/docs/CHANGES.txt

@@ -1,3 +1,91 @@
+0.99.15
+ - dead key support under Windows and X11 (via XIM)
+ - more character scripts (Latin 2, Latin 3, Latin 4, Latin 9, Katakana,
+   Arabic, Greek with diacritics, Technical, Special, Publishing, APL, Hebrew,
+   Thai, Currency signs - Korean Won sign and Euro sign) are now recognized and
+   converted to Unicode in the X11 console. Previously only Latin 1, Greek
+   without diacritics and Cyrillic were supported, but even they didn't work in
+   recent ptcpas versions, due to regressions, which are now fixed as well.
+ - use an alternative method (via GetKeyState) for obtaining the Alt, Shift and
+   Control key modifier status under Windows; This eliminates a problem, where
+   the alt key appears "stuck", after alt-tabbing away from the application,
+   then focusing back to it with a mouse click.
+ - new key modifiers added for distinguishing between left and right shift,
+   control and alt, the status of num lock, caps lock and scroll lock and for
+   distinguishing numpad keys and dead keys. All of them are implemented as
+   elements in the ModifierKeys set, which was added to IPTCKeyEvent. They can
+   be checked, for example, with:
+     if pmkNumLockActive in key_event.ModifierKeys then
+       ...
+   The following modifiers are available:
+     pmkAlt, pmkShift, pmkControl, pmkLeftAlt, pmkRightAlt, pmkLeftShift,
+     pmkRightShift, pmkLeftControl, pmkRightControl, pmkNumLockActive,
+     pmkNumLockPressed, pmkCapsLockActive, pmkCapsLockPressed,
+     pmkScrollLockActive, pmkScrollLockPressed, pmkNumPadKey, pmkDeadKey
+ - there is now a MoveMouseTo method, added to the console. It can be used to
+   warp the mouse cursor to a different location.
+ - added support for a relative mouse mode. It supports continuous mouse
+   motion, not limited within the boundaries of the current window. It is
+   usually used with an invisible cursor. It is activated with the
+   'relative mouse on' console option, and turned off with the option
+   'relative mouse off'.
+ - the number of mouse buttons supported has been increased to 31. There is now
+   support for a horizontal and a vertical mouse wheel, which are treated as
+   buttons. Overall, this is the default button arrangement:
+     PTCMouseButton1  - left mouse button
+     PTCMouseButton2  - right mouse button
+     PTCMouseButton3  - middle mouse button
+     PTCMouseButton4  - mouse wheel rotated forward (scroll up)
+     PTCMouseButton5  - mouse wheel rotated backward (scroll down)
+     PTCMouseButton6  - mouse horizontal scroll wheel rotated left
+     PTCMouseButton7  - mouse horizontal scroll wheel rotated right
+     PTCMouseButton8  - "back" button ("X button 1")
+     PTCMouseButton9  - "forward" button ("X button 2")
+   The remaining mouse buttons are hardware specific and will vary, depending
+   on the actual mouse (provided it has that many buttons at all).
+ - ptcgraph now has a global string variable WindowTitle, which allows you to
+   set the window title, before calling InitGraph
+ - ptcgraph was extended to also support resolutions, different than the ones,
+   defined by VESA. This means that you can now use ptcgraph with resolutions,
+   higher than 1280x1024 and widescreen (e.g. 16:9 or 16:10) aspect ratios, as
+   long as they are supported by the display. For this, you need to call
+   QueryAdapterInfo and walk through the linked list of modes, to choose a
+   mode, then pass its DriverNumber and ModeNumber to InitGraph. Here's an
+   example:
+
+uses
+  ptcgraph, ptccrt;
+var
+  m: PModeInfo;
+  gd, gm: Integer;
+begin
+  Writeln('List of all modes:');
+  m := QueryAdapterInfo;
+  while m <> nil do
+  begin
+    Writeln(m^.MaxX+1, ' x ', m^.MaxY+1, ' x ', m^.MaxColor);
+    m := m^.next;
+  end;
+
+  Writeln('Now let''s find 1920x1080 with 16-bit colour...');
+  m := QueryAdapterInfo;
+  while m <> nil do
+  begin
+    if (m^.MaxX = (1920-1)) and (m^.MaxY = (1080-1)) and (m^.MaxColor = 65536) then
+    begin
+      InitGraph(m^.DriverNumber, m^.ModeNumber, '');
+      SetColor($FFFF);
+      OutTextXY(0, 0, 'Hurrah! Full HD 1920x1080 mode is available!');
+      ReadKey;
+      CloseGraph;
+      Halt;
+    end;
+    m := m^.next;
+  end;
+
+  Writeln('Mode not found in list!');
+end.
+
 0.99.14.1
  - fixed X11 middle and right mouse button mapping. Previously, the right mouse
    button and the middle mouse button were swapped, compared to Windows and DOS

+ 7 - 4
packages/ptc/docs/INSTALL.txt

@@ -1,13 +1,16 @@
-The supported platforms are Linux, FreeBSD, Windows, Windows Mobile and DOS.
+The supported platforms are Linux, FreeBSD, Windows, Windows Mobile and 32-bit
+DOS (go32v2).
 
 Generally you need the latest stable version of the Free Pascal Compiler, which
-currently means version 2.6.2.
+currently means version 3.0.4. Note that Windows 95/98/ME and NT 4.0 are still
+supported, when this library is compiled with FPC 2.6.4. However, using
+FPC 2.6.4 isn't guaranteed to work for any other platforms, besides Windows.
 
  - Compiling the library:
 Before starting make sure the FPCDIR environment variable is set correctly.
-For example: (windows, fpc version 2.6.2, default install dir)
+For example: (windows, fpc version 3.0.4, default install dir)
 
-  set FPCDIR=c:\fpc\2.6.2
+  set FPCDIR=c:\fpc\3.0.4
 
 To compile the library type:
 

+ 1 - 1
packages/ptc/docs/README.txt

@@ -1,4 +1,4 @@
-PTCPas 0.99.14.1
+PTCPas 0.99.15
 Nikolay Nikolov ([email protected])
 
 PTCPas is a free, portable framebuffer library, written in Free Pascal. It is

+ 135 - 3
packages/ptc/examples/keyboard3.pp

@@ -10,11 +10,143 @@ program KeyboardExample3;
 uses
   ptc;
 
+function KeyCode2String(ACode: Integer): string;
+begin
+  case ACode of
+    PTCKEY_UNDEFINED    : Result := 'PTCKEY_UNDEFINED';
+    PTCKEY_CANCEL       : Result := 'PTCKEY_CANCEL';
+    PTCKEY_BACKSPACE    : Result := 'PTCKEY_BACKSPACE';
+    PTCKEY_TAB          : Result := 'PTCKEY_TAB';
+    PTCKEY_ENTER        : Result := 'PTCKEY_ENTER';
+    PTCKEY_CLEAR        : Result := 'PTCKEY_CLEAR';
+    PTCKEY_SHIFT        : Result := 'PTCKEY_SHIFT';
+    PTCKEY_CONTROL      : Result := 'PTCKEY_CONTROL';
+    PTCKEY_ALT          : Result := 'PTCKEY_ALT';
+    PTCKEY_PAUSE        : Result := 'PTCKEY_PAUSE';
+    PTCKEY_CAPSLOCK     : Result := 'PTCKEY_CAPSLOCK';
+    PTCKEY_KANA         : Result := 'PTCKEY_KANA';
+    PTCKEY_FINAL        : Result := 'PTCKEY_FINAL';
+    PTCKEY_KANJI        : Result := 'PTCKEY_KANJI';
+    PTCKEY_ESCAPE       : Result := 'PTCKEY_ESCAPE';
+    PTCKEY_CONVERT      : Result := 'PTCKEY_CONVERT';
+    PTCKEY_NONCONVERT   : Result := 'PTCKEY_NONCONVERT';
+    PTCKEY_ACCEPT       : Result := 'PTCKEY_ACCEPT';
+    PTCKEY_MODECHANGE   : Result := 'PTCKEY_MODECHANGE';
+    PTCKEY_SPACE        : Result := 'PTCKEY_SPACE';
+    PTCKEY_PAGEUP       : Result := 'PTCKEY_PAGEUP';
+    PTCKEY_PAGEDOWN     : Result := 'PTCKEY_PAGEDOWN';
+    PTCKEY_END          : Result := 'PTCKEY_END';
+    PTCKEY_HOME         : Result := 'PTCKEY_HOME';
+    PTCKEY_LEFT         : Result := 'PTCKEY_LEFT';
+    PTCKEY_UP           : Result := 'PTCKEY_UP';
+    PTCKEY_RIGHT        : Result := 'PTCKEY_RIGHT';
+    PTCKEY_DOWN         : Result := 'PTCKEY_DOWN';
+    PTCKEY_COMMA        : Result := 'PTCKEY_COMMA';
+    PTCKEY_PERIOD       : Result := 'PTCKEY_PERIOD';
+    PTCKEY_SLASH        : Result := 'PTCKEY_SLASH';
+    PTCKEY_ZERO         : Result := 'PTCKEY_ZERO';
+    PTCKEY_ONE          : Result := 'PTCKEY_ONE';
+    PTCKEY_TWO          : Result := 'PTCKEY_TWO';
+    PTCKEY_THREE        : Result := 'PTCKEY_THREE';
+    PTCKEY_FOUR         : Result := 'PTCKEY_FOUR';
+    PTCKEY_FIVE         : Result := 'PTCKEY_FIVE';
+    PTCKEY_SIX          : Result := 'PTCKEY_SIX';
+    PTCKEY_SEVEN        : Result := 'PTCKEY_SEVEN';
+    PTCKEY_EIGHT        : Result := 'PTCKEY_EIGHT';
+    PTCKEY_NINE         : Result := 'PTCKEY_NINE';
+    PTCKEY_SEMICOLON    : Result := 'PTCKEY_SEMICOLON';
+    PTCKEY_EQUALS       : Result := 'PTCKEY_EQUALS';
+    PTCKEY_A            : Result := 'PTCKEY_A';
+    PTCKEY_B            : Result := 'PTCKEY_B';
+    PTCKEY_C            : Result := 'PTCKEY_C';
+    PTCKEY_D            : Result := 'PTCKEY_D';
+    PTCKEY_E            : Result := 'PTCKEY_E';
+    PTCKEY_F            : Result := 'PTCKEY_F';
+    PTCKEY_G            : Result := 'PTCKEY_G';
+    PTCKEY_H            : Result := 'PTCKEY_H';
+    PTCKEY_I            : Result := 'PTCKEY_I';
+    PTCKEY_J            : Result := 'PTCKEY_J';
+    PTCKEY_K            : Result := 'PTCKEY_K';
+    PTCKEY_L            : Result := 'PTCKEY_L';
+    PTCKEY_M            : Result := 'PTCKEY_M';
+    PTCKEY_N            : Result := 'PTCKEY_N';
+    PTCKEY_O            : Result := 'PTCKEY_O';
+    PTCKEY_P            : Result := 'PTCKEY_P';
+    PTCKEY_Q            : Result := 'PTCKEY_Q';
+    PTCKEY_R            : Result := 'PTCKEY_R';
+    PTCKEY_S            : Result := 'PTCKEY_S';
+    PTCKEY_T            : Result := 'PTCKEY_T';
+    PTCKEY_U            : Result := 'PTCKEY_U';
+    PTCKEY_V            : Result := 'PTCKEY_V';
+    PTCKEY_W            : Result := 'PTCKEY_W';
+    PTCKEY_X            : Result := 'PTCKEY_X';
+    PTCKEY_Y            : Result := 'PTCKEY_Y';
+    PTCKEY_Z            : Result := 'PTCKEY_Z';
+    PTCKEY_OPENBRACKET  : Result := 'PTCKEY_OPENBRACKET';
+    PTCKEY_BACKSLASH    : Result := 'PTCKEY_BACKSLASH';
+    PTCKEY_CLOSEBRACKET : Result := 'PTCKEY_CLOSEBRACKET';
+    PTCKEY_NUMPAD0      : Result := 'PTCKEY_NUMPAD0';
+    PTCKEY_NUMPAD1      : Result := 'PTCKEY_NUMPAD1';
+    PTCKEY_NUMPAD2      : Result := 'PTCKEY_NUMPAD2';
+    PTCKEY_NUMPAD3      : Result := 'PTCKEY_NUMPAD3';
+    PTCKEY_NUMPAD4      : Result := 'PTCKEY_NUMPAD4';
+    PTCKEY_NUMPAD5      : Result := 'PTCKEY_NUMPAD5';
+    PTCKEY_NUMPAD6      : Result := 'PTCKEY_NUMPAD6';
+    PTCKEY_NUMPAD7      : Result := 'PTCKEY_NUMPAD7';
+    PTCKEY_NUMPAD8      : Result := 'PTCKEY_NUMPAD8';
+    PTCKEY_NUMPAD9      : Result := 'PTCKEY_NUMPAD9';
+    PTCKEY_MULTIPLY     : Result := 'PTCKEY_MULTIPLY';
+    PTCKEY_ADD          : Result := 'PTCKEY_ADD';
+    PTCKEY_SEPARATOR    : Result := 'PTCKEY_SEPARATOR';
+    PTCKEY_SUBTRACT     : Result := 'PTCKEY_SUBTRACT';
+    PTCKEY_DECIMAL      : Result := 'PTCKEY_DECIMAL';
+    PTCKEY_DIVIDE       : Result := 'PTCKEY_DIVIDE';
+    PTCKEY_F1           : Result := 'PTCKEY_F1';
+    PTCKEY_F2           : Result := 'PTCKEY_F2';
+    PTCKEY_F3           : Result := 'PTCKEY_F3';
+    PTCKEY_F4           : Result := 'PTCKEY_F4';
+    PTCKEY_F5           : Result := 'PTCKEY_F5';
+    PTCKEY_F6           : Result := 'PTCKEY_F6';
+    PTCKEY_F7           : Result := 'PTCKEY_F7';
+    PTCKEY_F8           : Result := 'PTCKEY_F8';
+    PTCKEY_F9           : Result := 'PTCKEY_F9';
+    PTCKEY_F10          : Result := 'PTCKEY_F10';
+    PTCKEY_F11          : Result := 'PTCKEY_F11';
+    PTCKEY_F12          : Result := 'PTCKEY_F12';
+    PTCKEY_DELETE       : Result := 'PTCKEY_DELETE';
+    PTCKEY_NUMLOCK      : Result := 'PTCKEY_NUMLOCK';
+    PTCKEY_SCROLLLOCK   : Result := 'PTCKEY_SCROLLLOCK';
+    PTCKEY_PRINTSCREEN  : Result := 'PTCKEY_PRINTSCREEN';
+    PTCKEY_INSERT       : Result := 'PTCKEY_INSERT';
+    PTCKEY_HELP         : Result := 'PTCKEY_HELP';
+    PTCKEY_META         : Result := 'PTCKEY_META';
+    PTCKEY_MINUS        : Result := 'PTCKEY_MINUS';
+    PTCKEY_BACKQUOTE    : Result := 'PTCKEY_BACKQUOTE';
+    PTCKEY_QUOTE        : Result := 'PTCKEY_QUOTE';
+    else
+      Result := '';
+  end;
+end;
+
 procedure DumpKey(AKey: IPTCKeyEvent);
+var
+  mk: TPTCModifierKey;
+  first: Boolean;
 begin
-  Writeln('Code=', AKey.Code:3, ', Unicode=$', HexStr(AKey.Unicode, 4),
-    ', Press=', AKey.Press:5, ', Shift=', AKey.Shift:5, ', Alt=', AKey.Alt:5,
-    ', Control=', AKey.Control:5);
+  Write('Code=', AKey.Code:3, ' (', KeyCode2String(AKey.Code):19,
+    '), Unicode=$', HexStr(AKey.Unicode, 4), ', Press=', AKey.Press:5,
+    ', Shift=', AKey.Shift:5, ', Alt=', AKey.Alt:5, ', Control=',
+    AKey.Control:5, ', ModifierKeys=[');
+  first := True;
+  for mk in TPTCModifierKey do
+    if mk in AKey.ModifierKeys then
+    begin
+      if not first then
+        Write(',');
+      first := False;
+      Write(mk);
+    end;
+  Writeln(']');
 end;
 
 var

+ 0 - 1
packages/ptc/fpmake.pp

@@ -186,7 +186,6 @@ begin
       AddInclude('vgaconsoled.inc', [go32v2]);
       AddInclude('vgaconsolei.inc', [go32v2]);
       AddUnit('p_gx',[Wince]);
-      AddUnit('go32fix',[go32v2]);
       AddUnit('mouse33h',[go32v2]);
       AddUnit('textfx2',[go32v2]);
       AddUnit('cga',[go32v2]);

+ 4 - 1
packages/ptc/src/core/baseconsoled.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -70,6 +70,9 @@ type
     function GetKeyReleaseEnabled: Boolean;
     property KeyReleaseEnabled: Boolean read GetKeyReleaseEnabled write SetKeyReleaseEnabled;
 
+    { mouse handling }
+    function MoveMouseTo(X, Y: Integer): Boolean;
+
     property Pages: Integer read GetPages;
     property Name: string read GetName;
     property Title: string read GetTitle;

+ 10 - 1
packages/ptc/src/core/baseconsolei.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2016, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -117,6 +117,9 @@ type
     procedure ReadKey;
     property KeyReleaseEnabled: Boolean read GetKeyReleaseEnabled write SetKeyReleaseEnabled;
 
+    { mouse handling }
+    function MoveMouseTo(X, Y: Integer): Boolean; virtual;
+
     property Pages: Integer read GetPages;
     property Name: string read GetName;
     property Title: string read GetTitle;
@@ -212,6 +215,12 @@ begin
   Result := FReleaseEnabled;
 end;
 
+{ must be overriden in consoles, that support moving the mouse cursor }
+function TPTCBaseConsole.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  Result := False;
+end;
+
 function TPTCOpenGLLessConsole.GetOpenGL_Enabled: Boolean;
 begin
   Result := False;

+ 8 - 1
packages/ptc/src/core/consolei.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2015  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2015, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -114,6 +114,7 @@ type
     function GetInformation: string; override;
     function NextEvent(out AEvent: IPTCEvent; AWait: Boolean; const AEventMask: TPTCEventMask): Boolean; override;
     function PeekEvent(AWait: Boolean; const AEventMask: TPTCEventMask): IPTCEvent; override;
+    function MoveMouseTo(X, Y: Integer): Boolean; override;
     procedure OpenGL_SwapBuffers; override;
     procedure OpenGL_SetSwapInterval(AInterval: Integer); override;
     function OpenGL_GetSwapInterval: Integer; override;
@@ -839,6 +840,12 @@ begin
     raise TPTCError.Create('console is not open (core)');
 end;
 
+function TPTCConsole.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  Check;
+  Result := FConsole.MoveMouseTo(X, Y);
+end;
+
 procedure TPTCConsole.PassOpenGLOptionsToInnerConsole;
 begin
   FConsole.OpenGL_Enabled := FUseOpenGL;

+ 1 - 1
packages/ptc/src/core/errori.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2007, 2009, 2010, 2012  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2007, 2009, 2010, 2012, 2013  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or

+ 7 - 2
packages/ptc/src/core/keyeventd.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2011, 2015  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2011, 2015, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -31,7 +31,12 @@
 }
 
 type
-  TPTCModifierKey = (pmkAlt, pmkShift, pmkControl);
+  TPTCModifierKey = (pmkAlt, pmkShift, pmkControl, pmkLeftAlt, pmkRightAlt,
+    pmkLeftShift, pmkRightShift, pmkLeftControl, pmkRightControl,
+    pmkNumLockActive, pmkNumLockPressed,
+    pmkCapsLockActive, pmkCapsLockPressed,
+    pmkScrollLockActive, pmkScrollLockPressed,
+    pmkNumPadKey,pmkDeadKey);
   TPTCModifierKeys = set of TPTCModifierKey;
   IPTCKeyEvent = interface(IPTCEvent)
     ['{9BD1CD41-1DF6-4392-99DC-885EADB6D85A}']

+ 32 - 6
packages/ptc/src/core/mouseeventd.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2007, 2009-2011  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2007, 2009-2011, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -34,11 +34,37 @@ type
 {todo  TPTCMouseCursor = (PTCMouseCursorDefault,
                      PTCMouseCursorAlwaysVisible,
                      PTCMouseCursorAlwaysInvisible);}
-  TPTCMouseButton = (PTCMouseButton1, { left mouse button }
-                     PTCMouseButton2, { right mouse button }
-                     PTCMouseButton3, { middle mouse button }
-                     PTCMouseButton4,
-                     PTCMouseButton5);
+  TPTCMouseButton = (PTCMouseButton1,  { left mouse button }
+                     PTCMouseButton2,  { right mouse button }
+                     PTCMouseButton3,  { middle mouse button }
+                     PTCMouseButton4,  { mouse wheel rotated forward (scroll up) }
+                     PTCMouseButton5,  { mouse wheel rotated backward (scroll down) }
+                     PTCMouseButton6,  { mouse horizontal scroll wheel rotated left }
+                     PTCMouseButton7,  { mouse horizontal scroll wheel rotated right }
+                     PTCMouseButton8,  { "back" button ("X button 1") }
+                     PTCMouseButton9,  { "forward" button ("X button 2") }
+                     PTCMouseButton10,
+                     PTCMouseButton11,
+                     PTCMouseButton12,
+                     PTCMouseButton13,
+                     PTCMouseButton14,
+                     PTCMouseButton15,
+                     PTCMouseButton16,
+                     PTCMouseButton17,
+                     PTCMouseButton18,
+                     PTCMouseButton19,
+                     PTCMouseButton20,
+                     PTCMouseButton21,
+                     PTCMouseButton22,
+                     PTCMouseButton23,
+                     PTCMouseButton24,
+                     PTCMouseButton25,
+                     PTCMouseButton26,
+                     PTCMouseButton27,
+                     PTCMouseButton28,
+                     PTCMouseButton29,
+                     PTCMouseButton30,
+                     PTCMouseButton31);
   TPTCMouseButtonState = set of TPTCMouseButton;
   IPTCMouseEvent = interface(IPTCEvent)
     ['{4D093608-6F27-4578-B41E-3492A4C7FEED}']

+ 0 - 1299
packages/ptc/src/dos/base/go32fix.pp

@@ -1,1299 +0,0 @@
-{
-    This file is part of the Free Pascal run time library.
-    and implements some stuff for protected mode programming
-    Copyright (c) 1999-2000 by the Free Pascal development team.
-
-    See the file COPYING.FPC, included in this distribution,
-    for details about the copyright.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- **********************************************************************}
-
-unit go32fix;
-
-{$S-,R-,I-,Q-} {no stack check, used by DPMIEXCP !! }
-
-interface
-
-    const
-    { contants for the run modes returned by get_run_mode }
-       rm_unknown = 0;
-       rm_raw     = 1;     { raw (without HIMEM) }
-       rm_xms     = 2;     { XMS (for example with HIMEM, without EMM386) }
-       rm_vcpi    = 3;     { VCPI (for example HIMEM and EMM386) }
-       rm_dpmi    = 4;     { DPMI (for example DOS box or 386Max) }
-
-    { flags }
-       carryflag     = $001;
-       parityflag    = $004;
-       auxcarryflag  = $010;
-       zeroflag      = $040;
-       signflag      = $080;
-       trapflag      = $100;
-       interruptflag = $200;
-       directionflag = $400;
-       overflowflag  = $800;
-
-    type
-       tmeminfo = record
-          available_memory,
-          available_pages,
-          available_lockable_pages,
-          linear_space,
-          unlocked_pages,
-          available_physical_pages,
-          total_physical_pages,
-          free_linear_space,
-          max_pages_in_paging_file,
-          reserved0,
-          reserved1,
-          reserved2: longint;
-       end;
-
-       tseginfo = record
-          offset: pointer;
-          segment: word;
-       end;
-
-       trealregs = record
-         case integer of
-          1: { 32-bit } (EDI, ESI, EBP, Res, EBX, EDX, ECX, EAX: longint;
-                         Flags, ES, DS, FS, GS, IP, CS, SP, SS: word);
-          2: { 16-bit } (DI, DI2, SI, SI2, BP, BP2, R1, R2: word;
-                         BX, BX2, DX, DX2, CX, CX2, AX, AX2: word);
-          3: { 8-bit }  (stuff: array[1..4] of longint;
-                         BL, BH, BL2, BH2, DL, DH, DL2, DH2,
-                         CL, CH, CL2, CH2, AL, AH, AL2, AH2: byte);
-          4: { Compat } (RealEDI, RealESI, RealEBP, RealRES,
-                         RealEBX, RealEDX, RealECX, RealEAX: longint;
-                         RealFlags,
-                         RealES, RealDS, RealFS, RealGS,
-                         RealIP, RealCS, RealSP, RealSS: word);
-       end;
-
-      registers = trealregs;
-
-      tdpmiversioninfo = record
-        major, minor: byte;
-	flags: word;
-	cpu: byte;
-	master_pic, slave_pic: byte;
-      end;
-
-    { this works only with real DPMI }
-    function allocate_ldt_descriptors(count: word): word;
-    function free_ldt_descriptor(d: word): boolean;
-    function segment_to_descriptor(seg: word): word;
-    function get_next_selector_increment_value: word;
-    function get_segment_base_address(d: word): longint;
-    function set_segment_base_address(d: word;s: dword): boolean;
-    function set_segment_limit(d: word;s: dword): boolean;
-    function set_descriptor_access_right(d: word;w: word): boolean;
-    function create_code_segment_alias_descriptor(seg: word): word;
-    function get_linear_addr(phys_addr: dword;size: longint): dword;
-    function free_linear_addr_mapping(linear_addr: dword): boolean;
-    function get_segment_limit(d: word): dword;
-    function get_descriptor_access_right(d: word): longint;
-    function get_page_size:longint;
-    function map_device_in_memory_block(handle,offset,pagecount,device:dword):boolean;
-    function get_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
-    function set_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
-    function realintr(intnr: word;var regs: trealregs): boolean;
-    function get_dpmi_version(var version: tdpmiversioninfo): boolean;
-
-    { is needed for functions which need a real mode buffer }
-    function global_dos_alloc(bytes: longint): longint;
-    function global_dos_free(selector: word): boolean;
-
-    var
-       { selector for the DOS memory (only usable if in DPMI mode) }
-       dosmemselector: word;
-       { result of dpmi call }
-       int31error: word;
-
-    { this procedure copies data where the source and destination }
-    { are specified by 48 bit pointers                            }
-    { Note: the procedure checks only for overlapping if          }
-    { source selector=destination selector                        }
-    procedure seg_move(sseg: word;source: longint;dseg: word;dest: longint;count: longint);
-
-    { fills a memory area specified by a 48 bit pointer with c }
-    procedure seg_fillchar(seg: word;ofs: longint;count: longint;c: char);
-    procedure seg_fillword(seg: word;ofs: longint;count: longint;w: word);
-
-    {************************************}
-    { this works with all PM interfaces: }
-    {************************************}
-
-    function get_meminfo(var meminfo: tmeminfo): boolean;
-    function get_pm_interrupt(vector: byte;var intaddr: tseginfo): boolean;
-    function set_pm_interrupt(vector: byte;const intaddr: tseginfo): boolean;
-    function get_rm_interrupt(vector: byte;var intaddr: tseginfo): boolean;
-    function set_rm_interrupt(vector: byte;const intaddr: tseginfo): boolean;
-    function get_exception_handler(e: byte;var intaddr: tseginfo): boolean;
-    function set_exception_handler(e: byte;const intaddr: tseginfo): boolean;
-    function get_pm_exception_handler(e: byte;var intaddr: tseginfo): boolean;
-    function set_pm_exception_handler(e: byte;const intaddr: tseginfo): boolean;
-    function free_rm_callback(var intaddr: tseginfo): boolean;
-    function get_rm_callback(pm_func: pointer;const reg: trealregs;var rmcb: tseginfo): boolean;
-    function get_cs: word;
-    function get_ds: word;
-    function get_ss: word;
-
-    { locking functions }
-    function allocate_memory_block(size:longint):longint;
-    function free_memory_block(blockhandle: longint): boolean;
-    function request_linear_region(linearaddr, size: longint;
-                                   var blockhandle: longint): boolean;
-    function lock_linear_region(linearaddr, size: longint): boolean;
-    function lock_data(var data;size: longint): boolean;
-    function lock_code(functionaddr: pointer;size: longint): boolean;
-    function unlock_linear_region(linearaddr, size: longint): boolean;
-    function unlock_data(var data;size: longint): boolean;
-    function unlock_code(functionaddr: pointer;size: longint): boolean;
-
-    { disables and enables interrupts }
-    procedure disable;
-    procedure enable;
-
-    function inportb(port: word): byte;
-    function inportw(port: word): word;
-    function inportl(port: word): longint;
-
-    procedure outportb(port: word;data: byte);
-    procedure outportw(port: word;data: word);
-    procedure outportl(port: word;data: longint);
-    function get_run_mode: word;
-
-    function transfer_buffer: longint;
-    function tb_segment: longint;
-    function tb_offset: longint;
-    function tb_size: longint;
-    procedure copytodos(var addr; len: longint);
-    procedure copyfromdos(var addr; len: longint);
-
-    procedure dpmi_dosmemput(seg: word;ofs: word;var data;count: longint);
-    procedure dpmi_dosmemget(seg: word;ofs: word;var data;count: longint);
-    procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs: word;count: longint);
-    procedure dpmi_dosmemfillchar(seg,ofs: word;count: longint;c: char);
-    procedure dpmi_dosmemfillword(seg,ofs: word;count: longint;w: word);
-
-
-
-    const
-       { this procedures are assigned to the procedure which are needed }
-       { for the current mode to access DOS memory                      }
-       { It's strongly recommended to use this procedures!              }
-       dosmemput: procedure(seg: word;ofs: word;var data;count: longint)=@dpmi_dosmemput;
-       dosmemget: procedure(seg: word;ofs: word;var data;count: longint)=@dpmi_dosmemget;
-       dosmemmove: procedure(sseg,sofs,dseg,dofs: word;count: longint)=@dpmi_dosmemmove;
-       dosmemfillchar: procedure(seg,ofs: word;count: longint;c: char)=@dpmi_dosmemfillchar;
-       dosmemfillword: procedure(seg,ofs: word;count: longint;w: word)=@dpmi_dosmemfillword;
-
-  implementation
-
-{$asmmode ATT}
-
-
-    { the following procedures copy from and to DOS memory using DPMI }
-    procedure dpmi_dosmemput(seg: word;ofs: word;var data;count: longint);
-
-      begin
-         seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
-      end;
-
-    procedure dpmi_dosmemget(seg: word;ofs: word;var data;count: longint);
-
-      begin
-         seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
-      end;
-
-    procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs: word;count: longint);
-
-      begin
-         seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
-      end;
-
-    procedure dpmi_dosmemfillchar(seg,ofs: word;count: longint;c: char);
-
-      begin
-         seg_fillchar(dosmemselector,seg*16+ofs,count,c);
-      end;
-
-    procedure dpmi_dosmemfillword(seg,ofs: word;count: longint;w: word);
-
-      begin
-         seg_fillword(dosmemselector,seg*16+ofs,count,w);
-      end;
-
-
-    procedure test_int31(flag: longint); stdcall; { stack-args! }
-      begin
-         asm
-            pushl %ebx
-            movw  $0,INT31ERROR
-            movl  flag,%ebx
-            testb $1,%bl
-            jz    .Lti31_1
-            movw  %ax,INT31ERROR
-            xorl  %eax,%eax
-            jmp   .Lti31_2
-            .Lti31_1:
-            movl  $1,%eax
-            .Lti31_2:
-            popl  %ebx
-         end;
-      end;
-
-    function global_dos_alloc(bytes: longint): longint;
-
-      begin
-         asm
-            pushl %ebx
-            movl bytes,%ebx
-            addl $0xf,%ebx              // round up
-            shrl $0x4,%ebx              // convert to Paragraphs
-            movl $0x100,%eax            // function 0x100
-            int  $0x31
-            jnc  .LDos_OK
-            movw %ax,INT31ERROR
-            xorl %eax,%eax
-            jmp  .LDos_end
-          .LDos_OK:
-            shll $0x10,%eax             // return Segment in hi(Result)
-            movw %dx,%ax                // return Selector in lo(Result)
-          .LDos_end:
-            movl %eax,__result
-            popl %ebx
-         end;
-      end;
-
-    function  global_dos_free(selector: word): boolean;
-
-      begin
-         asm
-            movw Selector,%dx
-            movl $0x101,%eax
-            int  $0x31
-            setnc %al
-            movb %al,__RESULT
-         end;
-      end;
-
-    function realintr(intnr: word;var regs: trealregs): boolean;
-
-      begin
-         regs.realsp:=0;
-         regs.realss:=0;
-         regs.realres:=0; { play it safe }
-         asm
-            { save all used registers to avoid crash under NTVDM }
-            { when spawning a 32-bit DPMI application            }
-            pushl %edi
-            pushl %ebx
-            pushw %fs
-            movw  intnr,%bx
-            xorl  %ecx,%ecx
-            movl  regs,%edi
-            { es is always equal ds }
-            movl  $0x300,%eax
-            int   $0x31
-            popw  %fs
-            setnc %al
-            movb  %al,__RESULT
-            popl  %ebx
-            popl  %edi
-         end;
-      end;
-
-    procedure seg_fillchar(seg: word;ofs: longint;count: longint;c: char);
-
-      begin
-         asm
-            pushl %edi
-            movl ofs,%edi
-            movl count,%ecx
-            movb c,%dl
-            { load es with selector }
-            pushw %es
-            movw seg,%ax
-            movw %ax,%es
-            { fill eax with duplicated c }
-            { so we can use stosl        }
-            movb %dl,%dh
-            movw %dx,%ax
-            shll $16,%eax
-            movw %dx,%ax
-            movl %ecx,%edx
-            shrl $2,%ecx
-            cld
-            rep
-            stosl
-            movl %edx,%ecx
-            andl $3,%ecx
-            rep
-            stosb
-            popw %es
-            popl %edi
-         end;
-      end;
-
-    procedure seg_fillword(seg: word;ofs: longint;count: longint;w: word);
-
-      begin
-         asm
-            pushl %edi
-            movl ofs,%edi
-            movl count,%ecx
-            movw w,%dx
-            { load segment }
-            pushw %es
-            movw seg,%ax
-            movw %ax,%es
-            { fill eax }
-            movw %dx,%ax
-            shll $16,%eax
-            movw %dx,%ax
-            movl %ecx,%edx
-            shrl $1,%ecx
-            cld
-            rep
-            stosl
-            movl %edx,%ecx
-            andl $1,%ecx
-            rep
-            stosw
-            popw %es
-            popl %edi
-         end;
-      end;
-
-    procedure seg_move(sseg: word;source: longint;dseg: word;dest: longint;count: longint);
-
-      begin
-         if count=0 then
-           exit;
-         if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
-           asm
-              pushl %esi
-              pushl %edi
-              pushw %es
-              pushw %ds
-              cld
-              movl count,%ecx
-              movl source,%esi
-              movl dest,%edi
-              movw dseg,%ax
-              movw %ax,%es
-              movw sseg,%ax
-              movw %ax,%ds
-              movl %ecx,%eax
-              shrl $2,%ecx
-              rep
-              movsl
-              movl %eax,%ecx
-              andl $3,%ecx
-              rep
-              movsb
-              popw %ds
-              popw %es
-              popl %edi
-              popl %esi
-           end ['ECX','EAX']
-         else if (source<dest) then
-           { copy backward for overlapping }
-           asm
-              pushl %esi
-              pushl %edi
-              pushw %es
-              pushw %ds
-              std
-              movl count,%ecx
-              movl source,%esi
-              movl dest,%edi
-              movw dseg,%ax
-              movw %ax,%es
-              movw sseg,%ax
-              movw %ax,%ds
-              addl %ecx,%esi
-              addl %ecx,%edi
-              movl %ecx,%eax
-              andl $3,%ecx
-              orl %ecx,%ecx
-              jz .LSEG_MOVE1
-
-              { calculate esi and edi}
-              decl %esi
-              decl %edi
-              rep
-              movsb
-              incl %esi
-              incl %edi
-           .LSEG_MOVE1:
-              subl $4,%esi
-              subl $4,%edi
-              movl %eax,%ecx
-              shrl $2,%ecx
-              rep
-              movsl
-              cld
-              popw %ds
-              popw %es
-              popl %edi
-              popl %esi
-           end ['ECX','EAX'];
-      end;
-
-    procedure outportb(port: word;data: byte);
-
-      begin
-         asm
-            movw port,%dx
-            movb data,%al
-            outb %al,%dx
-         end ['EAX','EDX'];
-      end;
-
-    procedure outportw(port: word;data: word);
-
-      begin
-         asm
-            movw port,%dx
-            movw data,%ax
-            outw %ax,%dx
-         end ['EAX','EDX'];
-      end;
-
-    procedure outportl(port: word;data: longint);
-
-      begin
-         asm
-            movw port,%dx
-            movl data,%eax
-            outl %eax,%dx
-         end ['EAX','EDX'];
-      end;
-
-    function inportb(port: word): byte;
-
-      begin
-         asm
-            movw port,%dx
-            inb %dx,%al
-            movb %al,__RESULT
-         end ['EAX','EDX'];
-      end;
-
-    function inportw(port: word): word;
-
-      begin
-         asm
-            movw port,%dx
-            inw %dx,%ax
-            movw %ax,__RESULT
-         end ['EAX','EDX'];
-      end;
-
-    function inportl(port: word): longint;
-
-      begin
-         asm
-            movw port,%dx
-            inl %dx,%eax
-            movl %eax,__RESULT
-         end ['EAX','EDX'];
-      end;
-
-
-
-    function get_cs: word;assembler;
-      asm
-            movw %cs,%ax
-      end;
-
-
-    function get_ss: word;assembler;
-      asm
-            movw %ss,%ax
-      end;
-
-
-    function get_ds: word;assembler;
-      asm
-            movw %ds,%ax
-      end;
-
-
-    function set_pm_interrupt(vector: byte;const intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl intaddr,%eax
-            movl (%eax),%edx
-            movw 4(%eax),%cx
-            movl $0x205,%eax
-            movb vector,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function set_rm_interrupt(vector: byte;const intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl intaddr,%eax
-            movw (%eax),%dx
-            movw 4(%eax),%cx
-            movl $0x201,%eax
-            movb vector,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function set_pm_exception_handler(e: byte;const intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl intaddr,%eax
-            movl (%eax),%edx
-            movw 4(%eax),%cx
-            movl $0x212,%eax
-            movb e,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function set_exception_handler(e: byte;const intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl intaddr,%eax
-            movl (%eax),%edx
-            movw 4(%eax),%cx
-            movl $0x203,%eax
-            movb e,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function get_pm_exception_handler(e: byte;var intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl $0x210,%eax
-            movb e,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl intaddr,%eax
-            movl %edx,(%eax)
-            movw %cx,4(%eax)
-            popl %ebx
-         end;
-      end;
-
-    function get_exception_handler(e: byte;var intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movl $0x202,%eax
-            movb e,%bl
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl intaddr,%eax
-            movl %edx,(%eax)
-            movw %cx,4(%eax)
-            popl %ebx
-         end;
-      end;
-
-    function get_pm_interrupt(vector: byte;var intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movb vector,%bl
-            movl $0x204,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl intaddr,%eax
-            movl %edx,(%eax)
-            movw %cx,4(%eax)
-            popl %ebx
-         end;
-      end;
-
-    function get_rm_interrupt(vector: byte;var intaddr: tseginfo): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movb vector,%bl
-            movl $0x200,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl intaddr,%eax
-            movzwl %dx,%edx
-            movl %edx,(%eax)
-            movw %cx,4(%eax)
-            popl %ebx
-         end;
-      end;
-
-    function free_rm_callback(var intaddr: tseginfo): boolean;
-      begin
-         asm
-            movl intaddr,%eax
-            movw (%eax),%dx
-            movw 4(%eax),%cx
-            movl $0x304,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-         end;
-      end;
-
-    { here we must use ___v2prt0_ds_alias instead of from v2prt0.s
-    because the exception processor sets the ds limit to $fff
-    at hardware exceptions }
-
-    var
-       ___v2prt0_ds_alias: word; external name '___v2prt0_ds_alias';
-
-    function get_rm_callback(pm_func: pointer;const reg: trealregs;var rmcb: tseginfo): boolean;
-      begin
-         asm
-            pushl %esi
-            pushl %edi
-            movl  pm_func,%esi
-            movl  reg,%edi
-            pushw %es
-            movw  ___v2prt0_ds_alias,%ax
-            movw  %ax,%es
-            pushw %ds
-            movw  %cs,%ax
-            movw  %ax,%ds
-            movl  $0x303,%eax
-            int   $0x31
-            popw  %ds
-            popw  %es
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl  rmcb,%eax
-            movzwl %dx,%edx
-            movl  %edx,(%eax)
-            movw  %cx,4(%eax)
-            popl %edi
-            popl %esi
-         end;
-      end;
-
-    function allocate_ldt_descriptors(count: word): word;
-
-      begin
-         asm
-            movw count,%cx
-            xorl %eax,%eax
-            int $0x31
-            movw %ax,__RESULT
-         end;
-      end;
-
-    function free_ldt_descriptor(d: word): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movw d,%bx
-            movl $1,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function segment_to_descriptor(seg: word): word;
-
-      begin
-         asm
-            pushl %ebx
-            movw seg,%bx
-            movl $2,%eax
-            int $0x31
-            movw %ax,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function get_next_selector_increment_value: word;
-
-      begin
-         asm
-            movl $3,%eax
-            int $0x31
-            movw %ax,__RESULT
-         end;
-      end;
-
-    function get_segment_base_address(d: word): longint;
-
-      begin
-         asm
-            pushl %ebx
-            movw d,%bx
-            movl $6,%eax
-            int $0x31
-            xorl %eax,%eax
-            movw %dx,%ax
-            shll $16,%ecx
-            orl %ecx,%eax
-            movl %eax,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function get_page_size:longint;
-      begin
-        asm
-           pushl %ebx
-           movl $0x604,%eax
-           int $0x31
-           shll $16,%ebx
-           movw %cx,%bx
-           movl %ebx,__RESULT
-           popl %ebx
-        end;
-      end;
-
-    function request_linear_region(linearaddr, size: longint;
-                                   var blockhandle: longint): boolean;
-      var
-         pageofs: longint;
-
-      begin
-         pageofs:=linearaddr and $3ff;
-         linearaddr:=linearaddr-pageofs;
-         size:=size+pageofs;
-         asm
-            pushl %ebx
-            pushl %esi
-            movl $0x504,%eax
-            movl linearaddr,%ebx
-            movl size,%ecx
-            movl $1,%edx
-            xorl %esi,%esi
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            movl blockhandle,%eax
-            movl %esi,(%eax)
-            movl %ebx,pageofs
-            popl %esi
-            popl %ebx
-         end;
-         if pageofs<>linearaddr then
-           request_linear_region:=false;
-      end;
-
-    function allocate_memory_block(size:longint):longint;
-      begin
-        asm
-          pushl %ebx
-          pushl %esi
-          movl  $0x501,%eax
-          movl  size,%ecx
-          movl  %ecx,%ebx
-          shrl  $16,%ebx
-          andl  $65535,%ecx
-          int   $0x31
-          jnc   .Lallocate_mem_block_err
-          xorl  %ebx,%ebx
-          xorl  %ecx,%ecx
-       .Lallocate_mem_block_err:
-          shll  $16,%ebx
-          movw  %cx,%bx
-          shll  $16,%esi
-          movw  %di,%si
-          movl  %ebx,__RESULT
-          popl %esi
-          popl %ebx
-        end;
-     end;
-
-    function free_memory_block(blockhandle: longint): boolean;
-      begin
-         asm
-            pushl %edi
-            pushl %esi
-            movl blockhandle,%esi
-            movl %esi,%edi
-            shll $16,%esi
-            movl $0x502,%eax
-            int  $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %esi
-            popl %edi
-         end;
-      end;
-
-    function lock_linear_region(linearaddr, size: longint): boolean;
-
-      begin
-          asm
-            pushl %ebx
-            pushl %edi
-            pushl %esi
-            movl  $0x600,%eax
-            movl  linearaddr,%ecx
-            movl  %ecx,%ebx
-            shrl  $16,%ebx
-            movl  size,%esi
-            movl  %esi,%edi
-            shrl  $16,%esi
-            int   $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %esi
-            popl %edi
-            popl %ebx
-          end;
-      end;
-
-    function lock_data(var data;size: longint): boolean;
-
-      var
-         linearaddr: longint;
-
-      begin
-         if get_run_mode<>rm_dpmi then
-           exit;
-         linearaddr:=longint(@data)+get_segment_base_address(get_ds);
-         lock_data:=lock_linear_region(linearaddr,size);
-      end;
-
-    function lock_code(functionaddr: pointer;size: longint): boolean;
-
-      var
-         linearaddr: longint;
-
-      begin
-         if get_run_mode<>rm_dpmi then
-           exit;
-         linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
-         lock_code:=lock_linear_region(linearaddr,size);
-      end;
-
-    function unlock_linear_region(linearaddr,size: longint): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            pushl %edi
-            pushl %esi
-            movl  $0x601,%eax
-            movl  linearaddr,%ecx
-            movl  %ecx,%ebx
-            shrl  $16,%ebx
-            movl  size,%esi
-            movl  %esi,%edi
-            shrl  $16,%esi
-            int   $0x31
-            pushf
-            call  test_int31
-            movb  %al,__RESULT
-            popl %esi
-            popl %edi
-            popl %ebx
-         end;
-      end;
-
-    function unlock_data(var data;size: longint): boolean;
-
-      var
-         linearaddr: longint;
-      begin
-         if get_run_mode<>rm_dpmi then
-           exit;
-         linearaddr:=longint(@data)+get_segment_base_address(get_ds);
-         unlock_data:=unlock_linear_region(linearaddr,size);
-      end;
-
-    function unlock_code(functionaddr: pointer;size: longint): boolean;
-
-      var
-         linearaddr: longint;
-      begin
-         if get_run_mode<>rm_dpmi then
-           exit;
-         linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
-         unlock_code:=unlock_linear_region(linearaddr,size);
-      end;
-
-    function set_segment_base_address(d: word;s: dword): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movw d,%bx
-            leal s,%eax
-            movw (%eax),%dx
-            movw 2(%eax),%cx
-            movl $7,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function set_descriptor_access_right(d: word;w: word): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movw d,%bx
-            movw w,%cx
-            movl $9,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function set_segment_limit(d: word;s: dword): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            movw d,%bx
-            leal s,%eax
-            movw (%eax),%dx
-            movw 2(%eax),%cx
-            movl $8,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function get_descriptor_access_right(d: word): longint;
-
-      begin
-         asm
-            movzwl d,%eax
-            lar %eax,%eax
-            jz .L_ok
-            xorl %eax,%eax
-         .L_ok:
-            movl %eax,__RESULT
-         end;
-      end;
-    function get_segment_limit(d: word): dword;
-
-      begin
-         asm
-            movzwl d,%eax
-            lsl %eax,%eax
-            jz .L_ok2
-            xorl %eax,%eax
-         .L_ok2:
-            movl %eax,__RESULT
-         end;
-      end;
-
-    function create_code_segment_alias_descriptor(seg: word): word;
-
-      begin
-         asm
-            pushl %ebx
-            movw seg,%bx
-            movl $0xa,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movw %ax,__RESULT
-            popl %ebx
-         end;
-      end;
-
-    function get_meminfo(var meminfo: tmeminfo): boolean;
-
-      begin
-         asm
-            pushl %edi
-            movl meminfo,%edi
-            movl $0x500,%eax
-            int $0x31
-            pushf
-            movb %al,__RESULT
-            call test_int31
-            popl %edi
-         end;
-      end;
-
-    function get_linear_addr(phys_addr: dword;size: longint): dword;
-
-      begin
-         asm
-            pushl %ebx
-            pushl %edi
-            pushl %esi
-            movl phys_addr,%ebx
-            movl %ebx,%ecx
-            shrl $16,%ebx
-            movl size,%esi
-            movl %esi,%edi
-            shrl $16,%esi
-            movl $0x800,%eax
-            int $0x31
-            pushf
-            call test_int31
-            shll $16,%ebx
-            movw %cx,%bx
-            movl %ebx,__RESULT
-            popl %esi
-            popl %edi
-            popl %ebx
-         end;
-      end;
-
-    function free_linear_addr_mapping(linear_addr: dword): boolean;
-
-      begin
-         asm
-            pushl %ebx
-            pushl %ecx
-            movl linear_addr,%ebx
-            movl %ebx,%ecx
-            shrl $16,%ebx
-            movl $0x801,%eax
-            int $0x31
-            pushf
-            call test_int31
-            movb %al,__RESULT
-	    popl %ecx
-            popl %ebx
-         end;
-      end;
-
-    procedure disable;assembler;
-
-      asm
-         cli
-      end;
-
-    procedure enable;assembler;
-
-      asm
-         sti
-      end;
-
-
-    var
-      _run_mode: word;external name '_run_mode';
-
-    function get_run_mode: word;
-
-      begin
-         get_run_mode:=_run_mode;
-      end;
-
-    function map_device_in_memory_block(handle,offset,pagecount,device:dword):boolean;
-      begin
-         asm
-           pushl %ebx
-           pushl %edi
-           pushl %esi
-           movl device,%edx
-           movl handle,%esi
-           movl offset,%ebx
-           movl pagecount,%ecx
-           movl $0x0508,%eax
-           int $0x31
-           pushf
-           call test_int31
-           movb %al,__RESULT
-           popl %esi
-           popl %edi
-           popl %ebx
-         end;
-      end;
-
-    function get_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
-      begin
-         asm
-           pushl %ebx
-           pushl %ecx
-           pushl %edx
-           pushl %esi
-           pushw %es
-	   pushw %ds
-	   popw %es
-           movl buf,%edx
-           movl handle,%esi
-           movl offset,%ebx
-           movl pagecount,%ecx
-           movl $0x0506,%eax
-           int $0x31
-           pushf
-           call test_int31
-           movb %al,__RESULT
-	   popw %es
-           popl %esi
-           popl %edx
-           popl %ecx
-           popl %ebx
-	 end;
-      end;
-
-    function set_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
-      begin
-         asm
-           pushl %ebx
-           pushl %ecx
-           pushl %edx
-           pushl %esi
-           pushw %es
-	   pushw %ds
-	   popw %es
-           movl buf,%edx
-           movl handle,%esi
-           movl offset,%ebx
-           movl pagecount,%ecx
-           movl $0x0507,%eax
-           int $0x31
-           pushf
-           call test_int31
-           movb %al,__RESULT
-	   popw %es
-           popl %esi
-           popl %edx
-           popl %ecx
-           popl %ebx
-	 end;
-      end;
-
-    function get_dpmi_version(var version: tdpmiversioninfo): boolean;
-      var
-        _version, _flags, _cpu, _pic: word;
-      begin
-         asm
-           movl $0x0400,%eax
-           int $0x31
-           pushf
-	   movw %ax,_version
-	   movw %bx,_flags
-	   movw %cx,_cpu
-	   movw %dx,_pic
-           call test_int31
-           movb %al,__RESULT
-	 end ['EAX','EBX','ECX','EDX'];
-
-	 if get_dpmi_version then
-	 begin
-	   FillChar(version, SizeOf(version), 0);
-	   version.major := _version shr 8;
-	   version.minor := _version and $ff;
-	   version.flags := _flags;
-	   version.cpu := _cpu and $ff;
-	   version.master_pic := _pic shr 8;
-	   version.slave_pic := _pic and $ff;
-	 end;
-      end;
-
-{*****************************************************************************
-                              Transfer Buffer
-*****************************************************************************}
-
-    function transfer_buffer: longint;
-      begin
-         transfer_buffer := go32_info_block.linear_address_of_transfer_buffer;
-      end;
-
-
-    function tb_segment: longint;
-      begin
-        tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
-      end;
-
-
-    function tb_offset: longint;
-      begin
-        tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
-      end;
-
-
-    function tb_size: longint;
-      begin
-         tb_size := go32_info_block.size_of_transfer_buffer;
-      end;
-
-
-    procedure copytodos(var addr; len: longint);
-       begin
-          if len>tb_size then
-            runerror(217);
-          seg_move(get_ds,longint(@addr),dosmemselector,transfer_buffer,len);
-       end;
-
-
-    procedure copyfromdos(var addr; len: longint);
-       begin
-          if len>tb_size then
-            runerror(217);
-          seg_move(dosmemselector,transfer_buffer,get_ds,longint(@addr),len);
-       end;
-
-
-    var
-      _core_selector: word;external name '_core_selector';
-
-begin
-   int31error:=0;
-   dosmemselector:=_core_selector;
-end.

+ 1 - 1
packages/ptc/src/dos/timeunit/timeunit.pp

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2010 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2010, 2017 Nikolay Nikolov ([email protected])
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public

+ 5 - 2
packages/ptc/src/ptc.pp

@@ -69,7 +69,7 @@ uses
 {$ENDIF FPDOC}
 
 const
-  PTCPAS_VERSION = 'PTCPas 0.99.14.1';
+  PTCPAS_VERSION = 'PTCPas 0.99.15';
 
 type
   PUint8  = ^Uint8;
@@ -117,7 +117,7 @@ implementation
 
 {$IFDEF GO32V2}
 uses
-  textfx2, vesa, vga, cga, timeunit, crt, go32fix, mouse33h;
+  textfx2, vesa, vga, cga, timeunit, crt, go32, mouse33h;
 {$ENDIF GO32V2}
 
 {$IF defined(WIN32) OR defined(WIN64)}
@@ -150,6 +150,9 @@ uses
     {$IFDEF ENABLE_X11_EXTENSION_GLX}
     , glx
     {$ENDIF ENABLE_X11_EXTENSION_GLX}
+    {$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+    , XI2, XInput2
+    {$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
   {$ENDIF X11}
   {$IFDEF COCOA}
     , CocoaAll

+ 240 - 0
packages/ptc/src/ptclaz.lpi

@@ -0,0 +1,240 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="ptclaz"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <Units Count="45">
+      <Unit0>
+        <Filename Value="ptclaz.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="ptc.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="ptc"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="core/aread.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="core/areai.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="core/baseconsoled.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="core/baseconsolei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="core/basesurfaced.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="core/basesurfacei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="core/cleard.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="core/cleari.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="core/clipperd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="core/clipperi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="core/closeeventd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="core/closeeventi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="core/colord.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="core/colori.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit15>
+      <Unit16>
+        <Filename Value="core/consoled.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit16>
+      <Unit17>
+        <Filename Value="core/consolei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit17>
+      <Unit18>
+        <Filename Value="core/copyd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit18>
+      <Unit19>
+        <Filename Value="core/copyi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit19>
+      <Unit20>
+        <Filename Value="core/coreimplementation.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit20>
+      <Unit21>
+        <Filename Value="core/coreinterface.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit21>
+      <Unit22>
+        <Filename Value="core/errord.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit22>
+      <Unit23>
+        <Filename Value="core/errori.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit23>
+      <Unit24>
+        <Filename Value="core/eventd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="core/eventi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="core/formatd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit26>
+      <Unit27>
+        <Filename Value="core/formati.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="core/keyeventd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="core/keyeventi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="core/log.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="core/moded.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="core/modei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit32>
+      <Unit33>
+        <Filename Value="core/mouseeventd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="core/mouseeventi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="core/openglattributesd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit35>
+      <Unit36>
+        <Filename Value="core/openglattributesi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit36>
+      <Unit37>
+        <Filename Value="core/paletted.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit37>
+      <Unit38>
+        <Filename Value="core/palettei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit38>
+      <Unit39>
+        <Filename Value="core/resizeeventd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit39>
+      <Unit40>
+        <Filename Value="core/resizeeventi.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit40>
+      <Unit41>
+        <Filename Value="core/surfaced.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit41>
+      <Unit42>
+        <Filename Value="core/surfacei.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit42>
+      <Unit43>
+        <Filename Value="core/timerd.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit43>
+      <Unit44>
+        <Filename Value="core/timeri.inc"/>
+        <IsPartOfProject Value="True"/>
+      </Unit44>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="ptclaz"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 6 - 0
packages/ptc/src/ptclaz.lpr

@@ -0,0 +1,6 @@
+program ptclaz;
+uses
+  ptc;
+begin
+end.
+

+ 6 - 0
packages/ptc/src/ptcpas.cfg

@@ -122,3 +122,9 @@
 #dga2
 #dga2 on
 #dga2 off
+#xinput2
+#xinput2 on
+#xinput2 off
+#xshm
+#xshm on
+#xshm off

+ 13 - 4
packages/ptc/src/win32/base/win32hook.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009, 2010, 2012  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009, 2010, 2012, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -104,7 +104,10 @@ begin
   if result = 0 then
   begin
     { call original window procedure }
-    Result := CallWindowProc(WNDPROC(lookup^.wndproc), hwnd, msg, wParam, lParam);
+    if IsWindowUnicode(hwnd) then
+      Result := CallWindowProcW(WNDPROC(lookup^.wndproc), hwnd, msg, wParam, lParam)
+    else
+      Result := CallWindowProcA(WNDPROC(lookup^.wndproc), hwnd, msg, wParam, lParam);
   end;
 
   { leave monitor }
@@ -189,7 +192,10 @@ begin
 {$ENDIF}
 
     { set window procedure to hook procedure }
-    SetWindowLongPtr(AWindow, GWLP_WNDPROC, PtrInt(@TWin32Hook_hook));
+    if IsWindowUnicode(AWindow) then
+      SetWindowLongPtrW(AWindow, GWLP_WNDPROC, PtrInt(@TWin32Hook_hook))
+    else
+      SetWindowLongPtrA(AWindow, GWLP_WNDPROC, PtrInt(@TWin32Hook_hook));
   end;
 
   { leave monitor }
@@ -236,7 +242,10 @@ begin
       if TWin32Hook_m_registry[index].count = 0 then
       begin
         { restore original window procedure }
-        SetWindowLongPtr(AWindow, GWLP_WNDPROC, TWin32Hook_m_registry[i].wndproc);
+        if IsWindowUnicode(AWindow) then
+          SetWindowLongPtrW(AWindow, GWLP_WNDPROC, TWin32Hook_m_registry[i].wndproc)
+        else
+          SetWindowLongPtrA(AWindow, GWLP_WNDPROC, TWin32Hook_m_registry[i].wndproc);
 
         { remove this lookup (quite inefficient for high count...) }
         for i := index to TWin32Hook_Count - 2 do

+ 90 - 43
packages/ptc/src/win32/base/win32kbd.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2012  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2012, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -38,11 +38,6 @@ begin
   FMonitor := TWin32Monitor.Create;
   FEvent := TWin32Event.Create;
 
-  { setup defaults }
-  FAlt := False;
-  FShift := False;
-  FControl := False;
-
   { setup data }
   FEventQueue := AEventQueue;
   FMultithreaded := AMultithreaded;
@@ -71,9 +66,15 @@ begin
 end;
 
 function TWin32Keyboard.WndProc(hWnd: HWND; message: DWord; wParam: WPARAM; lParam: LPARAM): LRESULT;
+const
+  {$warning move this to the windows unit! }
+  MAPVK_VK_TO_CHAR = 2;
+  MAPVK_VK_TO_VSC = 0;
+  MAPVK_VSC_TO_VK = 1;
+  MAPVK_VSC_TO_VK_EX = 3;
 var
   i: Integer;
-  scancode: Integer;
+  scancode: UINT;
   KeyStateArray: array [0..255] of Byte;
   AsciiBuf: Word;
   press: Boolean;
@@ -81,6 +82,8 @@ var
   TranslatedCharacters, TranslatedWideCharacters: Integer;
   WideStr: WideString;
   KeyCode: Integer;
+  ExtendedKey, DeadKey: Boolean;
+  ModifierKeys: TPTCModifierKeys;
 begin
   Result := 0;
   { check enabled flag }
@@ -91,19 +94,54 @@ begin
   if (message = WM_KEYDOWN) or (message = WM_KEYUP) or (message = WM_SYSKEYDOWN) or (message = WM_SYSKEYUP) then
   begin
     press := (message = WM_KEYDOWN) or (message = WM_SYSKEYDOWN);
+    ExtendedKey := (lParam and (1 shl 24)) <> 0;
+
+    ModifierKeys := [];
 
     { update modifiers }
-    if wParam = VK_MENU then
-      { alt }
-      FAlt := press
-    else
-      if wParam = VK_SHIFT then
-        { shift }
-        FShift := press
-      else
-        if wParam = VK_CONTROL then
-          { control }
-          FControl := press;
+    { dead key? }
+    DeadKey := (MapVirtualKey(wParam, MAPVK_VK_TO_CHAR) and $80000000) <> 0;
+    if DeadKey then
+      Include(ModifierKeys, pmkDeadKey);
+    { alt }
+    if (GetKeyState(VK_MENU) and $8000) <> 0 then
+      Include(ModifierKeys, pmkAlt);
+    { shift }
+    if (GetKeyState(VK_SHIFT) and $8000) <> 0 then
+      Include(ModifierKeys, pmkShift);
+    { control }
+    if (GetKeyState(VK_CONTROL) and $8000) <> 0 then
+      Include(ModifierKeys, pmkControl);
+    { left/right alt }
+    if (GetKeyState(VK_LMENU) and $8000) <> 0 then
+      Include(ModifierKeys, pmkLeftAlt);
+    if (GetKeyState(VK_RMENU) and $8000) <> 0 then
+      Include(ModifierKeys, pmkRightAlt);
+    { left/right shift }
+    if (GetKeyState(VK_LSHIFT) and $8000) <> 0 then
+      Include(ModifierKeys, pmkLeftShift);
+    if (GetKeyState(VK_RSHIFT) and $8000) <> 0 then
+      Include(ModifierKeys, pmkRightShift);
+    { left/right control }
+    if (GetKeyState(VK_LCONTROL) and $8000) <> 0 then
+      Include(ModifierKeys, pmkLeftControl);
+    if (GetKeyState(VK_RCONTROL) and $8000) <> 0 then
+      Include(ModifierKeys, pmkRightControl);
+    { num lock }
+    if (GetKeyState(VK_NUMLOCK) and $8000) <> 0 then
+      Include(ModifierKeys, pmkNumLockPressed);
+    if (GetKeyState(VK_NUMLOCK) and 1) <> 0 then
+      Include(ModifierKeys, pmkNumLockActive);
+    { caps lock }
+    if (GetKeyState(VK_CAPITAL) and $8000) <> 0 then
+      Include(ModifierKeys, pmkCapsLockPressed);
+    if (GetKeyState(VK_CAPITAL) and 1) <> 0 then
+      Include(ModifierKeys, pmkCapsLockActive);
+    { scroll lock }
+    if (GetKeyState(VK_SCROLL) and $8000) <> 0 then
+      Include(ModifierKeys, pmkScrollLockPressed);
+    if (GetKeyState(VK_SCROLL) and 1) <> 0 then
+      Include(ModifierKeys, pmkScrollLockActive);
 
     { enter monitor if multithreaded }
     if FMultithreaded then
@@ -114,25 +152,48 @@ begin
     if GetKeyboardState(@KeyStateArray) then
     begin
       scancode := (lParam shr 16) and $FF;
-      {todo: ToUnicode (Windows NT)}
-      TranslatedCharacters := ToAscii(wParam, scancode, @KeyStateArray, @AsciiBuf, 0);
-      if (TranslatedCharacters = 1) or (TranslatedCharacters = 2) then
+      if not press then
+        scancode := scancode or $8000;
+      if IsWindowUnicode(hWnd) then
+      begin
+        SetLength(WideStr, 16);
+        TranslatedWideCharacters := ToUnicode(wParam, scancode, @KeyStateArray, @WideStr[1], Length(WideStr), 0);
+        if TranslatedWideCharacters <> -1 then
+          SetLength(WideStr, TranslatedWideCharacters)
+        else
+          WideStr := '';
+      end
+      else
       begin
-        TranslatedWideCharacters := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @AsciiBuf, TranslatedCharacters, nil, 0);
-        if TranslatedWideCharacters <> 0 then
+        TranslatedCharacters := ToAscii(wParam, scancode, @KeyStateArray, @AsciiBuf, 0);
+        if TranslatedCharacters > 0 then
         begin
+          TranslatedWideCharacters := MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @AsciiBuf, TranslatedCharacters, nil, 0);
           SetLength(WideStr, TranslatedWideCharacters);
-          MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @AsciiBuf, TranslatedCharacters, @WideStr[1], TranslatedWideCharacters);
-
-          if Length(WideStr) = 1 then
-            uni := Ord(WideStr[1]);
-        end;
+          if TranslatedWideCharacters <> 0 then
+            MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, @AsciiBuf, TranslatedCharacters, @WideStr[1], TranslatedWideCharacters);
+        end
+        else
+          WideStr := '';
       end;
+      if Length(WideStr) = 1 then
+        uni := Ord(WideStr[1]);
     end;
 
     KeyCode := wParam;
     if wParam = VK_RETURN then
+    begin
       KeyCode := PTCKEY_ENTER;
+      if ExtendedKey then
+        Include(ModifierKeys, pmkNumPadKey);
+    end;
+    if not ExtendedKey and
+      (wParam in [VK_LEFT,VK_RIGHT,VK_UP,VK_DOWN,VK_INSERT,VK_DELETE,
+                  VK_HOME,VK_END,VK_PRIOR,VK_NEXT]) then
+      Include(ModifierKeys, pmkNumPadKey);
+    if wParam in [VK_CLEAR,VK_NUMPAD0..VK_NUMPAD9,VK_DECIMAL,VK_DIVIDE,
+                  VK_MULTIPLY,VK_SUBTRACT,VK_ADD,VK_NUMLOCK] then
+      Include(ModifierKeys, pmkNumPadKey);
     if wParam = VK_INSERT then
       KeyCode := PTCKEY_INSERT;
     if wParam = VK_DELETE then
@@ -145,7 +206,7 @@ begin
     { handle key repeat count }
     for i := 1 to lParam and $FFFF do
       { create and insert key object }
-      FEventQueue.AddEvent(TPTCKeyEvent.Create(KeyCode, uni, FAlt, FShift, FControl, press));
+      FEventQueue.AddEvent(TPTCKeyEvent.Create(KeyCode, uni, ModifierKeys, press));
 
     { check multithreaded flag }
     if FMultithreaded then
@@ -157,18 +218,4 @@ begin
       FMonitor.Leave;
     end;
   end;
-(*  else
-    if message = WM_KEYUP then
-      { update modifiers }
-      if wParam = VK_MENU then
-        { alt up }
-        m_alt := False
-      else
-        if wParam = VK_SHIFT then
-          { shift up }
-          m_shift := False
-        else
-          if wParam = VK_CONTROL then
-            { control up }
-            m_control := False;*)
 end;

+ 1 - 6
packages/ptc/src/win32/base/win32kbdd.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2009, 2010  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2009, 2010, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -42,11 +42,6 @@ type
     { flag data }
     FEnabled: Boolean;
 
-    { modifiers }
-    FAlt: Boolean;
-    FShift: Boolean;
-    FControl: Boolean;
-
     { window procedure }
     function WndProc(hWnd: HWND; message: DWord; wParam: WPARAM; lParam: LPARAM): LRESULT; override;
   public

+ 2 - 1
packages/ptc/src/win32/base/win32moused.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2007, 2009, 2010, 2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2007, 2009, 2010, 2013, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -62,6 +62,7 @@ type
 
     procedure SetWindowArea(AWindowX1, AWindowY1, AWindowX2, AWindowY2: Integer);
     procedure SetConsoleSize(AConsoleWidth, AConsoleHeight: Integer);
+    function MoveMouseTo(X, Y: Integer): Boolean;
 
     { control }
     procedure Enable;

+ 85 - 13
packages/ptc/src/win32/base/win32mousei.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2007, 2009, 2010, 2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2007, 2009, 2010, 2013, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -73,18 +73,48 @@ begin
   FEnabled := False;
 end;
 
+function TWin32Mouse.MoveMouseTo(X, Y: Integer): Boolean;
+var
+  WindowRect: RECT;
+  pt: TPOINT;
+begin
+  if (X < 0) or (X >= FConsoleWidth) or (Y <= 0) or (Y >= FConsoleHeight) then
+    exit(False);
+
+  if not FFullScreen then
+  begin
+    if not GetClientRect(FWindow, WindowRect) then
+      exit(False);
+
+    FWindowX1 := WindowRect.left;
+    FWindowY1 := WindowRect.top;
+    FWindowX2 := WindowRect.right - 1;
+    FWindowY2 := WindowRect.bottom - 1;
+  end;
+
+  pt.X := X * (FWindowX2 - FWindowX1) div (FConsoleWidth - 1) + FWindowX1;
+  pt.Y := Y * (FWindowY2 - FWindowY1) div (FConsoleHeight - 1) + FWindowY1;
+
+  if not ClientToScreen(FWindow, pt) then
+    exit(False);
+
+  Result := SetCursorPos(pt.X, pt.Y);
+end;
+
 function TWin32Mouse.WndProc(hWnd: HWND; message: DWord; wParam: WPARAM; lParam: LPARAM): LRESULT;
 var
   fwKeys: Integer;
-  xPos, yPos: Integer;
-  LButton, MButton, RButton: Boolean;
+  CurPos: POINT;
+  LButton, MButton, RButton, XButton1, XButton2: Boolean;
   TranslatedXPos, TranslatedYPos: Integer;
   PTCMouseButtonState: TPTCMouseButtonState;
   WindowRect: RECT;
+  ScrollAmount: Integer;
 
   button: TPTCMouseButton;
   before, after: Boolean;
   cstate: TPTCMouseButtonState;
+  I: Integer;
 begin
   Result := 0;
   { check enabled flag }
@@ -94,15 +124,27 @@ begin
   if (message = WM_MOUSEMOVE) or
      (message = WM_LBUTTONDOWN) or (message = WM_LBUTTONUP) or (message = WM_LBUTTONDBLCLK) or
      (message = WM_MBUTTONDOWN) or (message = WM_MBUTTONUP) or (message = WM_MBUTTONDBLCLK) or
-     (message = WM_RBUTTONDOWN) or (message = WM_RBUTTONUP) or (message = WM_RBUTTONDBLCLK) then
+     (message = WM_RBUTTONDOWN) or (message = WM_RBUTTONUP) or (message = WM_RBUTTONDBLCLK) or
+     (message = WM_XBUTTONDOWN) or (message = WM_XBUTTONUP) or (message = WM_XBUTTONDBLCLK) or
+     (message = WM_MOUSEWHEEL) or (message = WM_MOUSEHWHEEL) then
   begin
-    fwKeys := wParam; {MK_LBUTTON or MK_MBUTTON or MK_RBUTTON or MK_CONTROL or MK_SHIFT}
-    xPos := lParam and $FFFF;
-    yPos := (lParam shr 16) and $FFFF;
+    fwKeys := Word(wParam); {MK_LBUTTON or MK_MBUTTON or MK_RBUTTON or MK_CONTROL or MK_SHIFT}
+    CurPos.x := GET_X_LPARAM(lParam);
+    CurPos.y := GET_Y_LPARAM(lParam);
+
+    if (message = WM_MOUSEWHEEL) or (message = WM_MOUSEHWHEEL) then
+    begin
+      ScrollAmount := SmallInt(wParam shr 16);
+      { for WM_MOUSEWHEEL and WM_MOUSEHWHEEL, windows returns cursor position in
+        screen coordinates, instead of client coordinates, so convert them }
+      ScreenToClient(hWnd, CurPos);
+    end;
 
     LButton := (fwKeys and MK_LBUTTON) <> 0;
     MButton := (fwKeys and MK_MBUTTON) <> 0;
     RButton := (fwKeys and MK_RBUTTON) <> 0;
+    XButton1 := (fwKeys and MK_XBUTTON1) <> 0;
+    XButton2 := (fwKeys and MK_XBUTTON2) <> 0;
 
     if not FFullScreen then
     begin
@@ -114,16 +156,16 @@ begin
       FWindowY2 := WindowRect.bottom - 1;
     end;
 
-    if (xPos >= FWindowX1) and (yPos >= FWindowY1) and
-       (xPos <= FWindowX2) and (yPos <= FWindowY2) then
+    if (CurPos.x >= FWindowX1) and (CurPos.y >= FWindowY1) and
+       (CurPos.x <= FWindowX2) and (CurPos.y <= FWindowY2) then
     begin
       if FWindowX2 <> FWindowX1 then
-        TranslatedXPos := (xPos - FWindowX1) * (FConsoleWidth  - 1) div (FWindowX2 - FWindowX1)
+        TranslatedXPos := (CurPos.x - FWindowX1) * (FConsoleWidth  - 1) div (FWindowX2 - FWindowX1)
       else { avoid div by zero }
         TranslatedXPos := 0;
 
       if FWindowY2 <> FWindowY1 then
-        TranslatedYPos := (yPos - FWindowY1) * (FConsoleHeight - 1) div (FWindowY2 - FWindowY1)
+        TranslatedYPos := (CurPos.y - FWindowY1) * (FConsoleHeight - 1) div (FWindowY2 - FWindowY1)
       else { avoid div by zero }
         TranslatedYPos := 0;
 
@@ -141,12 +183,14 @@ begin
         PTCMouseButtonState := []
       else
         PTCMouseButtonState := [PTCMouseButton1];
-
       if RButton then
         PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton2];
-
       if MButton then
         PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton3];
+      if XButton1 then
+        PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton8];
+      if XButton2 then
+        PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton9];
 
       if not FPreviousMousePositionSaved then
       begin
@@ -180,6 +224,34 @@ begin
           end;
       end;
 
+      { scroll wheel? }
+      if (message = WM_MOUSEWHEEL) and (Abs(ScrollAmount) >= WHEEL_DELTA) then
+        if ScrollAmount > 0 then
+          for I := 1 to ScrollAmount div WHEEL_DELTA do
+          begin
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate + [PTCMouseButton4], True, PTCMouseButton4));
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate, False, PTCMouseButton4));
+          end
+        else
+          for I := 1 to Abs(ScrollAmount) div WHEEL_DELTA do
+          begin
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate + [PTCMouseButton5], True, PTCMouseButton5));
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate, False, PTCMouseButton5));
+          end;
+      if (message = WM_MOUSEHWHEEL) and (Abs(ScrollAmount) >= WHEEL_DELTA) then
+        if ScrollAmount > 0 then
+          for I := 1 to ScrollAmount div WHEEL_DELTA do
+          begin
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate + [PTCMouseButton7], True, PTCMouseButton7));
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate, False, PTCMouseButton7));
+          end
+        else
+          for I := 1 to Abs(ScrollAmount) div WHEEL_DELTA do
+          begin
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate + [PTCMouseButton6], True, PTCMouseButton6));
+            FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(TranslatedXPos, TranslatedYPos, 0, 0, cstate, False, PTCMouseButton6));
+          end;
+
       FPreviousMouseX := TranslatedXPos;
       FPreviousMouseY := TranslatedYPos;
       FPreviousMouseButtonState := PTCMouseButtonState;

+ 160 - 52
packages/ptc/src/win32/base/win32window.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2012  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2012, 2016, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -46,6 +46,8 @@ begin
   defaults;
   FWindow := window;
   FManaged := False;
+  FIsUnicode := IsWindowUnicode(window);
+  LOG('IsUnicode', IsUnicode);
 end;
 
 function WndProcSingleThreaded(hWnd: HWND; message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; forward;
@@ -59,33 +61,73 @@ var
   rectangle: RECT;
   display_width, display_height: Integer;
   wc: WNDCLASSEXA;
+  wcw: WNDCLASSEXW;
+  WinVer: OSVERSIONINFO;
+  AWndClassW, ATitleW: WideString;
 begin
   LOG('creating managed window');
   Defaults;
   FMultithreaded := AMultithreaded;
   try
+    FillChar(WinVer, SizeOf(WinVer), 0);
+    WinVer.dwOSVersionInfoSize := SizeOf(WinVer);
+    if not GetVersionEx(WinVer) then
+      raise TPTCError.Create('GetVersionEx failed');
+    { Win32s on Windows 3.1 and Win32 on Windows 95/98/ME don't support unicode }
+    FIsUnicode := (WinVer.dwPlatformId <> VER_PLATFORM_WIN32s) and
+      (WinVer.dwPlatformId <> VER_PLATFORM_WIN32_WINDOWS);
+    LOG('IsUnicode', IsUnicode);
+
     FInterceptClose := AInterceptClose;
     program_instance := GetModuleHandle(nil);
 {    library_instance := program_instance;}
-    wc.cbSize := SizeOf(wc);
-    wc.hInstance := program_instance;
-    wc.lpszClassName := PChar(AWndClass);
-    wc.style := AClassStyle;
-    wc.hIcon := 0{LoadIcon(library_instance, 'IDI_PTC_ICON')};
-    wc.hIconSm := 0;
-    wc.lpszMenuName := nil;
-    wc.cbClsExtra := 0;
-    wc.cbWndExtra := 0;
-    wc.hbrBackground := 0;{(HBRUSH) GetStockObject(BLACK_BRUSH)}
-    if AMultithreaded then
-      wc.lpfnWndProc := @WndProcMultiThreaded
-    else
-      wc.lpfnWndProc := @WndProcSingleThreaded;
-    if ACursor then
-      wc.hCursor := LoadCursor(0, IDC_ARROW)
+    if IsUnicode then
+    begin
+      AWndClassW := AWndClass;
+      ATitleW := ATitle;
+
+      wcw.cbSize := SizeOf(wcw);
+      wcw.hInstance := program_instance;
+      wcw.lpszClassName := PWideChar(AWndClassW);
+      wcw.style := AClassStyle;
+      wcw.hIcon := 0{LoadIcon(library_instance, 'IDI_PTC_ICON')};
+      wcw.hIconSm := 0;
+      wcw.lpszMenuName := nil;
+      wcw.cbClsExtra := 0;
+      wcw.cbWndExtra := 0;
+      wcw.hbrBackground := 0;{(HBRUSH) GetStockObject(BLACK_BRUSH)}
+      if AMultithreaded then
+        wcw.lpfnWndProc := @WndProcMultiThreaded
+      else
+        wcw.lpfnWndProc := @WndProcSingleThreaded;
+      if ACursor then
+        wcw.hCursor := LoadCursorW(0, PWideChar(IDC_ARROW))
+      else
+        wcw.hCursor := 0;
+      RegisterClassExW(wcw);
+    end
     else
-      wc.hCursor := 0;
-    RegisterClassExA(wc);
+    begin
+      wc.cbSize := SizeOf(wc);
+      wc.hInstance := program_instance;
+      wc.lpszClassName := PChar(AWndClass);
+      wc.style := AClassStyle;
+      wc.hIcon := 0{LoadIcon(library_instance, 'IDI_PTC_ICON')};
+      wc.hIconSm := 0;
+      wc.lpszMenuName := nil;
+      wc.cbClsExtra := 0;
+      wc.cbWndExtra := 0;
+      wc.hbrBackground := 0;{(HBRUSH) GetStockObject(BLACK_BRUSH)}
+      if AMultithreaded then
+        wc.lpfnWndProc := @WndProcMultiThreaded
+      else
+        wc.lpfnWndProc := @WndProcSingleThreaded;
+      if ACursor then
+        wc.hCursor := LoadCursorA(0, IDC_ARROW)
+      else
+        wc.hCursor := 0;
+      RegisterClassExA(wc);
+    end;
     with rectangle do
     begin
       left := 0;
@@ -117,7 +159,10 @@ begin
     end
     else
     begin
-      FWindow := CreateWindowExA(FExtra, PChar(FName), PChar(FTitle), FStyle, FX, FY, FWidth, FHeight, 0, 0, 0, Self);
+      if IsUnicode then
+        FWindow := CreateWindowExW(FExtra, PWideChar(AWndClassW), PWideChar(ATitleW), FStyle, FX, FY, FWidth, FHeight, 0, 0, 0, Self)
+      else
+        FWindow := CreateWindowExA(FExtra, PChar(FName), PChar(FTitle), FStyle, FX, FY, FWidth, FHeight, 0, 0, 0, Self);
       if not IsWindow(FWindow) then
         raise TPTCError.Create('could not create window');
       ShowWindow(FWindow, FShow);
@@ -140,16 +185,20 @@ end;
 procedure TWin32Window.Cursor(AFlag: Boolean);
 begin
   if AFlag then
-  begin
-//    SetClassLong(FWindow, GCL_HCURSOR, LoadCursor(0, IDC_ARROW));
-    SetClassLongPtr(FWindow, GCLP_HCURSOR, LoadCursor(0, IDC_ARROW));
-  end
+    if IsUnicode then
+      SetClassLongPtrW(FWindow, GCLP_HCURSOR, LoadCursorW(0, PWideChar(IDC_ARROW)))
+    else
+      SetClassLongPtrA(FWindow, GCLP_HCURSOR, LoadCursorA(0, IDC_ARROW))
   else
-  begin
-//    SetClassLong(FWindow, GCL_HCURSOR, 0);
-    SetClassLongPtr(FWindow, GCLP_HCURSOR, 0);
-  end;
-  SendMessage(FWindow, WM_SETCURSOR, 0, 0);
+    if IsUnicode then
+      SetClassLongPtrW(FWindow, GCLP_HCURSOR, 0)
+    else
+      SetClassLongPtrA(FWindow, GCLP_HCURSOR, 0);
+
+  if IsUnicode then
+    SendMessageW(FWindow, WM_SETCURSOR, 0, 0)
+  else
+    SendMessageA(FWindow, WM_SETCURSOR, 0, 0);
 end;
 
 procedure TWin32Window.ConfineCursor(AFlag: Boolean);
@@ -216,18 +265,43 @@ begin
     { updated to pump all window messages, and not just for our FWindow;
       this fixes keyboard layout switching and maybe other bugs and side effects...
       Seems like Windows wants everything pumped :) }
+
+    { TranslateMessage isn't called, because it's incompatible with the
+      ToAscii/ToUnicode functions, which we use for translating keys to
+      characters. Both ToAscii/ToUnicode and TranslateMessage modify the kernel
+      key state, in such a way, which assumes that only one of these functions
+      is called per key event, so when both are called, they kill the dead key
+      support (because the dead key pressed state is toggled twice or something
+      like that). TODO: maybe we should call TranslateMessage for windows, which
+      aren't managed by us? }
     if AWaitForMessage then
     begin
-      GetMessage(message, {FWindow}0, 0, 0);
-      TranslateMessage(message);
-      DispatchMessage(message);
-    end
-    else
-      while PeekMessage(message, {FWindow}0, 0, 0, PM_REMOVE) do
+      if IsUnicode then
       begin
-        TranslateMessage(message);
-        DispatchMessage(message);
+        GetMessageW(message, {FWindow}0, 0, 0);
+        //TranslateMessage(message);
+        DispatchMessageW(message);
+      end
+      else
+      begin
+        GetMessageA(message, {FWindow}0, 0, 0);
+        //TranslateMessage(message);
+        DispatchMessageA(message);
       end;
+    end
+    else
+      if IsUnicode then
+        while PeekMessageW(message, {FWindow}0, 0, 0, PM_REMOVE) do
+        begin
+          //TranslateMessage(message);
+          DispatchMessageW(message);
+        end
+      else
+        while PeekMessageA(message, {FWindow}0, 0, 0, PM_REMOVE) do
+        begin
+          //TranslateMessage(message);
+          DispatchMessageA(message);
+        end;
   end
   else
     Sleep(0);
@@ -251,7 +325,10 @@ begin
       begin
         pCreate := PCREATESTRUCT(lParam);
         WindowObject := TWin32Window(pCreate^.lpCreateParams);
-        SetWindowLongPtr(hWnd, GWLP_USERDATA, LONG_PTR(WindowObject));
+        if IsWindowUnicode(hWnd) then
+          SetWindowLongPtrW(hWnd, GWLP_USERDATA, LONG_PTR(WindowObject))
+        else
+          SetWindowLongPtrA(hWnd, GWLP_USERDATA, LONG_PTR(WindowObject));
         Result := WindowObject.WMCreate(hWnd, message, wParam, lParam);
       end;
     WM_DESTROY:
@@ -259,22 +336,35 @@ begin
         WindowObject := TWin32Window(GetWindowLongPtr(hWnd, GWLP_USERDATA));
         Result := WindowObject.WMDestroy(hWnd, message, wParam, lParam);
       end;
+    WM_MOUSEMOVE,
+    WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDBLCLK,
+    WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MBUTTONDBLCLK,
+    WM_RBUTTONDOWN, WM_RBUTTONUP, WM_RBUTTONDBLCLK,
+    WM_XBUTTONDOWN, WM_XBUTTONUP, WM_XBUTTONDBLCLK,
+    WM_MOUSEWHEEL, WM_MOUSEHWHEEL:
+      Result := 0;
     WM_SYSCOMMAND:
       begin
         { this fixes the pausing of the application when the Alt or F10 key is pressed }
         if wParam = SC_KEYMENU then
-	  Result := 0
-	else
-          Result := DefWindowProcA(hWnd, message, wParam, lParam);
+          Result := 0
+        else
+          if IsWindowUnicode(hWnd) then
+            Result := DefWindowProcW(hWnd, message, wParam, lParam)
+          else
+            Result := DefWindowProcA(hWnd, message, wParam, lParam);
       end;
     WM_SETCURSOR: begin
       if (LOWORD(lParam) = HTCLIENT) and (GetClassLongPtr(hWnd, GCLP_HCURSOR) = 0) then
       begin
         SetCursor(0);
-	Result := 1;
+        Result := 1;
       end
       else
-        Result := DefWindowProcA(hWnd, message, wParam, lParam);
+        if IsWindowUnicode(hWnd) then
+          Result := DefWindowProcW(hWnd, message, wParam, lParam)
+        else
+          Result := DefWindowProcA(hWnd, message, wParam, lParam);
     end;
     WM_CLOSE: begin
       LOG('TWin32Window WM_CLOSE');
@@ -285,7 +375,10 @@ begin
         Halt(0);
     end;
     else
-      Result := DefWindowProcA(hWnd, message, wParam, lParam);
+      if IsWindowUnicode(hWnd) then
+        Result := DefWindowProcW(hWnd, message, wParam, lParam)
+      else
+        Result := DefWindowProcA(hWnd, message, wParam, lParam);
   end;
 end;
 
@@ -297,18 +390,24 @@ begin
       begin
         { this fixes the pausing of the application when the Alt or F10 key is pressed }
         if wParam = SC_KEYMENU then
-	  Result := 0
-	else
-          Result := DefWindowProcA(hWnd, message, wParam, lParam);
+          Result := 0
+        else
+          if IsWindowUnicode(hWnd) then
+            Result := DefWindowProcW(hWnd, message, wParam, lParam)
+          else
+            Result := DefWindowProcA(hWnd, message, wParam, lParam);
       end;
     WM_SETCURSOR: begin
       if (LOWORD(lParam) = HTCLIENT) and (GetClassLongPtr(hWnd, GCLP_HCURSOR) = 0) then
       begin
         SetCursor(0);
-	Result := 1;
+        Result := 1;
       end
       else
-        Result := DefWindowProcA(hWnd, message, wParam, lParam);
+        if IsWindowUnicode(hWnd) then
+          Result := DefWindowProcW(hWnd, message, wParam, lParam)
+        else
+          Result := DefWindowProcA(hWnd, message, wParam, lParam);
     end;
     WM_DESTROY: begin
       LOG('TWin32Window WM_DESTROY');
@@ -319,7 +418,10 @@ begin
       Halt(0);
     end;
     else
-      Result := DefWindowProcA(hWnd, message, wParam, lParam);
+      if IsWindowUnicode(hWnd) then
+        Result := DefWindowProcW(hWnd, message, wParam, lParam)
+      else
+        Result := DefWindowProcA(hWnd, message, wParam, lParam);
   end;
 end;
 
@@ -406,10 +508,16 @@ end;
 
 function TWin32Window.WMCreate(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
 begin
-  Result := DefWindowProcA(hWnd, uMsg, wParam, lParam);
+  if IsUnicode then
+    Result := DefWindowProcW(hWnd, uMsg, wParam, lParam)
+  else
+    Result := DefWindowProcA(hWnd, uMsg, wParam, lParam);
 end;
 
 function TWin32Window.WMDestroy(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
 begin
-  Result := DefWindowProcA(hWnd, uMsg, wParam, lParam);
+  if IsUnicode then
+    Result := DefWindowProcW(hWnd, uMsg, wParam, lParam)
+  else
+    Result := DefWindowProcA(hWnd, uMsg, wParam, lParam);
 end;

+ 3 - 1
packages/ptc/src/win32/base/win32windowd.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009, 2010, 2012  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009, 2010, 2012, 2017  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -48,6 +48,7 @@ type
     FMultithreaded: Boolean;
     FCursorConfineInEffect: Boolean;
     FInterceptClose: Boolean;
+    FIsUnicode: Boolean;
 
 {    class function WndProcSingleThreaded(hWnd: HWND; message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;
     class function WndProcMultiThreaded(hWnd: HWND; message: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; StdCall;}
@@ -73,4 +74,5 @@ type
     property Managed: Boolean read FManaged;
     property Multithreaded: Boolean read FMultithreaded;
     property InterceptClose: Boolean read FInterceptClose write FInterceptClose;
+    property IsUnicode: Boolean read FIsUnicode;
   end;

+ 1 - 1
packages/ptc/src/win32/directx/p_ddraw.pp

@@ -2967,7 +2967,7 @@ const
 (*
  * DirectDraw supports deinterlacing of overlay surfaces
  *)
-  DDFXCAPS_OVERLAYDEINTERLACE		= $20000000;
+  DDFXCAPS_OVERLAYDEINTERLACE     = $20000000;
 
 (*
  * Driver can do alpha blending for blits.

+ 4829 - 0
packages/ptc/src/win32/directx/p_dinput.pp

@@ -0,0 +1,4829 @@
+(****************************************************************************
+ *
+ *  Copyright (C) 1996-2002 Microsoft Corporation.  All Rights Reserved.
+ *
+ *  File:       dinput.h
+ *  Content:    DirectInput include file
+ *
+ ****************************************************************************)
+
+unit p_dinput;
+
+{$MODE objfpc}{$H+}
+{$MACRO on}
+{$PACKRECORDS c}
+
+{$MODESWITCH NESTEDCOMMENTS-}
+
+interface
+
+uses
+  windows;
+
+//#ifndef __DINPUT_INCLUDED__
+//#define __DINPUT_INCLUDED__
+//
+//#include <winapifamily.h>
+//
+//#ifndef DIJ_RINGZERO
+//
+//#ifdef _WIN32
+//#define COM_NO_WINDOWS_H
+//#include <objbase.h>
+//#endif
+//
+//#endif /* DIJ_RINGZERO */
+//
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+//
+//
+//#pragma region Desktop Family
+//#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
+
+
+
+
+(*
+ *  To build applications for older versions of DirectInput
+ *
+ *  #define DIRECTINPUT_VERSION [ 0x0300 | 0x0500 | 0x0700 ]
+ *
+ *  before #include <dinput.h>.  By default, #include <dinput.h>
+ *  will produce a DirectX 8-compatible header file.
+ *
+ *)
+
+{$DEFINE DIRECTINPUT_HEADER_VERSION:=$0800}
+{$IFNDEF DIRECTINPUT_VERSION}
+{$DEFINE DIRECTINPUT_VERSION:=DIRECTINPUT_HEADER_VERSION}
+//#pragma message(__FILE__ ": DIRECTINPUT_VERSION undefined. Defaulting to version 0x0800")
+{$ENDIF}
+
+//#ifndef DIJ_RINGZERO
+
+(****************************************************************************
+ *
+ *      Class IDs
+ *
+ ****************************************************************************)
+
+const
+  CLSID_DirectInput       : TGuid = '{25E609E0-B259-11CF-BFC7-444553540000}';
+  CLSID_DirectInputDevice : TGuid = '{25E609E1-B259-11CF-BFC7-444553540000}';
+
+  CLSID_DirectInput8      : TGuid = '{25E609E4-B259-11CF-BFC7-444553540000}';
+  CLSID_DirectInputDevice8: TGuid = '{25E609E5-B259-11CF-BFC7-444553540000}';
+
+(****************************************************************************
+ *
+ *      Interfaces
+ *
+ ****************************************************************************)
+
+  IID_IDirectInputA       : TIID = '{89521360-AA8A-11CF-BFC7-444553540000}';
+  IID_IDirectInputW       : TIID = '{89521361-AA8A-11CF-BFC7-444553540000}';
+  IID_IDirectInput2A      : TIID = '{5944E662-AA8A-11CF-BFC7-444553540000}';
+  IID_IDirectInput2W      : TIID = '{5944E663-AA8A-11CF-BFC7-444553540000}';
+  IID_IDirectInput7A      : TIID = '{9A4CB684-236D-11D3-8E9D-00C04F6844AE}';
+  IID_IDirectInput7W      : TIID = '{9A4CB685-236D-11D3-8E9D-00C04F6844AE}';
+  IID_IDirectInput8A      : TIID = '{BF798030-483A-4DA2-AA99-5D64ED369700}';
+  IID_IDirectInput8W      : TIID = '{BF798031-483A-4DA2-AA99-5D64ED369700}';
+  IID_IDirectInputDeviceA : TIID = '{5944E680-C92E-11CF-BFC7-444553540000}';
+  IID_IDirectInputDeviceW : TIID = '{5944E681-C92E-11CF-BFC7-444553540000}';
+  IID_IDirectInputDevice2A: TIID = '{5944E682-C92E-11CF-BFC7-444553540000}';
+  IID_IDirectInputDevice2W: TIID = '{5944E683-C92E-11CF-BFC7-444553540000}';
+  IID_IDirectInputDevice7A: TIID = '{57D7C6BC-2356-11D3-8E9D-00C04F6844AE}';
+  IID_IDirectInputDevice7W: TIID = '{57D7C6BD-2356-11D3-8E9D-00C04F6844AE}';
+  IID_IDirectInputDevice8A: TIID = '{54D41080-DC15-4833-A41B-748F73A38179}';
+  IID_IDirectInputDevice8W: TIID = '{54D41081-DC15-4833-A41B-748F73A38179}';
+  IID_IDirectInputEffect  : TIID = '{E7E1F7C0-88D2-11D0-9AD0-00A0C9A06E35}';
+
+(****************************************************************************
+ *
+ *      Predefined object types
+ *
+ ****************************************************************************)
+
+  GUID_XAxis  : TGuid = '{A36D02E0-C9F3-11CF-BFC7-444553540000}';
+  GUID_YAxis  : TGuid = '{A36D02E1-C9F3-11CF-BFC7-444553540000}';
+  GUID_ZAxis  : TGuid = '{A36D02E2-C9F3-11CF-BFC7-444553540000}';
+  GUID_RxAxis : TGuid = '{A36D02F4-C9F3-11CF-BFC7-444553540000}';
+  GUID_RyAxis : TGuid = '{A36D02F5-C9F3-11CF-BFC7-444553540000}';
+  GUID_RzAxis : TGuid = '{A36D02E3-C9F3-11CF-BFC7-444553540000}';
+  GUID_Slider : TGuid = '{A36D02E4-C9F3-11CF-BFC7-444553540000}';
+
+  GUID_Button : TGuid = '{A36D02F0-C9F3-11CF-BFC7-444553540000}';
+  GUID_Key    : TGuid = '{55728220-D33C-11CF-BFC7-444553540000}';
+
+  GUID_POV    : TGuid = '{A36D02F2-C9F3-11CF-BFC7-444553540000}';
+
+  GUID_Unknown: TGuid = '{A36D02F3-C9F3-11CF-BFC7-444553540000}';
+
+(****************************************************************************
+ *
+ *      Predefined product GUIDs
+ *
+ ****************************************************************************)
+
+  GUID_SysMouse      : TGuid = '{6F1D2B60-D5A0-11CF-BFC7-444553540000}';
+  GUID_SysKeyboard   : TGuid = '{6F1D2B61-D5A0-11CF-BFC7-444553540000}';
+  GUID_Joystick      : TGuid = '{6F1D2B70-D5A0-11CF-BFC7-444553540000}';
+  GUID_SysMouseEm    : TGuid = '{6F1D2B80-D5A0-11CF-BFC7-444553540000}';
+  GUID_SysMouseEm2   : TGuid = '{6F1D2B81-D5A0-11CF-BFC7-444553540000}';
+  GUID_SysKeyboardEm : TGuid = '{6F1D2B82-D5A0-11CF-BFC7-444553540000}';
+  GUID_SysKeyboardEm2: TGuid = '{6F1D2B83-D5A0-11CF-BFC7-444553540000}';
+
+(****************************************************************************
+ *
+ *      Predefined force feedback effects
+ *
+ ****************************************************************************)
+
+  GUID_ConstantForce: TGuid = '{13541C20-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_RampForce    : TGuid = '{13541C21-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Square       : TGuid = '{13541C22-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Sine         : TGuid = '{13541C23-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Triangle     : TGuid = '{13541C24-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_SawtoothUp   : TGuid = '{13541C25-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_SawtoothDown : TGuid = '{13541C26-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Spring       : TGuid = '{13541C27-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Damper       : TGuid = '{13541C28-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Inertia      : TGuid = '{13541C29-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_Friction     : TGuid = '{13541C2A-8E33-11D0-9AD0-00A0C9A06E35}';
+  GUID_CustomForce  : TGuid = '{13541C2B-8E33-11D0-9AD0-00A0C9A06E35}';
+
+//#endif /* DIJ_RINGZERO */
+
+(****************************************************************************
+ *
+ *      Interfaces and Structures...
+ *
+ ****************************************************************************)
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+
+(****************************************************************************
+ *
+ *      IDirectInputEffect
+ *
+ ****************************************************************************)
+
+  DIEFT_ALL                = $00000000;
+
+  DIEFT_CONSTANTFORCE      = $00000001;
+  DIEFT_RAMPFORCE          = $00000002;
+  DIEFT_PERIODIC           = $00000003;
+  DIEFT_CONDITION          = $00000004;
+  DIEFT_CUSTOMFORCE        = $00000005;
+  DIEFT_HARDWARE           = $000000FF;
+  DIEFT_FFATTACK           = $00000200;
+  DIEFT_FFFADE             = $00000400;
+  DIEFT_SATURATION         = $00000800;
+  DIEFT_POSNEGCOEFFICIENTS = $00001000;
+  DIEFT_POSNEGSATURATION   = $00002000;
+  DIEFT_DEADBAND           = $00004000;
+  DIEFT_STARTDELAY         = $00008000;
+//#define DIEFT_GETTYPE(n)            LOBYTE(n)
+type
+  DIEFT_GETTYPE            = byte;
+
+const
+  DI_DEGREES               = 100;
+  DI_FFNOMINALMAX          = 10000;
+  DI_SECONDS               = 1000000;
+
+type
+  LPCDICONSTANTFORCE = ^TDICONSTANTFORCE;
+  PCDICONSTANTFORCE = ^TDICONSTANTFORCE;
+  LPDICONSTANTFORCE = ^TDICONSTANTFORCE;
+  PDICONSTANTFORCE = ^TDICONSTANTFORCE;
+  TDICONSTANTFORCE = record
+    lMagnitude: LONG;
+  end;
+
+  LPCDIRAMPFORCE = ^TDIRAMPFORCE;
+  PCDIRAMPFORCE = ^TDIRAMPFORCE;
+  LPDIRAMPFORCE = ^TDIRAMPFORCE;
+  PDIRAMPFORCE = ^TDIRAMPFORCE;
+  TDIRAMPFORCE = record
+    lStart: LONG;
+    lEnd  : LONG;
+  end;
+
+  LPCDIPERIODIC = ^TDIPERIODIC;
+  PCDIPERIODIC = ^TDIPERIODIC;
+  LPDIPERIODIC = ^TDIPERIODIC;
+  PDIPERIODIC = ^TDIPERIODIC;
+  TDIPERIODIC = record
+    dwMagnitude: DWORD;
+    lOffset: LONG;
+    dwPhase: DWORD;
+    dwPeriod: DWORD;
+  end;
+
+  LPCDICONDITION = ^TDICONDITION;
+  PCDICONDITION = ^TDICONDITION;
+  LPDICONDITION = ^TDICONDITION;
+  PDICONDITION = ^TDICONDITION;
+  TDICONDITION = record
+    lOffset: LONG;
+    lPositiveCoefficient: LONG;
+    lNegativeCoefficient: LONG;
+    dwPositiveSaturation: DWORD;
+    dwNegativeSaturation: DWORD;
+    lDeadBand: LONG;
+  end;
+
+  LPCDICUSTOMFORCE = ^TDICUSTOMFORCE;
+  PCDICUSTOMFORCE = ^TDICUSTOMFORCE;
+  LPDICUSTOMFORCE = ^TDICUSTOMFORCE;
+  PDICUSTOMFORCE = ^TDICUSTOMFORCE;
+  TDICUSTOMFORCE = record
+    cChannels: DWORD;
+    dwSamplePeriod: DWORD;
+    cSamples: DWORD;
+    rglForceData: LPLONG
+  end;
+
+
+  LPCDIENVELOPE = ^TDIENVELOPE;
+  PCDIENVELOPE = ^TDIENVELOPE;
+  LPDIENVELOPE = ^TDIENVELOPE;
+  PDIENVELOPE = ^TDIENVELOPE;
+  TDIENVELOPE = record
+    dwSize: DWORD;            { sizeof(DIENVELOPE)   }
+    dwAttackLevel: DWORD;
+    dwAttackTime: DWORD;      { Microseconds         }
+    dwFadeLevel: DWORD;
+    dwFadeTime: DWORD;        { Microseconds         }
+  end;
+
+
+{ This structure is defined for DirectX 5.0 compatibility }
+  LPCDIEFFECT_DX5 = ^TDIEFFECT_DX5;
+  PCDIEFFECT_DX5 = ^TDIEFFECT_DX5;
+  LPDIEFFECT_DX5 = ^TDIEFFECT_DX5;
+  PDIEFFECT_DX5 = ^TDIEFFECT_DX5;
+  TDIEFFECT_DX5 = record
+    dwSize: DWORD;                   { sizeof(DIEFFECT_DX5) }
+    dwFlags: DWORD;                  { DIEFF_*              }
+    dwDuration: DWORD;               { Microseconds         }
+    dwSamplePeriod: DWORD;           { Microseconds         }
+    dwGain: DWORD;
+    dwTriggerButton: DWORD;          { or DIEB_NOTRIGGER    }
+    dwTriggerRepeatInterval: DWORD;  { Microseconds         }
+    cAxes: DWORD;                    { Number of axes       }
+    rgdwAxes: LPDWORD;               { Array of axes        }
+    rglDirection: LPLONG;            { Array of directions  }
+    lpEnvelope: LPDIENVELOPE;        { Optional             }
+    cbTypeSpecificParams: DWORD;     { Size of params       }
+    lpvTypeSpecificParams: LPVOID;   { Pointer to params    }
+  end;
+
+  LPCDIEFFECT = ^TDIEFFECT;
+  PCDIEFFECT = ^TDIEFFECT;
+  LPDIEFFECT = ^TDIEFFECT;
+  PDIEFFECT = ^TDIEFFECT;
+  TDIEFFECT = record
+    dwSize: DWORD;                   { sizeof(DIEFFECT)     }
+    dwFlags: DWORD;                  { DIEFF_*              }
+    dwDuration: DWORD;               { Microseconds         }
+    dwSamplePeriod: DWORD;           { Microseconds         }
+    dwGain: DWORD;
+    dwTriggerButton: DWORD;          { or DIEB_NOTRIGGER    }
+    dwTriggerRepeatInterval: DWORD;  { Microseconds         }
+    cAxes: DWORD;                    { Number of axes       }
+    rgdwAxes: LPDWORD;               { Array of axes        }
+    rglDirection: LPLONG;            { Array of directions  }
+    lpEnvelope: LPDIENVELOPE;        { Optional             }
+    cbTypeSpecificParams: DWORD;     { Size of params       }
+    lpvTypeSpecificParams: LPVOID;   { Pointer to params    }
+{$IF DIRECTINPUT_VERSION >= $0600}
+    dwStartDelay: DWORD;             { Microseconds         }
+{$ENDIF} { DIRECTINPUT_VERSION >= $0600 }
+  end;
+  LPDIEFFECT_DX6 = LPDIEFFECT;
+  TDIEFFECT_DX6 = TDIEFFECT;
+
+
+{$IF DIRECTINPUT_VERSION >= $0700}
+//#ifndef DIJ_RINGZERO
+  LPCDIFILEEFFECT= ^TDIFILEEFFECT;
+  PCDIFILEEFFECT= ^TDIFILEEFFECT;
+  LPDIFILEEFFECT = ^TDIFILEEFFECT;
+  PDIFILEEFFECT = ^TDIFILEEFFECT;
+  TDIFILEEFFECT = record
+    dwSize: DWORD;
+    GuidEffect: GUID;
+    lpDiEffect: LPCDIEFFECT;
+    szFriendlyName: array [0..MAX_PATH-1] of CHAR;
+  end;
+//typedef BOOL (FAR PASCAL * LPDIENUMEFFECTSINFILECALLBACK)(LPCDIFILEEFFECT , LPVOID);
+  LPDIENUMEFFECTSINFILECALLBACK = function(lpDiFileEf: LPCDIFILEEFFECT; pvRef: LPVOID): BOOL; stdcall;
+//#endif /* DIJ_RINGZERO */
+{$ENDIF} { DIRECTINPUT_VERSION >= $0700 }
+
+const
+  DIEFF_OBJECTIDS             = $00000001;
+  DIEFF_OBJECTOFFSETS         = $00000002;
+  DIEFF_CARTESIAN             = $00000010;
+  DIEFF_POLAR                 = $00000020;
+  DIEFF_SPHERICAL             = $00000040;
+
+  DIEP_DURATION               = $00000001;
+  DIEP_SAMPLEPERIOD           = $00000002;
+  DIEP_GAIN                   = $00000004;
+  DIEP_TRIGGERBUTTON          = $00000008;
+  DIEP_TRIGGERREPEATINTERVAL  = $00000010;
+  DIEP_AXES                   = $00000020;
+  DIEP_DIRECTION              = $00000040;
+  DIEP_ENVELOPE               = $00000080;
+  DIEP_TYPESPECIFICPARAMS     = $00000100;
+{$IF DIRECTINPUT_VERSION >= 0x0600}
+  DIEP_STARTDELAY             = $00000200;
+  DIEP_ALLPARAMS_DX5          = $000001FF;
+  DIEP_ALLPARAMS              = $000003FF;
+{$ELSE} { DIRECTINPUT_VERSION < 0x0600 }
+  DIEP_ALLPARAMS              = $000001FF;
+{$ENDIF} { DIRECTINPUT_VERSION < 0x0600 }
+  DIEP_START                  = $20000000;
+  DIEP_NORESTART              = $40000000;
+  DIEP_NODOWNLOAD             = $80000000;
+  DIEB_NOTRIGGER              = $FFFFFFFF;
+
+  DIES_SOLO                   = $00000001;
+  DIES_NODOWNLOAD             = $80000000;
+
+  DIEGES_PLAYING              = $00000001;
+  DIEGES_EMULATED             = $00000002;
+
+type
+  LPDIEFFESCAPE = ^TDIEFFESCAPE;
+  PDIEFFESCAPE = ^TDIEFFESCAPE;
+  TDIEFFESCAPE = record
+    dwSize: DWORD;
+    dwCommand: DWORD;
+    lpvInBuffer: LPVOID;
+    cbInBuffer: DWORD;
+    lpvOutBuffer: LPVOID;
+    cbOutBuffer: DWORD;
+  end;
+
+//#ifndef DIJ_RINGZERO
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputEffect
+
+//DECLARE_INTERFACE_(IDirectInputEffect, IUnknown)
+type
+  IDirectInputEffect = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputEffect methods ***)
+    function Initialize(hinst: HINST; dwVersion: DWORD; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function GetEffectGuid(pguid: LPGUID): HRESULT; stdcall;
+    function GetParameters(peff: LPDIEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+    function SetParameters(peff: LPCDIEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+    function Start(dwIterations, dwFlags: DWORD): HRESULT; stdcall;
+    function Stop: HRESULT; stdcall;
+    function GetEffectStatus(pdwFlags: LPDWORD): HRESULT; stdcall;
+    function Download: HRESULT; stdcall;
+    function Unload: HRESULT; stdcall;
+    function Escape(pesc: LPDIEFFESCAPE): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputEffect *LPDIRECTINPUTEFFECT;
+  LPDIRECTINPUTEFFECT = IDirectInputEffect;
+
+{#if !defined(__cplusplus) || defined(CINTERFACE)
+#define IDirectInputEffect_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+#define IDirectInputEffect_AddRef(p) (p)->lpVtbl->AddRef(p)
+#define IDirectInputEffect_Release(p) (p)->lpVtbl->Release(p)
+#define IDirectInputEffect_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+#define IDirectInputEffect_GetEffectGuid(p,a) (p)->lpVtbl->GetEffectGuid(p,a)
+#define IDirectInputEffect_GetParameters(p,a,b) (p)->lpVtbl->GetParameters(p,a,b)
+#define IDirectInputEffect_SetParameters(p,a,b) (p)->lpVtbl->SetParameters(p,a,b)
+#define IDirectInputEffect_Start(p,a,b) (p)->lpVtbl->Start(p,a,b)
+#define IDirectInputEffect_Stop(p) (p)->lpVtbl->Stop(p)
+#define IDirectInputEffect_GetEffectStatus(p,a) (p)->lpVtbl->GetEffectStatus(p,a)
+#define IDirectInputEffect_Download(p) (p)->lpVtbl->Download(p)
+#define IDirectInputEffect_Unload(p) (p)->lpVtbl->Unload(p)
+#define IDirectInputEffect_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+#else
+#define IDirectInputEffect_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+#define IDirectInputEffect_AddRef(p) (p)->AddRef()
+#define IDirectInputEffect_Release(p) (p)->Release()
+#define IDirectInputEffect_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+#define IDirectInputEffect_GetEffectGuid(p,a) (p)->GetEffectGuid(a)
+#define IDirectInputEffect_GetParameters(p,a,b) (p)->GetParameters(a,b)
+#define IDirectInputEffect_SetParameters(p,a,b) (p)->SetParameters(a,b)
+#define IDirectInputEffect_Start(p,a,b) (p)->Start(a,b)
+#define IDirectInputEffect_Stop(p) (p)->Stop()
+#define IDirectInputEffect_GetEffectStatus(p,a) (p)->GetEffectStatus(a)
+#define IDirectInputEffect_Download(p) (p)->Download()
+#define IDirectInputEffect_Unload(p) (p)->Unload()
+#define IDirectInputEffect_Escape(p,a) (p)->Escape(a)
+#endif}
+
+//#endif /* DIJ_RINGZERO */
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+
+(****************************************************************************
+ *
+ *      IDirectInputDevice
+ *
+ ****************************************************************************)
+
+{$IF DIRECTINPUT_VERSION <= $700}
+const
+  DIDEVTYPE_DEVICE   = 1;
+  DIDEVTYPE_MOUSE    = 2;
+  DIDEVTYPE_KEYBOARD = 3;
+  DIDEVTYPE_JOYSTICK = 4;
+
+{$ELSE}
+const
+  DI8DEVCLASS_ALL          = 0;
+  DI8DEVCLASS_DEVICE       = 1;
+  DI8DEVCLASS_POINTER      = 2;
+  DI8DEVCLASS_KEYBOARD     = 3;
+  DI8DEVCLASS_GAMECTRL     = 4;
+
+  DI8DEVTYPE_DEVICE        = $11;
+  DI8DEVTYPE_MOUSE         = $12;
+  DI8DEVTYPE_KEYBOARD      = $13;
+  DI8DEVTYPE_JOYSTICK      = $14;
+  DI8DEVTYPE_GAMEPAD       = $15;
+  DI8DEVTYPE_DRIVING       = $16;
+  DI8DEVTYPE_FLIGHT        = $17;
+  DI8DEVTYPE_1STPERSON     = $18;
+  DI8DEVTYPE_DEVICECTRL    = $19;
+  DI8DEVTYPE_SCREENPOINTER = $1A;
+  DI8DEVTYPE_REMOTE        = $1B;
+  DI8DEVTYPE_SUPPLEMENTAL  = $1C;
+{$ENDIF} { DIRECTINPUT_VERSION <= 0x700 }
+
+const
+  DIDEVTYPE_HID            = $00010000;
+
+{$IF DIRECTINPUT_VERSION <= $700}
+const
+  DIDEVTYPEMOUSE_UNKNOWN        = 1;
+  DIDEVTYPEMOUSE_TRADITIONAL    = 2;
+  DIDEVTYPEMOUSE_FINGERSTICK    = 3;
+  DIDEVTYPEMOUSE_TOUCHPAD       = 4;
+  DIDEVTYPEMOUSE_TRACKBALL      = 5;
+
+  DIDEVTYPEKEYBOARD_UNKNOWN     =  0;
+  DIDEVTYPEKEYBOARD_PCXT        =  1;
+  DIDEVTYPEKEYBOARD_OLIVETTI    =  2;
+  DIDEVTYPEKEYBOARD_PCAT        =  3;
+  DIDEVTYPEKEYBOARD_PCENH       =  4;
+  DIDEVTYPEKEYBOARD_NOKIA1050   =  5;
+  DIDEVTYPEKEYBOARD_NOKIA9140   =  6;
+  DIDEVTYPEKEYBOARD_NEC98       =  7;
+  DIDEVTYPEKEYBOARD_NEC98LAPTOP =  8;
+  DIDEVTYPEKEYBOARD_NEC98106    =  9;
+  DIDEVTYPEKEYBOARD_JAPAN106    = 10;
+  DIDEVTYPEKEYBOARD_JAPANAX     = 11;
+  DIDEVTYPEKEYBOARD_J3100       = 12;
+
+  DIDEVTYPEJOYSTICK_UNKNOWN     = 1;
+  DIDEVTYPEJOYSTICK_TRADITIONAL = 2;
+  DIDEVTYPEJOYSTICK_FLIGHTSTICK = 3;
+  DIDEVTYPEJOYSTICK_GAMEPAD     = 4;
+  DIDEVTYPEJOYSTICK_RUDDER      = 5;
+  DIDEVTYPEJOYSTICK_WHEEL       = 6;
+  DIDEVTYPEJOYSTICK_HEADTRACKER = 7;
+
+{$ELSE}
+const
+  DI8DEVTYPEMOUSE_UNKNOWN                       = 1;
+  DI8DEVTYPEMOUSE_TRADITIONAL                   = 2;
+  DI8DEVTYPEMOUSE_FINGERSTICK                   = 3;
+  DI8DEVTYPEMOUSE_TOUCHPAD                      = 4;
+  DI8DEVTYPEMOUSE_TRACKBALL                     = 5;
+  DI8DEVTYPEMOUSE_ABSOLUTE                      = 6;
+
+  DI8DEVTYPEKEYBOARD_UNKNOWN                    =  0;
+  DI8DEVTYPEKEYBOARD_PCXT                       =  1;
+  DI8DEVTYPEKEYBOARD_OLIVETTI                   =  2;
+  DI8DEVTYPEKEYBOARD_PCAT                       =  3;
+  DI8DEVTYPEKEYBOARD_PCENH                      =  4;
+  DI8DEVTYPEKEYBOARD_NOKIA1050                  =  5;
+  DI8DEVTYPEKEYBOARD_NOKIA9140                  =  6;
+  DI8DEVTYPEKEYBOARD_NEC98                      =  7;
+  DI8DEVTYPEKEYBOARD_NEC98LAPTOP                =  8;
+  DI8DEVTYPEKEYBOARD_NEC98106                   =  9;
+  DI8DEVTYPEKEYBOARD_JAPAN106                   = 10;
+  DI8DEVTYPEKEYBOARD_JAPANAX                    = 11;
+  DI8DEVTYPEKEYBOARD_J3100                      = 12;
+
+  DI8DEVTYPE_LIMITEDGAMESUBTYPE                 = 1;
+
+  DI8DEVTYPEJOYSTICK_LIMITED                    = DI8DEVTYPE_LIMITEDGAMESUBTYPE;
+  DI8DEVTYPEJOYSTICK_STANDARD                   = 2;
+
+  DI8DEVTYPEGAMEPAD_LIMITED                     = DI8DEVTYPE_LIMITEDGAMESUBTYPE;
+  DI8DEVTYPEGAMEPAD_STANDARD                    = 2;
+  DI8DEVTYPEGAMEPAD_TILT                        = 3;
+
+  DI8DEVTYPEDRIVING_LIMITED                     = DI8DEVTYPE_LIMITEDGAMESUBTYPE;
+  DI8DEVTYPEDRIVING_COMBINEDPEDALS              = 2;
+  DI8DEVTYPEDRIVING_DUALPEDALS                  = 3;
+  DI8DEVTYPEDRIVING_THREEPEDALS                 = 4;
+  DI8DEVTYPEDRIVING_HANDHELD                    = 5;
+
+  DI8DEVTYPEFLIGHT_LIMITED                      = DI8DEVTYPE_LIMITEDGAMESUBTYPE;
+  DI8DEVTYPEFLIGHT_STICK                        = 2;
+  DI8DEVTYPEFLIGHT_YOKE                         = 3;
+  DI8DEVTYPEFLIGHT_RC                           = 4;
+
+  DI8DEVTYPE1STPERSON_LIMITED                   = DI8DEVTYPE_LIMITEDGAMESUBTYPE;
+  DI8DEVTYPE1STPERSON_UNKNOWN                   = 2;
+  DI8DEVTYPE1STPERSON_SIXDOF                    = 3;
+  DI8DEVTYPE1STPERSON_SHOOTER                   = 4;
+
+  DI8DEVTYPESCREENPTR_UNKNOWN                   = 2;
+  DI8DEVTYPESCREENPTR_LIGHTGUN                  = 3;
+  DI8DEVTYPESCREENPTR_LIGHTPEN                  = 4;
+  DI8DEVTYPESCREENPTR_TOUCH                     = 5;
+
+  DI8DEVTYPEREMOTE_UNKNOWN                      = 2;
+
+  DI8DEVTYPEDEVICECTRL_UNKNOWN                  = 2;
+  DI8DEVTYPEDEVICECTRL_COMMSSELECTION           = 3;
+  DI8DEVTYPEDEVICECTRL_COMMSSELECTION_HARDWIRED = 4;
+
+  DI8DEVTYPESUPPLEMENTAL_UNKNOWN                =  2;
+  DI8DEVTYPESUPPLEMENTAL_2NDHANDCONTROLLER      =  3;
+  DI8DEVTYPESUPPLEMENTAL_HEADTRACKER            =  4;
+  DI8DEVTYPESUPPLEMENTAL_HANDTRACKER            =  5;
+  DI8DEVTYPESUPPLEMENTAL_SHIFTSTICKGATE         =  6;
+  DI8DEVTYPESUPPLEMENTAL_SHIFTER                =  7;
+  DI8DEVTYPESUPPLEMENTAL_THROTTLE               =  8;
+  DI8DEVTYPESUPPLEMENTAL_SPLITTHROTTLE          =  9;
+  DI8DEVTYPESUPPLEMENTAL_COMBINEDPEDALS         = 10;
+  DI8DEVTYPESUPPLEMENTAL_DUALPEDALS             = 11;
+  DI8DEVTYPESUPPLEMENTAL_THREEPEDALS            = 12;
+  DI8DEVTYPESUPPLEMENTAL_RUDDERPEDALS           = 13;
+{$ENDIF} { DIRECTINPUT_VERSION <= $700 }
+
+//#define GET_DIDEVICE_TYPE(dwDevType)    LOBYTE(dwDevType)
+type
+  GET_DIDEVICE_TYPE = byte;
+//#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType)
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+{ This structure is defined for DirectX 3.0 compatibility }
+type
+  LPDIDEVCAPS_DX3 = ^TDIDEVCAPS_DX3;
+  PDIDEVCAPS_DX3 = ^TDIDEVCAPS_DX3;
+  TDIDEVCAPS_DX3 = record
+    dwSize: DWORD;
+    dwFlags: DWORD;
+    dwDevType: DWORD;
+    dwAxes: DWORD;
+    dwButtons: DWORD;
+    dwPOVs: DWORD;
+  end;
+{$ENDIF} { DIRECTINPUT_VERSION >= 0x0500 }
+
+  LPDIDEVCAPS = ^TDIDEVCAPS;
+  PDIDEVCAPS = ^TDIDEVCAPS;
+  TDIDEVCAPS = record
+    dwSize: DWORD;
+    dwFlags: DWORD;
+    dwDevType: DWORD;
+    dwAxes: DWORD;
+    dwButtons: DWORD;
+    dwPOVs: DWORD;
+{$IF DIRECTINPUT_VERSION >= $0500}
+    dwFFSamplePeriod: DWORD;
+    dwFFMinTimeResolution: DWORD;
+    dwFirmwareRevision: DWORD;
+    dwHardwareRevision: DWORD;
+    dwFFDriverVersion: DWORD;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  end;
+
+const
+  DIDC_ATTACHED           = $00000001;
+  DIDC_POLLEDDEVICE       = $00000002;
+  DIDC_EMULATED           = $00000004;
+  DIDC_POLLEDDATAFORMAT   = $00000008;
+{$IF DIRECTINPUT_VERSION >= $0500}
+  DIDC_FORCEFEEDBACK      = $00000100;
+  DIDC_FFATTACK           = $00000200;
+  DIDC_FFFADE             = $00000400;
+  DIDC_SATURATION         = $00000800;
+  DIDC_POSNEGCOEFFICIENTS = $00001000;
+  DIDC_POSNEGSATURATION   = $00002000;
+  DIDC_DEADBAND           = $00004000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  DIDC_STARTDELAY         = $00008000;
+{$IF DIRECTINPUT_VERSION >= $050a}
+  DIDC_ALIAS              = $00010000;
+  DIDC_PHANTOM            = $00020000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+{$IF DIRECTINPUT_VERSION >= $0800}
+  DIDC_HIDDEN             = $00040000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+  DIDFT_ALL             = $00000000;
+
+  DIDFT_RELAXIS         = $00000001;
+  DIDFT_ABSAXIS         = $00000002;
+  DIDFT_AXIS            = $00000003;
+
+  DIDFT_PSHBUTTON       = $00000004;
+  DIDFT_TGLBUTTON       = $00000008;
+  DIDFT_BUTTON          = $0000000C;
+
+  DIDFT_POV             = $00000010;
+  DIDFT_COLLECTION      = $00000040;
+  DIDFT_NODATA          = $00000080;
+
+  DIDFT_ANYINSTANCE     = $00FFFF00;
+  DIDFT_INSTANCEMASK    = DIDFT_ANYINSTANCE;
+  //DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8)
+  //DIDFT_GETTYPE(n)     LOBYTE(n)
+type
+  DIDFT_GETTYPE = byte;
+  //DIDFT_GETINSTANCE(n) LOWORD((n) >> 8)
+const
+  DIDFT_FFACTUATOR      = $01000000;
+  DIDFT_FFEFFECTTRIGGER = $02000000;
+{$IF DIRECTINPUT_VERSION >= $050a}
+  DIDFT_OUTPUT          = $10000000;
+  DIDFT_VENDORDEFINED   = $04000000;
+  DIDFT_ALIAS           = $08000000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+//  DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8)
+  DIDFT_NOCOLLECTION      = $00FFFF00;
+
+//#ifndef DIJ_RINGZERO
+
+type
+  LPCDIOBJECTDATAFORMAT = ^TDIOBJECTDATAFORMAT;
+  PCDIOBJECTDATAFORMAT = ^TDIOBJECTDATAFORMAT;
+  LPDIOBJECTDATAFORMAT = ^TDIOBJECTDATAFORMAT;
+  PDIOBJECTDATAFORMAT = ^TDIOBJECTDATAFORMAT;
+  TDIOBJECTDATAFORMAT = record
+    pguid: PGuid; {const GUID *}
+    dwOfs: DWORD;
+    dwType: DWORD;
+    dwFlags: DWORD;
+  end;
+
+  LPCDIDATAFORMAT = ^TDIDATAFORMAT;
+  PCDIDATAFORMAT = ^TDIDATAFORMAT;
+  LPDIDATAFORMAT = ^TDIDATAFORMAT;
+  PDIDATAFORMAT = ^TDIDATAFORMAT;
+  TDIDATAFORMAT = record
+    dwSize: DWORD;
+    dwObjSize: DWORD;
+    dwFlags: DWORD;
+    dwDataSize: DWORD;
+    dwNumObjs: DWORD;
+    rgodf: LPDIOBJECTDATAFORMAT;
+  end;
+
+const
+  DIDF_ABSAXIS = $00000001;
+  DIDF_RELAXIS = $00000002;
+
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+//extern const DIDATAFORMAT c_dfDIMouse;
+var
+  c_dfDIMouse: TDIDATAFORMAT; cvar; external;
+
+{$IF DIRECTINPUT_VERSION >= $0700}
+//extern const DIDATAFORMAT c_dfDIMouse2;
+  c_dfDIMouse2: TDIDATAFORMAT; cvar; external;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0700 }
+
+//extern const DIDATAFORMAT c_dfDIKeyboard;
+  c_dfDIKeyboard: TDIDATAFORMAT; cvar; external;
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+//extern const DIDATAFORMAT c_dfDIJoystick;
+  c_dfDIJoystick: TDIDATAFORMAT; cvar; external;
+//extern const DIDATAFORMAT c_dfDIJoystick2;
+  c_dfDIJoystick2: TDIDATAFORMAT; cvar; external;
+{$ENDIF} { DIRECTINPUT_VERSION >= 0x0500 }
+
+//#ifdef __cplusplus
+//};
+//#endif
+
+
+{$IF DIRECTINPUT_VERSION > $0700}
+
+//#pragma warning(push)
+//#pragma warning(disable:4201)   // Nameless union / struct when compiled for C.
+
+type
+  LPDIACTIONA = ^TDIACTIONA;
+  PDIACTIONA = ^TDIACTIONA;
+  TDIACTIONA = record
+    uAppData: UINT_PTR;
+    dwSemantic: DWORD;
+    dwFlags: DWORD;  {OPTIONAL}
+    case Integer of
+      0: (
+        lptszActionName: LPCSTR;  {OPTIONAL}
+        guidInstance: GUID;  {OPTIONAL}
+        dwObjID: DWORD;  {OPTIONAL}
+        dwHow: DWORD; {OPTIONAL}
+      );
+      1: (
+        uResIdString: UINT  {OPTIONAL}
+      );
+  end;
+  LPDIACTIONW = ^TDIACTIONW;
+  PDIACTIONW = ^TDIACTIONW;
+  TDIACTIONW = record
+    uAppData: UINT_PTR;
+    dwSemantic: DWORD;
+    dwFlags: DWORD;  {OPTIONAL}
+    case Integer of
+      0: (
+        lptszActionName: LPCWSTR;  {OPTIONAL}
+        guidInstance: GUID;  {OPTIONAL}
+        dwObjID: DWORD;  {OPTIONAL}
+        dwHow: DWORD; {OPTIONAL}
+      );
+      1: (
+        uResIdString: UINT;  {OPTIONAL}
+      );
+  end;
+{$IFDEF UNICODE}
+  TDIACTION = TDIACTIONW;
+  LPDIACTION = LPDIACTIONW;
+  PDIACTION = PDIACTIONW;
+{$ELSE}
+  TDIACTION = TDIACTIONA;
+  LPDIACTION = LPDIACTIONA;
+  PDIACTION = PDIACTIONA;
+{$ENDIF} // UNICODE
+
+  LPCDIACTIONA = ^TDIACTIONA;
+  PCDIACTIONA = ^TDIACTIONA;
+  LPCDIACTIONW = ^TDIACTIONW;
+  PCDIACTIONW = ^TDIACTIONW;
+{$IFDEF UNICODE}
+  LPCDIACTION = LPCDIACTIONW;
+  PCDIACTION = PCDIACTIONW;
+{$ELSE}
+  LPCDIACTION = LPCDIACTIONA;
+  PCDIACTION = PCDIACTIONA;
+{$ENDIF} // UNICODE
+
+//#pragma warning(pop)
+
+const
+  DIA_FORCEFEEDBACK = $00000001;
+  DIA_APPMAPPED     = $00000002;
+  DIA_APPNOMAP      = $00000004;
+  DIA_NORANGE       = $00000008;
+  DIA_APPFIXED      = $00000010;
+
+  DIAH_UNMAPPED     = $00000000;
+  DIAH_USERCONFIG   = $00000001;
+  DIAH_APPREQUESTED = $00000002;
+  DIAH_HWAPP        = $00000004;
+  DIAH_HWDEFAULT    = $00000008;
+  DIAH_DEFAULT      = $00000020;
+  DIAH_ERROR        = $80000000;
+
+type
+  LPDIACTIONFORMATA = ^TDIACTIONFORMATA;
+  PDIACTIONFORMATA = ^TDIACTIONFORMATA;
+  TDIACTIONFORMATA = record
+    dwSize: DWORD;
+    dwActionSize: DWORD;
+    dwDataSize: DWORD;
+    dwNumActions: DWORD;
+    rgoAction: LPDIACTIONA;
+    guidActionMap: GUID;
+    dwGenre: DWORD;
+    dwBufferSize: DWORD;
+    lAxisMin: LONG;  {OPTIONAL}
+    lAxisMax: LONG;  {OPTIONAL}
+    hInstString: HINST;  {OPTIONAL}
+    ftTimeStamp: FILETIME;
+    dwCRC: DWORD;
+    tszActionMap: array [0..MAX_PATH-1] of CHAR;
+  end;
+  LPDIACTIONFORMATW = ^TDIACTIONFORMATW;
+  PDIACTIONFORMATW = ^TDIACTIONFORMATW;
+  TDIACTIONFORMATW = record
+    dwSize: DWORD;
+    dwActionSize: DWORD;
+    dwDataSize: DWORD;
+    dwNumActions: DWORD;
+    rgoAction: LPDIACTIONW;
+    guidActionMap: GUID;
+    dwGenre: DWORD;
+    dwBufferSize: DWORD;
+    lAxisMin: LONG;  {OPTIONAL}
+    lAxisMax: LONG;  {OPTIONAL}
+    hInstString: HINST;  {OPTIONAL}
+    ftTimeStamp: FILETIME;
+    dwCRC: DWORD;
+    tszActionMap: array [0..MAX_PATH-1] of WCHAR;
+  end;
+{$IFDEF UNICODE}
+  TDIACTIONFORMAT = TDIACTIONFORMATW;
+  LPDIACTIONFORMAT = LPDIACTIONFORMATW;
+  PDIACTIONFORMAT = PDIACTIONFORMATW;
+{$ELSE}
+  TDIACTIONFORMAT = TDIACTIONFORMATA;
+  LPDIACTIONFORMAT = LPDIACTIONFORMATA;
+  PDIACTIONFORMAT = PDIACTIONFORMATA;
+{$ENDIF} // UNICODE
+  LPCDIACTIONFORMATA = ^TDIACTIONFORMATA;
+  PCDIACTIONFORMATA = ^TDIACTIONFORMATA;
+  LPCDIACTIONFORMATW = ^TDIACTIONFORMATW;
+  PCDIACTIONFORMATW = ^TDIACTIONFORMATW;
+{$IFDEF UNICODE}
+  LPCDIACTIONFORMAT = LPCDIACTIONFORMATW;
+  PCDIACTIONFORMAT = PCDIACTIONFORMATW;
+{$ELSE}
+  LPCDIACTIONFORMAT = LPCDIACTIONFORMATA;
+  PCDIACTIONFORMAT = PCDIACTIONFORMATA;
+{$ENDIF} // UNICODE
+
+const
+  DIAFTS_NEWDEVICELOW     = $FFFFFFFF;
+  DIAFTS_NEWDEVICEHIGH    = $FFFFFFFF;
+  DIAFTS_UNUSEDDEVICELOW  = $00000000;
+  DIAFTS_UNUSEDDEVICEHIGH = $00000000;
+
+  DIDBAM_DEFAULT          = $00000000;
+  DIDBAM_PRESERVE         = $00000001;
+  DIDBAM_INITIALIZE       = $00000002;
+  DIDBAM_HWDEFAULTS       = $00000004;
+
+  DIDSAM_DEFAULT          = $00000000;
+  DIDSAM_NOUSER           = $00000001;
+  DIDSAM_FORCESAVE        = $00000002;
+
+  DICD_DEFAULT            = $00000000;
+  DICD_EDIT               = $00000001;
+
+(*
+ * The following definition is normally defined in d3dtypes.h
+ *)
+{$IFNDEF D3DCOLOR_DEFINED}
+type
+  D3DCOLOR = DWORD;
+{$DEFINE D3DCOLOR_DEFINED}
+{$ENDIF}
+
+  LPCDICOLORSET = ^TDICOLORSET;
+  PCDICOLORSET = ^TDICOLORSET;
+  LPDICOLORSET = ^TDICOLORSET;
+  PDICOLORSET = ^TDICOLORSET;
+  TDICOLORSET = record
+    dwSize: DWORD;
+    cTextFore: D3DCOLOR;
+    cTextHighlight: D3DCOLOR;
+    cCalloutLine: D3DCOLOR;
+    cCalloutHighlight: D3DCOLOR;
+    cBorder: D3DCOLOR;
+    cControlFill: D3DCOLOR;
+    cHighlightFill: D3DCOLOR;
+    cAreaFill: D3DCOLOR;
+  end;
+
+
+  LPDICONFIGUREDEVICESPARAMSA = ^TDICONFIGUREDEVICESPARAMSA;
+  PDICONFIGUREDEVICESPARAMSA = ^TDICONFIGUREDEVICESPARAMSA;
+  TDICONFIGUREDEVICESPARAMSA = record
+    dwSize: DWORD;
+    dwcUsers: DWORD;
+    lptszUserNames: LPSTR;
+    dwcFormats: DWORD;
+    lprgFormats: LPDIACTIONFORMATA;
+    hwnd: HWND;
+    dics: TDICOLORSET;
+    lpUnkDDSTarget: {IUnknown FAR *}IUnknown;
+  end;
+  LPDICONFIGUREDEVICESPARAMSW = ^TDICONFIGUREDEVICESPARAMSW;
+  PDICONFIGUREDEVICESPARAMSW = ^TDICONFIGUREDEVICESPARAMSW;
+  TDICONFIGUREDEVICESPARAMSW = record
+    dwSize: DWORD;
+    dwcUsers: DWORD;
+    lptszUserNames: LPWSTR;
+    dwcFormats: DWORD;
+    lprgFormats: LPDIACTIONFORMATW;
+    hwnd: HWND;
+    dics: TDICOLORSET;
+    lpUnkDDSTarget: {IUnknown FAR *}IUnknown;
+  end;
+{$IFDEF UNICODE}
+  TDICONFIGUREDEVICESPARAMS = TDICONFIGUREDEVICESPARAMSW;
+  LPDICONFIGUREDEVICESPARAMS = LPDICONFIGUREDEVICESPARAMSW;
+  PDICONFIGUREDEVICESPARAMS = PDICONFIGUREDEVICESPARAMSW;
+{$ELSE}
+  TDICONFIGUREDEVICESPARAMS = TDICONFIGUREDEVICESPARAMSA;
+  LPDICONFIGUREDEVICESPARAMS = LPDICONFIGUREDEVICESPARAMSA;
+  PDICONFIGUREDEVICESPARAMS = PDICONFIGUREDEVICESPARAMSA;
+{$ENDIF} // UNICODE
+  LPCDICONFIGUREDEVICESPARAMSA = ^TDICONFIGUREDEVICESPARAMSA;
+  PCDICONFIGUREDEVICESPARAMSA = ^TDICONFIGUREDEVICESPARAMSA;
+  LPCDICONFIGUREDEVICESPARAMSW = ^TDICONFIGUREDEVICESPARAMSW;
+  PCDICONFIGUREDEVICESPARAMSW = ^TDICONFIGUREDEVICESPARAMSW;
+{$IFDEF UNICODE}
+  LPCDICONFIGUREDEVICESPARAMS = LPCDICONFIGUREDEVICESPARAMSW;
+  PCDICONFIGUREDEVICESPARAMS = PCDICONFIGUREDEVICESPARAMSW;
+{$ELSE}
+  LPCDICONFIGUREDEVICESPARAMS = LPCDICONFIGUREDEVICESPARAMSA;
+  PCDICONFIGUREDEVICESPARAMS = PCDICONFIGUREDEVICESPARAMSA;
+{$ENDIF} // UNICODE
+
+
+const
+  DIDIFT_CONFIGURATION = $00000001;
+  DIDIFT_OVERLAY       = $00000002;
+
+  DIDAL_CENTERED      = $00000000;
+  DIDAL_LEFTALIGNED   = $00000001;
+  DIDAL_RIGHTALIGNED  = $00000002;
+  DIDAL_MIDDLE        = $00000000;
+  DIDAL_TOPALIGNED    = $00000004;
+  DIDAL_BOTTOMALIGNED = $00000008;
+
+type
+  LPDIDEVICEIMAGEINFOA = ^TDIDEVICEIMAGEINFOA;
+  PDIDEVICEIMAGEINFOA = ^TDIDEVICEIMAGEINFOA;
+  TDIDEVICEIMAGEINFOA = record
+    tszImagePath: array [0..MAX_PATH-1] of CHAR;
+    dwFlags: DWORD;
+    // These are valid if DIDIFT_OVERLAY is present in dwFlags.
+    dwViewID: DWORD;
+    rcOverlay: RECT;
+    dwObjID: DWORD;
+    dwcValidPts: DWORD;
+    rgptCalloutLine: array [0..4] of POINT;
+    rcCalloutRect: RECT;
+    dwTextAlign: DWORD;
+  end;
+  LPDIDEVICEIMAGEINFOW = ^TDIDEVICEIMAGEINFOW;
+  PDIDEVICEIMAGEINFOW = ^TDIDEVICEIMAGEINFOW;
+  TDIDEVICEIMAGEINFOW = record
+    tszImagePath: array [0..MAX_PATH-1] of WCHAR;
+    dwFlags: DWORD;
+    // These are valid if DIDIFT_OVERLAY is present in dwFlags.
+    dwViewID: DWORD;
+    rcOverlay: RECT;
+    dwObjID: DWORD;
+    dwcValidPts: DWORD;
+    rgptCalloutLine: array [0..4] of POINT;
+    rcCalloutRect: RECT;
+    dwTextAlign: DWORD;
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEIMAGEINFO = TDIDEVICEIMAGEINFOW;
+  LPDIDEVICEIMAGEINFO = LPDIDEVICEIMAGEINFOW;
+  PDIDEVICEIMAGEINFO = PDIDEVICEIMAGEINFOW;
+{$ELSE}
+  TDIDEVICEIMAGEINFO = TDIDEVICEIMAGEINFOA;
+  LPDIDEVICEIMAGEINFO = LPDIDEVICEIMAGEINFOA;
+  PDIDEVICEIMAGEINFO = PDIDEVICEIMAGEINFOA;
+{$ENDIF} // UNICODE
+  LPCDIDEVICEIMAGEINFOA = ^TDIDEVICEIMAGEINFOA;
+  PCDIDEVICEIMAGEINFOA = ^TDIDEVICEIMAGEINFOA;
+  LPCDIDEVICEIMAGEINFOW = ^TDIDEVICEIMAGEINFOW;
+  PCDIDEVICEIMAGEINFOW = ^TDIDEVICEIMAGEINFOW;
+{$IFDEF UNICODE}
+  LPCDIDEVICEIMAGEINFO = LPCDIDEVICEIMAGEINFOW;
+  PCDIDEVICEIMAGEINFO = PCDIDEVICEIMAGEINFOW;
+{$ELSE}
+  LPCDIDEVICEIMAGEINFO = LPCDIDEVICEIMAGEINFOA;
+  PCDIDEVICEIMAGEINFO = PCDIDEVICEIMAGEINFOA;
+{$ENDIF} // UNICODE
+
+  LPDIDEVICEIMAGEINFOHEADERA = ^TDIDEVICEIMAGEINFOHEADERA;
+  PDIDEVICEIMAGEINFOHEADERA = ^TDIDEVICEIMAGEINFOHEADERA;
+  TDIDEVICEIMAGEINFOHEADERA = record
+    dwSize: DWORD;
+    dwSizeImageInfo: DWORD;
+    dwcViews: DWORD;
+    dwcButtons: DWORD;
+    dwcAxes: DWORD;
+    dwcPOVs: DWORD;
+    dwBufferSize: DWORD;
+    dwBufferUsed: DWORD;
+    lprgImageInfoArray: LPDIDEVICEIMAGEINFOA;
+  end;
+  LPDIDEVICEIMAGEINFOHEADERW = ^TDIDEVICEIMAGEINFOHEADERW;
+  PDIDEVICEIMAGEINFOHEADERW = ^TDIDEVICEIMAGEINFOHEADERW;
+  TDIDEVICEIMAGEINFOHEADERW = record
+    dwSize: DWORD;
+    dwSizeImageInfo: DWORD;
+    dwcViews: DWORD;
+    dwcButtons: DWORD;
+    dwcAxes: DWORD;
+    dwcPOVs: DWORD;
+    dwBufferSize: DWORD;
+    dwBufferUsed: DWORD;
+    lprgImageInfoArray: LPDIDEVICEIMAGEINFOW;
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEIMAGEINFOHEADER = TDIDEVICEIMAGEINFOHEADERW;
+  LPDIDEVICEIMAGEINFOHEADER = LPDIDEVICEIMAGEINFOHEADERW;
+  PDIDEVICEIMAGEINFOHEADER = PDIDEVICEIMAGEINFOHEADERW;
+{$ELSE}
+  TDIDEVICEIMAGEINFOHEADER = TDIDEVICEIMAGEINFOHEADERA;
+  LPDIDEVICEIMAGEINFOHEADER = LPDIDEVICEIMAGEINFOHEADERA;
+  PDIDEVICEIMAGEINFOHEADER = PDIDEVICEIMAGEINFOHEADERA;
+{$ENDIF} // UNICODE
+  LPCDIDEVICEIMAGEINFOHEADERA = ^TDIDEVICEIMAGEINFOHEADERA;
+  PCDIDEVICEIMAGEINFOHEADERA = ^TDIDEVICEIMAGEINFOHEADERA;
+  LPCDIDEVICEIMAGEINFOHEADERW = ^TDIDEVICEIMAGEINFOHEADERW;
+  PCDIDEVICEIMAGEINFOHEADERW = ^TDIDEVICEIMAGEINFOHEADERW;
+{$IFDEF UNICODE}
+  LPCDIDEVICEIMAGEINFOHEADER = LPCDIDEVICEIMAGEINFOHEADERW;
+  PCDIDEVICEIMAGEINFOHEADER = PCDIDEVICEIMAGEINFOHEADERW;
+{$ELSE}
+  LPCDIDEVICEIMAGEINFOHEADER = LPCDIDEVICEIMAGEINFOHEADERA;
+  PCDIDEVICEIMAGEINFOHEADER = PCDIDEVICEIMAGEINFOHEADERA;
+{$ENDIF} // UNICODE
+
+{$ENDIF} { DIRECTINPUT_VERSION > $0700 }
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+{ These structures are defined for DirectX 3.0 compatibility }
+
+type
+  LPDIDEVICEOBJECTINSTANCE_DX3A = ^TDIDEVICEOBJECTINSTANCE_DX3A;
+  PDIDEVICEOBJECTINSTANCE_DX3A = ^TDIDEVICEOBJECTINSTANCE_DX3A;
+  TDIDEVICEOBJECTINSTANCE_DX3A = record
+    dwSize: DWORD;
+    guidType: GUID;
+    dwOfs: DWORD;
+    dwType: DWORD;
+    dwFlags: DWORD;
+    tszName: array [0..MAX_PATH-1] of CHAR;
+  end;
+  LPDIDEVICEOBJECTINSTANCE_DX3W = ^TDIDEVICEOBJECTINSTANCE_DX3W;
+  PDIDEVICEOBJECTINSTANCE_DX3W = ^TDIDEVICEOBJECTINSTANCE_DX3W;
+  TDIDEVICEOBJECTINSTANCE_DX3W = record
+    dwSize: DWORD;
+    guidType: GUID;
+    dwOfs: DWORD;
+    dwType: DWORD;
+    dwFlags: DWORD;
+    tszName: array [0..MAX_PATH-1] of WCHAR;
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEOBJECTINSTANCE_DX3 = TDIDEVICEOBJECTINSTANCE_DX3W;
+  LPDIDEVICEOBJECTINSTANCE_DX3 = LPDIDEVICEOBJECTINSTANCE_DX3W;
+  PDIDEVICEOBJECTINSTANCE_DX3 = PDIDEVICEOBJECTINSTANCE_DX3W;
+{$ELSE}
+  TDIDEVICEOBJECTINSTANCE_DX3 = TDIDEVICEOBJECTINSTANCE_DX3A;
+  LPDIDEVICEOBJECTINSTANCE_DX3 = LPDIDEVICEOBJECTINSTANCE_DX3A;
+  PDIDEVICEOBJECTINSTANCE_DX3 = PDIDEVICEOBJECTINSTANCE_DX3A;
+{$ENDIF} // UNICODE
+  LPCDIDEVICEOBJECTINSTANCE_DX3A = ^TDIDEVICEOBJECTINSTANCE_DX3A;
+  LPCDIDEVICEOBJECTINSTANCE_DX3W = ^TDIDEVICEOBJECTINSTANCE_DX3W;
+  LPCDIDEVICEOBJECTINSTANCE_DX3 = ^TDIDEVICEOBJECTINSTANCE_DX3;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+
+  LPDIDEVICEOBJECTINSTANCEA = ^TDIDEVICEOBJECTINSTANCEA;
+  PDIDEVICEOBJECTINSTANCEA = ^TDIDEVICEOBJECTINSTANCEA;
+  TDIDEVICEOBJECTINSTANCEA = record
+    dwSize: DWORD;
+    guidType: GUID;
+    dwOfs: DWORD;
+    dwType: DWORD;
+    dwFlags: DWORD;
+    tszName: array [0..MAX_PATH-1] of CHAR;
+{$IF DIRECTINPUT_VERSION >= $0500}
+    dwFFMaxForce: DWORD;
+    dwFFForceResolution: DWORD;
+    wCollectionNumber: WORD;
+    wDesignatorIndex: WORD;
+    wUsagePage: WORD;
+    wUsage: WORD;
+    dwDimension: DWORD;
+    wExponent: WORD;
+    wReportId: WORD;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  end;
+  LPDIDEVICEOBJECTINSTANCEW = ^TDIDEVICEOBJECTINSTANCEW;
+  PDIDEVICEOBJECTINSTANCEW = ^TDIDEVICEOBJECTINSTANCEW;
+  TDIDEVICEOBJECTINSTANCEW = record
+    dwSize: DWORD;
+    guidType: GUID;
+    dwOfs: DWORD;
+    dwType: DWORD;
+    dwFlags: DWORD;
+    tszName: array [0..MAX_PATH-1] of WCHAR;
+{$IF DIRECTINPUT_VERSION >= $0500}
+    dwFFMaxForce: DWORD;
+    dwFFForceResolution: DWORD;
+    wCollectionNumber: WORD;
+    wDesignatorIndex: WORD;
+    wUsagePage: WORD;
+    wUsage: WORD;
+    dwDimension: DWORD;
+    wExponent: WORD;
+    wReportId: WORD;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEOBJECTINSTANCE = TDIDEVICEOBJECTINSTANCEW;
+  LPDIDEVICEOBJECTINSTANCE = LPDIDEVICEOBJECTINSTANCEW;
+  PDIDEVICEOBJECTINSTANCE = PDIDEVICEOBJECTINSTANCEW;
+{$ELSE}
+  TDIDEVICEOBJECTINSTANCE = TDIDEVICEOBJECTINSTANCEA;
+  LPDIDEVICEOBJECTINSTANCE = LPDIDEVICEOBJECTINSTANCEA;
+  PDIDEVICEOBJECTINSTANCE = PDIDEVICEOBJECTINSTANCEA;
+{$ENDIF} // UNICODE
+  LPCDIDEVICEOBJECTINSTANCEA = ^TDIDEVICEOBJECTINSTANCEA;
+  PCDIDEVICEOBJECTINSTANCEA = ^TDIDEVICEOBJECTINSTANCEA;
+  LPCDIDEVICEOBJECTINSTANCEW = ^TDIDEVICEOBJECTINSTANCEW;
+  PCDIDEVICEOBJECTINSTANCEW = ^TDIDEVICEOBJECTINSTANCEW;
+  LPCDIDEVICEOBJECTINSTANCE = ^TDIDEVICEOBJECTINSTANCE;
+  PCDIDEVICEOBJECTINSTANCE = ^TDIDEVICEOBJECTINSTANCE;
+
+  LPDIENUMDEVICEOBJECTSCALLBACKA = function(lpddoi: LPCDIDEVICEOBJECTINSTANCEA; pvRef: LPVOID): BOOL; stdcall;
+  LPDIENUMDEVICEOBJECTSCALLBACKW = function(lpddoi: LPCDIDEVICEOBJECTINSTANCEW; pvRef: LPVOID): BOOL; stdcall;
+{$IFDEF UNICODE}
+  LPDIENUMDEVICEOBJECTSCALLBACK = LPDIENUMDEVICEOBJECTSCALLBACKW;
+{$ELSE}
+  LPDIENUMDEVICEOBJECTSCALLBACK = LPDIENUMDEVICEOBJECTSCALLBACKA;
+{$ENDIF} // !UNICODE
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+const
+  DIDOI_FFACTUATOR      = $00000001;
+  DIDOI_FFEFFECTTRIGGER = $00000002;
+  DIDOI_POLLED          = $00008000;
+  DIDOI_ASPECTPOSITION  = $00000100;
+  DIDOI_ASPECTVELOCITY  = $00000200;
+  DIDOI_ASPECTACCEL     = $00000300;
+  DIDOI_ASPECTFORCE     = $00000400;
+  DIDOI_ASPECTMASK      = $00000F00;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+{$IF DIRECTINPUT_VERSION >= $050a}
+  DIDOI_GUIDISUSAGE     = $00010000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+type
+  LPCDIPROPHEADER = ^TDIPROPHEADER;
+  PCDIPROPHEADER = ^TDIPROPHEADER;
+  LPDIPROPHEADER = ^TDIPROPHEADER;
+  PDIPROPHEADER = ^TDIPROPHEADER;
+  TDIPROPHEADER = record
+    dwSize: DWORD;
+    dwHeaderSize: DWORD;
+    dwObj: DWORD;
+    dwHow: DWORD;
+  end;
+
+const
+  DIPH_DEVICE           = 0;
+  DIPH_BYOFFSET         = 1;
+  DIPH_BYID             = 2;
+{$IF DIRECTINPUT_VERSION >= $050a}
+  DIPH_BYUSAGE          = 3;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+//#if(DIRECTINPUT_VERSION >= 0x050a)
+//#define DIMAKEUSAGEDWORD(UsagePage, Usage) \
+//                                (DWORD)MAKELONG(Usage, UsagePage)
+//#endif /* DIRECTINPUT_VERSION >= 0x050a */
+
+type
+  LPCDIPROPDWORD = ^TDIPROPDWORD;
+  PCDIPROPDWORD = ^TDIPROPDWORD;
+  LPDIPROPDWORD = ^TDIPROPDWORD;
+  PDIPROPDWORD = ^TDIPROPDWORD;
+  TDIPROPDWORD = record
+    diph: TDIPROPHEADER;
+    dwData: DWORD;
+  end;
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+  LPCDIPROPPOINTER = ^TDIPROPPOINTER;
+  PCDIPROPPOINTER = ^TDIPROPPOINTER;
+  LPDIPROPPOINTER = ^TDIPROPPOINTER;
+  PDIPROPPOINTER = ^TDIPROPPOINTER;
+  TDIPROPPOINTER = record
+    diph: TDIPROPHEADER;
+    uData: UINT_PTR;
+  end;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+  LPCDIPROPRANGE = ^TDIPROPRANGE;
+  PCDIPROPRANGE = ^TDIPROPRANGE;
+  LPDIPROPRANGE = ^TDIPROPRANGE;
+  PDIPROPRANGE = ^TDIPROPRANGE;
+  TDIPROPRANGE = record
+    diph: TDIPROPHEADER;
+    lMin: LONG;
+    lMax: LONG;
+  end;
+
+const
+  DIPROPRANGE_NOMIN     = LONG($80000000);
+  DIPROPRANGE_NOMAX     = LONG($7FFFFFFF);
+
+{$IF DIRECTINPUT_VERSION >= $050a}
+type
+  LPCDIPROPCAL = ^TDIPROPCAL;
+  PCDIPROPCAL = ^TDIPROPCAL;
+  LPDIPROPCAL = ^TDIPROPCAL;
+  PDIPROPCAL = ^TDIPROPCAL;
+  TDIPROPCAL = record
+    diph: TDIPROPHEADER;
+    lMin: LONG;
+    lCenter: LONG;
+    lMax: LONG;
+  end;
+
+  LPCDIPROPCALPOV = ^TDIPROPCALPOV;
+  PCDIPROPCALPOV = ^TDIPROPCALPOV;
+  LPDIPROPCALPOV = ^TDIPROPCALPOV;
+  PDIPROPCALPOV = ^TDIPROPCALPOV;
+  TDIPROPCALPOV = record
+    diph: TDIPROPHEADER;
+    lMin: array [0..4] of LONG;
+    lMax: array [0..4] of LONG;
+  end;
+
+  LPCDIPROPGUIDANDPATH = ^TDIPROPGUIDANDPATH;
+  PCDIPROPGUIDANDPATH = ^TDIPROPGUIDANDPATH;
+  LPDIPROPGUIDANDPATH = ^TDIPROPGUIDANDPATH;
+  PDIPROPGUIDANDPATH = ^TDIPROPGUIDANDPATH;
+  TDIPROPGUIDANDPATH = record
+    diph: TDIPROPHEADER;
+    guidClass: GUID;
+    wszPath: array [0..MAX_PATH-1] of WCHAR;
+  end;
+
+  LPCDIPROPSTRING = ^TDIPROPSTRING;
+  PCDIPROPSTRING = ^TDIPROPSTRING;
+  LPDIPROPSTRING = ^TDIPROPSTRING;
+  PDIPROPSTRING = ^TDIPROPSTRING;
+  TDIPROPSTRING = record
+    diph: TDIPROPHEADER;
+    wsz: array [0..MAX_PATH-1] of WCHAR;
+  end;
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+const
+  MAXCPOINTSNUM        = 8;
+
+type
+  PCPOINT = ^TCPOINT;
+  TCPOINT = record
+    lP: LONG;      // raw value
+    dwLog: DWORD;  // logical_value / max_logical_value * 10000
+  end;
+
+  LPCDIPROPCPOINTS = ^TDIPROPCPOINTS;
+  PCDIPROPCPOINTS = ^TDIPROPCPOINTS;
+  LPDIPROPCPOINTS = ^TDIPROPCPOINTS;
+  PDIPROPCPOINTS = ^TDIPROPCPOINTS;
+  TDIPROPCPOINTS = record
+    diph: TDIPROPHEADER;
+    dwCPointsNum: DWORD;
+    cp: array [0..MAXCPOINTSNUM-1] of TCPOINT;
+  end;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+
+//#ifdef __cplusplus
+//#define MAKEDIPROP(prop)    (*(const GUID * )(prop))
+//#else
+//#define MAKEDIPROP(prop)    ((REFGUID)(prop))
+//#endif
+
+var
+//#define DIPROP_BUFFERSIZE       MAKEDIPROP(1)
+  DIPROP_BUFFERSIZE: TGuid absolute 1;
+
+//#define DIPROP_AXISMODE         MAKEDIPROP(2)
+  DIPROP_AXISMODE: TGuid absolute 2;
+
+const
+  DIPROPAXISMODE_ABS    = 0;
+  DIPROPAXISMODE_REL    = 1;
+
+var
+//#define DIPROP_GRANULARITY      MAKEDIPROP(3)
+  DIPROP_GRANULARITY: TGuid absolute 3;
+
+//#define DIPROP_RANGE            MAKEDIPROP(4)
+  DIPROP_RANGE: TGuid absolute 4;
+
+//#define DIPROP_DEADZONE         MAKEDIPROP(5)
+  DIPROP_DEADZONE: TGuid absolute 5;
+
+//#define DIPROP_SATURATION       MAKEDIPROP(6)
+  DIPROP_SATURATION: TGuid absolute 6;
+
+//#define DIPROP_FFGAIN           MAKEDIPROP(7)
+  DIPROP_FFGAIN: TGuid absolute 7;
+
+//#define DIPROP_FFLOAD           MAKEDIPROP(8)
+  DIPROP_FFLOAD: TGuid absolute 8;
+
+//#define DIPROP_AUTOCENTER       MAKEDIPROP(9)
+  DIPROP_AUTOCENTER: TGuid absolute 9;
+
+const
+  DIPROPAUTOCENTER_OFF  = 0;
+  DIPROPAUTOCENTER_ON   = 1;
+
+var
+//#define DIPROP_CALIBRATIONMODE  MAKEDIPROP(10)
+  DIPROP_CALIBRATIONMODE: TGuid absolute 10;
+
+const
+  DIPROPCALIBRATIONMODE_COOKED  = 0;
+  DIPROPCALIBRATIONMODE_RAW     = 1;
+
+{$IF DIRECTINPUT_VERSION >= $050a}
+var
+//#define DIPROP_CALIBRATION      MAKEDIPROP(11)
+  DIPROP_CALIBRATION: TGuid absolute 11;
+
+//#define DIPROP_GUIDANDPATH      MAKEDIPROP(12)
+  DIPROP_GUIDANDPATH: TGuid absolute 12;
+
+//#define DIPROP_INSTANCENAME     MAKEDIPROP(13)
+  DIPROP_INSTANCENAME: TGuid absolute 13;
+
+//#define DIPROP_PRODUCTNAME      MAKEDIPROP(14)
+  DIPROP_PRODUCTNAME: TGuid absolute 14;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+{$IF DIRECTINPUT_VERSION >= $05b2}
+var
+//#define DIPROP_JOYSTICKID       MAKEDIPROP(15)
+  DIPROP_JOYSTICKID: TGuid absolute 15;
+
+//#define DIPROP_GETPORTDISPLAYNAME       MAKEDIPROP(16)
+  DIPROP_GETPORTDISPLAYNAME: TGuid absolute 16;
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $05b2 }
+
+{$IF DIRECTINPUT_VERSION >= $0700}
+var
+//#define DIPROP_PHYSICALRANGE            MAKEDIPROP(18)
+  DIPROP_PHYSICALRANGE: TGuid absolute 18;
+
+//#define DIPROP_LOGICALRANGE             MAKEDIPROP(19)
+  DIPROP_LOGICALRANGE: TGuid absolute 19;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0700 }
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+//#define DIPROP_KEYNAME                     MAKEDIPROP(20)
+  DIPROP_KEYNAME: TGuid absolute 20;
+
+//#define DIPROP_CPOINTS                 MAKEDIPROP(21)
+  DIPROP_CPOINTS: TGuid absolute 21;
+
+//#define DIPROP_APPDATA       MAKEDIPROP(22)
+  DIPROP_APPDATA: TGuid absolute 22;
+
+//#define DIPROP_SCANCODE      MAKEDIPROP(23)
+  DIPROP_SCANCODE: TGuid absolute 23;
+
+//#define DIPROP_VIDPID           MAKEDIPROP(24)
+  DIPROP_VIDPID: TGuid absolute 24;
+
+//#define DIPROP_USERNAME         MAKEDIPROP(25)
+  DIPROP_USERNAME: TGuid absolute 25;
+
+//#define DIPROP_TYPENAME         MAKEDIPROP(26)
+  DIPROP_TYPENAME: TGuid absolute 26;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+
+type
+  LPCDIDEVICEOBJECTDATA_DX = ^TDIDEVICEOBJECTDATA_DX3;
+  PCDIDEVICEOBJECTDATA_DX = ^TDIDEVICEOBJECTDATA_DX3;
+  LPDIDEVICEOBJECTDATA_DX3 = ^TDIDEVICEOBJECTDATA_DX3;
+  PDIDEVICEOBJECTDATA_DX3 = ^TDIDEVICEOBJECTDATA_DX3;
+  TDIDEVICEOBJECTDATA_DX3 = record
+    dwOfs: DWORD;
+    dwData: DWORD;
+    dwTimeStamp: DWORD;
+    dwSequence: DWORD;
+  end;
+
+  LPCDIDEVICEOBJECTDATA = ^TDIDEVICEOBJECTDATA;
+  PCDIDEVICEOBJECTDATA = ^TDIDEVICEOBJECTDATA;
+  LPDIDEVICEOBJECTDATA = ^TDIDEVICEOBJECTDATA;
+  PDIDEVICEOBJECTDATA = ^TDIDEVICEOBJECTDATA;
+  TDIDEVICEOBJECTDATA = record
+    dwOfs: DWORD;
+    dwData: DWORD;
+    dwTimeStamp: DWORD;
+    dwSequence: DWORD;
+{$IF DIRECTINPUT_VERSION >= $0800}
+    uAppData: UINT_PTR;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+  end;
+
+const
+  DIGDD_PEEK        = $00000001;
+
+//#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
+//                        ((int)((dwSequence1) - (dwSequence2)) cmp 0)
+const
+  DISCL_EXCLUSIVE    = $00000001;
+  DISCL_NONEXCLUSIVE = $00000002;
+  DISCL_FOREGROUND   = $00000004;
+  DISCL_BACKGROUND   = $00000008;
+  DISCL_NOWINKEY     = $00000010;
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+{ These structures are defined for DirectX 3.0 compatibility }
+
+type
+  LPDIDEVICEINSTANCE_DX3A = ^TDIDEVICEINSTANCE_DX3A;
+  PDIDEVICEINSTANCE_DX3A = ^TDIDEVICEINSTANCE_DX3A;
+  TDIDEVICEINSTANCE_DX3A = record
+    dwSize: DWORD;
+    guidInstance: GUID;
+    guidProduct: GUID;
+    dwDevType: DWORD;
+    tszInstanceName: array [0..MAX_PATH-1] of CHAR;
+    tszProductName: array [0..MAX_PATH-1] of CHAR;
+  end;
+  LPDIDEVICEINSTANCE_DX3W = ^TDIDEVICEINSTANCE_DX3W;
+  PDIDEVICEINSTANCE_DX3W = ^TDIDEVICEINSTANCE_DX3W;
+  TDIDEVICEINSTANCE_DX3W = record
+    dwSize: DWORD;
+    guidInstance: GUID;
+    guidProduct: GUID;
+    dwDevType: DWORD;
+    tszInstanceName: array [0..MAX_PATH-1] of WCHAR;
+    tszProductName: array [0..MAX_PATH-1] of WCHAR;
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEINSTANCE_DX3 = TDIDEVICEINSTANCE_DX3W;
+  LPDIDEVICEINSTANCE_DX3 = LPDIDEVICEINSTANCE_DX3W;
+  PDIDEVICEINSTANCE_DX3 = PDIDEVICEINSTANCE_DX3W;
+{$ELSE}
+  TDIDEVICEINSTANCE_DX3 = TDIDEVICEINSTANCE_DX3A;
+  LPDIDEVICEINSTANCE_DX3 = LPDIDEVICEINSTANCE_DX3A;
+  PDIDEVICEINSTANCE_DX3 = PDIDEVICEINSTANCE_DX3A;
+{$ENDIF} // UNICODE
+  LPCDIDEVICEINSTANCE_DX3A = ^TDIDEVICEINSTANCE_DX3A;
+  PCDIDEVICEINSTANCE_DX3A = ^TDIDEVICEINSTANCE_DX3A;
+  LPCDIDEVICEINSTANCE_DX3W = ^TDIDEVICEINSTANCE_DX3W;
+  PCDIDEVICEINSTANCE_DX3W = ^TDIDEVICEINSTANCE_DX3W;
+  LPCDIDEVICEINSTANCE_DX3 = ^TDIDEVICEINSTANCE_DX3;
+  PCDIDEVICEINSTANCE_DX3 = ^TDIDEVICEINSTANCE_DX3;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+
+  LPDIDEVICEINSTANCEA = ^TDIDEVICEINSTANCEA;
+  PDIDEVICEINSTANCEA = ^TDIDEVICEINSTANCEA;
+  TDIDEVICEINSTANCEA = record
+    dwSize: DWORD;
+    guidInstance: GUID;
+    guidProduct: GUID;
+    dwDevType: DWORD;
+    tszInstanceName: array [0..MAX_PATH-1] of CHAR;
+    tszProductName: array [0..MAX_PATH-1] of CHAR;
+{$IF DIRECTINPUT_VERSION >= $0500}
+    guidFFDriver: GUID;
+    wUsagePage: WORD;
+    wUsage: WORD;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  end;
+  LPDIDEVICEINSTANCEW = ^TDIDEVICEINSTANCEW;
+  PDIDEVICEINSTANCEW = ^TDIDEVICEINSTANCEW;
+  TDIDEVICEINSTANCEW = record
+    dwSize: DWORD;
+    guidInstance: GUID;
+    guidProduct: GUID;
+    dwDevType: DWORD;
+    tszInstanceName: array [0..MAX_PATH-1] of WCHAR;
+    tszProductName: array [0..MAX_PATH-1] of WCHAR;
+{$IF DIRECTINPUT_VERSION >= $0500}
+    guidFFDriver: GUID;
+    wUsagePage: WORD;
+    wUsage: WORD;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+  end;
+{$IFDEF UNICODE}
+  TDIDEVICEINSTANCE = TDIDEVICEINSTANCEW;
+  LPDIDEVICEINSTANCE = LPDIDEVICEINSTANCEW;
+  PDIDEVICEINSTANCE = PDIDEVICEINSTANCEW;
+{$ELSE}
+  TDIDEVICEINSTANCE = TDIDEVICEINSTANCEA;
+  LPDIDEVICEINSTANCE = LPDIDEVICEINSTANCEA;
+  PDIDEVICEINSTANCE = PDIDEVICEINSTANCEA;
+{$ENDIF} // UNICODE
+
+  LPCDIDEVICEINSTANCEA = ^TDIDEVICEINSTANCEA;
+  PCDIDEVICEINSTANCEA = ^TDIDEVICEINSTANCEA;
+  LPCDIDEVICEINSTANCEW = ^TDIDEVICEINSTANCEW;
+  PCDIDEVICEINSTANCEW = ^TDIDEVICEINSTANCEW;
+  LPCDIDEVICEINSTANCE = ^TDIDEVICEINSTANCE;
+  PCDIDEVICEINSTANCE = ^TDIDEVICEINSTANCE;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDeviceW
+
+  IDirectInputDeviceW = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDeviceW methods ***)
+    function GetCapabilities(lpDIDevCaps: LPDIDEVCAPS): HRESULT; stdcall;
+    function EnumObjects(lpCallback: LPDIENUMDEVICEOBJECTSCALLBACKW; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPDIPROPHEADER): HRESULT; stdcall;
+    function SetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPCDIPROPHEADER): HRESULT; stdcall;
+    function Acquire: HRESULT; stdcall;
+    function Unacquire: HRESULT; stdcall;
+    function GetDeviceState(cbData: DWORD; lpvData: LPVOID): HRESULT; stdcall;
+    function GetDeviceData(cbObjectData: DWORD; rgdod: LPDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; dwFlags: DWORD): HRESULT; stdcall;
+    function SetDataFormat(lpdf: LPCDIDATAFORMAT): HRESULT; stdcall;
+    function SetEventNotification(hEvent: HANDLE): HRESULT; stdcall;
+    function SetCooperativeLevel(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function GetObjectInfo(pdidoi: LPDIDEVICEOBJECTINSTANCEW; dwObj: DWORD; dwHow: DWORD): HRESULT; stdcall;
+    function GetDeviceInfo(pdidi: LPDIDEVICEINSTANCEW): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDeviceW *LPDIRECTINPUTDEVICEW;
+  LPDIRECTINPUTDEVICEW = IDirectInputDeviceW;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDeviceA
+
+  IDirectInputDeviceA = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDeviceA methods ***)
+    function GetCapabilities(lpDIDevCaps: LPDIDEVCAPS): HRESULT; stdcall;
+    function EnumObjects(lpCallback: LPDIENUMDEVICEOBJECTSCALLBACKA; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPDIPROPHEADER): HRESULT; stdcall;
+    function SetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPCDIPROPHEADER): HRESULT; stdcall;
+    function Acquire: HRESULT; stdcall;
+    function Unacquire: HRESULT; stdcall;
+    function GetDeviceState(cbData: DWORD; lpvData: LPVOID): HRESULT; stdcall;
+    function GetDeviceData(cbObjectData: DWORD; rgdod: LPDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; dwFlags: DWORD): HRESULT; stdcall;
+    function SetDataFormat(lpdf: LPCDIDATAFORMAT): HRESULT; stdcall;
+    function SetEventNotification(hEvent: HANDLE): HRESULT; stdcall;
+    function SetCooperativeLevel(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function GetObjectInfo(pdidoi: LPDIDEVICEOBJECTINSTANCEA; dwObj: DWORD; dwHow: DWORD): HRESULT; stdcall;
+    function GetDeviceInfo(pdidi: LPDIDEVICEINSTANCEA): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDeviceA *LPDIRECTINPUTDEVICEA;
+  LPDIRECTINPUTDEVICEA = IDirectInputDeviceA;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInputDevice: TIID = '{5944E681-C92E-11CF-BFC7-444553540000}'{IID_IDirectInputDeviceW};
+type
+  IDirectInputDevice = IDirectInputDeviceW;
+{$ELSE}
+const
+  IID_IDirectInputDevice: TIID = '{5944E680-C92E-11CF-BFC7-444553540000}'{IID_IDirectInputDeviceA};
+type
+  IDirectInputDevice = IDirectInputDeviceA;
+{$ENDIF}
+//typedef struct IDirectInputDevice *LPDIRECTINPUTDEVICE;
+  LPDIRECTINPUTDEVICE = IDirectInputDevice;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInputDevice_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInputDevice_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInputDevice_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInputDevice_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+//#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+//#define IDirectInputDevice_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+//#define IDirectInputDevice_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+//#define IDirectInputDevice_Acquire(p) (p)->lpVtbl->Acquire(p)
+//#define IDirectInputDevice_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+//#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+//#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+//#define IDirectInputDevice_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+//#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+//#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+//#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+//#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInputDevice_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+//#else
+//#define IDirectInputDevice_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInputDevice_AddRef(p) (p)->AddRef()
+//#define IDirectInputDevice_Release(p) (p)->Release()
+//#define IDirectInputDevice_GetCapabilities(p,a) (p)->GetCapabilities(a)
+//#define IDirectInputDevice_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+//#define IDirectInputDevice_GetProperty(p,a,b) (p)->GetProperty(a,b)
+//#define IDirectInputDevice_SetProperty(p,a,b) (p)->SetProperty(a,b)
+//#define IDirectInputDevice_Acquire(p) (p)->Acquire()
+//#define IDirectInputDevice_Unacquire(p) (p)->Unacquire()
+//#define IDirectInputDevice_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+//#define IDirectInputDevice_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+//#define IDirectInputDevice_SetDataFormat(p,a) (p)->SetDataFormat(a)
+//#define IDirectInputDevice_SetEventNotification(p,a) (p)->SetEventNotification(a)
+//#define IDirectInputDevice_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+//#define IDirectInputDevice_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+//#define IDirectInputDevice_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+//#define IDirectInputDevice_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInputDevice_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+//#endif
+
+//#endif /* DIJ_RINGZERO */
+
+
+{$IF DIRECTINPUT_VERSION >= $0500}
+
+const
+  DISFFC_RESET           = $00000001;
+  DISFFC_STOPALL         = $00000002;
+  DISFFC_PAUSE           = $00000004;
+  DISFFC_CONTINUE        = $00000008;
+  DISFFC_SETACTUATORSON  = $00000010;
+  DISFFC_SETACTUATORSOFF = $00000020;
+
+  DIGFFS_EMPTY           = $00000001;
+  DIGFFS_STOPPED         = $00000002;
+  DIGFFS_PAUSED          = $00000004;
+  DIGFFS_ACTUATORSON     = $00000010;
+  DIGFFS_ACTUATORSOFF    = $00000020;
+  DIGFFS_POWERON         = $00000040;
+  DIGFFS_POWEROFF        = $00000080;
+  DIGFFS_SAFETYSWITCHON  = $00000100;
+  DIGFFS_SAFETYSWITCHOFF = $00000200;
+  DIGFFS_USERFFSWITCHON  = $00000400;
+  DIGFFS_USERFFSWITCHOFF = $00000800;
+  DIGFFS_DEVICELOST      = $80000000;
+
+//#ifndef DIJ_RINGZERO
+
+type
+  LPDIEFFECTINFOA = ^TDIEFFECTINFOA;
+  PDIEFFECTINFOA = ^TDIEFFECTINFOA;
+  TDIEFFECTINFOA = record
+    dwSize: DWORD;
+    guid: GUID;
+    dwEffType: DWORD;
+    dwStaticParams: DWORD;
+    dwDynamicParams: DWORD;
+    tszName: array [0..MAX_PATH-1] of CHAR;
+  end;
+  LPDIEFFECTINFOW = ^TDIEFFECTINFOW;
+  PDIEFFECTINFOW = ^TDIEFFECTINFOW;
+  TDIEFFECTINFOW = record
+    dwSize: DWORD;
+    guid: GUID;
+    dwEffType: DWORD;
+    dwStaticParams: DWORD;
+    dwDynamicParams: DWORD;
+    tszName: array [0..MAX_PATH-1] of WCHAR;
+  end;
+{$IFDEF UNICODE}
+  TDIEFFECTINFO = TDIEFFECTINFOW;
+  LPDIEFFECTINFO = LPDIEFFECTINFOW;
+  PDIEFFECTINFO = PDIEFFECTINFOW;
+{$ELSE}
+  TDIEFFECTINFO = TDIEFFECTINFOA;
+  LPDIEFFECTINFO = LPDIEFFECTINFOA;
+  PDIEFFECTINFO = PDIEFFECTINFOA;
+{$ENDIF} // UNICODE
+  LPCDIEFFECTINFOA = ^TDIEFFECTINFOA;
+  PCDIEFFECTINFOA = ^TDIEFFECTINFOA;
+  LPCDIEFFECTINFOW = ^TDIEFFECTINFOW;
+  PCDIEFFECTINFOW = ^TDIEFFECTINFOW;
+  LPCDIEFFECTINFO = ^TDIEFFECTINFO;
+  PCDIEFFECTINFO = ^TDIEFFECTINFO;
+
+const
+  DISDD_CONTINUE        = $00000001;
+
+type
+  LPDIENUMEFFECTSCALLBACKA = function(pdei: LPCDIEFFECTINFOA; pvRef: LPVOID): BOOL; stdcall;
+  LPDIENUMEFFECTSCALLBACKW = function(pdei: LPCDIEFFECTINFOW; pvRef: LPVOID): BOOL; stdcall;
+{$IFDEF UNICODE}
+  LPDIENUMEFFECTSCALLBACK = LPDIENUMEFFECTSCALLBACKW;
+{$ELSE}
+  LPDIENUMEFFECTSCALLBACK = LPDIENUMEFFECTSCALLBACKA;
+{$ENDIF} // !UNICODE
+  LPDIENUMCREATEDEFFECTOBJECTSCALLBACK = function(peff: LPDIRECTINPUTEFFECT; pvRef: LPVOID): BOOL; stdcall;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice2W
+
+  IDirectInputDevice2W = interface(IDirectInputDeviceW)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDeviceW methods ***)
+    {STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;}
+
+    (*** IDirectInputDevice2W methods ***)
+    function CreateEffect(const rguid: TGuid {REFGUID}; lpeff: LPCDIEFFECT; out ppdeff: IDirectInputEffect {LPDIRECTINPUTEFFECT *}; punkOuter: {LPUNKNOWN}IUnknown): HRESULT; stdcall;
+    function EnumEffects(lpCallback: LPDIENUMEFFECTSCALLBACKW; pvRef: LPVOID; dwEffType: DWORD): HRESULT; stdcall;
+    function GetEffectInfo(pdei: LPDIEFFECTINFOW; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function GetForceFeedbackState(pdwOut: LPDWORD): HRESULT; stdcall;
+    function SendForceFeedbackCommand(dwFlags: DWORD): HRESULT; stdcall;
+    function EnumCreatedEffectObjects(lpCallback: LPDIENUMCREATEDEFFECTOBJECTSCALLBACK; pvRef: LPVOID; fl: DWORD): HRESULT; stdcall;
+    function Escape(pesc: LPDIEFFESCAPE): HRESULT; stdcall;
+    function Poll: HRESULT; stdcall;
+    function SendDeviceData(cbObjectData: DWORD; rgdod: LPCDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; fl: DWORD): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice2W *LPDIRECTINPUTDEVICE2W;
+  LPDIRECTINPUTDEVICE2W = IDirectInputDevice2W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice2A
+
+  IDirectInputDevice2A = interface(IDirectInputDeviceA)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDeviceA methods ***)
+    {STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;}
+
+    (*** IDirectInputDevice2A methods ***)
+    function CreateEffect(const rguid: TGuid {REFGUID}; lpeff: LPCDIEFFECT; out ppdeff: IDirectInputEffect {LPDIRECTINPUTEFFECT *}; punkOuter: {LPUNKNOWN}IUnknown): HRESULT; stdcall;
+    function EnumEffects(lpCallback: LPDIENUMEFFECTSCALLBACKA; pvRef: LPVOID; dwEffType: DWORD): HRESULT; stdcall;
+    function GetEffectInfo(pdei: LPDIEFFECTINFOA; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function GetForceFeedbackState(pdwOut: LPDWORD): HRESULT; stdcall;
+    function SendForceFeedbackCommand(dwFlags: DWORD): HRESULT; stdcall;
+    function EnumCreatedEffectObjects(lpCallback: LPDIENUMCREATEDEFFECTOBJECTSCALLBACK; pvRef: LPVOID; fl: DWORD): HRESULT; stdcall;
+    function Escape(pesc: LPDIEFFESCAPE): HRESULT; stdcall;
+    function Poll: HRESULT; stdcall;
+    function SendDeviceData(cbObjectData: DWORD; rgdod: LPCDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; fl: DWORD): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice2A *LPDIRECTINPUTDEVICE2A;
+  LPDIRECTINPUTDEVICE2A = IDirectInputDevice2A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInputDevice2: TIID = '{5944E683-C92E-11CF-BFC7-444553540000}'{IID_IDirectInputDevice2W};
+type
+  IDirectInputDevice2 = IDirectInputDevice2W;
+{$ELSE}
+const
+  IID_IDirectInputDevice2: TIID = '{5944E682-C92E-11CF-BFC7-444553540000}'{IID_IDirectInputDevice2A};
+type
+  IDirectInputDevice2 = IDirectInputDevice2A;
+{$ENDIF}
+//typedef struct IDirectInputDevice2 *LPDIRECTINPUTDEVICE2;
+  LPDIRECTINPUTDEVICE2 = IDirectInputDevice2;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInputDevice2_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInputDevice2_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInputDevice2_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+//#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+//#define IDirectInputDevice2_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+//#define IDirectInputDevice2_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+//#define IDirectInputDevice2_Acquire(p) (p)->lpVtbl->Acquire(p)
+//#define IDirectInputDevice2_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+//#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+//#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice2_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+//#define IDirectInputDevice2_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+//#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+//#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+//#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+//#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+//#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+//#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+//#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+//#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+//#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+//#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+//#define IDirectInputDevice2_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+//#define IDirectInputDevice2_Poll(p) (p)->lpVtbl->Poll(p)
+//#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+//#else
+//#define IDirectInputDevice2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInputDevice2_AddRef(p) (p)->AddRef()
+//#define IDirectInputDevice2_Release(p) (p)->Release()
+//#define IDirectInputDevice2_GetCapabilities(p,a) (p)->GetCapabilities(a)
+//#define IDirectInputDevice2_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+//#define IDirectInputDevice2_GetProperty(p,a,b) (p)->GetProperty(a,b)
+//#define IDirectInputDevice2_SetProperty(p,a,b) (p)->SetProperty(a,b)
+//#define IDirectInputDevice2_Acquire(p) (p)->Acquire()
+//#define IDirectInputDevice2_Unacquire(p) (p)->Unacquire()
+//#define IDirectInputDevice2_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+//#define IDirectInputDevice2_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+//#define IDirectInputDevice2_SetDataFormat(p,a) (p)->SetDataFormat(a)
+//#define IDirectInputDevice2_SetEventNotification(p,a) (p)->SetEventNotification(a)
+//#define IDirectInputDevice2_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+//#define IDirectInputDevice2_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+//#define IDirectInputDevice2_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+//#define IDirectInputDevice2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInputDevice2_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+//#define IDirectInputDevice2_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+//#define IDirectInputDevice2_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+//#define IDirectInputDevice2_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+//#define IDirectInputDevice2_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+//#define IDirectInputDevice2_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+//#define IDirectInputDevice2_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+//#define IDirectInputDevice2_Escape(p,a) (p)->Escape(a)
+//#define IDirectInputDevice2_Poll(p) (p)->Poll()
+//#define IDirectInputDevice2_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+//#endif
+
+//#endif /* DIJ_RINGZERO */
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+
+{$IF DIRECTINPUT_VERSION >= $0700}
+const
+  DIFEF_DEFAULT             = $00000000;
+  DIFEF_INCLUDENONSTANDARD  = $00000001;
+  DIFEF_MODIFYIFNEEDED      = $00000010;
+
+//#ifndef DIJ_RINGZERO
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice7W
+
+type
+  IDirectInputDevice7W = interface(IDirectInputDevice2W)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDevice2W methods ***)
+    {STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEW,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEW) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOW,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;}
+
+    (*** IDirectInputDevice7W methods ***)
+    function EnumEffectsInFile(lpszFileName: LPCWSTR; pec: LPDIENUMEFFECTSINFILECALLBACK; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function WriteEffectToFile(lpszFileName: LPCWSTR; dwEntries: DWORD; rgDiFileEft: LPDIFILEEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice7W *LPDIRECTINPUTDEVICE7W;
+  LPDIRECTINPUTDEVICE7W = IDirectInputDevice7W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice7A
+
+  IDirectInputDevice7A = interface(IDirectInputDevice2A)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDevice2A methods ***)
+    {STDMETHOD(GetCapabilities)(THIS_ LPDIDEVCAPS) PURE;
+    STDMETHOD(EnumObjects)(THIS_ LPDIENUMDEVICEOBJECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetProperty)(THIS_ REFGUID,LPDIPROPHEADER) PURE;
+    STDMETHOD(SetProperty)(THIS_ REFGUID,LPCDIPROPHEADER) PURE;
+    STDMETHOD(Acquire)(THIS) PURE;
+    STDMETHOD(Unacquire)(THIS) PURE;
+    STDMETHOD(GetDeviceState)(THIS_ DWORD,LPVOID) PURE;
+    STDMETHOD(GetDeviceData)(THIS_ DWORD,LPDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;
+    STDMETHOD(SetDataFormat)(THIS_ LPCDIDATAFORMAT) PURE;
+    STDMETHOD(SetEventNotification)(THIS_ HANDLE) PURE;
+    STDMETHOD(SetCooperativeLevel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(GetObjectInfo)(THIS_ LPDIDEVICEOBJECTINSTANCEA,DWORD,DWORD) PURE;
+    STDMETHOD(GetDeviceInfo)(THIS_ LPDIDEVICEINSTANCEA) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD,REFGUID) PURE;
+    STDMETHOD(CreateEffect)(THIS_ REFGUID,LPCDIEFFECT,LPDIRECTINPUTEFFECT *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumEffects)(THIS_ LPDIENUMEFFECTSCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetEffectInfo)(THIS_ LPDIEFFECTINFOA,REFGUID) PURE;
+    STDMETHOD(GetForceFeedbackState)(THIS_ LPDWORD) PURE;
+    STDMETHOD(SendForceFeedbackCommand)(THIS_ DWORD) PURE;
+    STDMETHOD(EnumCreatedEffectObjects)(THIS_ LPDIENUMCREATEDEFFECTOBJECTSCALLBACK,LPVOID,DWORD) PURE;
+    STDMETHOD(Escape)(THIS_ LPDIEFFESCAPE) PURE;
+    STDMETHOD(Poll)(THIS) PURE;
+    STDMETHOD(SendDeviceData)(THIS_ DWORD,LPCDIDEVICEOBJECTDATA,LPDWORD,DWORD) PURE;}
+
+    (*** IDirectInputDevice7A methods ***)
+    function EnumEffectsInFile(lpszFileName: LPCSTR; pec: LPDIENUMEFFECTSINFILECALLBACK; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function WriteEffectToFile(lpszFileName: LPCSTR; dwEntries: DWORD; rgDiFileEft: LPDIFILEEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice7A *LPDIRECTINPUTDEVICE7A;
+  LPDIRECTINPUTDEVICE7A = IDirectInputDevice7A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInputDevice7: TIID = '{57D7C6BD-2356-11D3-8E9D-00C04F6844AE}'{IID_IDirectInputDevice7W};
+type
+  IDirectInputDevice7 = IDirectInputDevice7W;
+{$ELSE}
+const
+  IID_IDirectInputDevice7: TIID = '{57D7C6BC-2356-11D3-8E9D-00C04F6844AE}'{IID_IDirectInputDevice7A};
+type
+  IDirectInputDevice7 = IDirectInputDevice7A;
+{$ENDIF}
+//typedef struct IDirectInputDevice7 *LPDIRECTINPUTDEVICE7;
+  LPDIRECTINPUTDEVICE7 = IDirectInputDevice7;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInputDevice7_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInputDevice7_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInputDevice7_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+//#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+//#define IDirectInputDevice7_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+//#define IDirectInputDevice7_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+//#define IDirectInputDevice7_Acquire(p) (p)->lpVtbl->Acquire(p)
+//#define IDirectInputDevice7_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+//#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+//#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice7_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+//#define IDirectInputDevice7_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+//#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+//#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+//#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+//#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+//#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+//#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+//#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+//#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+//#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+//#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+//#define IDirectInputDevice7_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+//#define IDirectInputDevice7_Poll(p) (p)->lpVtbl->Poll(p)
+//#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d)
+//#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d)
+//#else
+//#define IDirectInputDevice7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInputDevice7_AddRef(p) (p)->AddRef()
+//#define IDirectInputDevice7_Release(p) (p)->Release()
+//#define IDirectInputDevice7_GetCapabilities(p,a) (p)->GetCapabilities(a)
+//#define IDirectInputDevice7_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+//#define IDirectInputDevice7_GetProperty(p,a,b) (p)->GetProperty(a,b)
+//#define IDirectInputDevice7_SetProperty(p,a,b) (p)->SetProperty(a,b)
+//#define IDirectInputDevice7_Acquire(p) (p)->Acquire()
+//#define IDirectInputDevice7_Unacquire(p) (p)->Unacquire()
+//#define IDirectInputDevice7_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+//#define IDirectInputDevice7_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+//#define IDirectInputDevice7_SetDataFormat(p,a) (p)->SetDataFormat(a)
+//#define IDirectInputDevice7_SetEventNotification(p,a) (p)->SetEventNotification(a)
+//#define IDirectInputDevice7_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+//#define IDirectInputDevice7_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+//#define IDirectInputDevice7_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+//#define IDirectInputDevice7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInputDevice7_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+//#define IDirectInputDevice7_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+//#define IDirectInputDevice7_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+//#define IDirectInputDevice7_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+//#define IDirectInputDevice7_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+//#define IDirectInputDevice7_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+//#define IDirectInputDevice7_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+//#define IDirectInputDevice7_Escape(p,a) (p)->Escape(a)
+//#define IDirectInputDevice7_Poll(p) (p)->Poll()
+//#define IDirectInputDevice7_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+//#define IDirectInputDevice7_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d)
+//#define IDirectInputDevice7_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d)
+//#endif
+
+//#endif /* DIJ_RINGZERO */
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $0700 }
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+
+//#ifndef DIJ_RINGZERO
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice8W
+
+type
+  IDirectInputDevice8W = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDevice8W methods ***)
+    function GetCapabilities(lpDIDevCaps: LPDIDEVCAPS): HRESULT; stdcall;
+    function EnumObjects(lpCallback: LPDIENUMDEVICEOBJECTSCALLBACKW; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPDIPROPHEADER): HRESULT; stdcall;
+    function SetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPCDIPROPHEADER): HRESULT; stdcall;
+    function Acquire: HRESULT; stdcall;
+    function Unacquire: HRESULT; stdcall;
+    function GetDeviceState(cbData: DWORD; lpvData: LPVOID): HRESULT; stdcall;
+    function GetDeviceData(cbObjectData: DWORD; rgdod: LPDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; dwFlags: DWORD): HRESULT; stdcall;
+    function SetDataFormat(lpdf: LPCDIDATAFORMAT): HRESULT; stdcall;
+    function SetEventNotification(hEvent: HANDLE): HRESULT; stdcall;
+    function SetCooperativeLevel(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function GetObjectInfo(pdidoi: LPDIDEVICEOBJECTINSTANCEW; dwObj: DWORD; dwHow: DWORD): HRESULT; stdcall;
+    function GetDeviceInfo(pdidi: LPDIDEVICEINSTANCEW): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function CreateEffect(const rguid: TGuid {REFGUID}; lpeff: LPCDIEFFECT; out ppdeff: IDirectInputEffect {LPDIRECTINPUTEFFECT *}; punkOuter: {LPUNKNOWN}IUnknown): HRESULT; stdcall;
+    function EnumEffects(lpCallback: LPDIENUMEFFECTSCALLBACKW; pvRef: LPVOID; dwEffType: DWORD): HRESULT; stdcall;
+    function GetEffectInfo(pdei: LPDIEFFECTINFOW; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function GetForceFeedbackState(pdwOut: LPDWORD): HRESULT; stdcall;
+    function SendForceFeedbackCommand(dwFlags: DWORD): HRESULT; stdcall;
+    function EnumCreatedEffectObjects(lpCallback: LPDIENUMCREATEDEFFECTOBJECTSCALLBACK; pvRef: LPVOID; fl: DWORD): HRESULT; stdcall;
+    function Escape(pesc: LPDIEFFESCAPE): HRESULT; stdcall;
+    function Poll: HRESULT; stdcall;
+    function SendDeviceData(cbObjectData: DWORD; rgdod: LPCDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; fl: DWORD): HRESULT; stdcall;
+    function EnumEffectsInFile(lpszFileName: LPCWSTR; pec: LPDIENUMEFFECTSINFILECALLBACK; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function WriteEffectToFile(lpszFileName: LPCWSTR; dwEntries: DWORD; rgDiFileEft: LPDIFILEEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+    function BuildActionMap(lpdiaf: LPDIACTIONFORMATW; lpszUserName: LPCWSTR; dwFlags: DWORD): HRESULT; stdcall;
+    function SetActionMap(lpdiActionFormat: LPDIACTIONFORMATW; lptszUserName: LPCWSTR; dwFlags: DWORD): HRESULT; stdcall;
+    function GetImageInfo(lpdiDevImageInfoHeader: LPDIDEVICEIMAGEINFOHEADERW): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice8W *LPDIRECTINPUTDEVICE8W;
+  LPDIRECTINPUTDEVICE8W = IDirectInputDevice8W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputDevice8A
+
+  IDirectInputDevice8A = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputDevice8A methods ***)
+    function GetCapabilities(lpDIDevCaps: LPDIDEVCAPS): HRESULT; stdcall;
+    function EnumObjects(lpCallback: LPDIENUMDEVICEOBJECTSCALLBACKA; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPDIPROPHEADER): HRESULT; stdcall;
+    function SetProperty(const rguidProp: TGuid {REFGUID}; pdiph: LPCDIPROPHEADER): HRESULT; stdcall;
+    function Acquire: HRESULT; stdcall;
+    function Unacquire: HRESULT; stdcall;
+    function GetDeviceState(cbData: DWORD; lpvData: LPVOID): HRESULT; stdcall;
+    function GetDeviceData(cbObjectData: DWORD; rgdod: LPDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; dwFlags: DWORD): HRESULT; stdcall;
+    function SetDataFormat(lpdf: LPCDIDATAFORMAT): HRESULT; stdcall;
+    function SetEventNotification(hEvent: HANDLE): HRESULT; stdcall;
+    function SetCooperativeLevel(hwnd: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function GetObjectInfo(pdidoi: LPDIDEVICEOBJECTINSTANCEA; dwObj: DWORD; dwHow: DWORD): HRESULT; stdcall;
+    function GetDeviceInfo(pdidi: LPDIDEVICEINSTANCEA): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function CreateEffect(const rguid: TGuid {REFGUID}; lpeff: LPCDIEFFECT;  out ppdeff: IDirectInputEffect {LPDIRECTINPUTEFFECT *}; punkOuter: {LPUNKNOWN}IUnknown): HRESULT; stdcall;
+    function EnumEffects(lpCallback: LPDIENUMEFFECTSCALLBACKA; pvRef: LPVOID; dwEffType: DWORD): HRESULT; stdcall;
+    function GetEffectInfo(pdei: LPDIEFFECTINFOA; const rguid: TGuid {REFGUID}): HRESULT; stdcall;
+    function GetForceFeedbackState(pdwOut: LPDWORD): HRESULT; stdcall;
+    function SendForceFeedbackCommand(dwFlags: DWORD): HRESULT; stdcall;
+    function EnumCreatedEffectObjects(lpCallback: LPDIENUMCREATEDEFFECTOBJECTSCALLBACK; pvRef: LPVOID; fl: DWORD): HRESULT; stdcall;
+    function Escape(pesc: LPDIEFFESCAPE): HRESULT; stdcall;
+    function Poll: HRESULT; stdcall;
+    function SendDeviceData(cbObjectData: DWORD; rgdod: LPCDIDEVICEOBJECTDATA; pdwInOut: LPDWORD; fl: DWORD): HRESULT; stdcall;
+    function EnumEffectsInFile(lpszFileName: LPCSTR; pec: LPDIENUMEFFECTSINFILECALLBACK; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function WriteEffectToFile(lpszFileName: LPCSTR; dwEntries: DWORD; rgDiFileEft: LPDIFILEEFFECT; dwFlags: DWORD): HRESULT; stdcall;
+    function BuildActionMap(lpdiaf: LPDIACTIONFORMATA; lpszUserName: LPCSTR; dwFlags: DWORD): HRESULT; stdcall;
+    function SetActionMap(lpdiActionFormat: LPDIACTIONFORMATA; lptszUserName: LPCSTR; dwFlags: DWORD): HRESULT; stdcall;
+    function GetImageInfo(lpdiDevImageInfoHeader: LPDIDEVICEIMAGEINFOHEADERA): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputDevice8A *LPDIRECTINPUTDEVICE8A;
+  LPDIRECTINPUTDEVICE8A = IDirectInputDevice8A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInputDevice8: TIID = '{54D41081-DC15-4833-A41B-748F73A38179}'{IID_IDirectInputDevice8W};
+type
+  IDirectInputDevice8 = IDirectInputDevice8W;
+{$ELSE}
+const
+  IID_IDirectInputDevice8: TIID = '{54D41080-DC15-4833-A41B-748F73A38179}'{IID_IDirectInputDevice8A};
+type
+  IDirectInputDevice8 = IDirectInputDevice8A;
+{$ENDIF}
+//typedef struct IDirectInputDevice8 *LPDIRECTINPUTDEVICE8;
+  LPDIRECTINPUTDEVICE8 = IDirectInputDevice8;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInputDevice8_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInputDevice8_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInputDevice8_GetCapabilities(p,a) (p)->lpVtbl->GetCapabilities(p,a)
+//#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->lpVtbl->EnumObjects(p,a,b,c)
+//#define IDirectInputDevice8_GetProperty(p,a,b) (p)->lpVtbl->GetProperty(p,a,b)
+//#define IDirectInputDevice8_SetProperty(p,a,b) (p)->lpVtbl->SetProperty(p,a,b)
+//#define IDirectInputDevice8_Acquire(p) (p)->lpVtbl->Acquire(p)
+//#define IDirectInputDevice8_Unacquire(p) (p)->lpVtbl->Unacquire(p)
+//#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->lpVtbl->GetDeviceState(p,a,b)
+//#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->lpVtbl->GetDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice8_SetDataFormat(p,a) (p)->lpVtbl->SetDataFormat(p,a)
+//#define IDirectInputDevice8_SetEventNotification(p,a) (p)->lpVtbl->SetEventNotification(p,a)
+//#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b)
+//#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->lpVtbl->GetObjectInfo(p,a,b,c)
+//#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->lpVtbl->GetDeviceInfo(p,a)
+//#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->lpVtbl->Initialize(p,a,b,c)
+//#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->lpVtbl->CreateEffect(p,a,b,c,d)
+//#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->lpVtbl->EnumEffects(p,a,b,c)
+//#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->lpVtbl->GetEffectInfo(p,a,b)
+//#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->lpVtbl->GetForceFeedbackState(p,a)
+//#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->lpVtbl->SendForceFeedbackCommand(p,a)
+//#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->lpVtbl->EnumCreatedEffectObjects(p,a,b,c)
+//#define IDirectInputDevice8_Escape(p,a) (p)->lpVtbl->Escape(p,a)
+//#define IDirectInputDevice8_Poll(p) (p)->lpVtbl->Poll(p)
+//#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->lpVtbl->SendDeviceData(p,a,b,c,d)
+//#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->lpVtbl->EnumEffectsInFile(p,a,b,c,d)
+//#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->lpVtbl->WriteEffectToFile(p,a,b,c,d)
+//#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->lpVtbl->BuildActionMap(p,a,b,c)
+//#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->lpVtbl->SetActionMap(p,a,b,c)
+//#define IDirectInputDevice8_GetImageInfo(p,a) (p)->lpVtbl->GetImageInfo(p,a)
+//#else
+//#define IDirectInputDevice8_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInputDevice8_AddRef(p) (p)->AddRef()
+//#define IDirectInputDevice8_Release(p) (p)->Release()
+//#define IDirectInputDevice8_GetCapabilities(p,a) (p)->GetCapabilities(a)
+//#define IDirectInputDevice8_EnumObjects(p,a,b,c) (p)->EnumObjects(a,b,c)
+//#define IDirectInputDevice8_GetProperty(p,a,b) (p)->GetProperty(a,b)
+//#define IDirectInputDevice8_SetProperty(p,a,b) (p)->SetProperty(a,b)
+//#define IDirectInputDevice8_Acquire(p) (p)->Acquire()
+//#define IDirectInputDevice8_Unacquire(p) (p)->Unacquire()
+//#define IDirectInputDevice8_GetDeviceState(p,a,b) (p)->GetDeviceState(a,b)
+//#define IDirectInputDevice8_GetDeviceData(p,a,b,c,d) (p)->GetDeviceData(a,b,c,d)
+//#define IDirectInputDevice8_SetDataFormat(p,a) (p)->SetDataFormat(a)
+//#define IDirectInputDevice8_SetEventNotification(p,a) (p)->SetEventNotification(a)
+//#define IDirectInputDevice8_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b)
+//#define IDirectInputDevice8_GetObjectInfo(p,a,b,c) (p)->GetObjectInfo(a,b,c)
+//#define IDirectInputDevice8_GetDeviceInfo(p,a) (p)->GetDeviceInfo(a)
+//#define IDirectInputDevice8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInputDevice8_Initialize(p,a,b,c) (p)->Initialize(a,b,c)
+//#define IDirectInputDevice8_CreateEffect(p,a,b,c,d) (p)->CreateEffect(a,b,c,d)
+//#define IDirectInputDevice8_EnumEffects(p,a,b,c) (p)->EnumEffects(a,b,c)
+//#define IDirectInputDevice8_GetEffectInfo(p,a,b) (p)->GetEffectInfo(a,b)
+//#define IDirectInputDevice8_GetForceFeedbackState(p,a) (p)->GetForceFeedbackState(a)
+//#define IDirectInputDevice8_SendForceFeedbackCommand(p,a) (p)->SendForceFeedbackCommand(a)
+//#define IDirectInputDevice8_EnumCreatedEffectObjects(p,a,b,c) (p)->EnumCreatedEffectObjects(a,b,c)
+//#define IDirectInputDevice8_Escape(p,a) (p)->Escape(a)
+//#define IDirectInputDevice8_Poll(p) (p)->Poll()
+//#define IDirectInputDevice8_SendDeviceData(p,a,b,c,d) (p)->SendDeviceData(a,b,c,d)
+//#define IDirectInputDevice8_EnumEffectsInFile(p,a,b,c,d) (p)->EnumEffectsInFile(a,b,c,d)
+//#define IDirectInputDevice8_WriteEffectToFile(p,a,b,c,d) (p)->WriteEffectToFile(a,b,c,d)
+//#define IDirectInputDevice8_BuildActionMap(p,a,b,c) (p)->BuildActionMap(a,b,c)
+//#define IDirectInputDevice8_SetActionMap(p,a,b,c) (p)->SetActionMap(a,b,c)
+//#define IDirectInputDevice8_GetImageInfo(p,a) (p)->GetImageInfo(a)
+//#endif
+
+//#endif /* DIJ_RINGZERO */
+
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+(****************************************************************************
+ *
+ *      Mouse
+ *
+ ****************************************************************************)
+
+//#ifndef DIJ_RINGZERO
+
+type
+  LPDIMOUSESTATE = ^TDIMOUSESTATE;
+  PDIMOUSESTATE = ^TDIMOUSESTATE;
+  TDIMOUSESTATE = record
+    lX: LONG;
+    lY: LONG;
+    lZ: LONG;
+    rgbButtons: array [0..3] of BYTE;
+  end;
+
+{$IF DIRECTINPUT_VERSION >= $0700}
+  LPDIMOUSESTATE2 = ^TDIMOUSESTATE2;
+  PDIMOUSESTATE2 = ^TDIMOUSESTATE2;
+  TDIMOUSESTATE2 = record
+    lX: LONG;
+    lY: LONG;
+    lZ: LONG;
+    rgbButtons: array [0..7] of BYTE;
+  end;
+{$ENDIF}
+
+
+//const
+//  DIMOFS_X: LONG       =  Ofs(PDIMOUSESTATE(nil)^.lX); { FIELD_OFFSET(DIMOUSESTATE, lX)}
+{  DIMOFS_Y       =  FIELD_OFFSET(DIMOUSESTATE, lY);
+  DIMOFS_Z       =  FIELD_OFFSET(DIMOUSESTATE, lZ);
+  DIMOFS_BUTTON0 = (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 0);
+  DIMOFS_BUTTON1 = (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 1);
+  DIMOFS_BUTTON2 = (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 2);
+  DIMOFS_BUTTON3 = (FIELD_OFFSET(DIMOUSESTATE, rgbButtons) + 3);}
+{$IF DIRECTINPUT_VERSION >= $0700}
+{  DIMOFS_BUTTON4 = (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 4);
+  DIMOFS_BUTTON5 = (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 5);
+  DIMOFS_BUTTON6 = (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 6);
+  DIMOFS_BUTTON7 = (FIELD_OFFSET(DIMOUSESTATE2, rgbButtons) + 7);}
+{$ENDIF}
+//#endif /* DIJ_RINGZERO */
+
+(****************************************************************************
+ *
+ *      Keyboard
+ *
+ ****************************************************************************)
+
+//#ifndef DIJ_RINGZERO
+
+(****************************************************************************
+ *
+ *      DirectInput keyboard scan codes
+ *
+ ****************************************************************************)
+//
+//    Copyright (C) Microsoft.  All rights reserved.
+//
+const
+  DIK_ESCAPE          = $01;
+  DIK_1               = $02;
+  DIK_2               = $03;
+  DIK_3               = $04;
+  DIK_4               = $05;
+  DIK_5               = $06;
+  DIK_6               = $07;
+  DIK_7               = $08;
+  DIK_8               = $09;
+  DIK_9               = $0A;
+  DIK_0               = $0B;
+  DIK_MINUS           = $0C;    { - on main keyboard }
+  DIK_EQUALS          = $0D;
+  DIK_BACK            = $0E;    { backspace }
+  DIK_TAB             = $0F;
+  DIK_Q               = $10;
+  DIK_W               = $11;
+  DIK_E               = $12;
+  DIK_R               = $13;
+  DIK_T               = $14;
+  DIK_Y               = $15;
+  DIK_U               = $16;
+  DIK_I               = $17;
+  DIK_O               = $18;
+  DIK_P               = $19;
+  DIK_LBRACKET        = $1A;
+  DIK_RBRACKET        = $1B;
+  DIK_RETURN          = $1C;    { Enter on main keyboard }
+  DIK_LCONTROL        = $1D;
+  DIK_A               = $1E;
+  DIK_S               = $1F;
+  DIK_D               = $20;
+  DIK_F               = $21;
+  DIK_G               = $22;
+  DIK_H               = $23;
+  DIK_J               = $24;
+  DIK_K               = $25;
+  DIK_L               = $26;
+  DIK_SEMICOLON       = $27;
+  DIK_APOSTROPHE      = $28;
+  DIK_GRAVE           = $29;    { accent grave }
+  DIK_LSHIFT          = $2A;
+  DIK_BACKSLASH       = $2B;
+  DIK_Z               = $2C;
+  DIK_X               = $2D;
+  DIK_C               = $2E;
+  DIK_V               = $2F;
+  DIK_B               = $30;
+  DIK_N               = $31;
+  DIK_M               = $32;
+  DIK_COMMA           = $33;
+  DIK_PERIOD          = $34;    { . on main keyboard }
+  DIK_SLASH           = $35;    { / on main keyboard }
+  DIK_RSHIFT          = $36;
+  DIK_MULTIPLY        = $37;    { * on numeric keypad }
+  DIK_LMENU           = $38;    { left Alt }
+  DIK_SPACE           = $39;
+  DIK_CAPITAL         = $3A;
+  DIK_F1              = $3B;
+  DIK_F2              = $3C;
+  DIK_F3              = $3D;
+  DIK_F4              = $3E;
+  DIK_F5              = $3F;
+  DIK_F6              = $40;
+  DIK_F7              = $41;
+  DIK_F8              = $42;
+  DIK_F9              = $43;
+  DIK_F10             = $44;
+  DIK_NUMLOCK         = $45;
+  DIK_SCROLL          = $46;    { Scroll Lock }
+  DIK_NUMPAD7         = $47;
+  DIK_NUMPAD8         = $48;
+  DIK_NUMPAD9         = $49;
+  DIK_SUBTRACT        = $4A;    { - on numeric keypad }
+  DIK_NUMPAD4         = $4B;
+  DIK_NUMPAD5         = $4C;
+  DIK_NUMPAD6         = $4D;
+  DIK_ADD             = $4E;    { + on numeric keypad }
+  DIK_NUMPAD1         = $4F;
+  DIK_NUMPAD2         = $50;
+  DIK_NUMPAD3         = $51;
+  DIK_NUMPAD0         = $52;
+  DIK_DECIMAL         = $53;    { . on numeric keypad }
+  DIK_OEM_102         = $56;    { <> or \| on RT 102-key keyboard (Non-U.S.) }
+  DIK_F11             = $57;
+  DIK_F12             = $58;
+  DIK_F13             = $64;    {                     (NEC PC98) }
+  DIK_F14             = $65;    {                     (NEC PC98) }
+  DIK_F15             = $66;    {                     (NEC PC98) }
+  DIK_KANA            = $70;    { (Japanese keyboard)            }
+  DIK_ABNT_C1         = $73;    { /? on Brazilian keyboard }
+  DIK_CONVERT         = $79;    { (Japanese keyboard)            }
+  DIK_NOCONVERT       = $7B;    { (Japanese keyboard)            }
+  DIK_YEN             = $7D;    { (Japanese keyboard)            }
+  DIK_ABNT_C2         = $7E;    { Numpad . on Brazilian keyboard }
+  DIK_NUMPADEQUALS    = $8D;    { = on numeric keypad (NEC PC98) }
+  DIK_PREVTRACK       = $90;    { Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) }
+  DIK_AT              = $91;    {                     (NEC PC98) }
+  DIK_COLON           = $92;    {                     (NEC PC98) }
+  DIK_UNDERLINE       = $93;    {                     (NEC PC98) }
+  DIK_KANJI           = $94;    { (Japanese keyboard)            }
+  DIK_STOP            = $95;    {                     (NEC PC98) }
+  DIK_AX              = $96;    {                     (Japan AX) }
+  DIK_UNLABELED       = $97;    {                        (J3100) }
+  DIK_NEXTTRACK       = $99;    { Next Track }
+  DIK_NUMPADENTER     = $9C;    { Enter on numeric keypad }
+  DIK_RCONTROL        = $9D;
+  DIK_MUTE            = $A0;    { Mute }
+  DIK_CALCULATOR      = $A1;    { Calculator }
+  DIK_PLAYPAUSE       = $A2;    { Play / Pause }
+  DIK_MEDIASTOP       = $A4;    { Media Stop }
+  DIK_VOLUMEDOWN      = $AE;    { Volume - }
+  DIK_VOLUMEUP        = $B0;    { Volume + }
+  DIK_WEBHOME         = $B2;    { Web home }
+  DIK_NUMPADCOMMA     = $B3;    { , on numeric keypad (NEC PC98) }
+  DIK_DIVIDE          = $B5;    { / on numeric keypad }
+  DIK_SYSRQ           = $B7;
+  DIK_RMENU           = $B8;    { right Alt }
+  DIK_PAUSE           = $C5;    { Pause }
+  DIK_HOME            = $C7;    { Home on arrow keypad }
+  DIK_UP              = $C8;    { UpArrow on arrow keypad }
+  DIK_PRIOR           = $C9;    { PgUp on arrow keypad }
+  DIK_LEFT            = $CB;    { LeftArrow on arrow keypad }
+  DIK_RIGHT           = $CD;    { RightArrow on arrow keypad }
+  DIK_END             = $CF;    { End on arrow keypad }
+  DIK_DOWN            = $D0;    { DownArrow on arrow keypad }
+  DIK_NEXT            = $D1;    { PgDn on arrow keypad }
+  DIK_INSERT          = $D2;    { Insert on arrow keypad }
+  DIK_DELETE          = $D3;    { Delete on arrow keypad }
+  DIK_LWIN            = $DB;    { Left Windows key }
+  DIK_RWIN            = $DC;    { Right Windows key }
+  DIK_APPS            = $DD;    { AppMenu key }
+  DIK_POWER           = $DE;    { System Power }
+  DIK_SLEEP           = $DF;    { System Sleep }
+  DIK_WAKE            = $E3;    { System Wake }
+  DIK_WEBSEARCH       = $E5;    { Web Search }
+  DIK_WEBFAVORITES    = $E6;    { Web Favorites }
+  DIK_WEBREFRESH      = $E7;    { Web Refresh }
+  DIK_WEBSTOP         = $E8;    { Web Stop }
+  DIK_WEBFORWARD      = $E9;    { Web Forward }
+  DIK_WEBBACK         = $EA;    { Web Back }
+  DIK_MYCOMPUTER      = $EB;    { My Computer }
+  DIK_MAIL            = $EC;    { Mail }
+  DIK_MEDIASELECT     = $ED;    { Media Select }
+
+(*
+ *  Alternate names for keys, to facilitate transition from DOS.
+ *)
+  DIK_BACKSPACE       = DIK_BACK;            { backspace }
+  DIK_NUMPADSTAR      = DIK_MULTIPLY;        { * on numeric keypad }
+  DIK_LALT            = DIK_LMENU;           { left Alt }
+  DIK_CAPSLOCK        = DIK_CAPITAL;         { CapsLock }
+  DIK_NUMPADMINUS     = DIK_SUBTRACT;        { - on numeric keypad }
+  DIK_NUMPADPLUS      = DIK_ADD;             { + on numeric keypad }
+  DIK_NUMPADPERIOD    = DIK_DECIMAL;         { . on numeric keypad }
+  DIK_NUMPADSLASH     = DIK_DIVIDE;          { / on numeric keypad }
+  DIK_RALT            = DIK_RMENU;           { right Alt }
+  DIK_UPARROW         = DIK_UP;              { UpArrow on arrow keypad }
+  DIK_PGUP            = DIK_PRIOR;           { PgUp on arrow keypad }
+  DIK_LEFTARROW       = DIK_LEFT;            { LeftArrow on arrow keypad }
+  DIK_RIGHTARROW      = DIK_RIGHT;           { RightArrow on arrow keypad }
+  DIK_DOWNARROW       = DIK_DOWN;            { DownArrow on arrow keypad }
+  DIK_PGDN            = DIK_NEXT;            { PgDn on arrow keypad }
+
+(*
+ *  Alternate names for keys originally not used on US keyboards.
+ *)
+  DIK_CIRCUMFLEX      = DIK_PREVTRACK;       { Japanese keyboard }
+
+//#endif /* DIJ_RINGZERO */
+
+(****************************************************************************
+ *
+ *      Joystick
+ *
+ ****************************************************************************)
+
+//#ifndef DIJ_RINGZERO
+
+type
+  LPDIJOYSTATE = ^TDIJOYSTATE;
+  PDIJOYSTATE = ^TDIJOYSTATE;
+  TDIJOYSTATE = record
+    lX: LONG;                            { x-axis position              }
+    lY: LONG;                            { y-axis position              }
+    lZ: LONG;                            { z-axis position              }
+    lRx: LONG;                           { x-axis rotation              }
+    lRy: LONG;                           { y-axis rotation              }
+    lRz: LONG;                           { z-axis rotation              }
+    rglSlider: array [0..1] of LONG;     { extra axes positions         }
+    rgdwPOV: array [0..3] of DWORD;      { POV directions               }
+    rgbButtons: array [0..31] of BYTE;   { 32 buttons                   }
+  end;
+
+  LPDIJOYSTATE2 = ^TDIJOYSTATE2;
+  PDIJOYSTATE2 = ^TDIJOYSTATE2;
+  TDIJOYSTATE2 = record
+    lX: LONG;                            { x-axis position              }
+    lY: LONG;                            { y-axis position              }
+    lZ: LONG;                            { z-axis position              }
+    lRx: LONG;                           { x-axis rotation              }
+    lRy: LONG;                           { y-axis rotation              }
+    lRz: LONG;                           { z-axis rotation              }
+    rglSlider: array [0..1] of LONG;     { extra axes positions         }
+    rgdwPOV: array [0..3] of DWORD;      { POV directions               }
+    rgbButtons: array [0..127] of BYTE;  { 128 buttons                  }
+    lVX: LONG;                           { x-axis velocity              }
+    lVY: LONG;                           { y-axis velocity              }
+    lVZ: LONG;                           { z-axis velocity              }
+    lVRx: LONG;                          { x-axis angular velocity      }
+    lVRy: LONG;                          { y-axis angular velocity      }
+    lVRz: LONG;                          { z-axis angular velocity      }
+    rglVSlider: array [0..1] of LONG;    { extra axes velocities        }
+    lAX: LONG;                           { x-axis acceleration          }
+    lAY: LONG;                           { y-axis acceleration          }
+    lAZ: LONG;                           { z-axis acceleration          }
+    lARx: LONG;                          { x-axis angular acceleration  }
+    lARy: LONG;                          { y-axis angular acceleration  }
+    lARz: LONG;                          { z-axis angular acceleration  }
+    rglASlider: array [0..1] of LONG;    { extra axes accelerations     }
+    lFX: LONG;                           { x-axis force                 }
+    lFY: LONG;                           { y-axis force                 }
+    lFZ: LONG;                           { z-axis force                 }
+    lFRx: LONG;                          { x-axis torque                }
+    lFRy: LONG;                          { y-axis torque                }
+    lFRz: LONG;                          { z-axis torque                }
+    rglFSlider: array [0..1] of LONG;    { extra axes forces            }
+  end;
+
+(*#define DIJOFS_X            FIELD_OFFSET(DIJOYSTATE, lX)
+#define DIJOFS_Y            FIELD_OFFSET(DIJOYSTATE, lY)
+#define DIJOFS_Z            FIELD_OFFSET(DIJOYSTATE, lZ)
+#define DIJOFS_RX           FIELD_OFFSET(DIJOYSTATE, lRx)
+#define DIJOFS_RY           FIELD_OFFSET(DIJOYSTATE, lRy)
+#define DIJOFS_RZ           FIELD_OFFSET(DIJOYSTATE, lRz)
+#define DIJOFS_SLIDER(n)   (FIELD_OFFSET(DIJOYSTATE, rglSlider) + \
+                                                        (n) * sizeof(LONG))
+#define DIJOFS_POV(n)      (FIELD_OFFSET(DIJOYSTATE, rgdwPOV) + \
+                                                        (n) * sizeof(DWORD))
+#define DIJOFS_BUTTON(n)   (FIELD_OFFSET(DIJOYSTATE, rgbButtons) + (n))
+#define DIJOFS_BUTTON0      DIJOFS_BUTTON(0)
+#define DIJOFS_BUTTON1      DIJOFS_BUTTON(1)
+#define DIJOFS_BUTTON2      DIJOFS_BUTTON(2)
+#define DIJOFS_BUTTON3      DIJOFS_BUTTON(3)
+#define DIJOFS_BUTTON4      DIJOFS_BUTTON(4)
+#define DIJOFS_BUTTON5      DIJOFS_BUTTON(5)
+#define DIJOFS_BUTTON6      DIJOFS_BUTTON(6)
+#define DIJOFS_BUTTON7      DIJOFS_BUTTON(7)
+#define DIJOFS_BUTTON8      DIJOFS_BUTTON(8)
+#define DIJOFS_BUTTON9      DIJOFS_BUTTON(9)
+#define DIJOFS_BUTTON10     DIJOFS_BUTTON(10)
+#define DIJOFS_BUTTON11     DIJOFS_BUTTON(11)
+#define DIJOFS_BUTTON12     DIJOFS_BUTTON(12)
+#define DIJOFS_BUTTON13     DIJOFS_BUTTON(13)
+#define DIJOFS_BUTTON14     DIJOFS_BUTTON(14)
+#define DIJOFS_BUTTON15     DIJOFS_BUTTON(15)
+#define DIJOFS_BUTTON16     DIJOFS_BUTTON(16)
+#define DIJOFS_BUTTON17     DIJOFS_BUTTON(17)
+#define DIJOFS_BUTTON18     DIJOFS_BUTTON(18)
+#define DIJOFS_BUTTON19     DIJOFS_BUTTON(19)
+#define DIJOFS_BUTTON20     DIJOFS_BUTTON(20)
+#define DIJOFS_BUTTON21     DIJOFS_BUTTON(21)
+#define DIJOFS_BUTTON22     DIJOFS_BUTTON(22)
+#define DIJOFS_BUTTON23     DIJOFS_BUTTON(23)
+#define DIJOFS_BUTTON24     DIJOFS_BUTTON(24)
+#define DIJOFS_BUTTON25     DIJOFS_BUTTON(25)
+#define DIJOFS_BUTTON26     DIJOFS_BUTTON(26)
+#define DIJOFS_BUTTON27     DIJOFS_BUTTON(27)
+#define DIJOFS_BUTTON28     DIJOFS_BUTTON(28)
+#define DIJOFS_BUTTON29     DIJOFS_BUTTON(29)
+#define DIJOFS_BUTTON30     DIJOFS_BUTTON(30)
+#define DIJOFS_BUTTON31     DIJOFS_BUTTON(31)*)
+
+
+//#endif /* DIJ_RINGZERO */
+
+(****************************************************************************
+ *
+ *  IDirectInput
+ *
+ ****************************************************************************)
+
+//#ifndef DIJ_RINGZERO
+
+const
+  DIENUM_STOP           = 0;
+  DIENUM_CONTINUE       = 1;
+
+type
+  LPDIENUMDEVICESCALLBACKA = function(lpddi: LPCDIDEVICEINSTANCEA; pvRef: LPVOID): BOOL; stdcall;
+  LPDIENUMDEVICESCALLBACKW = function(lpddi: LPCDIDEVICEINSTANCEW; pvRef: LPVOID): BOOL; stdcall;
+{$IFDEF UNICODE}
+  LPDIENUMDEVICESCALLBACK = LPDIENUMDEVICESCALLBACKW;
+{$ELSE}
+  LPDIENUMDEVICESCALLBACK = LPDIENUMDEVICESCALLBACKA;
+{$ENDIF} // !UNICODE
+  LPDICONFIGUREDEVICESCALLBACK = function(lpDDSTarget: {IUnknown FAR *}IUnknown; pvRef: LPVOID): BOOL; stdcall;
+
+const
+  DIEDFL_ALLDEVICES      = $00000000;
+  DIEDFL_ATTACHEDONLY    = $00000001;
+{$IF DIRECTINPUT_VERSION >= $0500}
+  DIEDFL_FORCEFEEDBACK   = $00000100;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0500 }
+{$IF DIRECTINPUT_VERSION >= $050a}
+  DIEDFL_INCLUDEALIASES  = $00010000;
+  DIEDFL_INCLUDEPHANTOMS = $00020000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+{$IF DIRECTINPUT_VERSION >= $0800}
+  DIEDFL_INCLUDEHIDDEN   = $00040000;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+type
+  LPDIENUMDEVICESBYSEMANTICSCBA = function(lpddi: LPCDIDEVICEINSTANCEA; lpdid: LPDIRECTINPUTDEVICE8A; dwFlags: DWORD; dwRemaining: DWORD; pvRef: LPVOID): BOOL; stdcall;
+  LPDIENUMDEVICESBYSEMANTICSCBW = function(lpddi: LPCDIDEVICEINSTANCEW; lpdid: LPDIRECTINPUTDEVICE8W; dwFlags: DWORD; dwRemaining: DWORD; pvRef: LPVOID): BOOL; stdcall;
+{$IFDEF UNICODE}
+  LPDIENUMDEVICESBYSEMANTICSCB = LPDIENUMDEVICESBYSEMANTICSCBW;
+{$ELSE}
+  LPDIENUMDEVICESBYSEMANTICSCB = LPDIENUMDEVICESBYSEMANTICSCBA;
+{$ENDIF} // !UNICODE
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+const
+  DIEDBS_MAPPEDPRI1        = $00000001;
+  DIEDBS_MAPPEDPRI2        = $00000002;
+  DIEDBS_RECENTDEVICE      = $00000010;
+  DIEDBS_NEWDEVICE         = $00000020;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+const
+  DIEDBSFL_ATTACHEDONLY       = $00000000;
+  DIEDBSFL_THISUSER           = $00000010;
+  DIEDBSFL_FORCEFEEDBACK      = DIEDFL_FORCEFEEDBACK;
+  DIEDBSFL_AVAILABLEDEVICES   = $00001000;
+  DIEDBSFL_MULTIMICEKEYBOARDS = $00002000;
+  DIEDBSFL_NONGAMINGDEVICES   = $00004000;
+  DIEDBSFL_VALID              = $00007110;
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputW
+
+type
+  IDirectInputW = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputW methods ***)
+    function CreateDevice(const rguid: TGuid; out lplpDirectInputDevice: IDirectInputDeviceW; pUnkOuter: IUnknown): HRESULT; stdcall;
+    function EnumDevices(dwDevType: DWORD; lpCallback: LPDIENUMDEVICESCALLBACKW; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetDeviceStatus(const rguidInstance: TGuid): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD): HRESULT; stdcall;
+  end;
+
+//  typedef struct IDirectInputW *LPDIRECTINPUTW;
+  LPDIRECTINPUTW = IDirectInputW;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInputA
+
+  IDirectInputA = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputA methods ***)
+    function CreateDevice(const rguid: TGuid; out lplpDirectInputDevice: IDirectInputDeviceA; pUnkOuter: IUnknown): HRESULT; stdcall;
+    function EnumDevices(dwDevType: DWORD; lpCallback: LPDIENUMDEVICESCALLBACKA; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetDeviceStatus(const rguidInstance: TGuid): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInputA *LPDIRECTINPUTA;
+  LPDIRECTINPUTA = IDirectInputA;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInput: TIID = {IID_IDirectInputW}'{89521361-AA8A-11CF-BFC7-444553540000}';
+type
+  IDirectInput = IDirectInputW;
+{$ELSE}
+const
+  IID_IDirectInput: TIID = {IID_IDirectInputA}'{89521360-AA8A-11CF-BFC7-444553540000}';
+type
+  IDirectInput = IDirectInputA;
+{$ENDIF}
+//typedef struct IDirectInput *LPDIRECTINPUT;
+  LPDIRECTINPUT = IDirectInput;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInput_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInput_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInput_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInput_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+//#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+//#define IDirectInput_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+//#define IDirectInput_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInput_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+//#else
+//#define IDirectInput_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInput_AddRef(p) (p)->AddRef()
+//#define IDirectInput_Release(p) (p)->Release()
+//#define IDirectInput_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+//#define IDirectInput_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+//#define IDirectInput_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+//#define IDirectInput_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInput_Initialize(p,a,b) (p)->Initialize(a,b)
+//#endif
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInput2W
+
+type
+  IDirectInput2W = interface(IDirectInputW)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputW methods ***)
+    {STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;}
+
+    (*** IDirectInput2W methods ***)
+    function FindDevice(const rguidClass: TGuid; ptszName: LPCWSTR; pguidInstance: LPGUID): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput2W *LPDIRECTINPUT2W;
+  LPDIRECTINPUT2W = IDirectInput2W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInput2A
+
+  IDirectInput2A = interface(IDirectInputA)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInputA methods ***)
+    {STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;}
+
+    (*** IDirectInput2A methods ***)
+    function FindDevice(const rguidClass: TGuid; ptszName: LPCSTR; pguidInstance: LPGUID): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput2A *LPDIRECTINPUT2A;
+  LPDIRECTINPUT2A = IDirectInput2A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInput2: TIID = {IID_IDirectInput2W}'{5944E663-AA8A-11CF-BFC7-444553540000}';
+type
+  IDirectInput2 = IDirectInput2W;
+{$ELSE}
+const
+  IID_IDirectInput2: TIID = {IID_IDirectInput2A}'{5944E662-AA8A-11CF-BFC7-444553540000}';
+type
+  IDirectInput2 = IDirectInput2A;
+{$ENDIF}
+//typedef struct IDirectInput2 *LPDIRECTINPUT2;
+  LPDIRECTINPUT2 = IDirectInput2;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInput2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInput2_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInput2_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInput2_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+//#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+//#define IDirectInput2_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+//#define IDirectInput2_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInput2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+//#define IDirectInput2_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+//#else
+//#define IDirectInput2_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInput2_AddRef(p) (p)->AddRef()
+//#define IDirectInput2_Release(p) (p)->Release()
+//#define IDirectInput2_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+//#define IDirectInput2_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+//#define IDirectInput2_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+//#define IDirectInput2_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInput2_Initialize(p,a,b) (p)->Initialize(a,b)
+//#define IDirectInput2_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+//#endif
+
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInput7W
+
+type
+  IDirectInput7W = interface(IDirectInput2W)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInput2W methods ***)
+    {STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEW *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKW,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCWSTR,LPGUID) PURE;}
+
+    (*** IDirectInput7W methods ***)
+    function CreateDeviceEx(const rguid: TGuid; const riid: TIID; out pvOut: LPVOID; pUnkOuter: IUnknown): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput7W *LPDIRECTINPUT7W;
+  LPDIRECTINPUT7W = IDirectInput7W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInput7A
+
+  IDirectInput7A = interface(IDirectInput2A)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInput2A methods ***)
+    {STDMETHOD(CreateDevice)(THIS_ REFGUID,LPDIRECTINPUTDEVICEA *,LPUNKNOWN) PURE;
+    STDMETHOD(EnumDevices)(THIS_ DWORD,LPDIENUMDEVICESCALLBACKA,LPVOID,DWORD) PURE;
+    STDMETHOD(GetDeviceStatus)(THIS_ REFGUID) PURE;
+    STDMETHOD(RunControlPanel)(THIS_ HWND,DWORD) PURE;
+    STDMETHOD(Initialize)(THIS_ HINSTANCE,DWORD) PURE;
+    STDMETHOD(FindDevice)(THIS_ REFGUID,LPCSTR,LPGUID) PURE;}
+
+    (*** IDirectInput7A methods ***)
+    function CreateDeviceEx(const rguid: TGuid; const riid: TIID; out pvOut: LPVOID; pUnkOuter: IUnknown): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput7A *LPDIRECTINPUT7A;
+  LPDIRECTINPUT7A = IDirectInput7A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInput7: TIID = {IID_IDirectInput7W}'{9A4CB685-236D-11D3-8E9D-00C04F6844AE}';
+type
+  IDirectInput7 = IDirectInput7W;
+{$ELSE}
+const
+  IID_IDirectInput7: TIID = {IID_IDirectInput7A}'{9A4CB684-236D-11D3-8E9D-00C04F6844AE}';
+type
+  IDirectInput7 = IDirectInput7A;
+{$ENDIF}
+//typedef struct IDirectInput7 *LPDIRECTINPUT7;
+  LPDIRECTINPUT7 = IDirectInput7;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInput7_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInput7_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInput7_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInput7_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+//#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+//#define IDirectInput7_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+//#define IDirectInput7_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInput7_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+//#define IDirectInput7_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+//#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->lpVtbl->CreateDeviceEx(p,a,b,c,d)
+//#else
+//#define IDirectInput7_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInput7_AddRef(p) (p)->AddRef()
+//#define IDirectInput7_Release(p) (p)->Release()
+//#define IDirectInput7_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+//#define IDirectInput7_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+//#define IDirectInput7_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+//#define IDirectInput7_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInput7_Initialize(p,a,b) (p)->Initialize(a,b)
+//#define IDirectInput7_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+//#define IDirectInput7_CreateDeviceEx(p,a,b,c,d) (p)->CreateDeviceEx(a,b,c,d)
+//#endif
+
+{$IF DIRECTINPUT_VERSION >= $0800}
+//#undef INTERFACE
+//#define INTERFACE IDirectInput8W
+
+type
+  IDirectInput8W = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInput8W methods ***)
+    function CreateDevice(const rguid: TGuid; out lplpDirectInputDevice: IDirectInputDevice8W; pUnkOuter: IUnknown): HRESULT; stdcall;
+    function EnumDevices(dwDevType: DWORD; lpCallback: LPDIENUMDEVICESCALLBACKW; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetDeviceStatus(const rguidInstance: TGuid): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD): HRESULT; stdcall;
+    function FindDevice(const rguidClass: TGuid; ptszName: LPCWSTR; pguidInstance: LPGUID): HRESULT; stdcall;
+    function EnumDevicesBySemantics(ptszUserName: LPCWSTR; lpdiActionFormat: LPDIACTIONFORMATW; lpCallback: LPDIENUMDEVICESBYSEMANTICSCBW; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function ConfigureDevices(lpdiCallback: LPDICONFIGUREDEVICESCALLBACK; lpdiCDParams: LPDICONFIGUREDEVICESPARAMSW; dwFlags: DWORD; pvRefData: LPVOID): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput8W *LPDIRECTINPUT8W;
+  LPDIRECTINPUT8W = IDirectInput8W;
+
+//#undef INTERFACE
+//#define INTERFACE IDirectInput8A
+
+  IDirectInput8A = interface(IUnknown)
+    (*** IUnknown methods ***)
+    {STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+    STDMETHOD_(ULONG,AddRef)(THIS) PURE;
+    STDMETHOD_(ULONG,Release)(THIS) PURE;}
+
+    (*** IDirectInput8A methods ***)
+    function CreateDevice(const rguid: TGuid; out lplpDirectInputDevice: IDirectInputDevice8A; pUnkOuter: IUnknown): HRESULT; stdcall;
+    function EnumDevices(dwDevType: DWORD; lpCallback: LPDIENUMDEVICESCALLBACKA; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function GetDeviceStatus(const rguidInstance: TGuid): HRESULT; stdcall;
+    function RunControlPanel(hwndOwner: HWND; dwFlags: DWORD): HRESULT; stdcall;
+    function Initialize(hinst: HINST; dwVersion: DWORD): HRESULT; stdcall;
+    function FindDevice(const rguidClass: TGuid; ptszName: LPCSTR; pguidInstance: LPGUID): HRESULT; stdcall;
+    function EnumDevicesBySemantics(ptszUserName: LPCSTR; lpdiActionFormat: LPDIACTIONFORMATA; lpCallback: LPDIENUMDEVICESBYSEMANTICSCBA; pvRef: LPVOID; dwFlags: DWORD): HRESULT; stdcall;
+    function ConfigureDevices(lpdiCallback: LPDICONFIGUREDEVICESCALLBACK; lpdiCDParams: LPDICONFIGUREDEVICESPARAMSA; dwFlags: DWORD; pvRefData: LPVOID): HRESULT; stdcall;
+  end;
+
+//typedef struct IDirectInput8A *LPDIRECTINPUT8A;
+  LPDIRECTINPUT8A = IDirectInput8A;
+
+{$IFDEF UNICODE}
+const
+  IID_IDirectInput8: TIID = {IID_IDirectInput8W}'{BF798031-483A-4DA2-AA99-5D64ED369700}';
+type
+  IDirectInput8 = IDirectInput8W;
+{$ELSE}
+const
+  IID_IDirectInput8: TIID = {IID_IDirectInput8A}'{BF798030-483A-4DA2-AA99-5D64ED369700}';
+type
+  IDirectInput8 = IDirectInput8A;
+{$ENDIF}
+//typedef struct IDirectInput8 *LPDIRECTINPUT8;
+  LPDIRECTINPUT8 = IDirectInput8;
+
+//#if !defined(__cplusplus) || defined(CINTERFACE)
+//#define IDirectInput8_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
+//#define IDirectInput8_AddRef(p) (p)->lpVtbl->AddRef(p)
+//#define IDirectInput8_Release(p) (p)->lpVtbl->Release(p)
+//#define IDirectInput8_CreateDevice(p,a,b,c) (p)->lpVtbl->CreateDevice(p,a,b,c)
+//#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->lpVtbl->EnumDevices(p,a,b,c,d)
+//#define IDirectInput8_GetDeviceStatus(p,a) (p)->lpVtbl->GetDeviceStatus(p,a)
+//#define IDirectInput8_RunControlPanel(p,a,b) (p)->lpVtbl->RunControlPanel(p,a,b)
+//#define IDirectInput8_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b)
+//#define IDirectInput8_FindDevice(p,a,b,c) (p)->lpVtbl->FindDevice(p,a,b,c)
+//#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->lpVtbl->EnumDevicesBySemantics(p,a,b,c,d,e)
+//#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->lpVtbl->ConfigureDevices(p,a,b,c,d)
+//#else
+//#define IDirectInput8_QueryInterface(p,a,b) (p)->QueryInterface(a,b)
+//#define IDirectInput8_AddRef(p) (p)->AddRef()
+//#define IDirectInput8_Release(p) (p)->Release()
+//#define IDirectInput8_CreateDevice(p,a,b,c) (p)->CreateDevice(a,b,c)
+//#define IDirectInput8_EnumDevices(p,a,b,c,d) (p)->EnumDevices(a,b,c,d)
+//#define IDirectInput8_GetDeviceStatus(p,a) (p)->GetDeviceStatus(a)
+//#define IDirectInput8_RunControlPanel(p,a,b) (p)->RunControlPanel(a,b)
+//#define IDirectInput8_Initialize(p,a,b) (p)->Initialize(a,b)
+//#define IDirectInput8_FindDevice(p,a,b,c) (p)->FindDevice(a,b,c)
+//#define IDirectInput8_EnumDevicesBySemantics(p,a,b,c,d,e) (p)->EnumDevicesBySemantics(a,b,c,d,e)
+//#define IDirectInput8_ConfigureDevices(p,a,b,c,d) (p)->ConfigureDevices(a,b,c,d)
+//#endif
+{$ENDIF} { DIRECTINPUT_VERSION >= $0800 }
+
+{$IF DIRECTINPUT_VERSION > $0700}
+
+//extern HRESULT WINAPI DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
+function DirectInput8Create(hinst: HINST; dwVersion: DWORD; const riidltf: TIID; out ppvOut: LPVOID; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput8';
+
+{$ELSE}
+//extern HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter);
+function DirectInputCreateA(hinst: HINST; dwVersion: DWORD; out ppDI: IDirectInputA; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput';
+//extern HRESULT WINAPI DirectInputCreateW(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTW *ppDI, LPUNKNOWN punkOuter);
+function DirectInputCreateW(hinst: HINST; dwVersion: DWORD; out ppDI: IDirectInputW; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput';
+{$IFDEF UNICODE}
+function DirectInputCreate(hinst: HINST; dwVersion: DWORD; out ppDI: IDirectInputW; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput' name 'DirectInputCreateW';
+{$ELSE}
+function DirectInputCreate(hinst: HINST; dwVersion: DWORD; out ppDI: IDirectInputA; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput' name 'DirectInputCreateA';
+{$ENDIF} // !UNICODE
+
+//extern HRESULT WINAPI DirectInputCreateEx(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
+function DirectInputCreateEx(hinst: HINST; dwVersion: DWORD; const riidltf: TIID; out ppvOut: LPVOID; punkOuter: IUnknown): HRESULT; stdcall; external 'dinput';
+
+{$ENDIF} { DIRECTINPUT_VERSION > $700 }
+
+//#endif /* DIJ_RINGZERO */
+
+
+(****************************************************************************
+ *
+ *  Return Codes
+ *
+ ****************************************************************************)
+
+(*
+ *  The operation completed successfully.
+ *)
+const
+  DI_OK                           = S_OK;
+
+(*
+ *  The device exists but is not currently attached.
+ *)
+  DI_NOTATTACHED                  = S_FALSE;
+
+(*
+ *  The device buffer overflowed.  Some input was lost.
+ *)
+  DI_BUFFEROVERFLOW               = S_FALSE;
+
+(*
+ *  The change in device properties had no effect.
+ *)
+  DI_PROPNOEFFECT                 = S_FALSE;
+
+(*
+ *  The operation had no effect.
+ *)
+  DI_NOEFFECT                     = S_FALSE;
+
+(*
+ *  The device is a polled device.  As a result, device buffering
+ *  will not collect any data and event notifications will not be
+ *  signalled until GetDeviceState is called.
+ *)
+  DI_POLLEDDEVICE                 = HRESULT($00000002);
+
+(*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but the effect was not
+ *  downloaded because the device is not exclusively acquired
+ *  or because the DIEP_NODOWNLOAD flag was passed.
+ *)
+  DI_DOWNLOADSKIPPED              = HRESULT($00000003);
+
+(*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but in order to change
+ *  the parameters, the effect needed to be restarted.
+ *)
+  DI_EFFECTRESTARTED              = HRESULT($00000004);
+
+(*
+ *  The parameters of the effect were successfully updated by
+ *  IDirectInputEffect::SetParameters, but some of them were
+ *  beyond the capabilities of the device and were truncated.
+ *)
+  DI_TRUNCATED                    = HRESULT($00000008);
+
+(*
+ *  The settings have been successfully applied but could not be
+ *  persisted.
+ *)
+  DI_SETTINGSNOTSAVED             = HRESULT($0000000B);
+
+(*
+ *  Equal to DI_EFFECTRESTARTED | DI_TRUNCATED.
+ *)
+  DI_TRUNCATEDANDRESTARTED        = HRESULT($0000000C);
+
+(*
+ *  A SUCCESS code indicating that settings cannot be modified.
+ *)
+  DI_WRITEPROTECT                 = HRESULT($00000013);
+
+(*
+ *  The application requires a newer version of DirectInput.
+ *)
+//  DIERR_OLDDIRECTINPUTVERSION     \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_OLD_WIN_VERSION)
+
+(*
+ *  The application was written for an unsupported prerelease version
+ *  of DirectInput.
+ *)
+//  DIERR_BETADIRECTINPUTVERSION    \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_RMODE_APP)
+
+(*
+ *  The object could not be created due to an incompatible driver version
+ *  or mismatched or incomplete driver components.
+ *)
+//  DIERR_BADDRIVERVER              \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BAD_DRIVER_LEVEL)
+
+(*
+ * The device or device instance or effect is not registered with DirectInput.
+ *)
+  DIERR_DEVICENOTREG              = REGDB_E_CLASSNOTREG;
+
+(*
+ * The requested object does not exist.
+ *)
+//  DIERR_NOTFOUND                  \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+(*
+ * The requested object does not exist.
+ *)
+//  DIERR_OBJECTNOTFOUND            \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND)
+
+(*
+ * An invalid parameter was passed to the returning function,
+ * or the object was not in a state that admitted the function
+ * to be called.
+ *)
+  DIERR_INVALIDPARAM              = E_INVALIDARG;
+
+(*
+ * The specified interface is not supported by the object
+ *)
+  DIERR_NOINTERFACE               = E_NOINTERFACE;
+
+(*
+ * An undetermined error occured inside the DInput subsystem
+ *)
+  DIERR_GENERIC                   = E_FAIL;
+
+(*
+ * The DInput subsystem couldn't allocate sufficient memory to complete the
+ * caller's request.
+ *)
+  DIERR_OUTOFMEMORY               = E_OUTOFMEMORY;
+
+(*
+ * The function called is not supported at this time
+ *)
+  DIERR_UNSUPPORTED               = E_NOTIMPL;
+
+(*
+ * This object has not been initialized
+ *)
+//  DIERR_NOTINITIALIZED            \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_READY)
+
+(*
+ * This object is already initialized
+ *)
+//  DIERR_ALREADYINITIALIZED        \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED)
+
+(*
+ * This object does not support aggregation
+ *)
+  DIERR_NOAGGREGATION             = CLASS_E_NOAGGREGATION;
+
+(*
+ * Another app has a higher priority level, preventing this call from
+ * succeeding.
+ *)
+  DIERR_OTHERAPPHASPRIO           = E_ACCESSDENIED;
+
+(*
+ * Access to the device has been lost.  It must be re-acquired.
+ *)
+//  DIERR_INPUTLOST                 \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_READ_FAULT)
+
+(*
+ * The operation cannot be performed while the device is acquired.
+ *)
+//  DIERR_ACQUIRED                  \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_BUSY)
+
+(*
+ * The operation cannot be performed unless the device is acquired.
+ *)
+//  DIERR_NOTACQUIRED               \
+//    MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_ACCESS)
+
+(*
+ * The specified property cannot be changed.
+ *)
+  DIERR_READONLY                  = E_ACCESSDENIED;
+
+(*
+ * The device already has an event notification associated with it.
+ *)
+  DIERR_HANDLEEXISTS              = E_ACCESSDENIED;
+
+(*
+ * Data is not yet available.
+ *)
+//#ifndef E_PENDING
+  E_PENDING                       = $8000000A;
+//#endif
+
+(*
+ * Unable to IDirectInputJoyConfig_Acquire because the user
+ * does not have sufficient privileges to change the joystick
+ * configuration.
+ *)
+  DIERR_INSUFFICIENTPRIVS         = $80040200;
+
+(*
+ * The device is full.
+ *)
+  DIERR_DEVICEFULL                = $80040201;
+
+(*
+ * Not all the requested information fit into the buffer.
+ *)
+  DIERR_MOREDATA                  = $80040202;
+
+(*
+ * The effect is not downloaded.
+ *)
+  DIERR_NOTDOWNLOADED             = $80040203;
+
+(*
+ *  The device cannot be reinitialized because there are still effects
+ *  attached to it.
+ *)
+  DIERR_HASEFFECTS                = $80040204;
+
+(*
+ *  The operation cannot be performed unless the device is acquired
+ *  in DISCL_EXCLUSIVE mode.
+ *)
+  DIERR_NOTEXCLUSIVEACQUIRED      = $80040205;
+
+(*
+ *  The effect could not be downloaded because essential information
+ *  is missing.  For example, no axes have been associated with the
+ *  effect, or no type-specific information has been created.
+ *)
+  DIERR_INCOMPLETEEFFECT          = $80040206;
+
+(*
+ *  Attempted to read buffered device data from a device that is
+ *  not buffered.
+ *)
+  DIERR_NOTBUFFERED               = $80040207;
+
+(*
+ *  An attempt was made to modify parameters of an effect while it is
+ *  playing.  Not all hardware devices support altering the parameters
+ *  of an effect while it is playing.
+ *)
+  DIERR_EFFECTPLAYING             = $80040208;
+
+(*
+ *  The operation could not be completed because the device is not
+ *  plugged in.
+ *)
+  DIERR_UNPLUGGED                 = $80040209;
+
+(*
+ *  SendDeviceData failed because more information was requested
+ *  to be sent than can be sent to the device.  Some devices have
+ *  restrictions on how much data can be sent to them.  (For example,
+ *  there might be a limit on the number of buttons that can be
+ *  pressed at once.)
+ *)
+  DIERR_REPORTFULL                = $8004020A;
+
+
+(*
+ *  A mapper file function failed because reading or writing the user or IHV
+ *  settings file failed.
+ *)
+  DIERR_MAPFILEFAIL               = $8004020B;
+
+
+//
+//    Copyright (C) Microsoft.  All rights reserved.
+//
+
+
+//
+//    Copyright (C) Microsoft.  All rights reserved.
+//
+(*--- DINPUT Mapper Definitions: New for Dx8         ---*)
+
+
+(*--- Keyboard
+      Physical Keyboard Device       ---*)
+
+//
+//    Copyright (C) Microsoft.  All rights reserved.
+//
+  DIKEYBOARD_ESCAPE                       = $81000401;
+  DIKEYBOARD_1                            = $81000402;
+  DIKEYBOARD_2                            = $81000403;
+  DIKEYBOARD_3                            = $81000404;
+  DIKEYBOARD_4                            = $81000405;
+  DIKEYBOARD_5                            = $81000406;
+  DIKEYBOARD_6                            = $81000407;
+  DIKEYBOARD_7                            = $81000408;
+  DIKEYBOARD_8                            = $81000409;
+  DIKEYBOARD_9                            = $8100040A;
+  DIKEYBOARD_0                            = $8100040B;
+  DIKEYBOARD_MINUS                        = $8100040C;    { - on main keyboard }
+  DIKEYBOARD_EQUALS                       = $8100040D;
+  DIKEYBOARD_BACK                         = $8100040E;    { backspace }
+  DIKEYBOARD_TAB                          = $8100040F;
+  DIKEYBOARD_Q                            = $81000410;
+  DIKEYBOARD_W                            = $81000411;
+  DIKEYBOARD_E                            = $81000412;
+  DIKEYBOARD_R                            = $81000413;
+  DIKEYBOARD_T                            = $81000414;
+  DIKEYBOARD_Y                            = $81000415;
+  DIKEYBOARD_U                            = $81000416;
+  DIKEYBOARD_I                            = $81000417;
+  DIKEYBOARD_O                            = $81000418;
+  DIKEYBOARD_P                            = $81000419;
+  DIKEYBOARD_LBRACKET                     = $8100041A;
+  DIKEYBOARD_RBRACKET                     = $8100041B;
+  DIKEYBOARD_RETURN                       = $8100041C;    { Enter on main keyboard }
+  DIKEYBOARD_LCONTROL                     = $8100041D;
+  DIKEYBOARD_A                            = $8100041E;
+  DIKEYBOARD_S                            = $8100041F;
+  DIKEYBOARD_D                            = $81000420;
+  DIKEYBOARD_F                            = $81000421;
+  DIKEYBOARD_G                            = $81000422;
+  DIKEYBOARD_H                            = $81000423;
+  DIKEYBOARD_J                            = $81000424;
+  DIKEYBOARD_K                            = $81000425;
+  DIKEYBOARD_L                            = $81000426;
+  DIKEYBOARD_SEMICOLON                    = $81000427;
+  DIKEYBOARD_APOSTROPHE                   = $81000428;
+  DIKEYBOARD_GRAVE                        = $81000429;    { accent grave }
+  DIKEYBOARD_LSHIFT                       = $8100042A;
+  DIKEYBOARD_BACKSLASH                    = $8100042B;
+  DIKEYBOARD_Z                            = $8100042C;
+  DIKEYBOARD_X                            = $8100042D;
+  DIKEYBOARD_C                            = $8100042E;
+  DIKEYBOARD_V                            = $8100042F;
+  DIKEYBOARD_B                            = $81000430;
+  DIKEYBOARD_N                            = $81000431;
+  DIKEYBOARD_M                            = $81000432;
+  DIKEYBOARD_COMMA                        = $81000433;
+  DIKEYBOARD_PERIOD                       = $81000434;    { . on main keyboard }
+  DIKEYBOARD_SLASH                        = $81000435;    { / on main keyboard }
+  DIKEYBOARD_RSHIFT                       = $81000436;
+  DIKEYBOARD_MULTIPLY                     = $81000437;    { * on numeric keypad }
+  DIKEYBOARD_LMENU                        = $81000438;    { left Alt }
+  DIKEYBOARD_SPACE                        = $81000439;
+  DIKEYBOARD_CAPITAL                      = $8100043A;
+  DIKEYBOARD_F1                           = $8100043B;
+  DIKEYBOARD_F2                           = $8100043C;
+  DIKEYBOARD_F3                           = $8100043D;
+  DIKEYBOARD_F4                           = $8100043E;
+  DIKEYBOARD_F5                           = $8100043F;
+  DIKEYBOARD_F6                           = $81000440;
+  DIKEYBOARD_F7                           = $81000441;
+  DIKEYBOARD_F8                           = $81000442;
+  DIKEYBOARD_F9                           = $81000443;
+  DIKEYBOARD_F10                          = $81000444;
+  DIKEYBOARD_NUMLOCK                      = $81000445;
+  DIKEYBOARD_SCROLL                       = $81000446;    { Scroll Lock }
+  DIKEYBOARD_NUMPAD7                      = $81000447;
+  DIKEYBOARD_NUMPAD8                      = $81000448;
+  DIKEYBOARD_NUMPAD9                      = $81000449;
+  DIKEYBOARD_SUBTRACT                     = $8100044A;    { - on numeric keypad }
+  DIKEYBOARD_NUMPAD4                      = $8100044B;
+  DIKEYBOARD_NUMPAD5                      = $8100044C;
+  DIKEYBOARD_NUMPAD6                      = $8100044D;
+  DIKEYBOARD_ADD                          = $8100044E;    { + on numeric keypad }
+  DIKEYBOARD_NUMPAD1                      = $8100044F;
+  DIKEYBOARD_NUMPAD2                      = $81000450;
+  DIKEYBOARD_NUMPAD3                      = $81000451;
+  DIKEYBOARD_NUMPAD0                      = $81000452;
+  DIKEYBOARD_DECIMAL                      = $81000453;    { . on numeric keypad }
+  DIKEYBOARD_OEM_102                      = $81000456;    { <> or \| on RT 102-key keyboard (Non-U.S.) }
+  DIKEYBOARD_F11                          = $81000457;
+  DIKEYBOARD_F12                          = $81000458;
+  DIKEYBOARD_F13                          = $81000464;    {                     (NEC PC98) }
+  DIKEYBOARD_F14                          = $81000465;    {                     (NEC PC98) }
+  DIKEYBOARD_F15                          = $81000466;    {                     (NEC PC98) }
+  DIKEYBOARD_KANA                         = $81000470;    { (Japanese keyboard)            }
+  DIKEYBOARD_ABNT_C1                      = $81000473;    { /? on Brazilian keyboard }
+  DIKEYBOARD_CONVERT                      = $81000479;    { (Japanese keyboard)            }
+  DIKEYBOARD_NOCONVERT                    = $8100047B;    { (Japanese keyboard)            }
+  DIKEYBOARD_YEN                          = $8100047D;    { (Japanese keyboard)            }
+  DIKEYBOARD_ABNT_C2                      = $8100047E;    { Numpad . on Brazilian keyboard }
+  DIKEYBOARD_NUMPADEQUALS                 = $8100048D;    { = on numeric keypad (NEC PC98) }
+  DIKEYBOARD_PREVTRACK                    = $81000490;    { Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) }
+  DIKEYBOARD_AT                           = $81000491;    {                     (NEC PC98) }
+  DIKEYBOARD_COLON                        = $81000492;    {                     (NEC PC98) }
+  DIKEYBOARD_UNDERLINE                    = $81000493;    {                     (NEC PC98) }
+  DIKEYBOARD_KANJI                        = $81000494;    { (Japanese keyboard)            }
+  DIKEYBOARD_STOP                         = $81000495;    {                     (NEC PC98) }
+  DIKEYBOARD_AX                           = $81000496;    {                     (Japan AX) }
+  DIKEYBOARD_UNLABELED                    = $81000497;    {                        (J3100) }
+  DIKEYBOARD_NEXTTRACK                    = $81000499;    { Next Track }
+  DIKEYBOARD_NUMPADENTER                  = $8100049C;    { Enter on numeric keypad }
+  DIKEYBOARD_RCONTROL                     = $8100049D;
+  DIKEYBOARD_MUTE                         = $810004A0;    { Mute }
+  DIKEYBOARD_CALCULATOR                   = $810004A1;    { Calculator }
+  DIKEYBOARD_PLAYPAUSE                    = $810004A2;    { Play / Pause }
+  DIKEYBOARD_MEDIASTOP                    = $810004A4;    { Media Stop }
+  DIKEYBOARD_VOLUMEDOWN                   = $810004AE;    { Volume - }
+  DIKEYBOARD_VOLUMEUP                     = $810004B0;    { Volume + }
+  DIKEYBOARD_WEBHOME                      = $810004B2;    { Web home }
+  DIKEYBOARD_NUMPADCOMMA                  = $810004B3;    { , on numeric keypad (NEC PC98) }
+  DIKEYBOARD_DIVIDE                       = $810004B5;    { / on numeric keypad }
+  DIKEYBOARD_SYSRQ                        = $810004B7;
+  DIKEYBOARD_RMENU                        = $810004B8;    { right Alt }
+  DIKEYBOARD_PAUSE                        = $810004C5;    { Pause }
+  DIKEYBOARD_HOME                         = $810004C7;    { Home on arrow keypad }
+  DIKEYBOARD_UP                           = $810004C8;    { UpArrow on arrow keypad }
+  DIKEYBOARD_PRIOR                        = $810004C9;    { PgUp on arrow keypad }
+  DIKEYBOARD_LEFT                         = $810004CB;    { LeftArrow on arrow keypad }
+  DIKEYBOARD_RIGHT                        = $810004CD;    { RightArrow on arrow keypad }
+  DIKEYBOARD_END                          = $810004CF;    { End on arrow keypad }
+  DIKEYBOARD_DOWN                         = $810004D0;    { DownArrow on arrow keypad }
+  DIKEYBOARD_NEXT                         = $810004D1;    { PgDn on arrow keypad }
+  DIKEYBOARD_INSERT                       = $810004D2;    { Insert on arrow keypad }
+  DIKEYBOARD_DELETE                       = $810004D3;    { Delete on arrow keypad }
+  DIKEYBOARD_LWIN                         = $810004DB;    { Left Windows key }
+  DIKEYBOARD_RWIN                         = $810004DC;    { Right Windows key }
+  DIKEYBOARD_APPS                         = $810004DD;    { AppMenu key }
+  DIKEYBOARD_POWER                        = $810004DE;    { System Power }
+  DIKEYBOARD_SLEEP                        = $810004DF;    { System Sleep }
+  DIKEYBOARD_WAKE                         = $810004E3;    { System Wake }
+  DIKEYBOARD_WEBSEARCH                    = $810004E5;    { Web Search }
+  DIKEYBOARD_WEBFAVORITES                 = $810004E6;    { Web Favorites }
+  DIKEYBOARD_WEBREFRESH                   = $810004E7;    { Web Refresh }
+  DIKEYBOARD_WEBSTOP                      = $810004E8;    { Web Stop }
+  DIKEYBOARD_WEBFORWARD                   = $810004E9;    { Web Forward }
+  DIKEYBOARD_WEBBACK                      = $810004EA;    { Web Back }
+  DIKEYBOARD_MYCOMPUTER                   = $810004EB;    { My Computer }
+  DIKEYBOARD_MAIL                         = $810004EC;    { Mail }
+  DIKEYBOARD_MEDIASELECT                  = $810004ED;    { Media Select }
+
+
+(*--- MOUSE
+      Physical Mouse Device             ---*)
+
+{#define DIMOUSE_XAXISAB                         (0x82000200 |DIMOFS_X ) /* X Axis-absolute: Some mice natively report absolute coordinates  */
+#define DIMOUSE_YAXISAB                         (0x82000200 |DIMOFS_Y ) /* Y Axis-absolute: Some mice natively report absolute coordinates */
+#define DIMOUSE_XAXIS                           (0x82000300 |DIMOFS_X ) /* X Axis */
+#define DIMOUSE_YAXIS                           (0x82000300 |DIMOFS_Y ) /* Y Axis */
+#define DIMOUSE_WHEEL                           (0x82000300 |DIMOFS_Z ) /* Z Axis */
+#define DIMOUSE_BUTTON0                         (0x82000400 |DIMOFS_BUTTON0) /* Button 0 */
+#define DIMOUSE_BUTTON1                         (0x82000400 |DIMOFS_BUTTON1) /* Button 1 */
+#define DIMOUSE_BUTTON2                         (0x82000400 |DIMOFS_BUTTON2) /* Button 2 */
+#define DIMOUSE_BUTTON3                         (0x82000400 |DIMOFS_BUTTON3) /* Button 3 */
+#define DIMOUSE_BUTTON4                         (0x82000400 |DIMOFS_BUTTON4) /* Button 4 */
+#define DIMOUSE_BUTTON5                         (0x82000400 |DIMOFS_BUTTON5) /* Button 5 */
+#define DIMOUSE_BUTTON6                         (0x82000400 |DIMOFS_BUTTON6) /* Button 6 */
+#define DIMOUSE_BUTTON7                         (0x82000400 |DIMOFS_BUTTON7) /* Button 7 */}
+
+
+(*--- VOICE
+      Physical Dplay Voice Device       ---*)
+
+  DIVOICE_CHANNEL1                        = $83000401;
+  DIVOICE_CHANNEL2                        = $83000402;
+  DIVOICE_CHANNEL3                        = $83000403;
+  DIVOICE_CHANNEL4                        = $83000404;
+  DIVOICE_CHANNEL5                        = $83000405;
+  DIVOICE_CHANNEL6                        = $83000406;
+  DIVOICE_CHANNEL7                        = $83000407;
+  DIVOICE_CHANNEL8                        = $83000408;
+  DIVOICE_TEAM                            = $83000409;
+  DIVOICE_ALL                             = $8300040A;
+  DIVOICE_RECORDMUTE                      = $8300040B;
+  DIVOICE_PLAYBACKMUTE                    = $8300040C;
+  DIVOICE_TRANSMIT                        = $8300040D;
+
+  DIVOICE_VOICECOMMAND                    = $83000410;
+
+
+(*--- Driving Simulator - Racing
+      Vehicle control is primary objective  ---*)
+  DIVIRTUAL_DRIVING_RACE                  = $01000000;
+  DIAXIS_DRIVINGR_STEER                   = $01008A01; { Steering }
+  DIAXIS_DRIVINGR_ACCELERATE              = $01039202; { Accelerate }
+  DIAXIS_DRIVINGR_BRAKE                   = $01041203; { Brake-Axis }
+  DIBUTTON_DRIVINGR_SHIFTUP               = $01000C01; { Shift to next higher gear }
+  DIBUTTON_DRIVINGR_SHIFTDOWN             = $01000C02; { Shift to next lower gear }
+  DIBUTTON_DRIVINGR_VIEW                  = $01001C03; { Cycle through view options }
+  DIBUTTON_DRIVINGR_MENU                  = $010004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIAXIS_DRIVINGR_ACCEL_AND_BRAKE         = $01014A04; { Some devices combine accelerate and brake in a single axis }
+  DIHATSWITCH_DRIVINGR_GLANCE             = $01004601; { Look around }
+  DIBUTTON_DRIVINGR_BRAKE                 = $01004C04; { Brake-button }
+  DIBUTTON_DRIVINGR_DASHBOARD             = $01004405; { Select next dashboard option }
+  DIBUTTON_DRIVINGR_AIDS                  = $01004406; { Driver correction aids }
+  DIBUTTON_DRIVINGR_MAP                   = $01004407; { Display Driving Map }
+  DIBUTTON_DRIVINGR_BOOST                 = $01004408; { Turbo Boost }
+  DIBUTTON_DRIVINGR_PIT                   = $01004409; { Pit stop notification }
+  DIBUTTON_DRIVINGR_ACCELERATE_LINK       = $0103D4E0; { Fallback Accelerate button }
+  DIBUTTON_DRIVINGR_STEER_LEFT_LINK       = $0100CCE4; { Fallback Steer Left button }
+  DIBUTTON_DRIVINGR_STEER_RIGHT_LINK      = $0100CCEC; { Fallback Steer Right button }
+  DIBUTTON_DRIVINGR_GLANCE_LEFT_LINK      = $0107C4E4; { Fallback Glance Left button }
+  DIBUTTON_DRIVINGR_GLANCE_RIGHT_LINK     = $0107C4EC; { Fallback Glance Right button }
+  DIBUTTON_DRIVINGR_DEVICE                = $010044FE; { Show input device and controls }
+  DIBUTTON_DRIVINGR_PAUSE                 = $010044FC; { Start / Pause / Restart game }
+
+(*--- Driving Simulator - Combat
+      Combat from within a vehicle is primary objective  ---*)
+  DIVIRTUAL_DRIVING_COMBAT                = $02000000;
+  DIAXIS_DRIVINGC_STEER                   = $02008A01; { Steering  }
+  DIAXIS_DRIVINGC_ACCELERATE              = $02039202; { Accelerate }
+  DIAXIS_DRIVINGC_BRAKE                   = $02041203; { Brake-axis }
+  DIBUTTON_DRIVINGC_FIRE                  = $02000C01; { Fire }
+  DIBUTTON_DRIVINGC_WEAPONS               = $02000C02; { Select next weapon }
+  DIBUTTON_DRIVINGC_TARGET                = $02000C03; { Select next available target }
+  DIBUTTON_DRIVINGC_MENU                  = $020004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIAXIS_DRIVINGC_ACCEL_AND_BRAKE         = $02014A04; { Some devices combine accelerate and brake in a single axis }
+  DIHATSWITCH_DRIVINGC_GLANCE             = $02004601; { Look around }
+  DIBUTTON_DRIVINGC_SHIFTUP               = $02004C04; { Shift to next higher gear }
+  DIBUTTON_DRIVINGC_SHIFTDOWN             = $02004C05; { Shift to next lower gear }
+  DIBUTTON_DRIVINGC_DASHBOARD             = $02004406; { Select next dashboard option }
+  DIBUTTON_DRIVINGC_AIDS                  = $02004407; { Driver correction aids }
+  DIBUTTON_DRIVINGC_BRAKE                 = $02004C08; { Brake-button }
+  DIBUTTON_DRIVINGC_FIRESECONDARY         = $02004C09; { Alternative fire button }
+  DIBUTTON_DRIVINGC_ACCELERATE_LINK       = $0203D4E0; { Fallback Accelerate button }
+  DIBUTTON_DRIVINGC_STEER_LEFT_LINK       = $0200CCE4; { Fallback Steer Left button }
+  DIBUTTON_DRIVINGC_STEER_RIGHT_LINK      = $0200CCEC; { Fallback Steer Right button }
+  DIBUTTON_DRIVINGC_GLANCE_LEFT_LINK      = $0207C4E4; { Fallback Glance Left button }
+  DIBUTTON_DRIVINGC_GLANCE_RIGHT_LINK     = $0207C4EC; { Fallback Glance Right button }
+  DIBUTTON_DRIVINGC_DEVICE                = $020044FE; { Show input device and controls }
+  DIBUTTON_DRIVINGC_PAUSE                 = $020044FC; { Start / Pause / Restart game }
+
+(*--- Driving Simulator - Tank
+      Combat from withing a tank is primary objective  ---*)
+  DIVIRTUAL_DRIVING_TANK                  = $03000000;
+  DIAXIS_DRIVINGT_STEER                   = $03008A01; { Turn tank left / right }
+  DIAXIS_DRIVINGT_BARREL                  = $03010202; { Raise / lower barrel }
+  DIAXIS_DRIVINGT_ACCELERATE              = $03039203; { Accelerate }
+  DIAXIS_DRIVINGT_ROTATE                  = $03020204; { Turn barrel left / right }
+  DIBUTTON_DRIVINGT_FIRE                  = $03000C01; { Fire }
+  DIBUTTON_DRIVINGT_WEAPONS               = $03000C02; { Select next weapon }
+  DIBUTTON_DRIVINGT_TARGET                = $03000C03; { Selects next available target }
+  DIBUTTON_DRIVINGT_MENU                  = $030004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_DRIVINGT_GLANCE             = $03004601; { Look around }
+  DIAXIS_DRIVINGT_BRAKE                   = $03045205; { Brake-axis }
+  DIAXIS_DRIVINGT_ACCEL_AND_BRAKE         = $03014A06; { Some devices combine accelerate and brake in a single axis }
+  DIBUTTON_DRIVINGT_VIEW                  = $03005C04; { Cycle through view options }
+  DIBUTTON_DRIVINGT_DASHBOARD             = $03005C05; { Select next dashboard option }
+  DIBUTTON_DRIVINGT_BRAKE                 = $03004C06; { Brake-button }
+  DIBUTTON_DRIVINGT_FIRESECONDARY         = $03004C07; { Alternative fire button }
+  DIBUTTON_DRIVINGT_ACCELERATE_LINK       = $0303D4E0; { Fallback Accelerate button }
+  DIBUTTON_DRIVINGT_STEER_LEFT_LINK       = $0300CCE4; { Fallback Steer Left button }
+  DIBUTTON_DRIVINGT_STEER_RIGHT_LINK      = $0300CCEC; { Fallback Steer Right button }
+  DIBUTTON_DRIVINGT_BARREL_UP_LINK        = $030144E0; { Fallback Barrel up button }
+  DIBUTTON_DRIVINGT_BARREL_DOWN_LINK      = $030144E8; { Fallback Barrel down button }
+  DIBUTTON_DRIVINGT_ROTATE_LEFT_LINK      = $030244E4; { Fallback Rotate left button }
+  DIBUTTON_DRIVINGT_ROTATE_RIGHT_LINK     = $030244EC; { Fallback Rotate right button }
+  DIBUTTON_DRIVINGT_GLANCE_LEFT_LINK      = $0307C4E4; { Fallback Glance Left button }
+  DIBUTTON_DRIVINGT_GLANCE_RIGHT_LINK     = $0307C4EC; { Fallback Glance Right button }
+  DIBUTTON_DRIVINGT_DEVICE                = $030044FE; { Show input device and controls }
+  DIBUTTON_DRIVINGT_PAUSE                 = $030044FC; { Start / Pause / Restart game }
+
+(*--- Flight Simulator - Civilian
+      Plane control is the primary objective  ---*)
+  DIVIRTUAL_FLYING_CIVILIAN               = $04000000;
+  DIAXIS_FLYINGC_BANK                     = $04008A01; { Roll ship left / right }
+  DIAXIS_FLYINGC_PITCH                    = $04010A02; { Nose up / down }
+  DIAXIS_FLYINGC_THROTTLE                 = $04039203; { Throttle }
+  DIBUTTON_FLYINGC_VIEW                   = $04002401; { Cycle through view options }
+  DIBUTTON_FLYINGC_DISPLAY                = $04002402; { Select next dashboard / heads up display option }
+  DIBUTTON_FLYINGC_GEAR                   = $04002C03; { Gear up / down }
+  DIBUTTON_FLYINGC_MENU                   = $040004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_FLYINGC_GLANCE              = $04004601; { Look around }
+  DIAXIS_FLYINGC_BRAKE                    = $04046A04; { Apply Brake }
+  DIAXIS_FLYINGC_RUDDER                   = $04025205; { Yaw ship left/right }
+  DIAXIS_FLYINGC_FLAPS                    = $04055A06; { Flaps }
+  DIBUTTON_FLYINGC_FLAPSUP                = $04006404; { Increment stepping up until fully retracted }
+  DIBUTTON_FLYINGC_FLAPSDOWN              = $04006405; { Decrement stepping down until fully extended }
+  DIBUTTON_FLYINGC_BRAKE_LINK             = $04046CE0; { Fallback brake button }
+  DIBUTTON_FLYINGC_FASTER_LINK            = $0403D4E0; { Fallback throttle up button }
+  DIBUTTON_FLYINGC_SLOWER_LINK            = $0403D4E8; { Fallback throttle down button }
+  DIBUTTON_FLYINGC_GLANCE_LEFT_LINK       = $0407C4E4; { Fallback Glance Left button }
+  DIBUTTON_FLYINGC_GLANCE_RIGHT_LINK      = $0407C4EC; { Fallback Glance Right button }
+  DIBUTTON_FLYINGC_GLANCE_UP_LINK         = $0407C4E0; { Fallback Glance Up button }
+  DIBUTTON_FLYINGC_GLANCE_DOWN_LINK       = $0407C4E8; { Fallback Glance Down button }
+  DIBUTTON_FLYINGC_DEVICE                 = $040044FE; { Show input device and controls }
+  DIBUTTON_FLYINGC_PAUSE                  = $040044FC; { Start / Pause / Restart game }
+
+(*--- Flight Simulator - Military
+      Aerial combat is the primary objective  ---*)
+  DIVIRTUAL_FLYING_MILITARY               = $05000000;
+  DIAXIS_FLYINGM_BANK                     = $05008A01; { Bank - Roll ship left / right }
+  DIAXIS_FLYINGM_PITCH                    = $05010A02; { Pitch - Nose up / down }
+  DIAXIS_FLYINGM_THROTTLE                 = $05039203; { Throttle - faster / slower }
+  DIBUTTON_FLYINGM_FIRE                   = $05000C01; { Fire }
+  DIBUTTON_FLYINGM_WEAPONS                = $05000C02; { Select next weapon }
+  DIBUTTON_FLYINGM_TARGET                 = $05000C03; { Selects next available target }
+  DIBUTTON_FLYINGM_MENU                   = $050004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_FLYINGM_GLANCE              = $05004601; { Look around }
+  DIBUTTON_FLYINGM_COUNTER                = $05005C04; { Activate counter measures }
+  DIAXIS_FLYINGM_RUDDER                   = $05024A04; { Rudder - Yaw ship left/right }
+  DIAXIS_FLYINGM_BRAKE                    = $05046205; { Brake-axis }
+  DIBUTTON_FLYINGM_VIEW                   = $05006405; { Cycle through view options }
+  DIBUTTON_FLYINGM_DISPLAY                = $05006406; { Select next dashboard option }
+  DIAXIS_FLYINGM_FLAPS                    = $05055206; { Flaps }
+  DIBUTTON_FLYINGM_FLAPSUP                = $05005407; { Increment stepping up until fully retracted }
+  DIBUTTON_FLYINGM_FLAPSDOWN              = $05005408; { Decrement stepping down until fully extended }
+  DIBUTTON_FLYINGM_FIRESECONDARY          = $05004C09; { Alternative fire button }
+  DIBUTTON_FLYINGM_GEAR                   = $0500640A; { Gear up / down }
+  DIBUTTON_FLYINGM_BRAKE_LINK             = $050464E0; { Fallback brake button }
+  DIBUTTON_FLYINGM_FASTER_LINK            = $0503D4E0; { Fallback throttle up button }
+  DIBUTTON_FLYINGM_SLOWER_LINK            = $0503D4E8; { Fallback throttle down button }
+  DIBUTTON_FLYINGM_GLANCE_LEFT_LINK       = $0507C4E4; { Fallback Glance Left button }
+  DIBUTTON_FLYINGM_GLANCE_RIGHT_LINK      = $0507C4EC; { Fallback Glance Right button }
+  DIBUTTON_FLYINGM_GLANCE_UP_LINK         = $0507C4E0; { Fallback Glance Up button }
+  DIBUTTON_FLYINGM_GLANCE_DOWN_LINK       = $0507C4E8; { Fallback Glance Down button }
+  DIBUTTON_FLYINGM_DEVICE                 = $050044FE; { Show input device and controls }
+  DIBUTTON_FLYINGM_PAUSE                  = $050044FC; { Start / Pause / Restart game }
+
+(*--- Flight Simulator - Combat Helicopter
+      Combat from helicopter is primary objective  ---*)
+  DIVIRTUAL_FLYING_HELICOPTER             = $06000000;
+  DIAXIS_FLYINGH_BANK                     = $06008A01; { Bank - Roll ship left / right }
+  DIAXIS_FLYINGH_PITCH                    = $06010A02; { Pitch - Nose up / down }
+  DIAXIS_FLYINGH_COLLECTIVE               = $06018A03; { Collective - Blade pitch/power }
+  DIBUTTON_FLYINGH_FIRE                   = $06001401; { Fire }
+  DIBUTTON_FLYINGH_WEAPONS                = $06001402; { Select next weapon }
+  DIBUTTON_FLYINGH_TARGET                 = $06001403; { Selects next available target }
+  DIBUTTON_FLYINGH_MENU                   = $060004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_FLYINGH_GLANCE              = $06004601; { Look around }
+  DIAXIS_FLYINGH_TORQUE                   = $06025A04; { Torque - Rotate ship around left / right axis }
+  DIAXIS_FLYINGH_THROTTLE                 = $0603DA05; { Throttle }
+  DIBUTTON_FLYINGH_COUNTER                = $06005404; { Activate counter measures }
+  DIBUTTON_FLYINGH_VIEW                   = $06006405; { Cycle through view options }
+  DIBUTTON_FLYINGH_GEAR                   = $06006406; { Gear up / down }
+  DIBUTTON_FLYINGH_FIRESECONDARY          = $06004C07; { Alternative fire button }
+  DIBUTTON_FLYINGH_FASTER_LINK            = $0603DCE0; { Fallback throttle up button }
+  DIBUTTON_FLYINGH_SLOWER_LINK            = $0603DCE8; { Fallback throttle down button }
+  DIBUTTON_FLYINGH_GLANCE_LEFT_LINK       = $0607C4E4; { Fallback Glance Left button }
+  DIBUTTON_FLYINGH_GLANCE_RIGHT_LINK      = $0607C4EC; { Fallback Glance Right button }
+  DIBUTTON_FLYINGH_GLANCE_UP_LINK         = $0607C4E0; { Fallback Glance Up button }
+  DIBUTTON_FLYINGH_GLANCE_DOWN_LINK       = $0607C4E8; { Fallback Glance Down button }
+  DIBUTTON_FLYINGH_DEVICE                 = $060044FE; { Show input device and controls }
+  DIBUTTON_FLYINGH_PAUSE                  = $060044FC; { Start / Pause / Restart game }
+
+(*--- Space Simulator - Combat
+      Space Simulator with weapons  ---*)
+  DIVIRTUAL_SPACESIM                      = $07000000;
+  DIAXIS_SPACESIM_LATERAL                 = $07008201; { Move ship left / right }
+  DIAXIS_SPACESIM_MOVE                    = $07010202; { Move ship forward/backward }
+  DIAXIS_SPACESIM_THROTTLE                = $07038203; { Throttle - Engine speed }
+  DIBUTTON_SPACESIM_FIRE                  = $07000401; { Fire }
+  DIBUTTON_SPACESIM_WEAPONS               = $07000402; { Select next weapon }
+  DIBUTTON_SPACESIM_TARGET                = $07000403; { Selects next available target }
+  DIBUTTON_SPACESIM_MENU                  = $070004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_SPACESIM_GLANCE             = $07004601; { Look around }
+  DIAXIS_SPACESIM_CLIMB                   = $0701C204; { Climb - Pitch ship up/down }
+  DIAXIS_SPACESIM_ROTATE                  = $07024205; { Rotate - Turn ship left/right }
+  DIBUTTON_SPACESIM_VIEW                  = $07004404; { Cycle through view options }
+  DIBUTTON_SPACESIM_DISPLAY               = $07004405; { Select next dashboard / heads up display option }
+  DIBUTTON_SPACESIM_RAISE                 = $07004406; { Raise ship while maintaining current pitch }
+  DIBUTTON_SPACESIM_LOWER                 = $07004407; { Lower ship while maintaining current pitch }
+  DIBUTTON_SPACESIM_GEAR                  = $07004408; { Gear up / down }
+  DIBUTTON_SPACESIM_FIRESECONDARY         = $07004409; { Alternative fire button }
+  DIBUTTON_SPACESIM_LEFT_LINK             = $0700C4E4; { Fallback move left button }
+  DIBUTTON_SPACESIM_RIGHT_LINK            = $0700C4EC; { Fallback move right button }
+  DIBUTTON_SPACESIM_FORWARD_LINK          = $070144E0; { Fallback move forward button }
+  DIBUTTON_SPACESIM_BACKWARD_LINK         = $070144E8; { Fallback move backwards button }
+  DIBUTTON_SPACESIM_FASTER_LINK           = $0703C4E0; { Fallback throttle up button }
+  DIBUTTON_SPACESIM_SLOWER_LINK           = $0703C4E8; { Fallback throttle down button }
+  DIBUTTON_SPACESIM_TURN_LEFT_LINK        = $070244E4; { Fallback turn left button }
+  DIBUTTON_SPACESIM_TURN_RIGHT_LINK       = $070244EC; { Fallback turn right button }
+  DIBUTTON_SPACESIM_GLANCE_LEFT_LINK      = $0707C4E4; { Fallback Glance Left button }
+  DIBUTTON_SPACESIM_GLANCE_RIGHT_LINK     = $0707C4EC; { Fallback Glance Right button }
+  DIBUTTON_SPACESIM_GLANCE_UP_LINK        = $0707C4E0; { Fallback Glance Up button }
+  DIBUTTON_SPACESIM_GLANCE_DOWN_LINK      = $0707C4E8; { Fallback Glance Down button }
+  DIBUTTON_SPACESIM_DEVICE                = $070044FE; { Show input device and controls }
+  DIBUTTON_SPACESIM_PAUSE                 = $070044FC; { Start / Pause / Restart game }
+
+(*--- Fighting - First Person
+      Hand to Hand combat is primary objective  ---*)
+  DIVIRTUAL_FIGHTING_HAND2HAND            = $08000000;
+  DIAXIS_FIGHTINGH_LATERAL                = $08008201; { Sidestep left/right }
+  DIAXIS_FIGHTINGH_MOVE                   = $08010202; { Move forward/backward }
+  DIBUTTON_FIGHTINGH_PUNCH                = $08000401; { Punch }
+  DIBUTTON_FIGHTINGH_KICK                 = $08000402; { Kick }
+  DIBUTTON_FIGHTINGH_BLOCK                = $08000403; { Block }
+  DIBUTTON_FIGHTINGH_CROUCH               = $08000404; { Crouch }
+  DIBUTTON_FIGHTINGH_JUMP                 = $08000405; { Jump }
+  DIBUTTON_FIGHTINGH_SPECIAL1             = $08000406; { Apply first special move }
+  DIBUTTON_FIGHTINGH_SPECIAL2             = $08000407; { Apply second special move }
+  DIBUTTON_FIGHTINGH_MENU                 = $080004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_FIGHTINGH_SELECT               = $08004408; { Select special move }
+  DIHATSWITCH_FIGHTINGH_SLIDE             = $08004601; { Look around }
+  DIBUTTON_FIGHTINGH_DISPLAY              = $08004409; { Shows next on-screen display option }
+  DIAXIS_FIGHTINGH_ROTATE                 = $08024203; { Rotate - Turn body left/right }
+  DIBUTTON_FIGHTINGH_DODGE                = $0800440A; { Dodge }
+  DIBUTTON_FIGHTINGH_LEFT_LINK            = $0800C4E4; { Fallback left sidestep button }
+  DIBUTTON_FIGHTINGH_RIGHT_LINK           = $0800C4EC; { Fallback right sidestep button }
+  DIBUTTON_FIGHTINGH_FORWARD_LINK         = $080144E0; { Fallback forward button }
+  DIBUTTON_FIGHTINGH_BACKWARD_LINK        = $080144E8; { Fallback backward button }
+  DIBUTTON_FIGHTINGH_DEVICE               = $080044FE; { Show input device and controls }
+  DIBUTTON_FIGHTINGH_PAUSE                = $080044FC; { Start / Pause / Restart game }
+
+(*--- Fighting - First Person Shooting
+      Navigation and combat are primary objectives  ---*)
+  DIVIRTUAL_FIGHTING_FPS                  = $09000000;
+  DIAXIS_FPS_ROTATE                       = $09008201; { Rotate character left/right }
+  DIAXIS_FPS_MOVE                         = $09010202; { Move forward/backward }
+  DIBUTTON_FPS_FIRE                       = $09000401; { Fire }
+  DIBUTTON_FPS_WEAPONS                    = $09000402; { Select next weapon }
+  DIBUTTON_FPS_APPLY                      = $09000403; { Use item }
+  DIBUTTON_FPS_SELECT                     = $09000404; { Select next inventory item }
+  DIBUTTON_FPS_CROUCH                     = $09000405; { Crouch/ climb down/ swim down }
+  DIBUTTON_FPS_JUMP                       = $09000406; { Jump/ climb up/ swim up }
+  DIAXIS_FPS_LOOKUPDOWN                   = $09018203; { Look up / down  }
+  DIBUTTON_FPS_STRAFE                     = $09000407; { Enable strafing while active }
+  DIBUTTON_FPS_MENU                       = $090004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_FPS_GLANCE                  = $09004601; { Look around }
+  DIBUTTON_FPS_DISPLAY                    = $09004408; { Shows next on-screen display option/ map }
+  DIAXIS_FPS_SIDESTEP                     = $09024204; { Sidestep }
+  DIBUTTON_FPS_DODGE                      = $09004409; { Dodge }
+  DIBUTTON_FPS_GLANCEL                    = $0900440A; { Glance Left }
+  DIBUTTON_FPS_GLANCER                    = $0900440B; { Glance Right }
+  DIBUTTON_FPS_FIRESECONDARY              = $0900440C; { Alternative fire button }
+  DIBUTTON_FPS_ROTATE_LEFT_LINK           = $0900C4E4; { Fallback rotate left button }
+  DIBUTTON_FPS_ROTATE_RIGHT_LINK          = $0900C4EC; { Fallback rotate right button }
+  DIBUTTON_FPS_FORWARD_LINK               = $090144E0; { Fallback forward button }
+  DIBUTTON_FPS_BACKWARD_LINK              = $090144E8; { Fallback backward button }
+  DIBUTTON_FPS_GLANCE_UP_LINK             = $0901C4E0; { Fallback look up button }
+  DIBUTTON_FPS_GLANCE_DOWN_LINK           = $0901C4E8; { Fallback look down button }
+  DIBUTTON_FPS_STEP_LEFT_LINK             = $090244E4; { Fallback step left button }
+  DIBUTTON_FPS_STEP_RIGHT_LINK            = $090244EC; { Fallback step right button }
+  DIBUTTON_FPS_DEVICE                     = $090044FE; { Show input device and controls }
+  DIBUTTON_FPS_PAUSE                      = $090044FC; { Start / Pause / Restart game }
+
+(*--- Fighting - Third Person action
+      Perspective of camera is behind the main character  ---*)
+  DIVIRTUAL_FIGHTING_THIRDPERSON          = $0A000000;
+  DIAXIS_TPS_TURN                         = $0A020201; { Turn left/right }
+  DIAXIS_TPS_MOVE                         = $0A010202; { Move forward/backward }
+  DIBUTTON_TPS_RUN                        = $0A000401; { Run or walk toggle switch }
+  DIBUTTON_TPS_ACTION                     = $0A000402; { Action Button }
+  DIBUTTON_TPS_SELECT                     = $0A000403; { Select next weapon }
+  DIBUTTON_TPS_USE                        = $0A000404; { Use inventory item currently selected }
+  DIBUTTON_TPS_JUMP                       = $0A000405; { Character Jumps }
+  DIBUTTON_TPS_MENU                       = $0A0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_TPS_GLANCE                  = $0A004601; { Look around }
+  DIBUTTON_TPS_VIEW                       = $0A004406; { Select camera view }
+  DIBUTTON_TPS_STEPLEFT                   = $0A004407; { Character takes a left step }
+  DIBUTTON_TPS_STEPRIGHT                  = $0A004408; { Character takes a right step }
+  DIAXIS_TPS_STEP                         = $0A00C203; { Character steps left/right }
+  DIBUTTON_TPS_DODGE                      = $0A004409; { Character dodges or ducks }
+  DIBUTTON_TPS_INVENTORY                  = $0A00440A; { Cycle through inventory }
+  DIBUTTON_TPS_TURN_LEFT_LINK             = $0A0244E4; { Fallback turn left button }
+  DIBUTTON_TPS_TURN_RIGHT_LINK            = $0A0244EC; { Fallback turn right button }
+  DIBUTTON_TPS_FORWARD_LINK               = $0A0144E0; { Fallback forward button }
+  DIBUTTON_TPS_BACKWARD_LINK              = $0A0144E8; { Fallback backward button }
+  DIBUTTON_TPS_GLANCE_UP_LINK             = $0A07C4E0; { Fallback look up button }
+  DIBUTTON_TPS_GLANCE_DOWN_LINK           = $0A07C4E8; { Fallback look down button }
+  DIBUTTON_TPS_GLANCE_LEFT_LINK           = $0A07C4E4; { Fallback glance up button }
+  DIBUTTON_TPS_GLANCE_RIGHT_LINK          = $0A07C4EC; { Fallback glance right button }
+  DIBUTTON_TPS_DEVICE                     = $0A0044FE; { Show input device and controls }
+  DIBUTTON_TPS_PAUSE                      = $0A0044FC; { Start / Pause / Restart game }
+
+(*--- Strategy - Role Playing
+      Navigation and problem solving are primary actions  ---*)
+  DIVIRTUAL_STRATEGY_ROLEPLAYING          = $0B000000;
+  DIAXIS_STRATEGYR_LATERAL                = $0B008201; { sidestep - left/right }
+  DIAXIS_STRATEGYR_MOVE                   = $0B010202; { move forward/backward }
+  DIBUTTON_STRATEGYR_GET                  = $0B000401; { Acquire item }
+  DIBUTTON_STRATEGYR_APPLY                = $0B000402; { Use selected item }
+  DIBUTTON_STRATEGYR_SELECT               = $0B000403; { Select nextitem }
+  DIBUTTON_STRATEGYR_ATTACK               = $0B000404; { Attack }
+  DIBUTTON_STRATEGYR_CAST                 = $0B000405; { Cast Spell }
+  DIBUTTON_STRATEGYR_CROUCH               = $0B000406; { Crouch }
+  DIBUTTON_STRATEGYR_JUMP                 = $0B000407; { Jump }
+  DIBUTTON_STRATEGYR_MENU                 = $0B0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_STRATEGYR_GLANCE            = $0B004601; { Look around }
+  DIBUTTON_STRATEGYR_MAP                  = $0B004408; { Cycle through map options }
+  DIBUTTON_STRATEGYR_DISPLAY              = $0B004409; { Shows next on-screen display option }
+  DIAXIS_STRATEGYR_ROTATE                 = $0B024203; { Turn body left/right }
+  DIBUTTON_STRATEGYR_LEFT_LINK            = $0B00C4E4; { Fallback sidestep left button }
+  DIBUTTON_STRATEGYR_RIGHT_LINK           = $0B00C4EC; { Fallback sidestep right button }
+  DIBUTTON_STRATEGYR_FORWARD_LINK         = $0B0144E0; { Fallback move forward button }
+  DIBUTTON_STRATEGYR_BACK_LINK            = $0B0144E8; { Fallback move backward button }
+  DIBUTTON_STRATEGYR_ROTATE_LEFT_LINK     = $0B0244E4; { Fallback turn body left button }
+  DIBUTTON_STRATEGYR_ROTATE_RIGHT_LINK    = $0B0244EC; { Fallback turn body right button }
+  DIBUTTON_STRATEGYR_DEVICE               = $0B0044FE; { Show input device and controls }
+  DIBUTTON_STRATEGYR_PAUSE                = $0B0044FC; { Start / Pause / Restart game }
+
+(*--- Strategy - Turn based
+      Navigation and problem solving are primary actions  ---*)
+  DIVIRTUAL_STRATEGY_TURN                 = $0C000000;
+  DIAXIS_STRATEGYT_LATERAL                = $0C008201; { Sidestep left/right }
+  DIAXIS_STRATEGYT_MOVE                   = $0C010202; { Move forward/backwards }
+  DIBUTTON_STRATEGYT_SELECT               = $0C000401; { Select unit or object }
+  DIBUTTON_STRATEGYT_INSTRUCT             = $0C000402; { Cycle through instructions }
+  DIBUTTON_STRATEGYT_APPLY                = $0C000403; { Apply selected instruction }
+  DIBUTTON_STRATEGYT_TEAM                 = $0C000404; { Select next team / cycle through all }
+  DIBUTTON_STRATEGYT_TURN                 = $0C000405; { Indicate turn over }
+  DIBUTTON_STRATEGYT_MENU                 = $0C0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_STRATEGYT_ZOOM                 = $0C004406; { Zoom - in / out }
+  DIBUTTON_STRATEGYT_MAP                  = $0C004407; { cycle through map options }
+  DIBUTTON_STRATEGYT_DISPLAY              = $0C004408; { shows next on-screen display options }
+  DIBUTTON_STRATEGYT_LEFT_LINK            = $0C00C4E4; { Fallback sidestep left button }
+  DIBUTTON_STRATEGYT_RIGHT_LINK           = $0C00C4EC; { Fallback sidestep right button }
+  DIBUTTON_STRATEGYT_FORWARD_LINK         = $0C0144E0; { Fallback move forward button }
+  DIBUTTON_STRATEGYT_BACK_LINK            = $0C0144E8; { Fallback move back button }
+  DIBUTTON_STRATEGYT_DEVICE               = $0C0044FE; { Show input device and controls }
+  DIBUTTON_STRATEGYT_PAUSE                = $0C0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Hunting
+      Hunting                ---*)
+  DIVIRTUAL_SPORTS_HUNTING                = $0D000000;
+  DIAXIS_HUNTING_LATERAL                  = $0D008201; { sidestep left/right }
+  DIAXIS_HUNTING_MOVE                     = $0D010202; { move forward/backwards }
+  DIBUTTON_HUNTING_FIRE                   = $0D000401; { Fire selected weapon }
+  DIBUTTON_HUNTING_AIM                    = $0D000402; { Select aim/move }
+  DIBUTTON_HUNTING_WEAPON                 = $0D000403; { Select next weapon }
+  DIBUTTON_HUNTING_BINOCULAR              = $0D000404; { Look through Binoculars }
+  DIBUTTON_HUNTING_CALL                   = $0D000405; { Make animal call }
+  DIBUTTON_HUNTING_MAP                    = $0D000406; { View Map }
+  DIBUTTON_HUNTING_SPECIAL                = $0D000407; { Special game operation }
+  DIBUTTON_HUNTING_MENU                   = $0D0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_HUNTING_GLANCE              = $0D004601; { Look around }
+  DIBUTTON_HUNTING_DISPLAY                = $0D004408; { show next on-screen display option }
+  DIAXIS_HUNTING_ROTATE                   = $0D024203; { Turn body left/right }
+  DIBUTTON_HUNTING_CROUCH                 = $0D004409; { Crouch/ Climb / Swim down }
+  DIBUTTON_HUNTING_JUMP                   = $0D00440A; { Jump/ Climb up / Swim up }
+  DIBUTTON_HUNTING_FIRESECONDARY          = $0D00440B; { Alternative fire button }
+  DIBUTTON_HUNTING_LEFT_LINK              = $0D00C4E4; { Fallback sidestep left button }
+  DIBUTTON_HUNTING_RIGHT_LINK             = $0D00C4EC; { Fallback sidestep right button }
+  DIBUTTON_HUNTING_FORWARD_LINK           = $0D0144E0; { Fallback move forward button }
+  DIBUTTON_HUNTING_BACK_LINK              = $0D0144E8; { Fallback move back button }
+  DIBUTTON_HUNTING_ROTATE_LEFT_LINK       = $0D0244E4; { Fallback turn body left button }
+  DIBUTTON_HUNTING_ROTATE_RIGHT_LINK      = $0D0244EC; { Fallback turn body right button }
+  DIBUTTON_HUNTING_DEVICE                 = $0D0044FE; { Show input device and controls }
+  DIBUTTON_HUNTING_PAUSE                  = $0D0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Fishing
+      Catching Fish is primary objective   ---*)
+  DIVIRTUAL_SPORTS_FISHING                = $0E000000;
+  DIAXIS_FISHING_LATERAL                  = $0E008201; { sidestep left/right }
+  DIAXIS_FISHING_MOVE                     = $0E010202; { move forward/backwards }
+  DIBUTTON_FISHING_CAST                   = $0E000401; { Cast line }
+  DIBUTTON_FISHING_TYPE                   = $0E000402; { Select cast type }
+  DIBUTTON_FISHING_BINOCULAR              = $0E000403; { Look through Binocular }
+  DIBUTTON_FISHING_BAIT                   = $0E000404; { Select type of Bait }
+  DIBUTTON_FISHING_MAP                    = $0E000405; { View Map }
+  DIBUTTON_FISHING_MENU                   = $0E0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_FISHING_GLANCE              = $0E004601; { Look around }
+  DIBUTTON_FISHING_DISPLAY                = $0E004406; { Show next on-screen display option }
+  DIAXIS_FISHING_ROTATE                   = $0E024203; { Turn character left / right }
+  DIBUTTON_FISHING_CROUCH                 = $0E004407; { Crouch/ Climb / Swim down }
+  DIBUTTON_FISHING_JUMP                   = $0E004408; { Jump/ Climb up / Swim up }
+  DIBUTTON_FISHING_LEFT_LINK              = $0E00C4E4; { Fallback sidestep left button }
+  DIBUTTON_FISHING_RIGHT_LINK             = $0E00C4EC; { Fallback sidestep right button }
+  DIBUTTON_FISHING_FORWARD_LINK           = $0E0144E0; { Fallback move forward button }
+  DIBUTTON_FISHING_BACK_LINK              = $0E0144E8; { Fallback move back button }
+  DIBUTTON_FISHING_ROTATE_LEFT_LINK       = $0E0244E4; { Fallback turn body left button }
+  DIBUTTON_FISHING_ROTATE_RIGHT_LINK      = $0E0244EC; { Fallback turn body right button }
+  DIBUTTON_FISHING_DEVICE                 = $0E0044FE; { Show input device and controls }
+  DIBUTTON_FISHING_PAUSE                  = $0E0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Baseball - Batting
+      Batter control is primary objective  ---*)
+  DIVIRTUAL_SPORTS_BASEBALL_BAT           = $0F000000;
+  DIAXIS_BASEBALLB_LATERAL                = $0F008201; { Aim left / right }
+  DIAXIS_BASEBALLB_MOVE                   = $0F010202; { Aim up / down }
+  DIBUTTON_BASEBALLB_SELECT               = $0F000401; { cycle through swing options }
+  DIBUTTON_BASEBALLB_NORMAL               = $0F000402; { normal swing }
+  DIBUTTON_BASEBALLB_POWER                = $0F000403; { swing for the fence }
+  DIBUTTON_BASEBALLB_BUNT                 = $0F000404; { bunt }
+  DIBUTTON_BASEBALLB_STEAL                = $0F000405; { Base runner attempts to steal a base }
+  DIBUTTON_BASEBALLB_BURST                = $0F000406; { Base runner invokes burst of speed }
+  DIBUTTON_BASEBALLB_SLIDE                = $0F000407; { Base runner slides into base }
+  DIBUTTON_BASEBALLB_CONTACT              = $0F000408; { Contact swing }
+  DIBUTTON_BASEBALLB_MENU                 = $0F0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_BASEBALLB_NOSTEAL              = $0F004409; { Base runner goes back to a base }
+  DIBUTTON_BASEBALLB_BOX                  = $0F00440A; { Enter or exit batting box }
+  DIBUTTON_BASEBALLB_LEFT_LINK            = $0F00C4E4; { Fallback sidestep left button }
+  DIBUTTON_BASEBALLB_RIGHT_LINK           = $0F00C4EC; { Fallback sidestep right button }
+  DIBUTTON_BASEBALLB_FORWARD_LINK         = $0F0144E0; { Fallback move forward button }
+  DIBUTTON_BASEBALLB_BACK_LINK            = $0F0144E8; { Fallback move back button }
+  DIBUTTON_BASEBALLB_DEVICE               = $0F0044FE; { Show input device and controls }
+  DIBUTTON_BASEBALLB_PAUSE                = $0F0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Baseball - Pitching
+      Pitcher control is primary objective   ---*)
+  DIVIRTUAL_SPORTS_BASEBALL_PITCH         = $10000000;
+  DIAXIS_BASEBALLP_LATERAL                = $10008201; { Aim left / right }
+  DIAXIS_BASEBALLP_MOVE                   = $10010202; { Aim up / down }
+  DIBUTTON_BASEBALLP_SELECT               = $10000401; { cycle through pitch selections }
+  DIBUTTON_BASEBALLP_PITCH                = $10000402; { throw pitch }
+  DIBUTTON_BASEBALLP_BASE                 = $10000403; { select base to throw to }
+  DIBUTTON_BASEBALLP_THROW                = $10000404; { throw to base }
+  DIBUTTON_BASEBALLP_FAKE                 = $10000405; { Fake a throw to a base }
+  DIBUTTON_BASEBALLP_MENU                 = $100004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_BASEBALLP_WALK                 = $10004406; { Throw intentional walk / pitch out }
+  DIBUTTON_BASEBALLP_LOOK                 = $10004407; { Look at runners on bases }
+  DIBUTTON_BASEBALLP_LEFT_LINK            = $1000C4E4; { Fallback sidestep left button }
+  DIBUTTON_BASEBALLP_RIGHT_LINK           = $1000C4EC; { Fallback sidestep right button }
+  DIBUTTON_BASEBALLP_FORWARD_LINK         = $100144E0; { Fallback move forward button }
+  DIBUTTON_BASEBALLP_BACK_LINK            = $100144E8; { Fallback move back button }
+  DIBUTTON_BASEBALLP_DEVICE               = $100044FE; { Show input device and controls }
+  DIBUTTON_BASEBALLP_PAUSE                = $100044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Baseball - Fielding
+      Fielder control is primary objective  ---*)
+  DIVIRTUAL_SPORTS_BASEBALL_FIELD         = $11000000;
+  DIAXIS_BASEBALLF_LATERAL                = $11008201; { Aim left / right }
+  DIAXIS_BASEBALLF_MOVE                   = $11010202; { Aim up / down }
+  DIBUTTON_BASEBALLF_NEAREST              = $11000401; { Switch to fielder nearest to the ball }
+  DIBUTTON_BASEBALLF_THROW1               = $11000402; { Make conservative throw }
+  DIBUTTON_BASEBALLF_THROW2               = $11000403; { Make aggressive throw }
+  DIBUTTON_BASEBALLF_BURST                = $11000404; { Invoke burst of speed }
+  DIBUTTON_BASEBALLF_JUMP                 = $11000405; { Jump to catch ball }
+  DIBUTTON_BASEBALLF_DIVE                 = $11000406; { Dive to catch ball }
+  DIBUTTON_BASEBALLF_MENU                 = $110004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_BASEBALLF_SHIFTIN              = $11004407; { Shift the infield positioning }
+  DIBUTTON_BASEBALLF_SHIFTOUT             = $11004408; { Shift the outfield positioning }
+  DIBUTTON_BASEBALLF_AIM_LEFT_LINK        = $1100C4E4; { Fallback aim left button }
+  DIBUTTON_BASEBALLF_AIM_RIGHT_LINK       = $1100C4EC; { Fallback aim right button }
+  DIBUTTON_BASEBALLF_FORWARD_LINK         = $110144E0; { Fallback move forward button }
+  DIBUTTON_BASEBALLF_BACK_LINK            = $110144E8; { Fallback move back button }
+  DIBUTTON_BASEBALLF_DEVICE               = $110044FE; { Show input device and controls }
+  DIBUTTON_BASEBALLF_PAUSE                = $110044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Basketball - Offense
+      Offense  ---*)
+  DIVIRTUAL_SPORTS_BASKETBALL_OFFENSE     = $12000000;
+  DIAXIS_BBALLO_LATERAL                   = $12008201; { left / right }
+  DIAXIS_BBALLO_MOVE                      = $12010202; { up / down }
+  DIBUTTON_BBALLO_SHOOT                   = $12000401; { shoot basket }
+  DIBUTTON_BBALLO_DUNK                    = $12000402; { dunk basket }
+  DIBUTTON_BBALLO_PASS                    = $12000403; { throw pass }
+  DIBUTTON_BBALLO_FAKE                    = $12000404; { fake shot or pass }
+  DIBUTTON_BBALLO_SPECIAL                 = $12000405; { apply special move }
+  DIBUTTON_BBALLO_PLAYER                  = $12000406; { select next player }
+  DIBUTTON_BBALLO_BURST                   = $12000407; { invoke burst }
+  DIBUTTON_BBALLO_CALL                    = $12000408; { call for ball / pass to me }
+  DIBUTTON_BBALLO_MENU                    = $120004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_BBALLO_GLANCE               = $12004601; { scroll view }
+  DIBUTTON_BBALLO_SCREEN                  = $12004409; { Call for screen }
+  DIBUTTON_BBALLO_PLAY                    = $1200440A; { Call for specific offensive play }
+  DIBUTTON_BBALLO_JAB                     = $1200440B; { Initiate fake drive to basket }
+  DIBUTTON_BBALLO_POST                    = $1200440C; { Perform post move }
+  DIBUTTON_BBALLO_TIMEOUT                 = $1200440D; { Time Out }
+  DIBUTTON_BBALLO_SUBSTITUTE              = $1200440E; { substitute one player for another }
+  DIBUTTON_BBALLO_LEFT_LINK               = $1200C4E4; { Fallback sidestep left button }
+  DIBUTTON_BBALLO_RIGHT_LINK              = $1200C4EC; { Fallback sidestep right button }
+  DIBUTTON_BBALLO_FORWARD_LINK            = $120144E0; { Fallback move forward button }
+  DIBUTTON_BBALLO_BACK_LINK               = $120144E8; { Fallback move back button }
+  DIBUTTON_BBALLO_DEVICE                  = $120044FE; { Show input device and controls }
+  DIBUTTON_BBALLO_PAUSE                   = $120044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Basketball - Defense
+      Defense  ---*)
+  DIVIRTUAL_SPORTS_BASKETBALL_DEFENSE     = $13000000;
+  DIAXIS_BBALLD_LATERAL                   = $13008201; { left / right }
+  DIAXIS_BBALLD_MOVE                      = $13010202; { up / down }
+  DIBUTTON_BBALLD_JUMP                    = $13000401; { jump to block shot }
+  DIBUTTON_BBALLD_STEAL                   = $13000402; { attempt to steal ball }
+  DIBUTTON_BBALLD_FAKE                    = $13000403; { fake block or steal }
+  DIBUTTON_BBALLD_SPECIAL                 = $13000404; { apply special move }
+  DIBUTTON_BBALLD_PLAYER                  = $13000405; { select next player }
+  DIBUTTON_BBALLD_BURST                   = $13000406; { invoke burst }
+  DIBUTTON_BBALLD_PLAY                    = $13000407; { call for specific defensive play }
+  DIBUTTON_BBALLD_MENU                    = $130004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_BBALLD_GLANCE               = $13004601; { scroll view }
+  DIBUTTON_BBALLD_TIMEOUT                 = $13004408; { Time Out }
+  DIBUTTON_BBALLD_SUBSTITUTE              = $13004409; { substitute one player for another }
+  DIBUTTON_BBALLD_LEFT_LINK               = $1300C4E4; { Fallback sidestep left button }
+  DIBUTTON_BBALLD_RIGHT_LINK              = $1300C4EC; { Fallback sidestep right button }
+  DIBUTTON_BBALLD_FORWARD_LINK            = $130144E0; { Fallback move forward button }
+  DIBUTTON_BBALLD_BACK_LINK               = $130144E8; { Fallback move back button }
+  DIBUTTON_BBALLD_DEVICE                  = $130044FE; { Show input device and controls }
+  DIBUTTON_BBALLD_PAUSE                   = $130044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Football - Play
+      Play selection  ---*)
+  DIVIRTUAL_SPORTS_FOOTBALL_FIELD         = $14000000;
+  DIBUTTON_FOOTBALLP_PLAY                 = $14000401; { cycle through available plays }
+  DIBUTTON_FOOTBALLP_SELECT               = $14000402; { select play }
+  DIBUTTON_FOOTBALLP_HELP                 = $14000403; { Bring up pop-up help }
+  DIBUTTON_FOOTBALLP_MENU                 = $140004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_FOOTBALLP_DEVICE               = $140044FE; { Show input device and controls }
+  DIBUTTON_FOOTBALLP_PAUSE                = $140044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Football - QB
+      Offense: Quarterback / Kicker  ---*)
+  DIVIRTUAL_SPORTS_FOOTBALL_QBCK          = $15000000;
+  DIAXIS_FOOTBALLQ_LATERAL                = $15008201; { Move / Aim: left / right }
+  DIAXIS_FOOTBALLQ_MOVE                   = $15010202; { Move / Aim: up / down }
+  DIBUTTON_FOOTBALLQ_SELECT               = $15000401; { Select }
+  DIBUTTON_FOOTBALLQ_SNAP                 = $15000402; { snap ball - start play }
+  DIBUTTON_FOOTBALLQ_JUMP                 = $15000403; { jump over defender }
+  DIBUTTON_FOOTBALLQ_SLIDE                = $15000404; { Dive/Slide }
+  DIBUTTON_FOOTBALLQ_PASS                 = $15000405; { throws pass to receiver }
+  DIBUTTON_FOOTBALLQ_FAKE                 = $15000406; { pump fake pass or fake kick }
+  DIBUTTON_FOOTBALLQ_MENU                 = $150004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_FOOTBALLQ_FAKESNAP             = $15004407; { Fake snap  }
+  DIBUTTON_FOOTBALLQ_MOTION               = $15004408; { Send receivers in motion }
+  DIBUTTON_FOOTBALLQ_AUDIBLE              = $15004409; { Change offensive play at line of scrimmage }
+  DIBUTTON_FOOTBALLQ_LEFT_LINK            = $1500C4E4; { Fallback sidestep left button }
+  DIBUTTON_FOOTBALLQ_RIGHT_LINK           = $1500C4EC; { Fallback sidestep right button }
+  DIBUTTON_FOOTBALLQ_FORWARD_LINK         = $150144E0; { Fallback move forward button }
+  DIBUTTON_FOOTBALLQ_BACK_LINK            = $150144E8; { Fallback move back button }
+  DIBUTTON_FOOTBALLQ_DEVICE               = $150044FE; { Show input device and controls }
+  DIBUTTON_FOOTBALLQ_PAUSE                = $150044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Football - Offense
+      Offense - Runner  ---*)
+  DIVIRTUAL_SPORTS_FOOTBALL_OFFENSE       = $16000000;
+  DIAXIS_FOOTBALLO_LATERAL                = $16008201; { Move / Aim: left / right }
+  DIAXIS_FOOTBALLO_MOVE                   = $16010202; { Move / Aim: up / down }
+  DIBUTTON_FOOTBALLO_JUMP                 = $16000401; { jump or hurdle over defender }
+  DIBUTTON_FOOTBALLO_LEFTARM              = $16000402; { holds out left arm }
+  DIBUTTON_FOOTBALLO_RIGHTARM             = $16000403; { holds out right arm }
+  DIBUTTON_FOOTBALLO_THROW                = $16000404; { throw pass or lateral ball to another runner }
+  DIBUTTON_FOOTBALLO_SPIN                 = $16000405; { Spin to avoid defenders }
+  DIBUTTON_FOOTBALLO_MENU                 = $160004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_FOOTBALLO_JUKE                 = $16004406; { Use special move to avoid defenders }
+  DIBUTTON_FOOTBALLO_SHOULDER             = $16004407; { Lower shoulder to run over defenders }
+  DIBUTTON_FOOTBALLO_TURBO                = $16004408; { Speed burst past defenders }
+  DIBUTTON_FOOTBALLO_DIVE                 = $16004409; { Dive over defenders }
+  DIBUTTON_FOOTBALLO_ZOOM                 = $1600440A; { Zoom view in / out }
+  DIBUTTON_FOOTBALLO_SUBSTITUTE           = $1600440B; { substitute one player for another }
+  DIBUTTON_FOOTBALLO_LEFT_LINK            = $1600C4E4; { Fallback sidestep left button }
+  DIBUTTON_FOOTBALLO_RIGHT_LINK           = $1600C4EC; { Fallback sidestep right button }
+  DIBUTTON_FOOTBALLO_FORWARD_LINK         = $160144E0; { Fallback move forward button }
+  DIBUTTON_FOOTBALLO_BACK_LINK            = $160144E8; { Fallback move back button }
+  DIBUTTON_FOOTBALLO_DEVICE               = $160044FE; { Show input device and controls }
+  DIBUTTON_FOOTBALLO_PAUSE                = $160044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Football - Defense
+      Defense     ---*)
+  DIVIRTUAL_SPORTS_FOOTBALL_DEFENSE       = $17000000;
+  DIAXIS_FOOTBALLD_LATERAL                = $17008201; { Move / Aim: left / right }
+  DIAXIS_FOOTBALLD_MOVE                   = $17010202; { Move / Aim: up / down }
+  DIBUTTON_FOOTBALLD_PLAY                 = $17000401; { cycle through available plays }
+  DIBUTTON_FOOTBALLD_SELECT               = $17000402; { select player closest to the ball }
+  DIBUTTON_FOOTBALLD_JUMP                 = $17000403; { jump to intercept or block }
+  DIBUTTON_FOOTBALLD_TACKLE               = $17000404; { tackler runner }
+  DIBUTTON_FOOTBALLD_FAKE                 = $17000405; { hold down to fake tackle or intercept }
+  DIBUTTON_FOOTBALLD_SUPERTACKLE          = $17000406; { Initiate special tackle }
+  DIBUTTON_FOOTBALLD_MENU                 = $170004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_FOOTBALLD_SPIN                 = $17004407; { Spin to beat offensive line }
+  DIBUTTON_FOOTBALLD_SWIM                 = $17004408; { Swim to beat the offensive line }
+  DIBUTTON_FOOTBALLD_BULLRUSH             = $17004409; { Bull rush the offensive line }
+  DIBUTTON_FOOTBALLD_RIP                  = $1700440A; { Rip the offensive line }
+  DIBUTTON_FOOTBALLD_AUDIBLE              = $1700440B; { Change defensive play at the line of scrimmage }
+  DIBUTTON_FOOTBALLD_ZOOM                 = $1700440C; { Zoom view in / out }
+  DIBUTTON_FOOTBALLD_SUBSTITUTE           = $1700440D; { substitute one player for another }
+  DIBUTTON_FOOTBALLD_LEFT_LINK            = $1700C4E4; { Fallback sidestep left button }
+  DIBUTTON_FOOTBALLD_RIGHT_LINK           = $1700C4EC; { Fallback sidestep right button }
+  DIBUTTON_FOOTBALLD_FORWARD_LINK         = $170144E0; { Fallback move forward button }
+  DIBUTTON_FOOTBALLD_BACK_LINK            = $170144E8; { Fallback move back button }
+  DIBUTTON_FOOTBALLD_DEVICE               = $170044FE; { Show input device and controls }
+  DIBUTTON_FOOTBALLD_PAUSE                = $170044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Golf
+                                ---*)
+  DIVIRTUAL_SPORTS_GOLF                   = $18000000;
+  DIAXIS_GOLF_LATERAL                     = $18008201; { Move / Aim: left / right }
+  DIAXIS_GOLF_MOVE                        = $18010202; { Move / Aim: up / down }
+  DIBUTTON_GOLF_SWING                     = $18000401; { swing club }
+  DIBUTTON_GOLF_SELECT                    = $18000402; { cycle between: club / swing strength / ball arc / ball spin }
+  DIBUTTON_GOLF_UP                        = $18000403; { increase selection }
+  DIBUTTON_GOLF_DOWN                      = $18000404; { decrease selection }
+  DIBUTTON_GOLF_TERRAIN                   = $18000405; { shows terrain detail }
+  DIBUTTON_GOLF_FLYBY                     = $18000406; { view the hole via a flyby }
+  DIBUTTON_GOLF_MENU                      = $180004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_GOLF_SCROLL                 = $18004601; { scroll view }
+  DIBUTTON_GOLF_ZOOM                      = $18004407; { Zoom view in / out }
+  DIBUTTON_GOLF_TIMEOUT                   = $18004408; { Call for time out }
+  DIBUTTON_GOLF_SUBSTITUTE                = $18004409; { substitute one player for another }
+  DIBUTTON_GOLF_LEFT_LINK                 = $1800C4E4; { Fallback sidestep left button }
+  DIBUTTON_GOLF_RIGHT_LINK                = $1800C4EC; { Fallback sidestep right button }
+  DIBUTTON_GOLF_FORWARD_LINK              = $180144E0; { Fallback move forward button }
+  DIBUTTON_GOLF_BACK_LINK                 = $180144E8; { Fallback move back button }
+  DIBUTTON_GOLF_DEVICE                    = $180044FE; { Show input device and controls }
+  DIBUTTON_GOLF_PAUSE                     = $180044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Hockey - Offense
+      Offense       ---*)
+  DIVIRTUAL_SPORTS_HOCKEY_OFFENSE         = $19000000;
+  DIAXIS_HOCKEYO_LATERAL                  = $19008201; { Move / Aim: left / right }
+  DIAXIS_HOCKEYO_MOVE                     = $19010202; { Move / Aim: up / down }
+  DIBUTTON_HOCKEYO_SHOOT                  = $19000401; { Shoot }
+  DIBUTTON_HOCKEYO_PASS                   = $19000402; { pass the puck }
+  DIBUTTON_HOCKEYO_BURST                  = $19000403; { invoke speed burst }
+  DIBUTTON_HOCKEYO_SPECIAL                = $19000404; { invoke special move }
+  DIBUTTON_HOCKEYO_FAKE                   = $19000405; { hold down to fake pass or kick }
+  DIBUTTON_HOCKEYO_MENU                   = $190004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_HOCKEYO_SCROLL              = $19004601; { scroll view }
+  DIBUTTON_HOCKEYO_ZOOM                   = $19004406; { Zoom view in / out }
+  DIBUTTON_HOCKEYO_STRATEGY               = $19004407; { Invoke coaching menu for strategy help }
+  DIBUTTON_HOCKEYO_TIMEOUT                = $19004408; { Call for time out }
+  DIBUTTON_HOCKEYO_SUBSTITUTE             = $19004409; { substitute one player for another }
+  DIBUTTON_HOCKEYO_LEFT_LINK              = $1900C4E4; { Fallback sidestep left button }
+  DIBUTTON_HOCKEYO_RIGHT_LINK             = $1900C4EC; { Fallback sidestep right button }
+  DIBUTTON_HOCKEYO_FORWARD_LINK           = $190144E0; { Fallback move forward button }
+  DIBUTTON_HOCKEYO_BACK_LINK              = $190144E8; { Fallback move back button }
+  DIBUTTON_HOCKEYO_DEVICE                 = $190044FE; { Show input device and controls }
+  DIBUTTON_HOCKEYO_PAUSE                  = $190044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Hockey - Defense
+      Defense       ---*)
+  DIVIRTUAL_SPORTS_HOCKEY_DEFENSE         = $1A000000;
+  DIAXIS_HOCKEYD_LATERAL                  = $1A008201; { Move / Aim: left / right }
+  DIAXIS_HOCKEYD_MOVE                     = $1A010202; { Move / Aim: up / down }
+  DIBUTTON_HOCKEYD_PLAYER                 = $1A000401; { control player closest to the puck }
+  DIBUTTON_HOCKEYD_STEAL                  = $1A000402; { attempt steal }
+  DIBUTTON_HOCKEYD_BURST                  = $1A000403; { speed burst or body check }
+  DIBUTTON_HOCKEYD_BLOCK                  = $1A000404; { block puck }
+  DIBUTTON_HOCKEYD_FAKE                   = $1A000405; { hold down to fake tackle or intercept }
+  DIBUTTON_HOCKEYD_MENU                   = $1A0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_HOCKEYD_SCROLL              = $1A004601; { scroll view }
+  DIBUTTON_HOCKEYD_ZOOM                   = $1A004406; { Zoom view in / out }
+  DIBUTTON_HOCKEYD_STRATEGY               = $1A004407; { Invoke coaching menu for strategy help }
+  DIBUTTON_HOCKEYD_TIMEOUT                = $1A004408; { Call for time out }
+  DIBUTTON_HOCKEYD_SUBSTITUTE             = $1A004409; { substitute one player for another }
+  DIBUTTON_HOCKEYD_LEFT_LINK              = $1A00C4E4; { Fallback sidestep left button }
+  DIBUTTON_HOCKEYD_RIGHT_LINK             = $1A00C4EC; { Fallback sidestep right button }
+  DIBUTTON_HOCKEYD_FORWARD_LINK           = $1A0144E0; { Fallback move forward button }
+  DIBUTTON_HOCKEYD_BACK_LINK              = $1A0144E8; { Fallback move back button }
+  DIBUTTON_HOCKEYD_DEVICE                 = $1A0044FE; { Show input device and controls }
+  DIBUTTON_HOCKEYD_PAUSE                  = $1A0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Hockey - Goalie
+      Goal tending  ---*)
+  DIVIRTUAL_SPORTS_HOCKEY_GOALIE          = $1B000000;
+  DIAXIS_HOCKEYG_LATERAL                  = $1B008201; { Move / Aim: left / right }
+  DIAXIS_HOCKEYG_MOVE                     = $1B010202; { Move / Aim: up / down }
+  DIBUTTON_HOCKEYG_PASS                   = $1B000401; { pass puck }
+  DIBUTTON_HOCKEYG_POKE                   = $1B000402; { poke / check / hack }
+  DIBUTTON_HOCKEYG_STEAL                  = $1B000403; { attempt steal }
+  DIBUTTON_HOCKEYG_BLOCK                  = $1B000404; { block puck }
+  DIBUTTON_HOCKEYG_MENU                   = $1B0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_HOCKEYG_SCROLL              = $1B004601; { scroll view }
+  DIBUTTON_HOCKEYG_ZOOM                   = $1B004405; { Zoom view in / out }
+  DIBUTTON_HOCKEYG_STRATEGY               = $1B004406; { Invoke coaching menu for strategy help }
+  DIBUTTON_HOCKEYG_TIMEOUT                = $1B004407; { Call for time out }
+  DIBUTTON_HOCKEYG_SUBSTITUTE             = $1B004408; { substitute one player for another }
+  DIBUTTON_HOCKEYG_LEFT_LINK              = $1B00C4E4; { Fallback sidestep left button }
+  DIBUTTON_HOCKEYG_RIGHT_LINK             = $1B00C4EC; { Fallback sidestep right button }
+  DIBUTTON_HOCKEYG_FORWARD_LINK           = $1B0144E0; { Fallback move forward button }
+  DIBUTTON_HOCKEYG_BACK_LINK              = $1B0144E8; { Fallback move back button }
+  DIBUTTON_HOCKEYG_DEVICE                 = $1B0044FE; { Show input device and controls }
+  DIBUTTON_HOCKEYG_PAUSE                  = $1B0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Mountain Biking
+                     ---*)
+  DIVIRTUAL_SPORTS_BIKING_MOUNTAIN        = $1C000000;
+  DIAXIS_BIKINGM_TURN                     = $1C008201; { left / right }
+  DIAXIS_BIKINGM_PEDAL                    = $1C010202; { Pedal faster / slower / brake }
+  DIBUTTON_BIKINGM_JUMP                   = $1C000401; { jump over obstacle }
+  DIBUTTON_BIKINGM_CAMERA                 = $1C000402; { switch camera view }
+  DIBUTTON_BIKINGM_SPECIAL1               = $1C000403; { perform first special move }
+  DIBUTTON_BIKINGM_SELECT                 = $1C000404; { Select }
+  DIBUTTON_BIKINGM_SPECIAL2               = $1C000405; { perform second special move }
+  DIBUTTON_BIKINGM_MENU                   = $1C0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_BIKINGM_SCROLL              = $1C004601; { scroll view }
+  DIBUTTON_BIKINGM_ZOOM                   = $1C004406; { Zoom view in / out }
+  DIAXIS_BIKINGM_BRAKE                    = $1C044203; { Brake axis  }
+  DIBUTTON_BIKINGM_LEFT_LINK              = $1C00C4E4; { Fallback turn left button }
+  DIBUTTON_BIKINGM_RIGHT_LINK             = $1C00C4EC; { Fallback turn right button }
+  DIBUTTON_BIKINGM_FASTER_LINK            = $1C0144E0; { Fallback pedal faster button }
+  DIBUTTON_BIKINGM_SLOWER_LINK            = $1C0144E8; { Fallback pedal slower button }
+  DIBUTTON_BIKINGM_BRAKE_BUTTON_LINK      = $1C0444E8; { Fallback brake button }
+  DIBUTTON_BIKINGM_DEVICE                 = $1C0044FE; { Show input device and controls }
+  DIBUTTON_BIKINGM_PAUSE                  = $1C0044FC; { Start / Pause / Restart game }
+
+(*--- Sports: Skiing / Snowboarding / Skateboarding
+        ---*)
+  DIVIRTUAL_SPORTS_SKIING                 = $1D000000;
+  DIAXIS_SKIING_TURN                      = $1D008201; { left / right }
+  DIAXIS_SKIING_SPEED                     = $1D010202; { faster / slower }
+  DIBUTTON_SKIING_JUMP                    = $1D000401; { Jump }
+  DIBUTTON_SKIING_CROUCH                  = $1D000402; { crouch down }
+  DIBUTTON_SKIING_CAMERA                  = $1D000403; { switch camera view }
+  DIBUTTON_SKIING_SPECIAL1                = $1D000404; { perform first special move }
+  DIBUTTON_SKIING_SELECT                  = $1D000405; { Select }
+  DIBUTTON_SKIING_SPECIAL2                = $1D000406; { perform second special move }
+  DIBUTTON_SKIING_MENU                    = $1D0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_SKIING_GLANCE               = $1D004601; { scroll view }
+  DIBUTTON_SKIING_ZOOM                    = $1D004407; { Zoom view in / out }
+  DIBUTTON_SKIING_LEFT_LINK               = $1D00C4E4; { Fallback turn left button }
+  DIBUTTON_SKIING_RIGHT_LINK              = $1D00C4EC; { Fallback turn right button }
+  DIBUTTON_SKIING_FASTER_LINK             = $1D0144E0; { Fallback increase speed button }
+  DIBUTTON_SKIING_SLOWER_LINK             = $1D0144E8; { Fallback decrease speed button }
+  DIBUTTON_SKIING_DEVICE                  = $1D0044FE; { Show input device and controls }
+  DIBUTTON_SKIING_PAUSE                   = $1D0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Soccer - Offense
+      Offense       ---*)
+  DIVIRTUAL_SPORTS_SOCCER_OFFENSE         = $1E000000;
+  DIAXIS_SOCCERO_LATERAL                  = $1E008201; { Move / Aim: left / right }
+  DIAXIS_SOCCERO_MOVE                     = $1E010202; { Move / Aim: up / down }
+  DIAXIS_SOCCERO_BEND                     = $1E018203; { Bend to soccer shot/pass }
+  DIBUTTON_SOCCERO_SHOOT                  = $1E000401; { Shoot the ball }
+  DIBUTTON_SOCCERO_PASS                   = $1E000402; { Pass  }
+  DIBUTTON_SOCCERO_FAKE                   = $1E000403; { Fake }
+  DIBUTTON_SOCCERO_PLAYER                 = $1E000404; { Select next player }
+  DIBUTTON_SOCCERO_SPECIAL1               = $1E000405; { Apply special move }
+  DIBUTTON_SOCCERO_SELECT                 = $1E000406; { Select special move }
+  DIBUTTON_SOCCERO_MENU                   = $1E0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_SOCCERO_GLANCE              = $1E004601; { scroll view }
+  DIBUTTON_SOCCERO_SUBSTITUTE             = $1E004407; { Substitute one player for another }
+  DIBUTTON_SOCCERO_SHOOTLOW               = $1E004408; { Shoot the ball low }
+  DIBUTTON_SOCCERO_SHOOTHIGH              = $1E004409; { Shoot the ball high }
+  DIBUTTON_SOCCERO_PASSTHRU               = $1E00440A; { Make a thru pass }
+  DIBUTTON_SOCCERO_SPRINT                 = $1E00440B; { Sprint / turbo boost }
+  DIBUTTON_SOCCERO_CONTROL                = $1E00440C; { Obtain control of the ball }
+  DIBUTTON_SOCCERO_HEAD                   = $1E00440D; { Attempt to head the ball }
+  DIBUTTON_SOCCERO_LEFT_LINK              = $1E00C4E4; { Fallback sidestep left button }
+  DIBUTTON_SOCCERO_RIGHT_LINK             = $1E00C4EC; { Fallback sidestep right button }
+  DIBUTTON_SOCCERO_FORWARD_LINK           = $1E0144E0; { Fallback move forward button }
+  DIBUTTON_SOCCERO_BACK_LINK              = $1E0144E8; { Fallback move back button }
+  DIBUTTON_SOCCERO_DEVICE                 = $1E0044FE; { Show input device and controls }
+  DIBUTTON_SOCCERO_PAUSE                  = $1E0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Soccer - Defense
+      Defense       ---*)
+  DIVIRTUAL_SPORTS_SOCCER_DEFENSE         = $1F000000;
+  DIAXIS_SOCCERD_LATERAL                  = $1F008201; { Move / Aim: left / right }
+  DIAXIS_SOCCERD_MOVE                     = $1F010202; { Move / Aim: up / down }
+  DIBUTTON_SOCCERD_BLOCK                  = $1F000401; { Attempt to block shot }
+  DIBUTTON_SOCCERD_STEAL                  = $1F000402; { Attempt to steal ball }
+  DIBUTTON_SOCCERD_FAKE                   = $1F000403; { Fake a block or a steal }
+  DIBUTTON_SOCCERD_PLAYER                 = $1F000404; { Select next player }
+  DIBUTTON_SOCCERD_SPECIAL                = $1F000405; { Apply special move }
+  DIBUTTON_SOCCERD_SELECT                 = $1F000406; { Select special move }
+  DIBUTTON_SOCCERD_SLIDE                  = $1F000407; { Attempt a slide tackle }
+  DIBUTTON_SOCCERD_MENU                   = $1F0004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_SOCCERD_GLANCE              = $1F004601; { scroll view }
+  DIBUTTON_SOCCERD_FOUL                   = $1F004408; { Initiate a foul / hard-foul }
+  DIBUTTON_SOCCERD_HEAD                   = $1F004409; { Attempt a Header }
+  DIBUTTON_SOCCERD_CLEAR                  = $1F00440A; { Attempt to clear the ball down the field }
+  DIBUTTON_SOCCERD_GOALIECHARGE           = $1F00440B; { Make the goalie charge out of the box }
+  DIBUTTON_SOCCERD_SUBSTITUTE             = $1F00440C; { Substitute one player for another }
+  DIBUTTON_SOCCERD_LEFT_LINK              = $1F00C4E4; { Fallback sidestep left button }
+  DIBUTTON_SOCCERD_RIGHT_LINK             = $1F00C4EC; { Fallback sidestep right button }
+  DIBUTTON_SOCCERD_FORWARD_LINK           = $1F0144E0; { Fallback move forward button }
+  DIBUTTON_SOCCERD_BACK_LINK              = $1F0144E8; { Fallback move back button }
+  DIBUTTON_SOCCERD_DEVICE                 = $1F0044FE; { Show input device and controls }
+  DIBUTTON_SOCCERD_PAUSE                  = $1F0044FC; { Start / Pause / Restart game }
+
+(*--- Sports - Racquet
+      Tennis - Table-Tennis - Squash   ---*)
+  DIVIRTUAL_SPORTS_RACQUET                = $20000000;
+  DIAXIS_RACQUET_LATERAL                  = $20008201; { Move / Aim: left / right }
+  DIAXIS_RACQUET_MOVE                     = $20010202; { Move / Aim: up / down }
+  DIBUTTON_RACQUET_SWING                  = $20000401; { Swing racquet }
+  DIBUTTON_RACQUET_BACKSWING              = $20000402; { Swing backhand }
+  DIBUTTON_RACQUET_SMASH                  = $20000403; { Smash shot }
+  DIBUTTON_RACQUET_SPECIAL                = $20000404; { Special shot }
+  DIBUTTON_RACQUET_SELECT                 = $20000405; { Select special shot }
+  DIBUTTON_RACQUET_MENU                   = $200004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_RACQUET_GLANCE              = $20004601; { scroll view }
+  DIBUTTON_RACQUET_TIMEOUT                = $20004406; { Call for time out }
+  DIBUTTON_RACQUET_SUBSTITUTE             = $20004407; { Substitute one player for another }
+  DIBUTTON_RACQUET_LEFT_LINK              = $2000C4E4; { Fallback sidestep left button }
+  DIBUTTON_RACQUET_RIGHT_LINK             = $2000C4EC; { Fallback sidestep right button }
+  DIBUTTON_RACQUET_FORWARD_LINK           = $200144E0; { Fallback move forward button }
+  DIBUTTON_RACQUET_BACK_LINK              = $200144E8; { Fallback move back button }
+  DIBUTTON_RACQUET_DEVICE                 = $200044FE; { Show input device and controls }
+  DIBUTTON_RACQUET_PAUSE                  = $200044FC; { Start / Pause / Restart game }
+
+(*--- Arcade- 2D
+      Side to Side movement        ---*)
+  DIVIRTUAL_ARCADE_SIDE2SIDE              = $21000000;
+  DIAXIS_ARCADES_LATERAL                  = $21008201; { left / right }
+  DIAXIS_ARCADES_MOVE                     = $21010202; { up / down }
+  DIBUTTON_ARCADES_THROW                  = $21000401; { throw object }
+  DIBUTTON_ARCADES_CARRY                  = $21000402; { carry object }
+  DIBUTTON_ARCADES_ATTACK                 = $21000403; { attack }
+  DIBUTTON_ARCADES_SPECIAL                = $21000404; { apply special move }
+  DIBUTTON_ARCADES_SELECT                 = $21000405; { select special move }
+  DIBUTTON_ARCADES_MENU                   = $210004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_ARCADES_VIEW                = $21004601; { scroll view left / right / up / down }
+  DIBUTTON_ARCADES_LEFT_LINK              = $2100C4E4; { Fallback sidestep left button }
+  DIBUTTON_ARCADES_RIGHT_LINK             = $2100C4EC; { Fallback sidestep right button }
+  DIBUTTON_ARCADES_FORWARD_LINK           = $210144E0; { Fallback move forward button }
+  DIBUTTON_ARCADES_BACK_LINK              = $210144E8; { Fallback move back button }
+  DIBUTTON_ARCADES_VIEW_UP_LINK           = $2107C4E0; { Fallback scroll view up button }
+  DIBUTTON_ARCADES_VIEW_DOWN_LINK         = $2107C4E8; { Fallback scroll view down button }
+  DIBUTTON_ARCADES_VIEW_LEFT_LINK         = $2107C4E4; { Fallback scroll view left button }
+  DIBUTTON_ARCADES_VIEW_RIGHT_LINK        = $2107C4EC; { Fallback scroll view right button }
+  DIBUTTON_ARCADES_DEVICE                 = $210044FE; { Show input device and controls }
+  DIBUTTON_ARCADES_PAUSE                  = $210044FC; { Start / Pause / Restart game }
+
+(*--- Arcade - Platform Game
+      Character moves around on screen  ---*)
+  DIVIRTUAL_ARCADE_PLATFORM               = $22000000;
+  DIAXIS_ARCADEP_LATERAL                  = $22008201; { Left / right }
+  DIAXIS_ARCADEP_MOVE                     = $22010202; { Up / down }
+  DIBUTTON_ARCADEP_JUMP                   = $22000401; { Jump }
+  DIBUTTON_ARCADEP_FIRE                   = $22000402; { Fire }
+  DIBUTTON_ARCADEP_CROUCH                 = $22000403; { Crouch }
+  DIBUTTON_ARCADEP_SPECIAL                = $22000404; { Apply special move }
+  DIBUTTON_ARCADEP_SELECT                 = $22000405; { Select special move }
+  DIBUTTON_ARCADEP_MENU                   = $220004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_ARCADEP_VIEW                = $22004601; { Scroll view }
+  DIBUTTON_ARCADEP_FIRESECONDARY          = $22004406; { Alternative fire button }
+  DIBUTTON_ARCADEP_LEFT_LINK              = $2200C4E4; { Fallback sidestep left button }
+  DIBUTTON_ARCADEP_RIGHT_LINK             = $2200C4EC; { Fallback sidestep right button }
+  DIBUTTON_ARCADEP_FORWARD_LINK           = $220144E0; { Fallback move forward button }
+  DIBUTTON_ARCADEP_BACK_LINK              = $220144E8; { Fallback move back button }
+  DIBUTTON_ARCADEP_VIEW_UP_LINK           = $2207C4E0; { Fallback scroll view up button }
+  DIBUTTON_ARCADEP_VIEW_DOWN_LINK         = $2207C4E8; { Fallback scroll view down button }
+  DIBUTTON_ARCADEP_VIEW_LEFT_LINK         = $2207C4E4; { Fallback scroll view left button }
+  DIBUTTON_ARCADEP_VIEW_RIGHT_LINK        = $2207C4EC; { Fallback scroll view right button }
+  DIBUTTON_ARCADEP_DEVICE                 = $220044FE; { Show input device and controls }
+  DIBUTTON_ARCADEP_PAUSE                  = $220044FC; { Start / Pause / Restart game }
+
+(*--- CAD - 2D Object Control
+      Controls to select and move objects in 2D  ---*)
+  DIVIRTUAL_CAD_2DCONTROL                 = $23000000;
+  DIAXIS_2DCONTROL_LATERAL                = $23008201; { Move view left / right }
+  DIAXIS_2DCONTROL_MOVE                   = $23010202; { Move view up / down }
+  DIAXIS_2DCONTROL_INOUT                  = $23018203; { Zoom - in / out }
+  DIBUTTON_2DCONTROL_SELECT               = $23000401; { Select Object }
+  DIBUTTON_2DCONTROL_SPECIAL1             = $23000402; { Do first special operation }
+  DIBUTTON_2DCONTROL_SPECIAL              = $23000403; { Select special operation }
+  DIBUTTON_2DCONTROL_SPECIAL2             = $23000404; { Do second special operation }
+  DIBUTTON_2DCONTROL_MENU                 = $230004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_2DCONTROL_HATSWITCH         = $23004601; { Hat switch }
+  DIAXIS_2DCONTROL_ROTATEZ                = $23024204; { Rotate view clockwise / counterclockwise }
+  DIBUTTON_2DCONTROL_DISPLAY              = $23004405; { Shows next on-screen display options }
+  DIBUTTON_2DCONTROL_DEVICE               = $230044FE; { Show input device and controls }
+  DIBUTTON_2DCONTROL_PAUSE                = $230044FC; { Start / Pause / Restart game }
+
+(*--- CAD - 3D object control
+      Controls to select and move objects within a 3D environment  ---*)
+  DIVIRTUAL_CAD_3DCONTROL                 = $24000000;
+  DIAXIS_3DCONTROL_LATERAL                = $24008201; { Move view left / right }
+  DIAXIS_3DCONTROL_MOVE                   = $24010202; { Move view up / down }
+  DIAXIS_3DCONTROL_INOUT                  = $24018203; { Zoom - in / out }
+  DIBUTTON_3DCONTROL_SELECT               = $24000401; { Select Object }
+  DIBUTTON_3DCONTROL_SPECIAL1             = $24000402; { Do first special operation }
+  DIBUTTON_3DCONTROL_SPECIAL              = $24000403; { Select special operation }
+  DIBUTTON_3DCONTROL_SPECIAL2             = $24000404; { Do second special operation }
+  DIBUTTON_3DCONTROL_MENU                 = $240004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_3DCONTROL_HATSWITCH         = $24004601; { Hat switch }
+  DIAXIS_3DCONTROL_ROTATEX                = $24034204; { Rotate view forward or up / backward or down }
+  DIAXIS_3DCONTROL_ROTATEY                = $2402C205; { Rotate view clockwise / counterclockwise }
+  DIAXIS_3DCONTROL_ROTATEZ                = $24024206; { Rotate view left / right }
+  DIBUTTON_3DCONTROL_DISPLAY              = $24004405; { Show next on-screen display options }
+  DIBUTTON_3DCONTROL_DEVICE               = $240044FE; { Show input device and controls }
+  DIBUTTON_3DCONTROL_PAUSE                = $240044FC; { Start / Pause / Restart game }
+
+(*--- CAD - 3D Navigation - Fly through
+      Controls for 3D modeling  ---*)
+  DIVIRTUAL_CAD_FLYBY                     = $25000000;
+  DIAXIS_CADF_LATERAL                     = $25008201; { move view left / right }
+  DIAXIS_CADF_MOVE                        = $25010202; { move view up / down }
+  DIAXIS_CADF_INOUT                       = $25018203; { in / out }
+  DIBUTTON_CADF_SELECT                    = $25000401; { Select Object }
+  DIBUTTON_CADF_SPECIAL1                  = $25000402; { do first special operation }
+  DIBUTTON_CADF_SPECIAL                   = $25000403; { Select special operation }
+  DIBUTTON_CADF_SPECIAL2                  = $25000404; { do second special operation }
+  DIBUTTON_CADF_MENU                      = $250004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_CADF_HATSWITCH              = $25004601; { Hat switch }
+  DIAXIS_CADF_ROTATEX                     = $25034204; { Rotate view forward or up / backward or down }
+  DIAXIS_CADF_ROTATEY                     = $2502C205; { Rotate view clockwise / counterclockwise }
+  DIAXIS_CADF_ROTATEZ                     = $25024206; { Rotate view left / right }
+  DIBUTTON_CADF_DISPLAY                   = $25004405; { shows next on-screen display options }
+  DIBUTTON_CADF_DEVICE                    = $250044FE; { Show input device and controls }
+  DIBUTTON_CADF_PAUSE                     = $250044FC; { Start / Pause / Restart game }
+
+(*--- CAD - 3D Model Control
+      Controls for 3D modeling  ---*)
+  DIVIRTUAL_CAD_MODEL                     = $26000000;
+  DIAXIS_CADM_LATERAL                     = $26008201; { move view left / right }
+  DIAXIS_CADM_MOVE                        = $26010202; { move view up / down }
+  DIAXIS_CADM_INOUT                       = $26018203; { in / out }
+  DIBUTTON_CADM_SELECT                    = $26000401; { Select Object }
+  DIBUTTON_CADM_SPECIAL1                  = $26000402; { do first special operation }
+  DIBUTTON_CADM_SPECIAL                   = $26000403; { Select special operation }
+  DIBUTTON_CADM_SPECIAL2                  = $26000404; { do second special operation }
+  DIBUTTON_CADM_MENU                      = $260004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIHATSWITCH_CADM_HATSWITCH              = $26004601; { Hat switch }
+  DIAXIS_CADM_ROTATEX                     = $26034204; { Rotate view forward or up / backward or down }
+  DIAXIS_CADM_ROTATEY                     = $2602C205; { Rotate view clockwise / counterclockwise }
+  DIAXIS_CADM_ROTATEZ                     = $26024206; { Rotate view left / right }
+  DIBUTTON_CADM_DISPLAY                   = $26004405; { shows next on-screen display options }
+  DIBUTTON_CADM_DEVICE                    = $260044FE; { Show input device and controls }
+  DIBUTTON_CADM_PAUSE                     = $260044FC; { Start / Pause / Restart game }
+
+(*--- Control - Media Equipment
+      Remote        ---*)
+  DIVIRTUAL_REMOTE_CONTROL                = $27000000;
+  DIAXIS_REMOTE_SLIDER                    = $27050201; { Slider for adjustment: volume / color / bass / etc }
+  DIBUTTON_REMOTE_MUTE                    = $27000401; { Set volume on current device to zero }
+  DIBUTTON_REMOTE_SELECT                  = $27000402; { Next/previous: channel/ track / chapter / picture / station }
+  DIBUTTON_REMOTE_PLAY                    = $27002403; { Start or pause entertainment on current device }
+  DIBUTTON_REMOTE_CUE                     = $27002404; { Move through current media }
+  DIBUTTON_REMOTE_REVIEW                  = $27002405; { Move through current media }
+  DIBUTTON_REMOTE_CHANGE                  = $27002406; { Select next device }
+  DIBUTTON_REMOTE_RECORD                  = $27002407; { Start recording the current media }
+  DIBUTTON_REMOTE_MENU                    = $270004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIAXIS_REMOTE_SLIDER2                   = $27054202; { Slider for adjustment: volume }
+  DIBUTTON_REMOTE_TV                      = $27005C08; { Select TV }
+  DIBUTTON_REMOTE_CABLE                   = $27005C09; { Select cable box }
+  DIBUTTON_REMOTE_CD                      = $27005C0A; { Select CD player }
+  DIBUTTON_REMOTE_VCR                     = $27005C0B; { Select VCR }
+  DIBUTTON_REMOTE_TUNER                   = $27005C0C; { Select tuner }
+  DIBUTTON_REMOTE_DVD                     = $27005C0D; { Select DVD player }
+  DIBUTTON_REMOTE_ADJUST                  = $27005C0E; { Enter device adjustment menu }
+  DIBUTTON_REMOTE_DIGIT0                  = $2700540F; { Digit 0 }
+  DIBUTTON_REMOTE_DIGIT1                  = $27005410; { Digit 1 }
+  DIBUTTON_REMOTE_DIGIT2                  = $27005411; { Digit 2 }
+  DIBUTTON_REMOTE_DIGIT3                  = $27005412; { Digit 3 }
+  DIBUTTON_REMOTE_DIGIT4                  = $27005413; { Digit 4 }
+  DIBUTTON_REMOTE_DIGIT5                  = $27005414; { Digit 5 }
+  DIBUTTON_REMOTE_DIGIT6                  = $27005415; { Digit 6 }
+  DIBUTTON_REMOTE_DIGIT7                  = $27005416; { Digit 7 }
+  DIBUTTON_REMOTE_DIGIT8                  = $27005417; { Digit 8 }
+  DIBUTTON_REMOTE_DIGIT9                  = $27005418; { Digit 9 }
+  DIBUTTON_REMOTE_DEVICE                  = $270044FE; { Show input device and controls }
+  DIBUTTON_REMOTE_PAUSE                   = $270044FC; { Start / Pause / Restart game }
+
+(*--- Control- Web
+      Help or Browser            ---*)
+  DIVIRTUAL_BROWSER_CONTROL               = $28000000;
+  DIAXIS_BROWSER_LATERAL                  = $28008201; { Move on screen pointer }
+  DIAXIS_BROWSER_MOVE                     = $28010202; { Move on screen pointer }
+  DIBUTTON_BROWSER_SELECT                 = $28000401; { Select current item }
+  DIAXIS_BROWSER_VIEW                     = $28018203; { Move view up/down }
+  DIBUTTON_BROWSER_REFRESH                = $28000402; { Refresh }
+  DIBUTTON_BROWSER_MENU                   = $280004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_BROWSER_SEARCH                 = $28004403; { Use search tool }
+  DIBUTTON_BROWSER_STOP                   = $28004404; { Cease current update }
+  DIBUTTON_BROWSER_HOME                   = $28004405; { Go directly to "home" location }
+  DIBUTTON_BROWSER_FAVORITES              = $28004406; { Mark current site as favorite }
+  DIBUTTON_BROWSER_NEXT                   = $28004407; { Select Next page }
+  DIBUTTON_BROWSER_PREVIOUS               = $28004408; { Select Previous page }
+  DIBUTTON_BROWSER_HISTORY                = $28004409; { Show/Hide History }
+  DIBUTTON_BROWSER_PRINT                  = $2800440A; { Print current page }
+  DIBUTTON_BROWSER_DEVICE                 = $280044FE; { Show input device and controls }
+  DIBUTTON_BROWSER_PAUSE                  = $280044FC; { Start / Pause / Restart game }
+
+(*--- Driving Simulator - Giant Walking Robot
+      Walking tank with weapons  ---*)
+  DIVIRTUAL_DRIVING_MECHA                 = $29000000;
+  DIAXIS_MECHA_STEER                      = $29008201; { Turns mecha left/right }
+  DIAXIS_MECHA_TORSO                      = $29010202; { Tilts torso forward/backward }
+  DIAXIS_MECHA_ROTATE                     = $29020203; { Turns torso left/right }
+  DIAXIS_MECHA_THROTTLE                   = $29038204; { Engine Speed }
+  DIBUTTON_MECHA_FIRE                     = $29000401; { Fire }
+  DIBUTTON_MECHA_WEAPONS                  = $29000402; { Select next weapon group }
+  DIBUTTON_MECHA_TARGET                   = $29000403; { Select closest enemy available target }
+  DIBUTTON_MECHA_REVERSE                  = $29000404; { Toggles throttle in/out of reverse }
+  DIBUTTON_MECHA_ZOOM                     = $29000405; { Zoom in/out targeting reticule }
+  DIBUTTON_MECHA_JUMP                     = $29000406; { Fires jump jets }
+  DIBUTTON_MECHA_MENU                     = $290004FD; { Show menu options }
+(*--- Priority 2 controls                            ---*)
+
+  DIBUTTON_MECHA_CENTER                   = $29004407; { Center torso to legs }
+  DIHATSWITCH_MECHA_GLANCE                = $29004601; { Look around }
+  DIBUTTON_MECHA_VIEW                     = $29004408; { Cycle through view options }
+  DIBUTTON_MECHA_FIRESECONDARY            = $29004409; { Alternative fire button }
+  DIBUTTON_MECHA_LEFT_LINK                = $2900C4E4; { Fallback steer left button }
+  DIBUTTON_MECHA_RIGHT_LINK               = $2900C4EC; { Fallback steer right button }
+  DIBUTTON_MECHA_FORWARD_LINK             = $290144E0; { Fallback tilt torso forward button }
+  DIBUTTON_MECHA_BACK_LINK                = $290144E8; { Fallback tilt toroso backward button }
+  DIBUTTON_MECHA_ROTATE_LEFT_LINK         = $290244E4; { Fallback rotate toroso right button }
+  DIBUTTON_MECHA_ROTATE_RIGHT_LINK        = $290244EC; { Fallback rotate torso left button }
+  DIBUTTON_MECHA_FASTER_LINK              = $2903C4E0; { Fallback increase engine speed }
+  DIBUTTON_MECHA_SLOWER_LINK              = $2903C4E8; { Fallback decrease engine speed }
+  DIBUTTON_MECHA_DEVICE                   = $290044FE; { Show input device and controls }
+  DIBUTTON_MECHA_PAUSE                    = $290044FC; { Start / Pause / Restart game }
+
+(*
+ *  "ANY" semantics can be used as a last resort to get mappings for actions
+ *  that match nothing in the chosen virtual genre.  These semantics will be
+ *  mapped at a lower priority that virtual genre semantics.  Also, hardware
+ *  vendors will not be able to provide sensible mappings for these unless
+ *  they provide application specific mappings.
+ *)
+  DIAXIS_ANY_X_1                          = $FF00C201;
+  DIAXIS_ANY_X_2                          = $FF00C202;
+  DIAXIS_ANY_Y_1                          = $FF014201;
+  DIAXIS_ANY_Y_2                          = $FF014202;
+  DIAXIS_ANY_Z_1                          = $FF01C201;
+  DIAXIS_ANY_Z_2                          = $FF01C202;
+  DIAXIS_ANY_R_1                          = $FF024201;
+  DIAXIS_ANY_R_2                          = $FF024202;
+  DIAXIS_ANY_U_1                          = $FF02C201;
+  DIAXIS_ANY_U_2                          = $FF02C202;
+  DIAXIS_ANY_V_1                          = $FF034201;
+  DIAXIS_ANY_V_2                          = $FF034202;
+  DIAXIS_ANY_A_1                          = $FF03C201;
+  DIAXIS_ANY_A_2                          = $FF03C202;
+  DIAXIS_ANY_B_1                          = $FF044201;
+  DIAXIS_ANY_B_2                          = $FF044202;
+  DIAXIS_ANY_C_1                          = $FF04C201;
+  DIAXIS_ANY_C_2                          = $FF04C202;
+  DIAXIS_ANY_S_1                          = $FF054201;
+  DIAXIS_ANY_S_2                          = $FF054202;
+
+  DIAXIS_ANY_1                            = $FF004201;
+  DIAXIS_ANY_2                            = $FF004202;
+  DIAXIS_ANY_3                            = $FF004203;
+  DIAXIS_ANY_4                            = $FF004204;
+
+  DIPOV_ANY_1                             = $FF004601;
+  DIPOV_ANY_2                             = $FF004602;
+  DIPOV_ANY_3                             = $FF004603;
+  DIPOV_ANY_4                             = $FF004604;
+
+//#define DIBUTTON_ANY(instance)                  ( 0xFF004400 | instance )
+
+
+//#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
+//#pragma endregion
+
+//#ifdef __cplusplus
+//};
+//#endif
+
+//#endif  /* __DINPUT_INCLUDED__ */
+
+(****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current sdk files
+ *
+ ****************************************************************************)
+
+{$IFDEF _INC_MMSYSTEM}
+{$IFNDEF MMNOJOY}
+
+{$IFNDEF __VJOYDX_INCLUDED__}
+{$DEFINE __VJOYDX_INCLUDED__}
+
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+
+//#pragma region Desktop Family
+//#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+
+(*
+ * Flag to indicate that the dwReserved2 field of the JOYINFOEX structure
+ * contains mini-driver specific data to be passed by VJoyD to the mini-
+ * driver instead of doing a poll.
+ *)
+const
+  JOY_PASSDRIVERDATA          = $10000000;
+
+(*
+ * Informs the joystick driver that the configuration has been changed
+ * and should be reloaded from the registery.
+ * dwFlags is reserved and should be set to zero
+ *)
+//WINMMAPI MMRESULT WINAPI joyConfigChanged( DWORD dwFlags );
+
+//#ifndef DIJ_RINGZERO
+(*
+ * Invoke the joystick control panel directly, using the passed window handle
+ * as the parent of the dialog.  This API is only supported for compatibility
+ * purposes; new applications should use the RunControlPanel method of a
+ * device interface for a game controller.
+ * The API is called by using the function pointer returned by
+ * GetProcAddress( hCPL, TEXT("ShowJoyCPL") ) where hCPL is a HMODULE returned
+ * by LoadLibrary( TEXT("joy.cpl") ).  The typedef is provided to allow
+ * declaration and casting of an appropriately typed variable.
+ *)
+//void WINAPI ShowJoyCPL( HWND hWnd );
+//typedef void (WINAPI* LPFNSHOWJOYCPL)( HWND hWnd );
+type
+  LPFNSHOWJOYCPL = procedure(hWnd: HWND); stdcall;
+//#endif
+
+(*
+ * Hardware Setting indicating that the device is a headtracker
+ *)
+const
+  JOY_HWS_ISHEADTRACKER       = $02000000;
+
+(*
+ * Hardware Setting indicating that the VxD is used to replace
+ * the standard analog polling
+ *)
+  JOY_HWS_ISGAMEPORTDRIVER    = $04000000;
+
+(*
+ * Hardware Setting indicating that the driver needs a standard
+ * gameport in order to communicate with the device.
+ *)
+  JOY_HWS_ISANALOGPORTDRIVER  = $08000000;
+
+(*
+ * Hardware Setting indicating that VJoyD should not load this
+ * driver, it will be loaded externally and will register with
+ * VJoyD of it's own accord.
+ *)
+  JOY_HWS_AUTOLOAD            = $10000000;
+
+(*
+ * Hardware Setting indicating that the driver acquires any
+ * resources needed without needing a devnode through VJoyD.
+ *)
+  JOY_HWS_NODEVNODE           = $20000000;
+
+
+(*
+ * Hardware Setting indicating that the device is a gameport bus
+ *)
+  JOY_HWS_ISGAMEPORTBUS       = $80000000;
+  JOY_HWS_GAMEPORTBUSBUSY     = $00000001;
+
+(*
+ * Usage Setting indicating that the settings are volatile and
+ * should be removed if still present on a reboot.
+ *)
+  JOY_US_VOLATILE             = $00000008;
+
+//#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
+//#pragma endregion
+
+//#ifdef __cplusplus
+//};
+//#endif
+
+{$ENDIF}  { __VJOYDX_INCLUDED__ }
+
+{$ENDIF}  { not MMNOJOY }
+{$ENDIF}  { _INC_MMSYSTEM }
+
+(****************************************************************************
+ *
+ *  Definitions for non-IDirectInput (VJoyD) features defined more recently
+ *  than the current ddk files
+ *
+ ****************************************************************************)
+
+//#ifndef DIJ_RINGZERO
+
+{$IFDEF _INC_MMDDK}
+{$IFNDEF MMNOJOYDEV}
+
+{$IFNDEF __VJOYDXD_INCLUDED__}
+{$DEFINE __VJOYDXD_INCLUDED__}
+(*
+ * Poll type in which the do_other field of the JOYOEMPOLLDATA
+ * structure contains mini-driver specific data passed from an app.
+ *)
+const
+  JOY_OEMPOLL_PASSDRIVERDATA = 7;
+
+{$ENDIF}  { __VJOYDXD_INCLUDED__ }
+
+{$ENDIF}  { not MMNOJOYDEV }
+{$ENDIF}  { _INC_MMDDK }
+
+//#endif /* DIJ_RINGZERO */
+
+function GET_DIDEVICE_SUBTYPE(dwDevType: DWORD): BYTE; inline;
+function DIDFT_MAKEINSTANCE(n: WORD): DWORD; inline;
+function DIDFT_GETINSTANCE(n: DWORD): WORD; inline;
+function DIDFT_ENUMCOLLECTION(n: WORD): DWORD; inline;
+{$IF DIRECTINPUT_VERSION >= $050a}
+function DIMAKEUSAGEDWORD(UsagePage, Usage: Word): DWORD; inline;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+function DISEQUENCE_COMPARE(dwSequence1: DWORD; const cmp: string; dwSequence2: DWORD): Boolean; inline;
+function DIBUTTON_ANY(instance: Byte): DWORD; inline;
+
+implementation
+
+//#define GET_DIDEVICE_SUBTYPE(dwDevType) HIBYTE(dwDevType)
+function GET_DIDEVICE_SUBTYPE(dwDevType: DWORD): BYTE; inline;
+begin
+  Result := HIBYTE(dwDevType);
+end;
+
+//#define DIDFT_MAKEINSTANCE(n) ((WORD)(n) << 8)
+function DIDFT_MAKEINSTANCE(n: WORD): DWORD; inline;
+begin
+  Result := n shl 8;
+end;
+
+//#define DIDFT_GETINSTANCE(n) LOWORD((n) >> 8)
+function DIDFT_GETINSTANCE(n: DWORD): WORD; inline;
+begin
+  Result := LOWORD(n shr 8);
+end;
+
+//#define DIDFT_ENUMCOLLECTION(n) ((WORD)(n) << 8)
+function DIDFT_ENUMCOLLECTION(n: WORD): DWORD; inline;
+begin
+  Result := n shl 8;
+end;
+
+{$IF DIRECTINPUT_VERSION >= $050a}
+//#define DIMAKEUSAGEDWORD(UsagePage, Usage) \
+//                                (DWORD)MAKELONG(Usage, UsagePage)
+function DIMAKEUSAGEDWORD(UsagePage, Usage: Word): DWORD; inline;
+begin
+  Result := MAKELONG(Usage, UsagePage);
+end;
+{$ENDIF} { DIRECTINPUT_VERSION >= $050a }
+
+//#define DISEQUENCE_COMPARE(dwSequence1, cmp, dwSequence2) \
+//                        ((int)((dwSequence1) - (dwSequence2)) cmp 0)
+function DISEQUENCE_COMPARE(dwSequence1: DWORD; const cmp: string; dwSequence2: DWORD): Boolean; inline;
+begin
+{$PUSH}{$Q-,R-}
+  if (cmp = '==') or (cmp = '=') then
+    Result := LongInt(dwSequence1 - dwSequence2) = 0
+  else if (cmp = '!=') or (cmp = '<>') then
+    Result := LongInt(dwSequence1 - dwSequence2) <> 0
+  else if cmp = '<' then
+    Result := LongInt(dwSequence1 - dwSequence2) < 0
+  else if cmp = '>' then
+    Result := LongInt(dwSequence1 - dwSequence2) > 0
+  else if cmp = '<=' then
+    Result := LongInt(dwSequence1 - dwSequence2) <= 0
+  else if cmp = '>=' then
+    Result := LongInt(dwSequence1 - dwSequence2) >= 0;
+{$POP}
+end;
+
+//#define DIBUTTON_ANY(instance)                  ( 0xFF004400 | instance )
+function DIBUTTON_ANY(instance: Byte): DWORD; inline;
+begin
+  Result := $FF004400 or instance;
+end;
+
+end.

+ 2 - 1
packages/ptc/src/win32/directx/win32directxconsoled.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -180,4 +180,5 @@ type
     function GetInformation: string; override;
     function NextEvent(out AEvent: IPTCEvent; AWait: Boolean; const AEventMask: TPTCEventMask): Boolean; override;
     function PeekEvent(AWait: Boolean; const AEventMask: TPTCEventMask): IPTCEvent; override;
+    function MoveMouseTo(X, Y: Integer): Boolean; override;
   end;

+ 8 - 2
packages/ptc/src/win32/directx/win32directxconsolei.inc

@@ -1,6 +1,6 @@
 {
     Free Pascal port of the OpenPTC C++ library.
-    Copyright (C) 2001-2003, 2006, 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2003, 2006, 2007, 2009-2013, 2016  Nikolay Nikolov ([email protected])
     Original C++ version by Glenn Fiedler ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -991,7 +991,7 @@ begin
   FKeyboard := TWin32Keyboard.Create(FWindow.handle, FWindow.thread, False, FEventQueue);
   FMouse := TWin32Mouse.Create(FWindow.handle, FWindow.thread, False, FEventQueue, FPrimary.Fullscreen, FPrimary.width, FPrimary.height);
   if FPrimary.Fullscreen then
-    FMouse.SetWindowArea(0, 0, FDisplay.Mode.Width, FDisplay.Mode.Height);
+    FMouse.SetWindowArea(0, 0, FDisplay.Mode.Width - 1, FDisplay.Mode.Height - 1);
   if not FPrimary.Fullscreen then
     FResize := TWin32Resize.Create(FWindow.handle, FWindow.thread, FEventQueue);
   FWindow.update;
@@ -1243,6 +1243,12 @@ begin
     FWindow.InterceptClose := AInterceptClose;
 end;
 
+function TDirectXConsole.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  CHECK_OPEN('TDirectXConsole.MoveMouseTo');
+  Result := FMouse.MoveMouseTo(X, Y);
+end;
+
 {$IFDEF DEBUG}
 procedure TDirectXConsole.CHECK_OPEN(AMsg: String);
 begin

+ 3 - 3
packages/ptc/src/win32/directx/win32directxdisplay.inc

@@ -119,8 +119,8 @@ begin
       if not found then
       begin
         LOG('adding 320x200x8 to mode list');
-	
-	Inc(FModesCount);
+
+        Inc(FModesCount);
         SetLength(FModes, FModesCount);
         FModes[FModesCount - 1] := TPTCMode.Create(320, 200, format8);
       end;
@@ -133,7 +133,7 @@ begin
       begin
         LOG('adding 320x240x8 to mode list');
 
-	Inc(FModesCount);
+        Inc(FModesCount);
         SetLength(FModes, FModesCount);
         FModes[FModesCount - 1] := TPTCMode.Create(320, 240, format8);
       end;

+ 12 - 12
packages/ptc/src/win32/directx/win32directxhook.inc

@@ -79,9 +79,9 @@ begin
       if active = False then
       begin
         if FConsole.FGrabMouse and (not FFullscreen) then
-	begin
-	  FConsole.FWindow.ConfineCursor(False);
-	end;
+        begin
+          FConsole.FWindow.ConfineCursor(False);
+        end;
 
         { deactivate }
         Deactivate;
@@ -103,19 +103,19 @@ begin
         begin
           { check show command is not minimize }
           if placement.showCmd <> SW_SHOWMINIMIZED then
-	  begin
+          begin
             {hide cursor}
             FConsole.FWin32Cursor.Hide;
-	  end;
+          end;
         end;
 
-	if FConsole.FGrabMouse and (not FFullscreen) then
-	begin
+        if FConsole.FGrabMouse and (not FFullscreen) then
+        begin
           if placement.showCmd <> SW_SHOWMINIMIZED then
-	  begin
+          begin
             FConsole.FWindow.ConfineCursor(True);
-	  end;
-	end;
+          end;
+        end;
 
         { activate }
         Activate;
@@ -130,13 +130,13 @@ begin
       if not FCursor then
       begin
         if FFullscreen or (LOWORD(lParam) = HTCLIENT) then
-	begin
+        begin
           { hide cursor }
           SetCursor(0);
 
           { handled }
           Result := 1;
-	end;
+        end;
       end;
     end;
     WM_PALETTECHANGED:

+ 5 - 3
packages/ptc/src/win32/gdi/win32gdiconsoled.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2007, 2009-2013, 2016  Nikolay Nikolov ([email protected])
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
@@ -154,7 +154,9 @@ type
     function NextEvent(out AEvent: IPTCEvent; AWait: Boolean; const AEventMask: TPTCEventMask): Boolean; override;
     function PeekEvent(AWait: Boolean; const AEventMask: TPTCEventMask): IPTCEvent; override;
 
+    function MoveMouseTo(X, Y: Integer): Boolean; override;
+
     procedure OpenGL_SwapBuffers; override;
-	procedure OpenGL_SetSwapInterval(AInterval: Integer); override;
-	function OpenGL_GetSwapInterval: Integer; override;
+    procedure OpenGL_SetSwapInterval(AInterval: Integer); override;
+    function OpenGL_GetSwapInterval: Integer; override;
   end;

+ 9 - 3
packages/ptc/src/win32/gdi/win32gdiconsolei.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2007, 2009-2013  Nikolay Nikolov ([email protected])
+    Copyright (C) 2007, 2009-2013, 2016  Nikolay Nikolov ([email protected])
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
@@ -225,7 +225,7 @@ begin
   FKeyboard := TWin32Keyboard.Create(FWindow.Handle, FWindow.Thread, False, FEventQueue);
   FMouse := TWin32Mouse.Create(FWindow.Handle, FWindow.Thread, False, FEventQueue, FFullScreen, AWidth, AHeight);
   if FFullscreen then
-    FMouse.SetWindowArea(0, 0, AWidth, AHeight);
+    FMouse.SetWindowArea(0, 0, AWidth - 1, AHeight - 1);
   if not FFullscreen and FResizable then
     FResize := TWin32Resize.Create(FWindow.Handle, FWindow.Thread, FEventQueue);
 
@@ -730,7 +730,7 @@ begin
     LOG('using WGL_EXT_swap_control');
     LOG('wglSwapIntervalEXT(' + IntToStr(AInterval) + ')');
     if not wglSwapIntervalEXT(AInterval) then
-	  LOG('wglSwapIntervalEXT failed');
+      LOG('wglSwapIntervalEXT failed');
   end
   else
     LOG('no supported extensions found for setting the swap interval');
@@ -761,6 +761,12 @@ begin
     FWindow.InterceptClose := AInterceptClose;
 end;
 
+function TGDIConsole.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  CheckOpen('TGDIConsole.MoveMouseTo');
+  Result := FMouse.MoveMouseTo(X, Y);
+end;
+
 procedure TGDIConsole.CheckOpen(const AMessage: String);
 begin
   if not FOpen then

+ 2 - 2
packages/ptc/src/win32/gdi/win32openglwindowd.inc

@@ -33,9 +33,9 @@ type
   TWin32OpenGLWindow = class(TWin32Window)
   private
     FPixelFormatDescriptor: PIXELFORMATDESCRIPTOR;
-	FChosenPixelFormatDescriptor: PIXELFORMATDESCRIPTOR;
+    FChosenPixelFormatDescriptor: PIXELFORMATDESCRIPTOR;
 
-	procedure SetOpenGLAttributes(const AOpenGLAttributes: IPTCOpenGLAttributes);
+    procedure SetOpenGLAttributes(const AOpenGLAttributes: IPTCOpenGLAttributes);
     function EnumerateAllPixelFormats(hdc: HDC): Boolean;
     function SetupOpenGLPixelFormat(hdc: HDC): Boolean;
     procedure LogPixelFormatDescriptor(const pfd: PIXELFORMATDESCRIPTOR);

+ 2 - 2
packages/ptc/src/win32/gdi/win32openglwindowi.inc

@@ -160,13 +160,13 @@ begin
     Flags := Flags or PFD_DOUBLEBUFFER_DONTCARE
   else
     if AOpenGLAttributes.DoubleBuffer then
-	  Flags := Flags or PFD_DOUBLEBUFFER;
+      Flags := Flags or PFD_DOUBLEBUFFER;
 
   if AOpenGLAttributes.StereoDontCare then
     Flags := Flags or PFD_STEREO_DONTCARE
   else
     if AOpenGLAttributes.Stereo then
-	  Flags := Flags or PFD_STEREO;
+      Flags := Flags or PFD_STEREO;
 
   FillChar(FPixelFormatDescriptor, SizeOf(FPixelFormatDescriptor), 0);
   FPixelFormatDescriptor.nSize := SizeOf(FPixelFormatDescriptor);

+ 4 - 1
packages/ptc/src/x11/x11consoled.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -40,6 +40,7 @@ type
 
     procedure UpdateCursor;
     procedure UpdateMouseGrab;
+    function UpdateRelativeMouseMode: Boolean;
 
     function CreateDisplay: TX11Display; { Factory method }
 
@@ -117,6 +118,8 @@ type
     function NextEvent(out AEvent: IPTCEvent; AWait: Boolean; const AEventMask: TPTCEventMask): Boolean; override;
     function PeekEvent(AWait: Boolean; const AEventMask: TPTCEventMask): IPTCEvent; override;
 
+    function MoveMouseTo(X, Y: Integer): Boolean; override;
+
     procedure OpenGL_SwapBuffers; override;
     procedure OpenGL_SetSwapInterval(AInterval: Integer); override;
     function OpenGL_GetSwapInterval: Integer; override;

+ 51 - 2
packages/ptc/src/x11/x11consolei.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2016, 2017 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -37,7 +37,8 @@ begin
   inherited Create;
 
   { default flags }
-  FFlags := [PTC_X11_TRY_XSHM, PTC_X11_TRY_XF86VIDMODE];
+  FFlags := [PTC_X11_TRY_XSHM, PTC_X11_TRY_XF86VIDMODE, PTC_X11_TRY_XINPUT2,
+             PTC_X11_TRY_XIM];
 
   FTitle := '';
 
@@ -170,6 +171,26 @@ begin
     FFlags := FFlags - [PTC_X11_TRY_XSHM];
     exit;
   end;
+  if (AOption = 'xinput2') or (AOption = 'xinput2 on') then
+  begin
+    FFlags := FFlags + [PTC_X11_TRY_XINPUT2];
+    exit;
+  end;
+  if AOption = 'xinput2 off' then
+  begin
+    FFlags := FFlags - [PTC_X11_TRY_XINPUT2];
+    exit;
+  end;
+  if (AOption = 'xim') or (AOption = 'xim on') then
+  begin
+    FFlags := FFlags + [PTC_X11_TRY_XIM];
+    exit;
+  end;
+  if AOption = 'xim off' then
+  begin
+    FFlags := FFlags - [PTC_X11_TRY_XIM];
+    exit;
+  end;
   if AOption = 'default cursor' then
   begin
     FFlags := FFlags - [PTC_X11_FULLSCREEN_CURSOR_VISIBLE, PTC_X11_WINDOWED_CURSOR_INVISIBLE];
@@ -200,6 +221,18 @@ begin
     UpdateMouseGrab;
     exit;
   end;
+  if AOption = 'relative mouse on' then
+  begin
+    FFlags := FFlags + [PTC_X11_RELATIVE_MOUSE_MODE];
+    Result := UpdateRelativeMouseMode;
+    exit;
+  end;
+  if AOption = 'relative mouse off' then
+  begin
+    FFlags := FFlags - [PTC_X11_RELATIVE_MOUSE_MODE];
+    Result := UpdateRelativeMouseMode;
+    exit;
+  end;
   if AOption = 'intercept window close' then
   begin
     FFlags := FFlags + [PTC_X11_INTERCEPT_WINDOW_CLOSE];
@@ -575,6 +608,22 @@ begin
     FX11Display.SetMouseGrab(PTC_X11_GRAB_MOUSE in FFlags);
 end;
 
+function TX11Console.UpdateRelativeMouseMode: Boolean;
+begin
+  if Assigned(FX11Display) then
+    Result := FX11Display.SetRelativeMouseMode(PTC_X11_RELATIVE_MOUSE_MODE in FFlags)
+  else
+    Result := True;
+end;
+
+function TX11Console.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  if Assigned(FX11Display) then
+    Result := FX11Display.MoveMouseTo(X, Y)
+  else
+    Result := False;
+end;
+
 procedure TX11Console.OpenGL_SwapBuffers;
 begin
   FX11Display.OpenGL_SwapBuffers;

+ 2 - 1
packages/ptc/src/x11/x11dga1displayd.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2012 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2012, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -76,6 +76,7 @@ type
     function IsOpen: Boolean; override;
     procedure SetCursor(AVisible: Boolean); override;
     procedure SetMouseGrab(AGrabMouse: Boolean); override;
+    function SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean; override;
   end;
 
 {$ENDIF ENABLE_X11_EXTENSION_XF86DGA1}

+ 7 - 1
packages/ptc/src/x11/x11dga1displayi.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2012 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2012, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -483,4 +483,10 @@ begin
   {...}
 end;
 
+function TX11DGA1Display.SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean;
+begin
+  {...}
+  Result := not ARelativeMouseMode;
+end;
+
 {$ENDIF ENABLE_X11_EXTENSION_XF86DGA1}

+ 2 - 1
packages/ptc/src/x11/x11dga2displayd.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2012 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2012, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -78,6 +78,7 @@ type
     function IsOpen: Boolean; override;
     procedure SetCursor(visible: Boolean); override;
     procedure SetMouseGrab(AGrabMouse: Boolean); override;
+    function SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean; override;
   end;
 
 {$ENDIF ENABLE_X11_EXTENSION_XF86DGA2}

+ 7 - 1
packages/ptc/src/x11/x11dga2displayi.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2012 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2012, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -560,4 +560,10 @@ begin
   {...}
 end;
 
+function TX11DGA2Display.SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean;
+begin
+  {...}
+  Result := not ARelativeMouseMode;
+end;
+
 {$ENDIF ENABLE_X11_EXTENSION_XF86DGA2}

+ 11 - 1
packages/ptc/src/x11/x11displayd.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2016, 2017 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -39,10 +39,13 @@ type
                    PTC_X11_TRY_XF86VIDMODE,
                    PTC_X11_TRY_XRANDR,
                    PTC_X11_TRY_XSHM,
+                   PTC_X11_TRY_XINPUT2,
+                   PTC_X11_TRY_XIM,
                    PTC_X11_DITHER,
                    PTC_X11_FULLSCREEN_CURSOR_VISIBLE,
                    PTC_X11_WINDOWED_CURSOR_INVISIBLE,
                    PTC_X11_GRAB_MOUSE,
+                   PTC_X11_RELATIVE_MOUSE_MODE,
                    PTC_X11_INTERCEPT_WINDOW_CLOSE,
                    PTC_X11_RESIZABLE_WINDOW,
                    PTC_X11_USE_OPENGL);
@@ -74,6 +77,9 @@ type
     FFunctionKeys: PInteger;
     FNormalKeys: PInteger;
 
+    FXIM: PXIM;
+    FXIC: PXIC;
+
     function GetInterceptClose: Boolean;
     procedure SetInterceptClose(AInterceptClose: Boolean);
 
@@ -148,6 +154,8 @@ type
     { mouse grab control }
     procedure SetMouseGrab(AGrabMouse: Boolean); virtual; abstract;
 
+    function SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean; virtual; abstract;
+
     { Data access }
     function Clip: IPTCArea;
 
@@ -176,6 +184,8 @@ type
     property Area: IPTCArea read GetArea;
     property Format: IPTCFormat read GetFormat;
 
+    function MoveMouseTo(X, Y: Integer): Boolean; virtual;
+
     procedure OpenGL_SwapBuffers; virtual;
     procedure OpenGL_SetSwapInterval(AInterval: Integer); virtual;
     function OpenGL_GetSwapInterval: Integer; virtual;

+ 56 - 6
packages/ptc/src/x11/x11displayi.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2015-2017 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -452,11 +452,23 @@ var
   uni: Integer;
   key: TPTCKeyEvent;
   buf: array [1..16] of Char;
+  lslen: cint;
+  status: TStatus;
+  eaten_by_im: Boolean = False;
 begin
-  sym := XLookupKeySym(@e, 0);
+  if Assigned(FXIM) and Assigned(FXIC) and (Self is TX11WindowDisplay) then
+  begin
+    eaten_by_im := XFilterEvent(@e, TX11WindowDisplay(Self).FWindow);
+  end;
   XLookupString(@e, @buf, SizeOf(buf), @sym_modded, nil);
+  if (e._type = KeyPress) and Assigned(FXIM) and Assigned(FXIC) then
+  begin
+    lslen := XmbLookupString(FXIC, @e, @buf, SizeOf(buf), @sym_modded, @status);
+//    Writeln(lslen, ' ', status, ' ', buf[1], ' ', XKeysymToString(sym_modded));
+  end;
+  sym := XLookupKeySym(@e, 0);
 //  Writeln('sym_modded = ', sym_modded);
-  uni := X11ConvertKeySymToUnicode(sym_modded);
+//  Writeln(HexStr(e.state, 8));
   modkeys := [];
   if (e.state and Mod1Mask) <> 0 then
     Include(modkeys, pmkAlt);
@@ -464,10 +476,42 @@ begin
     Include(modkeys, pmkShift);
   if (e.state and ControlMask) <> 0 then
     Include(modkeys, pmkControl);
+  if (e.state and LockMask) <> 0 then
+    Include(modkeys, pmkCapsLockActive);
+  if (e.state and Mod2Mask) <> 0 then
+    Include(modkeys, pmkNumLockActive);
+  if X11IsDeadKey(sym_modded) then
+    Include(modkeys, pmkDeadKey);
   if e._type = KeyPress then
-    press := True
+  begin
+    press := True;
+    uni := X11ConvertKeySymToUnicode(sym_modded);
+  end
   else
+  begin
     press := False;
+    uni := -1;
+  end;
+  if (sym_modded = XK_KP_Insert) or
+     (sym_modded = XK_KP_Delete) or
+     (sym_modded = XK_KP_Home) or
+     (sym_modded = XK_KP_End) or
+     (sym_modded = XK_KP_Prior) or
+     (sym_modded = XK_KP_Next) or
+     (sym_modded = XK_KP_Begin) or
+     (sym_modded = XK_KP_Left) or
+     (sym_modded = XK_KP_Right) or
+     (sym_modded = XK_KP_Up) or
+     (sym_modded = XK_KP_Down) or
+     (sym_modded = XK_KP_Divide) or
+     (sym_modded = XK_KP_Multiply) or
+     (sym_modded = XK_KP_Subtract) or
+     (sym_modded = XK_KP_Add) or
+     (sym_modded = XK_KP_Enter) or
+     (sym_modded = XK_KP_Decimal) or
+     ((sym_modded >= XK_KP_0) and (sym_modded <= XK_KP_9)) or
+     (sym_modded = XK_Num_Lock) then
+    Include(modkeys, pmkNumPadKey);
 
   // XK_ISO_Left_Tab is Shift-Tab
   if sym_modded = XK_ISO_Left_Tab then
@@ -496,9 +540,10 @@ begin
     0: key := TPTCKeyEvent.Create(FNormalKeys[sym_modded and $FF], uni, modkeys, press);
     $FF: key := TPTCKeyEvent.Create(FFunctionKeys[sym_modded and $FF], uni, modkeys, press);
     else
-      key := TPTCKeyEvent.Create;
+      key := TPTCKeyEvent.Create(PTCKEY_UNDEFINED, uni, modkeys, press);
   end;
-  FEventQueue.AddEvent(key);
+  if (not eaten_by_im) or (pmkDeadKey in modkeys) then
+    FEventQueue.AddEvent(key);
 end;
 
 function TX11Display.GetInterceptClose: Boolean;
@@ -519,6 +564,11 @@ begin
   raise TPTCError.Create('Console not in windowed mode');
 end;
 
+function TX11Display.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  Result := False;
+end;
+
 procedure TX11Display.OpenGL_SwapBuffers;
 begin
   raise TPTCError.Create('Not in OpenGL mode');

+ 1 - 0
packages/ptc/src/x11/x11extensions.inc

@@ -5,3 +5,4 @@
 {$DEFINE ENABLE_X11_EXTENSION_XF86DGA2}
 {$DEFINE ENABLE_X11_EXTENSION_XSHM}
 {$DEFINE ENABLE_X11_EXTENSION_GLX}
+{$DEFINE ENABLE_X11_EXTENSION_XINPUT2}

+ 734 - 197
packages/ptc/src/x11/x11unikey.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2012 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2012,2017 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -30,6 +30,25 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 }
 
+function X11IsDeadKey(sym: TKeySym): Boolean;
+begin
+  case sym of
+    XK_dead_grave, XK_dead_acute, XK_dead_circumflex,
+    XK_dead_tilde, XK_dead_macron, XK_dead_breve, XK_dead_abovedot,
+    XK_dead_diaeresis, XK_dead_abovering, XK_dead_doubleacute, XK_dead_caron,
+    XK_dead_cedilla, XK_dead_ogonek, XK_dead_iota, XK_dead_voiced_sound,
+    XK_dead_semivoiced_sound, XK_dead_belowdot, XK_dead_hook, XK_dead_horn,
+    XK_dead_stroke, XK_dead_abovecomma, XK_dead_abovereversedcomma,
+    XK_dead_doublegrave, XK_dead_belowring, XK_dead_belowmacron,
+    XK_dead_belowcircumflex, XK_dead_belowtilde, XK_dead_belowbreve,
+    XK_dead_belowdiaeresis, XK_dead_invertedbreve, XK_dead_belowcomma,
+    XK_dead_currency:
+      Result := True;
+    else
+      Result := False;
+  end;
+end;
+
 function X11ConvertKeySymToUnicode(sym: TKeySym): Integer;
 begin
   if (sym >= 0) and (sym <= $FF) then
@@ -61,206 +80,724 @@ begin
     XK_Escape: exit(27);
   End;
   case sym of
-    XKc_Cyrillic_GHE_bar     : exit($492);
-    XK_Cyrillic_ghe_bar      : exit($493);
-    XKc_Cyrillic_ZHE_descender: exit($496);
-    XK_Cyrillic_zhe_descender: exit($497);
-    XKc_Cyrillic_KA_descender: exit($49A);
-    XK_Cyrillic_ka_descender : exit($49B);
-    XKc_Cyrillic_KA_vertstroke: exit($49C);
-    XK_Cyrillic_ka_vertstroke: exit($49D);
-    XKc_Cyrillic_EN_descender: exit($4A2);
-    XK_Cyrillic_en_descender : exit($4A3);
-    XKc_Cyrillic_U_straight  : exit($4AE);
-    XK_Cyrillic_u_straight   : exit($4AF);
-    XKc_Cyrillic_U_straight_bar: exit($4B0);
-    XK_Cyrillic_u_straight_bar: exit($4B1);
-    XKc_Cyrillic_HA_descender: exit($4B2);
-    XK_Cyrillic_ha_descender : exit($4B3);
-    XKc_Cyrillic_CHE_descender: exit($4B6);
-    XK_Cyrillic_che_descender: exit($4B7);
-    XKc_Cyrillic_CHE_vertstroke: exit($4B8);
-    XK_Cyrillic_che_vertstroke: exit($4B9);
-    XKc_Cyrillic_SHHA        : exit($4BA);
-    XK_Cyrillic_shha         : exit($4BB);
+    { Latin 2 }
+    XKc_Aogonek      : exit($0104);  { U+0104 LATIN CAPITAL LETTER A WITH OGONEK }
+    XK_breve         : exit($02D8);  { U+02D8 BREVE }
+    XKc_Lstroke      : exit($0141);  { U+0141 LATIN CAPITAL LETTER L WITH STROKE }
+    XKc_Lcaron       : exit($013D);  { U+013D LATIN CAPITAL LETTER L WITH CARON }
+    XKc_Sacute       : exit($015A);  { U+015A LATIN CAPITAL LETTER S WITH ACUTE }
+    XKc_Scaron       : exit($0160);  { U+0160 LATIN CAPITAL LETTER S WITH CARON }
+    XKc_Scedilla     : exit($015E);  { U+015E LATIN CAPITAL LETTER S WITH CEDILLA }
+    XKc_Tcaron       : exit($0164);  { U+0164 LATIN CAPITAL LETTER T WITH CARON }
+    XKc_Zacute       : exit($0179);  { U+0179 LATIN CAPITAL LETTER Z WITH ACUTE }
+    XKc_Zcaron       : exit($017D);  { U+017D LATIN CAPITAL LETTER Z WITH CARON }
+    XKc_Zabovedot    : exit($017B);  { U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE }
+    XK_aogonek       : exit($0105);  { U+0105 LATIN SMALL LETTER A WITH OGONEK }
+    XK_ogonek        : exit($02DB);  { U+02DB OGONEK }
+    XK_lstroke       : exit($0142);  { U+0142 LATIN SMALL LETTER L WITH STROKE }
+    XK_lcaron        : exit($013E);  { U+013E LATIN SMALL LETTER L WITH CARON }
+    XK_sacute        : exit($015B);  { U+015B LATIN SMALL LETTER S WITH ACUTE }
+    XK_caron         : exit($02C7);  { U+02C7 CARON }
+    XK_scaron        : exit($0161);  { U+0161 LATIN SMALL LETTER S WITH CARON }
+    XK_scedilla      : exit($015F);  { U+015F LATIN SMALL LETTER S WITH CEDILLA }
+    XK_tcaron        : exit($0165);  { U+0165 LATIN SMALL LETTER T WITH CARON }
+    XK_zacute        : exit($017A);  { U+017A LATIN SMALL LETTER Z WITH ACUTE }
+    XK_doubleacute   : exit($02DD);  { U+02DD DOUBLE ACUTE ACCENT }
+    XK_zcaron        : exit($017E);  { U+017E LATIN SMALL LETTER Z WITH CARON }
+    XK_zabovedot     : exit($017C);  { U+017C LATIN SMALL LETTER Z WITH DOT ABOVE }
+    XKc_Racute       : exit($0154);  { U+0154 LATIN CAPITAL LETTER R WITH ACUTE }
+    XKc_Abreve       : exit($0102);  { U+0102 LATIN CAPITAL LETTER A WITH BREVE }
+    XKc_Lacute       : exit($0139);  { U+0139 LATIN CAPITAL LETTER L WITH ACUTE }
+    XKc_Cacute       : exit($0106);  { U+0106 LATIN CAPITAL LETTER C WITH ACUTE }
+    XKc_Ccaron       : exit($010C);  { U+010C LATIN CAPITAL LETTER C WITH CARON }
+    XKc_Eogonek      : exit($0118);  { U+0118 LATIN CAPITAL LETTER E WITH OGONEK }
+    XKc_Ecaron       : exit($011A);  { U+011A LATIN CAPITAL LETTER E WITH CARON }
+    XKc_Dcaron       : exit($010E);  { U+010E LATIN CAPITAL LETTER D WITH CARON }
+    XKc_Dstroke      : exit($0110);  { U+0110 LATIN CAPITAL LETTER D WITH STROKE }
+    XKc_Nacute       : exit($0143);  { U+0143 LATIN CAPITAL LETTER N WITH ACUTE }
+    XKc_Ncaron       : exit($0147);  { U+0147 LATIN CAPITAL LETTER N WITH CARON }
+    XKc_Odoubleacute : exit($0150);  { U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE }
+    XKc_Rcaron       : exit($0158);  { U+0158 LATIN CAPITAL LETTER R WITH CARON }
+    XKc_Uring        : exit($016E);  { U+016E LATIN CAPITAL LETTER U WITH RING ABOVE }
+    XKc_Udoubleacute : exit($0170);  { U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE }
+    XKc_Tcedilla     : exit($0162);  { U+0162 LATIN CAPITAL LETTER T WITH CEDILLA }
+    XK_racute        : exit($0155);  { U+0155 LATIN SMALL LETTER R WITH ACUTE }
+    XK_abreve        : exit($0103);  { U+0103 LATIN SMALL LETTER A WITH BREVE }
+    XK_lacute        : exit($013A);  { U+013A LATIN SMALL LETTER L WITH ACUTE }
+    XK_cacute        : exit($0107);  { U+0107 LATIN SMALL LETTER C WITH ACUTE }
+    XK_ccaron        : exit($010D);  { U+010D LATIN SMALL LETTER C WITH CARON }
+    XK_eogonek       : exit($0119);  { U+0119 LATIN SMALL LETTER E WITH OGONEK }
+    XK_ecaron        : exit($011B);  { U+011B LATIN SMALL LETTER E WITH CARON }
+    XK_dcaron        : exit($010F);  { U+010F LATIN SMALL LETTER D WITH CARON }
+    XK_dstroke       : exit($0111);  { U+0111 LATIN SMALL LETTER D WITH STROKE }
+    XK_nacute        : exit($0144);  { U+0144 LATIN SMALL LETTER N WITH ACUTE }
+    XK_ncaron        : exit($0148);  { U+0148 LATIN SMALL LETTER N WITH CARON }
+    XK_odoubleacute  : exit($0151);  { U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE }
+    XK_rcaron        : exit($0159);  { U+0159 LATIN SMALL LETTER R WITH CARON }
+    XK_uring         : exit($016F);  { U+016F LATIN SMALL LETTER U WITH RING ABOVE }
+    XK_udoubleacute  : exit($0171);  { U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE }
+    XK_tcedilla      : exit($0163);  { U+0163 LATIN SMALL LETTER T WITH CEDILLA }
+    XK_abovedot      : exit($02D9);  { U+02D9 DOT ABOVE }
+
+    { Latin 3 }
+    XKc_Hstroke     : exit($0126);  { U+0126 LATIN CAPITAL LETTER H WITH STROKE }
+    XKc_Hcircumflex : exit($0124);  { U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX }
+    XKc_Iabovedot   : exit($0130);  { U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE }
+    XKc_Gbreve      : exit($011E);  { U+011E LATIN CAPITAL LETTER G WITH BREVE }
+    XKc_Jcircumflex : exit($0134);  { U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX }
+    XK_hstroke      : exit($0127);  { U+0127 LATIN SMALL LETTER H WITH STROKE }
+    XK_hcircumflex  : exit($0125);  { U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX }
+    XK_idotless     : exit($0131);  { U+0131 LATIN SMALL LETTER DOTLESS I }
+    XK_gbreve       : exit($011F);  { U+011F LATIN SMALL LETTER G WITH BREVE }
+    XK_jcircumflex  : exit($0135);  { U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX }
+    XKc_Cabovedot   : exit($010A);  { U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE }
+    XKc_Ccircumflex : exit($0108);  { U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX }
+    XKc_Gabovedot   : exit($0120);  { U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE }
+    XKc_Gcircumflex : exit($011C);  { U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX }
+    XKc_Ubreve      : exit($016C);  { U+016C LATIN CAPITAL LETTER U WITH BREVE }
+    XKc_Scircumflex : exit($015C);  { U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX }
+    XK_cabovedot    : exit($010B);  { U+010B LATIN SMALL LETTER C WITH DOT ABOVE }
+    XK_ccircumflex  : exit($0109);  { U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX }
+    XK_gabovedot    : exit($0121);  { U+0121 LATIN SMALL LETTER G WITH DOT ABOVE }
+    XK_gcircumflex  : exit($011D);  { U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX }
+    XK_ubreve       : exit($016D);  { U+016D LATIN SMALL LETTER U WITH BREVE }
+    XK_scircumflex  : exit($015D);  { U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX }
+
+    { Latin 4 }
+    XK_kra        : exit($0138);  { U+0138 LATIN SMALL LETTER KRA }
+    XKc_Rcedilla  : exit($0156);  { U+0156 LATIN CAPITAL LETTER R WITH CEDILLA }
+    XKc_Itilde    : exit($0128);  { U+0128 LATIN CAPITAL LETTER I WITH TILDE }
+    XKc_Lcedilla  : exit($013B);  { U+013B LATIN CAPITAL LETTER L WITH CEDILLA }
+    XKc_Emacron   : exit($0112);  { U+0112 LATIN CAPITAL LETTER E WITH MACRON }
+    XKc_Gcedilla  : exit($0122);  { U+0122 LATIN CAPITAL LETTER G WITH CEDILLA }
+    XKc_Tslash    : exit($0166);  { U+0166 LATIN CAPITAL LETTER T WITH STROKE }
+    XK_rcedilla   : exit($0157);  { U+0157 LATIN SMALL LETTER R WITH CEDILLA }
+    XK_itilde     : exit($0129);  { U+0129 LATIN SMALL LETTER I WITH TILDE }
+    XK_lcedilla   : exit($013C);  { U+013C LATIN SMALL LETTER L WITH CEDILLA }
+    XK_emacron    : exit($0113);  { U+0113 LATIN SMALL LETTER E WITH MACRON }
+    XK_gcedilla   : exit($0123);  { U+0123 LATIN SMALL LETTER G WITH CEDILLA }
+    XK_tslash     : exit($0167);  { U+0167 LATIN SMALL LETTER T WITH STROKE }
+    XKc_ENG       : exit($014A);  { U+014A LATIN CAPITAL LETTER ENG }
+    XK_eng        : exit($014B);  { U+014B LATIN SMALL LETTER ENG }
+    XKc_Amacron   : exit($0100);  { U+0100 LATIN CAPITAL LETTER A WITH MACRON }
+    XKc_Iogonek   : exit($012E);  { U+012E LATIN CAPITAL LETTER I WITH OGONEK }
+    XKc_Eabovedot : exit($0116);  { U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE }
+    XKc_Imacron   : exit($012A);  { U+012A LATIN CAPITAL LETTER I WITH MACRON }
+    XKc_Ncedilla  : exit($0145);  { U+0145 LATIN CAPITAL LETTER N WITH CEDILLA }
+    XKc_Omacron   : exit($014C);  { U+014C LATIN CAPITAL LETTER O WITH MACRON }
+    XKc_Kcedilla  : exit($0136);  { U+0136 LATIN CAPITAL LETTER K WITH CEDILLA }
+    XKc_Uogonek   : exit($0172);  { U+0172 LATIN CAPITAL LETTER U WITH OGONEK }
+    XKc_Utilde    : exit($0168);  { U+0168 LATIN CAPITAL LETTER U WITH TILDE }
+    XKc_Umacron   : exit($016A);  { U+016A LATIN CAPITAL LETTER U WITH MACRON }
+    XK_amacron    : exit($0101);  { U+0101 LATIN SMALL LETTER A WITH MACRON }
+    XK_iogonek    : exit($012F);  { U+012F LATIN SMALL LETTER I WITH OGONEK }
+    XK_eabovedot  : exit($0117);  { U+0117 LATIN SMALL LETTER E WITH DOT ABOVE }
+    XK_imacron    : exit($012B);  { U+012B LATIN SMALL LETTER I WITH MACRON }
+    XK_ncedilla   : exit($0146);  { U+0146 LATIN SMALL LETTER N WITH CEDILLA }
+    XK_omacron    : exit($014D);  { U+014D LATIN SMALL LETTER O WITH MACRON }
+    XK_kcedilla   : exit($0137);  { U+0137 LATIN SMALL LETTER K WITH CEDILLA }
+    XK_uogonek    : exit($0173);  { U+0173 LATIN SMALL LETTER U WITH OGONEK }
+    XK_utilde     : exit($0169);  { U+0169 LATIN SMALL LETTER U WITH TILDE }
+    XK_umacron    : exit($016B);  { U+016B LATIN SMALL LETTER U WITH MACRON }
+
+    { Latin 9 }
+    XKc_OE         : exit($0152);  { U+0152 LATIN CAPITAL LIGATURE OE }
+    XK_oe          : exit($0153);  { U+0153 LATIN SMALL LIGATURE OE }
+    XKc_Ydiaeresis : exit($0178);  { U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS }
+
+    { Katakana }
+    XK_overline            : exit($203E);  { U+203E OVERLINE }
+    XK_kana_fullstop       : exit($3002);  { U+3002 IDEOGRAPHIC FULL STOP }
+    XK_kana_openingbracket : exit($300C);  { U+300C LEFT CORNER BRACKET }
+    XK_kana_closingbracket : exit($300D);  { U+300D RIGHT CORNER BRACKET }
+    XK_kana_comma          : exit($3001);  { U+3001 IDEOGRAPHIC COMMA }
+    XK_kana_conjunctive    : exit($30FB);  { U+30FB KATAKANA MIDDLE DOT }
+    XKc_kana_WO            : exit($30F2);  { U+30F2 KATAKANA LETTER WO }
+    XK_kana_a              : exit($30A1);  { U+30A1 KATAKANA LETTER SMALL A }
+    XK_kana_i              : exit($30A3);  { U+30A3 KATAKANA LETTER SMALL I }
+    XK_kana_u              : exit($30A5);  { U+30A5 KATAKANA LETTER SMALL U }
+    XK_kana_e              : exit($30A7);  { U+30A7 KATAKANA LETTER SMALL E }
+    XK_kana_o              : exit($30A9);  { U+30A9 KATAKANA LETTER SMALL O }
+    XK_kana_ya             : exit($30E3);  { U+30E3 KATAKANA LETTER SMALL YA }
+    XK_kana_yu             : exit($30E5);  { U+30E5 KATAKANA LETTER SMALL YU }
+    XK_kana_yo             : exit($30E7);  { U+30E7 KATAKANA LETTER SMALL YO }
+    XK_kana_tsu            : exit($30C3);  { U+30C3 KATAKANA LETTER SMALL TU }
+    XK_prolongedsound      : exit($30FC);  { U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK }
+    XKc_kana_A             : exit($30A2);  { U+30A2 KATAKANA LETTER A }
+    XKc_kana_I             : exit($30A4);  { U+30A4 KATAKANA LETTER I }
+    XKc_kana_U             : exit($30A6);  { U+30A6 KATAKANA LETTER U }
+    XKc_kana_E             : exit($30A8);  { U+30A8 KATAKANA LETTER E }
+    XKc_kana_O             : exit($30AA);  { U+30AA KATAKANA LETTER O }
+    XKc_kana_KA            : exit($30AB);  { U+30AB KATAKANA LETTER KA }
+    XKc_kana_KI            : exit($30AD);  { U+30AD KATAKANA LETTER KI }
+    XKc_kana_KU            : exit($30AF);  { U+30AF KATAKANA LETTER KU }
+    XKc_kana_KE            : exit($30B1);  { U+30B1 KATAKANA LETTER KE }
+    XKc_kana_KO            : exit($30B3);  { U+30B3 KATAKANA LETTER KO }
+    XKc_kana_SA            : exit($30B5);  { U+30B5 KATAKANA LETTER SA }
+    XKc_kana_SHI           : exit($30B7);  { U+30B7 KATAKANA LETTER SI }
+    XKc_kana_SU            : exit($30B9);  { U+30B9 KATAKANA LETTER SU }
+    XKc_kana_SE            : exit($30BB);  { U+30BB KATAKANA LETTER SE }
+    XKc_kana_SO            : exit($30BD);  { U+30BD KATAKANA LETTER SO }
+    XKc_kana_TA            : exit($30BF);  { U+30BF KATAKANA LETTER TA }
+    XKc_kana_CHI           : exit($30C1);  { U+30C1 KATAKANA LETTER TI }
+    XKc_kana_TSU           : exit($30C4);  { U+30C4 KATAKANA LETTER TU }
+    XKc_kana_TE            : exit($30C6);  { U+30C6 KATAKANA LETTER TE }
+    XKc_kana_TO            : exit($30C8);  { U+30C8 KATAKANA LETTER TO }
+    XKc_kana_NA            : exit($30CA);  { U+30CA KATAKANA LETTER NA }
+    XKc_kana_NI            : exit($30CB);  { U+30CB KATAKANA LETTER NI }
+    XKc_kana_NU            : exit($30CC);  { U+30CC KATAKANA LETTER NU }
+    XKc_kana_NE            : exit($30CD);  { U+30CD KATAKANA LETTER NE }
+    XKc_kana_NO            : exit($30CE);  { U+30CE KATAKANA LETTER NO }
+    XKc_kana_HA            : exit($30CF);  { U+30CF KATAKANA LETTER HA }
+    XKc_kana_HI            : exit($30D2);  { U+30D2 KATAKANA LETTER HI }
+    XKc_kana_FU            : exit($30D5);  { U+30D5 KATAKANA LETTER HU }
+    XKc_kana_HE            : exit($30D8);  { U+30D8 KATAKANA LETTER HE }
+    XKc_kana_HO            : exit($30DB);  { U+30DB KATAKANA LETTER HO }
+    XKc_kana_MA            : exit($30DE);  { U+30DE KATAKANA LETTER MA }
+    XKc_kana_MI            : exit($30DF);  { U+30DF KATAKANA LETTER MI }
+    XKc_kana_MU            : exit($30E0);  { U+30E0 KATAKANA LETTER MU }
+    XKc_kana_ME            : exit($30E1);  { U+30E1 KATAKANA LETTER ME }
+    XKc_kana_MO            : exit($30E2);  { U+30E2 KATAKANA LETTER MO }
+    XKc_kana_YA            : exit($30E4);  { U+30E4 KATAKANA LETTER YA }
+    XKc_kana_YU            : exit($30E6);  { U+30E6 KATAKANA LETTER YU }
+    XKc_kana_YO            : exit($30E8);  { U+30E8 KATAKANA LETTER YO }
+    XKc_kana_RA            : exit($30E9);  { U+30E9 KATAKANA LETTER RA }
+    XKc_kana_RI            : exit($30EA);  { U+30EA KATAKANA LETTER RI }
+    XKc_kana_RU            : exit($30EB);  { U+30EB KATAKANA LETTER RU }
+    XKc_kana_RE            : exit($30EC);  { U+30EC KATAKANA LETTER RE }
+    XKc_kana_RO            : exit($30ED);  { U+30ED KATAKANA LETTER RO }
+    XKc_kana_WA            : exit($30EF);  { U+30EF KATAKANA LETTER WA }
+    XKc_kana_N             : exit($30F3);  { U+30F3 KATAKANA LETTER N }
+    XK_voicedsound         : exit($309B);  { U+309B KATAKANA-HIRAGANA VOICED SOUND MARK }
+    XK_semivoicedsound     : exit($309C);  { U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK }
 
-    XKc_Cyrillic_SCHWA       : exit($4D8);
-    XK_Cyrillic_schwa        : exit($4D9);
-    XKc_Cyrillic_I_macron    : exit($4E2);
-    XK_Cyrillic_i_macron     : exit($4E3);
-    XKc_Cyrillic_O_bar       : exit($4E8);
-    XK_Cyrillic_o_bar        : exit($4E9);
-    XKc_Cyrillic_U_macron    : exit($4EE);
-    XK_Cyrillic_u_macron     : exit($4EF);
+    { Arabic }
+    XK_Arabic_comma          : exit($060C);     { U+060C ARABIC COMMA }
+    XK_Arabic_semicolon      : exit($061B);     { U+061B ARABIC SEMICOLON }
+    XK_Arabic_question_mark  : exit($061F);     { U+061F ARABIC QUESTION MARK }
+    XK_Arabic_hamza          : exit($0621);     { U+0621 ARABIC LETTER HAMZA }
+    XK_Arabic_maddaonalef    : exit($0622);     { U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE }
+    XK_Arabic_hamzaonalef    : exit($0623);     { U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE }
+    XK_Arabic_hamzaonwaw     : exit($0624);     { U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE }
+    XK_Arabic_hamzaunderalef : exit($0625);     { U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW }
+    XK_Arabic_hamzaonyeh     : exit($0626);     { U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE }
+    XK_Arabic_alef           : exit($0627);     { U+0627 ARABIC LETTER ALEF }
+    XK_Arabic_beh            : exit($0628);     { U+0628 ARABIC LETTER BEH }
+    XK_Arabic_tehmarbuta     : exit($0629);     { U+0629 ARABIC LETTER TEH MARBUTA }
+    XK_Arabic_teh            : exit($062A);     { U+062A ARABIC LETTER TEH }
+    XK_Arabic_theh           : exit($062B);     { U+062B ARABIC LETTER THEH }
+    XK_Arabic_jeem           : exit($062C);     { U+062C ARABIC LETTER JEEM }
+    XK_Arabic_hah            : exit($062D);     { U+062D ARABIC LETTER HAH }
+    XK_Arabic_khah           : exit($062E);     { U+062E ARABIC LETTER KHAH }
+    XK_Arabic_dal            : exit($062F);     { U+062F ARABIC LETTER DAL }
+    XK_Arabic_thal           : exit($0630);     { U+0630 ARABIC LETTER THAL }
+    XK_Arabic_ra             : exit($0631);     { U+0631 ARABIC LETTER REH }
+    XK_Arabic_zain           : exit($0632);     { U+0632 ARABIC LETTER ZAIN }
+    XK_Arabic_seen           : exit($0633);     { U+0633 ARABIC LETTER SEEN }
+    XK_Arabic_sheen          : exit($0634);     { U+0634 ARABIC LETTER SHEEN }
+    XK_Arabic_sad            : exit($0635);     { U+0635 ARABIC LETTER SAD }
+    XK_Arabic_dad            : exit($0636);     { U+0636 ARABIC LETTER DAD }
+    XK_Arabic_tah            : exit($0637);     { U+0637 ARABIC LETTER TAH }
+    XK_Arabic_zah            : exit($0638);     { U+0638 ARABIC LETTER ZAH }
+    XK_Arabic_ain            : exit($0639);     { U+0639 ARABIC LETTER AIN }
+    XK_Arabic_ghain          : exit($063A);     { U+063A ARABIC LETTER GHAIN }
+    XK_Arabic_tatweel        : exit($0640);     { U+0640 ARABIC TATWEEL }
+    XK_Arabic_feh            : exit($0641);     { U+0641 ARABIC LETTER FEH }
+    XK_Arabic_qaf            : exit($0642);     { U+0642 ARABIC LETTER QAF }
+    XK_Arabic_kaf            : exit($0643);     { U+0643 ARABIC LETTER KAF }
+    XK_Arabic_lam            : exit($0644);     { U+0644 ARABIC LETTER LAM }
+    XK_Arabic_meem           : exit($0645);     { U+0645 ARABIC LETTER MEEM }
+    XK_Arabic_noon           : exit($0646);     { U+0646 ARABIC LETTER NOON }
+    XK_Arabic_ha             : exit($0647);     { U+0647 ARABIC LETTER HEH }
+    XK_Arabic_waw            : exit($0648);     { U+0648 ARABIC LETTER WAW }
+    XK_Arabic_alefmaksura    : exit($0649);     { U+0649 ARABIC LETTER ALEF MAKSURA }
+    XK_Arabic_yeh            : exit($064A);     { U+064A ARABIC LETTER YEH }
+    XK_Arabic_fathatan       : exit($064B);     { U+064B ARABIC FATHATAN }
+    XK_Arabic_dammatan       : exit($064C);     { U+064C ARABIC DAMMATAN }
+    XK_Arabic_kasratan       : exit($064D);     { U+064D ARABIC KASRATAN }
+    XK_Arabic_fatha          : exit($064E);     { U+064E ARABIC FATHA }
+    XK_Arabic_damma          : exit($064F);     { U+064F ARABIC DAMMA }
+    XK_Arabic_kasra          : exit($0650);     { U+0650 ARABIC KASRA }
+    XK_Arabic_shadda         : exit($0651);     { U+0651 ARABIC SHADDA }
+    XK_Arabic_sukun          : exit($0652);     { U+0652 ARABIC SUKUN }
 
-    XK_Serbian_dje           : exit($452);
-    XK_Macedonia_gje         : exit($453);
-    XK_Cyrillic_io           : exit($451);
-    XK_Ukrainian_ie          : exit($454);
-    XK_Macedonia_dse         : exit($455);
-    XK_Ukrainian_i           : exit($456);
-    XK_Ukrainian_yi          : exit($457);
-    XK_Cyrillic_je           : exit($458);
-    XK_Cyrillic_lje          : exit($459);
-    XK_Cyrillic_nje          : exit($45A);
-    XK_Serbian_tshe          : exit($45B);
-    XK_Macedonia_kje         : exit($45C);
-    XK_Ukrainian_ghe_with_upturn: exit($491);
-    XK_Byelorussian_shortu   : exit($45E);
-    XK_Cyrillic_dzhe         : exit($45F);
-    XK_numerosign            : exit($2116);
-    XKc_Serbian_DJE          : exit($402);
-    XKc_Macedonia_GJE        : exit($403);
-    XKc_Cyrillic_IO          : exit($401);
-    XKc_Ukrainian_IE         : exit($404);
-    XKc_Macedonia_DSE        : exit($405);
-    XKc_Ukrainian_I          : exit($406);
-    XKc_Ukrainian_YI         : exit($407);
-    XKc_Cyrillic_JE          : exit($408);
-    XKc_Cyrillic_LJE         : exit($409);
-    XKc_Cyrillic_NJE         : exit($40A);
-    XKc_Serbian_TSHE         : exit($40B);
-    XKc_Macedonia_KJE        : exit($40C);
-    XKc_Ukrainian_GHE_WITH_UPTURN: exit($490);
-    XKc_Byelorussian_SHORTU  : exit($40E);
-    XKc_Cyrillic_DZHE        : exit($40F);
-    XK_Cyrillic_yu           : exit($44E);
-    XK_Cyrillic_a            : exit($430);
-    XK_Cyrillic_be           : exit($431);
-    XK_Cyrillic_tse          : exit($446);
-    XK_Cyrillic_de           : exit($434);
-    XK_Cyrillic_ie           : exit($435);
-    XK_Cyrillic_ef           : exit($444);
-    XK_Cyrillic_ghe          : exit($433);
-    XK_Cyrillic_ha           : exit($445);
-    XK_Cyrillic_i            : exit($438);
-    XK_Cyrillic_shorti       : exit($439);
-    XK_Cyrillic_ka           : exit($43A);
-    XK_Cyrillic_el           : exit($43B);
-    XK_Cyrillic_em           : exit($43C);
-    XK_Cyrillic_en           : exit($43D);
-    XK_Cyrillic_o            : exit($43E);
-    XK_Cyrillic_pe           : exit($43F);
-    XK_Cyrillic_ya           : exit($44F);
-    XK_Cyrillic_er           : exit($440);
-    XK_Cyrillic_es           : exit($441);
-    XK_Cyrillic_te           : exit($442);
-    XK_Cyrillic_u            : exit($443);
-    XK_Cyrillic_zhe          : exit($436);
-    XK_Cyrillic_ve           : exit($432);
-    XK_Cyrillic_softsign     : exit($44C);
-    XK_Cyrillic_yeru         : exit($44B);
-    XK_Cyrillic_ze           : exit($437);
-    XK_Cyrillic_sha          : exit($448);
-    XK_Cyrillic_e            : exit($44D);
-    XK_Cyrillic_shcha        : exit($449);
-    XK_Cyrillic_che          : exit($447);
-    XK_Cyrillic_hardsign     : exit($44A);
-    XKc_Cyrillic_YU          : exit($42E);
-    XKc_Cyrillic_A           : exit($410);
-    XKc_Cyrillic_BE          : exit($411);
-    XKc_Cyrillic_TSE         : exit($426);
-    XKc_Cyrillic_DE          : exit($414);
-    XKc_Cyrillic_IE          : exit($415);
-    XKc_Cyrillic_EF          : exit($424);
-    XKc_Cyrillic_GHE         : exit($413);
-    XKc_Cyrillic_HA          : exit($425);
-    XKc_Cyrillic_I           : exit($418);
-    XKc_Cyrillic_SHORTI      : exit($419);
-    XKc_Cyrillic_KA          : exit($41A);
-    XKc_Cyrillic_EL          : exit($41B);
-    XKc_Cyrillic_EM          : exit($41C);
-    XKc_Cyrillic_EN          : exit($41D);
-    XKc_Cyrillic_O           : exit($41E);
-    XKc_Cyrillic_PE          : exit($41F);
-    XKc_Cyrillic_YA          : exit($42F);
-    XKc_Cyrillic_ER          : exit($420);
-    XKc_Cyrillic_ES          : exit($421);
-    XKc_Cyrillic_TE          : exit($422);
-    XKc_Cyrillic_U           : exit($423);
-    XKc_Cyrillic_ZHE         : exit($416);
-    XKc_Cyrillic_VE          : exit($412);
-    XKc_Cyrillic_SOFTSIGN    : exit($42C);
-    XKc_Cyrillic_YERU        : exit($42B);
-    XKc_Cyrillic_ZE          : exit($417);
-    XKc_Cyrillic_SHA         : exit($428);
-    XKc_Cyrillic_E           : exit($42D);
-    XKc_Cyrillic_SHCHA       : exit($429);
-    XKc_Cyrillic_CHE         : exit($427);
-    XKc_Cyrillic_HARDSIGN    : exit($42A);
+    { Cyrillic }
+    XK_Serbian_dje                : exit($0452);  { U+0452 CYRILLIC SMALL LETTER DJE }
+    XK_Macedonia_gje              : exit($0453);  { U+0453 CYRILLIC SMALL LETTER GJE }
+    XK_Cyrillic_io                : exit($0451);  { U+0451 CYRILLIC SMALL LETTER IO }
+    XK_Ukrainian_ie               : exit($0454);  { U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE }
+    XK_Macedonia_dse              : exit($0455);  { U+0455 CYRILLIC SMALL LETTER DZE }
+    XK_Ukrainian_i                : exit($0456);  { U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I }
+    XK_Ukrainian_yi               : exit($0457);  { U+0457 CYRILLIC SMALL LETTER YI }
+    XK_Cyrillic_je                : exit($0458);  { U+0458 CYRILLIC SMALL LETTER JE }
+    XK_Cyrillic_lje               : exit($0459);  { U+0459 CYRILLIC SMALL LETTER LJE }
+    XK_Cyrillic_nje               : exit($045A);  { U+045A CYRILLIC SMALL LETTER NJE }
+    XK_Serbian_tshe               : exit($045B);  { U+045B CYRILLIC SMALL LETTER TSHE }
+    XK_Macedonia_kje              : exit($045C);  { U+045C CYRILLIC SMALL LETTER KJE }
+    XK_Ukrainian_ghe_with_upturn  : exit($0491);  { U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN }
+    XK_Byelorussian_shortu        : exit($045E);  { U+045E CYRILLIC SMALL LETTER SHORT U }
+    XK_Cyrillic_dzhe              : exit($045F);  { U+045F CYRILLIC SMALL LETTER DZHE }
+    XK_numerosign                 : exit($2116);  { U+2116 NUMERO SIGN }
+    XKc_Serbian_DJE               : exit($0402);  { U+0402 CYRILLIC CAPITAL LETTER DJE }
+    XKc_Macedonia_GJE             : exit($0403);  { U+0403 CYRILLIC CAPITAL LETTER GJE }
+    XKc_Cyrillic_IO               : exit($0401);  { U+0401 CYRILLIC CAPITAL LETTER IO }
+    XKc_Ukrainian_IE              : exit($0404);  { U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE }
+    XKc_Macedonia_DSE             : exit($0405);  { U+0405 CYRILLIC CAPITAL LETTER DZE }
+    XKc_Ukrainian_I               : exit($0406);  { U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I }
+    XKc_Ukrainian_YI              : exit($0407);  { U+0407 CYRILLIC CAPITAL LETTER YI }
+    XKc_Cyrillic_JE               : exit($0408);  { U+0408 CYRILLIC CAPITAL LETTER JE }
+    XKc_Cyrillic_LJE              : exit($0409);  { U+0409 CYRILLIC CAPITAL LETTER LJE }
+    XKc_Cyrillic_NJE              : exit($040A);  { U+040A CYRILLIC CAPITAL LETTER NJE }
+    XKc_Serbian_TSHE              : exit($040B);  { U+040B CYRILLIC CAPITAL LETTER TSHE }
+    XKc_Macedonia_KJE             : exit($040C);  { U+040C CYRILLIC CAPITAL LETTER KJE }
+    XKc_Ukrainian_GHE_WITH_UPTURN : exit($0490);  { U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN }
+    XKc_Byelorussian_SHORTU       : exit($040E);  { U+040E CYRILLIC CAPITAL LETTER SHORT U }
+    XKc_Cyrillic_DZHE             : exit($040F);  { U+040F CYRILLIC CAPITAL LETTER DZHE }
+    XK_Cyrillic_yu                : exit($044E);  { U+044E CYRILLIC SMALL LETTER YU }
+    XK_Cyrillic_a                 : exit($0430);  { U+0430 CYRILLIC SMALL LETTER A }
+    XK_Cyrillic_be                : exit($0431);  { U+0431 CYRILLIC SMALL LETTER BE }
+    XK_Cyrillic_tse               : exit($0446);  { U+0446 CYRILLIC SMALL LETTER TSE }
+    XK_Cyrillic_de                : exit($0434);  { U+0434 CYRILLIC SMALL LETTER DE }
+    XK_Cyrillic_ie                : exit($0435);  { U+0435 CYRILLIC SMALL LETTER IE }
+    XK_Cyrillic_ef                : exit($0444);  { U+0444 CYRILLIC SMALL LETTER EF }
+    XK_Cyrillic_ghe               : exit($0433);  { U+0433 CYRILLIC SMALL LETTER GHE }
+    XK_Cyrillic_ha                : exit($0445);  { U+0445 CYRILLIC SMALL LETTER HA }
+    XK_Cyrillic_i                 : exit($0438);  { U+0438 CYRILLIC SMALL LETTER I }
+    XK_Cyrillic_shorti            : exit($0439);  { U+0439 CYRILLIC SMALL LETTER SHORT I }
+    XK_Cyrillic_ka                : exit($043A);  { U+043A CYRILLIC SMALL LETTER KA }
+    XK_Cyrillic_el                : exit($043B);  { U+043B CYRILLIC SMALL LETTER EL }
+    XK_Cyrillic_em                : exit($043C);  { U+043C CYRILLIC SMALL LETTER EM }
+    XK_Cyrillic_en                : exit($043D);  { U+043D CYRILLIC SMALL LETTER EN }
+    XK_Cyrillic_o                 : exit($043E);  { U+043E CYRILLIC SMALL LETTER O }
+    XK_Cyrillic_pe                : exit($043F);  { U+043F CYRILLIC SMALL LETTER PE }
+    XK_Cyrillic_ya                : exit($044F);  { U+044F CYRILLIC SMALL LETTER YA }
+    XK_Cyrillic_er                : exit($0440);  { U+0440 CYRILLIC SMALL LETTER ER }
+    XK_Cyrillic_es                : exit($0441);  { U+0441 CYRILLIC SMALL LETTER ES }
+    XK_Cyrillic_te                : exit($0442);  { U+0442 CYRILLIC SMALL LETTER TE }
+    XK_Cyrillic_u                 : exit($0443);  { U+0443 CYRILLIC SMALL LETTER U }
+    XK_Cyrillic_zhe               : exit($0436);  { U+0436 CYRILLIC SMALL LETTER ZHE }
+    XK_Cyrillic_ve                : exit($0432);  { U+0432 CYRILLIC SMALL LETTER VE }
+    XK_Cyrillic_softsign          : exit($044C);  { U+044C CYRILLIC SMALL LETTER SOFT SIGN }
+    XK_Cyrillic_yeru              : exit($044B);  { U+044B CYRILLIC SMALL LETTER YERU }
+    XK_Cyrillic_ze                : exit($0437);  { U+0437 CYRILLIC SMALL LETTER ZE }
+    XK_Cyrillic_sha               : exit($0448);  { U+0448 CYRILLIC SMALL LETTER SHA }
+    XK_Cyrillic_e                 : exit($044D);  { U+044D CYRILLIC SMALL LETTER E }
+    XK_Cyrillic_shcha             : exit($0449);  { U+0449 CYRILLIC SMALL LETTER SHCHA }
+    XK_Cyrillic_che               : exit($0447);  { U+0447 CYRILLIC SMALL LETTER CHE }
+    XK_Cyrillic_hardsign          : exit($044A);  { U+044A CYRILLIC SMALL LETTER HARD SIGN }
+    XKc_Cyrillic_YU               : exit($042E);  { U+042E CYRILLIC CAPITAL LETTER YU }
+    XKc_Cyrillic_A                : exit($0410);  { U+0410 CYRILLIC CAPITAL LETTER A }
+    XKc_Cyrillic_BE               : exit($0411);  { U+0411 CYRILLIC CAPITAL LETTER BE }
+    XKc_Cyrillic_TSE              : exit($0426);  { U+0426 CYRILLIC CAPITAL LETTER TSE }
+    XKc_Cyrillic_DE               : exit($0414);  { U+0414 CYRILLIC CAPITAL LETTER DE }
+    XKc_Cyrillic_IE               : exit($0415);  { U+0415 CYRILLIC CAPITAL LETTER IE }
+    XKc_Cyrillic_EF               : exit($0424);  { U+0424 CYRILLIC CAPITAL LETTER EF }
+    XKc_Cyrillic_GHE              : exit($0413);  { U+0413 CYRILLIC CAPITAL LETTER GHE }
+    XKc_Cyrillic_HA               : exit($0425);  { U+0425 CYRILLIC CAPITAL LETTER HA }
+    XKc_Cyrillic_I                : exit($0418);  { U+0418 CYRILLIC CAPITAL LETTER I }
+    XKc_Cyrillic_SHORTI           : exit($0419);  { U+0419 CYRILLIC CAPITAL LETTER SHORT I }
+    XKc_Cyrillic_KA               : exit($041A);  { U+041A CYRILLIC CAPITAL LETTER KA }
+    XKc_Cyrillic_EL               : exit($041B);  { U+041B CYRILLIC CAPITAL LETTER EL }
+    XKc_Cyrillic_EM               : exit($041C);  { U+041C CYRILLIC CAPITAL LETTER EM }
+    XKc_Cyrillic_EN               : exit($041D);  { U+041D CYRILLIC CAPITAL LETTER EN }
+    XKc_Cyrillic_O                : exit($041E);  { U+041E CYRILLIC CAPITAL LETTER O }
+    XKc_Cyrillic_PE               : exit($041F);  { U+041F CYRILLIC CAPITAL LETTER PE }
+    XKc_Cyrillic_YA               : exit($042F);  { U+042F CYRILLIC CAPITAL LETTER YA }
+    XKc_Cyrillic_ER               : exit($0420);  { U+0420 CYRILLIC CAPITAL LETTER ER }
+    XKc_Cyrillic_ES               : exit($0421);  { U+0421 CYRILLIC CAPITAL LETTER ES }
+    XKc_Cyrillic_TE               : exit($0422);  { U+0422 CYRILLIC CAPITAL LETTER TE }
+    XKc_Cyrillic_U                : exit($0423);  { U+0423 CYRILLIC CAPITAL LETTER U }
+    XKc_Cyrillic_ZHE              : exit($0416);  { U+0416 CYRILLIC CAPITAL LETTER ZHE }
+    XKc_Cyrillic_VE               : exit($0412);  { U+0412 CYRILLIC CAPITAL LETTER VE }
+    XKc_Cyrillic_SOFTSIGN         : exit($042C);  { U+042C CYRILLIC CAPITAL LETTER SOFT SIGN }
+    XKc_Cyrillic_YERU             : exit($042B);  { U+042B CYRILLIC CAPITAL LETTER YERU }
+    XKc_Cyrillic_ZE               : exit($0417);  { U+0417 CYRILLIC CAPITAL LETTER ZE }
+    XKc_Cyrillic_SHA              : exit($0428);  { U+0428 CYRILLIC CAPITAL LETTER SHA }
+    XKc_Cyrillic_E                : exit($042D);  { U+042D CYRILLIC CAPITAL LETTER E }
+    XKc_Cyrillic_SHCHA            : exit($0429);  { U+0429 CYRILLIC CAPITAL LETTER SHCHA }
+    XKc_Cyrillic_CHE              : exit($0427);  { U+0427 CYRILLIC CAPITAL LETTER CHE }
+    XKc_Cyrillic_HARDSIGN         : exit($042A);  { U+042A CYRILLIC CAPITAL LETTER HARD SIGN }
 
-{    XKc_Greek_ALPHAaccent    : exit($);
-    XKc_Greek_EPSILONaccent  : exit($);
-    XKc_Greek_ETAaccent      : exit($);
-    XKc_Greek_IOTAaccent     : exit($);
-    XKc_Greek_IOTAdieresis   : exit($);
-    XKc_Greek_OMICRONaccent  : exit($);
-    XKc_Greek_UPSILONaccent  : exit($);
-    XKc_Greek_UPSILONdieresis: exit($);
-    XKc_Greek_OMEGAaccent    : exit($);
-    XK_Greek_accentdieresis  : exit($);
-    XK_Greek_horizbar        : exit($);
-    XK_Greek_alphaaccent     : exit($);
-    XK_Greek_epsilonaccent   : exit($);
-    XK_Greek_etaaccent       : exit($);
-    XK_Greek_iotaaccent      : exit($);
-    XK_Greek_iotadieresis    : exit($);
-    XK_Greek_iotaaccentdieresis: exit($);
-    XK_Greek_omicronaccent   : exit($);
-    XK_Greek_upsilonaccent   : exit($);
-    XK_Greek_upsilondieresis : exit($);
-    XK_Greek_upsilonaccentdieresis: exit($);
-    XK_Greek_omegaaccent     : exit($);}
-    XKc_Greek_ALPHA          : exit($391);
-    XKc_Greek_BETA           : exit($392);
-    XKc_Greek_GAMMA          : exit($393);
-    XKc_Greek_DELTA          : exit($394);
-    XKc_Greek_EPSILON        : exit($395);
-    XKc_Greek_ZETA           : exit($396);
-    XKc_Greek_ETA            : exit($397);
-    XKc_Greek_THETA          : exit($398);
-    XKc_Greek_IOTA           : exit($399);
-    XKc_Greek_KAPPA          : exit($39A);
-    XKc_Greek_LAMDA          : exit($39B);
-    XKc_Greek_MU             : exit($39C);
-    XKc_Greek_NU             : exit($39D);
-    XKc_Greek_XI             : exit($39E);
-    XKc_Greek_OMICRON        : exit($39F);
-    XKc_Greek_PI             : exit($3A0);
-    XKc_Greek_RHO            : exit($3A1);
-    XKc_Greek_SIGMA          : exit($3A3);
-    XKc_Greek_TAU            : exit($3A4);
-    XKc_Greek_UPSILON        : exit($3A5);
-    XKc_Greek_PHI            : exit($3A6);
-    XKc_Greek_CHI            : exit($3A7);
-    XKc_Greek_PSI            : exit($3A8);
-    XKc_Greek_OMEGA          : exit($3A9);
-    XK_Greek_alpha           : exit($3B1);
-    XK_Greek_beta            : exit($3B2);
-    XK_Greek_gamma           : exit($3B3);
-    XK_Greek_delta           : exit($3B4);
-    XK_Greek_epsilon         : exit($3B5);
-    XK_Greek_zeta            : exit($3B6);
-    XK_Greek_eta             : exit($3B7);
-    XK_Greek_theta           : exit($3B8);
-    XK_Greek_iota            : exit($3B9);
-    XK_Greek_kappa           : exit($3BA);
-    XK_Greek_lamda           : exit($3BB);
-    XK_Greek_mu              : exit($3BC);
-    XK_Greek_nu              : exit($3BD);
-    XK_Greek_xi              : exit($3BE);
-    XK_Greek_omicron         : exit($3BF);
-    XK_Greek_pi              : exit($3C0);
-    XK_Greek_rho             : exit($3C1);
-    XK_Greek_sigma           : exit($3C2);
-    XK_Greek_finalsmallsigma : exit($3C3);
-    XK_Greek_tau             : exit($3C4);
-    XK_Greek_upsilon         : exit($3C5);
-    XK_Greek_phi             : exit($3C6);
-    XK_Greek_chi             : exit($3C7);
-    XK_Greek_psi             : exit($3C8);
-    XK_Greek_omega           : exit($3C9);
+    { Greek }
+    XKc_Greek_ALPHAaccent          : exit($0386);  { U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS }
+    XKc_Greek_EPSILONaccent        : exit($0388);  { U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS }
+    XKc_Greek_ETAaccent            : exit($0389);  { U+0389 GREEK CAPITAL LETTER ETA WITH TONOS }
+    XKc_Greek_IOTAaccent           : exit($038A);  { U+038A GREEK CAPITAL LETTER IOTA WITH TONOS }
+    XKc_Greek_IOTAdieresis         : exit($03AA);  { U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA }
+    XKc_Greek_OMICRONaccent        : exit($038C);  { U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS }
+    XKc_Greek_UPSILONaccent        : exit($038E);  { U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS }
+    XKc_Greek_UPSILONdieresis      : exit($03AB);  { U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA }
+    XKc_Greek_OMEGAaccent          : exit($038F);  { U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS }
+    XK_Greek_accentdieresis        : exit($0385);  { U+0385 GREEK DIALYTIKA TONOS }
+    XK_Greek_horizbar              : exit($2015);  { U+2015 HORIZONTAL BAR }
+    XK_Greek_alphaaccent           : exit($03AC);  { U+03AC GREEK SMALL LETTER ALPHA WITH TONOS }
+    XK_Greek_epsilonaccent         : exit($03AD);  { U+03AD GREEK SMALL LETTER EPSILON WITH TONOS }
+    XK_Greek_etaaccent             : exit($03AE);  { U+03AE GREEK SMALL LETTER ETA WITH TONOS }
+    XK_Greek_iotaaccent            : exit($03AF);  { U+03AF GREEK SMALL LETTER IOTA WITH TONOS }
+    XK_Greek_iotadieresis          : exit($03CA);  { U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA }
+    XK_Greek_iotaaccentdieresis    : exit($0390);  { U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS }
+    XK_Greek_omicronaccent         : exit($03CC);  { U+03CC GREEK SMALL LETTER OMICRON WITH TONOS }
+    XK_Greek_upsilonaccent         : exit($03CD);  { U+03CD GREEK SMALL LETTER UPSILON WITH TONOS }
+    XK_Greek_upsilondieresis       : exit($03CB);  { U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA }
+    XK_Greek_upsilonaccentdieresis : exit($03B0);  { U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS }
+    XK_Greek_omegaaccent           : exit($03CE);  { U+03CE GREEK SMALL LETTER OMEGA WITH TONOS }
+    XKc_Greek_ALPHA                : exit($0391);  { U+0391 GREEK CAPITAL LETTER ALPHA }
+    XKc_Greek_BETA                 : exit($0392);  { U+0392 GREEK CAPITAL LETTER BETA }
+    XKc_Greek_GAMMA                : exit($0393);  { U+0393 GREEK CAPITAL LETTER GAMMA }
+    XKc_Greek_DELTA                : exit($0394);  { U+0394 GREEK CAPITAL LETTER DELTA }
+    XKc_Greek_EPSILON              : exit($0395);  { U+0395 GREEK CAPITAL LETTER EPSILON }
+    XKc_Greek_ZETA                 : exit($0396);  { U+0396 GREEK CAPITAL LETTER ZETA }
+    XKc_Greek_ETA                  : exit($0397);  { U+0397 GREEK CAPITAL LETTER ETA }
+    XKc_Greek_THETA                : exit($0398);  { U+0398 GREEK CAPITAL LETTER THETA }
+    XKc_Greek_IOTA                 : exit($0399);  { U+0399 GREEK CAPITAL LETTER IOTA }
+    XKc_Greek_KAPPA                : exit($039A);  { U+039A GREEK CAPITAL LETTER KAPPA }
+    XKc_Greek_LAMDA                : exit($039B);  { U+039B GREEK CAPITAL LETTER LAMDA }
+    XKc_Greek_MU                   : exit($039C);  { U+039C GREEK CAPITAL LETTER MU }
+    XKc_Greek_NU                   : exit($039D);  { U+039D GREEK CAPITAL LETTER NU }
+    XKc_Greek_XI                   : exit($039E);  { U+039E GREEK CAPITAL LETTER XI }
+    XKc_Greek_OMICRON              : exit($039F);  { U+039F GREEK CAPITAL LETTER OMICRON }
+    XKc_Greek_PI                   : exit($03A0);  { U+03A0 GREEK CAPITAL LETTER PI }
+    XKc_Greek_RHO                  : exit($03A1);  { U+03A1 GREEK CAPITAL LETTER RHO }
+    XKc_Greek_SIGMA                : exit($03A3);  { U+03A3 GREEK CAPITAL LETTER SIGMA }
+    XKc_Greek_TAU                  : exit($03A4);  { U+03A4 GREEK CAPITAL LETTER TAU }
+    XKc_Greek_UPSILON              : exit($03A5);  { U+03A5 GREEK CAPITAL LETTER UPSILON }
+    XKc_Greek_PHI                  : exit($03A6);  { U+03A6 GREEK CAPITAL LETTER PHI }
+    XKc_Greek_CHI                  : exit($03A7);  { U+03A7 GREEK CAPITAL LETTER CHI }
+    XKc_Greek_PSI                  : exit($03A8);  { U+03A8 GREEK CAPITAL LETTER PSI }
+    XKc_Greek_OMEGA                : exit($03A9);  { U+03A9 GREEK CAPITAL LETTER OMEGA }
+    XK_Greek_alpha                 : exit($03B1);  { U+03B1 GREEK SMALL LETTER ALPHA }
+    XK_Greek_beta                  : exit($03B2);  { U+03B2 GREEK SMALL LETTER BETA }
+    XK_Greek_gamma                 : exit($03B3);  { U+03B3 GREEK SMALL LETTER GAMMA }
+    XK_Greek_delta                 : exit($03B4);  { U+03B4 GREEK SMALL LETTER DELTA }
+    XK_Greek_epsilon               : exit($03B5);  { U+03B5 GREEK SMALL LETTER EPSILON }
+    XK_Greek_zeta                  : exit($03B6);  { U+03B6 GREEK SMALL LETTER ZETA }
+    XK_Greek_eta                   : exit($03B7);  { U+03B7 GREEK SMALL LETTER ETA }
+    XK_Greek_theta                 : exit($03B8);  { U+03B8 GREEK SMALL LETTER THETA }
+    XK_Greek_iota                  : exit($03B9);  { U+03B9 GREEK SMALL LETTER IOTA }
+    XK_Greek_kappa                 : exit($03BA);  { U+03BA GREEK SMALL LETTER KAPPA }
+    XK_Greek_lamda                 : exit($03BB);  { U+03BB GREEK SMALL LETTER LAMDA }
+    XK_Greek_mu                    : exit($03BC);  { U+03BC GREEK SMALL LETTER MU }
+    XK_Greek_nu                    : exit($03BD);  { U+03BD GREEK SMALL LETTER NU }
+    XK_Greek_xi                    : exit($03BE);  { U+03BE GREEK SMALL LETTER XI }
+    XK_Greek_omicron               : exit($03BF);  { U+03BF GREEK SMALL LETTER OMICRON }
+    XK_Greek_pi                    : exit($03C0);  { U+03C0 GREEK SMALL LETTER PI }
+    XK_Greek_rho                   : exit($03C1);  { U+03C1 GREEK SMALL LETTER RHO }
+    XK_Greek_sigma                 : exit($03C2);  { U+03C3 GREEK SMALL LETTER SIGMA }
+    XK_Greek_finalsmallsigma       : exit($03C3);  { U+03C2 GREEK SMALL LETTER FINAL SIGMA }
+    XK_Greek_tau                   : exit($03C4);  { U+03C4 GREEK SMALL LETTER TAU }
+    XK_Greek_upsilon               : exit($03C5);  { U+03C5 GREEK SMALL LETTER UPSILON }
+    XK_Greek_phi                   : exit($03C6);  { U+03C6 GREEK SMALL LETTER PHI }
+    XK_Greek_chi                   : exit($03C7);  { U+03C7 GREEK SMALL LETTER CHI }
+    XK_Greek_psi                   : exit($03C8);  { U+03C8 GREEK SMALL LETTER PSI }
+    XK_Greek_omega                 : exit($03C9);  { U+03C9 GREEK SMALL LETTER OMEGA }
+
+    { Technical }
+    XK_leftradical               : exit($23B7);  { U+23B7 RADICAL SYMBOL BOTTOM }
+    XK_topleftradical            : exit($250C);  {(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)}
+    XK_horizconnector            : exit($2500);  {(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)}
+    XK_topintegral               : exit($2320);  { U+2320 TOP HALF INTEGRAL }
+    XK_botintegral               : exit($2321);  { U+2321 BOTTOM HALF INTEGRAL }
+    XK_vertconnector             : exit($2502);  {(U+2502 BOX DRAWINGS LIGHT VERTICAL)}
+    XK_topleftsqbracket          : exit($23A1);  { U+23A1 LEFT SQUARE BRACKET UPPER CORNER }
+    XK_botleftsqbracket          : exit($23A3);  { U+23A3 LEFT SQUARE BRACKET LOWER CORNER }
+    XK_toprightsqbracket         : exit($23A4);  { U+23A4 RIGHT SQUARE BRACKET UPPER CORNER }
+    XK_botrightsqbracket         : exit($23A6);  { U+23A6 RIGHT SQUARE BRACKET LOWER CORNER }
+    XK_topleftparens             : exit($239B);  { U+239B LEFT PARENTHESIS UPPER HOOK }
+    XK_botleftparens             : exit($239D);  { U+239D LEFT PARENTHESIS LOWER HOOK }
+    XK_toprightparens            : exit($239E);  { U+239E RIGHT PARENTHESIS UPPER HOOK }
+    XK_botrightparens            : exit($23A0);  { U+23A0 RIGHT PARENTHESIS LOWER HOOK }
+    XK_leftmiddlecurlybrace      : exit($23A8);  { U+23A8 LEFT CURLY BRACKET MIDDLE PIECE }
+    XK_rightmiddlecurlybrace     : exit($23AC);  { U+23AC RIGHT CURLY BRACKET MIDDLE PIECE }
+{    XK_topleftsummation          : exit($);
+    XK_botleftsummation          : exit($);
+    XK_topvertsummationconnector : exit($);
+    XK_botvertsummationconnector : exit($);
+    XK_toprightsummation         : exit($);
+    XK_botrightsummation         : exit($);
+    XK_rightmiddlesummation      : exit($);}
+    XK_lessthanequal             : exit($2264);  { U+2264 LESS-THAN OR EQUAL TO }
+    XK_notequal                  : exit($2260);  { U+2260 NOT EQUAL TO }
+    XK_greaterthanequal          : exit($2265);  { U+2265 GREATER-THAN OR EQUAL TO }
+    XK_integral                  : exit($222B);  { U+222B INTEGRAL }
+    XK_therefore                 : exit($2234);  { U+2234 THEREFORE }
+    XK_variation                 : exit($221D);  { U+221D PROPORTIONAL TO }
+    XK_infinity                  : exit($221E);  { U+221E INFINITY }
+    XK_nabla                     : exit($2207);  { U+2207 NABLA }
+    XK_approximate               : exit($223C);  { U+223C TILDE OPERATOR }
+    XK_similarequal              : exit($2243);  { U+2243 ASYMPTOTICALLY EQUAL TO }
+    XK_ifonlyif                  : exit($21D4);  { U+21D4 LEFT RIGHT DOUBLE ARROW }
+    XK_implies                   : exit($21D2);  { U+21D2 RIGHTWARDS DOUBLE ARROW }
+    XK_identical                 : exit($2261);  { U+2261 IDENTICAL TO }
+    XK_radical                   : exit($221A);  { U+221A SQUARE ROOT }
+    XK_includedin                : exit($2282);  { U+2282 SUBSET OF }
+    XK_includes                  : exit($2283);  { U+2283 SUPERSET OF }
+    XK_intersection              : exit($2229);  { U+2229 INTERSECTION }
+    XK_union                     : exit($222A);  { U+222A UNION }
+    XK_logicaland                : exit($2227);  { U+2227 LOGICAL AND }
+    XK_logicalor                 : exit($2228);  { U+2228 LOGICAL OR }
+    XK_partialderivative         : exit($2202);  { U+2202 PARTIAL DIFFERENTIAL }
+    XK_function                  : exit($0192);  { U+0192 LATIN SMALL LETTER F WITH HOOK }
+    XK_leftarrow                 : exit($2190);  { U+2190 LEFTWARDS ARROW }
+    XK_uparrow                   : exit($2191);  { U+2191 UPWARDS ARROW }
+    XK_rightarrow                : exit($2192);  { U+2192 RIGHTWARDS ARROW }
+    XK_downarrow                 : exit($2193);  { U+2193 DOWNWARDS ARROW }
+
+    { Special }
+{    XK_blank          : exit($);}
+    XK_soliddiamond   : exit($25C6);  { U+25C6 BLACK DIAMOND }
+    XK_checkerboard   : exit($2592);  { U+2592 MEDIUM SHADE }
+    XK_ht             : exit($2409);  { U+2409 SYMBOL FOR HORIZONTAL TABULATION }
+    XK_ff             : exit($240C);  { U+240C SYMBOL FOR FORM FEED }
+    XK_cr             : exit($240D);  { U+240D SYMBOL FOR CARRIAGE RETURN }
+    XK_lf             : exit($240A);  { U+240A SYMBOL FOR LINE FEED }
+    XK_nl             : exit($2424);  { U+2424 SYMBOL FOR NEWLINE }
+    XK_vt             : exit($240B);  { U+240B SYMBOL FOR VERTICAL TABULATION }
+    XK_lowrightcorner : exit($2518);  { U+2518 BOX DRAWINGS LIGHT UP AND LEFT }
+    XK_uprightcorner  : exit($2510);  { U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT }
+    XK_upleftcorner   : exit($250C);  { U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT }
+    XK_lowleftcorner  : exit($2514);  { U+2514 BOX DRAWINGS LIGHT UP AND RIGHT }
+    XK_crossinglines  : exit($253C);  { U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL }
+    XK_horizlinescan1 : exit($23BA);  { U+23BA HORIZONTAL SCAN LINE-1 }
+    XK_horizlinescan3 : exit($23BB);  { U+23BB HORIZONTAL SCAN LINE-3 }
+    XK_horizlinescan5 : exit($2500);  { U+2500 BOX DRAWINGS LIGHT HORIZONTAL }
+    XK_horizlinescan7 : exit($23BC);  { U+23BC HORIZONTAL SCAN LINE-7 }
+    XK_horizlinescan9 : exit($23BD);  { U+23BD HORIZONTAL SCAN LINE-9 }
+    XK_leftt          : exit($251C);  { U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT }
+    XK_rightt         : exit($2524);  { U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT }
+    XK_bott           : exit($2534);  { U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL }
+    XK_topt           : exit($252C);  { U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL }
+    XK_vertbar        : exit($2502);  { U+2502 BOX DRAWINGS LIGHT VERTICAL }
+
+    { Publishing }
+    XK_emspace              : exit($2003);  { U+2003 EM SPACE }
+    XK_enspace              : exit($2002);  { U+2002 EN SPACE }
+    XK_em3space             : exit($2004);  { U+2004 THREE-PER-EM SPACE }
+    XK_em4space             : exit($2005);  { U+2005 FOUR-PER-EM SPACE }
+    XK_digitspace           : exit($2007);  { U+2007 FIGURE SPACE }
+    XK_punctspace           : exit($2008);  { U+2008 PUNCTUATION SPACE }
+    XK_thinspace            : exit($2009);  { U+2009 THIN SPACE }
+    XK_hairspace            : exit($200A);  { U+200A HAIR SPACE }
+    XK_emdash               : exit($2014);  { U+2014 EM DASH }
+    XK_endash               : exit($2013);  { U+2013 EN DASH }
+    XK_signifblank          : exit($2423);  {(U+2423 OPEN BOX)}
+    XK_ellipsis             : exit($2026);  { U+2026 HORIZONTAL ELLIPSIS }
+    XK_doubbaselinedot      : exit($2025);  { U+2025 TWO DOT LEADER }
+    XK_onethird             : exit($2153);  { U+2153 VULGAR FRACTION ONE THIRD }
+    XK_twothirds            : exit($2154);  { U+2154 VULGAR FRACTION TWO THIRDS }
+    XK_onefifth             : exit($2155);  { U+2155 VULGAR FRACTION ONE FIFTH }
+    XK_twofifths            : exit($2156);  { U+2156 VULGAR FRACTION TWO FIFTHS }
+    XK_threefifths          : exit($2157);  { U+2157 VULGAR FRACTION THREE FIFTHS }
+    XK_fourfifths           : exit($2158);  { U+2158 VULGAR FRACTION FOUR FIFTHS }
+    XK_onesixth             : exit($2159);  { U+2159 VULGAR FRACTION ONE SIXTH }
+    XK_fivesixths           : exit($215A);  { U+215A VULGAR FRACTION FIVE SIXTHS }
+    XK_careof               : exit($2105);  { U+2105 CARE OF }
+    XK_figdash              : exit($2012);  { U+2012 FIGURE DASH }
+    XK_leftanglebracket     : exit($27E8);  {(U+27E8 MATHEMATICAL LEFT ANGLE BRACKET)}
+    XK_decimalpoint         : exit($002E);  {(U+002E FULL STOP)}
+    XK_rightanglebracket    : exit($27E9);  {(U+27E9 MATHEMATICAL RIGHT ANGLE BRACKET)}
+{    XK_marker               : exit($);}
+    XK_oneeighth            : exit($215B);  { U+215B VULGAR FRACTION ONE EIGHTH }
+    XK_threeeighths         : exit($215C);  { U+215C VULGAR FRACTION THREE EIGHTHS }
+    XK_fiveeighths          : exit($215D);  { U+215D VULGAR FRACTION FIVE EIGHTHS }
+    XK_seveneighths         : exit($215E);  { U+215E VULGAR FRACTION SEVEN EIGHTHS }
+    XK_trademark            : exit($2122);  { U+2122 TRADE MARK SIGN }
+    XK_signaturemark        : exit($2613);  {(U+2613 SALTIRE)}
+{    XK_trademarkincircle    : exit($);}
+    XK_leftopentriangle     : exit($25C1);  {(U+25C1 WHITE LEFT-POINTING TRIANGLE)}
+    XK_rightopentriangle    : exit($25B7);  {(U+25B7 WHITE RIGHT-POINTING TRIANGLE)}
+    XK_emopencircle         : exit($25CB);  {(U+25CB WHITE CIRCLE)}
+    XK_emopenrectangle      : exit($25AF);  {(U+25AF WHITE VERTICAL RECTANGLE)}
+    XK_leftsinglequotemark  : exit($2018);  { U+2018 LEFT SINGLE QUOTATION MARK }
+    XK_rightsinglequotemark : exit($2019);  { U+2019 RIGHT SINGLE QUOTATION MARK }
+    XK_leftdoublequotemark  : exit($201C);  { U+201C LEFT DOUBLE QUOTATION MARK }
+    XK_rightdoublequotemark : exit($201D);  { U+201D RIGHT DOUBLE QUOTATION MARK }
+    XK_prescription         : exit($211E);  { U+211E PRESCRIPTION TAKE }
+    XK_permille             : exit($2030);  { U+2030 PER MILLE SIGN }
+    XK_minutes              : exit($2032);  { U+2032 PRIME }
+    XK_seconds              : exit($2033);  { U+2033 DOUBLE PRIME }
+    XK_latincross           : exit($271D);  { U+271D LATIN CROSS }
+{    XK_hexagram             : exit($);}
+    XK_filledrectbullet     : exit($25AC);  {(U+25AC BLACK RECTANGLE)}
+    XK_filledlefttribullet  : exit($25C0);  {(U+25C0 BLACK LEFT-POINTING TRIANGLE)}
+    XK_filledrighttribullet : exit($25B6);  {(U+25B6 BLACK RIGHT-POINTING TRIANGLE)}
+    XK_emfilledcircle       : exit($25CF);  {(U+25CF BLACK CIRCLE)}
+    XK_emfilledrect         : exit($25AE);  {(U+25AE BLACK VERTICAL RECTANGLE)}
+    XK_enopencircbullet     : exit($25E6);  {(U+25E6 WHITE BULLET)}
+    XK_enopensquarebullet   : exit($25AB);  {(U+25AB WHITE SMALL SQUARE)}
+    XK_openrectbullet       : exit($25AD);  {(U+25AD WHITE RECTANGLE)}
+    XK_opentribulletup      : exit($25B3);  {(U+25B3 WHITE UP-POINTING TRIANGLE)}
+    XK_opentribulletdown    : exit($25BD);  {(U+25BD WHITE DOWN-POINTING TRIANGLE)}
+    XK_openstar             : exit($2606);  {(U+2606 WHITE STAR)}
+    XK_enfilledcircbullet   : exit($2022);  {(U+2022 BULLET)}
+    XK_enfilledsqbullet     : exit($25AA);  {(U+25AA BLACK SMALL SQUARE)}
+    XK_filledtribulletup    : exit($25B2);  {(U+25B2 BLACK UP-POINTING TRIANGLE)}
+    XK_filledtribulletdown  : exit($25BC);  {(U+25BC BLACK DOWN-POINTING TRIANGLE)}
+    XK_leftpointer          : exit($261C);  {(U+261C WHITE LEFT POINTING INDEX)}
+    XK_rightpointer         : exit($261E);  {(U+261E WHITE RIGHT POINTING INDEX)}
+    XK_club                 : exit($2663);  { U+2663 BLACK CLUB SUIT }
+    XK_diamond              : exit($2666);  { U+2666 BLACK DIAMOND SUIT }
+    XK_heart                : exit($2665);  { U+2665 BLACK HEART SUIT }
+    XK_maltesecross         : exit($2720);  { U+2720 MALTESE CROSS }
+    XK_dagger               : exit($2020);  { U+2020 DAGGER }
+    XK_doubledagger         : exit($2021);  { U+2021 DOUBLE DAGGER }
+    XK_checkmark            : exit($2713);  { U+2713 CHECK MARK }
+    XK_ballotcross          : exit($2717);  { U+2717 BALLOT X }
+    XK_musicalsharp         : exit($266F);  { U+266F MUSIC SHARP SIGN }
+    XK_musicalflat          : exit($266D);  { U+266D MUSIC FLAT SIGN }
+    XK_malesymbol           : exit($2642);  { U+2642 MALE SIGN }
+    XK_femalesymbol         : exit($2640);  { U+2640 FEMALE SIGN }
+    XK_telephone            : exit($260E);  { U+260E BLACK TELEPHONE }
+    XK_telephonerecorder    : exit($2315);  { U+2315 TELEPHONE RECORDER }
+    XK_phonographcopyright  : exit($2117);  { U+2117 SOUND RECORDING COPYRIGHT }
+    XK_caret                : exit($2038);  { U+2038 CARET }
+    XK_singlelowquotemark   : exit($201A);  { U+201A SINGLE LOW-9 QUOTATION MARK }
+    XK_doublelowquotemark   : exit($201E);  { U+201E DOUBLE LOW-9 QUOTATION MARK }
+{    XK_cursor               : exit($);}
+
+    { APL }
+    XK_leftcaret  : exit($003C);  {(U+003C LESS-THAN SIGN)}
+    XK_rightcaret : exit($003E);  {(U+003E GREATER-THAN SIGN)}
+    XK_downcaret  : exit($2228);  {(U+2228 LOGICAL OR)}
+    XK_upcaret    : exit($2227);  {(U+2227 LOGICAL AND)}
+    XK_overbar    : exit($00AF);  {(U+00AF MACRON)}
+    XK_downtack   : exit($22A4);  { U+22A4 DOWN TACK }
+    XK_upshoe     : exit($2229);  {(U+2229 INTERSECTION)}
+    XK_downstile  : exit($230A);  { U+230A LEFT FLOOR }
+    XK_underbar   : exit($005F);  {(U+005F LOW LINE)}
+    XK_jot        : exit($2218);  { U+2218 RING OPERATOR }
+    XK_quad       : exit($2395);  { U+2395 APL FUNCTIONAL SYMBOL QUAD }
+    XK_uptack     : exit($22A5);  { U+22A5 UP TACK }
+    XK_circle     : exit($25CB);  { U+25CB WHITE CIRCLE }
+    XK_upstile    : exit($2308);  { U+2308 LEFT CEILING }
+    XK_downshoe   : exit($222A);  {(U+222A UNION)}
+    XK_rightshoe  : exit($2283);  {(U+2283 SUPERSET OF)}
+    XK_leftshoe   : exit($2282);  {(U+2282 SUBSET OF)}
+    XK_lefttack   : exit($22A3);  { U+22A3 LEFT TACK }
+    XK_righttack  : exit($22A2);  { U+22A2 RIGHT TACK }
+
+    { Hebrew }
+    XK_hebrew_doublelowline : exit($2017);  { U+2017 DOUBLE LOW LINE }
+    XK_hebrew_aleph         : exit($05D0);  { U+05D0 HEBREW LETTER ALEF }
+    XK_hebrew_bet           : exit($05D1);  { U+05D1 HEBREW LETTER BET }
+    XK_hebrew_gimel         : exit($05D2);  { U+05D2 HEBREW LETTER GIMEL }
+    XK_hebrew_dalet         : exit($05D3);  { U+05D3 HEBREW LETTER DALET }
+    XK_hebrew_he            : exit($05D4);  { U+05D4 HEBREW LETTER HE }
+    XK_hebrew_waw           : exit($05D5);  { U+05D5 HEBREW LETTER VAV }
+    XK_hebrew_zain          : exit($05D6);  { U+05D6 HEBREW LETTER ZAYIN }
+    XK_hebrew_chet          : exit($05D7);  { U+05D7 HEBREW LETTER HET }
+    XK_hebrew_tet           : exit($05D8);  { U+05D8 HEBREW LETTER TET }
+    XK_hebrew_yod           : exit($05D9);  { U+05D9 HEBREW LETTER YOD }
+    XK_hebrew_finalkaph     : exit($05DA);  { U+05DA HEBREW LETTER FINAL KAF }
+    XK_hebrew_kaph          : exit($05DB);  { U+05DB HEBREW LETTER KAF }
+    XK_hebrew_lamed         : exit($05DC);  { U+05DC HEBREW LETTER LAMED }
+    XK_hebrew_finalmem      : exit($05DD);  { U+05DD HEBREW LETTER FINAL MEM }
+    XK_hebrew_mem           : exit($05DE);  { U+05DE HEBREW LETTER MEM }
+    XK_hebrew_finalnun      : exit($05DF);  { U+05DF HEBREW LETTER FINAL NUN }
+    XK_hebrew_nun           : exit($05E0);  { U+05E0 HEBREW LETTER NUN }
+    XK_hebrew_samech        : exit($05E1);  { U+05E1 HEBREW LETTER SAMEKH }
+    XK_hebrew_ayin          : exit($05E2);  { U+05E2 HEBREW LETTER AYIN }
+    XK_hebrew_finalpe       : exit($05E3);  { U+05E3 HEBREW LETTER FINAL PE }
+    XK_hebrew_pe            : exit($05E4);  { U+05E4 HEBREW LETTER PE }
+    XK_hebrew_finalzade     : exit($05E5);  { U+05E5 HEBREW LETTER FINAL TSADI }
+    XK_hebrew_zade          : exit($05E6);  { U+05E6 HEBREW LETTER TSADI }
+    XK_hebrew_qoph          : exit($05E7);  { U+05E7 HEBREW LETTER QOF }
+    XK_hebrew_resh          : exit($05E8);  { U+05E8 HEBREW LETTER RESH }
+    XK_hebrew_shin          : exit($05E9);  { U+05E9 HEBREW LETTER SHIN }
+    XK_hebrew_taw           : exit($05EA);  { U+05EA HEBREW LETTER TAV }
+
+    { Thai }
+    XK_Thai_kokai             : exit($0E01);  { U+0E01 THAI CHARACTER KO KAI }
+    XK_Thai_khokhai           : exit($0E02);  { U+0E02 THAI CHARACTER KHO KHAI }
+    XK_Thai_khokhuat          : exit($0E03);  { U+0E03 THAI CHARACTER KHO KHUAT }
+    XK_Thai_khokhwai          : exit($0E04);  { U+0E04 THAI CHARACTER KHO KHWAI }
+    XK_Thai_khokhon           : exit($0E05);  { U+0E05 THAI CHARACTER KHO KHON }
+    XK_Thai_khorakhang        : exit($0E06);  { U+0E06 THAI CHARACTER KHO RAKHANG }
+    XK_Thai_ngongu            : exit($0E07);  { U+0E07 THAI CHARACTER NGO NGU }
+    XK_Thai_chochan           : exit($0E08);  { U+0E08 THAI CHARACTER CHO CHAN }
+    XK_Thai_choching          : exit($0E09);  { U+0E09 THAI CHARACTER CHO CHING }
+    XK_Thai_chochang          : exit($0E0A);  { U+0E0A THAI CHARACTER CHO CHANG }
+    XK_Thai_soso              : exit($0E0B);  { U+0E0B THAI CHARACTER SO SO }
+    XK_Thai_chochoe           : exit($0E0C);  { U+0E0C THAI CHARACTER CHO CHOE }
+    XK_Thai_yoying            : exit($0E0D);  { U+0E0D THAI CHARACTER YO YING }
+    XK_Thai_dochada           : exit($0E0E);  { U+0E0E THAI CHARACTER DO CHADA }
+    XK_Thai_topatak           : exit($0E0F);  { U+0E0F THAI CHARACTER TO PATAK }
+    XK_Thai_thothan           : exit($0E10);  { U+0E10 THAI CHARACTER THO THAN }
+    XK_Thai_thonangmontho     : exit($0E11);  { U+0E11 THAI CHARACTER THO NANGMONTHO }
+    XK_Thai_thophuthao        : exit($0E12);  { U+0E12 THAI CHARACTER THO PHUTHAO }
+    XK_Thai_nonen             : exit($0E13);  { U+0E13 THAI CHARACTER NO NEN }
+    XK_Thai_dodek             : exit($0E14);  { U+0E14 THAI CHARACTER DO DEK }
+    XK_Thai_totao             : exit($0E15);  { U+0E15 THAI CHARACTER TO TAO }
+    XK_Thai_thothung          : exit($0E16);  { U+0E16 THAI CHARACTER THO THUNG }
+    XK_Thai_thothahan         : exit($0E17);  { U+0E17 THAI CHARACTER THO THAHAN }
+    XK_Thai_thothong          : exit($0E18);  { U+0E18 THAI CHARACTER THO THONG }
+    XK_Thai_nonu              : exit($0E19);  { U+0E19 THAI CHARACTER NO NU }
+    XK_Thai_bobaimai          : exit($0E1A);  { U+0E1A THAI CHARACTER BO BAIMAI }
+    XK_Thai_popla             : exit($0E1B);  { U+0E1B THAI CHARACTER PO PLA }
+    XK_Thai_phophung          : exit($0E1C);  { U+0E1C THAI CHARACTER PHO PHUNG }
+    XK_Thai_fofa              : exit($0E1D);  { U+0E1D THAI CHARACTER FO FA }
+    XK_Thai_phophan           : exit($0E1E);  { U+0E1E THAI CHARACTER PHO PHAN }
+    XK_Thai_fofan             : exit($0E1F);  { U+0E1F THAI CHARACTER FO FAN }
+    XK_Thai_phosamphao        : exit($0E20);  { U+0E20 THAI CHARACTER PHO SAMPHAO }
+    XK_Thai_moma              : exit($0E21);  { U+0E21 THAI CHARACTER MO MA }
+    XK_Thai_yoyak             : exit($0E22);  { U+0E22 THAI CHARACTER YO YAK }
+    XK_Thai_rorua             : exit($0E23);  { U+0E23 THAI CHARACTER RO RUA }
+    XK_Thai_ru                : exit($0E24);  { U+0E24 THAI CHARACTER RU }
+    XK_Thai_loling            : exit($0E25);  { U+0E25 THAI CHARACTER LO LING }
+    XK_Thai_lu                : exit($0E26);  { U+0E26 THAI CHARACTER LU }
+    XK_Thai_wowaen            : exit($0E27);  { U+0E27 THAI CHARACTER WO WAEN }
+    XK_Thai_sosala            : exit($0E28);  { U+0E28 THAI CHARACTER SO SALA }
+    XK_Thai_sorusi            : exit($0E29);  { U+0E29 THAI CHARACTER SO RUSI }
+    XK_Thai_sosua             : exit($0E2A);  { U+0E2A THAI CHARACTER SO SUA }
+    XK_Thai_hohip             : exit($0E2B);  { U+0E2B THAI CHARACTER HO HIP }
+    XK_Thai_lochula           : exit($0E2C);  { U+0E2C THAI CHARACTER LO CHULA }
+    XK_Thai_oang              : exit($0E2D);  { U+0E2D THAI CHARACTER O ANG }
+    XK_Thai_honokhuk          : exit($0E2E);  { U+0E2E THAI CHARACTER HO NOKHUK }
+    XK_Thai_paiyannoi         : exit($0E2F);  { U+0E2F THAI CHARACTER PAIYANNOI }
+    XK_Thai_saraa             : exit($0E30);  { U+0E30 THAI CHARACTER SARA A }
+    XK_Thai_maihanakat        : exit($0E31);  { U+0E31 THAI CHARACTER MAI HAN-AKAT }
+    XK_Thai_saraaa            : exit($0E32);  { U+0E32 THAI CHARACTER SARA AA }
+    XK_Thai_saraam            : exit($0E33);  { U+0E33 THAI CHARACTER SARA AM }
+    XK_Thai_sarai             : exit($0E34);  { U+0E34 THAI CHARACTER SARA I }
+    XK_Thai_saraii            : exit($0E35);  { U+0E35 THAI CHARACTER SARA II }
+    XK_Thai_saraue            : exit($0E36);  { U+0E36 THAI CHARACTER SARA UE }
+    XK_Thai_sarauee           : exit($0E37);  { U+0E37 THAI CHARACTER SARA UEE }
+    XK_Thai_sarau             : exit($0E38);  { U+0E38 THAI CHARACTER SARA U }
+    XK_Thai_sarauu            : exit($0E39);  { U+0E39 THAI CHARACTER SARA UU }
+    XK_Thai_phinthu           : exit($0E3A);  { U+0E3A THAI CHARACTER PHINTHU }
+{    XK_Thai_maihanakat_maitho : exit($);}
+    XK_Thai_baht              : exit($0E3F);  { U+0E3F THAI CURRENCY SYMBOL BAHT }
+    XK_Thai_sarae             : exit($0E40);  { U+0E40 THAI CHARACTER SARA E }
+    XK_Thai_saraae            : exit($0E41);  { U+0E41 THAI CHARACTER SARA AE }
+    XK_Thai_sarao             : exit($0E42);  { U+0E42 THAI CHARACTER SARA O }
+    XK_Thai_saraaimaimuan     : exit($0E43);  { U+0E43 THAI CHARACTER SARA AI MAIMUAN }
+    XK_Thai_saraaimaimalai    : exit($0E44);  { U+0E44 THAI CHARACTER SARA AI MAIMALAI }
+    XK_Thai_lakkhangyao       : exit($0E45);  { U+0E45 THAI CHARACTER LAKKHANGYAO }
+    XK_Thai_maiyamok          : exit($0E46);  { U+0E46 THAI CHARACTER MAIYAMOK }
+    XK_Thai_maitaikhu         : exit($0E47);  { U+0E47 THAI CHARACTER MAITAIKHU }
+    XK_Thai_maiek             : exit($0E48);  { U+0E48 THAI CHARACTER MAI EK }
+    XK_Thai_maitho            : exit($0E49);  { U+0E49 THAI CHARACTER MAI THO }
+    XK_Thai_maitri            : exit($0E4A);  { U+0E4A THAI CHARACTER MAI TRI }
+    XK_Thai_maichattawa       : exit($0E4B);  { U+0E4B THAI CHARACTER MAI CHATTAWA }
+    XK_Thai_thanthakhat       : exit($0E4C);  { U+0E4C THAI CHARACTER THANTHAKHAT }
+    XK_Thai_nikhahit          : exit($0E4D);  { U+0E4D THAI CHARACTER NIKHAHIT }
+    XK_Thai_leksun            : exit($0E50);  { U+0E50 THAI DIGIT ZERO }
+    XK_Thai_leknung           : exit($0E51);  { U+0E51 THAI DIGIT ONE }
+    XK_Thai_leksong           : exit($0E52);  { U+0E52 THAI DIGIT TWO }
+    XK_Thai_leksam            : exit($0E53);  { U+0E53 THAI DIGIT THREE }
+    XK_Thai_leksi             : exit($0E54);  { U+0E54 THAI DIGIT FOUR }
+    XK_Thai_lekha             : exit($0E55);  { U+0E55 THAI DIGIT FIVE }
+    XK_Thai_lekhok            : exit($0E56);  { U+0E56 THAI DIGIT SIX }
+    XK_Thai_lekchet           : exit($0E57);  { U+0E57 THAI DIGIT SEVEN }
+    XK_Thai_lekpaet           : exit($0E58);  { U+0E58 THAI DIGIT EIGHT }
+    XK_Thai_lekkao            : exit($0E59);  { U+0E59 THAI DIGIT NINE }
+
+    { Korean }
+    XK_Korean_Won : exit($20A9);  {(U+20A9 WON SIGN)}
+
+    { Currency }
+    XK_EuroSign : exit($20ac);     { U+20AC EURO SIGN }
 
   end;
   X11ConvertKeySymToUnicode := -1;
 end;
+

+ 11 - 1
packages/ptc/src/x11/x11windowdisplayd.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2016 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -44,6 +44,7 @@ type
     FCursorVisible: Boolean;
     FGrabMouse: Boolean;
     FMouseGrabbed: Boolean;
+    FRelativeMouseMode: Boolean;
     FX11InvisibleCursor: TCursor; { Blank cursor }
     FFullScreen: Boolean; { Keeps a snapshot of the PTC_X11_FULLSCREEN option
                              taken at the time 'open' was called }
@@ -62,6 +63,13 @@ type
     FGLXFBConfig: TX11GLXFBConfig;
 {$ENDIF ENABLE_X11_EXTENSION_GLX}
 
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+    FXInput2Enabled: Boolean;
+    FXInput2MajorOpCode: cint;
+    FXInput2FirstEvent: cint;
+    FXInput2FirstError: cint;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+
     procedure EnterFullScreen;
     procedure LeaveFullScreen;
     procedure internal_ShowCursor(AVisible: Boolean);
@@ -99,6 +107,8 @@ type
     function IsOpen: Boolean; override;
     procedure SetCursor(AVisible: Boolean); override;
     procedure SetMouseGrab(AGrabMouse: Boolean); override;
+    function SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean; override;
+    function MoveMouseTo(X, Y: Integer): Boolean; override;
 {$IFDEF ENABLE_X11_EXTENSION_GLX}
     procedure OpenGL_SwapBuffers; override;
     procedure OpenGL_SetSwapInterval(AInterval: Integer); override;

+ 408 - 6
packages/ptc/src/x11/x11windowdisplayi.inc

@@ -1,6 +1,6 @@
 {
     This file is part of the PTCPas framebuffer library
-    Copyright (C) 2001-2013 Nikolay Nikolov ([email protected])
+    Copyright (C) 2001-2013, 2016, 2017 Nikolay Nikolov ([email protected])
     Original C++ version by Christian Nentwich ([email protected])
 
     This library is free software; you can redistribute it and/or
@@ -31,6 +31,11 @@
 }
 
 constructor TX11WindowDisplay.Create(ADisplay: PDisplay; AScreen: Integer; const AFlags: TX11Flags);
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+var
+  MajorVer, MinorVer: cint;
+  QueryVersionResult: TStatus;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
 begin
   inherited;
   FFocus := True;
@@ -38,6 +43,34 @@ begin
   FCursorVisible := True;
   FGrabMouse := False;
   FMouseGrabbed := False;
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  if PTC_X11_TRY_XINPUT2 in FFlags then
+  begin
+    LOG('Querying the XInput2 extension...');
+    if XQueryExtension(FDisplay, 'XInputExtension', @FXInput2MajorOpCode, @FXInput2FirstEvent, @FXInput2FirstError) then
+    begin
+      LOG('There is an XInput extension, now let''s query its version...');
+      MajorVer := 2;
+      MinorVer := 0;
+      LOG('We want version ' + IntToStr(MajorVer) + '.' + IntToStr(MinorVer));
+      QueryVersionResult := XIQueryVersion(FDisplay, @MajorVer, @MinorVer);
+      if QueryVersionResult = Success then
+      begin
+        LOG('XInput2 extension is available (version ' + IntToStr(MajorVer) + '.' + IntToStr(MinorVer) + ')');
+        FXInput2Enabled := True;
+      end
+      else
+      begin
+        LOG('The required XInput version is not available (version ' + IntToStr(MajorVer) + '.' + IntToStr(MinorVer) + ' only)');
+      end;
+    end
+    else
+    begin
+      LOG('XInput2 extension not available');
+      FXInput2Enabled := False;
+    end;
+  end;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
 end;
 
 destructor TX11WindowDisplay.Destroy;
@@ -46,6 +79,14 @@ begin
   inherited Destroy;
 end;
 
+{$warning remove, when fix added to xlib}
+function XGetIMValues(para1:PXIM; dotdotdot:array of const):Pchar;cdecl;external libX11;
+function XGetICValues(para1:PXIC; dotdotdot:array of const):Pchar;cdecl;external libX11;
+
+{function fpsetlocale(category: cint; locale: Pchar): PChar;cdecl;external 'c' name 'setlocale';
+const
+  LC_ALL = 6;}
+
 procedure TX11WindowDisplay.Open(ATitle: AnsiString; AWidth, AHeight: Integer; AFormat: IPTCFormat; const AOpenGLAttributes: IPTCOpenGLAttributes);
 var
   xgcv: TXGCValues;
@@ -62,6 +103,119 @@ var
   BlankCursorData: array [1..8] of Byte = (0, 0, 0, 0, 0, 0, 0, 0);
   CreateWindow_Depth: cint;
   CreateWindow_Visual: PVisual;
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  XInput2EventMask: TXIEventMask;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+  selected_im_style: TXIMStyle = 0;
+  im_event_mask: clong = 0;
+
+  function IMStyleToStr(style: TXIMStyle): string;
+  begin
+    Result := '';
+    if (style and XIMPreeditArea) <> 0 then
+      Result := Result + ' XIMPreeditArea';
+    if (style and XIMPreeditCallbacks) <> 0 then
+      Result := Result + ' XIMPreeditCallbacks';
+    if (style and XIMPreeditPosition) <> 0 then
+      Result := Result + ' XIMPreeditPosition';
+    if (style and XIMPreeditNothing) <> 0 then
+      Result := Result + ' XIMPreeditNothing';
+    if (style and XIMPreeditNone) <> 0 then
+      Result := Result + ' XIMPreeditNone';
+    if (style and XIMStatusArea) <> 0 then
+      Result := Result + ' XIMStatusArea';
+    if (style and XIMStatusCallbacks) <> 0 then
+      Result := Result + ' XIMStatusCallbacks';
+    if (style and XIMStatusNothing) <> 0 then
+      Result := Result + ' XIMStatusNothing';
+    if (style and XIMStatusNone) <> 0 then
+      Result := Result + ' XIMStatusNone';
+    if Length(Result) > 0 then
+      Delete(Result, 1, 1);
+    Result := IntToStr(style) + ' (' + Result + ')';
+  end;
+
+  procedure TryCreateIM;
+  const
+    PreferredStyle = XIMPreeditNothing or XIMStatusNothing;
+{    PreferredStyle = XIMPreeditNone or XIMStatusNone;}
+  var
+    im_supported_styles: PXIMStyles;
+    locale_modifiers: PChar;
+    I: Integer;
+  begin
+{    LOG('setting locale');
+    if fpsetlocale(LC_ALL, '') = nil then
+      LOG('set locale failed');}
+
+    { Check if X11 supports the current locale }
+    LOG('checking X11 support for the current locale');
+    if XSupportsLocale = 0 then
+    begin
+      LOG('locale not supported');
+      exit;
+    end;
+    LOG('locale supported');
+
+    LOG('setting locale modifiers');
+    locale_modifiers := XSetLocaleModifiers('@im=none');
+    if locale_modifiers = nil then
+    begin
+      LOG('XSetLocaleModifiers failed');
+    end
+    else
+    begin
+      LOG('XSetLocaleModifiers success; returned', locale_modifiers);
+    end;
+
+    { Open IM }
+    LOG('opening input method');
+    FXIM := XOpenIM(FDisplay, nil, '', '');
+    LOG('input method (ptr)', HexStr(FXIM));
+
+    { Select IM input style }
+    if Assigned(FXIM) then
+    begin
+      LOG('querying the supported input styles');
+      XGetIMValues(FXIM, [XNQueryInputStyle, @im_supported_styles, nil]);
+
+      if Assigned(im_supported_styles) then
+      begin
+        LOG('number of styles', im_supported_styles^.count_styles);
+        for I := 0 to im_supported_styles^.count_styles - 1 do
+        begin
+          LOG('style', IMStyleToStr(im_supported_styles^.supported_styles[I]));
+          if (im_supported_styles^.supported_styles[I] and PreferredStyle) = PreferredStyle then
+            selected_im_style := im_supported_styles^.supported_styles[I];
+        end;
+        XFree(im_supported_styles);
+        LOG('selected style', IMStyleToStr(selected_im_style));
+      end;
+    end;
+  end;
+
+  procedure TryCreateIC;
+  begin
+    if Assigned(FXIM) and (selected_im_style <> 0) then
+    begin
+      LOG('creating input context');
+      FXIC := XCreateIC(FXIM, [XNInputStyle, selected_im_style,
+                               XNClientWindow, FWindow,
+                               XNFocusWindow, FWindow, nil]);
+      LOG('input context (ptr)', HexStr(FXIC));
+
+      if Assigned(FXIC) then
+      begin
+        LOG('setting input context focus');
+        XSetICFocus(FXIC);
+
+        LOG('getting the IM event mask');
+        XGetICValues(FXIC, [XNFilterEvents, @im_event_mask, nil]);
+        LOG('IM event mask', im_event_mask);
+      end;
+    end;
+  end;
+
 begin
   FHeight := AHeight;
   FWidth := AWidth;
@@ -82,6 +236,10 @@ begin
   BlackColor.green := 0;
   BlackColor.blue := 0;
 
+  { Try to open an input method }
+  if PTC_X11_TRY_XIM in FFlags then
+    TryCreateIM;
+
   { Create the mode switcher object }
   if (FModeSwitcher = Nil) and FFullScreen then
     FModeSwitcher := CreateModeSwitcher;
@@ -205,13 +363,40 @@ begin
     if e._type = MapNotify then
       Break;
   until False;
+
+  { Try to create an input context for the input method }
+  if PTC_X11_TRY_XIM in FFlags then
+    TryCreateIC;
+
   { Get keyboard input and sync }
   XSelectInput(FDisplay, FWindow, KeyPressMask or KeyReleaseMask or
                                   StructureNotifyMask or FocusChangeMask or
                                   ButtonPressMask or ButtonReleaseMask or
-                                  PointerMotionMask or ExposureMask);
+                                  PointerMotionMask or ExposureMask or
+                                  EnterWindowMask or LeaveWindowMask or im_event_mask);
   XSync(FDisplay, False);
 
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  { enable XInput2 raw mouse input for the window as well }
+  if FXInput2Enabled then
+  begin
+    FillChar(XInput2EventMask, SizeOf(XInput2EventMask), 0);
+    XInput2EventMask.deviceid := XIAllMasterDevices;
+
+    XInput2EventMask.mask_len := XIMaskLen(XI_LASTEVENT);
+    XInput2EventMask.mask := AllocMem(XInput2EventMask.mask_len);
+    try
+      XISetMask(XInput2EventMask.mask, XI_RawMotion);
+      XISetMask(XInput2EventMask.mask, XI_RawButtonPress);
+      XISetMask(XInput2EventMask.mask, XI_RawButtonRelease);
+
+      XISelectEvents(FDisplay, RootWindow(FDisplay, FScreen){FWindow}, @XInput2EventMask, 1);
+    finally
+      FreeMem(XInput2EventMask.mask);
+    end;
+  end;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+
   if not (PTC_X11_USE_OPENGL in FFlags) then
   begin
     { Create XImage using factory method }
@@ -267,6 +452,20 @@ begin
   FreeAndNil(FGLXFBConfig);
 {$ENDIF ENABLE_X11_EXTENSION_GLX}
 
+  if Assigned(FXIC) then
+  begin
+    LOG('destroying input context');
+    XDestroyIC(FXIC);
+    FXIC := nil;
+  end;
+
+  if Assigned(FXIM) then
+  begin
+    LOG('closing input method');
+    XCloseIM(FXIM);
+    FXIM := nil;
+  end;
+
   {pthreads?!}
   if FCMap <> 0 then
   begin
@@ -392,6 +591,15 @@ begin
     internal_GrabMouse(FGrabMouse);
 end;
 
+function TX11WindowDisplay.SetRelativeMouseMode(ARelativeMouseMode: Boolean): Boolean;
+begin
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  if FXInput2Enabled then
+    FRelativeMouseMode := ARelativeMouseMode;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+  Result := ARelativeMouseMode = FRelativeMouseMode;
+end;
+
 procedure TX11WindowDisplay.EnterFullScreen;
 begin
   { try to switch mode }
@@ -480,6 +688,22 @@ var
     before, after: Boolean;
     cstate: TPTCMouseButtonState;
   begin
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+    { if XInput2 is enabled, and we're in relative mouse mode, then don't handle
+    the regular mouse events -> use the XInput2 raw mouse events in this case }
+    if FXInput2Enabled and FRelativeMouseMode then
+      exit;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+    if not FPreviousMousePositionSaved then
+    begin
+      FPreviousMouseX := -1; { -1 indicates relative mouse mode }
+      FPreviousMouseY := -1; { -1 indicates relative mouse mode }
+      FPreviousMouseButtonState := [];
+      PTCMouseButtonState := [];
+    end
+    else
+      PTCMouseButtonState := FPreviousMouseButtonState
+        - [PTCMouseButton1, PTCMouseButton2, PTCMouseButton3, PTCMouseButton4, PTCMouseButton5];
     case e._type of
       MotionNotify: begin
         x := e.xmotion.x;
@@ -498,6 +722,8 @@ var
             Button3: state := state or Button3Mask;
             Button4: state := state or Button4Mask;
             Button5: state := state or Button5Mask;
+            6..Ord(High(TPTCMouseButton))+1:
+              Include(PTCMouseButtonState, TPTCMouseButton((Ord(PTCMouseButton6)-6)+e.xbutton.button));
           end;
         end
         else
@@ -508,6 +734,8 @@ var
             Button3: state := state and (not Button3Mask);
             Button4: state := state and (not Button4Mask);
             Button5: state := state and (not Button5Mask);
+            6..Ord(High(TPTCMouseButton))+1:
+              Exclude(PTCMouseButtonState, TPTCMouseButton((Ord(PTCMouseButton6)-6)+e.xbutton.button));
           end;
         end;
       end;
@@ -515,10 +743,8 @@ var
         raise TPTCError.Create('Internal Error');
     end;
 
-    if (state and Button1Mask) = 0 then
-      PTCMouseButtonState := []
-    else
-      PTCMouseButtonState := [PTCMouseButton1];
+    if (state and Button1Mask) <> 0 then
+      PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton1];
     if (state and Button2Mask) <> 0 then
       PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton3];
     if (state and Button3Mask) <> 0 then
@@ -535,6 +761,12 @@ var
         FPreviousMouseX := x; { first DeltaX will be 0 }
         FPreviousMouseY := y; { first DeltaY will be 0 }
         FPreviousMouseButtonState := [];
+      end
+      { there's a previous mouse state saved, but it was in relative mouse mode? }
+      else if (FPreviousMouseX = -1) or (FPreviousMouseY = -1) then
+      begin
+        FPreviousMouseX := x; { first DeltaX after relative mouse mode will be 0 }
+        FPreviousMouseY := y; { first DeltaY after relative mouse mode will be 0 }
       end;
 
       { movement? }
@@ -581,11 +813,149 @@ var
     FPreviousHeight := e.xconfigure.height;
   end;
 
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  procedure HandleXInput2RawEvent(const xi2e: TXIRawEvent);
+  var
+    I: Integer;
+    MovementXAccelerated: cdouble = 0;
+    MovementXRaw: cdouble = 0;
+    MovementXRawInt: Integer = 0;
+    MovementXAvailable: Boolean = False;
+    MovementYAccelerated: cdouble = 0;
+    MovementYRaw: cdouble = 0;
+    MovementYRawInt: Integer = 0;
+    MovementYAvailable: Boolean = False;
+    valptr, rawptr: Pcdouble;
+    PTCMouseButtonState: TPTCMouseButtonState;
+
+    button: TPTCMouseButton;
+    before, after: Boolean;
+    cstate: TPTCMouseButtonState;
+  begin
+{    Writeln(xi2e.evtype, ' ', xi2e.detail);
+    valptr := xi2e.valuators.values;
+    rawptr := xi2e.raw_values;
+    for I := 0 to xi2e.valuators.mask_len*8 - 1 do
+      if XIMaskIsSet(xi2e.valuators.mask, I) then
+      begin
+        Writeln('Valuator ', I, ' value=', valptr^:0:50, ' raw=', rawptr^:0:50);
+        Inc(valptr);
+        Inc(rawptr);
+      end;}
+
+    { when not in relative mouse mode, we use the regular X11 mouse events }
+    if not FRelativeMouseMode then
+      exit;
+
+    if not FPreviousMousePositionSaved then
+    begin
+      FPreviousMouseX := -1; { -1 indicates relative mouse mode }
+      FPreviousMouseY := -1; { -1 indicates relative mouse mode }
+      FPreviousMouseButtonState := [];
+    end;
+
+    if (xi2e.evtype = XI_RawButtonPress) or (xi2e.evtype = XI_RawButtonRelease) then
+    begin
+      PTCMouseButtonState := FPreviousMouseButtonState;
+      if xi2e.evtype = XI_RawButtonPress then
+        case xi2e.detail of
+          Button1: PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton1];
+          Button2: PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton3];
+          Button3: PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton2];
+          Button4: PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton4];
+          Button5: PTCMouseButtonState := PTCMouseButtonState + [PTCMouseButton5];
+          6..Ord(High(TPTCMouseButton))+1:
+            Include(PTCMouseButtonState, TPTCMouseButton((Ord(PTCMouseButton6)-6)+xi2e.detail));
+        end
+      else
+        case xi2e.detail of
+          Button1: PTCMouseButtonState := PTCMouseButtonState - [PTCMouseButton1];
+          Button2: PTCMouseButtonState := PTCMouseButtonState - [PTCMouseButton3];
+          Button3: PTCMouseButtonState := PTCMouseButtonState - [PTCMouseButton2];
+          Button4: PTCMouseButtonState := PTCMouseButtonState - [PTCMouseButton4];
+          Button5: PTCMouseButtonState := PTCMouseButtonState - [PTCMouseButton5];
+          6..Ord(High(TPTCMouseButton))+1:
+            Exclude(PTCMouseButtonState, TPTCMouseButton((Ord(PTCMouseButton6)-6)+xi2e.detail));
+        end;
+    end
+    else
+      PTCMouseButtonState := FPreviousMouseButtonState;
+
+    if xi2e.valuators.mask_len > 0 then
+    begin
+      valptr := xi2e.valuators.values;
+      rawptr := xi2e.raw_values;
+      if XIMaskIsSet(xi2e.valuators.mask, 0) then
+      begin
+        MovementXAccelerated := valptr^;
+        MovementXRaw := rawptr^;
+        MovementXRawInt := Round(MovementXRaw);
+        MovementXAvailable := True;
+        Inc(valptr);
+        Inc(rawptr);
+      end;
+      if XIMaskIsSet(xi2e.valuators.mask, 1) then
+      begin
+        MovementYAccelerated := valptr^;
+        MovementYRaw := rawptr^;
+        MovementYRawInt := Round(MovementYRaw);
+        MovementYAvailable := True;
+        Inc(valptr);
+        Inc(rawptr);
+      end;
+    end;
+
+    { movement? }
+    if (MovementXRawInt <> 0) or (MovementYRawInt <> 0) then
+      FEventQueue.AddEvent(TPTCMouseEvent.Create(-1, -1, MovementXRawInt, MovementYRawInt, FPreviousMouseButtonState));
+
+    { button presses/releases? }
+    cstate := FPreviousMouseButtonState;
+    for button := Low(button) to High(button) do
+    begin
+      before := button In FPreviousMouseButtonState;
+      after := button In PTCMouseButtonState;
+      if after and (not before) then
+      begin
+        { button was pressed }
+        cstate := cstate + [button];
+        FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(-1, -1, 0, 0, cstate, True, button));
+      end
+      else
+        if before and (not after) then
+        begin
+          { button was released }
+          cstate := cstate - [button];
+          FEventQueue.AddEvent(TPTCMouseButtonEvent.Create(-1, -1, 0, 0, cstate, False, button));
+        end;
+    end;
+
+    FPreviousMouseX := -1;
+    FPreviousMouseY := -1;
+    FPreviousMouseButtonState := PTCMouseButtonState;
+    FPreviousMousePositionSaved := True;
+  end;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+
+var
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+  XInput2Event: PXIDeviceEvent;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
+  eaten_by_im: Boolean = False;
 begin
   NewFocusSpecified := False;
   while UsefulEventsPending do
   begin
     XNextEvent(FDisplay, @e);
+    { maybe send the event to the Input Method for processing. Only non-key
+      events are sent here (key events are sent in HandleKeyEvent instead) }
+    if Assigned(FXIM) and Assigned(FXIC) and
+      (e._type <> KeyPress) and (e._type <> KeyRelease) then
+    begin
+      eaten_by_im := XFilterEvent(@e, FWindow);
+      if eaten_by_im then
+        exit;
+    end;
     case e._type of
       FocusIn: begin
         NewFocus := True;
@@ -609,6 +979,30 @@ begin
       ConfigureNotify: HandleConfigureNotifyEvent;
       KeyPress, KeyRelease: HandleKeyEvent(e.xkey);
       ButtonPress, ButtonRelease, MotionNotify: HandleMouseEvent;
+      EnterNotify: begin
+        { clear the high (>=6) numbered mouse buttons, because the mouse events contain no state information for them }
+        FPreviousMouseButtonState := FPreviousMouseButtonState
+          * [PTCMouseButton1, PTCMouseButton2, PTCMouseButton3, PTCMouseButton4, PTCMouseButton5];
+      end;
+{$IFDEF ENABLE_X11_EXTENSION_XINPUT2}
+      GenericEvent: begin
+        if e.xcookie.extension = FXInput2MajorOpCode then
+        begin
+          if XGetEventData(FDisplay, @e.xcookie) then
+            try
+              XInput2Event := e.xcookie.data;
+              case XInput2Event^.evtype of
+                XI_RawButtonPress,
+                XI_RawButtonRelease,
+                XI_RawMotion:
+                  HandleXInput2RawEvent(PXIRawEvent(XInput2Event)^);
+              end;
+            finally
+              XFreeEventData(FDisplay, @e.xcookie);
+            end;
+        end;
+      end;
+{$ENDIF ENABLE_X11_EXTENSION_XINPUT2}
     end;
   end;
   if NewFocusSpecified then
@@ -618,6 +1012,14 @@ begin
     internal_GrabMouse(FGrabMouse);
 end;
 
+function TX11WindowDisplay.MoveMouseTo(X, Y: Integer): Boolean;
+begin
+  if not FOpen or (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then
+    exit(False);
+  XWarpPointer(FDisplay, None, FWindow, 0, 0, 0, 0, X, Y);
+  Result := True;
+end;
+
 procedure TX11WindowDisplay.Draw;
 begin
   if not (PTC_X11_USE_OPENGL in FFlags) then

+ 122 - 0
packages/ptc/tests/event.pp

@@ -0,0 +1,122 @@
+program event;
+
+{$MODE objfpc}{$H+}
+
+uses
+  SysUtils, ptc;
+
+function ButtonState2Str(const bs: TPTCMouseButtonState): string;
+var
+  I: TPTCMouseButton;
+begin
+  Result := '';
+  for I in TPTCMouseButton do
+    if I in bs then
+      WriteStr(Result, Result, ',', I);
+  if Result = '' then
+    Result := '[]'
+  else
+  begin
+    Result[1] := '[';
+    Result := Result + ']';
+  end;
+end;
+
+function ModifierKeys2Str(const mk: TPTCModifierKeys): string;
+var
+  I: TPTCModifierKey;
+begin
+  Result := '';
+  for I in TPTCModifierKey do
+    if I in mk then
+      WriteStr(Result, Result, ',', I);
+  if Result = '' then
+    Result := '[]'
+  else
+  begin
+    Result[1] := '[';
+    Result := Result + ']';
+  end;
+end;
+
+var
+  console: IPTCConsole;
+  ev: IPTCEvent;
+  Done: Boolean = False;
+  RX, RY: Integer;
+begin
+  try
+    try
+      console := TPTCConsoleFactory.CreateNew;
+
+      console.Option('intercept window close');
+  //    console.Option('resizable window');
+
+      console.Open('event test');
+
+      repeat
+        console.NextEvent(ev, True, PTCAnyEvent);
+        if Supports(ev, IPTCMouseButtonEvent) then
+          with ev as IPTCMouseButtonEvent do
+            Writeln('IPTCMouseButtonEvent(X=', X, '; Y=', Y, '; DeltaX=', DeltaX,
+            '; DeltaY=', DeltaY, '; ButtonState=', ButtonState2Str(ButtonState),
+            '; Press=', Press, '; Release=', Release, '; Button=', Button, ')')
+        else if Supports(ev, IPTCMouseEvent) then
+          with ev as IPTCMouseEvent do
+            Writeln('IPTCMouseEvent(X=', X, '; Y=', Y, '; DeltaX=', DeltaX,
+            '; DeltaY=', DeltaY, '; ButtonState=', ButtonState2Str(ButtonState),
+            ')')
+        else if Supports(ev, IPTCKeyEvent) then
+          with ev as IPTCKeyEvent do
+            Writeln('IPTCKeyEvent(Code=', Code, '; Unicode=', Unicode, '; Press=',
+              Press, '; Release=', Release, '; Alt=', Alt, '; Shift=', Shift,
+              '; Control=', Control, '; ModifierKeys=',
+              ModifierKeys2Str(ModifierKeys), ')')
+        else if Supports(ev, IPTCResizeEvent) then
+          with ev as IPTCResizeEvent do
+            Writeln('IPTCResizeEvent(Width=', Width, '; Height=', Height, ')')
+        else if Supports(ev, IPTCCloseEvent) then
+          with ev as IPTCCloseEvent do
+            Writeln('IPTCCloseEvent()')
+        else
+          Writeln('UNKNOWN EVENT TYPE');
+
+        if Supports(ev, IPTCKeyEvent) then
+          with ev as IPTCKeyEvent do
+            if Press then
+            begin
+              case Code of
+                PTCKEY_G:
+                  console.Option('grab mouse');
+                PTCKEY_U:
+                  console.Option('ungrab mouse');
+                PTCKEY_S:
+                  console.Option('show cursor');
+                PTCKEY_H:
+                  console.Option('hide cursor');
+                PTCKEY_R:
+                  console.Option('relative mouse on');
+                PTCKEY_A:
+                  console.Option('relative mouse off');
+                PTCKEY_M:
+                  begin
+                    RX := Random(console.Width);
+                    RY := Random(console.Height);
+                    Writeln('MoveMouseTo(', RX, ', ', RY, ')');
+                    if not console.MoveMouseTo(RX, RY) then
+                      writeln('MoveMouseTo FAILED (or is not supported by the console)');
+                  end;
+                PTCKEY_Q:
+                  Done := True;
+              end;
+            end;
+      until Done;
+    finally
+      if Assigned(console) then
+        console.Close;
+    end;
+  except
+    on error: TPTCError do
+      error.Report;
+  end;
+end.