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