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