|
|
1.1 root 1: /* 1.1.1.6 ! root 2: Hatari - ikbd.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. 1.1 root 6: 7: The keyboard processor(6301) handles any joystick/mouse task and sends bytes to the ACIA(6850) 8: When a byte arrives in the ACIA (which takes just over 7000 CPU cycles) an MFP interrupt is flagged. 9: The CPU can now read the byte from the ACIA by reading address $fffc02. 10: An annoying bug can be found in Dungeon Master. This, when run, turns off the mouse input - but of course 11: then you are unable to play the game! A bodge flag has been added so we need to be told twice to turn off 12: the mouse input(although I think this causes errors in other games...) 13: Also, the ACIA_CYCLES time is very important for games such as Carrier Command. The keyboard handler 14: in this game has a bug in it, which corrupts its own registers if more than one byte is queued up. This 15: value was found by a test program on a real ST and has correctly emulated the behaviour. 16: */ 1.1.1.6 ! root 17: static char rcsid[] = "Hatari $Id: ikbd.c,v 1.13 2003/03/09 15:39:07 thothy Exp $"; ! 18: ! 19: #include <time.h> 1.1 root 20: 21: #include "main.h" 22: #include "debug.h" 23: #include "decode.h" 24: #include "gemdos.h" 25: #include "ikbd.h" 26: #include "int.h" 27: #include "joy.h" 28: #include "m68000.h" 29: #include "memAlloc.h" 30: #include "memorySnapShot.h" 31: #include "mfp.h" 32: #include "misc.h" 33: #include "screen.h" 34: #include "video.h" 35: #include "vdi.h" 36: 37: #define DBL_CLICK_HISTORY 0x07 /* Number of frames since last click to see if need to send one or two clicks */ 38: #define ACIA_CYCLES 7200 /* Cycles(Multiple of 4) between sent to ACIA from keyboard along serial line - 500Hz/64, (approx' 6920-7200cycles from test program) */ 39: 40: #define IKBD_RESET_CYCLES 400000 /* Cycles after RESET before complete */ 41: 42: #define ABS_X_ONRESET 0 /* Initial XY for absolute mouse position after RESET command */ 43: #define ABS_Y_ONRESET 0 44: #define ABS_MAX_X_ONRESET 320 /* Initial absolute mouse limits after RESET command */ 45: #define ABS_MAY_Y_ONRESET 200 /* These values are never actually used as user MUST call 'IKBD_Cmd_AbsMouseMode' before ever using them */ 46: 47: #define ABS_PREVBUTTONS (0x02|0x8) /* Don't report any buttons up on first call to 'IKBD_Cmd_ReadAbsMousePos' */ 48: 49: 50: /* Keyboard state */ 51: KEYBOARD Keyboard; 52: 53: /* Keyboard processor */ 54: KEYBOARD_PROCESSOR KeyboardProcessor; /* Keyboard processor details */ 1.1.1.2 root 55: BOOL DoubleClickPattern[] = { /* Pattern of mouse button up/down in ST frames (run off a double-click message) */ 56: BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE, 57: 0,0,0,0,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE }; 1.1.1.6 ! root 58: ! 59: BOOL bMouseDisabled, bJoystickDisabled; ! 60: BOOL bDuringResetCriticalTime, bDontDuplicateFire; 1.1 root 61: 62: /* ACIA */ 63: unsigned char ACIAControlRegister = 0; 64: unsigned char ACIAStatusRegister = ACIA_STATUS_REGISTER__TX_BUFFER_EMPTY; /* Pass when read 0xfffc00 */ 65: unsigned char ACIAByte; /* When a byte has arrived at the ACIA(from the keyboard) it is stored here */ 66: BOOL bByteInTransitToACIA = FALSE; /* Is a byte being sent to the ACIA from the keyboard? */ 67: 68: /* 69: 6850 ACIA (Asynchronous Communications Inferface Apdater) 70: Page 41, ST Internals. Also ST Update Magazine, February 1989 (I glad I kept that!) 71: 72: Pins:- 73: Vss 74: RX DATA Receive Data 75: RX CLK Receive Clock 76: TX CLK Transmitter Clock 77: RTS Request To Send 78: TX DATA Transmitter Data 79: IRQ Interrupt Request 80: CS 0,1,2 Chip Select 81: RS Register Select 82: Vcc Voltage 83: R/W Read/Write 84: E Enable 85: D0-D7 Data 86: DCD Data Carrier Detect 87: CTS Clear To Send 88: 89: Registers:- 90: 0xfffc00 Keyboard ACIA Control (write)/Status(read) 91: 0xfffc02 Keyboard ACIA Data 92: 0xfffc04 MIDI ACIA Control (write)/Status(read) 93: 0xfffc06 MIDI ACIA Data 94: 95: Control Register (0xfffc00 write):- 96: Bits 0,1 - These bits determine by which factor the transmitter and receiver 97: clock will be divided. These bits also are joined with a master reset 98: function. The 6850 has no separate reset line, so it must be 99: accomplished though software. 100: 0 0 RXCLK/TXCLK without division 101: 0 1 RXCLK/TXCLK by 16 (MIDI) 102: 1 0 RXCLK/TXCLK by 64 (Keyboard) 103: 1 1 Master RESET 104: Bits 2,3,4 - These so-called Word Select bits tell whether 7 or 8 data-bits are 105: involved; whether 1 or 2 stop-bits are transferred; and the type of parity 106: Bits 5,6 - These Transmitter Control bits set the RTS output pin, and allow or prevent 107: an interrupt through the ACIA when the send register is emptied. Also, BREAK signals 108: can be sent over the serial output by this line. A BREAK signal is nothing more than 109: a long seqence of null bits 110: 0 0 RTS low, transmitter IRQ disabled 111: 0 1 RTS low, transmitter IRQ enabled 112: 1 0 RTS high, transmitter IRQ disabled 113: 1 1 RTS low, transmitter IRQ disabled, BREAK sent 114: Bit 7 - The Receiver Interrupt Enable bit determines whether the receiver interrupt 115: will be on. An interrupt can be caused by the DCD line chaning from low to high, or 116: by the receiver data buffer filling. Besides that, an interrupt can occur from an 117: OVERRUN ( a received character isn't properly read from the processior). 118: 0 Interrupt disabled 119: 1 Interrupt enabled 120: 121: Status Register (0xfffc00 read):- 122: Bit 0 - When this bit is high, the RX data register is full. The byte must be read 123: before a new character is received (otherwise an OVERRUN happens) 124: Bit 1 - This bit reflects the status of the TX data buffer. An empty register 125: set the bit. 126: Bit 2 - A low-high change in pin DCD sets bit 2. If the receiver interrupt is allowable, the IRQ 127: is cancelled. The bit is cleared when the status register and the receiver register are 128: read. This also cancels the IRQ. Bit 2 register remains highis the signal on the DCD pin 129: is still high; Bit 2 register low if DCD becomes low. 130: Bit 3 - This line shows the status of CTS. This signal cannot be altered by a mater reset, 131: or by ACIA programming. 132: Bit 4 - Shows 'Frame Errors'. Frame errors are when no stop-bit is recognized in receiver 133: switching. It can be set with every new character. 134: Bit 5 - This bit display the previously mentioned OVERRUN condition. Bit 5 is reset when the 135: RX buffer is read. 136: Bit 6 - This bit recognizes whether the parity of a received character is correct. The bit is 137: set on an error. 138: Bit 7 - This signals the state of the IRQ pins; this bit make it possible to switch several 139: IRQ lines on one interrupt input. In cases where an interrupt is program-generated, bit 7 140: can tell which IC cut off the interrupt. 141: 142: ST ACIA:- 143: Note CTS,DCD and RTS are not connected! Phew! 144: The keyboard ACIA are address 0xfffc000 and 0xfffc02. 145: Default parameters are :- 8-bit word, 1 stopbit, no parity, 77812.5 baud; 500KHz/64 (keyboard clock div) 146: Default MIDI parameters are are above but :- 31250 baud; 500KHz/16 (MIDI clock div) 147: */ 148: 1.1.1.2 root 149: /* List of possible keyboard commands, others are seen as NOPs by keyboard processor */ 1.1 root 150: IKBD_COMMAND_PARAMS KeyboardCommands[] = { 1.1.1.2 root 151: /* Known messages, counts include command byte */ 1.1.1.5 root 152: { 0x80,2, IKBD_Cmd_Reset }, 153: { 0x07,2, IKBD_Cmd_MouseAction }, 154: { 0x08,1, IKBD_Cmd_RelMouseMode }, 155: { 0x09,5, IKBD_Cmd_AbsMouseMode }, 156: { 0x0A,3, IKBD_Cmd_MouseCursorKeycodes }, 157: { 0x0B,3, IKBD_Cmd_SetMouseThreshold }, 158: { 0x0C,3, IKBD_Cmd_SetMouseScale }, 159: { 0x0D,1, IKBD_Cmd_ReadAbsMousePos }, 160: { 0x0E,6, IKBD_Cmd_SetInternalMousePos }, 161: { 0x0F,1, IKBD_Cmd_SetYAxisDown }, 162: { 0x10,1, IKBD_Cmd_SetYAxisUp }, 163: { 0x11,1, IKBD_Cmd_StartKeyboardTransfer }, 164: { 0x12,1, IKBD_Cmd_TurnMouseOff }, 165: { 0x13,1, IKBD_Cmd_StopKeyboardTransfer }, 166: { 0x14,1, IKBD_Cmd_ReturnJoystickAuto }, 167: { 0x15,1, IKBD_Cmd_StopJoystick }, 168: { 0x16,1, IKBD_Cmd_ReturnJoystick }, 169: { 0x17,2, IKBD_Cmd_SetJoystickDuration }, 170: { 0x18,1, IKBD_Cmd_SetJoystickFireDuration }, 171: { 0x19,7, IKBD_Cmd_SetCursorForJoystick }, 172: { 0x1A,1, IKBD_Cmd_DisableJoysticks }, 173: { 0x1B,7, IKBD_Cmd_SetClock }, 174: { 0x1C,1, IKBD_Cmd_ReadClock }, 175: { 0x20,4, IKBD_Cmd_LoadMemory }, 176: { 0x21,3, IKBD_Cmd_ReadMemory }, 177: { 0x22,3, IKBD_Cmd_Execute }, 1.1 root 178: 1.1.1.2 root 179: /* Report message (top bit set) - ignore for now... */ 1.1.1.5 root 180: { 0x88,1, IKBD_Cmd_NullFunction }, 181: { 0x89,1, IKBD_Cmd_NullFunction }, 182: { 0x8A,1, IKBD_Cmd_NullFunction }, 183: { 0x8B,1, IKBD_Cmd_NullFunction }, 184: { 0x8C,1, IKBD_Cmd_NullFunction }, 185: { 0x8F,1, IKBD_Cmd_NullFunction }, 186: { 0x90,1, IKBD_Cmd_NullFunction }, 187: { 0x92,1, IKBD_Cmd_NullFunction }, 188: { 0x94,1, IKBD_Cmd_NullFunction }, 189: { 0x95,1, IKBD_Cmd_NullFunction }, 190: { 0x99,1, IKBD_Cmd_NullFunction }, 1.1 root 191: 1.1.1.5 root 192: { 0xFF,0, NULL } /* Term */ 1.1 root 193: }; 194: 1.1.1.2 root 195: 196: /*-----------------------------------------------------------------------*/ 1.1 root 197: /* 198: Reset the IKBD processor 199: */ 200: void IKBD_Reset(BOOL bCold) 201: { 1.1.1.2 root 202: /* Reset internal keyboard processor details */ 1.1 root 203: if (bCold) 204: KeyboardProcessor.bReset = FALSE; 205: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL; 206: KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK; 207: 208: KeyboardProcessor.Abs.X = ABS_X_ONRESET; KeyboardProcessor.Abs.Y = ABS_Y_ONRESET; 209: KeyboardProcessor.Abs.MaxX = ABS_MAX_X_ONRESET; KeyboardProcessor.Abs.MaxY = ABS_MAY_Y_ONRESET; 210: KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS; 211: 212: KeyboardProcessor.Mouse.DeltaX = KeyboardProcessor.Mouse.DeltaY = 0; 213: KeyboardProcessor.Mouse.XScale = KeyboardProcessor.Mouse.YScale = 0; 214: KeyboardProcessor.Mouse.XThreshold = KeyboardProcessor.Mouse.YThreshold = 1; 1.1.1.2 root 215: KeyboardProcessor.Mouse.YAxis = 1; /* Y origin at top */ 1.1 root 216: KeyboardProcessor.Mouse.Action = 0; 217: 218: KeyboardProcessor.Joy.PrevJoyData[0] = KeyboardProcessor.Joy.PrevJoyData[1] = 0; 219: 1.1.1.2 root 220: /* Reset our ACIA status */ 1.1 root 221: bByteInTransitToACIA = FALSE; 222: ACIAControlRegister = 0; 223: ACIAStatusRegister = ACIA_STATUS_REGISTER__TX_BUFFER_EMPTY; 1.1.1.2 root 224: /* And our keyboard states and clear key state table */ 1.1 root 225: Keyboard.BufferHead = Keyboard.BufferTail = 0; 226: Keyboard.nBytesInInputBuffer = 0; 227: Memory_Clear(Keyboard.KeyStates,sizeof(Keyboard.KeyStates)); 228: Keyboard.bLButtonDown = BUTTON_NULL; 229: Keyboard.bRButtonDown = BUTTON_NULL; 230: Keyboard.bOldLButtonDown = Keyboard.bOldRButtonDown = BUTTON_NULL; 231: Keyboard.LButtonDblClk = Keyboard.RButtonDblClk = 0; 232: Keyboard.LButtonHistory = Keyboard.RButtonHistory = 0; 233: 1.1.1.6 ! root 234: /* Store BOOL for when disable mouse or joystick */ ! 235: bMouseDisabled = bJoystickDisabled = FALSE; ! 236: /* do emulate hardware 'quirk' where if disable both with 'x' time of a RESET ! 237: * command they are ignored! */ ! 238: bDuringResetCriticalTime = bDontDuplicateFire = FALSE; 1.1 root 239: } 240: 1.1.1.2 root 241: 242: /*-----------------------------------------------------------------------*/ 1.1 root 243: /* 244: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type) 245: */ 246: void IKBD_MemorySnapShot_Capture(BOOL bSave) 247: { 1.1.1.2 root 248: /* Save/Restore details */ 1.1 root 249: MemorySnapShot_Store(&Keyboard,sizeof(Keyboard)); 250: MemorySnapShot_Store(&KeyboardProcessor,sizeof(KeyboardProcessor)); 251: MemorySnapShot_Store(&ACIAControlRegister,sizeof(ACIAControlRegister)); 252: MemorySnapShot_Store(&ACIAStatusRegister,sizeof(ACIAStatusRegister)); 253: MemorySnapShot_Store(&ACIAByte,sizeof(ACIAByte)); 254: MemorySnapShot_Store(&bByteInTransitToACIA,sizeof(bByteInTransitToACIA)); 255: } 256: 1.1.1.2 root 257: 258: /*-----------------------------------------------------------------------*/ 1.1 root 259: /* 260: Calculate out 'delta' that mouse has moved by each frame, and add this to our internal keyboard position 261: */ 262: void IKBD_UpdateInternalMousePosition(void) 263: { 264: 1.1.1.4 root 265: KeyboardProcessor.Mouse.DeltaX = KeyboardProcessor.Mouse.dx; 266: KeyboardProcessor.Mouse.DeltaY = KeyboardProcessor.Mouse.dy; 267: KeyboardProcessor.Mouse.dx = 0; 268: KeyboardProcessor.Mouse.dy = 0; 1.1 root 269: 1.1.1.2 root 270: /* Update internal mouse coords - Y axis moves according to YAxis setting(up/down) */ 271: /* Limit to Max X/Y(inclusive) */ 1.1 root 272: KeyboardProcessor.Abs.X += KeyboardProcessor.Mouse.DeltaX; 273: if (KeyboardProcessor.Abs.X<0) 274: KeyboardProcessor.Abs.X = 0; 275: if (KeyboardProcessor.Abs.X>KeyboardProcessor.Abs.MaxX) 276: KeyboardProcessor.Abs.X = KeyboardProcessor.Abs.MaxX; 1.1.1.4 root 277: 1.1.1.2 root 278: KeyboardProcessor.Abs.Y += KeyboardProcessor.Mouse.DeltaY*KeyboardProcessor.Mouse.YAxis; /* Needed '+' for Falcon... */ 1.1 root 279: if (KeyboardProcessor.Abs.Y<0) 280: KeyboardProcessor.Abs.Y = 0; 281: if (KeyboardProcessor.Abs.Y>KeyboardProcessor.Abs.MaxY) 282: KeyboardProcessor.Abs.Y = KeyboardProcessor.Abs.MaxY; 1.1.1.4 root 283: 1.1 root 284: } 285: 1.1.1.2 root 286: 287: /*-----------------------------------------------------------------------*/ 1.1 root 288: /* 289: When running in maximum speed the emulation will not see 'double-clicks' of the mouse 290: as it is running so fast. In this case, we check for a Windows double-click and pass 291: the 'up'/'down' messages in emulation time to simulate the double-click effect! 292: */ 293: void IKBD_CheckForDoubleClicks(void) 294: { 1.1.1.3 root 295: /* 296: Things get a little complicated when running max speed as a normal 297: double-click is a load of 1's, followed by 0's, 1's and 0's - But the ST does 298: not see this as a double click as the space in 'ST' time between changes is so great. 299: Now, when we see a real double-click in max speed we actually send the down/up/down/up 300: in ST time. To get this correct(and not send three clicks) we look in a history buffer 301: and start at an index which gives the correct number of clicks! Phew! 302: */ 1.1 root 303: 1.1.1.2 root 304: /* Handle double clicks!!! */ 1.1 root 305: if (Keyboard.LButtonDblClk) { 306: if (Keyboard.LButtonDblClk==1) { /* First pressed! */ 307: if ((Keyboard.LButtonHistory&0x3f)==0) /* If not pressed button in long time do full dbl-click pattern */ 308: Keyboard.LButtonDblClk = 1; 309: else { 310: Keyboard.LButtonDblClk = 4; /* Otherwise, check where to begin to give 1111000011110000 pattern */ 311: if ((Keyboard.LButtonHistory&0x7)==0) 312: Keyboard.LButtonDblClk = 8; 313: else if ((Keyboard.LButtonHistory&0x3)==0) 314: Keyboard.LButtonDblClk = 7; 315: else if ((Keyboard.LButtonHistory&0x1)==0) 316: Keyboard.LButtonDblClk = 6; 317: } 318: } 319: 320: Keyboard.bLButtonDown = DoubleClickPattern[Keyboard.LButtonDblClk]; 321: Keyboard.LButtonDblClk++; 322: if (Keyboard.LButtonDblClk>=13) { /* Check for end of sequence */ 323: Keyboard.LButtonDblClk = 0; 324: Keyboard.bLButtonDown = FALSE; 325: } 326: } 327: if (Keyboard.RButtonDblClk) { 328: if (Keyboard.RButtonDblClk==1) { /* First pressed! */ 329: if ((Keyboard.RButtonHistory&0x3f)==0) /* If not pressed button in long time do full dbl-click pattern */ 330: Keyboard.RButtonDblClk = 1; 331: else { 332: Keyboard.RButtonDblClk = 4; /* Otherwise, check where to begin to give 1111000011110000 pattern */ 333: if ((Keyboard.RButtonHistory&0x7)==0) 334: Keyboard.RButtonDblClk = 8; 335: else if ((Keyboard.RButtonHistory&0x3)==0) 336: Keyboard.RButtonDblClk = 7; 337: else if ((Keyboard.RButtonHistory&0x1)==0) 338: Keyboard.RButtonDblClk = 6; 339: } 340: } 341: 342: Keyboard.bRButtonDown = DoubleClickPattern[Keyboard.RButtonDblClk]; 343: Keyboard.RButtonDblClk++; 344: if (Keyboard.RButtonDblClk>=13) { /* Check for end of sequence */ 345: Keyboard.RButtonDblClk = 0; 346: Keyboard.bRButtonDown = FALSE; 347: } 348: } 349: 1.1.1.2 root 350: /* Store presses into history */ 1.1 root 351: Keyboard.LButtonHistory = (Keyboard.LButtonHistory<<1); 352: if (Keyboard.bLButtonDown) 353: Keyboard.LButtonHistory |= 0x1; 354: Keyboard.RButtonHistory = (Keyboard.RButtonHistory<<1); 355: if (Keyboard.bRButtonDown) 356: Keyboard.RButtonHistory |= 0x1; 357: } 358: 1.1.1.2 root 359: 360: /*-----------------------------------------------------------------------*/ 1.1 root 361: /* 362: Convert button to BOOL value 363: */ 364: BOOL IKBD_ButtonBool(int Button) 365: { 1.1.1.2 root 366: /* Button pressed? */ 1.1 root 367: if (Button) 368: return(TRUE); 369: return(FALSE); 370: } 371: 1.1.1.2 root 372: 373: /*-----------------------------------------------------------------------*/ 1.1 root 374: /* 375: Return TRUE if buttons match, use this as buttons are a mask and not BOOLean 376: */ 377: BOOL IKBD_ButtonsEqual(int Button1,int Button2) 378: { 1.1.1.2 root 379: /* Return BOOL compare */ 1.1 root 380: return(IKBD_ButtonBool(Button1)==IKBD_ButtonBool(Button2)); 381: } 382: 1.1.1.2 root 383: 384: /*-----------------------------------------------------------------------*/ 1.1 root 385: /* 386: According to if the mouse if enabled or not the joystick 1 fire button/right mouse button 387: will become the same button, ie pressing one will also press the other and vise-versa 388: */ 389: void IKBD_DuplicateMouseFireButtons(void) 390: { 1.1.1.6 ! root 391: /* Don't duplicate fire button when program tries to use both! */ ! 392: if(bDontDuplicateFire) return; ! 393: 1.1.1.2 root 394: /* If mouse is off then joystick fire button goes to joystick */ 1.1.1.6 ! root 395: if (KeyboardProcessor.MouseMode==AUTOMODE_OFF) ! 396: { 1.1.1.2 root 397: /* If pressed right mouse button, should go to joystick 1 */ 1.1 root 398: if (Keyboard.bRButtonDown&BUTTON_MOUSE) 399: KeyboardProcessor.Joy.JoyData[1] |= 0x80; 1.1.1.2 root 400: /* And left mouse button, should go to joystick 0 */ 1.1 root 401: if (Keyboard.bLButtonDown&BUTTON_MOUSE) 402: KeyboardProcessor.Joy.JoyData[0] |= 0x80; 403: } 1.1.1.2 root 404: /* If mouse if on, joystick 1 fire button goes to mouse not to the joystick */ 1.1.1.6 ! root 405: else ! 406: { 1.1.1.2 root 407: /* Is fire button pressed? */ 1.1.1.6 ! root 408: if (KeyboardProcessor.Joy.JoyData[1]&0x80) ! 409: { 1.1.1.2 root 410: KeyboardProcessor.Joy.JoyData[1] &= 0x7f; /* Clear fire button bit */ 411: Keyboard.bRButtonDown |= BUTTON_JOYSTICK; /* Mimick on mouse right button */ 1.1 root 412: } 413: else 414: Keyboard.bRButtonDown &= ~BUTTON_JOYSTICK; 415: } 416: } 417: 1.1.1.2 root 418: 419: /*-----------------------------------------------------------------------*/ 1.1 root 420: /* 421: Send 'relative' mouse position 422: */ 423: void IKBD_SendRelMousePacket(void) 424: { 425: int ByteRelX,ByteRelY; 426: unsigned char Header; 427: 428: if ( (KeyboardProcessor.Mouse.DeltaX!=0) || (KeyboardProcessor.Mouse.DeltaY!=0) 429: || (!IKBD_ButtonsEqual(Keyboard.bOldLButtonDown,Keyboard.bLButtonDown)) || (!IKBD_ButtonsEqual(Keyboard.bOldRButtonDown,Keyboard.bRButtonDown)) ) { 1.1.1.2 root 430: /* Send packet to keyboard process */ 1.1 root 431: while(TRUE) { 432: ByteRelX = KeyboardProcessor.Mouse.DeltaX; 433: if (ByteRelX>127) ByteRelX = 127; 434: if (ByteRelX<-128) ByteRelX = -128; 435: ByteRelY = KeyboardProcessor.Mouse.DeltaY; 436: if (ByteRelY>127) ByteRelY = 127; 437: if (ByteRelY<-128) ByteRelY = -128; 438: 439: Header = 0xf8; 440: if (Keyboard.bLButtonDown) 441: Header |= 0x02; 442: if (Keyboard.bRButtonDown) 443: Header |= 0x01; 444: IKBD_AddKeyToKeyboardBuffer(Header); 445: IKBD_AddKeyToKeyboardBuffer(ByteRelX); 446: IKBD_AddKeyToKeyboardBuffer(ByteRelY*KeyboardProcessor.Mouse.YAxis); 447: 448: KeyboardProcessor.Mouse.DeltaX -= ByteRelX; 449: KeyboardProcessor.Mouse.DeltaY -= ByteRelY; 450: 451: if ( (KeyboardProcessor.Mouse.DeltaX==0) && (KeyboardProcessor.Mouse.DeltaY==0) ) 452: break; 453: 1.1.1.2 root 454: /* Store buttons for next time around */ 1.1 root 455: Keyboard.bOldLButtonDown = Keyboard.bLButtonDown; 456: Keyboard.bOldRButtonDown = Keyboard.bRButtonDown; 457: } 458: } 459: } 460: 1.1.1.2 root 461: 462: /*-----------------------------------------------------------------------*/ 1.1 root 463: /* 464: Send 'joysticks' bit masks 465: */ 466: void IKBD_SelAutoJoysticks(void) 467: { 468: unsigned char JoyData; 469: 1.1.1.2 root 470: /* Did joystick 0/mouse change? */ 1.1 root 471: JoyData = KeyboardProcessor.Joy.JoyData[0]; 472: if (JoyData!=KeyboardProcessor.Joy.PrevJoyData[0]) { 1.1.1.2 root 473: IKBD_AddKeyToKeyboardBuffer(0xFE); /* Joystick 0/Mouse */ 1.1 root 474: IKBD_AddKeyToKeyboardBuffer(JoyData); 475: 476: KeyboardProcessor.Joy.PrevJoyData[0] = JoyData; 477: } 478: 1.1.1.2 root 479: /* Did joystick 1(default) change? */ 1.1 root 480: JoyData = KeyboardProcessor.Joy.JoyData[1]; 481: if (JoyData!=KeyboardProcessor.Joy.PrevJoyData[1]) { 1.1.1.2 root 482: IKBD_AddKeyToKeyboardBuffer(0xFF); /* Joystick 1 */ 1.1 root 483: IKBD_AddKeyToKeyboardBuffer(JoyData); 484: 485: KeyboardProcessor.Joy.PrevJoyData[1] = JoyData; 486: } 487: } 488: 489: /*-----------------------------------------------------------------------*/ 490: /* 491: Send packets which are generated from the mouse action settings 492: If relative mode is on, still generate these packets 493: */ 494: void IKBD_SendOnMouseAction(void) 495: { 496: BOOL bReportPosition = FALSE; 497: 498: /* Report buttons as keys? Do in relative/absolute mode */ 499: if (KeyboardProcessor.Mouse.Action&0x4) { 500: /* Left button? */ 501: if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) ) 502: IKBD_AddKeyToKeyboardBuffer(0x74); /* Left */ 503: else if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) ) 504: IKBD_AddKeyToKeyboardBuffer(0x74|0x80); 505: /* Right button? */ 506: if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) ) 507: IKBD_AddKeyToKeyboardBuffer(0x75); /* Right */ 508: else if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) ) 509: IKBD_AddKeyToKeyboardBuffer(0x75|0x80); 510: 511: /* Ignore bottom two bits, so return now */ 512: return; 513: } 514: 515: /* Check MouseAction - report position on press/release */ 516: /* MUST do this before update relative positions as buttons get reset */ 517: if (KeyboardProcessor.Mouse.Action&0x3) { 518: /* Check for 'press'? */ 519: if (KeyboardProcessor.Mouse.Action&0x1) { 520: /* Did 'press' mouse buttons? */ 521: if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) ) { 522: bReportPosition = TRUE; 523: KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x04; 524: KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x02; 525: } 526: if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) ) { 527: bReportPosition = TRUE; 528: KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x01; 529: KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x08; 530: } 531: } 532: /* Check for 'release'? */ 533: if (KeyboardProcessor.Mouse.Action&0x2) { 534: /* Did 'release' mouse buttons? */ 535: if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) ) { 536: bReportPosition = TRUE; 537: KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x08; 538: KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x01; 539: } 540: if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) ) { 541: bReportPosition = TRUE; 542: KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x02; 543: KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x04; 544: } 545: } 546: 547: /* Do need to report? */ 548: if (bReportPosition) { 549: /* Only report if mouse in absolute mode */ 550: if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSEABS) { 551: #ifdef DEBUG_OUTPUT_IKBD 552: Debug_IKBD("Report ABS on MouseAction\n"); 553: #endif 554: IKBD_Cmd_ReadAbsMousePos(); 555: } 556: } 557: } 558: } 559: 1.1.1.2 root 560: 561: /*-----------------------------------------------------------------------*/ 1.1 root 562: /* 563: Send mouse movements as cursor keys 564: */ 565: void IKBD_SendCursorMousePacket(void) 566: { 567: int i=0; 568: 1.1.1.2 root 569: /* Run each 'Delta' as cursor presses */ 570: /* Limit to '10' loops as Windows cursor is a VERY poor quality. Eg, a single mouse movement */ 571: /* on and ST gives delta's of '1', mostly, but Windows goes as high as 20+! */ 1.1 root 572: while ( (i<10) && ((KeyboardProcessor.Mouse.DeltaX!=0) || (KeyboardProcessor.Mouse.DeltaY!=0) 573: || (!IKBD_ButtonsEqual(Keyboard.bOldLButtonDown,Keyboard.bLButtonDown)) || (!IKBD_ButtonsEqual(Keyboard.bOldRButtonDown,Keyboard.bRButtonDown))) ) { 1.1.1.2 root 574: /* Left? */ 1.1 root 575: if (KeyboardProcessor.Mouse.DeltaX<0) { 1.1.1.2 root 576: IKBD_AddKeyToKeyboardBuffer(75); /* Left cursor */ 1.1 root 577: IKBD_AddKeyToKeyboardBuffer(75|0x80); 578: KeyboardProcessor.Mouse.DeltaX++; 579: } 1.1.1.2 root 580: /* Right? */ 1.1 root 581: if (KeyboardProcessor.Mouse.DeltaX>0) { 1.1.1.2 root 582: IKBD_AddKeyToKeyboardBuffer(77); /* Right cursor */ 1.1 root 583: IKBD_AddKeyToKeyboardBuffer(77|0x80); 584: KeyboardProcessor.Mouse.DeltaX--; 585: } 1.1.1.2 root 586: /* Up? */ 1.1 root 587: if (KeyboardProcessor.Mouse.DeltaY<0) { 1.1.1.2 root 588: IKBD_AddKeyToKeyboardBuffer(72); /* Up cursor */ 1.1 root 589: IKBD_AddKeyToKeyboardBuffer(72|0x80); 590: KeyboardProcessor.Mouse.DeltaY++; 591: } 1.1.1.2 root 592: /* Down? */ 1.1 root 593: if (KeyboardProcessor.Mouse.DeltaY>0) { 1.1.1.2 root 594: IKBD_AddKeyToKeyboardBuffer(80); /* Down cursor */ 1.1 root 595: IKBD_AddKeyToKeyboardBuffer(80|0x80); 596: KeyboardProcessor.Mouse.DeltaY--; 597: } 598: 1.1.1.2 root 599: /* Left button? */ 1.1 root 600: if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) ) 1.1.1.2 root 601: IKBD_AddKeyToKeyboardBuffer(0x74); /* Left */ 1.1 root 602: else if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) ) 603: IKBD_AddKeyToKeyboardBuffer(0x74|0x80); 1.1.1.2 root 604: /* Right button? */ 1.1 root 605: if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) ) 1.1.1.2 root 606: IKBD_AddKeyToKeyboardBuffer(0x75); /* Right */ 1.1 root 607: else if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) ) 608: IKBD_AddKeyToKeyboardBuffer(0x75|0x80); 609: 610: Keyboard.bOldLButtonDown = Keyboard.bLButtonDown; 611: Keyboard.bOldRButtonDown = Keyboard.bRButtonDown; 612: 1.1.1.2 root 613: /* Count, so exit if try too many times! */ 1.1 root 614: i++; 615: } 616: } 617: 1.1.1.2 root 618: 619: /*-----------------------------------------------------------------------*/ 1.1 root 620: /* 621: Return packets from keyboard for auto, rel mouse, joystick etc... 622: */ 623: void IKBD_SendAutoKeyboardCommands(void) 624: { 625: /* Ignore anything until we've redirected our GEM handlers */ 1.1.1.3 root 626: if (!bInitGemDOS) 627: return; 1.1.1.2 root 628: 1.1 root 629: /* Don't do anything until processor is first reset */ 630: if (!KeyboardProcessor.bReset) 631: return; 632: 633: /* Read joysticks for this frame */ 634: /* If mouse is on, joystick 0 is not connected */ 635: KeyboardProcessor.Joy.JoyData[0] = (KeyboardProcessor.MouseMode==AUTOMODE_OFF) ? Joy_GetStickData(0):0x00; 636: KeyboardProcessor.Joy.JoyData[1] = Joy_GetStickData(1); 637: 638: /* Check for double-clicks in maximum speed mode */ 639: IKBD_CheckForDoubleClicks(); 640: 641: /* Handle Joystick/Mouse fire buttons */ 642: IKBD_DuplicateMouseFireButtons(); 643: 644: /* Send any packets which are to be reported by mouse action */ 645: IKBD_SendOnMouseAction(); 646: 647: /* Update internal mouse absolute position by find 'delta' of mouse movement */ 648: IKBD_UpdateInternalMousePosition(); 649: 650: /* Send automatic joystick packets */ 651: if (KeyboardProcessor.JoystickMode==AUTOMODE_JOYSTICK) 652: IKBD_SelAutoJoysticks(); 653: /* Send automatic relative mouse positions(absolute are not send automatically) */ 654: if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSEREL) 655: IKBD_SendRelMousePacket(); 656: /* Send cursor key directions for movements */ 657: else if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSECURSOR) 658: IKBD_SendCursorMousePacket(); 659: 660: /* Store buttons for next time around */ 661: Keyboard.bOldLButtonDown = Keyboard.bLButtonDown; 662: Keyboard.bOldRButtonDown = Keyboard.bRButtonDown; 663: 664: /* Send joystick button '2' as 'Space bar' key - MUST do here so does not get mixed up in middle of joystick packets! */ 665: if (JoystickSpaceBar) { 666: /* As we simulating space bar? */ 667: if (JoystickSpaceBar==JOYSTICK_SPACE_DOWN) { 1.1.1.2 root 668: IKBD_PressSTKey(57,TRUE); /* Press */ 1.1 root 669: JoystickSpaceBar = JOYSTICK_SPACE_UP; 670: } 671: else { //if (JoystickSpaceBar==JOYSTICK_SPACE_UP) { 1.1.1.2 root 672: IKBD_PressSTKey(57,FALSE); /* Release */ 673: JoystickSpaceBar = FALSE; /* Complete */ 1.1 root 674: } 675: } 676: } 677: 1.1.1.2 root 678: 679: /*-----------------------------------------------------------------------*/ 1.1 root 680: /* 681: On ST if disable Mouse AND Joystick with a set time of a RESET command they are 682: actually turned back on! (A number of games do this so can get mouse and joystick 683: packets at the same time) 684: */ 685: void IKBD_CheckResetDisableBug(void) 686: { 687: /* Have disabled BOTH mouse and joystick? */ 1.1.1.6 ! root 688: if (bMouseDisabled && bJoystickDisabled) ! 689: { 1.1 root 690: /* And in critical time? */ 1.1.1.6 ! root 691: if (bDuringResetCriticalTime) ! 692: { 1.1 root 693: /* Emulate relative mouse and joystick reports being turned back on */ 694: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL; 695: KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK; 1.1.1.6 ! root 696: bDontDuplicateFire = TRUE; ! 697: 1.1 root 698: #ifdef DEBUG_OUTPUT_IKBD 699: Debug_IKBD("IKBD Mouse+Joystick disabled during RESET. Revert.\n"); 700: Debugger_TabIKBD_AddListViewItem("( Mouse+Joystick disabled during RESET. Revert. )"); 701: #endif 702: } 703: } 704: } 705: 1.1.1.2 root 706: 707: /*-----------------------------------------------------------------------*/ 1.1 root 708: /* 709: Start timer after keyboard RESET command to emulate 'quirk' 710: If some IKBD commands are sent during time after a RESET they may be ignored 711: */ 712: void IKBD_InterruptHandler_ResetTimer(void) 713: { 1.1.1.2 root 714: /* Remove this interrupt from list and re-order */ 1.1 root 715: Int_AcknowledgeInterrupt(); 716: 1.1.1.2 root 717: /* Critical timer is over */ 1.1 root 718: bDuringResetCriticalTime = FALSE; 719: } 720: 721: 722: 1.1.1.2 root 723: /*-----------------------------------------------------------------------*/ 1.1 root 724: /* 725: List of keyboard commands 726: */ 727: 728: 1.1.1.2 root 729: /*-----------------------------------------------------------------------*/ 1.1 root 730: /* 731: Blank function for some keyboard commands - this can be used to find errors 732: */ 733: void IKBD_Cmd_NullFunction(void) 734: { 735: #ifdef DEBUG_OUTPUT_IKBD 736: Debug_IKBD("IKBD_Cmd_NullFunction\n"); 737: Debugger_TabIKBD_AddListViewItem("( NullFunction )"); 738: #endif 739: } 740: 1.1.1.2 root 741: 742: /*-----------------------------------------------------------------------*/ 1.1 root 743: /* 744: RESET 745: 746: 0x80 747: 0x01 748: 749: Performs self test and checks for stuck (closed) keys, if OK returns 0xF0. Otherwise 750: returns break codes for keys 751: */ 752: void IKBD_Cmd_Reset(void) 753: { 754: /* Check for error series of bytes, eg 0x80,0x01 */ 755: if (Keyboard.InputBuffer[1]==0x01) { 756: #ifdef DEBUG_OUTPUT_IKBD 757: Debug_IKBD("KEYBOARD ON\n"); 758: #endif 759: KeyboardProcessor.bReset = TRUE; /* Turn processor on; can now process commands */ 760: 761: /* Set defaults */ 762: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL; 763: KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK; 764: KeyboardProcessor.Abs.X = ABS_X_ONRESET; KeyboardProcessor.Abs.Y = ABS_Y_ONRESET; 765: KeyboardProcessor.Abs.MaxX = ABS_MAX_X_ONRESET; KeyboardProcessor.Abs.MaxY = ABS_MAY_Y_ONRESET; 766: KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS; 767: 768: IKBD_AddKeyToKeyboardBuffer(0xF0); /* Assume OK, return correct code */ 769: 770: /* Start timer - some commands are send during this time they may be ignored(see real ST!) */ 771: Int_AddRelativeInterrupt(IKBD_RESET_CYCLES,INTERRUPT_IKBD_RESETTIMER); 772: /* Set this 'critical' flag, gets reset when timer expires */ 773: bMouseDisabled = bJoystickDisabled = FALSE; 774: bDuringResetCriticalTime = TRUE; 1.1.1.6 ! root 775: bDontDuplicateFire = FALSE; 1.1 root 776: } 777: /* else if not 0x80,0x01 just ignore */ 778: #ifdef DEBUG_OUTPUT_IKBD 779: Debug_IKBD("IKBD_Cmd_Reset\n"); 780: Debugger_TabIKBD_AddListViewItem("RESET"); 781: #endif 782: } 783: 1.1.1.2 root 784: 785: /*-----------------------------------------------------------------------*/ 1.1 root 786: /* 787: SET MOUSE BUTTON ACTION 788: 789: 0x07 790: %00000mss ; mouse button action 791: ; (m is presumed =1 when in MOUSE KEYCODE mode) 792: ; mss=0xy, mouse button press or release causes mouse 793: ; position report 794: ; where y=1, mouse key press causes absolute report 795: ; and x=1, mouse key release causes absolute report 796: ; mss=100, mouse buttons act like keys 797: */ 798: void IKBD_Cmd_MouseAction(void) 799: { 800: KeyboardProcessor.Mouse.Action = Keyboard.InputBuffer[1]; 801: KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS; 802: #ifdef DEBUG_OUTPUT_IKBD 803: Debug_IKBD("IKBD_Cmd_MouseAction %d\n",(unsigned int)KeyboardProcessor.Mouse.Action); 804: Debugger_TabIKBD_AddListViewItem("MouseAction %d",(unsigned int)KeyboardProcessor.Mouse.Action); 805: #endif 806: } 807: 1.1.1.2 root 808: 809: /*-----------------------------------------------------------------------*/ 1.1 root 810: /* 811: SET RELATIVE MOUSE POSITION REPORTING 812: 813: 0x08 814: */ 815: void IKBD_Cmd_RelMouseMode(void) 816: { 817: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL; 818: #ifdef DEBUG_OUTPUT_IKBD 819: Debug_IKBD("IKBD_Cmd_RelMouseMode\n"); 820: Debugger_TabIKBD_AddListViewItem("RelMouseMode"); 821: #endif 822: } 823: 1.1.1.2 root 824: 825: /*-----------------------------------------------------------------------*/ 1.1 root 826: /* 827: SET ABSOLUTE MOUSE POSITIONING 828: 829: 0x09 830: XMSB ;X maximum (in scaled mouse clicks) 831: XLSB 832: YMSB ;Y maximum (in scaled mouse clicks) 833: YLSB 834: */ 835: void IKBD_Cmd_AbsMouseMode(void) 836: { 837: /* These maximums are 'inclusive' */ 838: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEABS; 839: KeyboardProcessor.Abs.MaxX = (((unsigned int)Keyboard.InputBuffer[1])<<8) | (unsigned int)Keyboard.InputBuffer[2]; 840: KeyboardProcessor.Abs.MaxY = (((unsigned int)Keyboard.InputBuffer[3])<<8) | (unsigned int)Keyboard.InputBuffer[4]; 841: #ifdef DEBUG_OUTPUT_IKBD 842: Debug_IKBD("IKBD_Cmd_AbsMouseMode %d,%d\n",KeyboardProcessor.Abs.MaxX,KeyboardProcessor.Abs.MaxY); 843: Debugger_TabIKBD_AddListViewItem("AbsMouseMode %d,%d",KeyboardProcessor.Abs.MaxX,KeyboardProcessor.Abs.MaxY); 844: #endif 845: } 846: 1.1.1.2 root 847: 848: /*-----------------------------------------------------------------------*/ 1.1 root 849: /* 850: SET MOUSE KEYCODE MODE 851: 852: 0x0A 853: deltax ; distance in X clicks to return (LEFT) or (RIGHT) 854: deltay ; distance in Y clicks to return (UP) or (DOWN) 855: */ 856: void IKBD_Cmd_MouseCursorKeycodes(void) 857: { 858: KeyboardProcessor.MouseMode = AUTOMODE_MOUSECURSOR; 859: KeyboardProcessor.Mouse.KeyCodeDeltaX = Keyboard.InputBuffer[1]; 860: KeyboardProcessor.Mouse.KeyCodeDeltaY = Keyboard.InputBuffer[2]; 861: #ifdef DEBUG_OUTPUT_IKBD 862: Debug_IKBD("IKBD_Cmd_MouseCursorKeycodes %d,%d\n",(int)KeyboardProcessor.Mouse.KeyCodeDeltaX,(int)KeyboardProcessor.Mouse.KeyCodeDeltaY); 863: Debugger_TabIKBD_AddListViewItem("MouseCursorKeycodes %d,%d",(int)KeyboardProcessor.Mouse.KeyCodeDeltaX,(int)KeyboardProcessor.Mouse.KeyCodeDeltaY); 864: #endif 865: } 866: 1.1.1.2 root 867: 868: /*-----------------------------------------------------------------------*/ 1.1 root 869: /* 870: SET MOUSE THRESHOLD 871: 872: 0x0B 873: X ; x threshold in mouse ticks (positive integers) 874: Y ; y threshold in mouse ticks (positive integers) 875: */ 876: void IKBD_Cmd_SetMouseThreshold(void) 877: { 878: KeyboardProcessor.Mouse.XThreshold = (unsigned int)Keyboard.InputBuffer[1]; 879: KeyboardProcessor.Mouse.YThreshold = (unsigned int)Keyboard.InputBuffer[2]; 880: #ifdef DEBUG_OUTPUT_IKBD 881: Debug_IKBD("IKBD_Cmd_SetMouseThreshold %d,%d\n",KeyboardProcessor.Mouse.XThreshold,KeyboardProcessor.Mouse.YThreshold); 882: Debugger_TabIKBD_AddListViewItem("SetMouseThreshold %d,%d",KeyboardProcessor.Mouse.XThreshold,KeyboardProcessor.Mouse.YThreshold); 883: #endif 884: } 885: 1.1.1.2 root 886: 887: /*-----------------------------------------------------------------------*/ 1.1 root 888: /* 889: SET MOUSE SCALE 890: 891: 0x0C 892: X ; horizontal mouse ticks per internel X 893: Y ; vertical mouse ticks per internel Y 894: */ 895: void IKBD_Cmd_SetMouseScale(void) 896: { 897: KeyboardProcessor.Mouse.XScale = (unsigned int)Keyboard.InputBuffer[1]; 898: KeyboardProcessor.Mouse.YScale = (unsigned int)Keyboard.InputBuffer[2]; 899: #ifdef DEBUG_OUTPUT_IKBD 900: Debug_IKBD("IKBD_Cmd_SetMouseScale %d,%d\n",KeyboardProcessor.Mouse.XScale,KeyboardProcessor.Mouse.YScale); 901: Debugger_TabIKBD_AddListViewItem("SetMouseScale %d,%d",KeyboardProcessor.Mouse.XScale,KeyboardProcessor.Mouse.YScale); 902: #endif 903: } 904: 905: /*-----------------------------------------------------------------------*/ 906: /* 907: INTERROGATE MOUSE POSITION 908: 909: 0x0D 910: Returns: 0xF7 ; absolute mouse position header 911: BUTTONS 912: 0000dcba 913: where a is right button down since last interrogation 914: b is right button up since last 915: c is left button down since last 916: d is left button up since last 917: XMSB ; X coordinate 918: XLSB 919: YMSB ; Y coordinate 920: YLSB 921: */ 922: void IKBD_Cmd_ReadAbsMousePos(void) 923: { 924: unsigned char Buttons,PrevButtons; 925: 926: /* Test buttons */ 927: Buttons = 0; 928: /* Set buttons to show if up/down */ 929: if (Keyboard.bRButtonDown) 930: Buttons |= 0x01; 931: else 932: Buttons |= 0x02; 933: if (Keyboard.bLButtonDown) 934: Buttons |= 0x04; 935: else 936: Buttons |= 0x08; 937: /* Mask off it didn't send last time */ 938: PrevButtons = KeyboardProcessor.Abs.PrevReadAbsMouseButtons; 939: KeyboardProcessor.Abs.PrevReadAbsMouseButtons = Buttons; 940: Buttons &= ~PrevButtons; 941: 942: /* And send packet */ 943: IKBD_AddKeyToKeyboardBuffer(0xf7); 944: IKBD_AddKeyToKeyboardBuffer(Buttons); 945: IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.X>>8); 946: IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.X&0xff); 947: IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.Y>>8); 948: IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.Y&0xff); 949: 950: #ifdef DEBUG_OUTPUT_IKBD 951: Debug_IKBD("IKBD_Cmd_ReadAbsMousePos %d,%d 0x%X\n",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y,Buttons); 952: Debugger_TabIKBD_AddListViewItem("ReadAbsMousePos %d,%d 0x%X",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y,Buttons); 953: #endif 954: } 955: 956: /*-----------------------------------------------------------------------*/ 957: /* 958: LOAD MOUSE POSITION 959: 960: 0x0E 961: 0x00 ; filler 962: XMSB ; X coordinate 963: XLSB ; (in scaled coordinate system) 964: YMSB ; Y coordinate 965: YLSB 966: */ 967: void IKBD_Cmd_SetInternalMousePos(void) 968: { 969: /* Setting these do not clip internal position(this happens on next update) */ 970: KeyboardProcessor.Abs.X = (((unsigned int)Keyboard.InputBuffer[2])<<8) | (unsigned int)Keyboard.InputBuffer[3]; 971: KeyboardProcessor.Abs.Y = (((unsigned int)Keyboard.InputBuffer[4])<<8) | (unsigned int)Keyboard.InputBuffer[5]; 972: #ifdef DEBUG_OUTPUT_IKBD 973: Debug_IKBD("IKBD_Cmd_SetInternalMousePos %d,%d\n",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y); 974: Debugger_TabIKBD_AddListViewItem("SetInternalMousePos %d,%d",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y); 975: #endif 976: } 977: 1.1.1.2 root 978: 979: /*-----------------------------------------------------------------------*/ 1.1 root 980: /* 981: SET Y=0 AT BOTTOM 982: 983: 0x0F 984: */ 985: void IKBD_Cmd_SetYAxisDown(void) 986: { 987: KeyboardProcessor.Mouse.YAxis = -1; 988: #ifdef DEBUG_OUTPUT_IKBD 989: Debug_IKBD("IKBD_Cmd_SetYAxisDown\n"); 990: Debugger_TabIKBD_AddListViewItem("SetYAxisDown"); 991: #endif 992: } 993: 1.1.1.2 root 994: 995: /*-----------------------------------------------------------------------*/ 1.1 root 996: /* 997: SET Y=0 AT TOP 998: 999: 0x10 1000: */ 1001: void IKBD_Cmd_SetYAxisUp(void) 1002: { 1003: KeyboardProcessor.Mouse.YAxis = 1; 1004: #ifdef DEBUG_OUTPUT_IKBD 1005: Debug_IKBD("IKBD_Cmd_SetYAxisUp\n"); 1006: Debugger_TabIKBD_AddListViewItem("SetYAxisUp"); 1007: #endif 1008: } 1009: 1.1.1.2 root 1010: 1011: /*-----------------------------------------------------------------------*/ 1.1 root 1012: /* 1013: RESUME 1014: 1015: 0x11 1016: */ 1017: void IKBD_Cmd_StartKeyboardTransfer(void) 1018: { 1019: #ifdef DEBUG_OUTPUT_IKBD 1020: Debug_IKBD("IKBD_Cmd_StartKeyboardTransfer\n"); 1021: Debugger_TabIKBD_AddListViewItem("StartKeyboardTransfer"); 1022: #endif 1023: } 1024: 1.1.1.2 root 1025: 1026: /*-----------------------------------------------------------------------*/ 1.1 root 1027: /* 1028: DISABLE MOUSE 1029: 1030: 0x12 1031: */ 1032: void IKBD_Cmd_TurnMouseOff(void) 1033: { 1034: KeyboardProcessor.MouseMode = AUTOMODE_OFF; 1035: bMouseDisabled = TRUE; 1036: #ifdef DEBUG_OUTPUT_IKBD 1037: Debug_IKBD("IKBD_Cmd_TurnMouseOff\n"); 1038: Debugger_TabIKBD_AddListViewItem("TurnMouseOff"); 1039: #endif 1040: 1041: IKBD_CheckResetDisableBug(); 1042: } 1043: 1.1.1.2 root 1044: 1045: /*-----------------------------------------------------------------------*/ 1.1 root 1046: /* 1047: PAUSE OUTPUT 1048: 1049: 0x13 1050: */ 1051: void IKBD_Cmd_StopKeyboardTransfer(void) 1052: { 1053: #ifdef DEBUG_OUTPUT_IKBD 1054: Debug_IKBD("IKBD_Cmd_StopKeyboardTransfer\n"); 1055: Debugger_TabIKBD_AddListViewItem("StopKeyboardTransfer"); 1056: #endif 1057: } 1058: 1.1.1.2 root 1059: 1060: /*-----------------------------------------------------------------------*/ 1.1 root 1061: /* 1062: SET JOYSTICK EVENT REPORTING 1063: 1064: 0x14 1065: */ 1066: void IKBD_Cmd_ReturnJoystickAuto(void) 1067: { 1.1.1.6 ! root 1068: KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK; ! 1069: KeyboardProcessor.MouseMode = AUTOMODE_OFF; ! 1070: ! 1071: /* Again, if try to disable mouse within time of a reset it isn't disabled! */ ! 1072: if (bDuringResetCriticalTime) ! 1073: { ! 1074: KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL; ! 1075: bDontDuplicateFire = TRUE; ! 1076: } ! 1077: 1.1 root 1078: #ifdef DEBUG_OUTPUT_IKBD 1.1.1.6 ! root 1079: Debug_IKBD("IKBD_Cmd_ReturnJoystickAuto\n"); 1.1 root 1080: #endif 1081: } 1082: 1.1.1.2 root 1083: 1084: /*-----------------------------------------------------------------------*/ 1.1 root 1085: /* 1086: SET JOYSTICK INTERROGATION MODE 1087: 1088: 0x15 1089: */ 1090: void IKBD_Cmd_StopJoystick(void) 1091: { 1092: KeyboardProcessor.JoystickMode = AUTOMODE_OFF; 1093: // Debug_IKBD("IKBD_Cmd_StopJoystick\n"); 1094: } 1095: 1.1.1.2 root 1096: 1097: /*-----------------------------------------------------------------------*/ 1.1 root 1098: /* 1099: JOYSTICK INTERROGATE 1100: 1101: 0x16 1102: */ 1103: void IKBD_Cmd_ReturnJoystick(void) 1104: { 1105: IKBD_AddKeyToKeyboardBuffer(0xFD); 1106: IKBD_AddKeyToKeyboardBuffer(Joy_GetStickData(0)); 1107: IKBD_AddKeyToKeyboardBuffer(Joy_GetStickData(1)); 1108: #ifdef DEBUG_OUTPUT_IKBD 1109: Debug_IKBD("IKBD_Cmd_ReturnJoystick\n"); 1110: Debugger_TabIKBD_AddListViewItem("ReturnJoystick"); 1111: #endif 1112: } 1113: 1.1.1.2 root 1114: 1115: /*-----------------------------------------------------------------------*/ 1.1 root 1116: /* 1117: SET JOYSTICK MONITORING 1118: 1119: 0x17 1120: rate ; time between samples in hundreths of a second 1121: Returns: (in packets of two as long as in mode) 1122: %000000xy where y is JOYSTICK1 Fire button 1123: and x is JOYSTICK0 Fire button 1124: %nnnnmmmm where m is JOYSTICK1 state 1125: and n is JOYSTICK0 state 1126: */ 1127: void IKBD_Cmd_SetJoystickDuration(void) 1128: { 1129: #ifdef DEBUG_OUTPUT_IKBD 1130: Debug_IKBD("IKBD_Cmd_SetJoystickDuration\n"); 1131: Debugger_TabIKBD_AddListViewItem("SetJoystickDuration"); 1132: #endif 1133: } 1134: 1.1.1.2 root 1135: 1136: /*-----------------------------------------------------------------------*/ 1.1 root 1137: /* 1138: SET FIRE BUTTON MONITORING 1139: 1140: 0x18 1141: Returns: (as long as in mode) 1142: %bbbbbbbb ; state of the JOYSTICK1 fire button packed 1143: ; 8 bits per byte, the first sample if the MSB 1144: */ 1145: void IKBD_Cmd_SetJoystickFireDuration(void) 1146: { 1147: #ifdef DEBUG_OUTPUT_IKBD 1148: Debug_IKBD("IKBD_Cmd_SetJoystickFireDuration\n"); 1149: Debugger_TabIKBD_AddListViewItem("SetJoystickFireDuration"); 1150: #endif 1151: } 1152: 1.1.1.2 root 1153: 1154: /*-----------------------------------------------------------------------*/ 1.1 root 1155: /* 1156: SET JOYSTICK KEYCODE MODE 1157: 1158: 0x19 1159: RX ; length of time (in tenths of seconds) until 1160: ; horizontal velocity breakpoint is reached 1161: RY ; length of time (in tenths of seconds) until 1162: ; vertical velocity breakpoint is reached 1163: TX ; length (in tenths of seconds) of joystick closure 1164: ; until horizontal cursor key is generated before RX 1165: ; has elapsed 1166: TY ; length (in tenths of seconds) of joystick closure 1167: ; until vertical cursor key is generated before RY 1168: ; has elapsed 1169: VX ; length (in tenths of seconds) of joystick closure 1170: ; until horizontal cursor keystokes are generated after RX 1171: ; has elapsed 1172: VY ; length (in tenths of seconds) of joystick closure 1173: ; until vertical cursor keystokes are generated after RY 1174: ; has elapsed 1175: */ 1176: void IKBD_Cmd_SetCursorForJoystick(void) 1177: { 1178: #ifdef DEBUG_OUTPUT_IKBD 1179: Debug_IKBD("IKBD_Cmd_SetCursorForJoystick\n"); 1180: Debugger_TabIKBD_AddListViewItem("SetCursorForJoystick"); 1181: #endif 1182: } 1183: 1.1.1.2 root 1184: 1185: /*-----------------------------------------------------------------------*/ 1.1 root 1186: /* 1187: DISABLE JOYSTICKS 1188: 1189: 0x1A 1190: */ 1191: void IKBD_Cmd_DisableJoysticks(void) 1192: { 1193: KeyboardProcessor.JoystickMode = AUTOMODE_OFF; 1194: bJoystickDisabled = TRUE; 1195: #ifdef DEBUG_OUTPUT_IKBD 1196: Debug_IKBD("IKBD_Cmd_DisableJoysticks\n"); 1197: Debugger_TabIKBD_AddListViewItem("DisableJoysticks"); 1198: #endif 1199: 1200: IKBD_CheckResetDisableBug(); 1201: } 1202: 1.1.1.2 root 1203: 1204: /*-----------------------------------------------------------------------*/ 1.1 root 1205: /* 1206: TIME-OF-DAY CLOCK SET 1207: 1208: 0x1B 1209: YY ; year (2 least significant digits) 1210: MM ; month 1211: DD ; day 1212: hh ; hour 1213: mm ; minute 1214: ss ; second 1215: */ 1216: void IKBD_Cmd_SetClock(void) 1217: { 1218: #ifdef DEBUG_OUTPUT_IKBD 1219: Debug_IKBD("IKBD_Cmd_SetClock\n"); 1220: Debugger_TabIKBD_AddListViewItem("SetClock"); 1221: #endif 1222: } 1223: 1.1.1.2 root 1224: 1225: /*-----------------------------------------------------------------------*/ 1.1 root 1226: /* 1227: INTERROGATE TIME-OF-DAT CLOCK 1228: 1229: 0x1C 1230: Returns: 1231: 0xFC ; time-of-day event header 1232: YY ; year (2 least significant digits) 1233: MM ; month 1234: DD ; day 1235: hh ; hour 1236: mm ; minute 1237: ss ; second 1238: */ 1239: void IKBD_Cmd_ReadClock(void) 1240: { 1.1.1.6 ! root 1241: struct tm *SystemTime; ! 1242: time_t nTimeTicks; 1.1 root 1243: 1.1.1.6 ! root 1244: /* Get system time */ ! 1245: nTimeTicks = time(NULL); ! 1246: SystemTime = localtime(&nTimeTicks); 1.1 root 1247: 1.1.1.6 ! root 1248: /* Return packet */ 1.1 root 1249: IKBD_AddKeyToKeyboardBuffer(0xFC); 1.1.1.6 ! root 1250: /* Return time-of-day clock as yy-mm-dd-hh-mm-ss as BCD */ ! 1251: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_year%100)); /* yy - year (2 least significant digits) */ ! 1252: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_mon+1)); /* mm - Month */ ! 1253: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_mday)); /* dd - Day */ ! 1254: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_hour)); /* hh - Hour */ ! 1255: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_min)); /* mm - Minute */ ! 1256: IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime->tm_sec)); /* ss - Second */ ! 1257: 1.1 root 1258: #ifdef DEBUG_OUTPUT_IKBD 1259: Debug_IKBD("IKBD_Cmd_ReadClock\n"); 1260: Debugger_TabIKBD_AddListViewItem("ReadClock"); 1261: #endif 1262: } 1263: 1.1.1.2 root 1264: 1265: /*-----------------------------------------------------------------------*/ 1.1 root 1266: /* 1267: MEMORY LOAD 1268: 1269: 0x20 1270: ADRMSB ; address in controller 1271: ADRLSB ; memory to be loaded 1272: NUM ; number of bytes (0-128) 1273: { data } 1274: */ 1275: void IKBD_Cmd_LoadMemory(void) 1276: { 1277: #ifdef DEBUG_OUTPUT_IKBD 1278: Debug_IKBD("IKBD_Cmd_LoadMemory\n"); 1279: Debugger_TabIKBD_AddListViewItem("LoadMemory"); 1280: #endif 1281: } 1282: 1.1.1.2 root 1283: 1284: /*-----------------------------------------------------------------------*/ 1.1 root 1285: /* 1286: MEMORY READ 1287: 1288: 0x21 1289: ADRMSB ; address in controller 1290: ADRLSB ; memory to be read 1291: Returns: 1292: 0xF6 ; status header 1293: 0x20 ; memory access 1294: { data } ; 6 data bytes starting at ADR 1295: */ 1296: void IKBD_Cmd_ReadMemory(void) 1297: { 1298: #ifdef DEBUG_OUTPUT_IKBD 1299: Debug_IKBD("IKBD_Cmd_ReadMemory\n"); 1300: Debugger_TabIKBD_AddListViewItem("ReadMemory"); 1301: #endif 1302: } 1303: 1.1.1.2 root 1304: 1305: /*-----------------------------------------------------------------------*/ 1.1 root 1306: /* 1307: CONTROLLER EXECUTE 1308: 1309: 0x22 1310: ADRMSB ; address of subroutine in 1311: ADRLSB ; controller memory to be called 1312: */ 1313: void IKBD_Cmd_Execute(void) 1314: { 1315: #ifdef DEBUG_OUTPUT_IKBD 1316: Debug_IKBD("IKBD_Cmd_Execute\n"); 1317: Debugger_TabIKBD_AddListViewItem("Execute"); 1318: #endif 1319: } 1320: 1321: 1.1.1.2 root 1322: /*-----------------------------------------------------------------------*/ 1.1 root 1323: /* 1324: Send data to keyboard processor via ACIA by writing to address 0xfffc02. 1325: For our emulation we bypass the ACIA (I've yet to see anything check for this) 1326: and add the byte directly into the keyboard input buffer. 1327: */ 1328: void IKBD_RunKeyboardCommand(void) 1329: { 1330: int i=0; 1331: 1.1.1.2 root 1332: /* Write into our keyboard input buffer */ 1.1 root 1333: Keyboard.InputBuffer[Keyboard.nBytesInInputBuffer++] = ACIAByte; 1334: 1.1.1.2 root 1335: /* Now check bytes to see if we have a valid/in-valid command string set */ 1.1 root 1336: while(KeyboardCommands[i].Command!=0xff) { 1.1.1.2 root 1337: /* Found command? */ 1.1 root 1338: if (KeyboardCommands[i].Command==Keyboard.InputBuffer[0]) { 1.1.1.2 root 1339: /* Is string complete, then can execute? */ 1.1 root 1340: if (KeyboardCommands[i].NumParameters==Keyboard.nBytesInInputBuffer) { 1341: CALL_VAR(KeyboardCommands[i].pCallFunction); 1342: Keyboard.nBytesInInputBuffer = 0; 1343: } 1344: 1345: return; 1346: } 1347: 1348: i++; 1349: } 1350: 1.1.1.2 root 1351: /* Command not known, reset buffer(IKBD assumes a NOP) */ 1.1 root 1352: Keyboard.nBytesInInputBuffer = 0; 1353: } 1354: 1.1.1.2 root 1355: 1356: /*-----------------------------------------------------------------------*/ 1.1 root 1357: /* 1358: Send byte to our keyboard processor, and execute 1359: */ 1360: void IKBD_SendByteToKeyboardProcessor(unsigned short bl) 1361: { 1.1.1.2 root 1362: ACIAByte = bl; /* Store byte to pass */ 1363: IKBD_RunKeyboardCommand(); /* And send */ 1.1 root 1364: } 1365: 1.1.1.2 root 1366: 1367: /*-----------------------------------------------------------------------*/ 1.1 root 1368: /* 1369: The byte stored in the ACIA 'ACIAByte' has been read by the CPU by reading from 1370: address $fffc02. We clear the status flag and set the GPIP register to signal read. 1371: */ 1372: unsigned short IKBD_GetByteFromACIA(void) 1373: { 1.1.1.2 root 1374: /* ACIA is now reset */ 1.1 root 1375: ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__RX_BUFFER_FULL; 1376: ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__INTERRUPT_REQUEST; 1377: ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__OVERRUN_ERROR; 1378: 1.1.1.2 root 1379: /* GPIP I4 - General Purpose Pin Keyboard/MIDI interrupt */ 1.1 root 1380: MFP_GPIP |= 0x10; 1381: return ACIAByte; /* Return byte from keyboard */ 1382: } 1383: 1.1.1.2 root 1384: 1385: /*-----------------------------------------------------------------------*/ 1.1 root 1386: /* 1387: Byte received in the ACIA from the keyboard processor. Store byte for read from $fffc02 1388: and clear the GPIP I4 register. This register will be remain low until byte has been 1389: read from ACIA. 1390: */ 1391: void IKBD_InterruptHandler_ACIA(void) 1392: { 1.1.1.2 root 1393: /* Remove this interrupt from list and re-order */ 1.1 root 1394: Int_AcknowledgeInterrupt(); 1395: 1.1.1.2 root 1396: /* Copy keyboard byte, ready for read from $fffc02 */ 1.1 root 1397: ACIAByte = Keyboard.Buffer[Keyboard.BufferHead++]; 1398: Keyboard.BufferHead &= KEYBOARD_BUFFER_MASK; 1399: 1.1.1.2 root 1400: /* Did we get an over-run? Ie byte has arrived from keyboard processor BEFORE CPU has read previous one from ACIA */ 1.1 root 1401: if (ACIAStatusRegister&ACIA_STATUS_REGISTER__RX_BUFFER_FULL) 1.1.1.2 root 1402: ACIAStatusRegister |= ACIA_STATUS_REGISTER__OVERRUN_ERROR; /* Set over-run */ 1.1 root 1403: 1.1.1.2 root 1404: /* ACIA buffer is now full */ 1.1 root 1405: ACIAStatusRegister |= ACIA_STATUS_REGISTER__RX_BUFFER_FULL; 1.1.1.2 root 1406: /* Signal interrupt pending */ 1.1 root 1407: ACIAStatusRegister |= ACIA_STATUS_REGISTER__INTERRUPT_REQUEST; 1.1.1.2 root 1408: /* GPIP I4 - General Purpose Pin Keyboard/MIDI interrupt */ 1409: /* NOTE: GPIP will remain low(0) until keyboard data is read from $fffc02. */ 1.1 root 1410: MFP_GPIP &= ~0x10; 1411: 1.1.1.2 root 1412: /* Acknowledge in MFP circuit, pass bit,enable,pending */ 1.1 root 1413: MFP_InputOnChannel(MFP_KEYBOARD_BIT,MFP_IERB,&MFP_IPRB); 1414: 1.1.1.2 root 1415: /* Clear flag so can allow another byte to be sent along serial line */ 1.1 root 1416: bByteInTransitToACIA = FALSE; 1.1.1.2 root 1417: /* If another key is waiting, start sending from keyboard processor now */ 1.1 root 1418: if (Keyboard.BufferHead!=Keyboard.BufferTail) 1419: IKBD_SendByteToACIA(); 1420: } 1421: 1422: 1.1.1.2 root 1423: /*-----------------------------------------------------------------------*/ 1.1 root 1424: /* 1425: Send a byte from the keyboard buffer to the ACIA. On a real ST this takes some time to send 1426: so we must be as accurate in the timing as possible - bytes do not appear to the 68000 instantly! 1427: We do this via an internal interrupt - neat! 1428: */ 1429: void IKBD_SendByteToACIA(void) 1430: { 1.1.1.2 root 1431: /* Transmit byte from keyboard processor to ACIA. This takes approx ACIA_CYCLES CPU clock cycles to complete */ 1.1 root 1432: if (!bByteInTransitToACIA) { 1.1.1.2 root 1433: /* Send byte to ACIA */ 1.1 root 1434: Int_AddRelativeInterrupt(ACIA_CYCLES,INTERRUPT_IKBD_ACIA); 1.1.1.2 root 1435: /* Set flag so only transmit one byte at a time */ 1.1 root 1436: bByteInTransitToACIA = TRUE; 1437: } 1438: } 1439: 1.1.1.2 root 1440: 1441: /*-----------------------------------------------------------------------*/ 1.1 root 1442: /* 1443: Add characer our internal keyboard buffer. These bytes are then sent one at a time to the ACIA. 1444: This is done via a delay to mimick the STs internal workings, as this is needed for games such 1445: as Carrier Command. 1446: */ 1447: void IKBD_AddKeyToKeyboardBuffer(unsigned char Data) 1448: { 1.1.1.2 root 1449: /* Is keyboard initialised yet? Ignore any bytes until it is */ 1.1 root 1450: if (!KeyboardProcessor.bReset) 1451: return; 1452: 1.1.1.2 root 1453: /* Check we have space to add byte */ 1.1 root 1454: if (Keyboard.BufferHead!=((Keyboard.BufferTail+1)&KEYBOARD_BUFFER_MASK)) { 1.1.1.2 root 1455: /* Add byte to our buffer */ 1.1 root 1456: Keyboard.Buffer[Keyboard.BufferTail++] = Data; 1457: Keyboard.BufferTail &= KEYBOARD_BUFFER_MASK; 1458: 1.1.1.2 root 1459: /* We have character ready to transmit from the ACIA - see if can send it now */ 1.1 root 1460: IKBD_SendByteToACIA(); 1461: } 1462: } 1463: 1.1.1.2 root 1464: 1465: /*-----------------------------------------------------------------------*/ 1.1 root 1466: /* 1467: When press/release key under Windows, execute this function 1468: */ 1469: void IKBD_PressSTKey(unsigned char ScanCode,BOOL bPress) 1470: { 1.1.1.2 root 1471: /* Ignore anything until we've redirected our GEM handlers */ 1.1.1.3 root 1472: if (!bInitGemDOS) 1473: return; 1.1 root 1474: if (!bPress) 1475: ScanCode |= 0x80; /* Set top bit if released key */ 1476: IKBD_AddKeyToKeyboardBuffer(ScanCode); /* And send to keyboard processor */ 1477: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.