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