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