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