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