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