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