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