I_CYBER.C 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // I_cyber.c
  2. #include <dos.h>
  3. #include <stdlib.h>
  4. /*
  5. ====================================================
  6. Doom control structure
  7. The keybaord and joystick will add to the values set by the cyberman,
  8. to a maximum of 0x19000 for forwardmove and sidemove. Angleturn is
  9. not bounded at all.
  10. parm normal fast
  11. ----- ------ ----
  12. forwardmove 0xc800 0x19000
  13. sidemove 0xc000 0x14000
  14. angleturn 0x2800000 0x5000000
  15. The keyboard and joystick have a 1/3 second slow turn of 0x1400000 under
  16. normal speed to help aiming.
  17. ====================================================
  18. */
  19. typedef struct
  20. {
  21. char forwardmove; // *2048 for move
  22. char sidemove; // *2048 for move
  23. short angleturn; // <<16 for angle delta
  24. short consistancy; // checks for net game
  25. unsigned char chatchar;
  26. unsigned char buttons;
  27. } ticcmd_t;
  28. #define BT_ATTACK 1
  29. #define BT_USE 2
  30. #define BT_CHANGE 4 // if true, the next 3 bits hold weapon num
  31. #define BT_WEAPONMASK (8+16+32)
  32. #define BT_WEAPONSHIFT 3
  33. //==================================================
  34. //
  35. // CyberMan detection and usage info
  36. //
  37. //==================================================
  38. #define DPMI_INT 0x31
  39. #define MOUSE_INT 0x33
  40. #define DOSMEMSIZE 64 // enough for any SWIFT structure
  41. typedef struct {
  42. short x;
  43. short y;
  44. short z;
  45. short pitch;
  46. short roll;
  47. short yaw;
  48. short buttons;
  49. } SWIFT_3DStatus;
  50. // DPMI real mode interrupt structure
  51. static struct rminfo {
  52. long EDI;
  53. long ESI;
  54. long EBP;
  55. long reserved_by_system;
  56. long EBX;
  57. long EDX;
  58. long ECX;
  59. long EAX;
  60. short flags;
  61. short ES,DS,FS,GS,IP,CS,SP,SS;
  62. } RMI;
  63. typedef struct {
  64. unsigned char deviceType;
  65. unsigned char majorVersion;
  66. unsigned char minorVersion;
  67. unsigned char absRelFlags;
  68. unsigned char centeringFlags;
  69. unsigned char reserved[5];
  70. } StaticDeviceData;
  71. // values for deviceType:
  72. #define DEVTYPE_CYBERMAN 1
  73. short selector;
  74. unsigned short segment; // segment of DOS memory block
  75. SWIFT_3DStatus *cyberstat;
  76. int isCyberPresent; // is CyberMan present?
  77. static union REGS regs;
  78. static struct SREGS sregs;
  79. extern int mousepresent;
  80. //===========================================================
  81. //
  82. // I_StartupCyberMan
  83. //
  84. // If a cyberman is present, init it and set isCyberPresent to 1
  85. //===========================================================
  86. void I_StartupCyberMan(void)
  87. {
  88. StaticDeviceData *pbuf;
  89. int success = 0;
  90. isCyberPresent = 0;
  91. cyberstat = (SWIFT_3DStatus *)I_AllocLow (DOSMEMSIZE);
  92. segment = (int)cyberstat>>4;
  93. pbuf = (StaticDeviceData *)cyberstat;
  94. memset(pbuf, 0, sizeof (StaticDeviceData));
  95. // Use DPMI call 300h to issue mouse interrupt
  96. memset(&RMI, 0, sizeof(RMI));
  97. RMI.EAX = 0x53C1; // SWIFT: Get Static Device Data
  98. RMI.ES = segment;
  99. RMI.EDX = 0;
  100. memset(&sregs, 0, sizeof (sregs));
  101. regs.w.ax = 0x0300; // DPMI: simulate interrupt
  102. regs.w.bx = MOUSE_INT;
  103. regs.w.cx = 0;
  104. regs.x.edi = FP_OFF(&RMI);
  105. sregs.es = FP_SEG(&RMI);
  106. int386x( DPMI_INT, &regs, &regs, &sregs );
  107. if ((short)RMI.EAX != 1)
  108. {
  109. // SWIFT functions not present
  110. tprintf("CyberMan: Wrong mouse driver - no SWIFT support (AX=%04x).\n",
  111. (unsigned)(short)RMI.EAX);
  112. }
  113. else
  114. if (pbuf->deviceType != DEVTYPE_CYBERMAN)
  115. {
  116. // no SWIFT device, or not CyberMan
  117. if (pbuf->deviceType == 0)
  118. {
  119. tprintf("CyberMan: no SWIFT device connected.\n");
  120. }
  121. else
  122. {
  123. tprintf("CyberMan: SWIFT device is not a CyberMan! (type=%d)\n",
  124. pbuf->deviceType);
  125. }
  126. }
  127. else
  128. {
  129. tprintf("CyberMan: CyberMan %d.%02d connected.\n",
  130. pbuf->majorVersion, pbuf->minorVersion);
  131. isCyberPresent = 1;
  132. mousepresent = 0;
  133. }
  134. }
  135. /*
  136. ===============
  137. =
  138. = I_ReadCyberCmds
  139. =
  140. ===============
  141. */
  142. int oldpos;
  143. void I_ReadCyberCmd (ticcmd_t *cmd)
  144. {
  145. int delta;
  146. // Use DPMI call 300h to issue mouse interrupt
  147. memset(&RMI, 0, sizeof(RMI));
  148. RMI.EAX = 0x5301; // SWIFT: Get Position and Buttons
  149. RMI.ES = segment;
  150. RMI.EDX = 0;
  151. memset(&sregs, 0, sizeof (sregs));
  152. regs.w.ax = 0x0300; // DPMI: simulate interrupt
  153. regs.w.bx = MOUSE_INT;
  154. regs.w.cx = 0;
  155. regs.x.edi = FP_OFF(&RMI);
  156. sregs.es = FP_SEG(&RMI);
  157. int386x( DPMI_INT, &regs, &regs, &sregs );
  158. if (cyberstat->y < -7900)
  159. cmd->forwardmove = 0xc800/2048;
  160. else if (cyberstat->y > 7900)
  161. cmd->forwardmove = -0xc800/2048;
  162. if (cyberstat->buttons & 4)
  163. cmd->buttons |= BT_ATTACK;
  164. if (cyberstat->buttons & 2)
  165. cmd->buttons |= BT_USE;
  166. delta = cyberstat->x - oldpos;
  167. oldpos = cyberstat->x;
  168. if (cyberstat->buttons & 1)
  169. { // strafe
  170. if (cyberstat->x < -7900)
  171. cmd->sidemove = -0xc800/2048;
  172. else if (cyberstat->x > 7900)
  173. cmd->sidemove = 0xc800/2048;
  174. else
  175. cmd->sidemove = delta*40/2048;
  176. }
  177. else
  178. {
  179. if (cyberstat->x < -7900)
  180. cmd->angleturn = 0x280;
  181. else if (cyberstat->x > 7900)
  182. cmd->angleturn = -0x280;
  183. else
  184. cmd->angleturn = -delta*0xa/16;
  185. }
  186. }
  187. void I_Tactile (int on, int off, int total)
  188. {
  189. if (!isCyberPresent)
  190. return;
  191. on /= 5;
  192. off /= 5;
  193. total /= 40;
  194. if (on > 255)
  195. on = 255;
  196. if (off > 255)
  197. off = 255;
  198. if (total > 255)
  199. total = 255;
  200. memset(&RMI, 0, sizeof(RMI));
  201. RMI.EAX = 0x5330; // SWIFT: Get Position and Buttons
  202. RMI.EBX = on*256+off;
  203. RMI.ECX = total;
  204. memset(&sregs, 0, sizeof (sregs));
  205. regs.w.ax = 0x0300; // DPMI: simulate interrupt
  206. regs.w.bx = MOUSE_INT;
  207. regs.w.cx = 0;
  208. regs.x.edi = FP_OFF(&RMI);
  209. sregs.es = FP_SEG(&RMI);
  210. int386x( DPMI_INT, &regs, &regs, &sregs );
  211. }