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